diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index fc86a7ea..ee44aab9 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -6,9 +6,13 @@ if(NOT CMAKE_BUILD_TYPE) FORCE) endif(NOT CMAKE_BUILD_TYPE) +# -std options for all build types +set(CMAKE_C_FLAGS "-std=c99" CACHE STRING "Flags used by the C compiler during all build types." FORCE) +set(CMAKE_CXX_FLAGS "-std=c++0x" CACHE STRING "Flags used by the C++ compiler during all build types." FORCE) + # some extra debug flags -set(CMAKE_C_FLAGS_DEBUG "-ggdb -Wall -W -Wextra -Wunused -Wdeclaration-after-statement -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Winline -Wmissing-noreturn -Wmissing-format-attribute -Wredundant-decls -std=c99 -pedantic -Werror" CACHE STRING "Flags used by the compiler during debug builds." FORCE) -set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -Wall -W -Wextra -Wunused -std=c++0x -pedantic -Werror" CACHE STRING "Flags used by the compiler during debug builds." FORCE) +set(CMAKE_C_FLAGS_DEBUG "-ggdb -Wall -W -Wextra -Wunused -Wdeclaration-after-statement -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Winline -Wmissing-noreturn -Wmissing-format-attribute -Wredundant-decls -pedantic -Werror" CACHE STRING "Flags used by the compiler during debug builds." FORCE) +set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -Wall -W -Wextra -Wunused -pedantic -Werror" CACHE STRING "Flags used by the compiler during debug builds." FORCE) if(CMAKE_BUILD_TYPE MATCHES "Debug") diff --git a/configure.ac.in b/configure.ac.in index de6eda30..7659accb 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -947,7 +947,7 @@ conky_CXXFLAGS=${conky_CXXFLAGS/-Wdeclaration-after-statement/} conky_CXXFLAGS=${conky_CXXFLAGS/-Wbad-function-cast/} conky_CXXFLAGS=${conky_CXXFLAGS/-Wstrict-prototypes/} conky_CXXFLAGS=${conky_CXXFLAGS/-Wold-style-definition/} -conky_CXXFLAGS=${conky_CXXFLAGS/-std=c99/-std=c++98} +conky_CXXFLAGS=${conky_CXXFLAGS/-std=c99/-std=c++0x} AC_SUBST(conky_CFLAGS) AC_SUBST(conky_CXXFLAGS) diff --git a/doc/config_settings.xml b/doc/config_settings.xml index 19c4f181..c9be564c 100644 --- a/doc/config_settings.xml +++ b/doc/config_settings.xml @@ -810,7 +810,7 @@ - + If true, variables that output times output a number diff --git a/extras/nano/conky.nanorc b/extras/nano/conky.nanorc index 2bf7c663..0643701b 100644 --- a/extras/nano/conky.nanorc +++ b/extras/nano/conky.nanorc @@ -5,7 +5,7 @@ syntax "conky" "(\.*conkyrc.*$|conky.conf)" ## Configuration items -color green "\<(alignment|append_file|background|border_inner_margin|border_outer_margin|border_width|color0|color1|color2|color3|color4|color5|color6|color7|color8|color9|colorN|cpu_avg_samples|default_bar_size|default_color|default_gauge_size|default_graph_size|default_outline_color|default_shade_color|diskio_avg_samples|display|double_buffer|draw_borders|draw_graph_borders|draw_outline|draw_shades|extra_newline|font|format_human_readable|gap_x|gap_y|if_up_strictness|imap|imlib_cache_flush_interval|imlib_cache_size|lua_draw_hook_post|lua_draw_hook_pre|lua_load|lua_shutdown_hook|lua_startup_hook|mail_spool|max_port_monitor_connections|max_specials|max_text_width|max_user_text|maximum_width|minimum_size|mpd_host|mpd_password|mpd_port|music_player_interval|net_avg_samples|no_buffers|out_to_console|out_to_ncurses|out_to_stderr|out_to_x|override_utf8_locale|overwrite_file|own_window|own_window_class|own_window_colour|own_window_hints|own_window_title|own_window_transparent|own_window_type|pad_percents|pop3|sensor_device|short_units|show_graph_range|show_graph_scale|stippled_borders|temperature_unit|template|template0|template1|template2|template3|template4|template5|template6|template7|template8|template9|text|text_buffer_size|top_cpu_separate|top_name_width|total_run_times|update_interval|update_interval_on_battery|uppercase|use_spacer|use_xft|xftalpha|xftfont)\>" +color green "\<(alignment|append_file|background|border_inner_margin|border_outer_margin|border_width|color0|color1|color2|color3|color4|color5|color6|color7|color8|color9|colorN|cpu_avg_samples|default_bar_size|default_color|default_gauge_size|default_graph_size|default_outline_color|default_shade_color|diskio_avg_samples|display|double_buffer|draw_borders|draw_graph_borders|draw_outline|draw_shades|extra_newline|font|format_human_readable|gap_x|gap_y|if_up_strictness|imap|imlib_cache_flush_interval|imlib_cache_size|lua_draw_hook_post|lua_draw_hook_pre|lua_load|lua_shutdown_hook|lua_startup_hook|mail_spool|max_port_monitor_connections|max_specials|max_text_width|max_user_text|maximum_width|minimum_size|mpd_host|mpd_password|mpd_port|music_player_interval|net_avg_samples|no_buffers|out_to_console|out_to_ncurses|out_to_stderr|out_to_x|override_utf8_locale|overwrite_file|own_window|own_window_class|own_window_colour|own_window_hints|own_window_title|own_window_transparent|own_window_type|pad_percents|pop3|sensor_device|short_units|show_graph_range|show_graph_scale|stippled_borders|temperature_unit|template|template0|template1|template2|template3|template4|template5|template6|template7|template8|template9|text|text_buffer_size|times_in_seconds|top_cpu_separate|top_name_width|total_run_times|update_interval|update_interval_on_battery|uppercase|use_spacer|use_xft|xftalpha|xftfont)\>" ## Configuration item constants color yellow "\<(above|below|bottom_left|bottom_right|bottom_middle|desktop|dock|no|none|normal|override|skip_pager|skip_taskbar|sticky|top_left|top_right|top_middle|middle_left|middle_right|middle_middle|undecorated|yes)\>" diff --git a/extras/vim/syntax/conkyrc.vim b/extras/vim/syntax/conkyrc.vim index 63c1f42f..b458ea6e 100644 --- a/extras/vim/syntax/conkyrc.vim +++ b/extras/vim/syntax/conkyrc.vim @@ -12,7 +12,7 @@ endif syn region ConkyrcComment start=/^\s*#/ end=/$/ -syn keyword ConkyrcSetting alignment append_file background border_inner_margin border_outer_margin border_width color0 color1 color2 color3 color4 color5 color6 color7 color8 color9 colorN cpu_avg_samples default_bar_size default_color default_gauge_size default_graph_size default_outline_color default_shade_color diskio_avg_samples display double_buffer draw_borders draw_graph_borders draw_outline draw_shades extra_newline font format_human_readable gap_x gap_y if_up_strictness imap imlib_cache_flush_interval imlib_cache_size lua_draw_hook_post lua_draw_hook_pre lua_load lua_shutdown_hook lua_startup_hook mail_spool max_port_monitor_connections max_specials max_text_width max_user_text maximum_width minimum_size mpd_host mpd_password mpd_port music_player_interval net_avg_samples no_buffers out_to_console out_to_ncurses out_to_stderr out_to_x override_utf8_locale overwrite_file own_window own_window_class own_window_colour own_window_hints own_window_title own_window_transparent own_window_type pad_percents pop3 sensor_device short_units show_graph_range show_graph_scale stippled_borders temperature_unit template template0 template1 template2 template3 template4 template5 template6 template7 template8 template9 text text_buffer_size top_cpu_separate top_name_width total_run_times update_interval update_interval_on_battery uppercase use_spacer use_xft xftalpha xftfont +syn keyword ConkyrcSetting alignment append_file background border_inner_margin border_outer_margin border_width color0 color1 color2 color3 color4 color5 color6 color7 color8 color9 colorN cpu_avg_samples default_bar_size default_color default_gauge_size default_graph_size default_outline_color default_shade_color diskio_avg_samples display double_buffer draw_borders draw_graph_borders draw_outline draw_shades extra_newline font format_human_readable gap_x gap_y if_up_strictness imap imlib_cache_flush_interval imlib_cache_size lua_draw_hook_post lua_draw_hook_pre lua_load lua_shutdown_hook lua_startup_hook mail_spool max_port_monitor_connections max_specials max_text_width max_user_text maximum_width minimum_size mpd_host mpd_password mpd_port music_player_interval net_avg_samples no_buffers out_to_console out_to_ncurses out_to_stderr out_to_x override_utf8_locale overwrite_file own_window own_window_class own_window_colour own_window_hints own_window_title own_window_transparent own_window_type pad_percents pop3 sensor_device short_units show_graph_range show_graph_scale stippled_borders temperature_unit template template0 template1 template2 template3 template4 template5 template6 template7 template8 template9 text text_buffer_size times_in_seconds top_cpu_separate top_name_width total_run_times update_interval update_interval_on_battery uppercase use_spacer use_xft xftalpha xftfont syn keyword ConkyrcConstant \ above diff --git a/src/Makefile.am b/src/Makefile.am index 397ffb08..61353bd7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,8 +53,8 @@ mandatory_sources = colours.c colours.h combine.c combine.h common.c common.h \ conky.cc conky.h core.cc core.h diskio.c diskio.h entropy.c entropy.h \ exec.c exec.h fs.c fs.h logging.h mail.c mail.h mixer.c mixer.h net_stat.c \ net_stat.h template.c template.h timed_thread.c timed_thread.h mboxscan.c \ - mboxscan.h read_tcp.c read_tcp.h scroll.c scroll.h specials.c \ - specials.h tailhead.c tailhead.h temphelper.c temphelper.h \ + mboxscan.h prioqueue.c prioqueue.h read_tcp.c read_tcp.h scroll.c scroll.h \ + specials.c specials.h tailhead.c tailhead.h temphelper.c temphelper.h \ text_object.c text_object.h timeinfo.c timeinfo.h top.c top.h algebra.c \ algebra.h proc.c proc.h user.c user.h diff --git a/src/algebra.h b/src/algebra.h index 2350a77b..c7e16a9e 100644 --- a/src/algebra.h +++ b/src/algebra.h @@ -40,13 +40,13 @@ enum match_type { OP_EQ = 3, /* == */ OP_LEQ = 4, /* <= */ OP_GEQ = 5, /* >= */ - OP_NEQ = 6, /* != */ + OP_NEQ = 6 /* != */ }; enum arg_type { ARG_STRING = 1, /* "asdf" */ ARG_LONG = 2, /* 123456 */ - ARG_DOUBLE = 3, /* 12.456 */ + ARG_DOUBLE = 3 /* 12.456 */ }; int compare(const char *); diff --git a/src/apcupsd.c b/src/apcupsd.c index eb2c0bea..d7678d2c 100644 --- a/src/apcupsd.c +++ b/src/apcupsd.c @@ -33,12 +33,37 @@ #include #include +enum _apcupsd_items { + APCUPSD_NAME, + APCUPSD_MODEL, + APCUPSD_UPSMODE, + APCUPSD_CABLE, + APCUPSD_STATUS, + APCUPSD_LINEV, + APCUPSD_LOAD, + APCUPSD_CHARGE, + APCUPSD_TIMELEFT, + APCUPSD_TEMP, + APCUPSD_LASTXFER, + _APCUPSD_COUNT +}; + +/* type for data exchange with main thread */ +#define APCUPSD_MAXSTR 32 +typedef struct apcupsd_s { + char items[_APCUPSD_COUNT][APCUPSD_MAXSTR+1]; /* e.g. items[APCUPSD_STATUS] */ + char host[64]; + int port; +} APCUPSD_S, *PAPCUPSD_S; + +static APCUPSD_S apcupsd; + + // // encapsulated recv() // static int net_recv_ex(int sock, void *buf, int size, struct timeval *tv) { - fd_set fds; int res; @@ -74,8 +99,8 @@ static int net_recv_ex(int sock, void *buf, int size, struct timeval *tv) // // read whole buffer or fail // -static int net_recv(int sock, void* buf, int size) { - +static int net_recv(int sock, void* buf, int size) +{ int todo = size; int off = 0; int len; @@ -93,8 +118,8 @@ static int net_recv(int sock, void* buf, int size) { // // get one response line // -static int get_line(int sock, char line[], short linesize) { - +static int get_line(int sock, char line[], short linesize) +{ // get the line length short sz; if (!net_recv(sock, &sz, sizeof(sz))) return -1; @@ -130,8 +155,8 @@ static int get_line(int sock, char line[], short linesize) { // // fills in the data received from a socket // -static int fill_items(int sock, PAPCUPSD_S apc) { - +static int fill_items(int sock, PAPCUPSD_S apc) +{ char line[512]; int len; while ((len = get_line(sock, line, sizeof(line)))) { @@ -148,15 +173,15 @@ static int fill_items(int sock, PAPCUPSD_S apc) { FILL("ITEMP", APCUPSD_TEMP, TRUE); FILL("LASTXFER", APCUPSD_LASTXFER, FALSE); } - + return len == 0; } // // Conky update function for apcupsd data // -void update_apcupsd(void) { - +void update_apcupsd(void) +{ int i; APCUPSD_S apc; int sock; @@ -182,27 +207,27 @@ void update_apcupsd(void) { break; } #ifdef HAVE_GETHOSTBYNAME_R - if (gethostbyname_r(info.apcupsd.host, &he_mem, hostbuff, sizeof(hostbuff), &he, &he_errno) || !he ) { + if (gethostbyname_r(apcupsd.host, &he_mem, hostbuff, sizeof(hostbuff), &he, &he_errno) || !he ) { NORM_ERR("APCUPSD gethostbyname_r: %s", hstrerror(h_errno)); break; } #else /* HAVE_GETHOSTBYNAME_R */ - he = gethostbyname(info.apcupsd.host); + he = gethostbyname(apcupsd.host); if (!he) { herror("gethostbyname"); break; } #endif /* HAVE_GETHOSTBYNAME_R */ - + memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = info.apcupsd.port; + addr.sin_port = apcupsd.port; memcpy(&addr.sin_addr, he->h_addr, he->h_length); if (connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) { // no error reporting, the daemon is probably not running break; } - + // // send status request - "status" - 6B // @@ -212,7 +237,7 @@ void update_apcupsd(void) { perror("send"); break; } - + // // read the lines of output and put them into the info structure // @@ -225,22 +250,34 @@ void update_apcupsd(void) { // // "atomically" copy the data into working set // - memcpy(info.apcupsd.items, apc.items, sizeof(info.apcupsd.items)); + memcpy(apcupsd.items, apc.items, sizeof(apcupsd.items)); return; } +int apcupsd_scan_arg(const char *arg) +{ + char host[64]; + int port; + if (sscanf(arg, "%63s %d", host, &port) != 2) + return 1; + + apcupsd.port = htons(port); + strncpy(apcupsd.host, host, sizeof(apcupsd.host)); + return 0; +} + double apcupsd_loadbarval(struct text_object *obj) { (void)obj; - return atof(info.apcupsd.items[APCUPSD_LOAD]); + return atof(apcupsd.items[APCUPSD_LOAD]); } #define APCUPSD_PRINT_GENERATOR(name, idx) \ void print_apcupsd_##name(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ - snprintf(p, p_max_size, "%s", info.apcupsd.items[APCUPSD_##idx]); \ + snprintf(p, p_max_size, "%s", apcupsd.items[APCUPSD_##idx]); \ } APCUPSD_PRINT_GENERATOR(name, NAME) diff --git a/src/apcupsd.h b/src/apcupsd.h index ab2fcb62..0accfcb7 100644 --- a/src/apcupsd.h +++ b/src/apcupsd.h @@ -29,28 +29,7 @@ extern "C" { #endif -enum _apcupsd_items { - APCUPSD_NAME, - APCUPSD_MODEL, - APCUPSD_UPSMODE, - APCUPSD_CABLE, - APCUPSD_STATUS, - APCUPSD_LINEV, - APCUPSD_LOAD, - APCUPSD_CHARGE, - APCUPSD_TIMELEFT, - APCUPSD_TEMP, - APCUPSD_LASTXFER, - _APCUPSD_COUNT, -}; - -/* type for data exchange with main thread */ -#define APCUPSD_MAXSTR 32 -typedef struct apcupsd_s { - char items[_APCUPSD_COUNT][APCUPSD_MAXSTR+1]; /* e.g. items[APCUPSD_STATUS] */ - char host[64]; - int port; -} APCUPSD_S, *PAPCUPSD_S; +int apcupsd_scan_arg(const char *); /* Service routine for the conky main thread */ void update_apcupsd(void); diff --git a/src/conky.cc b/src/conky.cc index 8cc21c80..1657f63e 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -33,6 +33,7 @@ #include "conky.h" #include "common.h" #include "timed_thread.h" +#include #include #include #include @@ -73,35 +74,21 @@ /* local headers */ #include "core.h" -#include "algebra.h" #include "build.h" #include "colours.h" -#include "combine.h" #include "diskio.h" #include "exec.h" -#include "proc.h" -#include "user.h" #ifdef X11 #include "fonts.h" #endif -#include "fs.h" #ifdef HAVE_ICONV #include "iconv_tools.h" #endif #include "logging.h" -#include "mixer.h" #include "mail.h" -#include "mboxscan.h" #include "net_stat.h" -#ifdef NVIDIA -#include "nvidia.h" -#endif -#include "read_tcp.h" -#include "scroll.h" -#include "specials.h" #include "temphelper.h" #include "template.h" -#include "tailhead.h" #include "timeinfo.h" #include "top.h" @@ -143,7 +130,7 @@ static char *tmpstring1, *tmpstring2; int short_units; int format_human_readable; int cpu_separate; -enum { +enum spacer_state { NO_SPACER = 0, LEFT_SPACER, RIGHT_SPACER @@ -734,8 +721,10 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) struct text_object *obj; size_t a; #ifdef HAVE_ICONV - char buff_in[p_max_size]; - buff_in[0] = 0; + char *buff_in; + + buff_in = (char *)malloc(p_max_size); + memset(buff_in, 0, p_max_size); #endif /* HAVE_ICONV */ p[0] = 0; @@ -779,6 +768,9 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) /* load any new fonts we may have had */ load_fonts(); #endif /* X11 */ +#ifdef HAVE_ICONV + free(buff_in); +#endif /* HAVE_ICONV */ } void evaluate(const char *text, char *p, int p_max_size) @@ -1216,7 +1208,7 @@ static void draw_string(const char *s) int draw_each_line_inner(char *s, int special_index, int last_special_applied) { #ifdef X11 - int font_h; + int font_h = 0; int cur_y_add = 0; #endif /* X11 */ char *recurse = 0; @@ -1484,32 +1476,29 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) unsigned short int timeunits; if (seconds != 0) { timeunits = seconds / 86400; seconds %= 86400; - if (timeunits > 0) { - asprintf(&tmp_day_str, "%dd", timeunits); - } else { + if (timeunits <= 0 || + asprintf(&tmp_day_str, "%dd", timeunits) == -1) { tmp_day_str = strdup(""); } timeunits = seconds / 3600; seconds %= 3600; - if (timeunits > 0) { - asprintf(&tmp_hour_str, "%dh", timeunits); - } else { + if (timeunits <= 0 || + asprintf(&tmp_hour_str, "%dh", timeunits) == -1) { tmp_hour_str = strdup(""); } timeunits = seconds / 60; seconds %= 60; - if (timeunits > 0) { - asprintf(&tmp_min_str, "%dm", timeunits); - } else { + if (timeunits <= 0 || + asprintf(&tmp_min_str, "%dm", timeunits) == -1) { tmp_min_str = strdup(""); } - if (seconds > 0) { - asprintf(&tmp_sec_str, "%ds", seconds); - } else { + if (seconds <= 0 || + asprintf(&tmp_sec_str, "%ds", seconds) == -1) { tmp_sec_str = strdup(""); } - asprintf(&tmp_str, "%s%s%s%s", tmp_day_str, tmp_hour_str, tmp_min_str, tmp_sec_str); + if (asprintf(&tmp_str, "%s%s%s%s", tmp_day_str, tmp_hour_str, tmp_min_str, tmp_sec_str) == -1) + tmp_str = strdup(""); free(tmp_day_str); free(tmp_hour_str); free(tmp_min_str); free(tmp_sec_str); } else { - asprintf(&tmp_str, "Range not possible"); // should never happen, but better safe then sorry + tmp_str = strdup("Range not possible"); // should never happen, but better safe then sorry } cur_x += (w / 2) - (font_ascent() * (strlen(tmp_str) / 2)); cur_y += font_h / 2; @@ -1876,9 +1865,9 @@ static void main_loop(void) info.looped = 0; while (terminate == 0 && (total_run_times == 0 || info.looped < total_run_times)) { if(update_interval_bat != NOBATTERY && update_interval_bat != update_interval_old) { - char buf[max_user_text]; + char buf[64]; - get_battery_short_status(buf, max_user_text, "BAT0"); + get_battery_short_status(buf, 64, "BAT0"); if(buf[0] == 'D') { update_interval = update_interval_bat; } else { @@ -2583,7 +2572,7 @@ static void set_default_configurations(void) mpd_set_host(mpd_env_host); } else { /* MPD_HOST contains a password */ - char mpd_password[mpd_hostpart - mpd_env_host + 1]; + char *mpd_password = (char *)malloc(mpd_hostpart - mpd_env_host + 1); snprintf(mpd_password, mpd_hostpart - mpd_env_host + 1, "%s", mpd_env_host); if (!strlen(mpd_hostpart + 1)) { @@ -2593,6 +2582,7 @@ static void set_default_configurations(void) } mpd_set_password(mpd_password, 1); + free(mpd_password); } } @@ -4186,7 +4176,8 @@ int main(int argc, char **argv) current_config = strndup(optarg, max_user_text); break; case 'q': - freopen("/dev/null", "w", stderr); + if (freopen("/dev/null", "w", stderr)) + CRIT_ERR(0, 0, "could not open /dev/null as stderr!"); break; case 'h': print_help(argv[0]); diff --git a/src/conky.h b/src/conky.h index d4f60c1c..b19829d2 100644 --- a/src/conky.h +++ b/src/conky.h @@ -116,11 +116,6 @@ struct text_object; #include "xmms2.h" #endif -#ifdef IBM -#include "ibm.h" -#include "smapi.h" -#endif - #ifdef APCUPSD #include "apcupsd.h" #endif @@ -247,10 +242,6 @@ struct information { struct x11_info x11; #endif -#ifdef APCUPSD - APCUPSD_S apcupsd; -#endif - short kflags; /* kernel settings, see enum KFLAG */ }; diff --git a/src/core.cc b/src/core.cc index c1b33382..6c49b8c5 100644 --- a/src/core.cc +++ b/src/core.cc @@ -46,6 +46,10 @@ #include "fonts.h" #endif #include "fs.h" +#ifdef IBM +#include "ibm.h" +#include "smapi.h" +#endif #ifdef HAVE_ICONV #include "iconv_tools.h" #endif @@ -139,7 +143,7 @@ struct text_object *construct_text_object(const char *s, const char *arg, long /* helper defines for internal use only */ #define __OBJ_HEAD(a, n) if (!strcmp(s, #a)) { \ - obj->type = OBJ_##a; add_update_callback(n); + add_update_callback(n); #define __OBJ_IF obj_be_ifblock_if(ifblock_opaque, obj) #define __OBJ_ARG(...) if (!arg) { CRIT_ERR(obj, free_at_crash, __VA_ARGS__); } @@ -152,23 +156,19 @@ struct text_object *construct_text_object(const char *s, const char *arg, long #ifdef X11 if (s[0] == '#') { - obj->type = OBJ_color; obj->data.l = get_x11_color(s); obj->callbacks.print = &new_fg; } else #endif /* X11 */ -#ifdef __OpenBSD__ - OBJ(freq, 0) - obj->callbacks.print = &print_freq; -#else +#ifndef __OpenBSD__ OBJ(acpitemp, 0) obj->data.i = open_acpi_temperature(arg); obj->callbacks.print = &print_acpitemp; obj->callbacks.free = &free_acpitemp; END OBJ(acpiacadapter, 0) obj->callbacks.print = &print_acpiacadapter; - END OBJ(freq, 0) #endif /* !__OpenBSD__ */ + END OBJ(freq, 0) get_cpu_count(); if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0 || atoi(&arg[0]) > info.cpu_count) { @@ -678,13 +678,12 @@ struct text_object *construct_text_object(const char *s, const char *arg, long /* XXX: maybe fiddle them apart later, as print_top() does * nothing else than just that, using an ugly switch(). */ if (strncmp(s, "top", 3) == EQUAL) { - add_update_callback(&update_meminfo); - add_update_callback(&update_top); - if (!parse_top_args(s, arg, obj)) { + if (parse_top_args(s, arg, obj)) { + add_update_callback(&update_top); + } else { + free(obj); return NULL; } - obj->callbacks.print = &print_top; - obj->callbacks.free = &free_top; } else #ifdef __linux__ OBJ(addr, &update_net_stats) @@ -1547,13 +1546,8 @@ struct text_object *construct_text_object(const char *s, const char *arg, long #endif /* NVIDIA */ #ifdef APCUPSD END OBJ_ARG(apcupsd, &update_apcupsd, "apcupsd needs arguments: ") - char host[64]; - int port; - if (sscanf(arg, "%63s %d", host, &port) != 2) { + if (apcupsd_scan_arg(arg)) { CRIT_ERR(obj, free_at_crash, "apcupsd needs arguments: "); - } else { - info.apcupsd.port = htons(port); - strncpy(info.apcupsd.host, host, sizeof(info.apcupsd.host)); } obj->callbacks.print = &gen_print_nothing; END OBJ(apcupsd_name, &update_apcupsd) @@ -1593,11 +1587,12 @@ struct text_object *construct_text_object(const char *s, const char *arg, long obj->callbacks.print = &print_apcupsd_lastxfer; #endif /* APCUPSD */ END { - char buf[text_buffer_size]; + char *buf = (char *)malloc(text_buffer_size); NORM_ERR("unknown variable %s", s); snprintf(buf, text_buffer_size, "${%s}", s); obj_be_plain_text(obj, buf); + free(buf); } #undef OBJ #undef OBJ_IF @@ -1690,7 +1685,7 @@ int extract_variable_text_internal(struct text_object *retval, const char *const s = p; if (*p != '$') { - char buf[text_buffer_size]; + char *buf = (char *)malloc(text_buffer_size); const char *var; /* variable is either $foo or ${foo} */ @@ -1737,6 +1732,7 @@ int extract_variable_text_internal(struct text_object *retval, const char *const if (obj) { append_object(retval, obj); } + free(buf); continue; } @@ -1769,6 +1765,7 @@ int extract_variable_text_internal(struct text_object *retval, const char *const if (obj != NULL) { append_object(retval, obj); } + free(buf); continue; } else { obj = create_plain_text("$"); diff --git a/src/ibm.h b/src/ibm.h index 1029969c..94f5f3dd 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -3,8 +3,6 @@ #ifndef _IBM_H #define _IBM_H -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/src/linux.c b/src/linux.c index eadb7b99..19d54391 100644 --- a/src/linux.c +++ b/src/linux.c @@ -63,6 +63,7 @@ #endif #include #include +#include /* The following ifdefs were adapted from gkrellm */ #include @@ -688,14 +689,20 @@ void update_stat(void) const char *stat_template = NULL; unsigned int malloc_cpu_size = 0; extern void* global_cpu; + + static pthread_mutex_t last_stat_update_mutex = PTHREAD_MUTEX_INITIALIZER; static double last_stat_update = 0.0; /* since we use wrappers for this function, the update machinery * can't eliminate double invocations of this function. Check for * them here, otherwise cpu_usage counters are freaking out. */ - if (last_stat_update == current_update_time) + pthread_mutex_lock(&last_stat_update_mutex); + if (last_stat_update == current_update_time) { + pthread_mutex_unlock(&last_stat_update_mutex); return; + } last_stat_update = current_update_time; + pthread_mutex_unlock(&last_stat_update_mutex); /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */ if (!cpu_setup || !info.cpu_usage) { diff --git a/src/mail.c b/src/mail.c index 2dba7cc1..f5be56be 100644 --- a/src/mail.c +++ b/src/mail.c @@ -653,9 +653,7 @@ static void *imap_thread(void *arg) unsigned long old_unseen = ULONG_MAX; unsigned long old_messages = ULONG_MAX; struct stat stat_buf; - struct hostent he, *he_res = 0; - int he_errno; - char hostbuff[2048]; + struct hostent *he_res = 0; struct sockaddr_in their_addr; // connector's address information struct mail_s *mail = (struct mail_s *)arg; int has_idle = 0; @@ -669,6 +667,10 @@ static void *imap_thread(void *arg) if (!resolved_host) { #ifdef HAVE_GETHOSTBYNAME_R + int he_errno; + struct hostent he; + char hostbuff[2048]; + if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info NORM_ERR("IMAP gethostbyname_r: %s", hstrerror(h_errno)); fail++; @@ -1008,9 +1010,7 @@ static void *pop3_thread(void *arg) unsigned int fail = 0; unsigned long old_unseen = ULONG_MAX; struct stat stat_buf; - struct hostent he, *he_res = 0; - int he_errno; - char hostbuff[2048]; + struct hostent *he_res = 0; struct sockaddr_in their_addr; // connector's address information struct mail_s *mail = (struct mail_s *)arg; char resolved_host = 0; @@ -1021,6 +1021,10 @@ static void *pop3_thread(void *arg) fd_set fdset; if (!resolved_host) { #ifdef HAVE_GETHOSTBYNAME_R + int he_errno; + struct hostent he; + char hostbuff[2048]; + if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info NORM_ERR("POP3 gethostbyname_r: %s", hstrerror(h_errno)); fail++; diff --git a/src/prioqueue.c b/src/prioqueue.c new file mode 100644 index 00000000..0c9d9927 --- /dev/null +++ b/src/prioqueue.c @@ -0,0 +1,207 @@ +/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=c + * + * prioqueue: a simple priority queue implementation + * + * The queue organises it's data internally using a doubly linked + * list, into which elements are inserted at the right position. This + * is definitely not the best algorithm for a priority queue, but it + * fits best for the given purpose, i.e. the top process sorting. + * This means we have a rather little amount of total elements (~200 + * on a normal system), which are to be inserted into a queue of only + * the few top-most elements (10 at the current state). Additionally, + * at each update interval, the queue is drained completely and + * refilled from scratch. + * + * Copyright (C) 2009 Phil Sutter + * + * Initially based on the former implementation of sorted processes in + * top.c, Copyright (C) 2005 David Carter + * + * 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 . + * + */ + +#include /* INT_MAX */ +#include +#include + +struct prio_elem { + struct prio_elem *next, *prev; + void *data; +}; + +struct prio_queue { + /* Compare a and b. Return: + * <0 if a should come before b, + * >0 if b should come before a, + * 0 if don't care */ + int (*compare)(void *a, void *b); + + /* Free element payload. Called when dropping elements. */ + void (*free)(void *a); + + /* Maximum size of queue. The first + * elements in the list take precedence. */ + int max_size; + + /* The pointers to the actual list. */ + struct prio_elem *head, *tail; + + /* The current number of elements in the list. */ + int cur_size; +}; + +/* nop callback to save us from conditional calling */ +static void pq_free_nop(void *a) { (void)a; } + +struct prio_queue *init_prio_queue(void) +{ + struct prio_queue *retval; + + retval = malloc(sizeof(struct prio_queue)); + memset(retval, 0, sizeof(struct prio_queue)); + + /* use pq_free_nop by default */ + retval->free = &pq_free_nop; + + /* Default to maximum possible size as restricted + * by the used data type. This also saves us from + * checking if caller has set this field or not. */ + retval->max_size = INT_MAX; + + return retval; +} + +void pq_set_compare(struct prio_queue *queue, int (*pqcompare)(void *a, void *b)) +{ + if (pqcompare) + queue->compare = pqcompare; +} + +void pq_set_free(struct prio_queue *queue, void (*pqfree)(void *a)) +{ + if (pqfree) + queue->free = pqfree; +} + +void pq_set_max_size(struct prio_queue *queue, int max_size) +{ + if (max_size >= 0) + queue->max_size = max_size; +} + +int pq_get_cur_size(struct prio_queue *queue) +{ + return queue->cur_size; +} + +static struct prio_elem *init_prio_elem(void *data) +{ + struct prio_elem *retval; + + retval = malloc(sizeof(struct prio_elem)); + memset(retval, 0, sizeof(struct prio_elem)); + + retval->data = data; + return retval; +} + +void insert_prio_elem(struct prio_queue *queue, void *data) +{ + struct prio_elem *cur; + + /* queue->compare is a must-have */ + if (!queue->compare) + return; + + /* empty queue, insert the first item */ + if (!queue->cur_size) { + queue->cur_size++; + queue->head = queue->tail = init_prio_elem(data); + return; + } + + /* short-cut 1: new item is lower than all others */ + if (queue->compare(queue->tail->data, data) <= 0) { + if (queue->cur_size < queue->max_size) { + queue->cur_size++; + queue->tail->next = init_prio_elem(data); + queue->tail->next->prev = queue->tail; + queue->tail = queue->tail->next; + } else /* list was already full */ + (*queue->free)(data); + return; + } + + /* short-cut 2: we have a new maximum */ + if (queue->compare(queue->head->data, data) >= 0) { + queue->cur_size++; + queue->head->prev = init_prio_elem(data); + queue->head->prev->next = queue->head; + queue->head = queue->head->prev; + goto check_cur_size; + } + + /* find the actual position if short-cuts failed */ + for (cur = queue->head->next; cur; cur = cur->next) { + if (queue->compare(cur->data, data) >= 0) { + queue->cur_size++; + cur->prev->next = init_prio_elem(data); + cur->prev->next->prev = cur->prev; + cur->prev->next->next = cur; + cur->prev = cur->prev->next; + break; + } + } + +check_cur_size: + /* drop the lowest item if queue overrun */ + if (queue->cur_size > queue->max_size) { + queue->cur_size--; + queue->tail = queue->tail->prev; + (*queue->free)(queue->tail->next->data); + free(queue->tail->next); + queue->tail->next = NULL; + } +} + +void *pop_prio_elem(struct prio_queue *queue) +{ + struct prio_elem *tmp; + void *data; + + if (queue->cur_size <= 0) + return NULL; + + tmp = queue->head; + data = tmp->data; + + queue->head = queue->head->next; + queue->cur_size--; + if (queue->head) + queue->head->prev = NULL; + else /* list is now empty */ + queue->tail = NULL; + + free(tmp); + return data; +} + +void free_prio_queue(struct prio_queue *queue) +{ + void *data; + while((data = pop_prio_elem(queue))) + (*queue->free)(data); + free(queue); +} diff --git a/src/prioqueue.h b/src/prioqueue.h new file mode 100644 index 00000000..764be23b --- /dev/null +++ b/src/prioqueue.h @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=c + * + * prioqueue: a simple priority queue implementation + * + * Copyright (C) 2009 Phil Sutter + * + * Initially based on the former implementation of sorted processes in + * top.c, Copyright (C) 2005 David Carter + * + * 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 . + * + */ + +#ifndef _PRIOQUEUE_H +#define _PRIOQUEUE_H + +/* forward-define for private data */ +struct prio_queue; + +/* typedef for a distinct prioqueue object */ +typedef struct prio_queue *prio_queue_t; + +/* initialise a prioqueue object (mandatory) */ +prio_queue_t init_prio_queue(void); + +/* set the compare function (mandatory) + * (*compare) shall return: + * <0 if a should come before b, + * >0 if b should come before a, + * 0 if doesn't matter */ +void pq_set_compare(prio_queue_t, int (*compare)(void *a, void *b)); + +/* set the data free function (optional) + * (*free) will be called when: + * - dropping elements from the end of a limited size queue and + * - free_prio_queue() finds leftover elements in the given queue */ +void pq_set_free(prio_queue_t, void (*free)(void *)); + +/* set a maximum queue size (optional) (defaults to INT_MAX) */ +void pq_set_max_size(prio_queue_t, int); + +/* insert an element into the given queue */ +void insert_prio_elem(prio_queue_t, void *); + +/* return the number of elements in the queue */ +int pq_get_cur_size(prio_queue_t queue); + +/* pop the top-most element from the queue + * returns NULL if queue is empty */ +void *pop_prio_elem(prio_queue_t); + +/* clear and free the given queue */ +void free_prio_queue(prio_queue_t); + +#endif /* _PRIOQUEUE_H */ diff --git a/src/scroll.c b/src/scroll.c index c27d99ee..ad8f4bdc 100644 --- a/src/scroll.c +++ b/src/scroll.c @@ -73,8 +73,8 @@ void parse_scroll_arg(struct text_object *obj, const char *arg, void *free_at_cr #ifdef X11 /* add a color object right after scroll to reset any color changes */ - obj->next->type = OBJ_color; obj->next->data.l = sd->resetcolor; + obj->next->callbacks.print = &new_fg; #endif /* X11 */ } diff --git a/src/smapi.c b/src/smapi.c index 5c7ed29b..6a579686 100644 --- a/src/smapi.c +++ b/src/smapi.c @@ -22,7 +22,6 @@ * */ #include "conky.h" /* text_buffer_size, PACKAGE_NAME, maybe more */ -#include "smapi.h" #include "temphelper.h" #include "logging.h" #include @@ -33,7 +32,18 @@ #define SYS_SMAPI_PATH "/sys/devices/platform/smapi" -int smapi_bat_installed_internal(int idx) +static int smapi_read_int(const char *path) +{ + FILE *fp; + int i = 0; + if ((fp = fopen(path, "r")) != NULL) { + fscanf(fp, "%i\n", &i); + fclose(fp); + } + return i; +} + +static int smapi_bat_installed_internal(int idx) { char path[128]; struct stat sb; @@ -48,7 +58,7 @@ int smapi_bat_installed_internal(int idx) } -char *smapi_read_str(const char *path) +static char *smapi_read_str(const char *path) { FILE *fp; char str[256] = "failed"; @@ -59,18 +69,7 @@ char *smapi_read_str(const char *path) return strndup(str, text_buffer_size); } -int smapi_read_int(const char *path) -{ - FILE *fp; - int i = 0; - if ((fp = fopen(path, "r")) != NULL) { - fscanf(fp, "%i\n", &i); - fclose(fp); - } - return i; -} - -char *smapi_get_str(const char *fname) +static char *smapi_get_str(const char *fname) { char path[128]; if(snprintf(path, 127, SYS_SMAPI_PATH "/%s", fname) < 0) @@ -79,7 +78,7 @@ char *smapi_get_str(const char *fname) return smapi_read_str(path); } -char *smapi_get_bat_str(int idx, const char *fname) +static char *smapi_get_bat_str(int idx, const char *fname) { char path[128]; if(snprintf(path, 127, SYS_SMAPI_PATH "/BAT%i/%s", idx, fname) < 0) @@ -87,7 +86,7 @@ char *smapi_get_bat_str(int idx, const char *fname) return smapi_read_str(path); } -int smapi_get_bat_int(int idx, const char *fname) +static int smapi_get_bat_int(int idx, const char *fname) { char path[128]; if(snprintf(path, 127, SYS_SMAPI_PATH "/BAT%i/%s", idx, fname) < 0) @@ -95,7 +94,7 @@ int smapi_get_bat_int(int idx, const char *fname) return smapi_read_int(path); } -char *smapi_get_bat_val(const char *args) +static char *smapi_get_bat_val(const char *args) { char fname[128]; int idx, cnt; @@ -112,7 +111,7 @@ char *smapi_get_bat_val(const char *args) return smapi_get_bat_str(idx, fname); } -char *smapi_get_val(const char *args) +static char *smapi_get_val(const char *args) { char str[128]; diff --git a/src/smapi.h b/src/smapi.h index 138749dc..77f5d7ab 100644 --- a/src/smapi.h +++ b/src/smapi.h @@ -28,18 +28,6 @@ extern "C" { #endif -int smapi_bat_installed_internal(int); - -char *smapi_read_str(const char *); -int smapi_read_int(const char *); - -char *smapi_get_str(const char *); -char *smapi_get_val(const char *); - -char *smapi_get_bat_str(int, const char *); -int smapi_get_bat_int(int, const char *); -char *smapi_get_bat_val(const char *); - void print_smapi(struct text_object *, char *, int); uint8_t smapi_bat_percentage(struct text_object *); void print_smapi_bat_temp(struct text_object *, char *, int); diff --git a/src/specials.h b/src/specials.h index 85bb3f74..5f36b416 100644 --- a/src/specials.h +++ b/src/specials.h @@ -59,7 +59,7 @@ enum special_types { VOFFSET, FONT, GOTO, - TAB, + TAB }; struct special_t { diff --git a/src/text_object.c b/src/text_object.c index cf4df73d..412fff3c 100644 --- a/src/text_object.c +++ b/src/text_object.c @@ -196,7 +196,6 @@ int ifblock_stack_empty(void **opaque) void obj_be_plain_text(struct text_object *obj, const char *text) { - obj->type = OBJ_text; obj->data.s = strdup(text); obj->verbatim_output = 1; diff --git a/src/text_object.h b/src/text_object.h index 73489e4c..e1ed2f38 100644 --- a/src/text_object.h +++ b/src/text_object.h @@ -37,444 +37,6 @@ extern "C" { #endif -enum text_object_type { - OBJ_read_tcp, - OBJ_addr, -#if defined(__linux__) - OBJ_addrs, -#endif /* __linux__ */ -#ifndef __OpenBSD__ - OBJ_acpiacadapter, - OBJ_acpifan, - OBJ_acpitemp, - OBJ_battery, - OBJ_battery_time, - OBJ_battery_percent, - OBJ_battery_bar, - OBJ_battery_short, -#endif /* !__OpenBSD__ */ - OBJ_buffers, - OBJ_cached, - OBJ_color, - OBJ_color0, - OBJ_color1, - OBJ_color2, - OBJ_color3, - OBJ_color4, - OBJ_color5, - OBJ_color6, - OBJ_color7, - OBJ_color8, - OBJ_color9, - OBJ_conky_version, - OBJ_conky_build_date, - OBJ_conky_build_arch, - OBJ_font, - OBJ_cpu, - OBJ_cpubar, - OBJ_cpugauge, -#ifdef X11 - OBJ_cpugraph, - OBJ_loadgraph, -#endif /* X11 */ - OBJ_diskio, - OBJ_diskio_read, - OBJ_diskio_write, -#ifdef X11 - OBJ_diskiograph, - OBJ_diskiograph_read, - OBJ_diskiograph_write, -#endif /* X11 */ - OBJ_downspeed, - OBJ_downspeedf, -#ifdef X11 - OBJ_downspeedgraph, -#endif /* X11 */ - OBJ_else, - OBJ_endif, - OBJ_eval, - OBJ_image, - OBJ_exec, - OBJ_execi, - OBJ_texeci, - OBJ_execbar, - OBJ_execibar, - OBJ_execgauge, - OBJ_execigauge, -#ifdef X11 - OBJ_execgraph, - OBJ_execigraph, -#endif /* X11 */ - OBJ_execp, - OBJ_execpi, - OBJ_freq, - OBJ_freq_g, - OBJ_fs_bar, - OBJ_fs_bar_free, - OBJ_fs_free, - OBJ_fs_free_perc, - OBJ_fs_size, - OBJ_fs_type, - OBJ_fs_used, - OBJ_fs_used_perc, - OBJ_goto, - OBJ_tab, - OBJ_hr, - OBJ_offset, - OBJ_voffset, - OBJ_alignr, - OBJ_alignc, - OBJ_i2c, - OBJ_platform, - OBJ_hwmon, -#if defined(__linux__) - OBJ_disk_protect, - OBJ_i8k_version, - OBJ_i8k_bios, - OBJ_i8k_serial, - OBJ_i8k_cpu_temp, - OBJ_i8k_left_fan_status, - OBJ_i8k_right_fan_status, - OBJ_i8k_left_fan_rpm, - OBJ_i8k_right_fan_rpm, - OBJ_i8k_ac_status, - OBJ_i8k_buttons_status, -#if defined(IBM) - OBJ_ibm_fan, - OBJ_ibm_temps, - OBJ_ibm_volume, - OBJ_ibm_brightness, - OBJ_smapi, -#ifdef X11 - OBJ_smapi_bat_bar, -#endif /* X11 */ - OBJ_smapi_bat_perc, - OBJ_smapi_bat_temp, - OBJ_smapi_bat_power, - OBJ_if_smapi_bat_installed, -#endif /* IBM */ - /* information from sony_laptop kernel module - * /sys/devices/platform/sony-laptop */ - OBJ_sony_fanspeed, - OBJ_if_gw, - OBJ_ioscheduler, - OBJ_gw_iface, - OBJ_gw_ip, - OBJ_laptop_mode, - OBJ_pb_battery, - OBJ_voltage_mv, - OBJ_voltage_v, - OBJ_wireless_essid, - OBJ_wireless_mode, - OBJ_wireless_bitrate, - OBJ_wireless_ap, - OBJ_wireless_link_qual, - OBJ_wireless_link_qual_max, - OBJ_wireless_link_qual_perc, - OBJ_wireless_link_bar, -#endif /* __linux__ */ -#if defined(__FreeBSD__) || defined(__linux__) - OBJ_if_up, -#endif - OBJ_if_empty, - OBJ_if_match, - OBJ_if_existing, - OBJ_if_mounted, - OBJ_if_running, - OBJ_if_updatenr, - OBJ_top, - OBJ_top_mem, - OBJ_top_time, -#ifdef IOSTATS - OBJ_top_io, -#endif - OBJ_tail, - OBJ_head, - OBJ_lines, - OBJ_words, - OBJ_kernel, - OBJ_loadavg, - OBJ_machine, - OBJ_mails, - OBJ_new_mails, - OBJ_seen_mails, - OBJ_unseen_mails, - OBJ_flagged_mails, - OBJ_unflagged_mails, - OBJ_format_time, - OBJ_forwarded_mails, - OBJ_unforwarded_mails, - OBJ_replied_mails, - OBJ_unreplied_mails, - OBJ_draft_mails, - OBJ_trashed_mails, - OBJ_mboxscan, - OBJ_mem, - OBJ_memeasyfree, - OBJ_memfree, - OBJ_memgauge, -#ifdef X11 - OBJ_memgraph, -#endif /* X11 */ - OBJ_membar, - OBJ_memmax, - OBJ_memperc, - OBJ_mixer, - OBJ_mixerl, - OBJ_mixerr, - OBJ_mixerbar, - OBJ_mixerlbar, - OBJ_mixerrbar, - OBJ_if_mixer_mute, -#ifdef X11 - OBJ_monitor, - OBJ_monitor_number, - OBJ_desktop, - OBJ_desktop_number, - OBJ_desktop_name, -#endif /* X11 */ - OBJ_nameserver, - OBJ_nodename, - OBJ_nvidia, - OBJ_pre_exec, - OBJ_cmdline_to_pid, - OBJ_pid_chroot, - OBJ_pid_cmdline, - OBJ_pid_cwd, - OBJ_pid_environ, - OBJ_pid_environ_list, - OBJ_pid_exe, - OBJ_pid_nice, - OBJ_pid_openfiles, - OBJ_pid_parent, - OBJ_pid_priority, - OBJ_pid_state, - OBJ_pid_state_short, - OBJ_pid_stderr, - OBJ_pid_stdin, - OBJ_pid_stdout, - OBJ_pid_threads, - OBJ_pid_thread_list, - OBJ_pid_time_kernelmode, - OBJ_pid_time_usermode, - OBJ_pid_time, - OBJ_pid_uid, - OBJ_pid_euid, - OBJ_pid_suid, - OBJ_pid_fsuid, - OBJ_pid_gid, - OBJ_pid_egid, - OBJ_pid_sgid, - OBJ_pid_fsgid, - OBJ_pid_read, - OBJ_pid_vmpeak, - OBJ_pid_vmsize, - OBJ_pid_vmlck, - OBJ_pid_vmhwm, - OBJ_pid_vmrss, - OBJ_pid_vmdata, - OBJ_pid_vmstk, - OBJ_pid_vmexe, - OBJ_pid_vmlib, - OBJ_pid_vmpte, - OBJ_pid_write, - OBJ_gid_name, - OBJ_uid_name, - OBJ_processes, - OBJ_running_processes, - OBJ_shadecolor, - OBJ_outlinecolor, - OBJ_stippled_hr, - OBJ_swap, - OBJ_swapfree, - OBJ_swapbar, - OBJ_swapmax, - OBJ_swapperc, - OBJ_sysname, - OBJ_text, - OBJ_threads, - OBJ_running_threads, - OBJ_time, - OBJ_utime, - OBJ_tztime, - OBJ_totaldown, - OBJ_totalup, - OBJ_updates, - OBJ_upspeed, - OBJ_upspeedf, -#ifdef X11 - OBJ_upspeedgraph, -#endif /* X11 */ - OBJ_uptime, - OBJ_uptime_short, - OBJ_user_names, - OBJ_user_terms, - OBJ_user_times, - OBJ_user_time, - OBJ_user_number, - OBJ_imap_messages, - OBJ_imap_unseen, - OBJ_pop3_unseen, - OBJ_pop3_used, -#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ - || defined(__OpenBSD__)) && (defined(i386) || defined(__i386__)) - OBJ_apm_adapter, - OBJ_apm_battery_time, - OBJ_apm_battery_life, -#endif /* __FreeBSD__ __OpenBSD__ */ -#ifdef __OpenBSD__ - OBJ_obsd_sensors_temp, - OBJ_obsd_sensors_fan, - OBJ_obsd_sensors_volt, - OBJ_obsd_vendor, - OBJ_obsd_product, -#endif /* __OpenBSD__ */ -#ifdef MPD - OBJ_mpd_title, - OBJ_mpd_artist, - OBJ_mpd_album, - OBJ_mpd_random, - OBJ_mpd_repeat, - OBJ_mpd_vol, - OBJ_mpd_bitrate, - OBJ_mpd_status, - OBJ_mpd_bar, - OBJ_mpd_elapsed, - OBJ_mpd_length, - OBJ_mpd_track, - OBJ_mpd_name, - OBJ_mpd_file, - OBJ_mpd_percent, - OBJ_mpd_smart, - OBJ_if_mpd_playing, -#endif /* MPD */ -#ifdef MOC - OBJ_moc_state, - OBJ_moc_file, - OBJ_moc_title, - OBJ_moc_artist, - OBJ_moc_song, - OBJ_moc_album, - OBJ_moc_totaltime, - OBJ_moc_timeleft, - OBJ_moc_curtime, - OBJ_moc_bitrate, - OBJ_moc_rate, -#endif /* MOC */ -#ifdef XMMS2 - OBJ_xmms2_artist, - OBJ_xmms2_album, - OBJ_xmms2_title, - OBJ_xmms2_genre, - OBJ_xmms2_comment, - OBJ_xmms2_url, - OBJ_xmms2_date, - OBJ_xmms2_tracknr, - OBJ_xmms2_bitrate, - OBJ_xmms2_id, - OBJ_xmms2_duration, - OBJ_xmms2_elapsed, - OBJ_xmms2_size, - OBJ_xmms2_percent, - OBJ_xmms2_status, -#ifdef X11 - OBJ_xmms2_bar, -#endif /* X11 */ - OBJ_xmms2_smart, - OBJ_xmms2_playlist, - OBJ_xmms2_timesplayed, - OBJ_if_xmms2_connected, -#endif /* XMMS2 */ -#ifdef AUDACIOUS - OBJ_audacious_status, - OBJ_audacious_title, - OBJ_audacious_length, - OBJ_audacious_length_seconds, - OBJ_audacious_position, - OBJ_audacious_position_seconds, - OBJ_audacious_bitrate, - OBJ_audacious_frequency, - OBJ_audacious_channels, - OBJ_audacious_filename, - OBJ_audacious_playlist_length, - OBJ_audacious_playlist_position, - OBJ_audacious_main_volume, -#ifdef X11 - OBJ_audacious_bar, -#endif /* X11 */ -#endif /* AUDACIOUS */ -#ifdef BMPX - OBJ_bmpx_title, - OBJ_bmpx_artist, - OBJ_bmpx_album, - OBJ_bmpx_track, - OBJ_bmpx_uri, - OBJ_bmpx_bitrate, -#endif /* BMPX */ -#ifdef EVE - OBJ_eve, -#endif /* EVE */ -#ifdef HAVE_CURL - OBJ_curl, -#endif /* HAVE_CURL */ -#ifdef RSS - OBJ_rss, -#endif /* RSS */ -#ifdef WEATHER - OBJ_weather, -#endif /* WEATHER */ -#ifdef XOAP - OBJ_weather_forecast, -#endif /* XOAP */ -#ifdef HAVE_LUA - OBJ_lua, - OBJ_lua_parse, - OBJ_lua_bar, - OBJ_lua_gauge, -#ifdef X11 - OBJ_lua_graph, -#endif /* X11 */ -#endif /* HAVE_LUA */ -#ifdef TCP_PORT_MONITOR - OBJ_tcp_portmon, -#endif /* TCP_PORT_MONITOR */ -#ifdef HAVE_ICONV - OBJ_iconv_start, - OBJ_iconv_stop, -#endif /* HAVE_ICONV */ -#ifdef HDDTEMP - OBJ_hddtemp, -#endif /* HDDTEMP */ - OBJ_include, - OBJ_blink, - OBJ_to_bytes, - OBJ_scroll, - OBJ_combine, - OBJ_entropy_avail, - OBJ_entropy_perc, - OBJ_entropy_poolsize, - OBJ_entropy_bar, -#ifdef APCUPSD - OBJ_apcupsd, - OBJ_apcupsd_name, - OBJ_apcupsd_model, - OBJ_apcupsd_upsmode, - OBJ_apcupsd_cable, - OBJ_apcupsd_status, - OBJ_apcupsd_linev, - OBJ_apcupsd_load, - OBJ_apcupsd_loadbar, - OBJ_apcupsd_loadgauge, -#ifdef X11 - OBJ_apcupsd_loadgraph, -#endif /* X11 */ - OBJ_apcupsd_charge, - OBJ_apcupsd_timeleft, - OBJ_apcupsd_temp, - OBJ_apcupsd_lastxfer, -#endif /* APCUPSD */ -}; - /* text object callbacks */ struct obj_cb { /* text object: print obj's output to p */ @@ -531,7 +93,6 @@ struct text_object { char verbatim_output; void *special_data; - int type; long line; struct obj_cb callbacks; }; diff --git a/src/top.c b/src/top.c index 507e194c..5147a59e 100644 --- a/src/top.c +++ b/src/top.c @@ -29,6 +29,7 @@ * */ +#include "prioqueue.h" #include "top.h" #include "logging.h" @@ -595,25 +596,11 @@ static void calc_io_each(void) * Find the top processes * ******************************************/ -/* free a sp_process structure */ -static void free_sp(struct sorted_process *sp) +/* cpu comparison function for prio queue */ +static int compare_cpu(void *va, void *vb) { - free(sp); -} + struct process *a = va, *b = vb; -/* create a new sp_process structure */ -static struct sorted_process *malloc_sp(struct process *proc) -{ - struct sorted_process *sp; - sp = malloc(sizeof(struct sorted_process)); - memset(sp, 0, sizeof(struct sorted_process)); - sp->proc = proc; - return sp; -} - -/* cpu comparison function for insert_sp_element */ -static int compare_cpu(struct process *a, struct process *b) -{ if (a->amount < b->amount) { return 1; } else if (a->amount > b->amount) { @@ -623,9 +610,11 @@ static int compare_cpu(struct process *a, struct process *b) } } -/* mem comparison function for insert_sp_element */ -static int compare_mem(struct process *a, struct process *b) +/* mem comparison function for prio queue */ +static int compare_mem(void *va, void *vb) { + struct process *a = va, *b = vb; + if (a->rss < b->rss) { return 1; } else if (a->rss > b->rss) { @@ -635,16 +624,20 @@ static int compare_mem(struct process *a, struct process *b) } } -/* CPU time comparision function for insert_sp_element */ -static int compare_time(struct process *a, struct process *b) +/* CPU time comparision function for prio queue */ +static int compare_time(void *va, void *vb) { + struct process *a = va, *b = vb; + return b->total_cpu_time - a->total_cpu_time; } #ifdef IOSTATS -/* I/O comparision function for insert_sp_element */ -static int compare_io(struct process *a, struct process *b) +/* I/O comparision function for prio queue */ +static int compare_io(void *va, void *vb) { + struct process *a = va, *b = vb; + if (a->io_perc < b->io_perc) { return 1; } else if (a->io_perc > b->io_perc) { @@ -655,78 +648,6 @@ static int compare_io(struct process *a, struct process *b) } #endif /* IOSTATS */ -/* insert this process into the list in a sorted fashion, - * or destroy it if it doesn't fit on the list */ -static int insert_sp_element(struct sorted_process *sp_cur, - struct sorted_process **p_sp_head, struct sorted_process **p_sp_tail, - int max_elements, int compare_funct(struct process *, struct process *)) -{ - - struct sorted_process *sp_readthru = NULL, *sp_destroy = NULL; - int did_insert = 0, x = 0; - - if (*p_sp_head == NULL) { - *p_sp_head = sp_cur; - *p_sp_tail = sp_cur; - return 1; - } - for (sp_readthru = *p_sp_head, x = 0; - sp_readthru != NULL && x < max_elements; - sp_readthru = sp_readthru->less, x++) { - if (compare_funct(sp_readthru->proc, sp_cur->proc) > 0 && !did_insert) { - /* sp_cur is bigger than sp_readthru - * so insert it before sp_readthru */ - sp_cur->less = sp_readthru; - if (sp_readthru == *p_sp_head) { - /* insert as the new head of the list */ - *p_sp_head = sp_cur; - } else { - /* insert inside the list */ - sp_readthru->greater->less = sp_cur; - sp_cur->greater = sp_readthru->greater; - } - sp_readthru->greater = sp_cur; - /* element was inserted, so increase the counter */ - did_insert = ++x; - } - } - if (x < max_elements && sp_readthru == NULL && !did_insert) { - /* sp_cur is the smallest element and list isn't full, - * so insert at the end */ - (*p_sp_tail)->less = sp_cur; - sp_cur->greater = *p_sp_tail; - *p_sp_tail = sp_cur; - did_insert = x; - } else if (x >= max_elements) { - /* We inserted an element and now the list is too big by one. - * Destroy the smallest element */ - sp_destroy = *p_sp_tail; - *p_sp_tail = sp_destroy->greater; - (*p_sp_tail)->less = NULL; - free_sp(sp_destroy); - } - if (!did_insert) { - /* sp_cur wasn't added to the sorted list, so destroy it */ - free_sp(sp_cur); - } - return did_insert; -} - -/* copy the procs in the sorted list to the array, and destroy the list */ -static void sp_acopy(struct sorted_process *sp_head, struct process **ar, int max_size) -{ - struct sorted_process *sp_cur, *sp_tmp; - int x; - - sp_cur = sp_head; - for (x = 0; x < max_size && sp_cur != NULL; x++) { - ar[x] = sp_cur->proc; - sp_tmp = sp_cur; - sp_cur = sp_cur->less; - free_sp(sp_tmp); - } -} - /* ****************************************************************** * * Get a sorted list of the top cpu hogs and top mem hogs. * * Results are stored in the cpu,mem arrays in decreasing order[0-9]. * @@ -739,14 +660,14 @@ void process_find_top(struct process **cpu, struct process **mem, #endif /* IOSTATS */ ) { - struct sorted_process *spc_head = NULL, *spc_tail = NULL, *spc_cur = NULL; - struct sorted_process *spm_head = NULL, *spm_tail = NULL, *spm_cur = NULL; - struct sorted_process *spt_head = NULL, *spt_tail = NULL, *spt_cur = NULL; + prio_queue_t cpu_queue, mem_queue, time_queue #ifdef IOSTATS - struct sorted_process *spi_head = NULL, *spi_tail = NULL, *spi_cur = NULL; -#endif /* IOSTATS */ + , io_queue +#endif + ; struct process *cur_proc = NULL; unsigned long long total = 0; + int i; if (!top_cpu && !top_mem && !top_time #ifdef IOSTATS @@ -757,6 +678,24 @@ void process_find_top(struct process **cpu, struct process **mem, return; } + cpu_queue = init_prio_queue(); + pq_set_compare(cpu_queue, &compare_cpu); + pq_set_max_size(cpu_queue, MAX_SP); + + mem_queue = init_prio_queue(); + pq_set_compare(mem_queue, &compare_mem); + pq_set_max_size(mem_queue, MAX_SP); + + time_queue = init_prio_queue(); + pq_set_compare(time_queue, &compare_time); + pq_set_max_size(time_queue, MAX_SP); + +#ifdef IOSTATS + io_queue = init_prio_queue(); + pq_set_compare(io_queue, &compare_io); + pq_set_max_size(io_queue, MAX_SP); +#endif + total = calc_cpu_total(); /* calculate the total of the processor */ update_process_table(); /* update the table with process list */ calc_cpu_each(total); /* and then the percentage for each task */ @@ -769,131 +708,40 @@ void process_find_top(struct process **cpu, struct process **mem, while (cur_proc != NULL) { if (top_cpu) { - spc_cur = malloc_sp(cur_proc); - insert_sp_element(spc_cur, &spc_head, &spc_tail, MAX_SP, - &compare_cpu); + insert_prio_elem(cpu_queue, cur_proc); } if (top_mem) { - spm_cur = malloc_sp(cur_proc); - insert_sp_element(spm_cur, &spm_head, &spm_tail, MAX_SP, - &compare_mem); + insert_prio_elem(mem_queue, cur_proc); } if (top_time) { - spt_cur = malloc_sp(cur_proc); - insert_sp_element(spt_cur, &spt_head, &spt_tail, MAX_SP, - &compare_time); + insert_prio_elem(time_queue, cur_proc); } #ifdef IOSTATS if (top_io) { - spi_cur = malloc_sp(cur_proc); - insert_sp_element(spi_cur, &spi_head, &spi_tail, MAX_SP, - &compare_io); + insert_prio_elem(io_queue, cur_proc); } #endif /* IOSTATS */ cur_proc = cur_proc->next; } - if (top_cpu) sp_acopy(spc_head, cpu, MAX_SP); - if (top_mem) sp_acopy(spm_head, mem, MAX_SP); - if (top_time) sp_acopy(spt_head, ptime, MAX_SP); + for (i = 0; i < MAX_SP; i++) { + if (top_cpu) + cpu[i] = pop_prio_elem(cpu_queue); + if (top_mem) + mem[i] = pop_prio_elem(mem_queue); + if (top_time) + ptime[i] = pop_prio_elem(time_queue); #ifdef IOSTATS - if (top_io) sp_acopy(spi_head, io, MAX_SP); + if (top_io) + io[i] = pop_prio_elem(io_queue); #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 (!arg) { - NORM_ERR("top needs arguments"); - return 0; } - - if (obj->data.opaque) { - return 1; - } - - if (s[3] == 0) { - obj->type = OBJ_top; - top_cpu = 1; - } else if (strcmp(&s[3], "_mem") == EQUAL) { - obj->type = OBJ_top_mem; - top_mem = 1; - } else if (strcmp(&s[3], "_time") == EQUAL) { - obj->type = OBJ_top_time; - top_time = 1; + free_prio_queue(cpu_queue); + free_prio_queue(mem_queue); + free_prio_queue(time_queue); #ifdef IOSTATS - } else if (strcmp(&s[3], "_io") == EQUAL) { - obj->type = OBJ_top_io; - top_io = 1; + free_prio_queue(io_queue); #endif /* IOSTATS */ - } else { -#ifdef IOSTATS - NORM_ERR("Must be top, top_mem, top_time or top_io"); -#else /* IOSTATS */ - NORM_ERR("Must be top, top_mem or top_time"); -#endif /* IOSTATS */ - 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) { - td->type = TOP_NAME; - } else if (strcmp(buf, "cpu") == EQUAL) { - td->type = TOP_CPU; - } else if (strcmp(buf, "pid") == EQUAL) { - td->type = TOP_PID; - } else if (strcmp(buf, "mem") == EQUAL) { - td->type = TOP_MEM; - } else if (strcmp(buf, "time") == EQUAL) { - td->type = TOP_TIME; - } else if (strcmp(buf, "mem_res") == EQUAL) { - td->type = TOP_MEM_RES; - } else if (strcmp(buf, "mem_vsize") == EQUAL) { - td->type = TOP_MEM_VSIZE; -#ifdef IOSTATS - } else if (strcmp(buf, "io_read") == EQUAL) { - td->type = TOP_READ_BYTES; - } else if (strcmp(buf, "io_write") == EQUAL) { - td->type = TOP_WRITE_BYTES; - } else if (strcmp(buf, "io_perc") == EQUAL) { - td->type = TOP_IO_PERC; -#endif /* IOSTATS */ - } else { - NORM_ERR("invalid type arg for top"); -#ifdef IOSTATS - NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize, " - "io_read, io_write, io_perc"); -#else /* IOSTATS */ - NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize"); -#endif /* IOSTATS */ - return 0; - } - if (n < 1 || n > 10) { - NORM_ERR("invalid num arg for top. Must be between 1 and 10."); - return 0; - } else { - td->num = n - 1; - } - } else { - NORM_ERR("invalid argument count for top"); - return 0; - } - return 1; } static char *format_time(unsigned long timeval, const int width) @@ -936,6 +784,13 @@ static char *format_time(unsigned long timeval, const int width) return strndup("", text_buffer_size); } +struct top_data { + struct process **list; + int num; + int was_parsed; + char *s; +}; + static unsigned int top_name_width = 15; /* return zero on success, non-zero otherwise */ @@ -946,97 +801,74 @@ int set_top_name_width(const char *s) return !(sscanf(s, "%u", &top_name_width) == 1); } -void print_top(struct text_object *obj, char *p, int p_max_size) +static void print_top_name(struct text_object *obj, char *p, int p_max_size) { - struct information *cur = &info; struct top_data *td = obj->data.opaque; - struct process **needed = 0; int width; - if (!td) + if (!td || !td->list || !td->list[td->num]) 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; -#ifdef IOSTATS - case OBJ_top_io: - needed = cur->io; - break; -#endif /* IOSTATS */ - default: - return; - } - - - if (needed[td->num]) { - char *timeval; - - switch (td->type) { - case TOP_NAME: - width = MIN(p_max_size, (int)top_name_width + 1); - snprintf(p, width + 1, "%-*s", width, - needed[td->num]->name); - break; - case TOP_CPU: - width = MIN(p_max_size, 7); - snprintf(p, width, "%6.2f", - needed[td->num]->amount); - break; - case TOP_PID: - width = MIN(p_max_size, 6); - snprintf(p, width, "%5i", - needed[td->num]->pid); - break; - case TOP_MEM: - /* Calculate a percentage of residential mem from total mem available. - * Since rss is bytes and memmax kilobytes, dividing by 10 suffices here. */ - width = MIN(p_max_size, 7); - snprintf(p, width, "%6.2f", - (float) ((float)needed[td->num]->rss / cur->memmax) / 10); - break; - case TOP_TIME: - width = MIN(p_max_size, 10); - timeval = format_time( - needed[td->num]->total_cpu_time, 9); - snprintf(p, width, "%9s", timeval); - free(timeval); - break; - case TOP_MEM_RES: - human_readable(needed[td->num]->rss, - p, p_max_size); - break; - case TOP_MEM_VSIZE: - human_readable(needed[td->num]->vsize, - p, p_max_size); - break; -#ifdef IOSTATS - case TOP_READ_BYTES: - human_readable(needed[td->num]->read_bytes / update_interval, - p, p_max_size); - break; - case TOP_WRITE_BYTES: - human_readable(needed[td->num]->write_bytes / update_interval, - p, p_max_size); - break; - case TOP_IO_PERC: - width = MIN(p_max_size, 7); - snprintf(p, width, "%6.2f", - needed[td->num]->io_perc); - break; -#endif - } - } + width = MIN(p_max_size, (int)top_name_width + 1); + snprintf(p, width + 1, "%-*s", width, td->list[td->num]->name); } -void free_top(struct text_object *obj) +static void print_top_mem(struct text_object *obj, char *p, int p_max_size) +{ + struct top_data *td = obj->data.opaque; + int width; + + if (!td || !td->list || !td->list[td->num]) + return; + + width = MIN(p_max_size, 7); + snprintf(p, width, "%6.2f", (float) ((float)td->list[td->num]->rss / info.memmax) / 10); +} + +static void print_top_time(struct text_object *obj, char *p, int p_max_size) +{ + struct top_data *td = obj->data.opaque; + int width; + char *timeval; + + if (!td || !td->list || !td->list[td->num]) + return; + + width = MIN(p_max_size, 10); + timeval = format_time(td->list[td->num]->total_cpu_time, 9); + snprintf(p, width, "%9s", timeval); + free(timeval); +} + +#define PRINT_TOP_GENERATOR(name, width, fmt, field) \ +static void print_top_##name(struct text_object *obj, char *p, int p_max_size) \ +{ \ + struct top_data *td = obj->data.opaque; \ + if (!td || !td->list || !td->list[td->num]) \ + return; \ + snprintf(p, MIN(p_max_size, width), fmt, td->list[td->num]->field); \ +} + +#define PRINT_TOP_HR_GENERATOR(name, field, denom) \ +static void print_top_##name(struct text_object *obj, char *p, int p_max_size) \ +{ \ + struct top_data *td = obj->data.opaque; \ + if (!td || !td->list || !td->list[td->num]) \ + return; \ + human_readable(td->list[td->num]->field / denom, p, p_max_size); \ +} + +PRINT_TOP_GENERATOR(cpu, 7, "%6.2f", amount) +PRINT_TOP_GENERATOR(pid, 6, "%5i", pid) +PRINT_TOP_HR_GENERATOR(mem_res, rss, 1) +PRINT_TOP_HR_GENERATOR(mem_vsize, vsize, 1) +#ifdef IOSTATS +PRINT_TOP_HR_GENERATOR(read_bytes, read_bytes, update_interval) +PRINT_TOP_HR_GENERATOR(write_bytes, write_bytes, update_interval) +PRINT_TOP_GENERATOR(io_perc, 7, "%6.2f", io_perc) +#endif /* IOSTATS */ + +static void free_top(struct text_object *obj) { struct top_data *td = obj->data.opaque; @@ -1047,3 +879,92 @@ void free_top(struct text_object *obj) free(obj->data.opaque); obj->data.opaque = NULL; } + +int parse_top_args(const char *s, const char *arg, struct text_object *obj) +{ + struct top_data *td; + char buf[64]; + int n; + + 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)); + + if (s[3] == 0) { + td->list = info.cpu; + top_cpu = 1; + } else if (strcmp(&s[3], "_mem") == EQUAL) { + td->list = info.memu; + top_mem = 1; + } else if (strcmp(&s[3], "_time") == EQUAL) { + td->list = info.time; + top_time = 1; +#ifdef IOSTATS + } else if (strcmp(&s[3], "_io") == EQUAL) { + td->list = info.io; + top_io = 1; +#endif /* IOSTATS */ + } else { +#ifdef IOSTATS + NORM_ERR("Must be top, top_mem, top_time or top_io"); +#else /* IOSTATS */ + NORM_ERR("Must be top, top_mem or top_time"); +#endif /* IOSTATS */ + free(obj->data.opaque); + obj->data.opaque = 0; + return 0; + } + + td->s = strndup(arg, text_buffer_size); + + if (sscanf(arg, "%63s %i", buf, &n) == 2) { + if (strcmp(buf, "name") == EQUAL) { + obj->callbacks.print = &print_top_name; + } else if (strcmp(buf, "cpu") == EQUAL) { + obj->callbacks.print = &print_top_cpu; + } else if (strcmp(buf, "pid") == EQUAL) { + obj->callbacks.print = &print_top_pid; + } else if (strcmp(buf, "mem") == EQUAL) { + obj->callbacks.print = &print_top_mem; + add_update_callback(&update_meminfo); + } else if (strcmp(buf, "time") == EQUAL) { + obj->callbacks.print = &print_top_time; + } else if (strcmp(buf, "mem_res") == EQUAL) { + obj->callbacks.print = &print_top_mem_res; + } else if (strcmp(buf, "mem_vsize") == EQUAL) { + obj->callbacks.print = &print_top_mem_vsize; +#ifdef IOSTATS + } else if (strcmp(buf, "io_read") == EQUAL) { + obj->callbacks.print = &print_top_read_bytes; + } else if (strcmp(buf, "io_write") == EQUAL) { + obj->callbacks.print = &print_top_write_bytes; + } else if (strcmp(buf, "io_perc") == EQUAL) { + obj->callbacks.print = &print_top_io_perc; +#endif /* IOSTATS */ + } else { + NORM_ERR("invalid type arg for top"); +#ifdef IOSTATS + NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize, " + "io_read, io_write, io_perc"); +#else /* IOSTATS */ + NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize"); +#endif /* IOSTATS */ + return 0; + } + if (n < 1 || n > 10) { + NORM_ERR("invalid num arg for top. Must be between 1 and 10."); + return 0; + } else { + td->num = n - 1; + } + } else { + NORM_ERR("invalid argument count for top"); + return 0; + } + obj->callbacks.free = &free_top; + return 1; +} diff --git a/src/top.h b/src/top.h index deddf1de..82ec05a5 100644 --- a/src/top.h +++ b/src/top.h @@ -146,8 +146,6 @@ 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 *); /* return zero on success, non-zero otherwise */ int set_top_name_width(const char *);