mirror of
https://github.com/Llewellynvdm/conky.git
synced 2025-02-14 18:06:32 +00:00
exec: put all exec-related stuff into it's own file
While here, also merge the execi and texeci fields of struct text_object, so more common code can be shared in between.
This commit is contained in:
parent
2631f42820
commit
7a168c377b
@ -50,11 +50,11 @@ endif # BUILD_CONFIG_OUTPUT
|
|||||||
|
|
||||||
# source files always needed for compiling
|
# source files always needed for compiling
|
||||||
mandatory_sources = colours.c colours.h common.c common.h conky.c conky.h \
|
mandatory_sources = colours.c colours.h common.c common.h conky.c conky.h \
|
||||||
core.c core.h diskio.c diskio.h fs.c fs.h logging.h mail.c mail.h \
|
core.c core.h diskio.c diskio.h exec.c exec.h fs.c fs.h logging.h \
|
||||||
mixer.c mixer.h template.c template.h timed_thread.c timed_thread.h \
|
mail.c mail.h mixer.c mixer.h template.c template.h timed_thread.c \
|
||||||
mboxscan.c mboxscan.h specials.c specials.h tailhead.c tailhead.h \
|
timed_thread.h mboxscan.c mboxscan.h specials.c specials.h tailhead.c \
|
||||||
temphelper.c temphelper.h text_object.c text_object.h timeinfo.c \
|
tailhead.h temphelper.c temphelper.h text_object.c text_object.h \
|
||||||
timeinfo.h algebra.c algebra.h
|
timeinfo.c timeinfo.h algebra.c algebra.h
|
||||||
|
|
||||||
# source files only needed when the apropriate option is enabled
|
# source files only needed when the apropriate option is enabled
|
||||||
audacious = audacious.c audacious.h
|
audacious = audacious.c audacious.h
|
||||||
|
328
src/conky.c
328
src/conky.c
@ -76,6 +76,7 @@
|
|||||||
#include "build.h"
|
#include "build.h"
|
||||||
#include "colours.h"
|
#include "colours.h"
|
||||||
#include "diskio.h"
|
#include "diskio.h"
|
||||||
|
#include "exec.h"
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
#include "fonts.h"
|
#include "fonts.h"
|
||||||
#endif
|
#endif
|
||||||
@ -163,7 +164,6 @@ double update_interval;
|
|||||||
double update_interval_old;
|
double update_interval_old;
|
||||||
double update_interval_bat;
|
double update_interval_bat;
|
||||||
void *global_cpu = NULL;
|
void *global_cpu = NULL;
|
||||||
pid_t childpid = 0;
|
|
||||||
|
|
||||||
int argc_copy;
|
int argc_copy;
|
||||||
char** argv_copy;
|
char** argv_copy;
|
||||||
@ -631,107 +631,6 @@ static void human_readable(long long num, char *buf, int size)
|
|||||||
/* global object list root element */
|
/* global object list root element */
|
||||||
static struct text_object global_root_object;
|
static struct text_object global_root_object;
|
||||||
|
|
||||||
//our own implementation of popen, the difference : the value of 'childpid' will be filled with
|
|
||||||
//the pid of the running 'command'. This is useful if want to kill it when it hangs while reading
|
|
||||||
//or writing to it. We have to kill it because pclose will wait until the process dies by itself
|
|
||||||
FILE* pid_popen(const char *command, const char *mode, pid_t *child) {
|
|
||||||
int ends[2];
|
|
||||||
int parentend, childend;
|
|
||||||
|
|
||||||
//by running pipe after the strcmp's we make sure that we don't have to create a pipe
|
|
||||||
//and close the ends if mode is something illegal
|
|
||||||
if(strcmp(mode, "r") == 0) {
|
|
||||||
if(pipe(ends) != 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
parentend = ends[0];
|
|
||||||
childend = ends[1];
|
|
||||||
} else if(strcmp(mode, "w") == 0) {
|
|
||||||
if(pipe(ends) != 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
parentend = ends[1];
|
|
||||||
childend = ends[0];
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*child = fork();
|
|
||||||
if(*child == -1) {
|
|
||||||
close(parentend);
|
|
||||||
close(childend);
|
|
||||||
return NULL;
|
|
||||||
} else if(*child > 0) {
|
|
||||||
close(childend);
|
|
||||||
waitpid(*child, NULL, 0);
|
|
||||||
} else {
|
|
||||||
//don't read from both stdin and pipe or write to both stdout and pipe
|
|
||||||
if(childend == ends[0]) {
|
|
||||||
close(0);
|
|
||||||
} else {
|
|
||||||
close(1);
|
|
||||||
}
|
|
||||||
dup(childend); //by dupping childend, the returned fd will have close-on-exec turned off
|
|
||||||
execl("/bin/sh", "sh", "-c", command, (char *) NULL);
|
|
||||||
_exit(EXIT_FAILURE); //child should die here, (normally execl will take care of this but it can fail)
|
|
||||||
}
|
|
||||||
return fdopen(parentend, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void read_exec(const char *data, char *buf, const int size)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
alarm(update_interval);
|
|
||||||
fp = pid_popen(data, "r", &childpid);
|
|
||||||
if(fp) {
|
|
||||||
int length;
|
|
||||||
|
|
||||||
length = fread(buf, 1, size, fp);
|
|
||||||
pclose(fp);
|
|
||||||
buf[length] = '\0';
|
|
||||||
if (length > 0 && buf[length - 1] == '\n') {
|
|
||||||
buf[length - 1] = '\0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buf[0] = '\0';
|
|
||||||
}
|
|
||||||
alarm(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_read_exec(const char *data, char *buf, const int size)
|
|
||||||
{
|
|
||||||
read_exec(data, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *threaded_exec(void *) __attribute__((noreturn));
|
|
||||||
|
|
||||||
void *threaded_exec(void *arg)
|
|
||||||
{
|
|
||||||
char *buff, *p2;
|
|
||||||
struct text_object *obj = (struct text_object *)arg;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
buff = malloc(text_buffer_size);
|
|
||||||
read_exec(obj->data.texeci.cmd, buff,
|
|
||||||
text_buffer_size);
|
|
||||||
p2 = buff;
|
|
||||||
while (*p2) {
|
|
||||||
if (*p2 == '\001') {
|
|
||||||
*p2 = ' ';
|
|
||||||
}
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
timed_thread_lock(obj->data.texeci.p_timed_thread);
|
|
||||||
strncpy(obj->data.texeci.buffer, buff, text_buffer_size);
|
|
||||||
timed_thread_unlock(obj->data.texeci.p_timed_thread);
|
|
||||||
free(buff);
|
|
||||||
if (timed_thread_test(obj->data.texeci.p_timed_thread, 0)) {
|
|
||||||
timed_thread_exit(obj->data.texeci.p_timed_thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* never reached */
|
|
||||||
}
|
|
||||||
|
|
||||||
static long current_text_color;
|
static long current_text_color;
|
||||||
|
|
||||||
void set_current_text_color(long colour)
|
void set_current_text_color(long colour)
|
||||||
@ -893,21 +792,6 @@ char *format_time(unsigned long timeval, const int width)
|
|||||||
return strndup("<inf>", text_buffer_size);
|
return strndup("<inf>", text_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove backspaced chars, example: "dog^H^H^Hcat" becomes "cat"
|
|
||||||
//string has to end with \0 and it's length should fit in a int
|
|
||||||
#define BACKSPACE 8
|
|
||||||
void remove_deleted_chars(char *string){
|
|
||||||
int i = 0;
|
|
||||||
while(string[i] != 0){
|
|
||||||
if(string[i] == BACKSPACE){
|
|
||||||
if(i != 0){
|
|
||||||
strcpy( &(string[i-1]), &(string[i+1]) );
|
|
||||||
i--;
|
|
||||||
}else strcpy( &(string[i]), &(string[i+1]) ); //necessary for ^H's at the start of a string
|
|
||||||
}else i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void format_media_player_time(char *buf, const int size,
|
static inline void format_media_player_time(char *buf, const int size,
|
||||||
int seconds)
|
int seconds)
|
||||||
{
|
{
|
||||||
@ -931,31 +815,6 @@ static inline void format_media_player_time(char *buf, const int size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double get_barnum(char *buf)
|
|
||||||
{
|
|
||||||
char *c = buf;
|
|
||||||
double barnum;
|
|
||||||
|
|
||||||
while (*c) {
|
|
||||||
if (*c == '\001') {
|
|
||||||
*c = ' ';
|
|
||||||
}
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sscanf(buf, "%lf", &barnum) == 0) {
|
|
||||||
NORM_ERR("reading exec value failed (perhaps it's not the "
|
|
||||||
"correct format?)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (barnum > 100.0 || barnum < 0.0) {
|
|
||||||
NORM_ERR("your exec value is not between 0 and 100, "
|
|
||||||
"therefore it will be ignored");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return barnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* substitutes all occurrences of '\n' with SECRIT_MULTILINE_CHAR, which allows
|
/* substitutes all occurrences of '\n' with SECRIT_MULTILINE_CHAR, which allows
|
||||||
* multiline objects like $exec work with $align[rc] and friends
|
* multiline objects like $exec work with $align[rc] and friends
|
||||||
*/
|
*/
|
||||||
@ -1503,206 +1362,43 @@ static void generate_text_internal(char *p, int p_max_size,
|
|||||||
evaluate(obj->data.s, p);
|
evaluate(obj->data.s, p);
|
||||||
}
|
}
|
||||||
OBJ(exec) {
|
OBJ(exec) {
|
||||||
read_exec(obj->data.s, p, text_buffer_size);
|
print_exec(obj, p, p_max_size);
|
||||||
remove_deleted_chars(p);
|
|
||||||
}
|
}
|
||||||
OBJ(execp) {
|
OBJ(execp) {
|
||||||
struct information *tmp_info;
|
print_execp(obj, p, p_max_size);
|
||||||
struct text_object subroot;
|
|
||||||
|
|
||||||
read_exec(obj->data.s, p, text_buffer_size);
|
|
||||||
|
|
||||||
tmp_info = malloc(sizeof(struct information));
|
|
||||||
memcpy(tmp_info, cur, sizeof(struct information));
|
|
||||||
parse_conky_vars(&subroot, p, p, tmp_info);
|
|
||||||
|
|
||||||
free_text_objects(&subroot, 1);
|
|
||||||
free(tmp_info);
|
|
||||||
}
|
}
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
OBJ(execgauge) {
|
OBJ(execgauge) {
|
||||||
double barnum;
|
print_execgauge(obj, p, p_max_size);
|
||||||
|
|
||||||
read_exec(obj->data.s, p, text_buffer_size);
|
|
||||||
barnum = get_barnum(p); /*using the same function*/
|
|
||||||
|
|
||||||
if (barnum >= 0.0) {
|
|
||||||
barnum /= 100;
|
|
||||||
new_gauge(p, obj->a, obj->b, round_to_int(barnum * 255.0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
OBJ(execbar) {
|
OBJ(execbar) {
|
||||||
double barnum;
|
print_execbar(obj, p, p_max_size);
|
||||||
|
|
||||||
read_exec(obj->data.s, p, text_buffer_size);
|
|
||||||
barnum = get_barnum(p);
|
|
||||||
|
|
||||||
if (barnum >= 0.0) {
|
|
||||||
#ifdef X11
|
|
||||||
if(output_methods & TO_X) {
|
|
||||||
barnum /= 100;
|
|
||||||
new_bar(p, obj->a, obj->b, round_to_int(barnum * 255.0));
|
|
||||||
}else{
|
|
||||||
#endif /* X11 */
|
|
||||||
if(!obj->a) obj->a = DEFAULT_BAR_WIDTH_NO_X;
|
|
||||||
new_bar_in_shell(p, p_max_size, barnum, obj->a);
|
|
||||||
#ifdef X11
|
|
||||||
}
|
|
||||||
#endif /* X11 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
OBJ(execgraph) {
|
OBJ(execgraph) {
|
||||||
char showaslog = FALSE;
|
print_execgraph(obj, p, p_max_size);
|
||||||
char tempgrad = FALSE;
|
|
||||||
double barnum;
|
|
||||||
char *cmd = obj->data.s;
|
|
||||||
|
|
||||||
if (strstr(cmd, " "TEMPGRAD) && strlen(cmd) > strlen(" "TEMPGRAD)) {
|
|
||||||
tempgrad = TRUE;
|
|
||||||
cmd += strlen(" "TEMPGRAD);
|
|
||||||
}
|
|
||||||
if (strstr(cmd, " "LOGGRAPH) && strlen(cmd) > strlen(" "LOGGRAPH)) {
|
|
||||||
showaslog = TRUE;
|
|
||||||
cmd += strlen(" "LOGGRAPH);
|
|
||||||
}
|
|
||||||
read_exec(cmd, p, text_buffer_size);
|
|
||||||
barnum = get_barnum(p);
|
|
||||||
|
|
||||||
if (barnum > 0) {
|
|
||||||
new_graph(p, obj->a, obj->b, obj->c, obj->d, round_to_int(barnum),
|
|
||||||
100, 1, showaslog, tempgrad);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
OBJ(execibar) {
|
OBJ(execibar) {
|
||||||
if (current_update_time - obj->data.execi.last_update
|
print_execibar(obj, p, p_max_size);
|
||||||
>= obj->data.execi.interval) {
|
|
||||||
double barnum;
|
|
||||||
|
|
||||||
read_exec(obj->data.execi.cmd, p, text_buffer_size);
|
|
||||||
barnum = get_barnum(p);
|
|
||||||
|
|
||||||
if (barnum >= 0.0) {
|
|
||||||
obj->f = barnum;
|
|
||||||
}
|
|
||||||
obj->data.execi.last_update = current_update_time;
|
|
||||||
}
|
|
||||||
#ifdef X11
|
|
||||||
if(output_methods & TO_X) {
|
|
||||||
new_bar(p, obj->a, obj->b, round_to_int(obj->f * 2.55));
|
|
||||||
} else {
|
|
||||||
#endif /* X11 */
|
|
||||||
if(!obj->a) obj->a = DEFAULT_BAR_WIDTH_NO_X;
|
|
||||||
new_bar_in_shell(p, p_max_size, round_to_int(obj->f), obj->a);
|
|
||||||
#ifdef X11
|
|
||||||
}
|
|
||||||
#endif /* X11 */
|
|
||||||
}
|
}
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
OBJ(execigraph) {
|
OBJ(execigraph) {
|
||||||
if (current_update_time - obj->data.execi.last_update
|
print_execigraph(obj, p, p_max_size);
|
||||||
>= obj->data.execi.interval) {
|
|
||||||
double barnum;
|
|
||||||
char showaslog = FALSE;
|
|
||||||
char tempgrad = FALSE;
|
|
||||||
char *cmd = obj->data.execi.cmd;
|
|
||||||
|
|
||||||
if (strstr(cmd, " "TEMPGRAD) && strlen(cmd) > strlen(" "TEMPGRAD)) {
|
|
||||||
tempgrad = TRUE;
|
|
||||||
cmd += strlen(" "TEMPGRAD);
|
|
||||||
}
|
|
||||||
if (strstr(cmd, " "LOGGRAPH) && strlen(cmd) > strlen(" "LOGGRAPH)) {
|
|
||||||
showaslog = TRUE;
|
|
||||||
cmd += strlen(" "LOGGRAPH);
|
|
||||||
}
|
|
||||||
obj->char_a = showaslog;
|
|
||||||
obj->char_b = tempgrad;
|
|
||||||
read_exec(cmd, p, text_buffer_size);
|
|
||||||
barnum = get_barnum(p);
|
|
||||||
|
|
||||||
if (barnum >= 0.0) {
|
|
||||||
obj->f = barnum;
|
|
||||||
}
|
|
||||||
obj->data.execi.last_update = current_update_time;
|
|
||||||
}
|
|
||||||
new_graph(p, obj->a, obj->b, obj->c, obj->d, (int) (obj->f), 100, 1, obj->char_a, obj->char_b);
|
|
||||||
}
|
}
|
||||||
OBJ(execigauge) {
|
OBJ(execigauge) {
|
||||||
if (current_update_time - obj->data.execi.last_update
|
print_execigauge(obj, p, p_max_size);
|
||||||
>= obj->data.execi.interval) {
|
|
||||||
double barnum;
|
|
||||||
|
|
||||||
read_exec(obj->data.execi.cmd, p, text_buffer_size);
|
|
||||||
barnum = get_barnum(p);
|
|
||||||
|
|
||||||
if (barnum >= 0.0) {
|
|
||||||
obj->f = 255 * barnum / 100.0;
|
|
||||||
}
|
|
||||||
obj->data.execi.last_update = current_update_time;
|
|
||||||
}
|
|
||||||
new_gauge(p, obj->a, obj->b, round_to_int(obj->f));
|
|
||||||
}
|
}
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
OBJ(execi) {
|
OBJ(execi) {
|
||||||
if (current_update_time - obj->data.execi.last_update
|
print_execi(obj, p, p_max_size);
|
||||||
>= obj->data.execi.interval
|
|
||||||
&& obj->data.execi.interval != 0) {
|
|
||||||
read_exec(obj->data.execi.cmd, obj->data.execi.buffer,
|
|
||||||
text_buffer_size);
|
|
||||||
obj->data.execi.last_update = current_update_time;
|
|
||||||
}
|
|
||||||
snprintf(p, text_buffer_size, "%s", obj->data.execi.buffer);
|
|
||||||
}
|
}
|
||||||
OBJ(execpi) {
|
OBJ(execpi) {
|
||||||
struct text_object subroot;
|
print_execpi(obj, p);
|
||||||
struct information *tmp_info =
|
|
||||||
malloc(sizeof(struct information));
|
|
||||||
memcpy(tmp_info, cur, sizeof(struct information));
|
|
||||||
|
|
||||||
if (current_update_time - obj->data.execi.last_update
|
|
||||||
< obj->data.execi.interval
|
|
||||||
|| obj->data.execi.interval == 0) {
|
|
||||||
parse_conky_vars(&subroot, obj->data.execi.buffer, p, tmp_info);
|
|
||||||
} else {
|
|
||||||
char *output = obj->data.execi.buffer;
|
|
||||||
FILE *fp = pid_popen(obj->data.execi.cmd, "r", &childpid);
|
|
||||||
int length = fread(output, 1, text_buffer_size, fp);
|
|
||||||
|
|
||||||
pclose(fp);
|
|
||||||
|
|
||||||
output[length] = '\0';
|
|
||||||
if (length > 0 && output[length - 1] == '\n') {
|
|
||||||
output[length - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_conky_vars(&subroot, obj->data.execi.buffer, p, tmp_info);
|
|
||||||
obj->data.execi.last_update = current_update_time;
|
|
||||||
}
|
|
||||||
free_text_objects(&subroot, 1);
|
|
||||||
free(tmp_info);
|
|
||||||
}
|
}
|
||||||
OBJ(texeci) {
|
OBJ(texeci) {
|
||||||
if (!obj->data.texeci.p_timed_thread) {
|
print_texeci(obj, p, p_max_size);
|
||||||
obj->data.texeci.p_timed_thread =
|
|
||||||
timed_thread_create(&threaded_exec,
|
|
||||||
(void *) obj, obj->data.texeci.interval * 1000000);
|
|
||||||
if (!obj->data.texeci.p_timed_thread) {
|
|
||||||
NORM_ERR("Error creating texeci timed thread");
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* note that we don't register this thread with the
|
|
||||||
* timed_thread list, because we destroy it manually
|
|
||||||
*/
|
|
||||||
if (timed_thread_run(obj->data.texeci.p_timed_thread)) {
|
|
||||||
NORM_ERR("Error running texeci timed thread");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
timed_thread_lock(obj->data.texeci.p_timed_thread);
|
|
||||||
snprintf(p, text_buffer_size, "%s", obj->data.texeci.buffer);
|
|
||||||
timed_thread_unlock(obj->data.texeci.p_timed_thread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
OBJ(imap_unseen) {
|
OBJ(imap_unseen) {
|
||||||
struct mail_s *mail = ensure_mail_thread(obj, imap_thread, "imap");
|
struct mail_s *mail = ensure_mail_thread(obj, imap_thread, "imap");
|
||||||
|
@ -336,9 +336,6 @@ extern unsigned int max_user_text;
|
|||||||
/* path to config file */
|
/* path to config file */
|
||||||
extern char *current_config;
|
extern char *current_config;
|
||||||
|
|
||||||
/* just a wrapper for read_exec() defined in conky.c */
|
|
||||||
void do_read_exec(const char *data, char *buf, const int size);
|
|
||||||
|
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
#define TO_X 1
|
#define TO_X 1
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
@ -367,4 +364,7 @@ void set_update_interval(double interval);
|
|||||||
#define UNUSED(a) (void)a
|
#define UNUSED(a) (void)a
|
||||||
#define UNUSED_ATTR __attribute__ ((unused))
|
#define UNUSED_ATTR __attribute__ ((unused))
|
||||||
|
|
||||||
|
void parse_conky_vars(struct text_object *, const char *,
|
||||||
|
char *, struct information *);
|
||||||
|
|
||||||
#endif /* _conky_h_ */
|
#endif /* _conky_h_ */
|
||||||
|
126
src/core.c
126
src/core.c
@ -35,6 +35,7 @@
|
|||||||
#include "build.h"
|
#include "build.h"
|
||||||
#include "colours.h"
|
#include "colours.h"
|
||||||
#include "diskio.h"
|
#include "diskio.h"
|
||||||
|
#include "exec.h"
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
#include "fonts.h"
|
#include "fonts.h"
|
||||||
#endif
|
#endif
|
||||||
@ -596,117 +597,39 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
|
|||||||
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
||||||
#endif /* IMLIB2 */
|
#endif /* IMLIB2 */
|
||||||
END OBJ(exec, 0)
|
END OBJ(exec, 0)
|
||||||
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
scan_exec_arg(obj, arg);
|
||||||
END OBJ(execp, 0)
|
END OBJ(execp, 0)
|
||||||
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
scan_exec_arg(obj, arg);
|
||||||
END OBJ(execbar, 0)
|
END OBJ(execbar, 0)
|
||||||
SIZE_DEFAULTS(bar);
|
SIZE_DEFAULTS(bar);
|
||||||
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
scan_exec_arg(obj, arg);
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
END OBJ(execgauge, 0)
|
END OBJ(execgauge, 0)
|
||||||
SIZE_DEFAULTS(gauge);
|
SIZE_DEFAULTS(gauge);
|
||||||
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
scan_exec_arg(obj, arg);
|
||||||
END OBJ(execgraph, 0)
|
END OBJ(execgraph, 0)
|
||||||
SIZE_DEFAULTS(graph);
|
SIZE_DEFAULTS(graph);
|
||||||
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
scan_exec_arg(obj, arg);
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
END OBJ(execibar, 0)
|
END OBJ_ARG(execibar, 0, "execibar needs arguments")
|
||||||
int n;
|
|
||||||
SIZE_DEFAULTS(bar);
|
SIZE_DEFAULTS(bar);
|
||||||
|
scan_execi_arg(obj, arg);
|
||||||
if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
NORM_ERR("${execibar <interval> command}");
|
|
||||||
obj->type = OBJ_text;
|
|
||||||
snprintf(buf, 256, "${%s}", s);
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
|
|
||||||
}
|
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
END OBJ(execigraph, 0)
|
END OBJ_ARG(execigraph, 0, "execigraph needs arguments")
|
||||||
int n;
|
|
||||||
SIZE_DEFAULTS(graph);
|
SIZE_DEFAULTS(graph);
|
||||||
|
scan_execi_arg(obj, arg);
|
||||||
if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
|
END OBJ_ARG(execigauge, 0, "execigauge needs arguments")
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
NORM_ERR("${execigraph <interval> command}");
|
|
||||||
obj->type = OBJ_text;
|
|
||||||
snprintf(buf, 256, "${%s}", s);
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
|
|
||||||
}
|
|
||||||
END OBJ(execigauge, 0)
|
|
||||||
int n;
|
|
||||||
SIZE_DEFAULTS(gauge);
|
SIZE_DEFAULTS(gauge);
|
||||||
|
scan_execi_arg(obj, arg);
|
||||||
if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
NORM_ERR("${execigauge <interval> command}");
|
|
||||||
obj->type = OBJ_text;
|
|
||||||
snprintf(buf, 256, "${%s}", s);
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
|
|
||||||
}
|
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
END OBJ(execi, 0)
|
END OBJ_ARG(execi, 0, "execi needs arguments")
|
||||||
int n;
|
scan_execi_arg(obj, arg);
|
||||||
|
END OBJ_ARG(execpi, 0, "execpi needs arguments")
|
||||||
if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
|
scan_execi_arg(obj, arg);
|
||||||
char buf[256];
|
END OBJ_ARG(texeci, 0, "texeci needs arguments")
|
||||||
|
scan_execi_arg(obj, arg);
|
||||||
NORM_ERR("${execi <interval> command}");
|
|
||||||
obj->type = OBJ_text;
|
|
||||||
snprintf(buf, 256, "${%s}", s);
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
|
|
||||||
obj->data.execi.buffer = malloc(text_buffer_size);
|
|
||||||
}
|
|
||||||
END OBJ(execpi, 0)
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
NORM_ERR("${execi <interval> command}");
|
|
||||||
obj->type = OBJ_text;
|
|
||||||
snprintf(buf, 256, "${%s}", s);
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
|
|
||||||
obj->data.execi.buffer = malloc(text_buffer_size);
|
|
||||||
}
|
|
||||||
END OBJ(texeci, 0)
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (!arg || sscanf(arg, "%f %n", &obj->data.texeci.interval, &n) <= 0) {
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
NORM_ERR("${texeci <interval> command}");
|
|
||||||
obj->type = OBJ_text;
|
|
||||||
snprintf(buf, 256, "${%s}", s);
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.texeci.cmd = strndup(arg + n, text_buffer_size);
|
|
||||||
obj->data.texeci.buffer = malloc(text_buffer_size);
|
|
||||||
}
|
|
||||||
obj->data.texeci.p_timed_thread = NULL;
|
|
||||||
END OBJ(pre_exec, 0)
|
END OBJ(pre_exec, 0)
|
||||||
obj->type = OBJ_text;
|
scan_pre_exec_arg(obj, arg);
|
||||||
if (arg) {
|
|
||||||
char buf[2048];
|
|
||||||
|
|
||||||
do_read_exec(arg, buf, sizeof(buf));
|
|
||||||
obj->data.s = strndup(buf, text_buffer_size);
|
|
||||||
} else {
|
|
||||||
obj->data.s = strndup("", text_buffer_size);
|
|
||||||
}
|
|
||||||
END OBJ(fs_bar, &update_fs_stats)
|
END OBJ(fs_bar, &update_fs_stats)
|
||||||
init_fs_bar(obj, arg);
|
init_fs_bar(obj, arg);
|
||||||
END OBJ(fs_bar_free, &update_fs_stats)
|
END OBJ(fs_bar_free, &update_fs_stats)
|
||||||
@ -1956,7 +1879,7 @@ void free_text_objects(struct text_object *root, int internal)
|
|||||||
case OBJ_execgraph:
|
case OBJ_execgraph:
|
||||||
#endif
|
#endif
|
||||||
case OBJ_execp:
|
case OBJ_execp:
|
||||||
free(data.s);
|
free_exec(obj);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_ICONV
|
#ifdef HAVE_ICONV
|
||||||
case OBJ_iconv_start:
|
case OBJ_iconv_start:
|
||||||
@ -2118,17 +2041,12 @@ void free_text_objects(struct text_object *root, int internal)
|
|||||||
case OBJ_execpi:
|
case OBJ_execpi:
|
||||||
case OBJ_execi:
|
case OBJ_execi:
|
||||||
case OBJ_execibar:
|
case OBJ_execibar:
|
||||||
|
case OBJ_texeci:
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
case OBJ_execigraph:
|
case OBJ_execigraph:
|
||||||
case OBJ_execigauge:
|
case OBJ_execigauge:
|
||||||
#endif /* X11 */
|
#endif /* X11 */
|
||||||
free(data.execi.cmd);
|
free_execi(obj);
|
||||||
free(data.execi.buffer);
|
|
||||||
break;
|
|
||||||
case OBJ_texeci:
|
|
||||||
if (data.texeci.p_timed_thread) timed_thread_destroy(data.texeci.p_timed_thread, &data.texeci.p_timed_thread);
|
|
||||||
free(data.texeci.cmd);
|
|
||||||
free(data.texeci.buffer);
|
|
||||||
break;
|
break;
|
||||||
case OBJ_nameserver:
|
case OBJ_nameserver:
|
||||||
free_dns_data();
|
free_dns_data();
|
||||||
|
455
src/exec.c
Normal file
455
src/exec.c
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
|
||||||
|
* vim: ts=4 sw=4 noet ai cindent syntax=c
|
||||||
|
*
|
||||||
|
* Conky, a system monitor, based on torsmo
|
||||||
|
*
|
||||||
|
* Any original torsmo code is licensed under the BSD license
|
||||||
|
*
|
||||||
|
* All code written since the fork of torsmo is licensed under the GPL
|
||||||
|
*
|
||||||
|
* Please see COPYING for details
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
|
||||||
|
* Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
|
||||||
|
* (see AUTHORS)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "conky.h"
|
||||||
|
#include "core.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "specials.h"
|
||||||
|
#include "text_object.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
/* FIXME: this will probably not work, since the variable is being reused
|
||||||
|
* between different text objects. So when a process really hangs, it's PID
|
||||||
|
* will be overwritten at the next iteration. */
|
||||||
|
pid_t childpid = 0;
|
||||||
|
|
||||||
|
//our own implementation of popen, the difference : the value of 'childpid' will be filled with
|
||||||
|
//the pid of the running 'command'. This is useful if want to kill it when it hangs while reading
|
||||||
|
//or writing to it. We have to kill it because pclose will wait until the process dies by itself
|
||||||
|
static FILE* pid_popen(const char *command, const char *mode, pid_t *child) {
|
||||||
|
int ends[2];
|
||||||
|
int parentend, childend;
|
||||||
|
|
||||||
|
//by running pipe after the strcmp's we make sure that we don't have to create a pipe
|
||||||
|
//and close the ends if mode is something illegal
|
||||||
|
if(strcmp(mode, "r") == 0) {
|
||||||
|
if(pipe(ends) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
parentend = ends[0];
|
||||||
|
childend = ends[1];
|
||||||
|
} else if(strcmp(mode, "w") == 0) {
|
||||||
|
if(pipe(ends) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
parentend = ends[1];
|
||||||
|
childend = ends[0];
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*child = fork();
|
||||||
|
if(*child == -1) {
|
||||||
|
close(parentend);
|
||||||
|
close(childend);
|
||||||
|
return NULL;
|
||||||
|
} else if(*child > 0) {
|
||||||
|
close(childend);
|
||||||
|
waitpid(*child, NULL, 0);
|
||||||
|
} else {
|
||||||
|
//don't read from both stdin and pipe or write to both stdout and pipe
|
||||||
|
if(childend == ends[0]) {
|
||||||
|
close(0);
|
||||||
|
} else {
|
||||||
|
close(1);
|
||||||
|
}
|
||||||
|
dup(childend); //by dupping childend, the returned fd will have close-on-exec turned off
|
||||||
|
execl("/bin/sh", "sh", "-c", command, (char *) NULL);
|
||||||
|
_exit(EXIT_FAILURE); //child should die here, (normally execl will take care of this but it can fail)
|
||||||
|
}
|
||||||
|
return fdopen(parentend, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove backspaced chars, example: "dog^H^H^Hcat" becomes "cat"
|
||||||
|
//string has to end with \0 and it's length should fit in a int
|
||||||
|
#define BACKSPACE 8
|
||||||
|
static void remove_deleted_chars(char *string){
|
||||||
|
int i = 0;
|
||||||
|
while(string[i] != 0){
|
||||||
|
if(string[i] == BACKSPACE){
|
||||||
|
if(i != 0){
|
||||||
|
strcpy( &(string[i-1]), &(string[i+1]) );
|
||||||
|
i--;
|
||||||
|
}else strcpy( &(string[i]), &(string[i+1]) ); //necessary for ^H's at the start of a string
|
||||||
|
}else i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double get_barnum(char *buf)
|
||||||
|
{
|
||||||
|
char *c = buf;
|
||||||
|
double barnum;
|
||||||
|
|
||||||
|
while (*c) {
|
||||||
|
if (*c == '\001') {
|
||||||
|
*c = ' ';
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(buf, "%lf", &barnum) == 0) {
|
||||||
|
NORM_ERR("reading exec value failed (perhaps it's not the "
|
||||||
|
"correct format?)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (barnum > 100.0 || barnum < 0.0) {
|
||||||
|
NORM_ERR("your exec value is not between 0 and 100, "
|
||||||
|
"therefore it will be ignored");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return barnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void read_exec(const char *data, char *buf, const int size)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
memset(buf, 0, size);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
alarm(update_interval);
|
||||||
|
fp = pid_popen(data, "r", &childpid);
|
||||||
|
if(fp) {
|
||||||
|
int length;
|
||||||
|
|
||||||
|
length = fread(buf, 1, size, fp);
|
||||||
|
pclose(fp);
|
||||||
|
buf[length] = '\0';
|
||||||
|
if (length > 0 && buf[length - 1] == '\n') {
|
||||||
|
buf[length - 1] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf[0] = '\0';
|
||||||
|
}
|
||||||
|
alarm(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *threaded_exec(void *) __attribute__((noreturn));
|
||||||
|
|
||||||
|
static void *threaded_exec(void *arg)
|
||||||
|
{
|
||||||
|
char *buff, *p2;
|
||||||
|
struct text_object *obj = arg;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
buff = malloc(text_buffer_size);
|
||||||
|
read_exec(obj->data.execi.cmd, buff, text_buffer_size);
|
||||||
|
p2 = buff;
|
||||||
|
while (*p2) {
|
||||||
|
if (*p2 == '\001') {
|
||||||
|
*p2 = ' ';
|
||||||
|
}
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
timed_thread_lock(obj->data.execi.p_timed_thread);
|
||||||
|
if (obj->data.execi.buffer)
|
||||||
|
free(obj->data.execi.buffer);
|
||||||
|
obj->data.execi.buffer = buff;
|
||||||
|
timed_thread_unlock(obj->data.execi.p_timed_thread);
|
||||||
|
if (timed_thread_test(obj->data.execi.p_timed_thread, 0)) {
|
||||||
|
timed_thread_exit(obj->data.execi.p_timed_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* never reached */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the execi fields and return true if the given interval has passed */
|
||||||
|
static int time_to_update(struct text_object *obj)
|
||||||
|
{
|
||||||
|
if (!obj->data.execi.interval)
|
||||||
|
return 0;
|
||||||
|
if (current_update_time - obj->data.execi.last_update >= obj->data.execi.interval)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan_exec_arg(struct text_object *obj, const char *arg)
|
||||||
|
{
|
||||||
|
obj->data.s = strndup(arg ? arg : "", text_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan_pre_exec_arg(struct text_object *obj, const char *arg)
|
||||||
|
{
|
||||||
|
char buf[2048];
|
||||||
|
|
||||||
|
obj->type = OBJ_text;
|
||||||
|
read_exec(arg, buf, sizeof(buf));
|
||||||
|
obj->data.s = strndup(buf, text_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan_execi_arg(struct text_object *obj, const char *arg)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
|
||||||
|
NORM_ERR("${execi* <interval> command}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_exec(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
read_exec(obj->data.s, p, p_max_size);
|
||||||
|
remove_deleted_chars(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execp(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
struct information *tmp_info;
|
||||||
|
struct text_object subroot;
|
||||||
|
|
||||||
|
read_exec(obj->data.s, p, p_max_size);
|
||||||
|
|
||||||
|
tmp_info = malloc(sizeof(struct information));
|
||||||
|
memcpy(tmp_info, &info, sizeof(struct information));
|
||||||
|
parse_conky_vars(&subroot, p, p, tmp_info);
|
||||||
|
|
||||||
|
free_text_objects(&subroot, 1);
|
||||||
|
free(tmp_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execi(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
if (time_to_update(obj)) {
|
||||||
|
if (!obj->data.execi.buffer)
|
||||||
|
obj->data.execi.buffer = malloc(text_buffer_size);
|
||||||
|
read_exec(obj->data.execi.cmd, obj->data.execi.buffer, text_buffer_size);
|
||||||
|
obj->data.execi.last_update = current_update_time;
|
||||||
|
}
|
||||||
|
snprintf(p, p_max_size, "%s", obj->data.execi.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execpi(struct text_object *obj, char *p)
|
||||||
|
{
|
||||||
|
struct text_object subroot;
|
||||||
|
struct information *tmp_info;
|
||||||
|
|
||||||
|
tmp_info = malloc(sizeof(struct information));
|
||||||
|
memcpy(tmp_info, &info, sizeof(struct information));
|
||||||
|
|
||||||
|
if (!time_to_update(obj)) {
|
||||||
|
parse_conky_vars(&subroot, obj->data.execi.buffer, p, tmp_info);
|
||||||
|
} else {
|
||||||
|
char *output;
|
||||||
|
int length;
|
||||||
|
FILE *fp = pid_popen(obj->data.execi.cmd, "r", &childpid);
|
||||||
|
|
||||||
|
if (!obj->data.execi.buffer)
|
||||||
|
obj->data.execi.buffer = malloc(text_buffer_size);
|
||||||
|
|
||||||
|
length = fread(obj->data.execi.buffer, 1, text_buffer_size, fp);
|
||||||
|
pclose(fp);
|
||||||
|
|
||||||
|
output = obj->data.execi.buffer;
|
||||||
|
output[length] = '\0';
|
||||||
|
if (length > 0 && output[length - 1] == '\n') {
|
||||||
|
output[length - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_conky_vars(&subroot, obj->data.execi.buffer, p, tmp_info);
|
||||||
|
obj->data.execi.last_update = current_update_time;
|
||||||
|
}
|
||||||
|
free_text_objects(&subroot, 1);
|
||||||
|
free(tmp_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_texeci(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
if (!obj->data.execi.p_timed_thread) {
|
||||||
|
obj->data.execi.p_timed_thread =
|
||||||
|
timed_thread_create(&threaded_exec,
|
||||||
|
(void *) obj, obj->data.execi.interval * 1000000);
|
||||||
|
if (!obj->data.execi.p_timed_thread) {
|
||||||
|
NORM_ERR("Error creating texeci timed thread");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* note that we don't register this thread with the
|
||||||
|
* timed_thread list, because we destroy it manually
|
||||||
|
*/
|
||||||
|
if (timed_thread_run(obj->data.execi.p_timed_thread)) {
|
||||||
|
NORM_ERR("Error running texeci timed thread");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timed_thread_lock(obj->data.execi.p_timed_thread);
|
||||||
|
snprintf(p, p_max_size, "%s", obj->data.execi.buffer);
|
||||||
|
timed_thread_unlock(obj->data.execi.p_timed_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef X11
|
||||||
|
void print_execgauge(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
double barnum;
|
||||||
|
|
||||||
|
read_exec(obj->data.s, p, p_max_size);
|
||||||
|
barnum = get_barnum(p); /*using the same function*/
|
||||||
|
|
||||||
|
if (barnum >= 0.0) {
|
||||||
|
barnum /= 100;
|
||||||
|
new_gauge(p, obj->a, obj->b, round_to_int(barnum * 255.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execgraph(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
char showaslog = FALSE;
|
||||||
|
char tempgrad = FALSE;
|
||||||
|
double barnum;
|
||||||
|
char *cmd = obj->data.execi.cmd;
|
||||||
|
|
||||||
|
if (strstr(cmd, " "TEMPGRAD) && strlen(cmd) > strlen(" "TEMPGRAD)) {
|
||||||
|
tempgrad = TRUE;
|
||||||
|
cmd += strlen(" "TEMPGRAD);
|
||||||
|
}
|
||||||
|
if (strstr(cmd, " "LOGGRAPH) && strlen(cmd) > strlen(" "LOGGRAPH)) {
|
||||||
|
showaslog = TRUE;
|
||||||
|
cmd += strlen(" "LOGGRAPH);
|
||||||
|
}
|
||||||
|
read_exec(cmd, p, p_max_size);
|
||||||
|
barnum = get_barnum(p);
|
||||||
|
|
||||||
|
if (barnum > 0) {
|
||||||
|
new_graph(p, obj->a, obj->b, obj->c, obj->d, round_to_int(barnum),
|
||||||
|
100, 1, showaslog, tempgrad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execigraph(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
if (time_to_update(obj)) {
|
||||||
|
double barnum;
|
||||||
|
char showaslog = FALSE;
|
||||||
|
char tempgrad = FALSE;
|
||||||
|
char *cmd = obj->data.execi.cmd;
|
||||||
|
|
||||||
|
if (strstr(cmd, " "TEMPGRAD) && strlen(cmd) > strlen(" "TEMPGRAD)) {
|
||||||
|
tempgrad = TRUE;
|
||||||
|
cmd += strlen(" "TEMPGRAD);
|
||||||
|
}
|
||||||
|
if (strstr(cmd, " "LOGGRAPH) && strlen(cmd) > strlen(" "LOGGRAPH)) {
|
||||||
|
showaslog = TRUE;
|
||||||
|
cmd += strlen(" "LOGGRAPH);
|
||||||
|
}
|
||||||
|
obj->char_a = showaslog;
|
||||||
|
obj->char_b = tempgrad;
|
||||||
|
read_exec(cmd, p, p_max_size);
|
||||||
|
barnum = get_barnum(p);
|
||||||
|
|
||||||
|
if (barnum >= 0.0) {
|
||||||
|
obj->f = barnum;
|
||||||
|
}
|
||||||
|
obj->data.execi.last_update = current_update_time;
|
||||||
|
}
|
||||||
|
new_graph(p, obj->a, obj->b, obj->c, obj->d, (int) (obj->f), 100, 1, obj->char_a, obj->char_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execigauge(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
if (time_to_update(obj)) {
|
||||||
|
double barnum;
|
||||||
|
|
||||||
|
read_exec(obj->data.execi.cmd, p, p_max_size);
|
||||||
|
barnum = get_barnum(p);
|
||||||
|
|
||||||
|
if (barnum >= 0.0) {
|
||||||
|
obj->f = 255 * barnum / 100.0;
|
||||||
|
}
|
||||||
|
obj->data.execi.last_update = current_update_time;
|
||||||
|
}
|
||||||
|
new_gauge(p, obj->a, obj->b, round_to_int(obj->f));
|
||||||
|
}
|
||||||
|
#endif /* X11 */
|
||||||
|
|
||||||
|
void print_execbar(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
double barnum;
|
||||||
|
read_exec(obj->data.s, p, p_max_size);
|
||||||
|
barnum = get_barnum(p);
|
||||||
|
|
||||||
|
if (barnum >= 0.0) {
|
||||||
|
#ifdef X11
|
||||||
|
if(output_methods & TO_X) {
|
||||||
|
barnum /= 100;
|
||||||
|
new_bar(p, obj->a, obj->b, round_to_int(barnum * 255.0));
|
||||||
|
}else
|
||||||
|
#endif /* X11 */
|
||||||
|
{
|
||||||
|
if(!obj->a) obj->a = DEFAULT_BAR_WIDTH_NO_X;
|
||||||
|
new_bar_in_shell(p, p_max_size, barnum, obj->a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_execibar(struct text_object *obj, char *p, int p_max_size)
|
||||||
|
{
|
||||||
|
double barnum;
|
||||||
|
|
||||||
|
if (time_to_update(obj)) {
|
||||||
|
read_exec(obj->data.execi.cmd, p, p_max_size);
|
||||||
|
barnum = get_barnum(p);
|
||||||
|
|
||||||
|
if (barnum >= 0.0) {
|
||||||
|
obj->f = barnum;
|
||||||
|
}
|
||||||
|
obj->data.execi.last_update = current_update_time;
|
||||||
|
}
|
||||||
|
#ifdef X11
|
||||||
|
if(output_methods & TO_X) {
|
||||||
|
new_bar(p, obj->a, obj->b, round_to_int(obj->f * 2.55));
|
||||||
|
} else
|
||||||
|
#endif /* X11 */
|
||||||
|
{
|
||||||
|
if(!obj->a) obj->a = DEFAULT_BAR_WIDTH_NO_X;
|
||||||
|
new_bar_in_shell(p, p_max_size, round_to_int(obj->f), obj->a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_exec(struct text_object *obj)
|
||||||
|
{
|
||||||
|
if (obj->data.s) {
|
||||||
|
free(obj->data.s);
|
||||||
|
obj->data.s = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_execi(struct text_object *obj)
|
||||||
|
{
|
||||||
|
if (obj->data.execi.p_timed_thread)
|
||||||
|
timed_thread_destroy(obj->data.execi.p_timed_thread, &obj->data.execi.p_timed_thread);
|
||||||
|
if (obj->data.execi.cmd)
|
||||||
|
free(obj->data.execi.cmd);
|
||||||
|
if (obj->data.execi.buffer)
|
||||||
|
free(obj->data.execi.buffer);
|
||||||
|
memset(&obj->data.execi, 0, sizeof(obj->data.execi));
|
||||||
|
}
|
54
src/exec.h
Normal file
54
src/exec.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
|
||||||
|
* vim: ts=4 sw=4 noet ai cindent syntax=c
|
||||||
|
*
|
||||||
|
* Conky, a system monitor, based on torsmo
|
||||||
|
*
|
||||||
|
* Any original torsmo code is licensed under the BSD license
|
||||||
|
*
|
||||||
|
* All code written since the fork of torsmo is licensed under the GPL
|
||||||
|
*
|
||||||
|
* Please see COPYING for details
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
|
||||||
|
* Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
|
||||||
|
* (see AUTHORS)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _EXEC_H
|
||||||
|
#define _EXEC_H
|
||||||
|
|
||||||
|
extern pid_t childpid;
|
||||||
|
|
||||||
|
void scan_exec_arg(struct text_object *, const char *);
|
||||||
|
void scan_pre_exec_arg(struct text_object *, const char *);
|
||||||
|
void scan_execi_arg(struct text_object *, const char *);
|
||||||
|
void print_exec(struct text_object *, char *, int);
|
||||||
|
void print_execp(struct text_object *, char *, int);
|
||||||
|
void print_execi(struct text_object *, char *, int);
|
||||||
|
void print_execpi(struct text_object *, char *);
|
||||||
|
void print_texeci(struct text_object *, char *, int);
|
||||||
|
#ifdef X11
|
||||||
|
void print_execgauge(struct text_object *, char *, int);
|
||||||
|
void print_execgraph(struct text_object *, char *, int);
|
||||||
|
void print_execigraph(struct text_object *, char *, int);
|
||||||
|
void print_execigauge(struct text_object *, char *, int);
|
||||||
|
#endif /* X11 */
|
||||||
|
void print_execbar(struct text_object *, char *, int);
|
||||||
|
void print_execibar(struct text_object *, char *, int);
|
||||||
|
void free_exec(struct text_object *);
|
||||||
|
void free_execi(struct text_object *);
|
||||||
|
#endif /* _EXEC_H */
|
@ -511,15 +511,8 @@ struct text_object {
|
|||||||
char *cmd;
|
char *cmd;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
double data;
|
double data;
|
||||||
} execi; /* 5 */
|
|
||||||
|
|
||||||
struct {
|
|
||||||
float interval;
|
|
||||||
char *cmd;
|
|
||||||
char *buffer;
|
|
||||||
double data;
|
|
||||||
timed_thread *p_timed_thread;
|
timed_thread *p_timed_thread;
|
||||||
} texeci;
|
} execi; /* 5 */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int a, b;
|
int a, b;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user