diff --git a/cmake/Conky.cmake b/cmake/Conky.cmake index 7ca0e930..87b0282d 100644 --- a/cmake/Conky.cmake +++ b/cmake/Conky.cmake @@ -26,7 +26,7 @@ try_compile(GCC4_WORKS ${CMAKE_MODULE_PATH}/gcc44test.cc ) if(NOT GCC4_WORKS) - message(WARNING "Conky 2.x maybe requires GCC 4.4.0 or newer") + message(FATAL_ERROR "Conky 2.x requires GCC 4.4.0 or newer") endif(NOT GCC4_WORKS) # Set system vars diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index 541f919c..1a6e3404 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -57,6 +57,7 @@ set(CONFIG_FILE "$HOME/.conkyrc" CACHE STRING "Configfile of the user") set(MAX_USER_TEXT_DEFAULT "16384" CACHE STRING "Default maximum size of config TEXT buffer, i.e. below TEXT line.") set(DEFAULT_TEXT_BUFFER_SIZE "256" CACHE STRING "Default size used for temporary, static text buffers") set(MAX_NET_INTERFACES "16" CACHE STRING "Maximum number of network devices") +set(HTTPPORT "10080" CACHE STRING "Port to use for out_to_http") # Platform specific options @@ -149,4 +150,10 @@ endif(BUILD_WEATHER_XOAP) option(BUILD_APCUPSD "Enable APCUPSD support" true) +option(BUILD_ICAL "Enable if you want iCalendar (RFC 5545) support" false) + +option(BUILD_IRC "Enable if you want IRC support" false) + +option(BUILD_HTTP "Enable if you want HTTP support" false) + option(BUILD_ICONV "Enable iconv support" false) diff --git a/cmake/ConkyPlatformChecks.cmake b/cmake/ConkyPlatformChecks.cmake index 1341e015..8952dfe8 100644 --- a/cmake/ConkyPlatformChecks.cmake +++ b/cmake/ConkyPlatformChecks.cmake @@ -66,6 +66,31 @@ if(BUILD_MATH) set(conky_libs ${conky_libs} -lm) endif(BUILD_MATH) +if(BUILD_ICAL) + check_include_files(libical/ical.h ICAL_H_) + if(NOT ICAL_H_) + message(FATAL_ERROR "Unable to find libical") + endif(NOT ICAL_H_) + set(conky_libs ${conky_libs} -lical) +endif(BUILD_ICAL) + +if(BUILD_IRC) + check_include_files(libircclient/libircclient.h IRC_H_) + if(NOT IRC_H_) + message(FATAL_ERROR "Unable to find libircclient") + endif(NOT IRC_H_) + set(conky_libs ${conky_libs} -lircclient) +endif(BUILD_IRC) + +if(BUILD_HTTP) + find_file(HTTP_H_ microhttpd.h) + #I'm not using check_include_files because microhttpd.h seems to need a lot of different headers and i'm not sure which... + if(NOT HTTP_H_) + message(FATAL_ERROR "Unable to find libmicrohttpd") + endif(NOT HTTP_H_) + set(conky_libs ${conky_libs} -lmicrohttpd) +endif(BUILD_HTTP) + if(BUILD_BUILTIN_CONFIG) check_function_exists(fopencookie HAVE_FOPENCOOKIE) check_function_exists(funopen HAVE_FUNOPEN) @@ -191,6 +216,10 @@ if(BUILD_LUA) pkg_check_modules(CAIRO REQUIRED cairo cairo-xlib) set(luacairo_libs ${CAIRO_LIBRARIES} ${LUA_LIBRARIES}) set(luacairo_includes ${CAIRO_INCLUDE_DIRS} ${LUA_INCLUDE_DIRS}) + find_program(APP_PATCH patch) + if(NOT APP_PATCH) + message(FATAL_ERROR "Unable to find program 'patch'") + endif(NOT APP_PATCH) endif(BUILD_LUA_CAIRO) if(BUILD_LUA_IMLIB2) set(WANT_TOLUA true) diff --git a/cmake/ToLua.cmake b/cmake/ToLua.cmake index 0cd1eae8..c8b067c9 100644 --- a/cmake/ToLua.cmake +++ b/cmake/ToLua.cmake @@ -20,26 +20,34 @@ # along with this program. If not, see . # -function(wrap_tolua VAR) -if(NOT ARGN) - message(SEND_ERROR "Error: wrap_tolua called without any files") - return() -endif(NOT ARGN) - +function(wrap_tolua VAR FIL) SET(INCL) SET(${VAR}) -FOREACH(FIL ${ARGN}) - GET_FILENAME_COMPONENT(ABS_FIL ${FIL} ABSOLUTE) - GET_FILENAME_COMPONENT(FIL_WE ${FIL} NAME_WE) - LIST(APPEND ${VAR} "${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}.c") - ADD_CUSTOM_COMMAND( OUTPUT ${${VAR}} ${INCL} COMMAND ${APP_TOLUA} -n - ${FIL_WE} -o ${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}.c ${ABS_FIL} DEPENDS - ${ABS_FIL} COMMENT "Running tolua++ on ${FIL}" - VERBATIM ) +GET_FILENAME_COMPONENT(ABS_FIL ${FIL} ABSOLUTE) +GET_FILENAME_COMPONENT(FIL_WE ${FIL} NAME_WE) +LIST(APPEND ${VAR} "${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}.c") + +if(DEFINED ARGV2) + GET_FILENAME_COMPONENT(PATCH ${ARGV2} ABSOLUTE) + SET(TOLUA_OUT ${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}-orig.c) + ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}.c + COMMAND ${APP_PATCH} -s ${TOLUA_OUT} ${PATCH} -o ${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}.c + DEPENDS ${TOLUA_OUT} ${PATCH} + COMMENT "Patching lib${FIL_WE}-orig.c" + VERBATIM) + SET_SOURCE_FILES_PROPERTIES(${TOLUA_OUT} PROPERTIES GENERATED TRUE) +else() + SET(TOLUA_OUT ${CMAKE_CURRENT_BINARY_DIR}/lib${FIL_WE}.c) +endif(DEFINED ARGV2) + +ADD_CUSTOM_COMMAND( OUTPUT ${TOLUA_OUT} ${INCL} COMMAND ${APP_TOLUA} -n + ${FIL_WE} -o ${TOLUA_OUT} ${ABS_FIL} DEPENDS + ${ABS_FIL} COMMENT "Running tolua++ on ${FIL}" + VERBATIM ) + +SET_SOURCE_FILES_PROPERTIES(${${VAR}} ${INCL} PROPERTIES GENERATED TRUE) - SET_SOURCE_FILES_PROPERTIES(${${VAR}} ${INCL} PROPERTIES GENERATED TRUE) -ENDFOREACH(FIL) SET(${VAR} ${${VAR}} PARENT_SCOPE) diff --git a/cmake/config.h.in b/cmake/config.h.in index 3644a99d..0b5bf4b6 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -18,6 +18,7 @@ #define MAX_USER_TEXT_DEFAULT @MAX_USER_TEXT_DEFAULT@ #define DEFAULT_TEXT_BUFFER_SIZE @DEFAULT_TEXT_BUFFER_SIZE@ #define MAX_NET_INTERFACES @MAX_NET_INTERFACES@ +#define HTTPPORT @HTTPPORT@ #cmakedefine HAVE_SYS_STATFS_H 1 #cmakedefine HAVE_SYS_PARAM_H 1 @@ -87,6 +88,12 @@ #cmakedefine BUILD_WLAN 1 +#cmakedefine BUILD_ICAL 1 + +#cmakedefine BUILD_IRC 1 + +#cmakedefine BUILD_HTTP 1 + #cmakedefine BUILD_ICONV 1 #cmakedefine BUILD_LUA_CAIRO 1 @@ -99,4 +106,6 @@ #cmakedefine BUILD_IBM 1 +#cmakedefine BUILD_RSS 1 + #endif /* _conky_config_h_ */ diff --git a/doc/config_settings.xml b/doc/config_settings.xml index efdd30ab..ad8036fa 100644 --- a/doc/config_settings.xml +++ b/doc/config_settings.xml @@ -305,6 +305,17 @@ 7634. + + + + + + + When this is set the page generated with + out_to_http will automatically refresh each interval. Default + value is no. + + @@ -608,6 +619,15 @@ Print text to stdout. + + + + + + + Let conky act as a small http-server serving it's text. + + diff --git a/doc/variables.xml b/doc/variables.xml index 96b8b4e6..bc07927b 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -1537,6 +1537,32 @@ volume, controlled by the volume keys (0-14). + + + + + + + + Shows title of event number 'number' in the ical (RFC 5545) file + 'file'. The events are first ordered by starting time, events that started + in the past are ignored. The events that are shown are the VEVENTS, the + title that is shown is the SUMMARY and the starting time used for sorting + is DTSTART . + + + + + + + + + + Shows everything that's being told in #channel on IRCserver + 'server'. TCP-port 6667 is used for the connection unless 'port' is + specified. + + @@ -3281,7 +3307,7 @@ Displays the data of a stock symbol. The following data - is supported: adv(Average Daily Volume),ask,asksize,bid + is supported: adv(Average Daily Volume), ask, asksize, bid, askrt(ask realtime), bidrt(bid realtime), bookvalue, bidsize, change, commission, changert(change realtime), ahcrt(After Hours Change realtime), ds(dividend/share), ltd(Last Trade Date), tradedate, es(earnings/share), ei(error indication), epsecy(EPS Estimate Current Year), epseny(EPS Estimate Next Year), epsenq(EPS Estimate Next Quarter), floatshares, dayslow, dayshigh, 52weeklow, 52weekhigh, hgp(Holdings Gain Percent), ag(Annualized Gain), hg(Holdings Gain), hgprt(Holdings Gain Percent realtime), hgrt(Holdings Gain realtime), moreinfo, obrt(Order Book realtime), mc(Market Capitalization), mcrt(Market Cap realtime), ebitda, c52wlow(Change From 52-week Low), pc52wlow(Percent Change From 52-week Low), cprt(change percent realtime), lts(Last Trade Size), c52whigh(Change from 52-week high), pc52whigh(percent change from 52-week high), ltp(last trade price), hl(high limit), ll(low limit), dr(day's range), drrt(day's range realtime), 50ma(50-day Moving Average), 200ma(200-day Moving Average), c200ma(Change From 200-day Moving Average), pc200ma(Percent Change From 200-day Moving Average), c50ma(Change From 50-day Moving Average), pc50ma(Percent Change From 50-day Moving Average), name, notes, open, pc(previous close), pricepaid, cip(change in percent), ps(price/sales), pb(price/book), edv(Ex-Dividend Date), per(P/E Ratio), dpd(Dividend Pay Date), perrt(P/E Ratio realtime), pegr(PEG Ratio), pepsecy(Price/EPS Estimate Current Year), pepseny(Price/EPS Estimate Next Year), symbol, sharesowned, shortratio, ltt(Last Trade Time), tradelinks, tt(Ticker Trend), 1ytp(1 yr Target Price), volume, hv(Holdings Value), hvrt(Holdings Value realtime), 52weekrange, dvc(Day's Value Change), dvcrt(Day's Value Change realtime), se(Stock Exchange), dy(Dividend Yield) @@ -3363,6 +3389,21 @@ displayed, or until the text buffer is filled. + + + + + + + + Displays the number of microseconds it takes to + get a reply on a ping to to tcp 'port' on 'host'. 'port' is optional + and has 80 as default. This works on both open and closed + ports, just make sure that the port is not behind a firewall or you + will get 'down' as answer. It's best to test a closed port instead + of an open port, you will get a quicker response. + + @@ -4118,6 +4159,16 @@ Wireless bitrate (ie 11 Mb/s) (Linux only) + + + + + + + + WLAN channel on which device 'net' is listening (Linux only) + + @@ -4128,6 +4179,16 @@ Wireless access point ESSID (Linux only) + + + + + + + + Frequency on which device 'net' is listening (Linux only) + + diff --git a/extras/nano/conky.nanorc b/extras/nano/conky.nanorc index 9ffca656..367249a7 100644 --- a/extras/nano/conky.nanorc +++ b/extras/nano/conky.nanorc @@ -5,13 +5,13 @@ 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_text_width|max_user_text|maximum_width|minimum_size|mpd_host|mpd_password|mpd_port|music_player_interval|mysql_host|mysql_port|mysql_user|mysql_password|mysql_db|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)\>" +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|http_refresh|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_text_width|max_user_text|maximum_width|minimum_size|mpd_host|mpd_password|mpd_port|music_player_interval|mysql_host|mysql_port|mysql_user|mysql_password|mysql_db|net_avg_samples|no_buffers|out_to_console|out_to_http|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)\>" ## Variables -color brightblue "\<(acpiacadapter|acpifan|acpitemp|addr|addrs|alignc|alignr|apcupsd|apcupsd_cable|apcupsd_charge|apcupsd_lastxfer|apcupsd_linev|apcupsd_load|apcupsd_loadbar|apcupsd_loadgauge|apcupsd_loadgraph|apcupsd_model|apcupsd_name|apcupsd_status|apcupsd_temp|apcupsd_timeleft|apcupsd_upsmode|apm_adapter|apm_battery_life|apm_battery_time|audacious_bar|audacious_bitrate|audacious_channels|audacious_filename|audacious_frequency|audacious_length|audacious_length_seconds|audacious_main_volume|audacious_playlist_length|audacious_playlist_position|audacious_position|audacious_position_seconds|audacious_status|audacious_title|battery|battery_bar|battery_percent|battery_short|battery_time|blink|bmpx_album|bmpx_artist|bmpx_bitrate|bmpx_title|bmpx_track|bmpx_uri|buffers|cached|cmdline_to_pid|color|color0|color1|color2|color3|color4|color5|color6|color7|color8|color9|combine|conky_build_arch|conky_build_date|conky_version|cpu|cpubar|cpugauge|cpugraph|curl|desktop|desktop_name|desktop_number|disk_protect|diskio|diskio_read|diskio_write|diskiograph|diskiograph_read|diskiograph_write|distribution|downspeed|downspeedf|downspeedgraph|draft_mails|else|endif|entropy_avail|entropy_bar|entropy_perc|entropy_poolsize|eval|eve|exec|execbar|execgauge|execgraph|execi|execibar|execigauge|execigraph|execp|execpi|flagged_mails|font|format_time|forwarded_mails|freq|freq_g|fs_bar|fs_bar_free|fs_free|fs_free_perc|fs_size|fs_type|fs_used|fs_used_perc|goto|gw_iface|gw_ip|hddtemp|head|hr|hwmon|i2c|i8k_ac_status|i8k_bios|i8k_buttons_status|i8k_cpu_temp|i8k_left_fan_rpm|i8k_left_fan_status|i8k_right_fan_rpm|i8k_right_fan_status|i8k_serial|i8k_version|ibm_brightness|ibm_fan|ibm_temps|ibm_volume|iconv_start|iconv_stop|if_empty|if_existing|if_gw|if_match|if_mixer_mute|if_mounted|if_mpd_playing|if_running|if_smapi_bat_installed|if_up|if_updatenr|if_xmms2_connected|image|imap_messages|imap_unseen|include|ioscheduler|kernel|laptop_mode|lines|loadavg|loadgraph|lua|lua_bar|lua_gauge|lua_graph|lua_parse|machine|mails|mboxscan|mem|memwithbuffers|membar|memwithbuffersbar|memeasyfree|memfree|memgauge|memgraph|memmax|memperc|mixer|mixerbar|mixerl|mixerlbar|mixerr|mixerrbar|moc_album|moc_artist|moc_bitrate|moc_curtime|moc_file|moc_rate|moc_song|moc_state|moc_timeleft|moc_title|moc_totaltime|monitor|monitor_number|mpd_album|mpd_artist|mpd_bar|mpd_bitrate|mpd_elapsed|mpd_file|mpd_length|mpd_name|mpd_percent|mpd_random|mpd_repeat|mpd_smart|mpd_status|mpd_title|mpd_track|mpd_vol|mysql|nameserver|new_mails|nodename|nodename_short|no_update|nvidia|obsd_product|obsd_sensors_fan|obsd_sensors_temp|obsd_sensors_volt|obsd_vendor|offset|outlinecolor|pb_battery|pid_chroot|pid_cmdline|pid_cwd|pid_environ|pid_environ_list|pid_exe|pid_nice|pid_openfiles|pid_parent|pid_priority|pid_state|pid_state_short|pid_stderr|pid_stdin|pid_stdout|pid_threads|pid_thread_list|pid_time_kernelmode|pid_time_usermode|pid_time|pid_uid|pid_euid|pid_suid|pid_fsuid|pid_gid|pid_egid|pid_sgid|pid_fsgid|pid_read|pid_vmpeak|pid_vmsize|pid_vmlck|pid_vmhwm|pid_vmrss|pid_vmdata|pid_vmstk|pid_vmexe|pid_vmlib|pid_vmpte|pid_write|platform|pop3_unseen|pop3_used|pre_exec|processes|read_tcp|read_udp|replied_mails|rss|running_processes|running_threads|scroll|seen_mails|shadecolor|smapi|smapi_bat_bar|smapi_bat_perc|smapi_bat_power|smapi_bat_temp|sony_fanspeed|stippled_hr|stock|swap|swapbar|swapfree|swapmax|swapperc|sysname|tab|tail|tcp_portmon|template0|template1|template2|template3|template4|template5|template6|template7|template8|template9|texeci|texecpi|threads|time|to_bytes|top|top_io|top_mem|top_time|totaldown|totalup|trashed_mails|tztime|gid_name|uid_name|unflagged_mails|unforwarded_mails|unreplied_mails|unseen_mails|updates|upspeed|upspeedf|upspeedgraph|uptime|uptime_short|user_names|user_number|user_terms|user_times|user_time|utime|voffset|voltage_mv|voltage_v|weather|wireless_ap|wireless_bitrate|wireless_essid|wireless_link_bar|wireless_link_qual|wireless_link_qual_max|wireless_link_qual_perc|wireless_mode|words|xmms2_album|xmms2_artist|xmms2_bar|xmms2_bitrate|xmms2_comment|xmms2_date|xmms2_duration|xmms2_elapsed|xmms2_genre|xmms2_id|xmms2_percent|xmms2_playlist|xmms2_size|xmms2_smart|xmms2_status|xmms2_timesplayed|xmms2_title|xmms2_tracknr|xmms2_url)\>" +color brightblue "\<(acpiacadapter|acpifan|acpitemp|addr|addrs|alignc|alignr|apcupsd|apcupsd_cable|apcupsd_charge|apcupsd_lastxfer|apcupsd_linev|apcupsd_load|apcupsd_loadbar|apcupsd_loadgauge|apcupsd_loadgraph|apcupsd_model|apcupsd_name|apcupsd_status|apcupsd_temp|apcupsd_timeleft|apcupsd_upsmode|apm_adapter|apm_battery_life|apm_battery_time|audacious_bar|audacious_bitrate|audacious_channels|audacious_filename|audacious_frequency|audacious_length|audacious_length_seconds|audacious_main_volume|audacious_playlist_length|audacious_playlist_position|audacious_position|audacious_position_seconds|audacious_status|audacious_title|battery|battery_bar|battery_percent|battery_short|battery_time|blink|bmpx_album|bmpx_artist|bmpx_bitrate|bmpx_title|bmpx_track|bmpx_uri|buffers|cached|cmdline_to_pid|color|color0|color1|color2|color3|color4|color5|color6|color7|color8|color9|combine|conky_build_arch|conky_build_date|conky_version|cpu|cpubar|cpugauge|cpugraph|curl|desktop|desktop_name|desktop_number|disk_protect|diskio|diskio_read|diskio_write|diskiograph|diskiograph_read|diskiograph_write|distribution|downspeed|downspeedf|downspeedgraph|draft_mails|else|endif|entropy_avail|entropy_bar|entropy_perc|entropy_poolsize|eval|eve|exec|execbar|execgauge|execgraph|execi|execibar|execigauge|execigraph|execp|execpi|flagged_mails|font|format_time|forwarded_mails|freq|freq_g|fs_bar|fs_bar_free|fs_free|fs_free_perc|fs_size|fs_type|fs_used|fs_used_perc|goto|gw_iface|gw_ip|hddtemp|head|hr|hwmon|i2c|i8k_ac_status|i8k_bios|i8k_buttons_status|i8k_cpu_temp|i8k_left_fan_rpm|i8k_left_fan_status|i8k_right_fan_rpm|i8k_right_fan_status|i8k_serial|i8k_version|ibm_brightness|ibm_fan|ibm_temps|ibm_volume|ical|iconv_start|iconv_stop|if_empty|if_existing|if_gw|if_match|if_mixer_mute|if_mounted|if_mpd_playing|if_running|if_smapi_bat_installed|if_up|if_updatenr|if_xmms2_connected|image|imap_messages|imap_unseen|include|ioscheduler|irc|kernel|laptop_mode|lines|loadavg|loadgraph|lua|lua_bar|lua_gauge|lua_graph|lua_parse|machine|mails|mboxscan|mem|memwithbuffers|membar|memwithbuffersbar|memeasyfree|memfree|memgauge|memgraph|memmax|memperc|mixer|mixerbar|mixerl|mixerlbar|mixerr|mixerrbar|moc_album|moc_artist|moc_bitrate|moc_curtime|moc_file|moc_rate|moc_song|moc_state|moc_timeleft|moc_title|moc_totaltime|monitor|monitor_number|mpd_album|mpd_artist|mpd_bar|mpd_bitrate|mpd_elapsed|mpd_file|mpd_length|mpd_name|mpd_percent|mpd_random|mpd_repeat|mpd_smart|mpd_status|mpd_title|mpd_track|mpd_vol|mysql|nameserver|new_mails|nodename|nodename_short|no_update|nvidia|obsd_product|obsd_sensors_fan|obsd_sensors_temp|obsd_sensors_volt|obsd_vendor|offset|outlinecolor|pb_battery|pid_chroot|pid_cmdline|pid_cwd|pid_environ|pid_environ_list|pid_exe|pid_nice|pid_openfiles|pid_parent|pid_priority|pid_state|pid_state_short|pid_stderr|pid_stdin|pid_stdout|pid_threads|pid_thread_list|pid_time_kernelmode|pid_time_usermode|pid_time|pid_uid|pid_euid|pid_suid|pid_fsuid|pid_gid|pid_egid|pid_sgid|pid_fsgid|pid_read|pid_vmpeak|pid_vmsize|pid_vmlck|pid_vmhwm|pid_vmrss|pid_vmdata|pid_vmstk|pid_vmexe|pid_vmlib|pid_vmpte|pid_write|platform|pop3_unseen|pop3_used|pre_exec|processes|read_tcp|read_udp|replied_mails|rss|running_processes|running_threads|scroll|seen_mails|shadecolor|smapi|smapi_bat_bar|smapi_bat_perc|smapi_bat_power|smapi_bat_temp|sony_fanspeed|stippled_hr|stock|swap|swapbar|swapfree|swapmax|swapperc|sysname|tab|tail|tcp_ping|tcp_portmon|template0|template1|template2|template3|template4|template5|template6|template7|template8|template9|texeci|texecpi|threads|time|to_bytes|top|top_io|top_mem|top_time|totaldown|totalup|trashed_mails|tztime|gid_name|uid_name|unflagged_mails|unforwarded_mails|unreplied_mails|unseen_mails|updates|upspeed|upspeedf|upspeedgraph|uptime|uptime_short|user_names|user_number|user_terms|user_times|user_time|utime|voffset|voltage_mv|voltage_v|weather|wireless_ap|wireless_bitrate|wireless_essid|wireless_link_bar|wireless_link_qual|wireless_link_qual_max|wireless_link_qual_perc|wireless_mode|words|xmms2_album|xmms2_artist|xmms2_bar|xmms2_bitrate|xmms2_comment|xmms2_date|xmms2_duration|xmms2_elapsed|xmms2_genre|xmms2_id|xmms2_percent|xmms2_playlist|xmms2_size|xmms2_smart|xmms2_status|xmms2_timesplayed|xmms2_title|xmms2_tracknr|xmms2_url)\>" color brightblue "\$\{?[0-9A-Z_!@#$*?-]+\}?" color cyan "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)" diff --git a/extras/vim/syntax/conkyrc.vim b/extras/vim/syntax/conkyrc.vim index 27f7c3f0..a4b50e63 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_text_width max_user_text maximum_width minimum_size mpd_host mpd_password mpd_port music_player_interval mysql_host mysql_port mysql_user mysql_password mysql_db 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 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 http_refresh 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_text_width max_user_text maximum_width minimum_size mpd_host mpd_password mpd_port music_player_interval mysql_host mysql_port mysql_user mysql_password mysql_db net_avg_samples no_buffers out_to_console out_to_http 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 @@ -50,7 +50,7 @@ syn region ConkyrcVar start=/\$\w\@=/ end=/\W\@=\|$/ contained contains=ConkyrcV syn match ConkyrcVarStuff /{\@<=/ms=s contained nextgroup=ConkyrcVarName -syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite acpiacadapter acpifan acpitemp addr addrs alignc alignr apcupsd apcupsd_cable apcupsd_charge apcupsd_lastxfer apcupsd_linev apcupsd_load apcupsd_loadbar apcupsd_loadgauge apcupsd_loadgraph apcupsd_model apcupsd_name apcupsd_status apcupsd_temp apcupsd_timeleft apcupsd_upsmode apm_adapter apm_battery_life apm_battery_time audacious_bar audacious_bitrate audacious_channels audacious_filename audacious_frequency audacious_length audacious_length_seconds audacious_main_volume audacious_playlist_length audacious_playlist_position audacious_position audacious_position_seconds audacious_status audacious_title battery battery_bar battery_percent battery_short battery_time blink bmpx_album bmpx_artist bmpx_bitrate bmpx_title bmpx_track bmpx_uri buffers cached cmdline_to_pid color color0 color1 color2 color3 color4 color5 color6 color7 color8 color9 combine conky_build_arch conky_build_date conky_version cpu cpubar cpugauge cpugraph curl desktop desktop_name desktop_number disk_protect diskio diskio_read diskio_write diskiograph diskiograph_read diskiograph_write distribution downspeed downspeedf downspeedgraph draft_mails else endif entropy_avail entropy_bar entropy_perc entropy_poolsize eval eve exec execbar execgauge execgraph execi execibar execigauge execigraph execp execpi flagged_mails font format_time forwarded_mails freq freq_g fs_bar fs_bar_free fs_free fs_free_perc fs_size fs_type fs_used fs_used_perc goto gw_iface gw_ip hddtemp head hr hwmon i2c i8k_ac_status i8k_bios i8k_buttons_status i8k_cpu_temp i8k_left_fan_rpm i8k_left_fan_status i8k_right_fan_rpm i8k_right_fan_status i8k_serial i8k_version ibm_brightness ibm_fan ibm_temps ibm_volume iconv_start iconv_stop if_empty if_existing if_gw if_match if_mixer_mute if_mounted if_mpd_playing if_running if_smapi_bat_installed if_up if_updatenr if_xmms2_connected image imap_messages imap_unseen include ioscheduler kernel laptop_mode lines loadavg loadgraph lua lua_bar lua_gauge lua_graph lua_parse machine mails mboxscan mem memwithbuffers membar memwithbuffersbar memeasyfree memfree memgauge memgraph memmax memperc mixer mixerbar mixerl mixerlbar mixerr mixerrbar moc_album moc_artist moc_bitrate moc_curtime moc_file moc_rate moc_song moc_state moc_timeleft moc_title moc_totaltime monitor monitor_number mpd_album mpd_artist mpd_bar mpd_bitrate mpd_elapsed mpd_file mpd_length mpd_name mpd_percent mpd_random mpd_repeat mpd_smart mpd_status mpd_title mpd_track mpd_vol mysql nameserver new_mails nodename nodename_short no_update nvidia obsd_product obsd_sensors_fan obsd_sensors_temp obsd_sensors_volt obsd_vendor offset outlinecolor pb_battery pid_chroot pid_cmdline pid_cwd pid_environ pid_environ_list pid_exe pid_nice pid_openfiles pid_parent pid_priority pid_state pid_state_short pid_stderr pid_stdin pid_stdout pid_threads pid_thread_list pid_time_kernelmode pid_time_usermode pid_time pid_uid pid_euid pid_suid pid_fsuid pid_gid pid_egid pid_sgid pid_fsgid pid_read pid_vmpeak pid_vmsize pid_vmlck pid_vmhwm pid_vmrss pid_vmdata pid_vmstk pid_vmexe pid_vmlib pid_vmpte pid_write platform pop3_unseen pop3_used pre_exec processes read_tcp read_udp replied_mails rss running_processes running_threads scroll seen_mails shadecolor smapi smapi_bat_bar smapi_bat_perc smapi_bat_power smapi_bat_temp sony_fanspeed stippled_hr stock swap swapbar swapfree swapmax swapperc sysname tab tail tcp_portmon template0 template1 template2 template3 template4 template5 template6 template7 template8 template9 texeci texecpi threads time to_bytes top top_io top_mem top_time totaldown totalup trashed_mails tztime gid_name uid_name unflagged_mails unforwarded_mails unreplied_mails unseen_mails updates upspeed upspeedf upspeedgraph uptime uptime_short user_names user_number user_terms user_times user_time utime voffset voltage_mv voltage_v weather wireless_ap wireless_bitrate wireless_essid wireless_link_bar wireless_link_qual wireless_link_qual_max wireless_link_qual_perc wireless_mode words xmms2_album xmms2_artist xmms2_bar xmms2_bitrate xmms2_comment xmms2_date xmms2_duration xmms2_elapsed xmms2_genre xmms2_id xmms2_percent xmms2_playlist xmms2_size xmms2_smart xmms2_status xmms2_timesplayed xmms2_title xmms2_tracknr xmms2_url +syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite acpiacadapter acpifan acpitemp addr addrs alignc alignr apcupsd apcupsd_cable apcupsd_charge apcupsd_lastxfer apcupsd_linev apcupsd_load apcupsd_loadbar apcupsd_loadgauge apcupsd_loadgraph apcupsd_model apcupsd_name apcupsd_status apcupsd_temp apcupsd_timeleft apcupsd_upsmode apm_adapter apm_battery_life apm_battery_time audacious_bar audacious_bitrate audacious_channels audacious_filename audacious_frequency audacious_length audacious_length_seconds audacious_main_volume audacious_playlist_length audacious_playlist_position audacious_position audacious_position_seconds audacious_status audacious_title battery battery_bar battery_percent battery_short battery_time blink bmpx_album bmpx_artist bmpx_bitrate bmpx_title bmpx_track bmpx_uri buffers cached cmdline_to_pid color color0 color1 color2 color3 color4 color5 color6 color7 color8 color9 combine conky_build_arch conky_build_date conky_version cpu cpubar cpugauge cpugraph curl desktop desktop_name desktop_number disk_protect diskio diskio_read diskio_write diskiograph diskiograph_read diskiograph_write distribution downspeed downspeedf downspeedgraph draft_mails else endif entropy_avail entropy_bar entropy_perc entropy_poolsize eval eve exec execbar execgauge execgraph execi execibar execigauge execigraph execp execpi flagged_mails font format_time forwarded_mails freq freq_g fs_bar fs_bar_free fs_free fs_free_perc fs_size fs_type fs_used fs_used_perc goto gw_iface gw_ip hddtemp head hr hwmon i2c i8k_ac_status i8k_bios i8k_buttons_status i8k_cpu_temp i8k_left_fan_rpm i8k_left_fan_status i8k_right_fan_rpm i8k_right_fan_status i8k_serial i8k_version ibm_brightness ibm_fan ibm_temps ibm_volume ical iconv_start iconv_stop if_empty if_existing if_gw if_match if_mixer_mute if_mounted if_mpd_playing if_running if_smapi_bat_installed if_up if_updatenr if_xmms2_connected image imap_messages imap_unseen include ioscheduler irc kernel laptop_mode lines loadavg loadgraph lua lua_bar lua_gauge lua_graph lua_parse machine mails mboxscan mem memwithbuffers membar memwithbuffersbar memeasyfree memfree memgauge memgraph memmax memperc mixer mixerbar mixerl mixerlbar mixerr mixerrbar moc_album moc_artist moc_bitrate moc_curtime moc_file moc_rate moc_song moc_state moc_timeleft moc_title moc_totaltime monitor monitor_number mpd_album mpd_artist mpd_bar mpd_bitrate mpd_elapsed mpd_file mpd_length mpd_name mpd_percent mpd_random mpd_repeat mpd_smart mpd_status mpd_title mpd_track mpd_vol mysql nameserver new_mails nodename nodename_short no_update nvidia obsd_product obsd_sensors_fan obsd_sensors_temp obsd_sensors_volt obsd_vendor offset outlinecolor pb_battery pid_chroot pid_cmdline pid_cwd pid_environ pid_environ_list pid_exe pid_nice pid_openfiles pid_parent pid_priority pid_state pid_state_short pid_stderr pid_stdin pid_stdout pid_threads pid_thread_list pid_time_kernelmode pid_time_usermode pid_time pid_uid pid_euid pid_suid pid_fsuid pid_gid pid_egid pid_sgid pid_fsgid pid_read pid_vmpeak pid_vmsize pid_vmlck pid_vmhwm pid_vmrss pid_vmdata pid_vmstk pid_vmexe pid_vmlib pid_vmpte pid_write platform pop3_unseen pop3_used pre_exec processes read_tcp read_udp replied_mails rss running_processes running_threads scroll seen_mails shadecolor smapi smapi_bat_bar smapi_bat_perc smapi_bat_power smapi_bat_temp sony_fanspeed stippled_hr stock swap swapbar swapfree swapmax swapperc sysname tab tail tcp_ping tcp_portmon template0 template1 template2 template3 template4 template5 template6 template7 template8 template9 texeci texecpi threads time to_bytes top top_io top_mem top_time totaldown totalup trashed_mails tztime gid_name uid_name unflagged_mails unforwarded_mails unreplied_mails unseen_mails updates upspeed upspeedf upspeedgraph uptime uptime_short user_names user_number user_terms user_times user_time utime voffset voltage_mv voltage_v weather wireless_ap wireless_bitrate wireless_essid wireless_link_bar wireless_link_qual wireless_link_qual_max wireless_link_qual_perc wireless_mode words xmms2_album xmms2_artist xmms2_bar xmms2_bitrate xmms2_comment xmms2_date xmms2_duration xmms2_elapsed xmms2_genre xmms2_id xmms2_percent xmms2_playlist xmms2_size xmms2_smart xmms2_status xmms2_timesplayed xmms2_title xmms2_tracknr xmms2_url hi def link ConkyrcComment Comment hi def link ConkyrcSetting Keyword diff --git a/lua/CMakeLists.txt b/lua/CMakeLists.txt index bde5a679..3ff7e958 100644 --- a/lua/CMakeLists.txt +++ b/lua/CMakeLists.txt @@ -30,7 +30,9 @@ set(CMAKE_CXX_FLAGS_DEBUG "-ggdb") if(BUILD_LUA_CAIRO) include_directories(${luacairo_includes} ${CMAKE_CURRENT_SOURCE_DIR}) - wrap_tolua(luacairo_src cairo.pkg) + # cairo_set_dash() needs this special hack to work properly + # if you have a better solution, please let me know + wrap_tolua(luacairo_src cairo.pkg libcairo.patch) add_library(cairo SHARED ${luacairo_src}) diff --git a/lua/cairo.pkg b/lua/cairo.pkg index 65019bc2..6acf113a 100644 --- a/lua/cairo.pkg +++ b/lua/cairo.pkg @@ -240,7 +240,7 @@ typedef enum _cairo_line_join { void cairo_set_line_join(cairo_t * cr, cairo_line_join_t line_join); -void cairo_set_dash(cairo_t * cr, const double *dashes, int num_dashes, double offset); +void cairo_set_dash(cairo_t * cr, const double dashes[num_dashes], int num_dashes, double offset); void cairo_set_miter_limit(cairo_t * cr, double limit); diff --git a/lua/libcairo.patch b/lua/libcairo.patch new file mode 100644 index 00000000..037eb17a --- /dev/null +++ b/lua/libcairo.patch @@ -0,0 +1,16 @@ +--- lua/libcairo.c~ 2010-06-11 23:14:43.000000000 +0200 ++++ lua/libcairo.c 2010-06-12 10:47:51.000000000 +0200 +@@ -1452,12 +1452,12 @@ + #endif + { + struct _cairo* cr = (( struct _cairo*) tolua_tousertype(tolua_S,1,0)); ++ int num_dashes = ((int) tolua_tonumber(tolua_S,3,0)); + #ifdef __cplusplus + double* dashes = Mtolua_new_dim(double, num_dashes); + #else + double* dashes = (double*) malloc((num_dashes)*sizeof(double)); + #endif +- int num_dashes = ((int) tolua_tonumber(tolua_S,3,0)); + double offset = ((double) tolua_tonumber(tolua_S,4,0)); + { + #ifndef TOLUA_RELEASE diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 364614c2..7b94ee91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -165,6 +165,16 @@ if(BUILD_APCUPSD) set(optional_sources ${optional_sources} ${apcupsd}) endif(BUILD_APCUPSD) +if(BUILD_ICAL) + set(ical ical.cc) + set(optional_sources ${optional_sources} ${ical}) +endif(BUILD_ICAL) + +if(BUILD_IRC) + set(irc irc.cc) + set(optional_sources ${optional_sources} ${irc}) +endif(BUILD_IRC) + if(BUILD_ICONV) set(iconv iconv_tools.cc) set(optional_sources ${optional_sources} ${iconv}) diff --git a/src/apcupsd.cc b/src/apcupsd.cc index 2e3564d1..8f7fad6b 100644 --- a/src/apcupsd.cc +++ b/src/apcupsd.cc @@ -180,7 +180,7 @@ static int fill_items(int sock, PAPCUPSD_S apc) // // Conky update function for apcupsd data // -void update_apcupsd(void) +int update_apcupsd(void) { int i; APCUPSD_S apc; @@ -251,7 +251,7 @@ void update_apcupsd(void) // "atomically" copy the data into working set // memcpy(apcupsd.items, apc.items, sizeof(apcupsd.items)); - return; + return 0; } int apcupsd_scan_arg(const char *arg) diff --git a/src/apcupsd.h b/src/apcupsd.h index 25562698..67862b44 100644 --- a/src/apcupsd.h +++ b/src/apcupsd.h @@ -28,7 +28,7 @@ int apcupsd_scan_arg(const char *); /* Service routine for the conky main thread */ -void update_apcupsd(void); +int update_apcupsd(void); double apcupsd_loadbarval(struct text_object *); diff --git a/src/audacious.cc b/src/audacious.cc index 283d68ed..9dfb3154 100644 --- a/src/audacious.cc +++ b/src/audacious.cc @@ -63,7 +63,7 @@ static audacious_t audacious_items; /* ----------------------------------------- * Conky update function for audacious data. * ----------------------------------------- */ -void update_audacious(void) +int update_audacious(void) { /* The worker thread is updating audacious_items array asynchronously * to the main conky thread. @@ -77,6 +77,7 @@ void update_audacious(void) std::lock_guard lock(info.audacious.p_timed_thread->mutex()); memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items)); + return 0; } /* --------------------------------------------------------- @@ -88,9 +89,8 @@ int create_audacious_thread(void) { if (!info.audacious.p_timed_thread) { info.audacious.p_timed_thread = - timed_thread::create(std::bind(audacious_thread_func, - std::placeholders::_1), info.music_player_interval * - 1000000); + timed_thread::create(std::bind(audacious_thread_func, std::placeholders::_1), + std::chrono::microseconds(long(info.music_player_interval * 1000000))); } if (!info.audacious.p_timed_thread) { diff --git a/src/audacious.h b/src/audacious.h index 16382589..c7667716 100644 --- a/src/audacious.h +++ b/src/audacious.h @@ -60,7 +60,7 @@ int create_audacious_thread(void); int destroy_audacious_thread(void); /* Service routine for the conky main thread */ -void update_audacious(void); +int update_audacious(void); /* Thread functions */ void audacious_thread_func(thread_handle &handle); diff --git a/src/ccurl_thread.cc b/src/ccurl_thread.cc index 8ed04e99..3817e04f 100644 --- a/src/ccurl_thread.cc +++ b/src/ccurl_thread.cc @@ -94,7 +94,7 @@ size_t ccurl_write_memory_callback(void *ptr, size_t size, size_t nmemb, void *d /* fetch our datums */ -void ccurl_fetch_data(thread_handle &handle, ccurl_location_ptr &curloc) +void ccurl_fetch_data(thread_handle &handle, const ccurl_location_ptr &curloc) { CURL *curl = NULL; CURLcode res; @@ -136,22 +136,22 @@ void ccurl_fetch_data(thread_handle &handle, ccurl_location_ptr &curloc) } } -void ccurl_thread(thread_handle &handle, ccurl_location_ptr curloc); +void ccurl_thread(thread_handle &handle, const ccurl_location_ptr &curloc); -void ccurl_init_thread(ccurl_location_ptr curloc, int interval) +void ccurl_init_thread(const ccurl_location_ptr &curloc, int interval) { #ifdef DEBUG assert(curloc->result); #endif /* DEBUG */ curloc->p_timed_thread = timed_thread::create(std::bind(ccurl_thread, - std::placeholders::_1, curloc), interval * 1000000); + std::placeholders::_1, curloc), std::chrono::seconds(interval)); if (!curloc->p_timed_thread) { NORM_ERR("curl thread: error creating timed thread"); } } -void ccurl_thread(thread_handle &handle, ccurl_location_ptr curloc) +void ccurl_thread(thread_handle &handle, const ccurl_location_ptr &curloc) { while (1) { @@ -185,7 +185,7 @@ void ccurl_free_info(void) /* straight copy, used by $curl */ static void ccurl_parse_data(char *result, const char *data) { - strncpy(result, data, max_user_text); + if(result) strncpy(result, data, max_user_text); } /* prints result data to text buffer, used by $curl */ diff --git a/src/ccurl_thread.h b/src/ccurl_thread.h index f8c96be5..3d468917 100644 --- a/src/ccurl_thread.h +++ b/src/ccurl_thread.h @@ -56,7 +56,7 @@ ccurl_location_ptr ccurl_find_location(ccurl_location_list &locations, char *uri void ccurl_free_locations(ccurl_location_list &locations); /* initiates a curl thread at the location specified using the interval in * seconds */ -void ccurl_init_thread(ccurl_location_ptr curloc, int interval); +void ccurl_init_thread(const ccurl_location_ptr &curloc, int interval); /* curl thread lib exports end */ diff --git a/src/common.cc b/src/common.cc index 0b584e18..40ff101f 100644 --- a/src/common.cc +++ b/src/common.cc @@ -87,9 +87,10 @@ char *strndup(const char *s, size_t n) } #endif /* HAVE_STRNDUP */ -void update_uname(void) +int update_uname(void) { uname(&info.uname_s); + return 0; } double get_time(void) @@ -261,7 +262,7 @@ void format_seconds_short(char *buf, unsigned int n, long seconds) * Populated while initialising text objects in construct_text_object(). */ struct update_cb { struct update_cb *next; - void (*func)(void); + int (*func)(void); pthread_t thread; sem_t start_wait, end_wait; update_cb() : next(NULL), func(NULL) {} @@ -279,7 +280,7 @@ static int threading_started = 0; /* Register an update callback. Don't allow duplicates, to minimise side * effects and overhead. */ -void add_update_callback(void (*func)(void)) +void add_update_callback(int (*func)(void)) { struct update_cb *uc = &update_cb_head; @@ -369,7 +370,12 @@ static void *run_update_callback(void *data) while (1) { if (sem_wait(&ucb->start_wait)) return(NULL); if (ucb->running == 0) return(NULL); - (*ucb->func)(); + if((*ucb->func)()) { + ucb->next = ucb; //this is normally not be possible, so we use it to show that there was a critical error + sem_post(&ucb->end_wait); + sem_post(&ucb->end_wait); + pthread_exit(NULL); + } if (sem_post(&ucb->end_wait)) return(NULL); } } @@ -404,8 +410,14 @@ void update_stuff(void) } /* need to synchronise here, otherwise locking is needed (as data * would be printed with some update callbacks still running) */ - for (uc = update_cb_head.next; uc; uc = uc->next) + for (uc = update_cb_head.next; uc; uc = uc->next) { sem_wait(&uc->end_wait); + if(uc == uc->next) { + pthread_join(uc->thread, NULL); + delete uc; + exit(EXIT_FAILURE); + } + } /* XXX: move the following into the update_meminfo() functions? */ if (no_buffers.get(*state)) { @@ -826,7 +838,7 @@ void print_stock(struct text_object *obj, char *p, int p_max_size) p[0] = 0; return; } - ccurl_process_info(p, p_max_size, obj->data.s, 0); + ccurl_process_info(p, p_max_size, obj->data.s, 1); } void free_stock(struct text_object *obj) diff --git a/src/common.h b/src/common.h index 68cdca9f..be0bf17e 100644 --- a/src/common.h +++ b/src/common.h @@ -38,27 +38,26 @@ char* readfile(const char* filename, int* total_read, char showerror); void print_to_bytes(struct text_object *, char *, int); -void add_update_callback(void (*func)(void)); +void add_update_callback(int (*func)(void)); void free_update_callbacks(void); void start_update_threading(void); void strfold(char *start, int count); int check_mount(struct text_object *); void prepare_update(void); -void update_uptime(void); -void update_meminfo(void); -void update_net_stats(void); -void update_cpu_usage(void); -void update_total_processes(void); -void update_uname(void); -void update_threads(void); -void update_running_processes(void); +int update_uptime(void); +int update_meminfo(void); +int update_net_stats(void); +int update_cpu_usage(void); +int update_total_processes(void); +int update_uname(void); +int update_threads(void); +int update_running_processes(void); void update_stuff(void); char get_freq(char *, size_t, const char *, int, unsigned int); void print_voltage_mv(struct text_object *, char *, int); void print_voltage_v(struct text_object *, char *, int); -void update_load_average(void); -void update_top(void); +int update_load_average(void); void free_all_processes(void); struct process *get_first_process(void); void get_cpu_count(void); diff --git a/src/conky.cc b/src/conky.cc index 9704904d..d63f18d2 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -35,6 +35,7 @@ #include "timed-thread.h" #include #include +#include #include #include #include @@ -67,9 +68,9 @@ #include #include #include -#ifdef BUILD_WEATHER_XOAP +#if defined BUILD_WEATHER_XOAP || defined BUILD_RSS #include -#endif /* BUILD_WEATHER_XOAP */ +#endif /* local headers */ #include "core.h" @@ -109,6 +110,9 @@ #elif defined(__OpenBSD__) #include "openbsd.h" #endif +#ifdef BUILD_HTTP +#include +#endif #if defined(__FreeBSD_kernel__) #include @@ -238,6 +242,12 @@ static void print_version(void) #ifdef BUILD_PORT_MONITORS " * portmon\n" #endif /* BUILD_PORT_MONITORS */ +#ifdef BUILD_HTTP + " * HTTP\n" +#endif +#ifdef BUILD_IRC + " * IRC\n" +#endif #ifdef BUILD_CURL " * Curl\n" #endif /* BUILD_CURL */ @@ -346,6 +356,20 @@ static int cpu_avg_samples, net_avg_samples, diskio_avg_samples; char *overwrite_file = NULL; FILE *overwrite_fpointer = NULL; char *append_file = NULL; FILE *append_fpointer = NULL; +#ifdef BUILD_HTTP +std::string webpage; +struct MHD_Daemon *httpd; +bool http_refresh; + +int sendanswer(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) { + struct MHD_Response *response = MHD_create_response_from_data(webpage.length(), (void*) webpage.c_str(), MHD_NO, MHD_NO); + int ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); + if(cls || url || method || version || upload_data || upload_data_size || con_cls) {} //make compiler happy + return ret; +} +#endif + #ifdef BUILD_X11 static conky::simple_config_setting show_graph_scale("show_graph_scale", false, false); @@ -480,6 +504,7 @@ static inline void for_each_line(char *b, int f(char *, int)) char *ps, *pe; int special_index = 0; /* specials index */ + if(! b) return; for (ps = b, pe = b; *pe; pe++) { if (*pe == '\n') { *pe = '\0'; @@ -738,6 +763,9 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) { struct text_object *obj; size_t a; + + if(! p) return; + #ifdef BUILD_ICONV char *buff_in; @@ -1144,6 +1172,17 @@ static inline void set_foreground_color(long c) return; } +std::string string_replace_all(std::string original, std::string oldpart, std::string newpart, std::string::size_type start) { + std::string::size_type i = start; + int oldpartlen = oldpart.length(); + while(1) { + i = original.find(oldpart, i); + if(i == std::string::npos) break; + original.replace(i, oldpartlen, newpart); + } + return original; +} + static void draw_string(const char *s) { int i, i2, pos, width_of_s; @@ -1181,6 +1220,16 @@ static void draw_string(const char *s) if (out_to_ncurses.get(*state) && draw_mode == FG) { printw("%s", s_with_newlines); } +#endif +#ifdef BUILD_HTTP + if ((output_methods & TO_HTTP) && draw_mode == FG) { + std::string::size_type origlen = webpage.length(); + webpage.append(s_with_newlines); + webpage = string_replace_all(webpage, "\n", "
", origlen); + webpage = string_replace_all(webpage, " ", "  ", origlen); + webpage = string_replace_all(webpage, "  ", "  ", origlen); + webpage.append("
"); + } #endif free(s_with_newlines); memset(tmpstring1, 0, text_buffer_size); @@ -1739,6 +1788,22 @@ static int draw_line(char *s, int special_index) static void draw_text(void) { +#ifdef BUILD_HTTP +#define WEBPAGE_START1 "\n" +#define WEBPAGE_START2 "Conky

" +#define WEBPAGE_END "

" + if (output_methods & TO_HTTP) { + webpage = WEBPAGE_START1; + if(http_refresh) { + webpage.append(""); + } + webpage.append(WEBPAGE_START2); + } +#endif #ifdef BUILD_X11 #ifdef BUILD_LUA llua_draw_pre_hook(); @@ -1777,6 +1842,11 @@ static void draw_text(void) #if defined(BUILD_LUA) && defined(BUILD_X11) llua_draw_post_hook(); #endif /* BUILD_LUA */ +#ifdef BUILD_HTTP + if (output_methods & TO_HTTP) { + webpage.append(WEBPAGE_END); + } +#endif } static void draw_stuff(void) @@ -2409,10 +2479,13 @@ void free_specials(special_t *current) { } } -void clean_up(void *memtofree1, void* memtofree2) +void clean_up_without_threads(void *memtofree1, void* memtofree2) { - free_update_callbacks(); - +#ifdef BUILD_HTTP + if(output_methods & TO_HTTP) { + MHD_stop_daemon(httpd); + } +#endif conftree_empty(currentconffile); currentconffile = NULL; free_and_zero(memtofree1); @@ -2449,10 +2522,10 @@ void clean_up(void *memtofree1, void* memtofree2) #ifdef BUILD_CURL ccurl_free_info(); #endif -#ifdef RSS +#ifdef BUILD_RSS rss_free_info(); #endif -#ifdef BUILD_WEATHER +#if defined BUILD_WEATHER_METAR || defined BUILD_WEATHER_XOAP weather_free_info(); #endif #ifdef BUILD_LUA @@ -2463,9 +2536,9 @@ void clean_up(void *memtofree1, void* memtofree2) if (out_to_x.get(*state)) cimlib_deinit(); #endif /* BUILD_IMLIB2 */ -#ifdef BUILD_WEATHER_XOAP +#if defined BUILD_WEATHER_XOAP || defined BUILD_RSS xmlCleanupParser(); -#endif /* BUILD_WEATHER_XOAP */ +#endif free_specials(specials); @@ -2477,6 +2550,12 @@ void clean_up(void *memtofree1, void* memtofree2) state.reset(); } +void clean_up(void *memtofree1, void* memtofree2) +{ + free_update_callbacks(); + clean_up_without_threads(memtofree1, memtofree2); +} + static void set_default_configurations(void) { #ifdef BUILD_MPD @@ -2492,6 +2571,9 @@ static void set_default_configurations(void) top_cpu = 0; top_mem = 0; top_time = 0; +#ifdef BUILD_HTTP + http_refresh = false; +#endif #ifdef BUILD_IOSTATS top_io = 0; #endif @@ -2922,6 +3004,19 @@ char load_config_file(const char *f) CONF("max_text_width") { max_text_width = atoi(value); } +#ifdef BUILD_HTTP + CONF("out_to_http") { + if(string_to_bool(value)) { + output_methods |= TO_HTTP; + httpd = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, HTTPPORT, NULL, NULL, &sendanswer, NULL, MHD_OPTION_END); + } + } + CONF("http_refresh") { + if(string_to_bool(value)) { + http_refresh = true; + } + } +#endif CONF("overwrite_file") { free_and_zero(overwrite_file); if (overwrite_works(value)) { @@ -3006,12 +3101,10 @@ char load_config_file(const char *f) } } #endif /* BUILD_X11 */ -#ifdef __linux__ CONF("top_name_width") { if (set_top_name_width(value)) CONF_ERR; } -#endif /* __linux__ */ #ifdef HDDTEMP CONF("hddtemp_host") { set_hddtemp_host(value); diff --git a/src/conky.h b/src/conky.h index 08cd2adb..3fe685c3 100644 --- a/src/conky.h +++ b/src/conky.h @@ -324,6 +324,9 @@ extern std::string current_config; #define TO_STDERR 4 #define OVERWRITE_FILE 8 #define APPEND_FILE 16 +#ifdef BUILD_HTTP +#define TO_HTTP 64 +#endif enum x_initialiser_state { NO = 0, YES = 1, diff --git a/src/core.cc b/src/core.cc index e2281ab4..94558520 100644 --- a/src/core.cc +++ b/src/core.cc @@ -45,6 +45,12 @@ #ifdef BUILD_MYSQL #include "mysql.h" #endif +#ifdef BUILD_ICAL +#include "ical.h" +#endif +#ifdef BUILD_IRC +#include "irc.h" +#endif #ifdef BUILD_X11 #include "fonts.h" #endif @@ -139,10 +145,10 @@ static struct text_object *create_plain_text(const char *s) void stock_parse_arg(struct text_object *obj, const char *arg) { char stock[8]; - char data[8]; + char data[16]; obj->data.s = NULL; - if(sscanf(arg, "%7s %7s", stock, data) != 2) { + if(sscanf(arg, "%7s %15s", stock, data) != 2) { NORM_ERR("wrong number of arguments for $stock"); return; } @@ -150,8 +156,86 @@ void stock_parse_arg(struct text_object *obj, const char *arg) else if(!strcasecmp("adv", data)) strcpy(data, "a2"); else if(!strcasecmp("asksize", data)) strcpy(data, "a5"); else if(!strcasecmp("bid", data)) strcpy(data, "b"); + else if(!strcasecmp("askrt", data)) strcpy(data, "b2"); + else if(!strcasecmp("bidrt", data)) strcpy(data, "b3"); + else if(!strcasecmp("bookvalue", data)) strcpy(data, "b4"); + else if(!strcasecmp("bidsize", data)) strcpy(data, "b6"); + else if(!strcasecmp("change", data)) strcpy(data, "c1"); + else if(!strcasecmp("commission", data)) strcpy(data, "c3"); + else if(!strcasecmp("changert", data)) strcpy(data, "c6"); + else if(!strcasecmp("ahcrt", data)) strcpy(data, "c8"); + else if(!strcasecmp("ds", data)) strcpy(data, "d"); + else if(!strcasecmp("ltd", data)) strcpy(data, "d1"); + else if(!strcasecmp("tradedate", data)) strcpy(data, "d2"); + else if(!strcasecmp("es", data)) strcpy(data, "e"); + else if(!strcasecmp("ei", data)) strcpy(data, "e1"); + else if(!strcasecmp("epsecy", data)) strcpy(data, "e7"); + else if(!strcasecmp("epseny", data)) strcpy(data, "e8"); + else if(!strcasecmp("epsenq", data)) strcpy(data, "e9"); + else if(!strcasecmp("floatshares", data)) strcpy(data, "f6"); + else if(!strcasecmp("dayslow", data)) strcpy(data, "g"); + else if(!strcasecmp("dayshigh", data)) strcpy(data, "h"); + else if(!strcasecmp("52weeklow", data)) strcpy(data, "j"); + else if(!strcasecmp("52weekhigh", data)) strcpy(data, "k"); + else if(!strcasecmp("hgp", data)) strcpy(data, "g1"); + else if(!strcasecmp("ag", data)) strcpy(data, "g3"); + else if(!strcasecmp("hg", data)) strcpy(data, "g4"); + else if(!strcasecmp("hgprt", data)) strcpy(data, "g5"); + else if(!strcasecmp("hgrt", data)) strcpy(data, "g6"); + else if(!strcasecmp("moreinfo", data)) strcpy(data, "i"); + else if(!strcasecmp("obrt", data)) strcpy(data, "i5"); + else if(!strcasecmp("mc", data)) strcpy(data, "j1"); + else if(!strcasecmp("mcrt", data)) strcpy(data, "j3"); + else if(!strcasecmp("ebitda", data)) strcpy(data, "j4"); + else if(!strcasecmp("c52wlow", data)) strcpy(data, "j5"); + else if(!strcasecmp("pc52wlow", data)) strcpy(data, "j6"); + else if(!strcasecmp("cprt", data)) strcpy(data, "k2"); + else if(!strcasecmp("lts", data)) strcpy(data, "k3"); + else if(!strcasecmp("c52whigh", data)) strcpy(data, "k4"); + else if(!strcasecmp("pc52whigh", data)) strcpy(data, "k5"); + else if(!strcasecmp("ltp", data)) strcpy(data, "l1"); + else if(!strcasecmp("hl", data)) strcpy(data, "l2"); + else if(!strcasecmp("ll", data)) strcpy(data, "l3"); + else if(!strcasecmp("dr", data)) strcpy(data, "m"); + else if(!strcasecmp("drrt", data)) strcpy(data, "m2"); + else if(!strcasecmp("50ma", data)) strcpy(data, "m3"); + else if(!strcasecmp("200ma", data)) strcpy(data, "m4"); + else if(!strcasecmp("c200ma", data)) strcpy(data, "m5"); + else if(!strcasecmp("pc200ma", data)) strcpy(data, "m6"); + else if(!strcasecmp("c50ma", data)) strcpy(data, "m7"); + else if(!strcasecmp("pc50ma", data)) strcpy(data, "m8"); + else if(!strcasecmp("name", data)) strcpy(data, "n"); + else if(!strcasecmp("notes", data)) strcpy(data, "n4"); + else if(!strcasecmp("open", data)) strcpy(data, "o"); + else if(!strcasecmp("pc", data)) strcpy(data, "p"); + else if(!strcasecmp("pricepaid", data)) strcpy(data, "p1"); + else if(!strcasecmp("cip", data)) strcpy(data, "p2"); + else if(!strcasecmp("ps", data)) strcpy(data, "p5"); + else if(!strcasecmp("pb", data)) strcpy(data, "p6"); + else if(!strcasecmp("edv", data)) strcpy(data, "q"); + else if(!strcasecmp("per", data)) strcpy(data, "r"); + else if(!strcasecmp("dpd", data)) strcpy(data, "r1"); + else if(!strcasecmp("perrt", data)) strcpy(data, "r2"); + else if(!strcasecmp("pegr", data)) strcpy(data, "r5"); + else if(!strcasecmp("pepsecy", data)) strcpy(data, "r6"); + else if(!strcasecmp("pepseny", data)) strcpy(data, "r7"); + else if(!strcasecmp("symbol", data)) strcpy(data, "s"); + else if(!strcasecmp("sharesowned", data)) strcpy(data, "s1"); + else if(!strcasecmp("shortratio", data)) strcpy(data, "s7"); + else if(!strcasecmp("ltt", data)) strcpy(data, "t1"); + else if(!strcasecmp("tradelinks", data)) strcpy(data, "t6"); + else if(!strcasecmp("tt", data)) strcpy(data, "t7"); + else if(!strcasecmp("1ytp", data)) strcpy(data, "t8"); + else if(!strcasecmp("volume", data)) strcpy(data, "v"); + else if(!strcasecmp("hv", data)) strcpy(data, "v1"); + else if(!strcasecmp("hvrt", data)) strcpy(data, "v7"); + else if(!strcasecmp("52weekrange", data)) strcpy(data, "w"); + else if(!strcasecmp("dvc", data)) strcpy(data, "w1"); + else if(!strcasecmp("dvcrt", data)) strcpy(data, "w4"); + else if(!strcasecmp("se", data)) strcpy(data, "x"); + else if(!strcasecmp("dy", data)) strcpy(data, "y"); else { - NORM_ERR("\"%s\" is not supported by $stock. Supported: adv,ask,asksize,bid", data); + NORM_ERR("\"%s\" is not supported by $stock. Supported: 1ytp, 200ma, 50ma, 52weeklow, 52weekhigh, 52weekrange, adv, ag, ahcrt, ask, askrt, asksize, bid, bidrt, bidsize, bookvalue, c200ma, c50ma, c52whigh, c52wlow, change, changert, cip, commission, cprt, dayshigh, dayslow, dpd, dr, drrt, ds, dvc, dvcrt, dy, ebitda, edv, ei, epsecy, epsenq, epseny, es, floatshares, hg, hgp, hgprt, hl, hv, hvrt, ll, ltd, ltp, lts, ltt, mc, mcrt, moreinfo, name, notes, obrt, open, pb, pc, pc200ma, pc50ma, pc52whigh, pc52wlow, pegr, pepsecy, pepseny, per, perrt, pricepaid, ps, se, sharesowned, shortratio, symbol, tradedate, tradelinks, tt, volume", data); return; } #define MAX_FINYAH_URL_LENGTH 64 @@ -241,6 +325,10 @@ struct text_object *construct_text_object(char *s, const char *arg, long parse_read_tcpip_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_read_udp; obj->callbacks.free = &free_read_tcpip; + END OBJ_ARG(tcp_ping, 0, "tcp_ping: Needs \"host (port)\" as argument(s)") + parse_tcp_ping_arg(obj, arg, free_at_crash); + obj->callbacks.print = &print_tcp_ping; + obj->callbacks.free = &free_tcp_ping; #if defined(__linux__) END OBJ(voltage_mv, 0) get_cpu_count(); @@ -269,6 +357,12 @@ struct text_object *construct_text_object(char *s, const char *arg, long END OBJ(wireless_essid, &update_net_stats) obj->data.opaque = get_net_stat(arg, obj, free_at_crash); obj->callbacks.print = &print_wireless_essid; + END OBJ(wireless_channel, &update_net_stats) + parse_net_stat_arg(obj, arg, free_at_crash); + obj->callbacks.print = &print_wireless_channel; + END OBJ(wireless_freq, &update_net_stats) + parse_net_stat_arg(obj, arg, free_at_crash); + obj->callbacks.print = &print_wireless_frequency; END OBJ(wireless_mode, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_wireless_mode; @@ -343,12 +437,13 @@ struct text_object *construct_text_object(char *s, const char *arg, long obj->callbacks.free = &gen_free_opaque; END OBJ(battery_bar, 0) char bat[64]; - if (arg) { + + arg = scan_bar(obj, arg, 100); + if (arg && strlen(arg)>0) { sscanf(arg, "%63s", bat); } else { strcpy(bat, "BAT0"); } - scan_bar(obj, bat, 100); obj->data.s = strndup(bat, text_buffer_size); obj->callbacks.barval = &get_battery_perct_bar; obj->callbacks.free = &gen_free_opaque; @@ -623,7 +718,6 @@ struct text_object *construct_text_object(char *s, const char *arg, long obj->callbacks.free = &free_exec; END OBJ(execp, 0) scan_exec_arg(obj, arg); - obj->verbatim_output = 1; obj->parse = true; obj->thread = false; obj->callbacks.print = &print_exec; @@ -664,7 +758,6 @@ struct text_object *construct_text_object(char *s, const char *arg, long obj->callbacks.free = &free_execi; END OBJ_ARG(execpi, 0, "execpi needs arguments") scan_execi_arg(obj, arg); - obj->verbatim_output = 1; obj->parse = true; obj->thread = false; obj->callbacks.print = &print_execi; @@ -1130,6 +1223,18 @@ struct text_object *construct_text_object(char *s, const char *arg, long scan_tztime(obj, arg); obj->callbacks.print = &print_tztime; obj->callbacks.free = &free_tztime; +#ifdef BUILD_ICAL + END OBJ_ARG(ical, 0, "ical requires arguments") + parse_ical_args(obj, arg, free_at_crash, s); + obj->callbacks.print = &print_ical; + obj->callbacks.free = &free_ical; +#endif +#ifdef BUILD_IRC + END OBJ_ARG(irc, 0, "irc requires arguments") + parse_irc_args(obj, arg); + obj->callbacks.print = &print_irc; + obj->callbacks.free = &free_irc; +#endif #ifdef BUILD_ICONV END OBJ_ARG(iconv_start, 0, "Iconv requires arguments") init_iconv_start(obj, free_at_crash, arg); @@ -1521,12 +1626,10 @@ struct text_object *construct_text_object(char *s, const char *arg, long #ifdef BUILD_LUA END OBJ_ARG(lua, 0, "lua needs arguments: [function parameters]") obj->data.s = strndup(arg, text_buffer_size); - obj->verbatim_output = 1; obj->callbacks.print = &print_lua; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(lua_parse, 0, "lua_parse needs arguments: [function parameters]") obj->data.s = strndup(arg, text_buffer_size); - obj->verbatim_output = 1; obj->callbacks.print = &print_lua_parse; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(lua_bar, 0, "lua_bar needs arguments: , [function parameters]") diff --git a/src/diskio.h b/src/diskio.h index f8bbd3ed..15009214 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -63,7 +63,7 @@ struct diskio_stat { extern struct diskio_stat stats; struct diskio_stat *prepare_diskio_stat(const char *); -void update_diskio(void); +int update_diskio(void); void clear_diskio_stats(void); void update_diskio_values(struct diskio_stat *, unsigned int, unsigned int); diff --git a/src/entropy.cc b/src/entropy.cc index 86fdadea..a8200c85 100644 --- a/src/entropy.cc +++ b/src/entropy.cc @@ -49,10 +49,11 @@ struct _entropy { static _entropy entropy; -void update_entropy(void) +int update_entropy(void) { get_entropy_avail(&entropy.avail); get_entropy_poolsize(&entropy.poolsize); + return 0; } void print_entropy_avail(struct text_object *obj, char *p, int p_max_size) diff --git a/src/entropy.h b/src/entropy.h index d508a042..765d2d18 100644 --- a/src/entropy.h +++ b/src/entropy.h @@ -31,7 +31,7 @@ #ifndef _ENTROPY_H #define _ENTROPY_H -void update_entropy(void); +int update_entropy(void); void print_entropy_avail(struct text_object *, char *, int); uint8_t entropy_percentage(struct text_object *); diff --git a/src/exec.cc b/src/exec.cc index 15038d73..076774df 100644 --- a/src/exec.cc +++ b/src/exec.cc @@ -323,7 +323,8 @@ void print_execi(struct text_object *obj, char *p, int p_max_size) * note that we don't register this thread with the * timed_thread list, because we destroy it manually */ - ed->p_timed_thread = timed_thread::create(std::bind(threaded_exec, std::placeholders::_1, obj), ed->interval * 1000000, false); + ed->p_timed_thread = timed_thread::create(std::bind(threaded_exec, std::placeholders::_1, obj), + std::chrono::microseconds(long(ed->interval * 1000000)), false); if (!ed->p_timed_thread) { NORM_ERR("Error creating texeci timed thread"); } diff --git a/src/freebsd.cc b/src/freebsd.cc index dfe18b71..e988a5e3 100644 --- a/src/freebsd.cc +++ b/src/freebsd.cc @@ -70,7 +70,7 @@ kvm_t *kd; __attribute__((gnu_inline)) inline void -proc_find_top(struct process **cpu, struct process **mem); +proc_find_top(struct process **cpu, struct process **mem, struct process **time); static short cpu_setup = 0; @@ -121,7 +121,7 @@ void prepare_update(void) { } -void update_uptime(void) +int update_uptime(void) { int mib[2] = { CTL_KERN, KERN_BOOTTIME }; struct timeval boottime; @@ -136,6 +136,8 @@ void update_uptime(void) fprintf(stderr, "Could not get uptime\n"); info.uptime = 0; } + + return 0; } int check_mount(struct text_object *obj) @@ -156,7 +158,7 @@ int check_mount(struct text_object *obj) return 0; } -void update_meminfo(void) +int update_meminfo(void) { u_int total_pages, inactive_pages, free_pages; unsigned long swap_avail, swap_free; @@ -189,9 +191,11 @@ void update_meminfo(void) info.swap = 0; info.swapfree = 0; } + + return 0; } -void update_net_stats(void) +int update_net_stats(void) { struct net_stat *ns; double delta; @@ -202,11 +206,11 @@ void update_net_stats(void) /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { - return; + return 0; } if (getifaddrs(&ifap) < 0) { - return; + return 0; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { @@ -262,18 +266,20 @@ void update_net_stats(void) } freeifaddrs(ifap); + return 0; } -void update_total_processes(void) +int update_total_processes(void) { int n_processes; kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes); info.procs = n_processes; + return 0; } -void update_running_processes(void) +int update_running_processes(void) { struct kinfo_proc *p; int n_processes; @@ -291,6 +297,7 @@ void update_running_processes(void) } info.run_procs = cnt; + return 0; } void get_cpu_count(void) @@ -316,7 +323,7 @@ struct cpu_info { long oldused; }; -void update_cpu_usage(void) +int update_cpu_usage(void) { int i, j = 0; long used, total; @@ -394,9 +401,10 @@ void update_cpu_usage(void) } free(cp_time); + return 0; } -void update_load_average(void) +int update_load_average(void) { double v[3]; @@ -405,6 +413,8 @@ void update_load_average(void) info.loadavg[0] = (double) v[0]; info.loadavg[1] = (double) v[1]; info.loadavg[2] = (double) v[2]; + + return 0; } double get_acpi_temperature(int fd) @@ -585,11 +595,6 @@ char get_freq(char *p_client_buffer, size_t client_buffer_size, const char *p_fo return 1; } -void update_top(void) -{ - proc_find_top(info.cpu, info.memu); -} - #if 0 void update_wifi_stats(void) { @@ -645,7 +650,7 @@ cleanup: } #endif -void update_diskio(void) +int update_diskio(void) { int devs_count, num_selected, num_selections, dn; struct device_selection *dev_select = NULL; @@ -663,7 +668,7 @@ void update_diskio(void) if (devstat_getdevs(NULL, &statinfo_cur) < 0) { free(statinfo_cur.dinfo); - return; + return 0; } devs_count = statinfo_cur.dinfo->numdevs; @@ -695,111 +700,36 @@ void update_diskio(void) } free(statinfo_cur.dinfo); + return 0; } /* While topless is obviously better, top is also not bad. */ -int comparecpu(const void *a, const void *b) -{ - if (((const struct process *)a)->amount > ((const struct process *)b)->amount) { - return -1; - } else if (((const struct process *)a)->amount < ((const struct process *)b)->amount) { - return 1; - } else { - return 0; - } -} - -int comparemem(const void *a, const void *b) -{ - if (((const struct process *)a)->rss > ((const struct process *)b)->rss) { - return -1; - } else if (((const struct process *)a)->rss < ((const struct process *)b)->rss) { - return 1; - } else { - return 0; - } -} - -__attribute__((gnu_inline)) inline void -proc_find_top(struct process **cpu, struct process **mem) +void get_top_info(void) { struct kinfo_proc *p; + struct process *proc; int n_processes; - int i, j = 0; - struct process *processes; - - int total_pages; - - /* we get total pages count again to be sure it is up to date */ - if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages) != 0) { - CRIT_ERR(NULL, NULL, "Cannot read sysctl \"vm.stats.vm.v_page_count\""); - } + int i; p = kvm_getprocs(kd, KERN_PROC_PROC, 0, &n_processes); - processes = (process *) malloc(n_processes * sizeof(struct process)); for (i = 0; i < n_processes; i++) { if (!((p[i].ki_flag & P_SYSTEM)) && p[i].ki_comm != NULL) { - processes[j].pid = p[i].ki_pid; - processes[j].name = strndup(p[i].ki_comm, text_buffer_size); - processes[j].amount = 100.0 * p[i].ki_pctcpu / FSCALE; - processes[j].vsize = p[i].ki_size; - processes[j].rss = (p[i].ki_rssize * getpagesize()); - j++; + proc = find_process(p[i].ki_pid); + if (!proc) + proc = new_process(p[i].ki_pid); + + proc->time_stamp = g_time; + proc->name = strndup(p[i].ki_comm, text_buffer_size); + proc->amount = 100.0 * p[i].ki_pctcpu / FSCALE; + proc->vsize = p[i].ki_size; + proc->rss = (p[i].ki_rssize * getpagesize()); + /* ki_runtime is in microseconds, total_cpu_time in centiseconds. + * Therefore we divide by 10000. */ + proc->total_cpu_time = p[i].ki_runtime / 10000; } } - - qsort(processes, j - 1, sizeof(struct process), comparemem); - for (i = 0; i < 10 && i < n_processes; i++) { - struct process *tmp, *ttmp; - - tmp = (process *) malloc(sizeof(struct process)); - tmp->pid = processes[i].pid; - tmp->amount = processes[i].amount; - tmp->name = strndup(processes[i].name, text_buffer_size); - tmp->rss = processes[i].rss; - tmp->vsize = processes[i].vsize; - - ttmp = mem[i]; - mem[i] = tmp; - if (ttmp != NULL) { - free(ttmp->name); - free(ttmp); - } - } - - qsort(processes, j - 1, sizeof(struct process), comparecpu); - for (i = 0; i < 10 && i < n_processes; i++) { - struct process *tmp, *ttmp; - - tmp = (process *) malloc(sizeof(struct process)); - tmp->pid = processes[i].pid; - tmp->amount = processes[i].amount; - tmp->name = strndup(processes[i].name, text_buffer_size); - tmp->rss = processes[i].rss; - tmp->vsize = processes[i].vsize; - - ttmp = cpu[i]; - cpu[i] = tmp; - if (ttmp != NULL) { - free(ttmp->name); - free(ttmp); - } - } - -#if defined(FREEBSD_DEBUG) - printf("=====\nmem\n"); - for (i = 0; i < 10; i++) { - printf("%d: %s(%d) %ld %ld\n", i, mem[i]->name, - mem[i]->pid, mem[i]->vsize, mem[i]->rss); - } -#endif - - for (i = 0; i < j; i++) { - free(processes[i].name); - } - free(processes); } void get_battery_short_status(char *buffer, unsigned int n, const char *bat) diff --git a/src/fs.cc b/src/fs.cc index 1ace9c36..7fdddcd8 100644 --- a/src/fs.cc +++ b/src/fs.cc @@ -69,13 +69,13 @@ static void update_fs_stat(struct fs_stat *fs); void get_fs_type(const char *path, char *result); -void update_fs_stats(void) +int update_fs_stats(void) { unsigned i; static double last_fs_update = 0.0; if (current_update_time - last_fs_update < 13) - return; + return 0; for (i = 0; i < MAX_FS_STATS; ++i) { if (fs_stats[i].set) { @@ -83,6 +83,7 @@ void update_fs_stats(void) } } last_fs_update = current_update_time; + return 0; } void clear_fs_stats(void) diff --git a/src/fs.h b/src/fs.h index 64ac11d8..19285d96 100644 --- a/src/fs.h +++ b/src/fs.h @@ -58,7 +58,7 @@ void print_fs_size(struct text_object *, char *, int); void print_fs_used(struct text_object *, char *, int); void print_fs_type(struct text_object *, char *, int); -void update_fs_stats(void); +int update_fs_stats(void); struct fs_stat *prepare_fs_stat(const char *path); void clear_fs_stats(void); diff --git a/src/hddtemp.cc b/src/hddtemp.cc index 68173240..7238b0ce 100644 --- a/src/hddtemp.cc +++ b/src/hddtemp.cc @@ -207,29 +207,30 @@ out_fail: return 1; } -void update_hddtemp(void) { +int update_hddtemp(void) { char *data, *dev, unit, *saveptr; short val; static double last_hddtemp_update = 0.0; /* limit tcp connection overhead */ if (current_update_time - last_hddtemp_update < 5) - return; + return 0; last_hddtemp_update = current_update_time; free_hddtemp_info(); if (!(data = fetch_hddtemp_output())) - return; + return 0; if (read_hdd_val(data, &dev, &val, &unit, &saveptr)) { free(data); - return; + return 0; } do { add_hddtemp_info(dev, val, unit); } while (!read_hdd_val(NULL, &dev, &val, &unit, &saveptr)); free(data); + return 0; } void free_hddtemp(struct text_object *obj) diff --git a/src/hddtemp.h b/src/hddtemp.h index f84df705..b4c1cdf5 100644 --- a/src/hddtemp.h +++ b/src/hddtemp.h @@ -29,7 +29,7 @@ void set_hddtemp_host(const char *); void set_hddtemp_port(const char *); -void update_hddtemp(void); +int update_hddtemp(void); void free_hddtemp(struct text_object *); void print_hddtemp(struct text_object *, char *, int); diff --git a/src/i8k.cc b/src/i8k.cc index f9aac854..79aa980c 100644 --- a/src/i8k.cc +++ b/src/i8k.cc @@ -32,6 +32,7 @@ #include #include #include +#include "conky.h" #include "logging.h" #include "temphelper.h" #include "text_object.h" @@ -53,7 +54,7 @@ struct _i8k { #define PROC_I8K "/proc/i8k" #define I8K_DELIM " " static char *i8k_procbuf = NULL; -void update_i8k(void) +int update_i8k(void) { FILE *fp; @@ -61,8 +62,13 @@ void update_i8k(void) i8k_procbuf = (char *) malloc(128 * sizeof(char)); } if ((fp = fopen(PROC_I8K, "r")) == NULL) { - CRIT_ERR(NULL, NULL, "/proc/i8k doesn't exist! use insmod to make sure the kernel " - "driver is loaded..."); + free_and_zero(i8k_procbuf); + /*THREAD_CRIT_ERR(NULL, NULL, "/proc/i8k doesn't exist! use insmod to make sure the kernel " + "driver is loaded...");*/ + NORM_ERR("/proc/i8k doesn't exist! use insmod to make sure the kernel driver is loaded..."); + clean_up_without_threads(NULL, NULL); + free(current_mail_spool); + return 1; } memset(&i8k_procbuf[0], 0, 128); @@ -82,6 +88,7 @@ void update_i8k(void) i8k.right_fan_rpm = strtok(NULL, I8K_DELIM); i8k.ac_status = strtok(NULL, I8K_DELIM); i8k.buttons_status = strtok(NULL, I8K_DELIM); + return 0; } static const char *fan_status_to_string(int status) diff --git a/src/i8k.h b/src/i8k.h index 88da9df8..5606118a 100644 --- a/src/i8k.h +++ b/src/i8k.h @@ -32,7 +32,7 @@ #ifndef _I8K_H #define _I8K_H -void update_i8k(void); +int update_i8k(void); void print_i8k_left_fan_status(struct text_object *, char *, int); void print_i8k_cpu_temp(struct text_object *, char *, int); void print_i8k_right_fan_status(struct text_object *, char *, int); diff --git a/src/ibm.cc b/src/ibm.cc index 534db16e..a72b3660 100644 --- a/src/ibm.cc +++ b/src/ibm.cc @@ -129,7 +129,7 @@ void get_ibm_acpi_fan(struct text_object *obj, char *p, int p_max_size) temperatures: 41 43 31 46 33 -128 29 -128 * Peter Tarjan (ptarjan@citromail.hu) */ -void get_ibm_acpi_temps(void) +int get_ibm_acpi_temps(void) { FILE *fp; @@ -158,6 +158,7 @@ void get_ibm_acpi_temps(void) } fclose(fp); + return 0; } /* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi. diff --git a/src/ibm.h b/src/ibm.h index cc84d4f9..e7fbe4e0 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -27,7 +27,7 @@ #define _IBM_H void get_ibm_acpi_fan(struct text_object *, char *, int); -void get_ibm_acpi_temps(void); +int get_ibm_acpi_temps(void); void get_ibm_acpi_volume(struct text_object *, char *, int); void get_ibm_acpi_brightness(struct text_object *, char *, int); diff --git a/src/ical.cc b/src/ical.cc new file mode 100644 index 00000000..99d535fb --- /dev/null +++ b/src/ical.cc @@ -0,0 +1,184 @@ +/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=cpp + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (c) 2005-2010 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 . + * + */ + +#include +#include "conky.h" +#include "logging.h" + +struct ical_event { + icaltimetype start; + icalcomponent *event; + ical_event *next, *prev; +}; + +struct obj_ical { + struct ical_event *list; + icalcomponent *comps; + icalparser *parser; + unsigned int num; +}; + +char* read_stream(char *s, size_t size, void *d) { + return fgets(s, size, (FILE*) d); +} + +struct ical_event *add_event(struct ical_event *listend, icalcomponent *new_ev) { + struct ical_event *ev_new, *ev_cur; + icaltimetype start; + + start = icalcomponent_get_dtstart(new_ev); + if(icaltime_compare(start, icaltime_from_timet(time(NULL), 0)) <= 0) { + icalproperty *rrule = icalcomponent_get_first_property(new_ev, ICAL_RRULE_PROPERTY); + if(rrule) { + icalrecur_iterator* ritr = icalrecur_iterator_new(icalproperty_get_rrule(rrule), start); + icaltimetype nexttime = icalrecur_iterator_next(ritr); + while (!icaltime_is_null_time(nexttime)) { + if(icaltime_compare(nexttime, icaltime_from_timet(time(NULL), 0)) > 0) { + start = nexttime; + break; + } + nexttime = icalrecur_iterator_next(ritr); + } + icalrecur_iterator_free(ritr); + } else return NULL; + } + ev_new = (struct ical_event *) malloc(sizeof(struct ical_event)); + memset(ev_new, 0, sizeof(struct ical_event)); + ev_new->event = new_ev; + ev_new->start = start; + if(listend) { //list already contains events + ev_cur = listend; + while(icaltime_compare(ev_new->start, ev_cur->start) <= 0) { + if( ! ev_cur->prev) { //ev_new starts first + ev_new->next = ev_cur; + ev_cur->prev = ev_new; + return listend; + } + ev_cur = ev_cur->prev; + } + if(ev_cur == listend) { //ev_new starts last + ev_cur->next = ev_new; + ev_new->prev = ev_cur; + return ev_new; + } + //ev_new somewhere in the middle + ev_new->prev = ev_cur; + ev_new->next = ev_cur->next; + ev_cur->next->prev = ev_new; + ev_cur->next = ev_new; + return listend; + } + return ev_new; +} + +void parse_ical_args(struct text_object *obj, const char* arg, void *free_at_crash, void *free_at_crash2) { + char *filename = strdup(arg); + FILE *file; + icalparser *parser; + icalcomponent *allc, *curc; + struct ical_event *ll_start, *ll_end, *ll_new; + struct obj_ical *opaque; + unsigned int num; + + if(sscanf(arg , "%d %s", &num, filename) != 2) { + free(filename); + free(obj); + CRIT_ERR(free_at_crash, free_at_crash2, "wrong number of arguments for $ical"); + } + file = fopen(filename, "r"); + if( ! file) { + free(obj); + free(free_at_crash); + CRIT_ERR(filename, free_at_crash2, "Can't read file %s", filename); + return; + } + free(filename); + parser = icalparser_new(); + icalparser_set_gen_data(parser, file); + allc = icalparser_parse(parser, read_stream); + fclose(file); + curc = icalcomponent_get_first_component(allc, ICAL_VEVENT_COMPONENT); + if(!curc) { + icalparser_free(parser); + icalcomponent_free(allc); + NORM_ERR("No ical events available"); + return; + } + ll_start = add_event(NULL, curc); + ll_end = ll_start; + while(1) { + curc = icalcomponent_get_next_component(allc, ICAL_VEVENT_COMPONENT); + if(!curc) break; + ll_new = add_event(ll_end, curc); + if( ! ll_start) { //first component was not added + ll_start = ll_new; + ll_end = ll_new; + }else if( ll_start->prev ) { + ll_start = ll_start->prev; + }else if( ll_end->next ) { + ll_end = ll_end->next; + } + } + opaque = (struct obj_ical *) malloc(sizeof(struct obj_ical)); + opaque->list = ll_start; + opaque->parser = parser; + opaque->comps = allc; + opaque->num = num; + obj->data.opaque = opaque; +} + +void print_ical(struct text_object *obj, char *p, int p_max_size) { + struct obj_ical *ical_obj = (struct obj_ical *) obj->data.opaque; + struct ical_event *ll_current; + + if( ! ical_obj) return; + ll_current = ical_obj->list; + unsigned int i=1; + while(1) { + if( ! ll_current) return; + if(i > ical_obj->num) return; + if(i == ical_obj->num) break; + if(i < ical_obj->num) { + ll_current = ll_current->next; + i++; + } + } + snprintf(p, p_max_size, "%s", icalproperty_get_summary(icalcomponent_get_first_property(ll_current->event, ICAL_SUMMARY_PROPERTY))); +} + +void free_ical(struct text_object *obj) { + struct obj_ical *ical_free_me = (struct obj_ical *) obj->data.opaque; + + if( ! ical_free_me) return; + icalcomponent_free(ical_free_me->comps); + icalparser_free(ical_free_me->parser); + while(ical_free_me->list) { + if(ical_free_me->list->next) { + ical_free_me->list = ical_free_me->list->next; + free_and_zero(ical_free_me->list->prev); + } else free_and_zero(ical_free_me->list); + } + free(obj->data.opaque); +} diff --git a/src/ical.h b/src/ical.h new file mode 100644 index 00000000..a17c5922 --- /dev/null +++ b/src/ical.h @@ -0,0 +1,33 @@ +/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=cpp + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (c) 2005-2010 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 . + * + */ + +#ifndef ICAL_H_ +#define ICAL_H_ + +void parse_ical_args(struct text_object *, const char*, void*, void*); +void print_ical(struct text_object *, char *, int); +void free_ical(struct text_object *); + +#endif /*ICAL_H_*/ diff --git a/src/irc.cc b/src/irc.cc new file mode 100644 index 00000000..d3512fff --- /dev/null +++ b/src/irc.cc @@ -0,0 +1,204 @@ +/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=cpp + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (c) 2005-2010 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 . + * + */ + +#include "conky.h" +#include "logging.h" +#include +#include +#include +#include "text_object.h" +#include + +struct ll_text { + char *text; + struct ll_text *next; +}; + +struct obj_irc { + pthread_t *thread; + irc_session_t *session; + char *arg; +}; + +struct ctx { + char *chan; + struct ll_text *messages; +}; + +void ev_connected(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count) { + struct ctx *ctxptr = (struct ctx *) irc_get_ctx(session); + if(irc_cmd_join(session, ctxptr->chan, NULL) != 0) { + NORM_ERR("irc: %s", irc_strerror(irc_errno(session))); + } + if(event || origin || params || count) {} //fix gcc warnings +} + +void addmessage(struct ctx *ctxptr, char *nick, const char *text) { + struct ll_text *lastmsg = ctxptr->messages; + struct ll_text *newmsg = (struct ll_text*) malloc(sizeof(struct ll_text)); + newmsg->text = (char*) malloc(strlen(nick) + strlen(text) + 4); //4 = ": \n" + sprintf(newmsg->text, "%s: %s\n", nick, text); + newmsg->next = NULL; + if(!lastmsg) { + ctxptr->messages = newmsg; + } else { + while(lastmsg->next) { + lastmsg = lastmsg->next; + } + lastmsg->next = newmsg; + } +} + +void ev_talkinchan(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count) { + char nickname[64]; + struct ctx *ctxptr = (struct ctx *) irc_get_ctx(session); + + irc_target_get_nick(origin, nickname, sizeof(nickname)); + addmessage(ctxptr, nickname, params[1]); + if(session || event || count) {} //fix gcc warnings +} + +void ev_num(irc_session_t *session, unsigned int event, const char *origin, const char **params, unsigned int count) { + char attachment[4]="_00"; + + if(event == 433) { //nick in use + char *newnick = (char*) malloc(strlen(params[1]) + 4); + strcpy(newnick, params[1]); + attachment[1] += rand() % 10; + attachment[2] += rand() % 10; + strcat(newnick, attachment); + irc_cmd_nick(session, newnick); + free(newnick); + } + if(origin || count) {} //fix gcc warnings +} + +#define IRCSYNTAX "The correct syntax is ${irc server(:port) #channel}" +#define IRCPORT 6667 +#define IRCNICK "conky" +#define IRCSERVERPASS NULL +#define IRCUSER NULL +#define IRCREAL NULL + +void *ircclient(void *ptr) { + struct obj_irc *ircobj = (struct obj_irc *) ptr; + struct ctx *ctxptr = (struct ctx *) malloc(sizeof(struct ctx)); + irc_callbacks_t callbacks; + char *server; + char *strport; + unsigned int port; + + memset (&callbacks, 0, sizeof(callbacks)); + callbacks.event_connect = ev_connected; + callbacks.event_channel = ev_talkinchan; + callbacks.event_numeric = ev_num; + ircobj->session = irc_create_session(&callbacks); + server = strtok(ircobj->arg , " "); + ctxptr->chan = strtok(NULL , " "); + if( ! ctxptr->chan) { + NORM_ERR("irc: %s", IRCSYNTAX); + } + ctxptr->messages = NULL; + irc_set_ctx(ircobj->session, ctxptr); + server = strtok(server, ":"); + strport = strtok(NULL, ":"); + if(strport) { + port = strtol(strport, NULL, 10); + if(port < 1 || port > 65535) + port = IRCPORT; + } else { + port = IRCPORT; + } + if(irc_connect(ircobj->session, server, port, IRCSERVERPASS, IRCNICK, IRCUSER, IRCREAL) != 0) { + NORM_ERR("irc: %s", irc_strerror(irc_errno(ircobj->session))); + } + if(irc_run(ircobj->session) != 0) { + int ircerror = irc_errno(ircobj->session); + if(irc_is_connected(ircobj->session)) { + NORM_ERR("irc: %s", irc_strerror(ircerror)); + } else { + NORM_ERR("irc: disconnected"); + } + } + free(ircobj->arg); + free(ctxptr); + return NULL; +} + +void parse_irc_args(struct text_object *obj, const char* arg) { + struct obj_irc* opaque = (struct obj_irc *) malloc(sizeof(struct obj_irc)); + opaque->thread = (pthread_t *) malloc(sizeof(pthread_t)); + srand(time(NULL)); + opaque->session = NULL; + opaque->arg = strdup(arg); + pthread_create(opaque->thread, NULL, ircclient, opaque); + obj->data.opaque = opaque; +} + +void print_irc(struct text_object *obj, char *p, int p_max_size) { + struct obj_irc *ircobj = (struct obj_irc *) obj->data.opaque; + struct ctx *ctxptr; + struct ll_text *nextmsg, *curmsg; + + if( ! ircobj->session) return; + if( ! irc_is_connected(ircobj->session)) return; + ctxptr = (struct ctx *) irc_get_ctx(ircobj->session); + curmsg = ctxptr->messages; + while(curmsg) { + nextmsg = curmsg->next; + strncat(p, curmsg->text, p_max_size - strlen(p) - 1); + free(curmsg->text); + free(curmsg); + curmsg = nextmsg; + } + if(p[0] != 0) { + p[strlen(p) - 1] = 0; + } + ctxptr->messages = NULL; +} + +void free_irc(struct text_object *obj) { + struct obj_irc *ircobj = (struct obj_irc *) obj->data.opaque; + struct ctx *ctxptr; + struct ll_text *nextmsg, *curmsg = NULL; + + if(ircobj->session) { + if( irc_is_connected(ircobj->session)) { + ctxptr = (struct ctx *) irc_get_ctx(ircobj->session); + curmsg = ctxptr->messages; + irc_disconnect(ircobj->session); + } + pthread_join(*(ircobj->thread), NULL); + irc_destroy_session(ircobj->session); + } + free(ircobj->thread); + free(obj->data.opaque); + while(curmsg) { + nextmsg = curmsg->next; + free(curmsg->text); + free(curmsg); + curmsg = nextmsg; + } +} diff --git a/src/irc.h b/src/irc.h new file mode 100644 index 00000000..cb9f6a2a --- /dev/null +++ b/src/irc.h @@ -0,0 +1,33 @@ +/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=cpp + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (c) 2005-2010 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 . + * + */ + +#ifndef IRC_H_ +#define IRC_H_ + +void parse_irc_args(struct text_object *, const char*); +void print_irc(struct text_object *, char *, int); +void free_irc(struct text_object *); + +#endif /*IRC_H_*/ diff --git a/src/linux.cc b/src/linux.cc index 39ee545d..c7026e64 100644 --- a/src/linux.cc +++ b/src/linux.cc @@ -46,6 +46,7 @@ #include // #include #include +#include "setting.hh" #include "top.h" #include @@ -91,6 +92,8 @@ struct sysfs { #define SHORTSTAT_TEMPL "%*s %llu %llu %llu" #define LONGSTAT_TEMPL "%*s %llu %llu %llu " +static conky::simple_config_setting top_cpu_separate("top_cpu_separate", false, true); + /* This flag tells the linux routines to use the /proc system where possible, * even if other api's are available, e.g. sysinfo() or getloadavg(). * the reason for this is to allow for /proc-based distributed monitoring. @@ -101,7 +104,7 @@ void prepare_update(void) { } -void update_uptime(void) +int update_uptime(void) { #ifdef HAVE_SYSINFO if (!prefer_proc) { @@ -117,12 +120,13 @@ void update_uptime(void) if (!(fp = open_file("/proc/uptime", &rep))) { info.uptime = 0.0; - return; + return 0; } if (fscanf(fp, "%lf", &info.uptime) <= 0) info.uptime = 0; fclose(fp); } + return 0; } int check_mount(struct text_object *obj) @@ -153,7 +157,7 @@ int check_mount(struct text_object *obj) /* these things are also in sysinfo except Buffers: * (that's why I'm reading them from proc) */ -void update_meminfo(void) +int update_meminfo(void) { FILE *meminfo_fp; static int rep = 0; @@ -165,7 +169,7 @@ void update_meminfo(void) info.bufmem = info.buffers = info.cached = info.memfree = info.memeasyfree = 0; if (!(meminfo_fp = open_file("/proc/meminfo", &rep))) { - return; + return 0; } while (!feof(meminfo_fp)) { @@ -195,6 +199,7 @@ void update_meminfo(void) info.bufmem = info.cached + info.buffers; fclose(meminfo_fp); + return 0; } void print_laptop_mode(struct text_object *obj, char *p, int p_max_size) @@ -270,7 +275,7 @@ void update_gateway_info_failure(const char *reason) /* Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT */ #define RT_ENTRY_FORMAT "%63s %lx %lx %x %*d %*d %*d %lx %*d %*d %*d\n" -void update_gateway_info(void) +int update_gateway_info(void) { FILE *fp; struct in_addr ina; @@ -284,13 +289,13 @@ void update_gateway_info(void) if ((fp = fopen("/proc/net/route", "r")) == NULL) { update_gateway_info_failure("fopen()"); - return; + return 0; } /* skip over the table header line, which is always present */ if (fscanf(fp, "%*[^\n]\n") < 0) { fclose(fp); - return; + return 0; } while (!feof(fp)) { @@ -307,7 +312,7 @@ void update_gateway_info(void) } } fclose(fp); - return; + return 0; } void free_gateway_info(struct text_object *obj) @@ -339,7 +344,7 @@ void print_gateway_ip(struct text_object *obj, char *p, int p_max_size) snprintf(p, p_max_size, "%s", gw_info.ip); } -void update_net_stats(void) +int update_net_stats(void) { FILE *net_dev_fp; static int rep = 0; @@ -363,19 +368,19 @@ void update_net_stats(void) /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { - return; + return 0; } /* open file and ignore first two lines */ if (!(net_dev_fp = open_file("/proc/net/dev", &rep))) { clear_net_stats(); - return; + return 0; } if (!fgets(buf, 255, net_dev_fp) || /* garbage */ !fgets(buf, 255, net_dev_fp)) { /* garbage (field names) */ fclose(net_dev_fp); - return; + return 0; } /* read each interface */ @@ -544,6 +549,16 @@ void update_net_stats(void) snprintf(ns->essid, 32, "off/any"); } } + // get channel and freq + if (winfo->b.has_freq) { + if(winfo->has_range == 1) { + ns->channel = iw_freq_to_channel(winfo->b.freq, &(winfo->range)); + iw_print_freq_value(ns->freq, 16, winfo->b.freq); + } else { + ns->channel = 0; + ns->freq[0] = 0; + } + } snprintf(ns->mode, 16, "%s", iw_operation_mode[winfo->b.mode]); } @@ -554,11 +569,12 @@ void update_net_stats(void) first = 0; fclose(net_dev_fp); + return 0; } int result; -void update_total_processes(void) +int update_total_processes(void) { DIR *dir; struct dirent *entry; @@ -567,23 +583,24 @@ void update_total_processes(void) info.procs = 0; if (!(dir = opendir("/proc"))) { - return; + return 0; } while ((entry = readdir(dir))) { if (!entry) { /* Problem reading list of processes */ closedir(dir); info.procs = 0; - return; + return 0; } if (sscanf(entry->d_name, "%d%c", &ignore1, &ignore2) == 1) { info.procs++; } } closedir(dir); + return 0; } -void update_threads(void) +int update_threads(void) { #ifdef HAVE_SYSINFO if (!prefer_proc) { @@ -599,12 +616,13 @@ void update_threads(void) if (!(fp = open_file("/proc/loadavg", &rep))) { info.threads = 0; - return; + return 0; } if (fscanf(fp, "%*f %*f %*f %*d/%hu", &info.threads) <= 0) info.threads = 0; fclose(fp); } + return 0; } #define CPU_SAMPLE_COUNT 15 @@ -678,7 +696,7 @@ void get_cpu_count(void) #define TMPL_LONGSTAT "%*s %llu %llu %llu %llu %llu %llu %llu %llu" #define TMPL_SHORTSTAT "%*s %llu %llu %llu %llu" -void update_stat(void) +int update_stat(void) { FILE *stat_fp; static int rep = 0; @@ -700,7 +718,7 @@ void update_stat(void) pthread_mutex_lock(&last_stat_update_mutex); if (last_stat_update == current_update_time) { pthread_mutex_unlock(&last_stat_update_mutex); - return; + return 0; } last_stat_update = current_update_time; pthread_mutex_unlock(&last_stat_update_mutex); @@ -728,7 +746,7 @@ void update_stat(void) if (info.cpu_usage) { memset(info.cpu_usage, 0, info.cpu_count * sizeof(float)); } - return; + return 0; } idx = 0; @@ -799,19 +817,22 @@ void update_stat(void) } } fclose(stat_fp); + return 0; } -void update_running_processes(void) +int update_running_processes(void) { update_stat(); + return 0; } -void update_cpu_usage(void) +int update_cpu_usage(void) { update_stat(); + return 0; } -void update_load_average(void) +int update_load_average(void) { #ifdef HAVE_GETLOADAVG if (!prefer_proc) { @@ -829,13 +850,14 @@ void update_load_average(void) if (!(fp = open_file("/proc/loadavg", &rep))) { info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0; - return; + return 0; } if (fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1], &info.loadavg[2]) < 0) info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0; fclose(fp); } + return 0; } /***********************************************************/ @@ -2209,16 +2231,6 @@ void get_powerbook_batt_info(struct text_object *obj, char *buffer, int n) snprintf(buffer, n, "%s", pb_battery_info[obj->data.i]); } -void update_top(void) -{ - process_find_top(info.cpu, info.memu, info.time -#ifdef BUILD_IOSTATS - , info.io -#endif - ); - info.first_process = get_first_process(); -} - #define ENTROPY_AVAIL_PATH "/proc/sys/kernel/random/entropy_avail" int get_entropy_avail(unsigned int *val) @@ -2319,7 +2331,7 @@ int is_disk(char *dev) return dev_cur->memoized; } -void update_diskio(void) +int update_diskio(void) { FILE *fp; static int rep = 0; @@ -2335,7 +2347,7 @@ void update_diskio(void) stats.current_write = 0; if (!(fp = open_file("/proc/diskstats", &rep))) { - return; + return 0; } /* read reads and writes from all disks (minor = 0), including cd-roms @@ -2370,6 +2382,7 @@ void update_diskio(void) } update_diskio_values(&stats, total_reads, total_writes); fclose(fp); + return 0; } void print_distribution(struct text_object *obj, char *p, int p_max_size) @@ -2407,3 +2420,343 @@ void print_distribution(struct text_object *obj, char *p, int p_max_size) } } +/****************************************** + * Calculate cpu total * + ******************************************/ +#define TMPL_SHORTPROC "%*s %llu %llu %llu %llu" +#define TMPL_LONGPROC "%*s %llu %llu %llu %llu %llu %llu %llu %llu" + +static unsigned long long calc_cpu_total(void) +{ + static unsigned long long previous_total = 0; + unsigned long long total = 0; + unsigned long long t = 0; + int rc; + int ps; + char line[BUFFER_LEN] = { 0 }; + unsigned long long cpu = 0; + unsigned long long niceval = 0; + unsigned long long systemval = 0; + unsigned long long idle = 0; + unsigned long long iowait = 0; + unsigned long long irq = 0; + unsigned long long softirq = 0; + unsigned long long steal = 0; + const char *template_ = + KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGPROC : TMPL_SHORTPROC; + + ps = open("/proc/stat", O_RDONLY); + rc = read(ps, line, sizeof(line)); + close(ps); + if (rc < 0) { + return 0; + } + + sscanf(line, template_, &cpu, &niceval, &systemval, &idle, &iowait, &irq, + &softirq, &steal); + total = cpu + niceval + systemval + idle + iowait + irq + softirq + steal; + + t = total - previous_total; + previous_total = total; + + return t; +} + +/****************************************** + * Calculate each processes cpu * + ******************************************/ + +inline static void calc_cpu_each(unsigned long long total) +{ + float mul = 100.0; + if(top_cpu_separate.get(*state)) + mul *= info.cpu_count; + + for(struct process *p = first_process; p; p = p->next) + p->amount = mul * (p->user_time + p->kernel_time) / (float) total; +} + +#ifdef BUILD_IOSTATS +static void calc_io_each(void) +{ + struct process *p; + unsigned long long sum = 0; + + for (p = first_process; p; p = p->next) + sum += p->read_bytes + p->write_bytes; + + if(sum == 0) + sum = 1; /* to avoid having NANs if no I/O occured */ + for (p = first_process; p; p = p->next) + p->io_perc = 100.0 * (p->read_bytes + p->write_bytes) / (float) sum; +} +#endif /* BUILD_IOSTATS */ + +/****************************************** + * Extract information from /proc * + ******************************************/ + +#define PROCFS_TEMPLATE "/proc/%d/stat" +#define PROCFS_CMDLINE_TEMPLATE "/proc/%d/cmdline" + +/* These are the guts that extract information out of /proc. + * Anyone hoping to port wmtop should look here first. */ +static void process_parse_stat(struct process *process) +{ + char line[BUFFER_LEN] = { 0 }, filename[BUFFER_LEN], procname[BUFFER_LEN]; + char state[4]; + int ps; + unsigned long user_time = 0; + unsigned long kernel_time = 0; + int rc; + char *r, *q; + int endl; + int nice_val; + char *lparen, *rparen; + + snprintf(filename, sizeof(filename), PROCFS_TEMPLATE, process->pid); + + ps = open(filename, O_RDONLY); + if (ps < 0) { + /* The process must have finished in the last few jiffies! */ + return; + } + + /* Mark process as up-to-date. */ + process->time_stamp = g_time; + + rc = read(ps, line, sizeof(line)); + close(ps); + if (rc < 0) { + return; + } + + /* Extract cpu times from data in /proc filesystem */ + lparen = strchr(line, '('); + rparen = strrchr(line, ')'); + if(!lparen || !rparen || rparen < lparen) + return; // this should not happen + + rc = MIN((unsigned)(rparen - lparen - 1), sizeof(procname) - 1); + strncpy(procname, lparen + 1, rc); + procname[rc] = '\0'; + rc = sscanf(rparen + 1, "%3s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu " + "%lu %*s %*s %*s %d %*s %*s %*s %u %u", state, &process->user_time, + &process->kernel_time, &nice_val, &process->vsize, &process->rss); + if (rc < 6) { + NORM_ERR("scaning data for %s failed, got only %d fields", procname, rc); + return; + } + + if(state[0]=='R') + ++ info.run_procs; + + /* remove any "kdeinit: " */ + if (procname == strstr(procname, "kdeinit")) { + snprintf(filename, sizeof(filename), PROCFS_CMDLINE_TEMPLATE, + process->pid); + + ps = open(filename, O_RDONLY); + if (ps < 0) { + /* The process must have finished in the last few jiffies! */ + return; + } + + endl = read(ps, line, sizeof(line)); + close(ps); + + /* null terminate the input */ + line[endl] = 0; + /* account for "kdeinit: " */ + if ((char *) line == strstr(line, "kdeinit: ")) { + r = ((char *) line) + 9; + } else { + r = (char *) line; + } + + q = procname; + /* stop at space */ + while (*r && *r != ' ') { + *q++ = *r++; + } + *q = 0; + } + + free_and_zero(process->name); + process->name = strndup(procname, text_buffer_size); + process->rss *= getpagesize(); + + process->total_cpu_time = process->user_time + process->kernel_time; + if (process->previous_user_time == ULONG_MAX) { + process->previous_user_time = process->user_time; + } + if (process->previous_kernel_time == ULONG_MAX) { + process->previous_kernel_time = process->kernel_time; + } + + /* strangely, the values aren't monotonous */ + if (process->previous_user_time > process->user_time) + process->previous_user_time = process->user_time; + + if (process->previous_kernel_time > process->kernel_time) + process->previous_kernel_time = process->kernel_time; + + /* store the difference of the user_time */ + user_time = process->user_time - process->previous_user_time; + kernel_time = process->kernel_time - process->previous_kernel_time; + + /* backup the process->user_time for next time around */ + process->previous_user_time = process->user_time; + process->previous_kernel_time = process->kernel_time; + + /* store only the difference of the user_time here... */ + process->user_time = user_time; + process->kernel_time = kernel_time; +} + +#ifdef BUILD_IOSTATS +#define PROCFS_TEMPLATE_IO "/proc/%d/io" +static void process_parse_io(struct process *process) +{ + static const char *read_bytes_str="read_bytes:"; + static const char *write_bytes_str="write_bytes:"; + + char line[BUFFER_LEN] = { 0 }, filename[BUFFER_LEN]; + int ps; + int rc; + char *pos, *endpos; + unsigned long long read_bytes, write_bytes; + + snprintf(filename, sizeof(filename), PROCFS_TEMPLATE_IO, process->pid); + + ps = open(filename, O_RDONLY); + if (ps < 0) { + /* The process must have finished in the last few jiffies! + * Or, the kernel doesn't support I/O accounting. + */ + return; + } + + rc = read(ps, line, sizeof(line)); + close(ps); + if (rc < 0) { + return; + } + + pos = strstr(line, read_bytes_str); + if (pos == NULL) { + /* these should not happen (unless the format of the file changes) */ + return; + } + pos += strlen(read_bytes_str); + process->read_bytes = strtoull(pos, &endpos, 10); + if (endpos == pos) { + return; + } + + pos = strstr(line, write_bytes_str); + if (pos == NULL) { + return; + } + pos += strlen(write_bytes_str); + process->write_bytes = strtoull(pos, &endpos, 10); + if (endpos == pos) { + return; + } + + if (process->previous_read_bytes == ULLONG_MAX) { + process->previous_read_bytes = process->read_bytes; + } + if (process->previous_write_bytes == ULLONG_MAX) { + process->previous_write_bytes = process->write_bytes; + } + + /* store the difference of the byte counts */ + read_bytes = process->read_bytes - process->previous_read_bytes; + write_bytes = process->write_bytes - process->previous_write_bytes; + + /* backup the counts for next time around */ + process->previous_read_bytes = process->read_bytes; + process->previous_write_bytes = process->write_bytes; + + /* store only the difference here... */ + process->read_bytes = read_bytes; + process->write_bytes = write_bytes; +} +#endif /* BUILD_IOSTATS */ + +/****************************************** + * Get process structure for process pid * + ******************************************/ + +/* This function seems to hog all of the CPU time. + * I can't figure out why - it doesn't do much. */ +static void calculate_stats(struct process *process) +{ + /* compute each process cpu usage by reading /proc//stat */ + process_parse_stat(process); + +#ifdef BUILD_IOSTATS + process_parse_io(process); +#endif /* BUILD_IOSTATS */ + + /* + * Check name against the exclusion list + */ + /* if (process->counted && exclusion_expression && + * !regexec(exclusion_expression, process->name, 0, 0, 0)) + * process->counted = 0; */ +} + +/****************************************** + * Update process table * + ******************************************/ + +static void update_process_table(void) +{ + DIR *dir; + struct dirent *entry; + + if (!(dir = opendir("/proc"))) { + return; + } + + info.run_procs = 0; + + /* Get list of processes from /proc directory */ + while ((entry = readdir(dir))) { + pid_t pid; + + if (!entry) { + /* Problem reading list of processes */ + closedir(dir); + return; + } + + if (sscanf(entry->d_name, "%d", &pid) > 0) { + struct process *p; + + p = find_process(pid); + if (!p) { + p = new_process(pid); + } + + /* compute each process cpu usage */ + calculate_stats(p); + } + } + + closedir(dir); +} + +void get_top_info(void) +{ + unsigned long long total = 0; + + 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 */ +#ifdef BUILD_IOSTATS + calc_io_each(); /* percentage of I/O for each task */ +#endif /* BUILD_IOSTATS */ +} diff --git a/src/linux.h b/src/linux.h index 71697821..982647ac 100644 --- a/src/linux.h +++ b/src/linux.h @@ -33,7 +33,7 @@ void print_disk_protect_queue(struct text_object *, char *, int); void print_ioscheduler(struct text_object *, char *, int); void print_laptop_mode(struct text_object *, char *, int); -void update_gateway_info(void); +int update_gateway_info(void); void free_gateway_info(struct text_object *obj); int gateway_exists(struct text_object *); void print_gateway_iface(struct text_object *, char *, int); @@ -51,7 +51,7 @@ void free_sysfs_sensor(struct text_object *); int get_entropy_avail(unsigned int *); int get_entropy_poolsize(unsigned int *); -void update_stat(void); +int update_stat(void); void print_distribution(struct text_object *, char *, int); diff --git a/src/llua.cc b/src/llua.cc index 05273c95..13749153 100644 --- a/src/llua.cc +++ b/src/llua.cc @@ -42,6 +42,8 @@ void llua_rm_notifies(void); static int llua_block_notify = 0; #endif /* HAVE_SYS_INOTIFY_H */ +#define MIN(a, b) ( (a) < (b) ? (a) : (b) ) + static char *draw_pre_hook = 0; static char *draw_post_hook = 0; static char *startup_hook = 0; @@ -156,6 +158,34 @@ void llua_load(const char *script) } } +/* + * Returns the first space-delimited token of the string starting at position *len. + * On return *len contains the length of the token. Spaces inside brackets are ignored, so that + * eg. '${foo bar}' is treated as a single token. Sets *len to zero and *str points to the end of + * the string when there are no more tokens. + */ +static const char* tokenize(const char *str, size_t *len) +{ + str += *len; + *len = 0; + while(str && isspace(*str)) + ++str; + + size_t level = 0; + while(str[*len] && (level > 0 || !isspace(str[*len]))) { + switch(str[*len]) { + case '{': ++level; break; + case '}': --level; break; + } + ++*len; + } + + if(!str[*len] && level > 0) + NORM_ERR("tokenize: improperly nested token: %s", str); + + return str; +} + /* llua_do_call does a flexible call to any Lua function string: [par1] [par2...] @@ -166,35 +196,31 @@ static char *llua_do_call(const char *string, int retc) static char func[64]; int argc = 0; - char *tmp = strdup(string); - char *ptr = strtok(tmp, " "); + size_t len = 0; + + const char *ptr = tokenize(string, &len); /* proceed only if the function name is present */ - if (!ptr) { - free(tmp); + if (!len) { return NULL; } /* call only conky_ prefixed functions */ - if(strncmp(ptr, LUAPREFIX, strlen(LUAPREFIX)) == 0) { - snprintf(func, 64, "%s", ptr); - }else{ - snprintf(func, 64, "%s%s", LUAPREFIX, ptr); - } + if(strncmp(ptr, LUAPREFIX, strlen(LUAPREFIX)) != 0) { + snprintf(func, sizeof func, "%s", LUAPREFIX); + } else + *func = 0; + strncat(func, ptr, MIN(len, sizeof(func) - strlen(func) - 1)); /* push the function name to stack */ lua_getglobal(lua_L, func); /* parse all function parameters from args and push them to the stack */ - ptr = strtok(NULL, " "); - while (ptr) { - lua_pushstring(lua_L, ptr); - ptr = strtok(NULL, " "); + while( ptr = tokenize(ptr, &len), len) { + lua_pushlstring(lua_L, ptr, len); argc++; } - free(tmp); - if(lua_pcall(lua_L, argc, retc, 0) != 0) { NORM_ERR("llua_do_call: function %s execution failed: %s", func, lua_tostring(lua_L, -1)); lua_pop(lua_L, -1); diff --git a/src/logging.h b/src/logging.h index 45ef7585..2dbe8b28 100644 --- a/src/logging.h +++ b/src/logging.h @@ -33,6 +33,7 @@ #include "mail.h" void clean_up(void *memtofree1, void* memtofree2); +void clean_up_without_threads(void *memtofree1, void* memtofree2); #define NORM_ERR(...) { \ fprintf(stderr, PACKAGE_NAME": "); \ @@ -44,6 +45,9 @@ void clean_up(void *memtofree1, void* memtofree2); #define CRIT_ERR(memtofree1, memtofree2, ...) \ { NORM_ERR(__VA_ARGS__); clean_up(memtofree1, memtofree2); free(current_mail_spool); exit(EXIT_FAILURE); } +#define THREAD_CRIT_ERR(memtofree1, memtofree2, ...) \ + { NORM_ERR(__VA_ARGS__); clean_up_without_threads(memtofree1, memtofree2); free(current_mail_spool); return; } + /* debugging output */ extern int global_debug_level; #define __DBGP(level, ...) \ diff --git a/src/mail.cc b/src/mail.cc index c1a76422..02a3e1d8 100644 --- a/src/mail.cc +++ b/src/mail.cc @@ -62,6 +62,8 @@ #define POP3_TYPE 1 #define IMAP_TYPE 2 +#define MAXFOLDERSIZE 128 + struct mail_s { // for imap and pop3 unsigned long unseen; unsigned long messages; @@ -75,16 +77,16 @@ struct mail_s { // for imap and pop3 char user[128]; char pass[128]; char command[1024]; - char folder[128]; timed_thread_ptr p_timed_thread; char secure; + char folder[MAXFOLDERSIZE]; mail_s() : unseen(0), messages(0), used(0), quota(0), port(0), retries(0), interval(0), last_update(0), secure(0) { host[0] = 0; user[0] = 0; pass[0] = 0; command[0] = 0; - memset(folder, 0, 128); /* to satisfy valgrind */ + memset(folder, 0, MAXFOLDERSIZE); /* to satisfy valgrind */ } }; @@ -474,17 +476,18 @@ struct mail_s *parse_mail_args(char type, const char *arg) if (type == IMAP_TYPE) { tmp = (char*)strstr(arg, "-f "); if (tmp) { - int len = 1024; + int len = MAXFOLDERSIZE-1; tmp += 3; if (tmp[0] == '\'') { len = (char*)strstr(tmp + 1, "'") - tmp - 1; - if (len > 1024) { - len = 1024; + if (len > MAXFOLDERSIZE-1) { + len = MAXFOLDERSIZE-1; } + tmp++; } - strncpy(mail->folder, tmp + 1, len); + strncpy(mail->folder, tmp, len); } else { - strncpy(mail->folder, "INBOX", 128); // default imap inbox + strncpy(mail->folder, "INBOX", MAXFOLDERSIZE-1); // default imap inbox } } tmp = (char*)strstr(arg, "-e "); @@ -640,7 +643,8 @@ static void ensure_mail_thread(struct mail_s *mail, if (mail->p_timed_thread) return; - mail->p_timed_thread = timed_thread::create(std::bind(func, std::placeholders::_1, mail), mail->interval * 1000000); + mail->p_timed_thread = timed_thread::create(std::bind(func, std::placeholders::_1, mail), + std::chrono::microseconds(long(mail->interval * 1000000))); if (!mail->p_timed_thread) { NORM_ERR("Error creating %s timed thread", text); } diff --git a/src/moc.cc b/src/moc.cc index 157d67ba..1e74ca27 100644 --- a/src/moc.cc +++ b/src/moc.cc @@ -126,7 +126,7 @@ static void update_moc_loop(thread_handle &handle) /* never reached */ } -static int run_moc_thread(double interval) +static int run_moc_thread(std::chrono::microseconds interval) { if (moc_thread) return 0; @@ -139,9 +139,10 @@ static int run_moc_thread(double interval) return 0; } -void update_moc(void) +int update_moc(void) { - run_moc_thread(info.music_player_interval * 100000); + run_moc_thread(std::chrono::microseconds(long(info.music_player_interval * 100000))); + return 0; } #define MOC_PRINT_GENERATOR(type, alt) \ diff --git a/src/moc.h b/src/moc.h index 7433e1d8..5cc53050 100644 --- a/src/moc.h +++ b/src/moc.h @@ -24,7 +24,7 @@ #ifndef MOC_H_ #define MOC_H_ -void update_moc(void); +int update_moc(void); void free_moc(struct text_object *); void print_moc_state(struct text_object *, char *, int); diff --git a/src/mpd.cc b/src/mpd.cc index 0734b0cd..8a6ad577 100644 --- a/src/mpd.cc +++ b/src/mpd.cc @@ -125,20 +125,20 @@ void free_mpd(struct text_object *obj) static void update_mpd_thread(thread_handle &handle); -void update_mpd(void) +int update_mpd(void) { - int interval; static timed_thread_ptr thread; if (thread) - return; + return 0; - interval = info.music_player_interval * 1000000; - thread = timed_thread::create(std::bind(update_mpd_thread, std::placeholders::_1), interval); + thread = timed_thread::create(std::bind(update_mpd_thread, std::placeholders::_1), + std::chrono::microseconds(long(info.music_player_interval * 1000000)) ); if (!thread) { NORM_ERR("Failed to create MPD timed thread"); - return; + return 0; } + return 0; } /* stringMAXdup dups at most text_buffer_size bytes */ diff --git a/src/mpd.h b/src/mpd.h index 80c38e4c..c2506a84 100644 --- a/src/mpd.h +++ b/src/mpd.h @@ -35,7 +35,7 @@ int mpd_set_port(const char *); /* text object functions */ void init_mpd(void); void free_mpd(struct text_object *); -void update_mpd(void); +int update_mpd(void); void print_mpd_elapsed(struct text_object *, char *, int); void print_mpd_length(struct text_object *, char *, int); diff --git a/src/net_stat.cc b/src/net_stat.cc index 28308886..aceae345 100644 --- a/src/net_stat.cc +++ b/src/net_stat.cc @@ -247,6 +247,32 @@ void print_wireless_mode(struct text_object *obj, char *p, int p_max_size) snprintf(p, p_max_size, "%s", ns->mode); } +void print_wireless_channel(struct text_object *obj, char *p, int p_max_size) +{ + struct net_stat *ns = (struct net_stat *)obj->data.opaque; + + if (!ns) + return; + + if(ns->channel != 0) { + snprintf(p, p_max_size, "%i", ns->channel); + } else { + snprintf(p, p_max_size, "/"); + } +} +void print_wireless_frequency(struct text_object *obj, char *p, int p_max_size) +{ + struct net_stat *ns = (struct net_stat *)obj->data.opaque; + + if (!ns) + return; + + if(ns->freq[0] != 0) { + snprintf(p, p_max_size, "%s", ns->freq); + } else { + snprintf(p, p_max_size, "/"); + } +} void print_wireless_bitrate(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; @@ -396,7 +422,7 @@ void free_dns_data(struct text_object *obj) memset(&dns_data, 0, sizeof(dns_data)); } -void update_dns_data(void) +int update_dns_data(void) { FILE *fp; char line[256]; @@ -404,7 +430,7 @@ void update_dns_data(void) /* maybe updating too often causes higher load because of /etc lying on a real FS if (current_update_time - last_dns_update < 10.0) - return; + return 0; last_dns_update = current_update_time; */ @@ -412,7 +438,7 @@ void update_dns_data(void) free_dns_data(NULL); if ((fp = fopen("/etc/resolv.conf", "r")) == NULL) - return; + return 0; while(!feof(fp)) { if (fgets(line, 255, fp) == NULL) { break; @@ -425,6 +451,7 @@ void update_dns_data(void) } } fclose(fp); + return 0; } void parse_nameserver_arg(struct text_object *obj, const char *arg) diff --git a/src/net_stat.h b/src/net_stat.h index 0ebd54b2..e048eba7 100644 --- a/src/net_stat.h +++ b/src/net_stat.h @@ -46,6 +46,8 @@ struct net_stat { double net_rec[15], net_trans[15]; // wireless extensions char essid[32]; + int channel; + char freq[16]; char bitrate[16]; char mode[16]; int link_qual; @@ -76,6 +78,8 @@ double upspeedgraphval(struct text_object *); #endif /* BUILD_X11 */ #ifdef BUILD_WLAN void print_wireless_essid(struct text_object *, char *, int); +void print_wireless_channel(struct text_object *, char *, int); +void print_wireless_frequency(struct text_object *, char *, int); void print_wireless_mode(struct text_object *, char *, int); void print_wireless_bitrate(struct text_object *, char *, int); void print_wireless_ap(struct text_object *, char *, int); @@ -92,7 +96,7 @@ int interface_up(struct text_object *); void free_if_up(struct text_object *); void free_dns_data(struct text_object *); -void update_dns_data(void); +int update_dns_data(void); void parse_nameserver_arg(struct text_object *, const char *); void print_nameserver(struct text_object *, char *, int); diff --git a/src/openbsd.cc b/src/openbsd.cc index 4a53b4a1..033c2018 100644 --- a/src/openbsd.cc +++ b/src/openbsd.cc @@ -611,12 +611,6 @@ char get_freq(char *p_client_buffer, size_t client_buffer_size, return 1; } -void update_top() -{ - kvm_init(); - proc_find_top(info.cpu, info.memu); -} - #if 0 /* deprecated, will rewrite this soon in update_net_stats() -hifi */ void update_wifi_stats() @@ -685,108 +679,30 @@ void update_diskio() /* While topless is obviously better, top is also not bad. */ -int comparecpu(const void *a, const void *b) -{ - if (((struct process *) a)->amount > ((struct process *) b)->amount) { - return -1; - } - - if (((struct process *) a)->amount < ((struct process *) b)->amount) { - return 1; - } - - return 0; -} - -int comparemem(const void *a, const void *b) -{ - if (((struct process *) a)->rss > ((struct process *) b)->rss) { - return -1; - } - - if (((struct process *) a)->rss < ((struct process *) b)->rss) { - return 1; - } - - return 0; -} - -inline void proc_find_top(struct process **cpu, struct process **mem) +void get_top_info(void) { struct kinfo_proc2 *p; + struct process *proc; int n_processes; - int i, j = 0; - struct process *processes; - int mib[2]; + int i; - u_int total_pages; - int64_t usermem; - int pagesize = getpagesize(); + kvm_init(); - /* we get total pages count again to be sure it is up to date */ - mib[0] = CTL_HW; - mib[1] = HW_USERMEM64; - size_t size = sizeof(usermem); - - if (sysctl(mib, 2, &usermem, &size, NULL, 0) == -1) { - NORM_ERR("error reading usermem"); - } - - /* translate bytes into page count */ - total_pages = usermem / pagesize; - - int max_size = sizeof(struct kinfo_proc2); - - p = kvm_getproc2(kd, KERN_PROC_ALL, 0, max_size, &n_processes); - processes = malloc(n_processes * sizeof(struct process)); + p = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), + &n_processes); for (i = 0; i < n_processes; i++) { if (!((p[i].p_flag & P_SYSTEM)) && p[i].p_comm != NULL) { - processes[j].pid = p[i].p_pid; - processes[j].name = strndup(p[i].p_comm, text_buffer_size); - processes[j].amount = 100.0 * p[i].p_pctcpu / FSCALE; - j++; + proc = find_process(p[i].p_pid); + if (!proc) + proc = new_process(p[i].p_pid); + + proc->time_stamp = g_time; + proc->name = strndup(p[i].p_comm, text_buffer_size); + proc->amount = 100.0 * p[i].p_pctcpu / FSCALE; + /* TODO: vsize, rss, total_cpu_time */ } } - - qsort(processes, j - 1, sizeof(struct process), comparemem); - for (i = 0; i < 10; i++) { - struct process *tmp, *ttmp; - - tmp = malloc(sizeof(struct process)); - tmp->pid = processes[i].pid; - tmp->amount = processes[i].amount; - tmp->name = strndup(processes[i].name, text_buffer_size); - - ttmp = mem[i]; - mem[i] = tmp; - if (ttmp != NULL) { - free(ttmp->name); - free(ttmp); - } - } - - qsort(processes, j - 1, sizeof(struct process), comparecpu); - for (i = 0; i < 10; i++) { - struct process *tmp, *ttmp; - - tmp = malloc(sizeof(struct process)); - tmp->pid = processes[i].pid; - tmp->amount = processes[i].amount; - tmp->name = strndup(processes[i].name, text_buffer_size); - - ttmp = cpu[i]; - cpu[i] = tmp; - if (ttmp != NULL) { - free(ttmp->name); - free(ttmp); - } - } - - for (i = 0; i < j; i++) { - free(processes[i].name); - } - free(processes); } /* empty stubs so conky links */ diff --git a/src/read_tcpip.cc b/src/read_tcpip.cc index 39258f13..d6e1ac1d 100644 --- a/src/read_tcpip.cc +++ b/src/read_tcpip.cc @@ -35,7 +35,11 @@ #include #include #include +#include +#include #include +#include +#include struct read_tcpip_data { char *host; @@ -63,6 +67,81 @@ void parse_read_tcpip_arg(struct text_object *obj, const char *arg, void *free_a obj->data.opaque = rtd; } +void parse_tcp_ping_arg(struct text_object *obj, const char *arg, void *free_at_crash) +{ +#define DEFAULT_TCP_PING_PORT 80 + struct sockaddr_in *addr; + char *hostname; + struct hostent* he; + + addr = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in)); + obj->data.opaque = addr; + memset(addr, 0, sizeof(struct sockaddr_in)); + hostname = (char *) malloc(strlen(arg)+1); + switch( sscanf(arg, "%s %"SCNu16, hostname, &(addr->sin_port)) ) { + case 1: + addr->sin_port = DEFAULT_TCP_PING_PORT; + break; + case 2: + break; + default: //this point should never be reached + free(hostname); + CRIT_ERR(obj, free_at_crash, "tcp_ping: Reading arguments failed"); + } + if(!(he = gethostbyname(hostname))) { + NORM_ERR("tcp_ping: Problem with resolving '%s', using 'localhost' instead", hostname); + if(!(he = gethostbyname("localhost"))) { + free(hostname); + CRIT_ERR(obj, free_at_crash, "tcp_ping: Resolving 'localhost' also failed"); + } + } + free(hostname); + addr->sin_port = htons(addr->sin_port); + addr->sin_family = he->h_addrtype; + memcpy(&(addr->sin_addr), he->h_addr, he->h_length); +} + +void print_tcp_ping(struct text_object *obj, char *p, int p_max_size) +{ + struct timeval tv1, tv2, timeout; + struct sockaddr_in *addr = (struct sockaddr_in *) obj->data.opaque; + int addrlen = sizeof(struct sockaddr); + int sock = socket(addr->sin_family, SOCK_STREAM, IPPROTO_TCP); + unsigned long long usecdiff; + fd_set writefds; + + if(sock != -1) { + fcntl(sock, F_SETFL, O_NONBLOCK | fcntl(sock, F_GETFL)); + + FD_ZERO(&writefds); + FD_SET(sock, &writefds); +#define TCP_PING_TIMEOUT 10 + timeout.tv_sec = (int) TCP_PING_TIMEOUT; + timeout.tv_usec = (TCP_PING_TIMEOUT - timeout.tv_sec) * 1000000; + connect(sock, (struct sockaddr*) addr, addrlen); //this will "fail" because sock is non-blocking + if(errno == EINPROGRESS) { //but EINPROGRESS is only a "false fail" + gettimeofday(&tv1, 0); + if(select(sock+1, NULL, &writefds, NULL, &timeout) != -1) { + gettimeofday(&tv2, 0); + usecdiff = ((tv2.tv_sec - tv1.tv_sec) * 1000000) + tv2.tv_usec - tv1.tv_usec; + if(usecdiff <= TCP_PING_TIMEOUT * 1000000) { + snprintf(p, p_max_size, "%llu", usecdiff); + } else { +#define TCP_PING_FAILED "down" + snprintf(p, p_max_size, TCP_PING_FAILED); + } + } else { + NORM_ERR("tcp_ping: Couldn't wait on the 'pong'"); + } + } else { + NORM_ERR("tcp_ping: Couldn't start connection"); + } + close(sock); + } else { + NORM_ERR("tcp_ping: Couldn't create socket"); + } +} + void print_read_tcpip(struct text_object *obj, char *p, int p_max_size, int protocol) { int sock, received; @@ -71,6 +150,7 @@ void print_read_tcpip(struct text_object *obj, char *p, int p_max_size, int prot fd_set readfds; struct timeval tv; struct read_tcpip_data *rtd = (struct read_tcpip_data *) obj->data.opaque; + ssize_t written; //only used to to suppress warning (gcc wants the returnvalue of write() in a var) if (!rtd) return; @@ -96,7 +176,7 @@ void print_read_tcpip(struct text_object *obj, char *p, int p_max_size, int prot return; } if(protocol == IPPROTO_UDP) - write(sock, NULL, 0); //when using udp send a zero-length packet to let the other end know of our existence + written = write(sock, NULL, 0); //when using udp send a zero-length packet to let the other end know of our existence FD_ZERO(&readfds); FD_SET(sock, &readfds); tv.tv_sec = 1; @@ -128,3 +208,13 @@ void free_read_tcpip(struct text_object *obj) free_and_zero(rtd->host); free_and_zero(obj->data.opaque); } + +void free_tcp_ping(struct text_object *obj) +{ + struct sockaddr_in *addr = (struct sockaddr_in *) obj->data.opaque; + + if (!addr) + return; + + free_and_zero(obj->data.opaque); +} diff --git a/src/read_tcpip.h b/src/read_tcpip.h index 44bcf932..fd364042 100644 --- a/src/read_tcpip.h +++ b/src/read_tcpip.h @@ -32,8 +32,11 @@ #define _READ_TCP_H void parse_read_tcpip_arg(struct text_object *, const char *, void *); +void parse_tcp_ping_arg(struct text_object *obj, const char *arg, void *free_at_crash); void print_read_tcp(struct text_object *, char *, int); void print_read_udp(struct text_object *, char *, int); +void print_tcp_ping(struct text_object *, char *, int); void free_read_tcpip(struct text_object *); +void free_tcp_ping(struct text_object *); #endif /* _READ_TCP_H */ diff --git a/src/rss.cc b/src/rss.cc index 61627ffd..79b73b2c 100644 --- a/src/rss.cc +++ b/src/rss.cc @@ -41,11 +41,15 @@ struct rss_data { unsigned int nrspaces; }; -static ccurl_location_list locations; +static ccurl_location_list locations_rss; void rss_free_info(void) { - ccurl_free_locations(locations); + for (ccurl_location_list::iterator i = locations_rss.begin(); + i != locations_rss.end(); i++) { + prss_free((PRSS*) (*i)->result); + } + ccurl_free_locations(locations_rss); } static void rss_process_info(char *p, int p_max_size, char *uri, char *action, int @@ -54,7 +58,7 @@ static void rss_process_info(char *p, int p_max_size, char *uri, char *action, i PRSS *data; char *str; - ccurl_location_ptr curloc = ccurl_find_location(locations, uri); + ccurl_location_ptr curloc = ccurl_find_location(locations_rss, uri); assert(act_par >= 0 && action); @@ -63,7 +67,7 @@ static void rss_process_info(char *p, int p_max_size, char *uri, char *action, i memset(curloc->result, 0, sizeof(PRSS)); curloc->process_function = std::bind(prss_parse_data, std::placeholders::_1, std::placeholders::_2); - ccurl_init_thread(curloc, interval); + ccurl_init_thread(curloc, interval * 60); if (!curloc->p_timed_thread) { NORM_ERR("error setting up RSS thread"); } diff --git a/src/tcp-portmon.cc b/src/tcp-portmon.cc index 433e37b3..a2cb6b70 100644 --- a/src/tcp-portmon.cc +++ b/src/tcp-portmon.cc @@ -131,9 +131,10 @@ void tcp_portmon_action(struct text_object *obj, char *p, int p_max_size) } } -void tcp_portmon_update(void) +int tcp_portmon_update(void) { update_tcp_port_monitor_collection(pmc); + return 0; } int tcp_portmon_clear(void) diff --git a/src/tcp-portmon.h b/src/tcp-portmon.h index 992a97c4..db3699a5 100644 --- a/src/tcp-portmon.h +++ b/src/tcp-portmon.h @@ -39,7 +39,7 @@ struct text_object; int tcp_portmon_init(struct text_object *, const char *); void tcp_portmon_action(struct text_object *, char *, int); -void tcp_portmon_update(void); +int tcp_portmon_update(void); int tcp_portmon_clear(void); int tcp_portmon_set_max_connections(int); void tcp_portmon_free(struct text_object *); diff --git a/src/timed-thread.cc b/src/timed-thread.cc index d60cb517..e85d405d 100644 --- a/src/timed-thread.cc +++ b/src/timed-thread.cc @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -39,9 +38,23 @@ #include "timed-thread.h" #include "logging.h" +/* + * In gcc-4.5 condition_variable::wait_until returns a (strong) enum cv_status. + * In gcc-4.4 it returns bool. + * This hack is needed so it can work on both. + */ +#if __GNUC__*100 + __GNUC_MINOR__ >= 405 +inline bool cv_status_to_bool(std::cv_status s) +{ return s == std::cv_status::no_timeout; } +#else +inline bool cv_status_to_bool(bool s) +{ return s; } +#endif + /* Abstraction layer for timed threads */ typedef struct std::chrono::system_clock clk; +using std::chrono::duration_cast; /* private */ struct _timed_thread { @@ -59,8 +72,8 @@ typedef std::list thread_list_t; thread_list_t thread_list; /* create a timed thread (object creation only) */ -timed_thread::timed_thread(const std::function start_routine, unsigned - int interval_usecs) : +timed_thread::timed_thread(const std::function &start_routine, + std::chrono::microseconds interval_usecs) : p_timed_thread(new _timed_thread), p_thread_handle(this), interval_usecs(interval_usecs), running(false) { @@ -163,16 +176,7 @@ int timed_thread::test(int override_wait_time) #endif /* DEBUG */ bool rc = false; /* determine when to wait until */ -#ifdef _GLIBCXX_USE_CLOCK_REALTIME - clk::time_point wait_time = p_timed_thread->last_time + - clk::duration(interval_usecs * 1000); -#elif defined(_GLIBCXX_USE_GETTIMEOFDAY) - clk::time_point wait_time = p_timed_thread->last_time + - clk::duration(interval_usecs); -#else - clk::time_point wait_time = p_timed_thread->last_time + - clk::duration(interval_usecs / 1000000); -#endif + clk::time_point wait_time = p_timed_thread->last_time + duration_cast(interval_usecs); /* acquire runnable_cond mutex */ { @@ -188,26 +192,13 @@ int timed_thread::test(int override_wait_time) } /* release mutex and wait until future time for runnable_cond to signal */ - rc = p_timed_thread->runnable_cond.wait_until(lock, wait_time); + rc = cv_status_to_bool( p_timed_thread->runnable_cond.wait_until(lock, wait_time) ); } p_timed_thread->last_time = clk::now(); -#ifdef _GLIBCXX_USE_CLOCK_REALTIME - if (wait_time + clk::duration(interval_usecs * 1000) > - p_timed_thread->last_time) { + if (wait_time + duration_cast(interval_usecs) > p_timed_thread->last_time) { p_timed_thread->last_time = wait_time; } -#elif defined(_GLIBCXX_USE_GETTIMEOFDAY) - if (wait_time + clk::duration(interval_usecs) > - p_timed_thread->last_time) { - p_timed_thread->last_time = wait_time; - } -#else - if (wait_time + clk::duration(interval_usecs / 1000000) > - p_timed_thread->last_time) { - p_timed_thread->last_time = wait_time; - } -#endif /* if runnable_cond was signaled, tell caller to exit thread */ return rc; diff --git a/src/timed-thread.h b/src/timed-thread.h index 2b487cb5..c2c3059e 100644 --- a/src/timed-thread.h +++ b/src/timed-thread.h @@ -26,6 +26,7 @@ #define _TIMED_THREAD_H_ #include +#include #include #include @@ -59,9 +60,9 @@ class thread_handle { class timed_thread { public: /* create a timed thread (object creation only) */ - static timed_thread_ptr create(const std::function start_routine, const unsigned int - interval_usecs, bool register_for_destruction = true) { - timed_thread_ptr ptr(new timed_thread(std::cref(start_routine), interval_usecs)); + static timed_thread_ptr create(const std::function &start_routine, + std::chrono::microseconds interval_usecs, bool register_for_destruction = true) { + timed_thread_ptr ptr(new timed_thread(start_routine, interval_usecs)); if (register_for_destruction) { register_(ptr); } @@ -92,8 +93,8 @@ class timed_thread { private: /* create a timed thread (object creation only) */ - timed_thread(const std::function start_routine, unsigned int - interval_usecs); + timed_thread(const std::function &start_routine, + std::chrono::microseconds interval_usecs); /* waits required interval (unless override_wait_time is non-zero) for * termination signal returns 1 if received, 0 otherwise. should also return 1 @@ -112,7 +113,7 @@ class timed_thread { /* private internal data */ std::auto_ptr<_timed_thread> p_timed_thread; thread_handle p_thread_handle; - unsigned int interval_usecs; + std::chrono::microseconds interval_usecs; bool running; friend class thread_handle; }; diff --git a/src/top.cc b/src/top.cc index 98d7404f..f38b232a 100644 --- a/src/top.cc +++ b/src/top.cc @@ -32,16 +32,13 @@ #include "prioqueue.h" #include "top.h" #include "logging.h" -#include "setting.hh" /* hash table size - always a power of 2 */ #define HTABSIZE 256 -static unsigned long g_time = 0; -static unsigned long long previous_total = 0; -static struct process *first_process = 0; +struct process *first_process = 0; -static conky::simple_config_setting top_cpu_separate("top_cpu_separate", false, true); +unsigned long g_time = 0; /* a simple hash table to speed up find_process() */ struct proc_hash_entry { @@ -141,7 +138,7 @@ struct process *get_process_by_name(const char *name) return 0; } -static struct process *find_process(pid_t pid) +struct process *find_process(pid_t pid) { struct proc_hash_entry *phe; @@ -155,7 +152,7 @@ static struct process *find_process(pid_t pid) } /* Create a new process object and insert it into the process list */ -static struct process *new_process(int p) +struct process *new_process(int p) { struct process *process; process = (struct process *) malloc(sizeof(struct process)); @@ -194,273 +191,6 @@ static struct process *new_process(int p) * Functions * ******************************************/ -/****************************************** - * Extract information from /proc * - ******************************************/ - -/* These are the guts that extract information out of /proc. - * Anyone hoping to port wmtop should look here first. */ -static int process_parse_stat(struct process *process) -{ - char line[BUFFER_LEN] = { 0 }, filename[BUFFER_LEN], procname[BUFFER_LEN]; - char state[4]; - int ps; - unsigned long user_time = 0; - unsigned long kernel_time = 0; - int rc; - char *r, *q; - int endl; - int nice_val; - char *lparen, *rparen; - - snprintf(filename, sizeof(filename), PROCFS_TEMPLATE, process->pid); - - ps = open(filename, O_RDONLY); - if (ps < 0) { - /* The process must have finished in the last few jiffies! */ - return 1; - } - - /* Mark process as up-to-date. */ - process->time_stamp = g_time; - - rc = read(ps, line, sizeof(line)); - close(ps); - if (rc < 0) { - return 1; - } - - /* Extract cpu times from data in /proc filesystem */ - lparen = strchr(line, '('); - rparen = strrchr(line, ')'); - if(!lparen || !rparen || rparen < lparen) - return 1; // this should not happen - - rc = MIN((unsigned)(rparen - lparen - 1), sizeof(procname) - 1); - strncpy(procname, lparen + 1, rc); - procname[rc] = '\0'; - rc = sscanf(rparen + 1, "%3s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu " - "%lu %*s %*s %*s %d %*s %*s %*s %u %u", state, &process->user_time, - &process->kernel_time, &nice_val, &process->vsize, &process->rss); - if (rc < 6) { - NORM_ERR("scaning data for %s failed, got only %d fields", procname, rc); - return 1; - } - - if(state[0]=='R') - ++ info.run_procs; - - /* remove any "kdeinit: " */ - if (procname == strstr(procname, "kdeinit")) { - snprintf(filename, sizeof(filename), PROCFS_CMDLINE_TEMPLATE, - process->pid); - - ps = open(filename, O_RDONLY); - if (ps < 0) { - /* The process must have finished in the last few jiffies! */ - return 1; - } - - endl = read(ps, line, sizeof(line)); - close(ps); - - /* null terminate the input */ - line[endl] = 0; - /* account for "kdeinit: " */ - if ((char *) line == strstr(line, "kdeinit: ")) { - r = ((char *) line) + 9; - } else { - r = (char *) line; - } - - q = procname; - /* stop at space */ - while (*r && *r != ' ') { - *q++ = *r++; - } - *q = 0; - } - - free_and_zero(process->name); - process->name = strndup(procname, text_buffer_size); - process->rss *= getpagesize(); - - process->total_cpu_time = process->user_time + process->kernel_time; - if (process->previous_user_time == ULONG_MAX) { - process->previous_user_time = process->user_time; - } - if (process->previous_kernel_time == ULONG_MAX) { - process->previous_kernel_time = process->kernel_time; - } - - /* strangely, the values aren't monotonous */ - if (process->previous_user_time > process->user_time) - process->previous_user_time = process->user_time; - - if (process->previous_kernel_time > process->kernel_time) - process->previous_kernel_time = process->kernel_time; - - /* store the difference of the user_time */ - user_time = process->user_time - process->previous_user_time; - kernel_time = process->kernel_time - process->previous_kernel_time; - - /* backup the process->user_time for next time around */ - process->previous_user_time = process->user_time; - process->previous_kernel_time = process->kernel_time; - - /* store only the difference of the user_time here... */ - process->user_time = user_time; - process->kernel_time = kernel_time; - - return 0; -} - -#ifdef BUILD_IOSTATS -static int process_parse_io(struct process *process) -{ - static const char *read_bytes_str="read_bytes:"; - static const char *write_bytes_str="write_bytes:"; - - char line[BUFFER_LEN] = { 0 }, filename[BUFFER_LEN]; - int ps; - int rc; - char *pos, *endpos; - unsigned long long read_bytes, write_bytes; - - snprintf(filename, sizeof(filename), PROCFS_TEMPLATE_IO, process->pid); - - ps = open(filename, O_RDONLY); - if (ps < 0) { - /* The process must have finished in the last few jiffies! - * Or, the kernel doesn't support I/O accounting. - */ - return 1; - } - - rc = read(ps, line, sizeof(line)); - close(ps); - if (rc < 0) { - return 1; - } - - pos = strstr(line, read_bytes_str); - if (pos == NULL) { - /* these should not happen (unless the format of the file changes) */ - return 1; - } - pos += strlen(read_bytes_str); - process->read_bytes = strtoull(pos, &endpos, 10); - if (endpos == pos) { - return 1; - } - - pos = strstr(line, write_bytes_str); - if (pos == NULL) { - return 1; - } - pos += strlen(write_bytes_str); - process->write_bytes = strtoull(pos, &endpos, 10); - if (endpos == pos) { - return 1; - } - - if (process->previous_read_bytes == ULLONG_MAX) { - process->previous_read_bytes = process->read_bytes; - } - if (process->previous_write_bytes == ULLONG_MAX) { - process->previous_write_bytes = process->write_bytes; - } - - /* store the difference of the byte counts */ - read_bytes = process->read_bytes - process->previous_read_bytes; - write_bytes = process->write_bytes - process->previous_write_bytes; - - /* backup the counts for next time around */ - process->previous_read_bytes = process->read_bytes; - process->previous_write_bytes = process->write_bytes; - - /* store only the difference here... */ - process->read_bytes = read_bytes; - process->write_bytes = write_bytes; - - return 0; -} -#endif /* BUILD_IOSTATS */ - -/****************************************** - * Get process structure for process pid * - ******************************************/ - -/* This function seems to hog all of the CPU time. - * I can't figure out why - it doesn't do much. */ -static int calculate_stats(struct process *process) -{ - int rc; - - /* compute each process cpu usage by reading /proc//stat */ - rc = process_parse_stat(process); - if (rc) return 1; - /* rc = process_parse_statm(process); if (rc) return 1; */ - -#ifdef BUILD_IOSTATS - rc = process_parse_io(process); - if (rc) return 1; -#endif /* BUILD_IOSTATS */ - - /* - * Check name against the exclusion list - */ - /* if (process->counted && exclusion_expression && - * !regexec(exclusion_expression, process->name, 0, 0, 0)) - * process->counted = 0; */ - - return 0; -} - -/****************************************** - * Update process table * - ******************************************/ - -static int update_process_table(void) -{ - DIR *dir; - struct dirent *entry; - - if (!(dir = opendir("/proc"))) { - return 1; - } - - info.run_procs = 0; - ++g_time; - - /* Get list of processes from /proc directory */ - while ((entry = readdir(dir))) { - pid_t pid; - - if (!entry) { - /* Problem reading list of processes */ - closedir(dir); - return 1; - } - - if (sscanf(entry->d_name, "%d", &pid) > 0) { - struct process *p; - - p = find_process(pid); - if (!p) { - p = new_process(pid); - } - - /* compute each process cpu usage */ - calculate_stats(p); - } - } - - closedir(dir); - - return 0; -} - /****************************************** * Destroy and remove a process * ******************************************/ @@ -516,77 +246,6 @@ static void process_cleanup(void) } } -/****************************************** - * Calculate cpu total * - ******************************************/ -#define TMPL_SHORTPROC "%*s %llu %llu %llu %llu" -#define TMPL_LONGPROC "%*s %llu %llu %llu %llu %llu %llu %llu %llu" - -static unsigned long long calc_cpu_total(void) -{ - unsigned long long total = 0; - unsigned long long t = 0; - int rc; - int ps; - char line[BUFFER_LEN] = { 0 }; - unsigned long long cpu = 0; - unsigned long long niceval = 0; - unsigned long long systemval = 0; - unsigned long long idle = 0; - unsigned long long iowait = 0; - unsigned long long irq = 0; - unsigned long long softirq = 0; - unsigned long long steal = 0; - const char *template_ = - KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGPROC : TMPL_SHORTPROC; - - ps = open("/proc/stat", O_RDONLY); - rc = read(ps, line, sizeof(line)); - close(ps); - if (rc < 0) { - return 0; - } - - sscanf(line, template_, &cpu, &niceval, &systemval, &idle, &iowait, &irq, - &softirq, &steal); - total = cpu + niceval + systemval + idle + iowait + irq + softirq + steal; - - t = total - previous_total; - previous_total = total; - - return t; -} - -/****************************************** - * Calculate each processes cpu * - ******************************************/ - -inline static void calc_cpu_each(unsigned long long total) -{ - float mul = 100.0; - if(top_cpu_separate.get(*state)) - mul *= info.cpu_count; - - for(struct process *p = first_process; p; p = p->next) - p->amount = mul * (p->user_time + p->kernel_time) / (float) total; -} - -#ifdef BUILD_IOSTATS -static void calc_io_each(void) -{ - struct process *p; - unsigned long long sum = 0; - - for (p = first_process; p; p = p->next) - sum += p->read_bytes + p->write_bytes; - - if(sum == 0) - sum = 1; /* to avoid having NANs if no I/O occured */ - for (p = first_process; p; p = p->next) - p->io_perc = 100.0 * (p->read_bytes + p->write_bytes) / (float) sum; -} -#endif /* BUILD_IOSTATS */ - /****************************************** * Find the top processes * ******************************************/ @@ -596,13 +255,7 @@ static int compare_cpu(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; - if (a->amount < b->amount) { - return 1; - } else if (a->amount > b->amount) { - return -1; - } else { - return 0; - } + return b->amount - a->amount; } /* mem comparison function for prio queue */ @@ -610,13 +263,7 @@ static int compare_mem(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; - if (a->rss < b->rss) { - return 1; - } else if (a->rss > b->rss) { - return -1; - } else { - return 0; - } + return b->rss - a->rss; } /* CPU time comparision function for prio queue */ @@ -633,13 +280,7 @@ static int compare_io(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; - if (a->io_perc < b->io_perc) { - return 1; - } else if (a->io_perc > b->io_perc) { - return -1; - } else { - return 0; - } + return b->io_perc - a->io_perc; } #endif /* BUILD_IOSTATS */ @@ -648,20 +289,18 @@ static int compare_io(void *va, void *vb) * Results are stored in the cpu,mem arrays in decreasing order[0-9]. * * ****************************************************************** */ -void process_find_top(struct process **cpu, struct process **mem, +static void process_find_top(struct process **cpu, struct process **mem, struct process **ptime #ifdef BUILD_IOSTATS , struct process **io #endif /* BUILD_IOSTATS */ ) { - prio_queue_t cpu_queue, mem_queue, time_queue + prio_queue_t cpu_queue, mem_queue, time_queue; #ifdef BUILD_IOSTATS - , io_queue + prio_queue_t io_queue; #endif - ; struct process *cur_proc = NULL; - unsigned long long total = 0; int i; if (!top_cpu && !top_mem && !top_time @@ -691,13 +330,16 @@ void process_find_top(struct process **cpu, struct process **mem, 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 */ + /* g_time is the time_stamp entry for process. It is updated when the + * process information is updated to indicate that the process is still + * alive (and must not be removed from the process list in + * process_cleanup()) */ + ++g_time; + + /* OS-specific function updating process list */ + get_top_info(); + process_cleanup(); /* cleanup list from exited processes */ -#ifdef BUILD_IOSTATS - calc_io_each(); /* percentage of I/O for each task */ -#endif /* BUILD_IOSTATS */ cur_proc = first_process; @@ -739,6 +381,17 @@ void process_find_top(struct process **cpu, struct process **mem, #endif /* BUILD_IOSTATS */ } +int update_top(void) +{ + process_find_top(info.cpu, info.memu, info.time +#ifdef BUILD_IOSTATS + , info.io +#endif + ); + info.first_process = get_first_process(); + return 0; +} + static char *format_time(unsigned long timeval, const int width) { char buf[10]; @@ -945,16 +598,22 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) #else /* BUILD_IOSTATS */ NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize"); #endif /* BUILD_IOSTATS */ + free_and_zero(td->s); + free_and_zero(obj->data.opaque); return 0; } if (n < 1 || n > 10) { NORM_ERR("invalid num arg for top. Must be between 1 and 10."); + free_and_zero(td->s); + free_and_zero(obj->data.opaque); return 0; } else { td->num = n - 1; } } else { NORM_ERR("invalid argument count for top"); + free_and_zero(td->s); + free_and_zero(obj->data.opaque); return 0; } obj->callbacks.free = &free_top; diff --git a/src/top.h b/src/top.h index d1a4fad7..ae9b8b18 100644 --- a/src/top.h +++ b/src/top.h @@ -74,10 +74,6 @@ * and it'll take me a while to write a replacement. */ #define BUFFER_LEN 1024 -#define PROCFS_TEMPLATE "/proc/%d/stat" -#define PROCFS_TEMPLATE_MEM "/proc/%d/statm" -#define PROCFS_TEMPLATE_IO "/proc/%d/io" -#define PROCFS_CMDLINE_TEMPLATE "/proc/%d/cmdline" #define MAX_SP 10 // number of elements to sort enum top_field { @@ -131,13 +127,6 @@ struct sorted_process { struct process *proc; }; -/* Pointer to head of process list */ -void process_find_top(struct process **, struct process **, struct process ** -#ifdef BUILD_IOSTATS - , struct process ** -#endif - ); - /* lookup a program by it's name */ struct process *get_process_by_name(const char *); @@ -146,4 +135,14 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj); /* return zero on success, non-zero otherwise */ int set_top_name_width(const char *); +int update_top(void); + +void get_top_info(void); + +extern struct process *first_process; +extern unsigned long g_time; + +struct process *find_process(pid_t pid); +struct process *new_process(int p); + #endif /* _top_h_ */ diff --git a/src/users.cc b/src/users.cc index ac36dab8..599f3228 100644 --- a/src/users.cc +++ b/src/users.cc @@ -151,7 +151,7 @@ static void update_user_time(char *tty) } } -void update_users(void) +int update_users(void) { struct information *current_info = &info; char temp[BUFLEN] = ""; @@ -197,6 +197,7 @@ void update_users(void) current_info->users.times = (char*)malloc(text_buffer_size); strncpy(current_info->users.times, "broken", text_buffer_size); } + return 0; } void print_user_names(struct text_object *obj, char *p, int p_max_size) diff --git a/src/users.h b/src/users.h index 49e7bfd4..dd5e7ece 100644 --- a/src/users.h +++ b/src/users.h @@ -31,7 +31,7 @@ #ifndef _USERS_H #define _USERS_H -void update_users(void); +int update_users(void); void print_user_names(struct text_object *, char *, int); void print_user_terms(struct text_object *, char *, int); diff --git a/src/xmms2.cc b/src/xmms2.cc index 86a2d194..109480f0 100644 --- a/src/xmms2.cc +++ b/src/xmms2.cc @@ -239,6 +239,7 @@ int handle_playback_state_change(xmmsv_t *value, void *p) break; case XMMS_PLAYBACK_STATUS_STOP: strncpy(ptr->xmms2.status, "Stopped", text_buffer_size - 1); + ptr->xmms2.elapsed = ptr->xmms2.progress = ptr->xmms2.percent = 0; break; default: strncpy(ptr->xmms2.status, "Unknown", text_buffer_size - 1); @@ -268,7 +269,7 @@ int handle_playlist_loaded(xmmsv_t *value, void *p) return TRUE; } -void update_xmms2(void) +int update_xmms2(void) { struct information *current_info = &info; @@ -282,7 +283,7 @@ void update_xmms2(void) /* did init fail? */ if (xmms2_conn == NULL) { fprintf(stderr,"XMMS2 init failed. %s\n", xmmsc_get_last_error(xmms2_conn)); - return; + return 0; } /* init ok but not connected yet.. */ @@ -300,7 +301,7 @@ void update_xmms2(void) if (!xmmsc_connect(xmms2_conn, path)) { fprintf(stderr,"XMMS2 connection failed. %s\n", xmmsc_get_last_error(xmms2_conn)); current_info->xmms2.conn_state = CONN_NO; - return; + return 0; } /* set callbacks */ @@ -334,6 +335,7 @@ void update_xmms2(void) xmmsc_io_out_handle(xmms2_conn); } + return 0; } void print_xmms2_tracknr(struct text_object *obj, char *p, int p_max_size) diff --git a/src/xmms2.h b/src/xmms2.h index 44da5699..3e25a281 100644 --- a/src/xmms2.h +++ b/src/xmms2.h @@ -54,7 +54,7 @@ struct xmms2_s { int conn_state; }; -void update_xmms2(void); +int update_xmms2(void); void print_xmms2_tracknr(struct text_object *, char *, int); void print_xmms2_elapsed(struct text_object *, char *, int);