diff --git a/src/conky.c b/src/conky.c index 05fce9ad..fdc0a060 100644 --- a/src/conky.c +++ b/src/conky.c @@ -711,46 +711,6 @@ void parse_conky_vars(struct text_object *root, const char *txt, char *p, struct generate_text_internal(p, max_user_text, *root, cur); } -char *format_time(unsigned long timeval, const int width) -{ - char buf[10]; - unsigned long nt; // narrow time, for speed on 32-bit - unsigned cc; // centiseconds - unsigned nn; // multi-purpose whatever - - nt = timeval; - cc = nt % 100; // centiseconds past second - nt /= 100; // total seconds - nn = nt % 60; // seconds past the minute - nt /= 60; // total minutes - if (width >= snprintf(buf, sizeof buf, "%lu:%02u.%02u", - nt, nn, cc)) { - return strndup(buf, text_buffer_size); - } - if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) { - return strndup(buf, text_buffer_size); - } - nn = nt % 60; // minutes past the hour - nt /= 60; // total hours - if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) { - return strndup(buf, text_buffer_size); - } - nn = nt; // now also hours - if (width >= snprintf(buf, sizeof buf, "%uh", nn)) { - return strndup(buf, text_buffer_size); - } - nn /= 24; // now days - if (width >= snprintf(buf, sizeof buf, "%ud", nn)) { - return strndup(buf, text_buffer_size); - } - nn /= 7; // now weeks - if (width >= snprintf(buf, sizeof buf, "%uw", nn)) { - return strndup(buf, text_buffer_size); - } - // well shoot, this outta' fit... - return strndup("", text_buffer_size); -} - static inline void format_media_player_time(char *buf, const int size, int seconds) { @@ -2106,70 +2066,14 @@ void generate_text_internal(char *p, int p_max_size, * times, we have this special handler. */ break; case OBJ_top: - parse_top_args("top", obj->data.top.s, obj); - if (!needed) needed = cur->cpu; case OBJ_top_mem: - parse_top_args("top_mem", obj->data.top.s, obj); - if (!needed) needed = cur->memu; case OBJ_top_time: - parse_top_args("top_time", obj->data.top.s, obj); - if (!needed) needed = cur->time; #ifdef IOSTATS case OBJ_top_io: - parse_top_args("top_io", obj->data.top.s, obj); - if (!needed) needed = cur->io; #endif - - if (needed[obj->data.top.num]) { - char *timeval; - - switch (obj->data.top.type) { - case TOP_NAME: - snprintf(p, top_name_width + 1, "%-*s", top_name_width, - needed[obj->data.top.num]->name); - break; - case TOP_CPU: - snprintf(p, 7, "%6.2f", - needed[obj->data.top.num]->amount); - break; - case TOP_PID: - snprintf(p, 6, "%5i", - needed[obj->data.top.num]->pid); - break; - case TOP_MEM: - snprintf(p, 7, "%6.2f", - needed[obj->data.top.num]->totalmem); - break; - case TOP_TIME: - timeval = format_time( - needed[obj->data.top.num]->total_cpu_time, 9); - snprintf(p, 10, "%9s", timeval); - free(timeval); - break; - case TOP_MEM_RES: - human_readable(needed[obj->data.top.num]->rss, - p, 255); - break; - case TOP_MEM_VSIZE: - human_readable(needed[obj->data.top.num]->vsize, - p, 255); - break; -#ifdef IOSTATS - case TOP_READ_BYTES: - human_readable(needed[obj->data.top.num]->read_bytes / update_interval, - p, 255); - break; - case TOP_WRITE_BYTES: - human_readable(needed[obj->data.top.num]->write_bytes / update_interval, - p, 255); - break; - case TOP_IO_PERC: - snprintf(p, 7, "%6.2f", - needed[obj->data.top.num]->io_perc); - break; -#endif - } - } + /* yes, passing top_name_width instead + * of p_max_size is intended here */ + print_top(obj, p, top_name_width); OBJ(tail) { print_tailhead("tail", obj, p, p_max_size); } diff --git a/src/core.c b/src/core.c index 49f2576b..bb9d3132 100644 --- a/src/core.c +++ b/src/core.c @@ -1599,11 +1599,7 @@ void free_text_objects(struct text_object *root, int internal) #ifdef IOSTATS case OBJ_top_io: #endif - if (info.first_process && !internal) { - free_all_processes(); - info.first_process = NULL; - } - if (data.top.s) free(data.top.s); + free_top(obj, internal); break; #ifdef HDDTEMP case OBJ_hddtemp: diff --git a/src/text_object.h b/src/text_object.h index 8731cd66..db57584f 100644 --- a/src/text_object.h +++ b/src/text_object.h @@ -457,13 +457,6 @@ struct text_object { char *str; } ifblock; - struct { - int num; - int type; - int was_parsed; - char *s; - } top; - struct { double last_update; float interval; diff --git a/src/top.c b/src/top.c index da9f92ed..76236ead 100644 --- a/src/top.c +++ b/src/top.c @@ -800,18 +800,26 @@ void process_find_top(struct process **cpu, struct process **mem, #endif /* IOSTATS */ } +struct top_data { + int num; + int type; + int was_parsed; + char *s; +}; + int parse_top_args(const char *s, const char *arg, struct text_object *obj) { + struct top_data *td; char buf[64]; int n; - if (obj->data.top.was_parsed) { - return 1; + if (!arg) { + NORM_ERR("top needs arguments"); + return 0; } - obj->data.top.was_parsed = 1; - if (arg && !obj->data.top.s) { - obj->data.top.s = strndup(arg, text_buffer_size); + if (obj->data.opaque) { + return 1; } if (s[3] == 0) { @@ -837,33 +845,32 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) return 0; } - if (!arg) { - NORM_ERR("top needs arguments"); - return 0; - } + obj->data.opaque = td = malloc(sizeof(struct top_data)); + memset(td, 0, sizeof(struct top_data)); + td->s = strndup(arg, text_buffer_size); if (sscanf(arg, "%63s %i", buf, &n) == 2) { if (strcmp(buf, "name") == EQUAL) { - obj->data.top.type = TOP_NAME; + td->type = TOP_NAME; } else if (strcmp(buf, "cpu") == EQUAL) { - obj->data.top.type = TOP_CPU; + td->type = TOP_CPU; } else if (strcmp(buf, "pid") == EQUAL) { - obj->data.top.type = TOP_PID; + td->type = TOP_PID; } else if (strcmp(buf, "mem") == EQUAL) { - obj->data.top.type = TOP_MEM; + td->type = TOP_MEM; } else if (strcmp(buf, "time") == EQUAL) { - obj->data.top.type = TOP_TIME; + td->type = TOP_TIME; } else if (strcmp(buf, "mem_res") == EQUAL) { - obj->data.top.type = TOP_MEM_RES; + td->type = TOP_MEM_RES; } else if (strcmp(buf, "mem_vsize") == EQUAL) { - obj->data.top.type = TOP_MEM_VSIZE; + td->type = TOP_MEM_VSIZE; #ifdef IOSTATS } else if (strcmp(buf, "io_read") == EQUAL) { - obj->data.top.type = TOP_READ_BYTES; + td->type = TOP_READ_BYTES; } else if (strcmp(buf, "io_write") == EQUAL) { - obj->data.top.type = TOP_WRITE_BYTES; + td->type = TOP_WRITE_BYTES; } else if (strcmp(buf, "io_perc") == EQUAL) { - obj->data.top.type = TOP_IO_PERC; + td->type = TOP_IO_PERC; #endif /* IOSTATS */ } else { NORM_ERR("invalid type arg for top"); @@ -879,7 +886,7 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) NORM_ERR("invalid num arg for top. Must be between 1 and 10."); return 0; } else { - obj->data.top.num = n - 1; + td->num = n - 1; } } else { NORM_ERR("invalid argument count for top"); @@ -888,4 +895,137 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) return 1; } +static char *format_time(unsigned long timeval, const int width) +{ + char buf[10]; + unsigned long nt; // narrow time, for speed on 32-bit + unsigned cc; // centiseconds + unsigned nn; // multi-purpose whatever + nt = timeval; + cc = nt % 100; // centiseconds past second + nt /= 100; // total seconds + nn = nt % 60; // seconds past the minute + nt /= 60; // total minutes + if (width >= snprintf(buf, sizeof buf, "%lu:%02u.%02u", + nt, nn, cc)) { + return strndup(buf, text_buffer_size); + } + if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) { + return strndup(buf, text_buffer_size); + } + nn = nt % 60; // minutes past the hour + nt /= 60; // total hours + if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) { + return strndup(buf, text_buffer_size); + } + nn = nt; // now also hours + if (width >= snprintf(buf, sizeof buf, "%uh", nn)) { + return strndup(buf, text_buffer_size); + } + nn /= 24; // now days + if (width >= snprintf(buf, sizeof buf, "%ud", nn)) { + return strndup(buf, text_buffer_size); + } + nn /= 7; // now weeks + if (width >= snprintf(buf, sizeof buf, "%uw", nn)) { + return strndup(buf, text_buffer_size); + } + // well shoot, this outta' fit... + return strndup("", text_buffer_size); +} + +void print_top(struct text_object *obj, char *p, int top_name_width) +{ + struct information *cur = &info; + struct top_data *td = obj->data.opaque; + struct process **needed = 0; + + if (!td) + return; + + switch (obj->type) { + case OBJ_top: + needed = cur->cpu; + break; + case OBJ_top_mem: + needed = cur->memu; + break; + case OBJ_top_time: + needed = cur->time; + break; + case OBJ_top_io: + needed = cur->io; + break; + default: + return; + } + + if (needed[td->num]) { + char *timeval; + + switch (td->type) { + case TOP_NAME: + snprintf(p, top_name_width + 1, "%-*s", top_name_width, + needed[td->num]->name); + break; + case TOP_CPU: + snprintf(p, 7, "%6.2f", + needed[td->num]->amount); + break; + case TOP_PID: + snprintf(p, 6, "%5i", + needed[td->num]->pid); + break; + case TOP_MEM: + snprintf(p, 7, "%6.2f", + needed[td->num]->totalmem); + break; + case TOP_TIME: + timeval = format_time( + needed[td->num]->total_cpu_time, 9); + snprintf(p, 10, "%9s", timeval); + free(timeval); + break; + case TOP_MEM_RES: + human_readable(needed[td->num]->rss, + p, 255); + break; + case TOP_MEM_VSIZE: + human_readable(needed[td->num]->vsize, + p, 255); + break; +#ifdef IOSTATS + case TOP_READ_BYTES: + human_readable(needed[td->num]->read_bytes / update_interval, + p, 255); + break; + case TOP_WRITE_BYTES: + human_readable(needed[td->num]->write_bytes / update_interval, + p, 255); + break; + case TOP_IO_PERC: + snprintf(p, 7, "%6.2f", + needed[td->num]->io_perc); + break; +#endif + } + } +} + +void free_top(struct text_object *obj, int internal) +{ + struct top_data *td = obj->data.opaque; + + if (info.first_process && !internal) { + free_all_processes(); + info.first_process = NULL; + } + + if (!td) + return; + if (td->s) + free(td->s); + free(obj->data.opaque); + obj->data.opaque = NULL; +} diff --git a/src/top.h b/src/top.h index f15d7822..e5773d1f 100644 --- a/src/top.h +++ b/src/top.h @@ -143,5 +143,7 @@ void process_find_top(struct process **, struct process **, struct process ** struct process *get_process_by_name(const char *); int parse_top_args(const char *s, const char *arg, struct text_object *obj); +void print_top(struct text_object *, char *, int); +void free_top(struct text_object *, int); #endif /* _top_h_ */