pax_global_header00006660000000000000000000000064126231166410014514gustar00rootroot0000000000000052 comment=15662beb39de2a369588e0938f7c8c0353058a28 conky-1.10.1/000077500000000000000000000000001262311664100127175ustar00rootroot00000000000000conky-1.10.1/.gitignore000066400000000000000000000003271262311664100147110ustar00rootroot00000000000000*~ .*.swp Doxyfile patches/ doc/conky.1 README build* doc/*.html Makefile CMakeCache.txt CMakeFiles *.cmake data/convertconf.h data/defconfig.h lua/libcairo-orig.c lua/libcairo.c lua/libimlib2.c *.so *.a /config.h conky-1.10.1/.travis.yml000066400000000000000000000006111262311664100150260ustar00rootroot00000000000000language: cpp compiler: - gcc before_install: - sudo apt-get update -qq - sudo apt-get install -qq cmake libxdamage-dev libx11-dev libxft-dev libxdamage-dev libxext-dev libglib2.0-dev libxml2-dev libcurl4-gnutls-dev liblua5.1-0-dev libimlib2-dev libtolua++5.1-dev libcairo2-dev gawk before_script: - mkdir build && cd build && cmake ../ script: - make branches: only: - master conky-1.10.1/AUTHORS000066400000000000000000000206101262311664100137660ustar00rootroot00000000000000NOTE: Since moving to Git, I am no longer going to continue to update this file (in favour of Git's log stuff). If you want to add yourself here when you submit a patch, feel free. Authors of conky in alphapetical order (please, send mail if I forgot somebody or email address / name is wrong): adi Outline stuff ACPI fan & adapter Adi Zaimi original top code Alex Iconv patch affinity X-Mozilla-Status support akash battery_percent and battery_bar Asbjrn Zweidorff Kjr support for EVE-Online skill monitoring Aseem Mohanty if_up patch Ben Kibbey $tail fifo patch multiple mailbox patch Blondak diskio read & write patch Bobby Beckmann Interface IP and Wireless Quality patch Byron Clark sysfs AC adapter support patch David Carter CPU usage being reported incorrectly by top Brenden Matthews project maintainer Bruce Merry Xdbe (double buffering) btlee linkstatus patch (http://forums.gentoo.org/viewtopic-p-2765647.html#2765647) calmar mboxscan cromka if_existing patch for string matching dan-h adt746x fix Dan Piponi original top code Dave Clark original top code David McCabe utime garo developer Ram Yalamanchili tztime Daniel Thiele APM support for FreeBSD Denis WM_CLASS patch statfs patch Dennis Frommknecht NVCtrl, temperature monitoring for nvdia-based graphics cards Dennis Kaandorp adt746x stuff Elisey O. Savateev Fixed if_mounted on FreeBSD Egor(knick_) Iconv patch Erik Scharwaechter $if_empty patch Falk Feuersenger I2C divisor from a file Fanat1k Iconv patch flitsch hwmon support fow mpd_title max length Gwenhael LE MOINE Manual setting of the position WM_CLASS for window when drawing to own window Hannu Saransaari Main code Henri Hkkinen MOC support hinokind support negative values in human_readable() Jaromir Smrcek APC UPS daemon support Jason Mitchell developer UTF8 fix Source clean up Jason Tan developer debian package maintainer Joe Myre - developer jack_mort - gentoo forums $tab patch Jarmo Hekkanen SETI stuff Jeremy Burch $cached and $buffers JL Farinacci pad_percents Johannes Winkelmann disk I/O on linux more consistent cpu freq handling on linux capitalize Hertz in cpu frequeny jolapache maildir format Jonas Koelker reload on SIGHUP patch pad percantages fix patch Joshua Gerrish mpd password patch Jrgen P. Tjern Restores default settings before loading new config file in SIGHUP Some cleaning and commenting apparently :) SIGHUP config file reload Kapil Hari Paranjape ibm_volume patch kFreeBSD support patch realtime clock patch sysfs battery patch mail_spool patch Kevin Lyles add long options patch add cpu separate option patch add time to top patch simplify round_to_int patch goto width fix patch offset width fix patch individual diskio patch short_units & human_readable patch killfire fs_used_perc and fs_bar_free patch Lars Kotthoff $loadgraph, show_graph_scale patch Lassi Selander XMMS2 patch XMMS2 fixes Lauri Hakkarainen Some translating, web and other stuff Leszek Krupiski Battery number for ACPI battery Load average bug fix Lucas Brutschy MLDonkey patch if constructs patch Marcus Huesgen battery_bar fix Markus Meissner NVIDIA Graficcard support with libXNVCtrl patch Michal Januszewski hddtemp support Michal Ziabkowski $if_up memleak fix Miroslav Lichvar move audacious thread init to update_audacious() patch x86_64 freq_dyn patch buffer overflow in update_net_stats() patch Moncelier Camille METAR patch Morgan Veyret own_window_type dock patch Nattfodd Fixed top_mem dupes nathanj439 MPD time fix Nikos Ntarmos FreeBSD total memory patch norsetto fix SIGUSR1/SIGHUP segfault Pascal Eberhard graph and bar fix for right alignment Peter Tarjan IBM acpi support patch SMP support for freq stuff CPU voltage patch Petr Holub fix autotools on FreeBSD in autogen.sh Improved battery readout on FreeBSD Philip Kovacs tcp port monitor with hashing functionality Audacious, Xmms, BMP, Infopipe stuff Various Xlib changes, e.g. own_window hints, etc. Phil multiple batteries support tp_smapi support if_up patch fix sysfs crashing patch Psychon a bunch of code cleanups roiban adi hex colour patch Ryan Tandy fs_type patch if_mpd_playing patch Rui Paulo NetBSD support Roland Shoemaker user info patch conky version info patch Roman Bogorodskiy FreeBSD support BMPx support Ryan Twitchell head/tail rewrite patch Mikko Sysikaski prss.c and prss.h Sceptik --quiet patch Stepan Zastupov WiFi signal level detection support on FreeBSD Szymon Boniecki Reads current LC_TIME Thomas Cort CPU frequency patch for alpha Toni exec*/tail/head output evalution Toni Spets hifi OpenBSD support Linux wifi code RSS code (created together with Mikko Sysikaski) Lua scripting Tris Scroll step patch tyir MPD features patch 1319461 Vivenzio Pagliari Some useful patches for port monitoring PowerBook battery patch Walt Nelson $freq fix Warren Dukes libmpdclient warudemaru rss and vsize for top wedge battery time fix for 2.6.24 William DiPlacido Frequency from /proc/cpuinfo Some other SETI stuff zimba-tm alignment none patch zotrix FreeBSD patch for <10 procs Daniel Beler argb visual patch conky-1.10.1/CMakeLists.txt000066400000000000000000000040631262311664100154620ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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 . # cmake_minimum_required(VERSION 2.6) project(conky) # This is the directory for our custom CMake modules. set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) # 'core' CMake stuff include(Conky) # Handle build options include(ConkyBuildOptions) # Do platform checks include(ConkyPlatformChecks) # CPack module for installation tasks include(ConkyCPackSetup) # setup our configuration headers configure_file(${CMAKE_MODULE_PATH}/config.h.in ${CMAKE_BINARY_DIR}/config.h) configure_file(${CMAKE_MODULE_PATH}/build.h.in ${CMAKE_BINARY_DIR}/build.h) # Finally, add some code add_subdirectory(lua) add_subdirectory(data) add_subdirectory(doc) add_subdirectory(src) IF(NOT DEFINED DOC_PATH) set(DOC_PATH "share/doc/${CPACK_PACKAGE_NAME}-${VERSION}") ENDIF(NOT DEFINED DOC_PATH) set(DOC_FILES extras/convert.lua data/conky_no_x11.conf data/conky.conf) set(HTML_PATH "${DOC_PATH}/html") set(HTML_FILES doc/config_settings.html doc/docs.html doc/lua.html doc/variables.html) set(MAN_PATH "share/man/man1") set(MAN_FILES doc/conky.1) install(FILES ${DOC_FILES} DESTINATION ${DOC_PATH}) if(MAINTAINER_MODE) install(FILES ${HTML_FILES} DESTINATION ${HTML_PATH}) install(FILES ${MAN_FILES} DESTINATION ${MAN_PATH}) endif(MAINTAINER_MODE) conky-1.10.1/COPYING000066400000000000000000000007321262311664100137540ustar00rootroot00000000000000Any original torsmo code is licensed under the BSD license (see LICENSE.BSD for a copy) All code written since the fork of torsmo is licensed under the GPL (see LICENSE.GPL for a copy), except where noted differently (such as in portmon and audacious code which are LGPL, and prss which is an MIT-style license). Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al. (see AUTHORS) All rights reserved. conky-1.10.1/ChangeLog000066400000000000000000001342351262311664100145010ustar00rootroot000000000000002010-02-18 * $memwithbuffers object and bar (sf.net #2954143), thanks kingfishr 2009-12-09 * Replaced GHashTable with tr1::unordered_map in tcp_portmon. This means portmon no longer depends on glib. 2009-12-01 * Reenable top objects for all target OS's 2009-11-24 * Added support for max_text_width 2009-11-20 * Allow for mpd connections to use IPv6 2009-11-19 * Added support for $pid_read and $pid_write 2009-11-17 * Added support for $format_time 2009-11-16 * Added support for $pid_threads, $pid_thread_list, $pid_nice, $pid_priority, $pid_time_usermode, $pid_time_kernelmode and $pid_time * Added IPv6 support to $tcp_portmon 2009-11-15 * Added support for $pid_parent, $pid_uid, $pid_euid, $pid_suid, $pid_fsuid, $pid_gid, $pid_egid, $pid_sgid and $pid_fsgid * Added support for $uid_name and $gid_name * Renamed $running_processes to $running_threads * Added real $running_processes * Added support for $pid_vmpeak, $pid_vmsize, $pid_vmlck, $pid_vmhwm, $pid_vmrss, $pid_vmdata, $pid_vmstk, $pid_vmexe, $pid_vmlib, $pid_vmpte 2009-11-14 * Added support for $pid_state and $pid_state_short * Added support for $cmdline_to_pid * Make it possible to use other vars as arguments for the $pid_'s 2009-11-13 * Add $conky_user_time (sf.net #2830919) * Drop adt746x objects * Added support for $pid_chroot * Added middle_middle alignment support 2009-11-12 * Added support for $pid_environ_list, $pid_exe, $pid_openfiles, $pid_stdin, $pid_stdout and $pid_stderr 2009-11-11 * Added support for $pid_cmdline, $pid_cwd, $pid_environ 2009-11-10 * Fix $if_mpd_playing and $mpd_percent when you stop playing a song, thanks Sakari Matikka 2009-11-09 * Fix $scroll only scrolls once 2009-11-08 * Fix segfaults and memleaks in curl * Fix building with metar but without xoap 2009-11-07 * Added support for $threads on Linux * Fixed bug in $processes on Linux * Fixed building with --disable-x11, --disable-xft, --disable-lua, --disable-ncurses and --disable-iostats * Added ncurses to the "-v" output when necessary 2009-10-25 * Fixed loadavg and loadgraph argument parsing and corrected it's documentation. 2009-09-11 * Fixed configure test failure. Tolua test program couldn't find lua libraries (even though they existed) and failed to compile. 2009-09-06 * Rewrite hddtemp support for better scaling. 2009-08-10 * Add day and date data_type to $weather_forecast 2009-08-03 * Added support for $weather_forecast (experimental) 2009-08-01 * Added support for out_to_ncurses 2009-07-31 * Removed alias config option due to brokenness * Added support for $include 2009-07-29 * Add icon data_type for xoap weather 2009-07-23 * Changed xoap parsing method to xpath, in preparation to include forecast data 2009-07-19 * Fixed out-of-tree builds * Update MPD elapsed/progress when stopped (sf.net #2792113) * Overhauled RSS and weather, added $curl 2009-07-18 * Added compilation switch --enable-xoap to be able to use www.weather.com as a source of weather data (this avoids adding libxml2 as a required dependency for users that wish to use noaa and not weather.com) * Added support for X alignment across multi-lined objects (i.e., using $alignr with $exec) * Disabled OpenMP code until GCC's implementation stabilizes * www.weather.com can now be used as well as a source of weather data 2009-07-11 * Added support for $desktop, $desktop_number and $desktop_name (sf.net #2040528) 2009-07-09 * Added support for $swapfree * Improved Lua API (lua_read_parse has been removed in favour of the conky_parse() Lua API call) * Introduced new Lua Cairo and Imlib2 bindings 2009-07-08 * Fixed a couple memory-related bugs 2009-07-06 * Added support for $weather (experimental) 2009-07-04 * Remove newline with comment only lines in TEXT * Improved parsing of graph arguments, removed "log"|"normal" arguments in favour of -l switch 2009-07-01 * Fix escaping of comments in TEXT (sf.net #2813390, thanks Nils) 2009-06-29 * Fix segfault in to_real_path, it's sometimes called with the same source and dest without checking the length, causing a segfault. 2009-06-20 * Use the internal process list for if_running on Linux 2009-06-14 * Fix XMMS2 related crash (sf.net #2806111 and #2805310, thanks Lassi) 2009-06-13 * Added support for $blink * Added support for $to_bytes * Fix segfault due to bad checking of return values for inotify code (sf.net #2804886) * Added 'own_window_type panel' to make Conky behave like a panel (thanks Ole) 2009-06-12 * Added support for per-task I/O statistics - $top_io 2009-06-11 * Added border_inner_margin and border_outer_margin config options, and deprecated border_margin 2009-06-10 * Fix regression with loading of non-Xft fonts (sf.net #2804324) 2009-06-09 * Fixed a regression which causes fonts to not be rendered properly with certain types of windows * Added format_human_readable option (sf.net #2803345, thanks Vincent) * Fix bug in comments within TEXT (where the line contains just '#') (sf.net #2803586), thanks Pavelo * Fix bug in $mails (sf.net #2802529, thanks Nikos) 2009-06-08 * $battery_short can now also display F (full), N (not present),E (empty), U (unknown) * Fix problem that $battery and $battery_short displayed unknown on some systems when the battery wasn't unknown but full 2009-06-06 * Add support for membar,swapbar,cpubar,fs_bar,fs_bar_free,battery_bar, execbar,execibar,lua_bar,entropy_bar,mpd_bar,apcupsd_loadbar and wireless_link_bar * Fix finding IP before first update 2009-06-04 * Add entropy_perc printing the available entropy as percentage * Add read_tcp to print stuff from tcp-sockets 2009-06-03 * Improved Imlib2 cache control by adding a global cache flush option, and per image cache flushing 2009-05-24 * Added fancy new 'temperature gradients' feature for graphs, via the -t switch at the end of graph arguments. * Allow ~/... and $HOME/... paths for more stuff. 2009-06-07 * Conky 1.7.1 released 2009-05-31 * Fix hostname resolution for mpd_host * Made sure that no X11 stuff is in the binary with --disable-X11 2009-05-19 * Added inotify support to reload the config when modified automatically on systems that support it * Added inotify support for reloading Lua scripts automagically 2009-05-17 * Added support for the Lua programming language * Added support for rending images by way of Imlib2 * Patch to fix rounding error with CPU values (thanks Filipe) * Added support for execbar without X 2009-05-16 * Added another builtin config that is used when compiled with --disable-X11 2009-05-13 * Fix segfault when there is no config available 2009-05-12 * Make sure if_gw isn't checked twice 2009-05-11 * Added arguments to hwmon for value precalculation 2009-05-10 * Added support for APC UPS daemon monitoring * Fixed hwmon for kernel 2.6.29 2009-05-09 * Allow the use of '#' for comments within text area (can be escaped with '\#' 2009-05-08 * Only include disp when needed * Made sure update_uname works without X11 2009-05-07 * Fix occasional cpubar segfaults * Added top_name_width config option 2009-05-05 * Added some completely pointless OpenMP optimizations(?) 2009-05-03 * Added Sony VAIO fanspeed info (thanks Yeon-Hyeong) 2009-05-01 * Added diskio_avg_samples patch (thanks Yeon-Hyeong) * Fixed $texeci regression 2009-04-30 * Added $combine, a var that places 2 other vars next to each other, even if they have a output of multiple lines. This also makes the moving of RSS-itemes with $goto (see change from 2009-04-19) no longer necessary. 2009-04-28 * Various XMMS2 updates (thanks Lassi) * Make ALSA mixers available on Linux, and added $if_mixer_mute (thanks 2009-04-19 * Make it possible to place spaces in front of RSS-items as a workaround for the problem that $goto only moves the first RSS-item. This is only a workaround and should be replaced by a permanent fix that makes $goto move all RSS-items ! 2009-04-13 * Fix broken compilation without X11 2009-04-09 * Added default_bar/graph/gauge_size config options (thanks wire64 for the idea) 2009-03-24 * Added eval text object to realise double parsing 2009-03-15 * Added gauge widget patch, sf.net id #2676128 (thanks Aner) 2009-05-01 * Conky 1.7.0 "Hungry Hobo" released! 2009-04-28 * Various XMMS2 updates (thanks Lassi) 2009-04-09 * Fix broken xmms2 compilation (thanks fusetak) * Minor fix for fs_used_perc, fs_free and fs_free_perc (thanks lightpriest) 2009-03-28 * Applied FreeBSD patches (thanks Nikos) 2009-03-16 * Fix bug with wacky netstat values on startup 2009-03-15 * Added extra newline patch, sf.net id #2638601 (thanks Ali) * Disk i/o support on FreeBSD patch, sf.net id #2657227 (thanks Nikos) * Added gauge widget patch, sf.net id #2676128 (thanks Aner) 2009-03-07 * Added alias patch ( sf.net id #2663691 ) changed it to prevent it from overwriting existing environment variables and updated docs, syntaxfiles, ... 2009-03-01 * Added if_updatenr * Rewrite human_readable() to minimise amount of padding * Fix padding in temp_print() * Fix padding of $processes and $running_processes 2009-02-17 * Added $battery_short patch, sf.net id #2300911 (thanks Swoog) * Patch by Kim Holviala sf.net id #2484548: * change the height of execbar and execibar to be the same as other bars have by default (6 pixels) * treat mixer values as percentages as they're usually 0-100 (switch to spaced_print() with pad_percents) * change temp_print() from snprintf() to spaced_print() * remove decimals from temp_print() as none of the current sources can supply values smaller than 1 degree (C or F, doesn't matter) * fix number printing in human_readable() * network $upspeed and $downspeed now use human_readable() * Fix diskio_read/write patch sf.net id #2493084 (thanks Alexander) * Fix nvidia memory frequency reading patch sf.net id #2493134 * Patch to clarify things in conky.conf sf.net id #2548805 (thanks Carpathia). * Fix shown battery status when the battery is not charging any more but is not full charged patch sf.net id #2556056 (thanks Martin) * Extended support for local Maildir patch sf.net id #2561323 (thanks Nicolas) * XMMS2 fix and refactoring patch sf.net id #2579357 (thanks Tamim) * Null mpd variables should have an empty string patch sf.net id #2564747 2009-02-15 * Added out_to_x 2009-02-12 * Added overwrite_file and append_file 2009-02-10 * Added out_to_stderr 2009-02-08 * Refactor top code, add top_time to sort by process cpu time (thanks sohalt). 2009-01-04 * Drop --enable-smapi and use --enable-ibm instead * Make ibm-acpi objects optional (--enable-ibm) 2008-12-20 * Add if_match object comparing strings, floats and ints 2008-12-18 * Fix segfault for diskiograph*, note the changed order of arguments * Fix documentation for all graph objects 2008-12-17 * Make gateway objects also detect routes with missing RTF_GATEWAY flag 2008-12-15 * Have a maximum width for all variable length mpd vars * Patch to allow escaping newlines in the config (thanks Itai) 2008-12-14 * Fix disk_protect for linux-2.6.27 (and hopefully above) * Improve behaviour of $pb_battery 2008-12-09 * Add an option to timed_thread_test() to not wait for the interval period (so that IMAP IDLE works better) 2008-12-08 * Fix runtime debugging macros again * Big hddtemp rewrite * Remove README from git and ignore it * Remove obsolete documentation 2008-12-07 * Removing $freq_dyn and $freq_dyn_g due to license issues (see sf.net tracker bug #2166612) * Allow more than 9 CPUs for CPU stats (bug 2155500) * Fix broken $execbar (bug 2133709) * Don't put unit with hddtemp values for consistency (bug 2133107) * Limit $battery_percent to 100 (bug 2145006) * Fix runtime debugging macros * Make unit of all temperature objects selectable * Make Conky in dock mode a withdrawn window 2008-12-06 * Switching from svn to git repository. The repo can be viewed from http://git.omp.am/?p=conky.git;a=summary and you can clone the repo with: git clone git://git.omp.am/conky.git * Fix for wrong usage of strncat (thanks Pavol) * Adds a variable if_xmms2_connected to hide objects when xmms2d is not running (thanks Lassi) * Fix for buffer overflow with $execi (thanks Cesare) * Fetch volume through Audacious API (thanks Erik) 2008-12-06 * Removed duplicate sanity check for diskio 2008-11-30 * Added runtime debugging output 2008-11-29 * Added template support 2008-10-08 * Applied OpenBSD patches * Added $if_mpd_playing patch (thanks tarpman) 2008-09-24 * Introduced (buggy) support for IMAP IDLE * Added support for MOC (the console audio player) (thanks henux) * Added scroll step patch (thanks asto) 2008-09-11 * Maybe fix missing include bug (http://bugs.gentoo.org/show_bug.cgi?id=235233) * Improve timed_thread interval timing * Improve Conky's overall interval timing * Added small patch to support negative values (such as negative disk capacity) (thanks hinokind) 2008-09-10 * Improved hddtemp support 2008-09-07 * Fixed bug with freq_dyn on x86_64 (thanks Miroslav) * Fixed buffer overflow in update_net_stats() (thanks Miroslav) * Small fix for nvidia mem freq (thanks Cezary) 2008-08-14 * Conky 1.6.1 released * Fix compile error when MPD support not enabled 2008-08-05 * Add option to specify number of retries for IMAP/POP3 stuff (via -r) 2008-08-03 * Smaller $nvidia improvements 2008-07-29 * Added missing header to package dist 2008-07-21 * Conky 1.6.0 released 2008-07-16 * Fixed bug with $if_empty and $mpd_* vars (sf.net #2008752) 2008-07-06 * Made log/normal argument for graphs optional 2008-07-03 * Solve linking on problems on some systems (like Debian's Lenny) 2008-07-01 * Add libgnu convenience lib, modules stdio and getaddrinfo. * Configure option for mathfunctions 2008-06-29 * Fixed missing entries in Makefile.am * Get rid of obsolete gethostbyaddr and getservbyport 2008-06-28 * Added sysfs AC adapter support patch (thanks Byron) * Added support for EVE-Online skill monitoring (thanks Asbjørn) 2008-06-25 * new variables smapi_bat_temp and smapi_bat_power * improved docs for freq_dyn* variables 2008-06-21 * Replaced the global text_object array and count with a text_object_list * Renamed various vars * Removed redundancy in various parts 2008-06-20 * Use output_methods instead of out_to_console * Made some functions non-inline to compile with gcc 4.2 and higher 2008-06-19 * Fixed compilation issues with --enable-testing * Refactored format_seconds and format_seconds_short * Changed addr to print "No Address" when there is no address * Removed redundancy in various parts * Split help output into a separate function 2008-06-17 * Made defines of magic numbers 2008-06-16 * Moved audacious defs into header * Fixed 3 bufferoverflows in a struct utmp in users.c 2008-06-09 * Graphs can now be logarithmic (except execigraph) 2008-06-08 * Bugfix, $memgraph wasn't working and needed docs * Code for $lines and $words * Bugfix, $execgraph showed 0-0 instead of 0-100 values 2008-06-07 * Case-insensitive values for if_up_strictness * Fix bug where DEV_NAME can read uninitialised memory * Fix bug where ${if_mounted /}foo$endif prints foo on 1 line for each update instead of just 1 line 2008-06-06 * Code for $scroll * Code for $memfree and $memeasyfree 2008-06-05 * Fix bug where conky prints everything twice to STDOUT when out_to_console is enabled * Code for show_graph_range * Code for $monitor and $monitor_number 2008-06-04 * Fix bug where conky tries to free a already freed pointer when you use gw_iface with a empty routingtable in linux * Fix bug where conky tries to tries to display deleted chars in a string (chars followed by a backspace-char) causing strange output. 2008-06-03 * Added NVIDIA Graficcard support patch (thanks meissna) * Added --quiet patch (thanks sceptik) 2008-05-30 * Simplified docs for color0-9 config settings and variables. * Improved $if_up for configurable behaviour. 2008-04-29 * own_window_type dock patch (thanks Morgan). * Fix for $if_up memleak (thanks Micha¿). 2008-04-12 * Added patch for the following (thanks larsko): * New $loadgraph to show a graph of load averages, * add "show_graph_scale" option to turn off/on the showing of the current max value for the graph, * minor code fixes, * update nano and vim syntax highlighting stuff. 2008-04-10 * Getting rid of goto usage throughout code. * Fix bug due to usage of gethostbyname() in threads (which is not reentrant) by using gethostbyname_r() when available. * Added patch for battery_time problem on 2.6.24 (thanks wedge). * Added patch to fix broken xmms2 stuff (thanks sleipner). * Added patch to fix SIGHUP/SIGUSR1 segfault (thanks norsetto). * Added patch to improve $if_up (thanks Aseem). 2008-04-02 * Added patch to use mail_spool correctly (thanks Kapil) * Replacing strdup() with strndup() throughout 2008-04-01 * Fixed segfault when configuration doesn't contain TEXT block (thanks Pippijn). 2008-03-31 * Conky 1.5.1 released. * Added --enable-testing configure option to use insane compiler flags. 2008-03-30 * Added mem_res and mem_vsize to $top. * Improved parsing of $diskio*, $disk_protect and $ioscheduler args. 2008-03-29 * Increased C99 compliance. * Fixed potential segfault in get_ioscheduler(). * Implemented upwards path traversal for fs_type. * Fixed bug in libmpdclient that caused file descriptors to be left open. * Cleaned up output of battery_* vars. 2008-03-28 * Fixed messed up percentages (fs_free_perc, fs_used_perc, mpd_percent, battery_percent). 2008-03-24 * Fixed for specifying a non-existent configuration file. * Added disk_protect. * Fixed too many open files bug in laptop_mode. * Fixed reading interface adresses. * Fixed battery_bar default size. 2008-03-23 * Fixed compilation with --disable-x11. * Fixed linux.c compilation problem due to (suspected) broken linux headers. * $battery_bar sysfs fix (thanks Marcus). 2008-03-22 * Conky 1.5.0 released. * Smapi review: improved code, fixed memleaks and smapi_bat_perc when using pad_percents. * Fixed spaced_print, so pad_percents should now work as expected. * Removed a line of dead code. * Added support for displaying the default gateway. * Support displaying current laptop_mode. * Per-disk IO scheduler information now available. * Support printing current nameservers. 2008-03-20 * Added CRLF characters to POP3 and IMAP stuff (should play nicer with some servers now). * Added preliminary support for parsing the output of external commands (via $execp and $execpi). * Applied FreeBSD total memory patch (thanks Nikos). 2008-03-19 * Fixed a number of small memory leaks. * Performed some minor profiling on Conky; reduced text_buffer_size default to 128 bytes to improve performance. * Fixed some minor bugs introduced by new patches. 2008-03-17 * Applied 12 patches: 1) sysfs battery support (for Linux >=2.6.24) (thanks Kapil) 2) Improved audacious support patch (thanks Miroslav) 3) tp_smapi support patch for IBM laptops (thanks Phil) 4) user info patch (thanks Roland) 5) added conky build info patch (thanks Roland) 6) added if_up patch (thanks Phil) 7) added reload on SIGHUP patch (thanks Jonas) 8) added pad percentages patch (thanks Jonas) 9) added fs_type patch (thanks Ryan) 10) added xmms2 fixes patch (thanks Lassi) 11) fix sysfs crash patch (thanks Phil) 12) multiple ip patch ($addrs). * Added more alignment support (top_middle, bottom_middle, middle_left, and middle_right). 2008-02-08 * Applied 2 patches: 1) Add diskio for individual devices. 2) Improved output of units, added "short_units" option. 2008-01-05 * Applied some more submitted patches: 1) Add long forms of (most of) the command-line options. 2) Added an option (top_cpu_separate) that emulates top's "separate cpus" option. Processor usage is shown as a percentage of a single processor on your system, instead of a percentage of all processors combined. 3) Adds a parameter (time) to top and top_mem that will show the cumulative CPU time of a process. 4) Simplified integer rounding. 5) Fixed the window width when a goto is used. 6) Fixed the window width when an offset is used. (thanks Kevin Lyles). 2007-12-31 * Applied submitted patches: 1) to suport Debian's kFreeBSD; 2) to use realtime clock in timed threads and 3) to fix get_ibm_acpi_volume zero value bug (thanks Kapil Hari Paranjape). 2007-11-22 * Conky 1.4.9 released. 2007-11-18 * Added Gentoo USE flag audacious-legacy for Audacious legacy support. 2007-11-16 * Added support for Audacious 1.4.0 and legacy versions via --enable-audacious=yes|no|legacy. 2007-11-14 * Fix compilation error with --disable-x11 (bug #1830373). * Bump doc stylesheet from 4.3 to 4.4. 2007-10-31 * Fix mpd_smart bug #1822773. 2007-10-23 * Externalize default config file: ${sysconfdir}/conky/conky.conf 2007-10-21 * Initialize music_player_interval so built-in .conkyrc actual works. * Lower timed_thread minimum timing interval from 50 usecs to 10 usecs. * Separate timed thread asserts for clarity. * Remove ${tail /var/log/Xorg.0.log} from default text. * Update vim/nano syntax files. 2007-10-18 * Conky 1.4.8 released. 2007-10-17 * doc/man fixes 1810328 & 1813483. * struct alignment patch 1812924 (sohalt). 2007-10-02 * Multiple mailbox patch (thanks Ben Kibbey). 2007-09-28 * Small fix for $ibm_volume (thanks Kapil Hari Paranjape). * Patch so $tail can read from a fifo file descriptor (thanks Ben Kibbey). 2007-09-01 * Improved performance slightly. * Added 'music_player_interval' config option to specify an update interval for music player threads (currently honored by mpd and audacious). * Fixed some minor memory leaks associated with SIGUSR1. * Zero out imap and pop3 stuff when the connection fails. 2007-08-31 * _Really_ fix mpd SIGPIPE issues. * Fix timed thread race condition, seen esp. on new kernel scheduler (cfs). * Fix $audacious_title not being displayed when no length argument indicated. 2007-08-30 * Conky 1.4.7 released. * Check for pkg-config >=0.19. * Use timed_thread for mpd. 2007-08-27 * Fixed issue with SIGPIPE and mpd. * Updated COPYING (with more clarifications). 2007-08-14 * Updated vim/nano syntax files. 2007-08-12 * Added $hwmon var, similar to $i2c and $platform. 2007-08-12 * Added var $platform which is similar to $i2c and accommodates the conversion of many devices from /sys/bus/i2c/devices to /sys/bus/platform/devices. * Removed config item post_21_kernel since it forced all i2c device lookups to go to /sys/bus/platform/devices and some people may need a mix of both i2c and platform devices. 2007-08-10 * Clarifying licensing 2007-08-08 * RSS support * Wireless support for Linux 2007-08-05 * Conky 1.4.6 released * Updated to libmpdclient 0.13.0 * Added 'post_21_kernel' config param to specify kernels 2.6.22 and newer so i2c works properly 2007-08-04 * Fixed potential issue on FreeBSD when nprocs < 10 (thanks zotrix) * Added support for multiple batteries when using acpi (thanks Phil) * a bunch of code cleanups (thanks Psychon) * added max length paramater to mpd_title (thinks fow) * a number of small bug fixes 2007-07-15 * Fix PID display, patch #1753934. thanks sohalt. * Fix displaying 4 GB traffic after reloading network driver, patch #1754260. thanks sohalt. 2007-06-21 * Right-justify top/top_mem vars (pid/cpu/mem} so they align on the decimal. 2007-04-25 * Added color[0-9] variable patch (thanks jieryn) 2007-04-05 * Added if_empty patch (thanks Erik) * Added if_existing patch for string matching (thanks cromka) * Added hwmon support (thanks flitsch) * Some xmms2 updates (thanks sleipner) * Added $battery_percent and $battery_bar (thanks akash) 2007-02-25 * OpenBSD support added to Conky (thanks hifi) * Updated mboxscan stuff (thanks calmar) 2007-02-25 * Created branch/1.5 copy of trunk/conky1. Removing all experimental network code from trunk/conky1. 2007-02-14 * Include missing mboxscan.h in conky.h. * Fixed signedness warnings in conky.c. 2007-02-11 * Added buffer_text_size option to change the size of the buffer for things like $exec, $tail, et cetera * Added $mboxscan which lets you display the Subject and From fields from recent email in an mbox file * Disambiguated (is that a word?) $cpu docs 2007-01-14 * Fallback to gettimeofday() when clock_gettime () not available (mac os). 2007-01-09 * API change (timing in milliseconds) for dexter_timedsampler_new (). 2007-01-07 * Add config.rpath (created by gettextize -copy) to distribution to satisfy AM_ICONV. * Clean up some warnings; remove ftp.[ch] from src/Makefile.am. 2006-12-29 * Update svn ebuild to new sourceforge url scheme. - requires deletion of existing wc: rm -rf /usr/portage/distfile/svn-src/conky/ * Added head/tail rewrite patch (thanks Ryan Twitchell) * Added diskio read/write sf.net patch 1542880 (thanks Blondak) 2006-12-26 * Clear conky vars on disconnect/failure to open files. 2006-12-23 * Updated to libmpdclient 0.12.0 2006-12-22 * client/server infrastructure and prototype for linux only (so far): - requires libdexter (http://sourceforge.net/projects/libdexter) and the dxt-sysinfo plugin (svn only at the moment). * new config items: - dexter_client yes/no - dexter_server yes/no - dexter_config /path/to/libdexter/config (default: $HOME/.dexterrc) - own_window_class (default: Conky) - replaces wm_class_name - own_window_title (default: - conky) * removed config items: - wm_class_name (use own_window_class, same function) * configure changes: --disable-network (default=yes) with auto-detection for libdexter. - remove useless --enable-proc-uptime (PROC_UPTIME never referenced). HAVE_SYSINFO and others determine if /proc/uptime is used. - silently disable xft, double-buffer and xdamage if no x11. - change enable/disable labels to reflect defaults accurately. - simplified compile-based checks for sysinfo/getloadavg and by moving them into AC_CHECK_FUNCS. * allow decorated, own_window=yes windows to be given input focus by WM: - do not pass button clicks through to desktop in this scenario as conky immediately loses focus. 2006-12-13 * Clarify LGPL license on timed_thread modules. * Update NEWS files. 2006-12-12 * Split battery variable into two: battery, e.g. "charging 75%" and battery_time, e.g. "3h 15m". * Conky 1.4.5 released. 2006-12-11 * Close pop3/imap sockets. * Fix outstanding battery issues. 2006-12-10 * Fix peek table bug with new portmon code. 2006-12-09 * Replaced hash module used by libtcp-portmon with GLib's GHashTable, due to licensing issue noted by Fedora Core packagers. * Eliminated config items: min_port_monitors, min_port_monitor_connections * Added config item: max_port_monitor_connections 2006-11-30 * Added $entropy_avail, $entropy_poolsize and $entropy_bar for the crypto freaks. Idea suggested by Perttu Luukko in feature request 1497050. * Added max length specifier to audacious_title. Closes feature request #1600631. 2006-11-28 * Rearrange retry attempts in pop3 and imap code, removing sleep() calls which cause the whole process to sleep, not just the thread. 2006-11-22 * Added max_specials config item with default 512. This should close bug #1574523 for real this time. Thanks to John Harrigan for this one. 2006-11-21 * Changed autotools for subversion versioning. * Updated svn ebuild for gentoo. * Documentation updates for clarity, i.e. close bug #1599041. 2006-11-20 * fix compile error with --disable-xdamage when Xdamage.h not present. 2006-11-18 * fix bug where present rate var was not being read from acpi battery state file: /proc/acpi/battery/%s/state. 2006-11-15 * Change linkstatus display for use_spacer. Closes bug #1577580. 2006-11-14 * Fix compile error with --disable-x11. * Add new timed thread abstraction routines. * Convert thread activity to timed threads, including texeci, imap, pop3, audacious. * Change memory vars from unsigned long to unsigned long long to fix reported overflow, e.g. swapmax >= 4Gb. 2006-11-13 * Use pthread_cond_timedwait() instead of sleep() in audacious thread. Will convert all worker threads to this timing method. 2006-11-12 * Fix freebsd build error. * Minor changes to syntax files. * Conky 1.4.4 released. 2006-11-11 * Add max_user_text to documentation. * Fixed BadWindow bugs (#1568366, #1588384). 2006-11-10 * Remove on_bottom and xmms_player completely. * Closed ibm_temps bug #1591609. * Conky 1.4.3 released. 2006-11-09 * Updated vim and nano syntax coloring scripts. * Added extras/ dir with syntax stuff to distribution tarball. 2006-11-08 * Added new config item 'max_user_text' with default 16384, twice as large as previous hard-coded default of 8192 bytes. Increase as needed to accomodate large config files with a great deal of text. This closes SF bug #1574523. 2006-11-07 * Changes to configure.ac for pkg-config on x11/xext/xdamage, with fallback to conventional checks. * Fixed segmentation fault on SUGUSR1 bug. * Commented out Imlib2 from configure.ac since it's only partially implemented. 2006-11-04 * Removed broken mldonkey and seti support. * Added Hellf[i]re's nano syntax coloring script to svn. 2006-11-03 * Removed support for Xmms, BMP and Infopipe from conky. The Xmms and Bmp players are projects are dead and distros such as Gentoo are slating them for removal. * Added support for Audacious using new audacious vars. 2006-10-18 * Implement WiFi signal level detection on FreeBSD (patch by Stepan Zastupov) 2006-10-04 * Fix buffer overflow in parsing LC_ALL, LC_CTYPE and LANG environment variables and fix crash for users with locale name longer than 10 chars (repored by Michael Schwendt) 2006-09-30 * --enable-debug added. * prevent libtool from adding its default CFLAGS 2006-09-28 * Use pkg-config instead of xft-config. * Fix last line bug which had required padding text with extra blank line to see text on last line. 2006-09-01 * Fix type-punning and "differ in signedness" warnings seen with gcc-4.1 -O2. 2006-08-27 * Fix compilation errors when building with --diable-x11; bug #1547164 2006-08-12 * Make configure script print summary info * Make `conky -v` show compiled-in features 2006-08-10 * Added Spock's patches, adding hddtemp, goto and tab variables. 2006-07-13 * Added tztime patch to show time in arbitrary time zones (thanks Ram Yalamanchili) 2006-06-07 * Small battery fix (thanks Nexox, sf.net patch 1500014) * Fixed order of variables/objects in docs (thanks Peter Tarjan) 2006-05-27 * Fixed a bug with $font 2006-05-24 * Xdamage support for composite and pals 2006-05-23 * CPU voltage support via $voltage_mv and $voltage_v (thanks to Peter Tarjan for the patch) 2006-05-21 * SMP support for $freq and $freq_g (thanks to Peter Tarjan for the patch) 2006-05-17 * Fixed issue with graphs not reaching all the way to the borders (sf.net bug 1470480) * Cleaned up units 2006-05-15 * Conky 1.4.2 released 2006-05-13 * GNU Iconv support added, new objects $iconv_start and $iconv_stop * Added some safety to the threading code 2006-05-09 * Changed $font behavior so that the font persists past the next newline. It can be set back to the default with $font with no args. (closes bug 1478676 on sf.net) 2006-05-08 * Added simple POP3/IMAP mail clients 2006-04-23 * Added support for PowerBook batteries * Fixed broken $if/$else stuff 2006-04-15 * Added patch from Peter Tarjan to add support for IBM ACPI * Added xmms2 patch from Lassi Selander (sf.net patch 1469523) 2006-04-11 * Removed sa_restorer crap (may fix some compile errors for some people) 2006-04-07 * Added patch for adt746x fan/cpu speed for kernel >=2.6.12 2006-03-30 * Added patch to support new port monitor REMOTESERVICE peekable. 2006-03-29 * Scan port numbers as short. Fixes debian bug# 359974. 2006-03-25 * Added XMMS2 patch 1456203 from Lassi Selander * Added FreeBSD battery patch 1456008 from Petr Holub 2006-03-21 * Fixed ${top(_mem)} related code on FreeBSD (with help of Petr Holub ) 2006-03-15 * Removed bmp-infopipe dependency from 1.4.1 and 1.9999 ebuilds for Gentoo (Gentoo bug# 125226). * Fixed subversion ebuild for conky1 (1.9999) so it pulls the new trunk path for conky1. 2006-03-12 * FreeBSD cpu info patch * Conky 1.4.1 released 2006-03-07 * Fixed issue where some WM's don't control conky own_window windows. * Added newly-updated vim file detection and syntax hilighting files to svn. * Fixed issue with graphs resetting colours (sf.net bug #1420473) 2006-03-06 * Fixed battery problems when charged * MPD code handles broken pipe now, instead of just killing conky * Switch from CVS to SVN. Thanks SourceForge. 2006-03-05 * Added patch to make $cpu stuff work on alpha (thanks Thomas Cort) http://bugs.gentoo.org/show_bug.cgi?id=122637#c3 * Stop using override_redirect true -- conky back under WM control when using 'own_window yes'. * Fixed texeci breakage when forking to background is on 2006-02-14 * Drastically simplified own_window=yes window creation code. * on_bottom and wm_class_name deprecated (they do nothing) 2006-02-13 * Fixed typo bug in portmon code that caused incorrect monitor data to be displayed. 2006-02-12 * Conky 1.4.0 released 2006-01-27 * Cleaned up texeci code 2006-01-26 * Added freedesktop.org extended window manager hints (EWMH) for window type NORMAL and state's STICKY/SKIP_PAGER/SKIP_TASKBAR. Fixes stacking order issues with freedesktop-compliant wm's, such as XFCE4+. 2006-01-25 * Fixed stupid graph code (it still sucks) sf.net bug 1372962 * Fixed $if_* stuff, sf.net bug 1401338 and 1400854 * Fixed xmms.c code to load glib 1.2 shared object lib. 2006-01-11 * Added xmms version 1 support. * Added bmp through 0.9.7.1 support. * Added config item xmms_player: none, xmms, bmp, audacious or infopipe. 2006-01-07 * Added Audacious media player support. 2006-01-06 * Fixed infopipe bug (select() affects timer as a side effect on Linux!) 2006-01-05 * Added draw_graph_borders option * Added XMMS/BMP InfoPipe plugin support 2006-01-01 * Conky 1.3.5 released 2005-12-31 * Fixed bug with use_xft causing ignorance of font selection (sf.net bug 1387564) * Fixed issue with parsing of hex values for colours 2005-12-30 * Added BMPx (http://beep-media-player.org/) support 2005-12-14 * Fixed issues with execi stuff 2005-12-10 * Added sf.net patch 1374576 2005-12-05 * Fixed sf.net bug 1367745 2005-11-30 * Fixed sf.net bugs 1369607, 1367735 and gentoo bug 113921, all variations of the same array out of bounds issue. * "Fixed" code in fs.c and conky.c to make fs stats match those displayed by df (affects reporting against ext3 filesystems only) 2005-11-27 * new code in linux.c and top.c to calculate CPU % correctly on 2.6 kernels. 2005-11-24 * Fixed gentoo bug# 113219 2005-11-23 * Added #define/#undef SIGNAL_BLOCKING in conky.c for experimenting with synchronous signal processing. set to #undef for previous behavior. * Use POSIX signal api's, not the ANSI signal(). 2005-11-22 * Fixed IP address bug (sf.net bug 1359055) 2005-11-16 * Conky 1.3.4 released 2005-11-12 * Replaced bitwise copy of tcp_connection_t with function copy_tcp_connection(). * Changed call interfaces for get_acpi_fan(), get_acpi_ac_adapter(), get_freq(), get_freq_dynamic(), get_adt746x_cpu(), get_adt746x_fan(), eliminating all mallocs. pkovacs. See bug 1355470. 2005-11-11 * moved hash sizing code into portmon lib, where it belongs * More mem leaks fixed. 2005-11-10 * Added config items min_port_monitors / min_port_monitor_connections 2005-11-09 * Cleaned up top code, bug fixes * Fixed some memory leaks 2005-11-08 * Fix bug# 1351686. Patch by boojit. * Fixed 1331576 (I think) with bad cpu usage reporting 2005-11-01 * Documentation updates for compiling and port monitoring * Removed cairo stuff (it's useless) 2005-10-31 * Added statfs sf.net patch 1344493 2005-10-30 * Added tcp port monitor support (pkovacs) 2005-10-28 * Added WM_CLASS patch from sf.net patch 1340825 2005-10-21 * acpi segfault should be fixed (sf.net bug 1330893) * SIGUSR1 bug fixed? (sf.net bug 1330914) 2005-10-17 * Ugly MPD mem leak fixed * Other mem leaks fixed * Fixed thing where conky exits if LC_ALL and friends isn't set * Conky 1.3.3 released 2005-10-13 * Conky 1.3.2 released 2005-10-10 * More MPD objects (sf.net patch 1319461) 2005-10-07 * fixed mldonkey bug? sf.net bug 1316531 2005-09-30 * Linkstatus patch from btlee on f.g.o (see http://forums.gentoo.org/viewtopic-p-2765647.html#2765647) 2005-09-29 * Fixed build on FreeBSD for non-i386 * Made it so top_mem doesn't show all the forks of one process 2005-09-27 * Fixed small bug in config parsing (thanks robgrady, bug 1306032) 2005-09-24 * Fixed bug where graphs/bars don't show when maximum_width is enabled 2005-09-15 * Fixed right-alignment bug thanks to Pascal Eberhard * Applied patch 1291420 from sf.net * Fixed issue with whack graph data * Fixed issue with Conky quitting when a file fails to load 2005-09-11 * Fixed bug with xft and double buffer in own window * 1.3.1 released 2005-09-04 * Misc small bug fixes 2005-09-03 * MPD patch (sf.net patch 1281108) * Fixed graph width bug 2005-08-31 * FreeBSD support was added * 1.3.0 released 2005-08-27 * added threaded execi, $texeci * feature freeze 2005-08-26 * Fixed slight vertical misalignment of bars/graphs (sf.net 1273994) * Diskio fixes (sf.net 1274140) * $alignr and $alignc now have 25% more goodness! (sf.net bug 1273905) * Far better SMP support * Added support for i8k kernel driver, parsing information for dell inspiron laptops found in /proc/i8k (sf.net request 1256058) 2005-08-25 * More own_window fixes * applied disk io patch (sf.net patch 1271691) * applied $freq fixes patch, adds new $freq_dyn (sf.net patch 1271633) * removed units from $freq* output * fix for graph config parsing * Added $head, fixed mem leak with $tail 2005-08-24 * More configure and makefile updates * Added scale arg for net graphs * Fixed bug in own_window stuff--amazing fake transparency now works properly * added own_window_colour, own_window_transparent 2005-08-23 * Added maximum_width 2005-08-22 * Added $execibar and $execigraph 2005-08-21 * Moved source into src/, moved docs into doc/ * Updated makefiles 2005-08-20 * Applied patch from zimba-tm, closes patch 1260225 * Fixed ugly gradient bug. closes bug 1255608 * Added $voffset * Removed metar code. It sucked. * Added $acpitempf for amooricans * $tail fixes 2005-08-12 * Multiple unit additions and modifications 2005-08-07 * mpd password patch from Joshua Gerrish * conky can run without X now, use --disable-x11 when configuring ========================================================================= ========================================================================= 2005-08-06 * Conky 1.2 released 2005-08-05 * small fixes * added CVS ebuild, huge thanks to Hopeless for this 2005-08-04 * special thanks to Citizen_X and his patience * Citizen_X pwns * keep shakin' those big 'ol titties * Citizen_X * Citizen_X * Citizen_X * Citizen_X 2005-08-03 * many small fixes, thanks to those who reported problems 2005-08-02 * dramatically improved how conky handles fonts * fixed issues with graph args * fixed shades and outlines 2005-08-01 * stabilized code * added gradients to graphs (very pretty) * things * added $font, yay * feature freeze; only bugfixes now 2005-07-30 * finalized graphing code, see $cpugraph, $memgraph, $execgraph, $downspeedgraph, and $upspeedgraph * added override_utf8_locale option * poop * $tab patch from jack_mort on f.g.o 2005-07-28 * Added new graphing code, such as $cpugraph * small fixes all round * stuff * things * added more mpd objects 2005-07-24 * Conky now has UTF-8 support * Fixed $freq for those with CPU scaling * Fixed the problem with total_run_times * Fixed alignment of bars and lines and stuff * Reduced conky's memory usage (yay!) * Removed top_sort_cpu, added top_mem which sorts by mem usage instead of cpu 2005-07-17 * Fixed a pile of bugs in configure script * Added proper checking for headers in configure script * Made METAR shit threaded so it would stop being retarded, also made it try more then once to update * Added $metar_tempf and ${i2c tempf} for americans 2005-07-16 * Added option for Conky to update N times and quit, see total_run_times in conkyrc.sample * Added metar code for weather info, thanks to somebody on sf.net * Added $alignr and $alignc for right and centre alignment * Added wireless info and IP addr patch, thanks Bobby Beckmann, options $addr and $linkstatus (please test!), as well as fixed a mem leak in this patch * adt746x fix, thanks to dan-h on sf.net * Added mldonkey support patch, thanks Lucas Brutschy on sf.net * Added patch to allow hex colour values, thanks roiban adi on sf.net * Added if constructs patch, thanks Lucas Brutschy on sf.net * Fixed bug in tab code (hopefully for the last time) * Added option to sort by cpu or memory for top, see top_sort_cpu 2005-07-12 * Added fix for battery charged state (thanks to Lukas Zapletal ) ========================================================================= ========================================================================= 2005-07-05 * Conky 1.1 released 2005-07-03 * Added $mpd_bar and $mpd_bitrate * Some minor code cleanups prior to release * Fixed problem with Conky not compiling when XFT disabled * Fixed configure.in problems with Xdbe 2005-07-01 * Fixed memory leak in MPD code * Added new $tail object (see conkyrc.sample) which loves to suck CPU and memory * Fixed more mem leaks 2005-06-30 * Added use_spacer to config * Added $mpd_status * Added small fix for i2c from Filedil on forums.gentoo.org 2005-06-28 * Made it possible to use tabs to right-justify (just add a bunch) * Added ${execbar} (see conkyrc.sample) 2005-06-26 * Added memory % to top output * Added initial cairo backend (it's really quite useless at this stage actually, and I'm not sure if there is even any point to it) 2005-06-25 * Conky now recognizes the tab character correctly * Added simple config option to print to stdout (out_to_console ) 2005-06-23 * Added top output. Check the sample config. * Cleaned up code. 2005-06-22 * Finished MPD support ($mpd_title, $mpd_artist, $mpd_album, $mpd_vol) * Removed NVCtrl code * Added noswap and i2c patches ========================================================================= ========================================================================= 2005-06-21 * Version 1.0. Conky is born from the ashes of torsmo. Main site: http://conky.sf.net/ * Added xwin patch * Added new feature for sample averaging of CPU and net info 2004-12-22 * Version 0.18 released 2004-12-21 * Fixed some double buffer + Xft stuff * Applied X-Mozilla-Status patch (thanks affinity) * Applied NVCtrl patch and modified it a bit (temperature monitoring for nvdia-based graphics cards) (I couldn't test this so it may or may not work or even compile) (thanks Dennis Frommknecht) * Applied fs_used_perc and fs_bar_free patch (thanks killfire [send me mail, I didn't catch your name from sourceforge]) * Applied patch that supports mailbox that is in some 'maildir' format (thanks jolapache [send mail, I didn't catch your name from sourceforge]) * min -> m * Applied pad_percents patch (thanks JL Farinacci) * Fixed some stuff in acpi fan and acpi ac adapter * Optional XFT even when compiled in 2004-11-30 * Applied utime patch (UTC time) (thanks David McCabe) 2004-11-29 * Applied Xdbe patch, this includes double_buffer configuration and -b command line option (thanks Bruce Merry) * Applied some other seti patch, not tested (thanks William DiPlacido) 2004-08-25 * Applied netbsd patch (thanks Rui Paulo) * Applied cpu frequency patch (thanks William DiPlacido) * Applied adt746x patch (thanks Dennis Kaandorp) * Applied some other FreeBSD patch by the same guy 2004-07-31 * Applied FreeBSD patch (thanks Roman Bogorodskiy) 2004-07-25 * Xft support and xftfont configuration * rewrote some stuff, there might be some new bugs in old places 2004-07-24 * I2C divisor from a file (thanks Falk Feuersenger) 2004-07-20 * changed battery thing to ${battery } * SETI@Home stuff (thanks Jarski) 2004-07-05 * changed signal for config file reloading to SIGUSR1 * mixer stuff, $mixer, $mixerl, $mixerr, $mixerbar, $mixerlbar, $mixerrbar 2004-06-03 * maybe fixed acpi battery thing when "present rate" isn't known 2004-06-01 * fixed width for all bars, use like ${cpubar 4,50} 2004-05-25 * Version 0.17 released 2004-05-23 * battery number for ACPI battery (thanks Leszek Krupiñski) * default battery is now BAT0 instead of BAT1, set ${battery 1} if the old battery thing worked * bug fix on load average reporting (thanks Leszek Krupiñski) * outlines to text, draw_outline and default_outline_color configurations and $outlinecolor (thanks adi) * $acpifan, $acpiacadapter, $uptime_short (thanks adi) 2004-05-19 * fixed a bug when starting after Opera (and some other programs) * sticky window * minimum_size 2004-05-18 * added border_width configuration 2004-05-16 * fixed zero length bar bug 2004-05-15 * file system stats, $fs_bar, $fs_free, $fs_free_perc, $fs_size, $fs_used * leaves ACPI temperature file open (faster) * -a option to change alignment on command line 2004-05-14 * fixed ACPI temperature bug * border_margin configuration * ${execi }, execute with specific interval * added possibility to manually set the position (-x and -y options) (thanks to Gwenhael LE MOINE) * $buffers and $cached (thanks to Jeremy Burch) * WM_CLASS when drawing to own window (thanks to Gwenhael LE MOINE) 2004-05-14 * Version 0.16 released 2004-05-13 * $pre_exec, execute a shell command one time * preparsing of text (faster but more memory usage) * less system calls (faster) * APM things to $battery (untested) 2004-05-12 * added $new_mails changed $mails to tell total mail count 2004-05-11 * transparent window, own_window configuration, -o cmdline option * $exec, execute a shell command * $acpitemp, $battery - acpi stuff (not really tested) 2004-05-10 * $loadavg, load average * $mails, unread local mails, mail_spool configuration 2004-05-09 * Version 0.15 released 2004-05-06 * SIGHUP reloads config file (thanks Jørgen P. Tjernø) * Some other stuff conky-1.10.1/INSTALL000066400000000000000000000173441262311664100137610ustar00rootroot00000000000000Basic Installation ================== These are generic installation instructions. NOTE: If you use Gentoo, see the README about using the included ebuild. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. conky-1.10.1/LICENSE.BSD000066400000000000000000000031261262311664100143350ustar00rootroot00000000000000Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al. (see AUTHORS) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. conky-1.10.1/LICENSE.GPL000066400000000000000000001045131262311664100143510ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . conky-1.10.1/NEWS000066400000000000000000000055631262311664100134270ustar00rootroot00000000000000Summary of changes for Conky release 1.4.5: ------------------------------------------- Added config items: - max_specials - max_port_monitor_connections Removed config items: - min_port_monitors - min_port_monitor_connections Added variables: - entropy_avail - entropy_poolsize - entropy_bar Added length specifier to audacious_title. Split battery var into: - battery and battery_time Fixed broken texeci variable. Fixed build error with --disable-x11. Fixed build error with --disable-xdamage. Fixed acpi battery issues. Fixed mem var overflows when >= 4GB. Close pop3/imap sockets properly. Improved internal thread handling. Converted tcp_portmon internal hash to GLib for GPL compatibility. Summary of changes for Conky release 1.4.4: ------------------------------------------- * fix build error for freebsd. * fix BadWindow errors when using own_window_type override or desktop. * minor documentation updates * minor wifi code changes for freebsd. Summary of changes for Conky release 1.4.3: ------------------------------------------- * Removed support for dead projects: Xmms 1, Beep Media Player (BMP) and the Infopipe plugin. - Removed the following related configuration items: - xmms_player - Removed the following related variables: - xmms_bar - xmms_bitrate - xmms_channels - xmms_filename - xmms_frequency - xmms_length - xmms_length_seconds - xmms_playlist_position - xmms_playlist_length - xmms_position - xmms_position_seconds - xmms_status - xmms_title * Removed configuration item: - on_bottom: please use 'own_window_hints below' instead. * Added support for Audacious music player: http://audacious-media-player.org - Added the following related variables: - audacious_bar - audacious_bitrate - audacious_channels - audacious_filename - audacious_frequency - audacious_length - audacious_length_seconds - audacious_playlist_position - audacious_playlist_length - audacious_position - audacious_position_seconds - audacious_status - audacious_title * Added new configuration item: - max_user_text [default: 16384]: specifies the maximum buffer size for user text in the .conkyrc file. Useful for people with enormous config files who were running up against the hard-coded default of 8192 bytes. * Added new variables: - tztime: Local time for specified timezone - hddtemp: interface to hddtemp hard disk temp monitor: http://www.guzu.net/linux/hddtemp.php - goto and tab: additional alignment control - voltage_mv and voltage_v: CPU voltages * Other changes: - added SMP support for $freq and $freq_g - added WiFi signal level detection on FreeBSD - added Xdamage support for X11 - added verbose configuration information to conky -v - added extras directory to tarball with nano and vim syntax coloring scripts. - fixed as many bugs as we could :] conky-1.10.1/README.cmake000066400000000000000000000015231262311664100146570ustar00rootroot00000000000000Hello, there. Using CMake to build Conky is pretty easy, and here is how I do it: 1. From the top level source dir, create a build working dir, and cd into it $ mkdir build $ cd build 2. Run the cmake configuration process $ cmake ../ # pass the path to the sources to cmake OR $ ccmake ../ # you can also use the fance curses interface, or try cmake-gui 3. Compile as usual, and enjoy the out-of-source goodness $ make # make install # if you want There are a number of build options for Conky, and the best way to discover them is to use the ccmake (or cmake-gui) CMake tool for browsing them. Certain Conky build time features (such as doc generation) require third-party applications, which you should be notified of via CMake. In the case of doc generation, you'll need the docbook2X package (available on most distributions). conky-1.10.1/README.md000066400000000000000000000056771262311664100142150ustar00rootroot00000000000000## Conky [![Build Status](https://travis-ci.org/brndnmtthws/conky.png)](https://travis-ci.org/brndnmtthws/conky) **Conky** is a free, light-weight system monitor for X, that displays any kind of information on your desktop. Grab the [latest release from GitHub](https://github.com/brndnmtthws/conky/releases/latest). ### Features Conky can display more than 300 built-in objects, including support for: * A plethora of OS stats (uname, uptime, **CPU usage**, **mem usage**, disk usage, **"top"** like process stats, and **network monitoring**, just to name a few). * Built-in **IMAP** and **POP3** support. * Built-in support for many popular music players ([MPD][], [XMMS2][], [BMPx][], [Audacious][]). * Can be extended using built-in [**Lua**](lua) support, or any of your own scripts and programs ([more](Lua Interface)). * Built-in [**Imlib2**][Imlib2] and [**Cairo**][cairo] bindings for arbitrary drawing with Lua ([more](wiki/Lua-Interface)). ... and much much more. Conky can display information either as text, or using simple progress bars and graph widgets, with different fonts and colours. ### Screenshots [![screenshot](https://github.com/brndnmtthws/conky/wiki/configs/brenden/screenshot-thumb.png)](https://raw.github.com/wiki/brndnmtthws/conky/configs/brenden/screenshot.png) [![screenshot](https://github.com/brndnmtthws/conky/wiki/configs/ke49/screenshot-thumb.png)](https://raw.github.com/wiki/brndnmtthws/conky/configs/ke49/screenshot.png) [![screenshot](https://github.com/brndnmtthws/conky/wiki/configs/jc/screenshot-thumb.png)](https://raw.github.com/wiki/brndnmtthws/conky/configs/jc/screenshot.png) See the [User Configs](https://github.com/brndnmtthws/conky/wiki/User-Configs) section of the wiki for more screenshots and their associated Conky config files. ### Documentation The [GitHub Wiki](https://github.com/brndnmtthws/conky/wiki) serves as a central hub for all of Conky's documentation. Quick links: * [Install](https://github.com/brndnmtthws/conky/wiki/Installation) * [Configure](https://github.com/brndnmtthws/conky/wiki/Configure) * [User Configs](https://github.com/brndnmtthws/conky/wiki/User-Configs) * [Frequently Asked Questions](https://github.com/brndnmtthws/conky/wiki/FAQ) ### License Conky is licensed under the terms of the [GPLv3](LICENSE.GPL) and [BSD](LICENSE.BSD) licenses. [MPD]: http://musicpd.org/ [XMMS2]: http://wiki.xmms2.xmms.se/index.php/Main_Page [BMPx]: http://bmpx.backtrace.info/site/BMPx_Homepage [Audacious]: http://audacious-media-player.org/ [luawiki]: http://en.wikipedia.org/wiki/Lua_%28programming_language%29 [stable-src]: https://github.com/brndnmtthws/conky/archive/1.9.0.tar.gz [devel-src]: https://github.com/brndnmtthws/conky/archive/master.tar.gz [wiki]: https://github.com/brndnmtthws/conky/wiki [lists]: http://sourceforge.net/mail/?group_id=143975 [ircconky]: irc://irc.freenode.net/conky [Imlib2]: http://docs.enlightenment.org/api/imlib2/html/ [cairo]: http://www.cairographics.org/ conky-1.10.1/TODO000066400000000000000000000004041262311664100134050ustar00rootroot000000000000001.x - implement _XROOTPMAP_ID and ESETROOT_PMAP_ID alterative for pseudo-transperency. 2.0.0 - schedule TBD * rewrite core of Conky in C++ * implement new features like a cairo backend, network transparency, and whatever else * distributed functionality conky-1.10.1/changelog2html.py000077500000000000000000000012561262311664100161760ustar00rootroot00000000000000#!/usr/bin/env python import sys if len(sys.argv) <= 1: print >> sys.stderr, "Usage: ./changelog2html.py [changelog file]" sys.exit(1) f = sys.argv[1] blah = 0 print '' for i in open(f).read().splitlines(): # ignore empty lines if i and i[0].isspace(): if not '*' in i: print ' ' + i.strip() else: s = i.split('*', 1)[1].strip() print '
  • ' + s.replace('<', '<').replace('>', '>') else: if blah: print '' print '

    %s

    ' % i.strip() print '
      ' blah = 1 if blah: print '
    ' print '' conky-1.10.1/check_docs.py000077500000000000000000000156101262311664100153640ustar00rootroot00000000000000#!/usr/bin/python # # This script will check the documentation consistency against the code. It # doesn't check the actual accuracy of the documentation, it just ensures that # everything is documented and that nothing which doesn't exist in Conky # appears in the documentation. # # This script also updates the vim and nano syntax files so it doesn't have to # be done manually. # # Requires the ElementTree Python module for the sorting stuff, see: # http://effbot.org/zone/element-index.htm # # You should also install htmltidy, but it's not necessary. # import os.path import re import sys import mmap from datetime import * file_names = dict() file_names["text_objects"] = "src/text_object.h" file_names["conky"] = "src/conky.c" file_names["vim_syntax"] = "extras/vim/syntax/conkyrc.vim" file_names["nano_syntax"] = "extras/nano/conky.nanorc" file_names["variables"] = "doc/variables.xml" file_names["config_settings"] = "doc/config_settings.xml" file_names["lua"] = "doc/lua.xml" file_names["docs"] = "doc/docs.xml" file_names["command_options"] = "doc/command_options.xml" for fn in file_names.values(): if not os.path.exists(fn) or not os.path.isfile(fn): print "'%s' doesn't exist, or isn't a file" % (fn) exit(1) print 'sorting/tidying docs...' # sort the docs by variable/config setting import string import xml.etree.ElementTree as ET vars_xml = ET.parse(file_names['variables']) config_xml = ET.parse(file_names['config_settings']) getkey = lambda x: x.findtext('term/command/option') vars = vars_xml.getroot() vars[:] = sorted(vars, key=getkey) configs = config_xml.getroot() configs[:] = sorted(configs, key=getkey) vars_xml.write(file_names['variables']) config_xml.write(file_names['config_settings']) def tidy(file): command = ['tidy', '-qim', '-xml', '-utf8', '--indent-spaces', '4'] os.system('%s %s 2>/dev/null' % (string.join(command), file)) tidy(file_names['variables']) tidy(file_names['config_settings']) tidy(file_names['lua']) tidy(file_names['command_options']) # # Do all the objects first # objects = [] file = open(file_names["text_objects"], "r") exp = re.compile("\s*OBJ_(\w*).*") while file: line = file.readline() if len(line) == 0: break res = exp.match(line) if res: obj = res.group(1) if not re.match("color\d", obj) and obj != "text": # ignore colourN stuff objects.append(res.group(1)) file.close() print 'counted %i text objects' % len(objects) doc_objects = [] exp = re.compile("\s*.*") print "checking docs -> objs consistency (in %s)" % (file_names["text_objects"]) for var in vars: term = getkey(var) doc_objects.append(term) if ['templaten', 'colorn'].count(doc_objects[len(doc_objects) - 1].lower()): # ignore these continue if doc_objects[len(doc_objects) - 1] not in objects: print " '%s' is documented, but doesn't seem to be an object" % (doc_objects[len(doc_objects) - 1]) print "done\n" print "checking objs -> docs consistency (in %s)" % (file_names["variables"]) for obj in objects: if obj not in doc_objects: print " '%s' seems to be undocumented" % (obj) print "done\n" # # Now we'll do config settings # config_entries = [] file = open(file_names["conky"], "r") exp1 = re.compile('\s*CONF\("(\w*)".*') exp2 = re.compile('\s*CONF2\("(\w*)".*') exp3 = re.compile('\s*CONF3\("(\w*)".*') while file: line = file.readline() if len(line) == 0: break res = exp1.match(line) if not res: res = exp2.match(line) if not res: res = exp3.match(line) if res: conf = res.group(1) if re.match("color\d", conf): conf = "colorN" if config_entries.count(conf) == 0: config_entries.append(conf) file.close() print 'counted %i config settings' % len(config_entries) doc_configs = [] print "checking docs -> configs consistency (in %s)" % (file_names["conky"]) for config in configs: term = getkey(config) doc_configs.append(term) if ['text', 'templaten'].count(doc_configs[len(doc_configs) - 1].lower()): # ignore these continue if doc_configs[len(doc_configs) - 1] not in config_entries: print " '%s' is documented, but doesn't seem to be a config setting" % (doc_configs[len(doc_configs) - 1]) print "done\n" print "checking configs -> docs consistency (in %s)" % (file_names["config_settings"]) for obj in config_entries: if obj != "text" and obj != "template" and obj not in doc_configs: print " '%s' seems to be undocumented" % (obj) print "done\n" # Cheat and add the colour/template stuff. for i in range(0, 10): objects.append("color" + str(i)) config_entries.append("color" + str(i)) objects.append("template" + str(i)) config_entries.append("template" + str(i)) # Finally, sort everything. objects.sort() config_entries.sort() # # Update nano syntax stuff # print "updating nano syntax...", sys.stdout.flush() file = open(file_names["nano_syntax"], "rw+") lines = [] while file: line = file.readline() if len(line) == 0: break lines.append(line) # find the line we want to update for line in lines: if re.match("color green ", line): idx = lines.index(line) lines.pop(idx) # remove old line line = 'color green "\<(' for obj in config_entries: line += "%s|" % (obj) line = line[:len(line) - 1] line += ')\>"\n' lines.insert(idx, line) if re.match("color brightblue ", line): idx = lines.index(line) lines.pop(idx) # remove old line line = 'color brightblue "\<(' for obj in objects: line += "%s|" % (obj) line = line[:len(line) - 1] line += ')\>"\n' lines.insert(idx, line) break # want to ignore everything after this line file.truncate(0) file.seek(0) file.writelines(lines) file.close() print "done." # # Update vim syntax stuff # print "updating vim syntax...", sys.stdout.flush() file = open(file_names["vim_syntax"], "rw+") lines = [] while file: line = file.readline() if len(line) == 0: break lines.append(line) # find the line we want to update for line in lines: if re.match("syn keyword ConkyrcSetting ", line): idx = lines.index(line) lines.pop(idx) # remove old line line = 'syn keyword ConkyrcSetting ' for obj in config_entries: line += "%s " % (obj) line = line[:len(line) - 1] line += '\n' lines.insert(idx, line) if re.match("syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite ", line): idx = lines.index(line) lines.pop(idx) # remove old line line = 'syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite ' for obj in objects: line += "%s " % (obj) line = line[:len(line) - 1] line += '\n' lines.insert(idx, line) break # want to ignore everything after this line file.truncate(0) file.seek(0) file.writelines(lines) file.close() # lastly, update the date in docs.xml file = open(file_names["docs"], 'r+') map = mmap.mmap(file.fileno(), os.path.getsize(file_names["docs"])) d = map.find("") d += 6 # skip over first date stuff map[d:d+10] = datetime.now().strftime("%F") map.close() file.close() print "done." conky-1.10.1/cmake/000077500000000000000000000000001262311664100137775ustar00rootroot00000000000000conky-1.10.1/cmake/Conky.cmake000066400000000000000000000107241262311664100160700ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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 . # #set(RELEASE true) # Set system vars if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(OS_LINUX true) endif(CMAKE_SYSTEM_NAME MATCHES "Linux") if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set(OS_FREEBSD true) endif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if(CMAKE_SYSTEM_NAME MATCHES "DragonFly") set(OS_DRAGONFLY true) endif(CMAKE_SYSTEM_NAME MATCHES "DragonFly") if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") set(OS_OPENBSD true) endif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") if(CMAKE_SYSTEM_NAME MATCHES "Solaris") set(OS_SOLARIS true) endif(CMAKE_SYSTEM_NAME MATCHES "Solaris") if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") set(OS_NETBSD true) endif(CMAKE_SYSTEM_NAME MATCHES "NetBSD") if(NOT OS_LINUX AND NOT OS_FREEBSD AND NOT OS_OPENBSD AND NOT OS_DRAGONFLY) message(FATAL_ERROR "Your platform, '${CMAKE_SYSTEM_NAME}', is not currently supported. Patches are welcome.") endif(NOT OS_LINUX AND NOT OS_FREEBSD AND NOT OS_OPENBSD AND NOT OS_DRAGONFLY) include(FindThreads) find_package(Threads) set(conky_libs ${CMAKE_THREAD_LIBS_INIT}) set(conky_includes ${CMAKE_BINARY_DIR}) add_definitions(-D_LARGEFILE64_SOURCE -D_POSIX_C_SOURCE=200809L) # Standard definitions set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_LARGEFILE64_SOURCE -D_POSIX_C_SOURCE=200809L") if(OS_DRAGONFLY) set(conky_libs ${conky_libs} -L/usr/pkg/lib) set(conky_includes ${conky_includes} -I/usr/pkg/include) endif(OS_DRAGONFLY) # Do version stuff set(VERSION_MAJOR "1") set(VERSION_MINOR "10") set(VERSION_PATCH "1") find_program(APP_AWK awk) if(NOT APP_AWK) message(FATAL_ERROR "Unable to find program 'awk'") endif(NOT APP_AWK) find_program(APP_WC wc) if(NOT APP_WC) message(FATAL_ERROR "Unable to find program 'wc'") endif(NOT APP_WC) find_program(APP_DATE date) if(NOT APP_DATE) message(FATAL_ERROR "Unable to find program 'date'") endif(NOT APP_DATE) find_program(APP_UNAME uname) if(NOT APP_UNAME) message(FATAL_ERROR "Unable to find program 'uname'") endif(NOT APP_UNAME) if(NOT RELEASE) find_program(APP_GIT git) if(NOT APP_GIT) message(FATAL_ERROR "Unable to find program 'git'") endif(NOT APP_GIT) mark_as_advanced(APP_GIT) endif(NOT RELEASE) mark_as_advanced(APP_AWK APP_WC APP_DATE APP_UNAME) #BUILD_DATE=$(LANG=en_US LC_ALL=en_US LOCALE=en_US date) #BUILD_ARCH="$(uname -sr) ($(uname -m))" execute_process(COMMAND ${APP_DATE} RESULT_VARIABLE RETVAL OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${APP_UNAME} -srm RESULT_VARIABLE RETVAL OUTPUT_VARIABLE BUILD_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) if(RELEASE) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") else(RELEASE) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}_pre${COMMIT_COUNT}") endif(RELEASE) set(COPYRIGHT "Copyright Brenden Matthews, et al, 2005-2015") macro(AC_SEARCH_LIBS FUNCTION_NAME INCLUDES TARGET_VAR) if("${TARGET_VAR}" MATCHES "^${TARGET_VAR}$") unset(AC_SEARCH_LIBS_TMP CACHE) check_symbol_exists(${FUNCTION_NAME} ${INCLUDES} AC_SEARCH_LIBS_TMP) if(${AC_SEARCH_LIBS_TMP}) set(${TARGET_VAR} "" CACHE INTERNAL "Library containing ${FUNCTION_NAME}") else(${AC_SEARCH_LIBS_TMP}) foreach(LIB ${ARGN}) unset(AC_SEARCH_LIBS_TMP CACHE) unset(AC_SEARCH_LIBS_FOUND CACHE) find_library(AC_SEARCH_LIBS_TMP ${LIB}) check_library_exists(${LIB} ${FUNCTION_NAME} ${AC_SEARCH_LIBS_TMP} AC_SEARCH_LIBS_FOUND) if(${AC_SEARCH_LIBS_FOUND}) set(${TARGET_VAR} ${AC_SEARCH_LIBS_TMP} CACHE INTERNAL "Library containing ${FUNCTION_NAME}") break() endif(${AC_SEARCH_LIBS_FOUND}) endforeach(LIB) endif(${AC_SEARCH_LIBS_TMP}) endif("${TARGET_VAR}" MATCHES "^${TARGET_VAR}$") endmacro(AC_SEARCH_LIBS) conky-1.10.1/cmake/ConkyBuildOptions.cmake000066400000000000000000000165431262311664100204310ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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 . # if(NOT CMAKE_BUILD_TYPE) if(MAINTAINER_MODE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) else(MAINTAINER_MODE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif(MAINTAINER_MODE) endif(NOT CMAKE_BUILD_TYPE) # -std options for all build types set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}" CACHE STRING "Flags used by the C compiler during all build types." FORCE) set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}" CACHE STRING "Flags used by the C++ compiler during all build types." FORCE) if(MAINTAINER_MODE) # some extra debug flags when in 'maintainer mode' set(CMAKE_C_FLAGS_DEBUG "-ggdb -Wall -W -Wextra -Wunused -Wdeclaration-after-statement -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Winline -Wmissing-noreturn -Wmissing-format-attribute -Wredundant-decls -pedantic -Werror ${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "Flags used by the compiler during debug builds." FORCE) set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -Wall -W -Wextra -Wunused -pedantic -Werror -Wno-format ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Flags used by the compiler during debug builds." FORCE) endif(MAINTAINER_MODE) option(RELEASE "Build release package" false) mark_as_advanced(RELEASE) option(MAINTAINER_MODE "Enable maintainer mode (builds docs)" false) option(BUILD_I18N "Enable if you want internationalization support" true) if(BUILD_I18N) set(LOCALE_DIR "${CMAKE_INSTALL_PREFIX}/share/locale" CACHE STRING "Directory containing the locales") endif(BUILD_I18N) # Some standard options set(SYSTEM_CONFIG_FILE "/etc/conky/conky.conf" CACHE STRING "Default system-wide Conky configuration file") # use FORCE below to make sure this changes when CMAKE_INSTALL_PREFIX is modified set(PACKAGE_LIBRARY_DIR "${CMAKE_INSTALL_PREFIX}/lib/conky" CACHE STRING "Package library path (where Lua bindings are installed" FORCE) set(DEFAULTNETDEV "eth0" CACHE STRING "Default networkdevice") set(XDG_CONFIG_FILE "$HOME/.config/conky/conky.conf" CACHE STRING "Configfile of the user (XDG)") 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 "64" CACHE STRING "Maximum number of network devices") # Platform specific options # Linux only if(OS_LINUX) option(BUILD_PORT_MONITORS "Build TCP portmon support" true) option(BUILD_IBM "Support for IBM/Lenovo notebooks" true) option(BUILD_HDDTEMP "Support for hddtemp" true) option(BUILD_WLAN "Enable wireless support" false) # nvidia may also work on FreeBSD, not sure option(BUILD_NVIDIA "Enable nvidia support" false) option(BUILD_IPV6 "Enable if you want IPv6 support" true) else(OS_LINUX) set(BUILD_PORT_MONITORS false) set(BUILD_IBM false) set(BUILD_HDDTEMP false) set(BUILD_WLAN false) set(BUILD_NVIDIA false) set(BUILD_IPV6 false) endif(OS_LINUX) # Optional features etc # option(BUILD_BUILTIN_CONFIG "Enable builtin default configuration" true) option(BUILD_IOSTATS "Enable disk I/O stats" true) option(BUILD_OLD_CONFIG "Enable support for the old syntax of configurations" true) option(BUILD_MATH "Enable math support" true) option(BUILD_NCURSES "Enable ncurses support" true) if(BUILD_NCURSES) option(LEAKFREE_NCURSES "Enable to hide false ncurses-memleaks in valgrind (works only when ncurses is compiled with --disable-leaks)" false) else(BUILD_NCURSES) set(LEAKFREE_NCURSES false CACHE BOOL "Enable to hide false ncurses-memleaks in valgrind (works only when ncurses is compiled with --disable-leaks)" FORCE) endif(BUILD_NCURSES) option(BUILD_X11 "Build X11 support" true) if(BUILD_X11) option(OWN_WINDOW "Enable own_window support" true) option(BUILD_XDAMAGE "Build Xdamage support" true) option(BUILD_XDBE "Build Xdbe (double-buffer) support" false) option(BUILD_XFT "Build Xft (freetype fonts) support" true) option(BUILD_IMLIB2 "Enable Imlib2 support" false) option(BUILD_XSHAPE "Enable Xshape support" false) else(BUILD_X11) set(OWN_WINDOW false CACHE BOOL "Enable own_window support" FORCE) set(BUILD_XDAMAGE false CACHE BOOL "Build Xdamage support" FORCE) set(BUILD_XDBE false CACHE BOOL "Build Xdbe (double-buffer) support" FORCE) set(BUILD_XFT false CACHE BOOL "Build Xft (freetype fonts) support" FORCE) set(BUILD_IMLIB2 false CACHE BOOL "Enable Imlib2 support" FORCE) set(BUILD_XSHAPE false CACHE BOOL "Enable Xshape support" FORCE) endif(BUILD_X11) if(OWN_WINDOW) option(BUILD_ARGB "Build ARGB (real transparency) support" true) else(OWN_WINDOW) set(BUILD_ARGB false CACHE BOOL "Build ARGB (real transparency) support" FORCE) endif(OWN_WINDOW) option(BUILD_LUA_CAIRO "Build cairo bindings for Lua" false) option(BUILD_LUA_IMLIB2 "Build Imlib2 bindings for Lua" false) option(BUILD_LUA_RSVG "Build rsvg bindings for Lua" false) option(BUILD_AUDACIOUS "Build audacious (music player) support" false) option(BUILD_BMPX "Build BMPx (music player) support" false) option(BUILD_MPD "Enable if you want MPD (music player) support" true) option(BUILD_MYSQL "Enable if you want MySQL support" false) option(BUILD_MOC "Enable if you want MOC (music player) support" true) option(BUILD_XMMS2 "Enable if you want XMMS2 (music player) support" false) option(BUILD_EVE "Enable if you want Eve-Online skill monitoring support" false) option(BUILD_CURL "Enable if you want Curl support" false) option(BUILD_RSS "Enable if you want RSS support" false) option(BUILD_WEATHER_METAR "Enable METAR weather support" false) option(BUILD_WEATHER_XOAP "Enable XOAP weather support" false) if(BUILD_WEATHER_METAR OR BUILD_WEATHER_XOAP OR BUILD_RSS) set(BUILD_CURL true) endif(BUILD_WEATHER_METAR OR BUILD_WEATHER_XOAP OR BUILD_RSS) if(BUILD_WEATHER_XOAP) set(XOAP_FILE "$HOME/.xoaprc" CACHE STRING "Path of XOAP file for weather" FORCE) 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) if(BUILD_HTTP) set(HTTPPORT "10080" CACHE STRING "Port to use for out_to_http") endif(BUILD_HTTP) option(BUILD_ICONV "Enable iconv support" false) option(BUILD_CMUS "Enable support for cmus music player" false) conky-1.10.1/cmake/ConkyCPackSetup.cmake000066400000000000000000000042671262311664100200200ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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 . # set(CPACK_GENERATOR "TGZ;STGZ;DEB") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>=2.10-1), libgcc1 (>= 1:4.4.0)") set(CPACK_PACKAGE_CONTACT "brenden@diddyinc.com") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Brenden Matthews") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION}-${CMAKE_SYSTEM_NAME}-${CPU_ARCH}") set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME}) set(CPACK_STRIP_FILES true) # Version numbering, copyright notice, etc. are taken from the variables # defined in ../CMakeLists.txt. set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}") if(CPACK_GENERATOR MATCHES "NSIS") set(CPACK_NSIS_COMPRESSOR "/FINAL /SOLID lzma") set(CPACK_PACKAGE_EXECUTABLES ${PROJECT_NAME} ${PROJECT_NAME}) endif(CPACK_GENERATOR MATCHES "NSIS") # Source package setup. Compile with "make package_source". set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION}-src") set(CPACK_SOURCE_GENERATOR "TBZ2") execute_process(COMMAND ${APP_UNAME} COMMAND ${APP_AWK} "{print $1}" RESULT_VARIABLE RETVAL OUTPUT_VARIABLE CPU_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) set(CPACK_SOURCE_IGNORE_FILES # Exclude backup files generated by text editors. "~$" # Git dir/files. "\\\\.git.*$" # vim swap files "\\\\..*\\\\.swp$" # Build dir. "build.*$" ) # Enable CPack include(CPack) conky-1.10.1/cmake/ConkyPlatformChecks.cmake000066400000000000000000000337021262311664100207170ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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(FindPkgConfig) include(CheckFunctionExists) include(CheckIncludeFiles) include(CheckSymbolExists) # Check for some headers check_include_files(sys/statfs.h HAVE_SYS_STATFS_H) check_include_files(sys/param.h HAVE_SYS_PARAM_H) check_include_files(sys/inotify.h HAVE_SYS_INOTIFY_H) check_include_files(dirent.h HAVE_DIRENT_H) # Check for some functions check_function_exists(strndup HAVE_STRNDUP) check_symbol_exists(pipe2 "unistd.h" HAVE_PIPE2) check_symbol_exists(O_CLOEXEC "fcntl.h" HAVE_O_CLOEXEC) check_symbol_exists(statfs64 "sys/statfs.h" HAVE_STATFS64) AC_SEARCH_LIBS(clock_gettime "time.h" CLOCK_GETTIME_LIB "rt") if(NOT DEFINED CLOCK_GETTIME_LIB) message(FATAL_ERROR "clock_gettime not found.") endif(NOT DEFINED CLOCK_GETTIME_LIB) set(conky_libs ${conky_libs} ${CLOCK_GETTIME_LIB}) # standard path to search for includes set(INCLUDE_SEARCH_PATH /usr/include /usr/local/include) # Set system vars if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(OS_LINUX true) endif(CMAKE_SYSTEM_NAME MATCHES "Linux") if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set(OS_FREEBSD true) set(conky_libs ${conky_libs} -lkvm -ldevstat) endif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if(CMAKE_SYSTEM_NAME MATCHES "DragonFly") set(OS_DRAGONFLY true) set(conky_libs ${conky_libs} -ldevstat) endif(CMAKE_SYSTEM_NAME MATCHES "DragonFly") if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") set(OS_OPENBSD true) endif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") if(CMAKE_SYSTEM_NAME MATCHES "Solaris") set(OS_SOLARIS true) endif(CMAKE_SYSTEM_NAME MATCHES "Solaris") if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") set(OS_NETBSD true) endif(CMAKE_SYSTEM_NAME MATCHES "NetBSD") if(NOT OS_LINUX AND NOT OS_FREEBSD AND NOT OS_OPENBSD AND NOT OS_DRAGONFLY) message(FATAL_ERROR "Your platform, '${CMAKE_SYSTEM_NAME}', is not currently supported. Patches are welcome.") endif(NOT OS_LINUX AND NOT OS_FREEBSD AND NOT OS_OPENBSD AND NOT OS_DRAGONFLY) if(BUILD_I18N AND OS_DRAGONFLY) set(conky_libs ${conky_libs} -lintl) endif(BUILD_I18N AND OS_DRAGONFLY) 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_IPV6) find_file(IF_INET6 if_inet6 PATHS /proc/net) if(NOT IF_INET6) message(WARNING "/proc/net/if_inet6 unavailable") endif(NOT IF_INET6) endif(BUILD_IPV6) 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_NCURSES) check_include_files(ncurses.h NCURSES_H) find_library(NCURSES_LIB NAMES ncurses) if(NOT NCURSES_H OR NOT NCURSES_LIB) message(FATAL_ERROR "Unable to find ncurses library") endif(NOT NCURSES_H OR NOT NCURSES_LIB) set(conky_libs ${conky_libs} ${NCURSES_LIB}) endif(BUILD_NCURSES) if(BUILD_MYSQL) find_path(mysql_INCLUDE_PATH mysql.h ${INCLUDE_SEARCH_PATH} /usr/include/mysql /usr/local/include/mysql) if(NOT mysql_INCLUDE_PATH) message(FATAL_ERROR "Unable to find mysql.h") endif(NOT mysql_INCLUDE_PATH) set(conky_includes ${conky_includes} ${mysql_INCLUDE_PATH}) find_library(MYSQLCLIENT_LIB NAMES mysqlclient) if(NOT MYSQLCLIENT_LIB) message(FATAL_ERROR "Unable to find mysqlclient library") endif(NOT MYSQLCLIENT_LIB) set(conky_libs ${conky_libs} ${MYSQLCLIENT_LIB}) endif(BUILD_MYSQL) if(BUILD_WLAN) check_include_file(iwlib.h IWLIB_H -D_GNU_SOURCE) if(NOT IWLIB_H) message(FATAL_ERROR "Unable to find iwlib.h") endif(NOT IWLIB_H) find_library(IWLIB_LIB NAMES iw) if(NOT IWLIB_LIB) message(FATAL_ERROR "Unable to find libiw.so") endif(NOT IWLIB_LIB) set(conky_libs ${conky_libs} ${IWLIB_LIB}) check_function_exists(iw_sockets_open IWLIB_SOCKETS_OPEN_FUNC) endif(BUILD_WLAN) if(BUILD_PORT_MONITORS) check_function_exists(getnameinfo HAVE_GETNAMEINFO) if(NOT HAVE_GETNAMEINFO) message(FATAL_ERROR "could not find getnameinfo()") endif(NOT HAVE_GETNAMEINFO) check_include_files("netdb.h;netinet/in.h;netinet/tcp.h;sys/socket.h;arpa/inet.h" HAVE_PORTMON_HEADERS) if(NOT HAVE_PORTMON_HEADERS) message(FATAL_ERROR "missing needed network header(s) for port monitoring") endif(NOT HAVE_PORTMON_HEADERS) endif(BUILD_PORT_MONITORS) # Check for iconv if(BUILD_ICONV) check_include_files(iconv.h HAVE_ICONV_H) find_library(ICONV_LIBRARY NAMES iconv) if(NOT ICONV_LIBRARY) # maybe iconv() is provided by libc set(ICONV_LIBRARY "" CACHE FILEPATH "Path to the iconv library, if iconv is not provided by libc" FORCE) endif(NOT ICONV_LIBRARY) set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARY}) check_function_exists(iconv ICONV_FUNC) if(HAVE_ICONV_H AND ICONV_FUNC) set(conky_includes ${conky_includes} ${ICONV_INCLUDE_DIR}) set(conky_libs ${conky_libs} ${ICONV_LIBRARY}) else(HAVE_ICONV_H AND ICONV_FUNC) message(FATAL_ERROR "Unable to find iconv library") endif(HAVE_ICONV_H AND ICONV_FUNC) endif(BUILD_ICONV) # check for Xlib if(BUILD_X11) include(FindX11) find_package(X11) if(X11_FOUND) set(conky_includes ${conky_includes} ${X11_INCLUDE_DIR}) set(conky_libs ${conky_libs} ${X11_LIBRARIES}) # check for Xdamage if(BUILD_XDAMAGE) if(NOT X11_Xdamage_FOUND) message(FATAL_ERROR "Unable to find Xdamage library") endif(NOT X11_Xdamage_FOUND) if(NOT X11_Xfixes_FOUND) message(FATAL_ERROR "Unable to find Xfixes library") endif(NOT X11_Xfixes_FOUND) set(conky_libs ${conky_libs} ${X11_Xdamage_LIB} ${X11_Xfixes_LIB}) endif(BUILD_XDAMAGE) if(BUILD_XSHAPE) if(NOT X11_Xshape_FOUND) message(FATAL_ERROR "Unable to find Xshape library") endif(NOT X11_Xshape_FOUND) set(conky_libs ${conky_libs} ${X11_Xshape_LIB} ) endif(BUILD_XSHAPE) # check for Xft if(BUILD_XFT) find_path(freetype_INCLUDE_PATH config/ftconfig.h ${INCLUDE_SEARCH_PATH} /usr/include/freetype2 /usr/local/include/freetype2 /usr/pkg/include/freetype2) if(freetype_INCLUDE_PATH) set(freetype_FOUND true) set(conky_includes ${conky_includes} ${freetype_INCLUDE_PATH}) else(freetype_INCLUDE_PATH) find_path(freetype_INCLUDE_PATH freetype/config/ftconfig.h ${INCLUDE_SEARCH_PATH} /usr/include/freetype2 /usr/local/include/freetype2 /usr/pkg/include/freetype2) if(freetype_INCLUDE_PATH) set(freetype_FOUND true) set(conky_includes ${conky_includes} ${freetype_INCLUDE_PATH}) else(freetype_INCLUDE_PATH) message(FATAL_ERROR "Unable to find freetype library") endif(freetype_INCLUDE_PATH) endif(freetype_INCLUDE_PATH) if(NOT X11_Xft_FOUND) message(FATAL_ERROR "Unable to find Xft library") endif(NOT X11_Xft_FOUND) set(conky_libs ${conky_libs} ${X11_Xft_LIB}) endif(BUILD_XFT) # check for Xdbe if(BUILD_XDBE) if(NOT X11_Xext_FOUND) message(FATAL_ERROR "Unable to find Xext library (needed for Xdbe)") endif(NOT X11_Xext_FOUND) set(conky_libs ${conky_libs} ${X11_Xext_LIB}) endif(BUILD_XDBE) else(X11_FOUND) message(FATAL_ERROR "Unable to find X11 library") endif(X11_FOUND) endif(BUILD_X11) pkg_search_module(LUA REQUIRED lua5.2 lua-5.2 lua>=5.1 lua5.1 lua-5.1) set(conky_libs ${conky_libs} ${LUA_LIBRARIES}) set(conky_includes ${conky_includes} ${LUA_INCLUDE_DIRS}) link_directories(${LUA_LIBRARY_DIRS}) if(BUILD_LUA_CAIRO) set(WANT_TOLUA true) 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) pkg_check_modules(IMLIB2 imlib2) set(luaimlib2_libs ${IMLIB2_LIB} ${LUA_LIBRARIES}) set(luaimlib2_includes ${IMLIB2_INCLUDE_PATH} ${LUA_INCLUDE_DIRS}) endif(BUILD_LUA_IMLIB2) if(BUILD_LUA_RSVG) set(WANT_TOLUA true) pkg_check_modules(RSVG REQUIRED librsvg-2.0) set(luarsvg_libs ${RSVG_LIBRARIES} ${LUA_LIBRARIES}) set(luarsvg_includes ${RSVG_INCLUDE_DIRS} ${LUA_INCLUDE_DIRS}) endif(BUILD_LUA_RSVG) if(BUILD_AUDACIOUS) set(WANT_GLIB true) pkg_check_modules(NEW_AUDACIOUS audacious>=1.4.0) if(NEW_AUDACIOUS_FOUND) pkg_check_modules(AUDACIOUS REQUIRED audclient>=1.4.0) pkg_check_modules(DBUS_GLIB REQUIRED dbus-glib-1) else(NEW_AUDACIOUS_FOUND) pkg_check_modules(AUDACIOUS REQUIRED audacious<1.4.0) endif(NEW_AUDACIOUS_FOUND) set(conky_libs ${conky_libs} ${AUDACIOUS_LIBRARIES} ${DBUS_GLIB_LIBRARIES}) set(conky_includes ${conky_includes} ${AUDACIOUS_INCLUDE_DIRS} ${DBUS_GLIB_INCLUDE_DIRS}) endif(BUILD_AUDACIOUS) if(BUILD_BMPX) pkg_check_modules(BMPX REQUIRED bmp-2.0>=0.14.0) set(conky_libs ${conky_libs} ${BMPX_LIBRARIES}) set(conky_includes ${conky_includes} ${BMPX_INCLUDE_DIRS}) endif(BUILD_BMPX) if(BUILD_XMMS2) pkg_check_modules(XMMS2 REQUIRED xmms2-client>=0.6) set(conky_libs ${conky_libs} ${XMMS2_LIBRARIES}) set(conky_includes ${conky_includes} ${XMMS2_INCLUDE_DIRS}) endif(BUILD_XMMS2) if(BUILD_EVE) set(WANT_CURL true) set(WANT_LIBXML2 true) endif(BUILD_EVE) if(BUILD_CURL) set(WANT_CURL true) endif(BUILD_CURL) if(BUILD_RSS) set(WANT_CURL true) set(WANT_LIBXML2 true) endif(BUILD_RSS) if(BUILD_WEATHER_METAR) set(WANT_CURL true) set(BUILD_WEATHER true) endif(BUILD_WEATHER_METAR) if(BUILD_WEATHER_XOAP) set(WANT_LIBXML2 true) set(WANT_CURL true) set(BUILD_XOAP true) set(BUILD_WEATHER true) endif(BUILD_WEATHER_XOAP) if(BUILD_NVIDIA) find_path(XNVCtrl_INCLUDE_PATH NVCtrl/NVCtrl.h ${INCLUDE_SEARCH_PATH}) find_library(XNVCtrl_LIB NAMES XNVCtrl) if(XNVCtrl_INCLUDE_PATH AND XNVCtrl_LIB) set(XNVCtrl_FOUND true) set(conky_libs ${conky_libs} ${XNVCtrl_LIB}) set(conky_includes ${conky_includes} ${XNVCtrl_INCLUDE_PATH}) else(XNVCtrl_INCLUDE_PATH AND XNVCtrl_LIB) message(FATAL_ERROR "Unable to find XNVCtrl library") endif(XNVCtrl_INCLUDE_PATH AND XNVCtrl_LIB) endif(BUILD_NVIDIA) if(BUILD_IMLIB2) pkg_search_module(IMLIB2 REQUIRED imlib2 Imlib2) set(conky_libs ${conky_libs} ${IMLIB2_LIB} ${IMLIB2_LDFLAGS}) set(conky_includes ${conky_includes} ${IMLIB2_INCLUDE_PATH}) endif(BUILD_IMLIB2) # Common libraries if(WANT_GLIB) pkg_check_modules(GLIB REQUIRED glib-2.0) set(conky_libs ${conky_libs} ${GLIB_LIBRARIES}) set(conky_includes ${conky_includes} ${GLIB_INCLUDE_DIRS}) endif(WANT_GLIB) if(WANT_CURL) pkg_check_modules(CURL REQUIRED libcurl) set(conky_libs ${conky_libs} ${CURL_LIBRARIES}) set(conky_includes ${conky_includes} ${CURL_INCLUDE_DIRS}) endif(WANT_CURL) if(WANT_LIBXML2) pkg_check_modules(LIBXML2 REQUIRED libxml-2.0) set(conky_libs ${conky_libs} ${LIBXML2_LIBRARIES}) set(conky_includes ${conky_includes} ${LIBXML2_INCLUDE_DIRS}) endif(WANT_LIBXML2) if(WANT_TOLUA) find_program(APP_TOLUA NAMES tolua++ tolua++5.1 tolua++-5.1) if(NOT APP_TOLUA) message(FATAL_ERROR "Unable to find program 'tolua++'") endif(NOT APP_TOLUA) find_library(TOLUA_LIBS NAMES tolua++ tolua++5.1 tolua++-5.1) find_path(TOLUA_INCLUDE_PATH tolua++.h ${INCLUDE_SEARCH_PATH}) if(TOLUA_INCLUDE_PATH AND TOLUA_LIBS) set(TOLUA_FOUND true) else(TOLUA_INCLUDE_PATH AND TOLUA_LIBS) message(FATAL_ERROR "Unable to find tolua++ library") endif(TOLUA_INCLUDE_PATH AND TOLUA_LIBS) mark_as_advanced(APP_TOLUA TOLUA_INCLUDE_PATH TOLUA_LIBS) set(conky_includes ${conky_includes} ${TOLUA_INCLUDE_PATH}) set(conky_libs ${conky_libs} ${TOLUA_LIBS}) set(LUA_EXTRAS true) endif(WANT_TOLUA) # Look for doc generation programs if(MAINTAINER_MODE) # Used for doc generation find_program(APP_DB2X_XSLTPROC db2x_xsltproc) if(NOT APP_DB2X_XSLTPROC) message(FATAL_ERROR "Unable to find program 'db2x_xsltproc'") endif(NOT APP_DB2X_XSLTPROC) find_program(APP_DB2X_MANXML db2x_manxml) if(NOT APP_DB2X_MANXML) message(FATAL_ERROR "Unable to find program 'db2x_manxml'") endif(NOT APP_DB2X_MANXML) find_program(APP_XSLTPROC xsltproc) if(NOT APP_XSLTPROC) message(FATAL_ERROR "Unable to find program 'xsltproc'") endif(NOT APP_XSLTPROC) find_program(APP_MAN man) if(NOT APP_MAN) message(FATAL_ERROR "Unable to find program 'man'") endif(NOT APP_MAN) find_program(APP_LESS less) if(NOT APP_LESS) message(FATAL_ERROR "Unable to find program 'less'") endif(NOT APP_LESS) find_program(APP_SED sed) if(NOT APP_SED) message(FATAL_ERROR "Unable to find program 'sed'") endif(NOT APP_SED) mark_as_advanced(APP_DB2X_XSLTPROC APP_DB2X_MANXML APP_XSLTPROC APP_MAN APP_SED APP_LESS) endif(MAINTAINER_MODE) if(CMAKE_BUILD_TYPE MATCHES "Debug") set(DEBUG true) endif(CMAKE_BUILD_TYPE MATCHES "Debug") # The version numbers are simply derived from the date and number of commits # since start of month if(DEBUG) execute_process(COMMAND ${APP_GIT} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git log --since=${VERSION_MAJOR}-${VERSION_MINOR}-01 --pretty=oneline COMMAND ${APP_WC} -l COMMAND ${APP_AWK} "{print $1}" RESULT_VARIABLE RETVAL OUTPUT_VARIABLE COMMIT_COUNT OUTPUT_STRIP_TRAILING_WHITESPACE) endif(DEBUG) conky-1.10.1/cmake/Docbook.cmake000066400000000000000000000071651262311664100163720ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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 . # # ${db2x_xsltproc_cmd} -s man ${srcdir}/docs.xml -o docs.mxml # ${db2x_manxml_cmd} docs.mxml # ${xsltproc_cmd} http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl ${srcdir}/docs.xml > docs.html # man -P 'less -is' ./conky.1 > README # sed -i "s/[[:cntrl:]]\[[0-9]*m//g" README # sed -i "s/\xE2//g" README # sed -i "s/\x80//g" README # sed -i "s/\x90/-/g" README # mv README ${top_srcdir} # ${xsltproc_cmd} ${srcdir}/variables.xsl ${srcdir}/variables.xml > variables.html # ${xsltproc_cmd} ${srcdir}/config_settings.xsl ${srcdir}/config_settings.xml > config_settings.html # ${xsltproc_cmd} ${srcdir}/lua.xsl ${srcdir}/lua.xml > lua.html #else #conky.1: #endif #man_MANS = conky.1 if(MAINTAINER_MODE) function(wrap_xsltproc) if(NOT ARGV) message(SEND_ERROR "Error: wrap_xsltproc called without any files") return() endif(NOT ARGV) FOREACH(FIL ${ARGV}) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html COMMAND ${APP_XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xsl ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xml > ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xsl ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xml COMMENT "Running xsltproc on ${FIL}" ) ADD_CUSTOM_TARGET(${FIL}.html ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html) ENDFOREACH(FIL) endfunction(wrap_xsltproc) function(wrap_man) if(NOT ARGV) message(SEND_ERROR "Error: wrap_man called without any files") return() endif(NOT ARGV) FOREACH(FIL ${ARGV}) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.1 ${CMAKE_SOURCE_DIR}/README COMMAND ${APP_XSLTPROC} http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xml > ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html COMMAND ${APP_DB2X_XSLTPROC} -s man ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xml -o ${FIL}.mxml COMMAND ${APP_DB2X_MANXML} --encoding=utf-8 ${FIL}.mxml --output-dir ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${APP_XSLTPROC} http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xml > ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html COMMAND ${APP_MAN} -P '${APP_LESS} -is' ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.1 > ${CMAKE_SOURCE_DIR}/README COMMAND ${APP_SED} -i "s/[[:cntrl:]]\\[[0-9]*m//g" ${CMAKE_SOURCE_DIR}/README COMMAND ${APP_SED} -i "s/\\xE2//g" ${CMAKE_SOURCE_DIR}/README COMMAND ${APP_SED} -i "s/\\x80//g" ${CMAKE_SOURCE_DIR}/README COMMAND ${APP_SED} -i "s/\\x90/-/g" ${CMAKE_SOURCE_DIR}/README DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.xml COMMENT "Proccessing man page for ${FIL}" ) ADD_CUSTOM_TARGET(${FIL} ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FIL}.html) ENDFOREACH(FIL) endfunction(wrap_man) endif(MAINTAINER_MODE) conky-1.10.1/cmake/ToLua.cmake000066400000000000000000000035761262311664100160400ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2010 Brenden Matthews, 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 . # function(wrap_tolua VAR FIL) SET(INCL) SET(${VAR}) 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(${VAR} ${${VAR}} PARENT_SCOPE) endfunction(wrap_tolua) conky-1.10.1/cmake/build.h.in000066400000000000000000000002311262311664100156500ustar00rootroot00000000000000#ifndef __BUILD_H #define __BUILD_H /* Conky build info */ #define BUILD_DATE "@BUILD_DATE@" #define BUILD_ARCH "@BUILD_ARCH@" #endif /* __BUILD_H */ conky-1.10.1/cmake/config.h.in000066400000000000000000000046711262311664100160320ustar00rootroot00000000000000/* * Auto-generated header for CMake. See config.h.in if you need to modify the * original. */ #ifndef _conky_config_h_ #define _conky_config_h_ #cmakedefine DEBUG #define SYSTEM_NAME "@CMAKE_SYSTEM_NAME@" #define PACKAGE_NAME "@PROJECT_NAME@" #define VERSION "@VERSION@" #define SYSTEM_CONFIG_FILE "@SYSTEM_CONFIG_FILE@" #define PACKAGE_LIBDIR "@PACKAGE_LIBRARY_DIR@" #define DEFAULTNETDEV "@DEFAULTNETDEV@" #define XDG_CONFIG_FILE "@XDG_CONFIG_FILE@" #define CONFIG_FILE "@CONFIG_FILE@" #define LOCALE_DIR "@LOCALE_DIR@" #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 BUILD_I18N 1 #cmakedefine HAVE_SYS_STATFS_H 1 #cmakedefine HAVE_SYS_PARAM_H 1 #cmakedefine HAVE_SYS_INOTIFY_H 1 #cmakedefine HAVE_DIRENT_H 1 #cmakedefine HAVE_STRNDUP 1 #cmakedefine HAVE_FOPENCOOKIE 1 #cmakedefine HAVE_FUNOPEN 1 #cmakedefine HAVE_PIPE2 1 #cmakedefine HAVE_O_CLOEXEC 1 #cmakedefine BUILD_X11 1 #cmakedefine OWN_WINDOW 1 #cmakedefine BUILD_XDAMAGE 1 #cmakedefine BUILD_XFT 1 #cmakedefine BUILD_XSHAPE 1 #cmakedefine BUILD_ARGB 1 #cmakedefine BUILD_XDBE 1 #cmakedefine BUILD_PORT_MONITORS 1 #cmakedefine BUILD_AUDACIOUS 1 #cmakedefine NEW_AUDACIOUS_FOUND 1 #cmakedefine BUILD_MPD 1 #cmakedefine BUILD_MYSQL 1 #cmakedefine BUILD_MOC 1 #cmakedefine BUILD_NVIDIA 0 #cmakedefine BUILD_XMMS2 1 #cmakedefine BUILD_HDDTEMP 1 #cmakedefine BUILD_EVE 1 #cmakedefine BUILD_LIBXML2 1 #cmakedefine BUILD_CURL 1 #cmakedefine BUILD_WEATHER_XOAP 1 #cmakedefine BUILD_WEATHER_METAR 1 #define XOAP_FILE "@XOAP_FILE@" #cmakedefine BUILD_IMLIB2 1 #cmakedefine BUILD_MATH 1 #cmakedefine BUILD_BUILTIN_CONFIG 1 #cmakedefine BUILD_OLD_CONFIG 1 #cmakedefine BUILD_NCURSES 1 #cmakedefine LEAKFREE_NCURSES 1 #cmakedefine BUILD_APCUPSD 1 #cmakedefine BUILD_IOSTATS 1 #cmakedefine BUILD_WLAN 1 #cmakedefine BUILD_ICAL 1 #cmakedefine BUILD_IRC 1 #cmakedefine BUILD_IPV6 1 #cmakedefine BUILD_HTTP 1 #cmakedefine BUILD_ICONV 1 #cmakedefine BUILD_LUA_CAIRO 1 #cmakedefine BUILD_LUA_IMLIB2 1 #cmakedefine BUILD_LUA_RSVG 1 #if defined(BUILD_LUA_CAIRO) || defined(BUILD_LUA_IMLIB2) || defined(BUILD_LUA_RSVG) #define BUILD_LUA_EXTRAS #endif #cmakedefine BUILD_IBM 1 #cmakedefine BUILD_RSS 1 #cmakedefine BUILD_CMUS 1 #cmakedefine HAVE_STATFS64 1 #ifndef HAVE_STATFS64 #define statfs64 statfs #endif #endif /* _conky_config_h_ */ conky-1.10.1/data/000077500000000000000000000000001262311664100136305ustar00rootroot00000000000000conky-1.10.1/data/CMakeLists.txt000066400000000000000000000032751262311664100163770ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2012 Brenden Matthews, 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 . # if(BUILD_BUILTIN_CONFIG) # generate defconfig if(BUILD_X11) set(builtin_config conky.conf) else(BUILD_X11) set(builtin_config conky_no_x11.conf) endif(BUILD_X11) add_custom_command(OUTPUT defconfig.h COMMAND ${CMAKE_SOURCE_DIR}/text2c.sh ${CMAKE_CURRENT_SOURCE_DIR}/${builtin_config} defconfig.h defconfig DEPENDS ${builtin_config} ) add_custom_target(defconfig ALL DEPENDS defconfig.h) set_source_files_properties(defconfig.h PROPERTIES GENERATED TRUE) endif(BUILD_BUILTIN_CONFIG) if(BUILD_OLD_CONFIG) add_custom_command(OUTPUT convertconf.h COMMAND ${CMAKE_SOURCE_DIR}/text2c.sh ${CMAKE_SOURCE_DIR}/extras/convert.lua convertconf.h convertconf DEPENDS ${CMAKE_SOURCE_DIR}/extras/convert.lua ) add_custom_target(convertconf ALL DEPENDS convertconf.h) set_source_files_properties(convertconf.h PROPERTIES GENERATED TRUE) endif(BUILD_OLD_CONFIG) conky-1.10.1/data/Makefile.am000066400000000000000000000023211262311664100156620ustar00rootroot00000000000000# -*- mode: Makefile; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- # # Conky, a system monitor, based on torsmo # # Any original torsmo code is licensed under the BSD license # # All code written since the fork of torsmo is licensed under the GPL # # Please see COPYING for details # # Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen # Copyright (c) 2005-2012 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 . # configdir = ${sysconfdir}/conky dist_config_DATA = conky.conf conky_no_x11.conf # vi:set ts=4 sw=4 noet ai nocindent syntax=automake: conky-1.10.1/data/conky-dfly-smp.conf000066400000000000000000000064111262311664100173550ustar00rootroot00000000000000-- vim: ts=4 sw=4 noet ai cindent syntax=lua --[[ Conky, a system monitor, based on torsmo Any original torsmo code is licensed under the BSD license All code written since the fork of torsmo is licensed under the GPL Please see COPYING for details Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen Copyright (c) 2005-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 . ]] conky.config = { alignment = 'bottom_left', background = false, border_width = 1, cpu_avg_samples = 2, default_color = 'white', default_outline_color = 'white', default_shade_color = 'white', draw_borders = false, draw_graph_borders = true, draw_outline = false, draw_shades = false, use_xft = false, --font = 'DejaVu Sans Mono:size=12', gap_x = 5, gap_y = 30, minimum_height = 5, minimum_width = 5, net_avg_samples = 2, no_buffers = true, out_to_console = false, out_to_stderr = false, extra_newline = false, own_window = false, own_window_class = 'Conky', own_window_type = 'desktop', stippled_borders = 0, update_interval = 3.0, uppercase = false, use_spacer = 'none', show_graph_scale = false, show_graph_range = false } conky.text = [[ $sysname $version on $machine $hr ${color grey}Uptime:$color $uptime #${color grey}Temp:$color $acpitemp #${color grey}Frequency (in MHz):$color $freq #${color grey}Frequency (in GHz):$color $freq_g ${color grey}RAM Usage:$color $mem/$memmax - $memperc% ${membar 4} ${color grey}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar 4} ${color grey}CPU Usage:$color $cpu% ${cpubar 4} ${color grey}CPU 0: ${cpu cpu1}% ${cpubar cpu1 4} CPU 1: ${cpu cpu2}% ${cpubar cpu2 4} CPU 2: ${cpu cpu3}% ${cpubar cpu3 4} CPU 3: ${cpu cpu4}% ${cpubar cpu4 4}$color ${color grey}Processes:$color $processes ${color grey}Running:$color $running_processes $hr ${color grey}File systems: / $color${fs_used /}/${fs_size /} ${fs_bar 6 /} ${color grey}Networking: Up:$color ${upspeed re0} ${color grey} - Down:$color ${downspeed re0} $hr ${color grey}Name PID CPU% MEM% ${color lightgrey} ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1} ${color lightgrey} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2} ${color lightgrey} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3} ${color lightgrey} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4} ${color lightgrey} ${top name 5} ${top pid 5} ${top cpu 5} ${top mem 5} ${color lightgrey} ${top name 6} ${top pid 6} ${top cpu 6} ${top mem 6} ${color lightgrey} ${top name 7} ${top pid 7} ${top cpu 7} ${top mem 7} ${color lightgrey} ${top name 8} ${top pid 8} ${top cpu 8} ${top mem 8} ]] conky-1.10.1/data/conky.conf000066400000000000000000000054621262311664100156310ustar00rootroot00000000000000-- vim: ts=4 sw=4 noet ai cindent syntax=lua --[[ Conky, a system monitor, based on torsmo Any original torsmo code is licensed under the BSD license All code written since the fork of torsmo is licensed under the GPL Please see COPYING for details Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen Copyright (c) 2005-2012 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 . ]] conky.config = { alignment = 'top_left', background = false, border_width = 1, cpu_avg_samples = 2, default_color = 'white', default_outline_color = 'white', default_shade_color = 'white', draw_borders = false, draw_graph_borders = true, draw_outline = false, draw_shades = false, use_xft = true, font = 'DejaVu Sans Mono:size=12', gap_x = 5, gap_y = 60, minimum_height = 5, minimum_width = 5, net_avg_samples = 2, no_buffers = true, out_to_console = false, out_to_stderr = false, extra_newline = false, own_window = true, own_window_class = 'Conky', own_window_type = 'desktop', stippled_borders = 0, update_interval = 1.0, uppercase = false, use_spacer = 'none', show_graph_scale = false, show_graph_range = false } conky.text = [[ ${scroll 16 $nodename - $sysname $kernel on $machine | } $hr ${color grey}Uptime:$color $uptime ${color grey}Frequency (in MHz):$color $freq ${color grey}Frequency (in GHz):$color $freq_g ${color grey}RAM Usage:$color $mem/$memmax - $memperc% ${membar 4} ${color grey}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar 4} ${color grey}CPU Usage:$color $cpu% ${cpubar 4} ${color grey}Processes:$color $processes ${color grey}Running:$color $running_processes $hr ${color grey}File systems: / $color${fs_used /}/${fs_size /} ${fs_bar 6 /} ${color grey}Networking: Up:$color ${upspeed eth0} ${color grey} - Down:$color ${downspeed eth0} $hr ${color grey}Name PID CPU% MEM% ${color lightgrey} ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1} ${color lightgrey} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2} ${color lightgrey} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3} ${color lightgrey} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4} ]] conky-1.10.1/data/conky_no_x11.conf000066400000000000000000000035771262311664100170230ustar00rootroot00000000000000-- Conky, a system monitor, based on torsmo -- Any original torsmo code is licensed under the BSD license -- All code written since the fork of torsmo is licensed under the GPL -- Please see COPYING for details -- Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen -- Copyright (c) 2005-2012 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 . conky.config = { background = false, cpu_avg_samples = 2, net_avg_samples = 2, no_buffers = true, out_to_stderr = false, update_interval = 1.0, uppercase = false, use_spacer = 'none', }; conky.text = [[${scroll 16 $nodename - $sysname $kernel on $machine | } Uptime: $uptime Frequency (in MHz): $freq Frequency (in GHz): $freq_g RAM Usage: $mem/$memmax - $memperc% ${membar 4} Swap Usage: $swap/$swapmax - $swapperc% ${swapbar 4} CPU Usage: $cpu% ${cpubar 4} Processes: $processes Running: $running_processes File systems: / ${fs_used /}/${fs_size /} ${fs_bar 6 /} Networking: Up: ${upspeed eth0} - Down: ${downspeed eth0} Name PID CPU% MEM% ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4} ]]; conky-1.10.1/doc/000077500000000000000000000000001262311664100134645ustar00rootroot00000000000000conky-1.10.1/doc/CMakeLists.txt000066400000000000000000000017211262311664100162250ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2012 Brenden Matthews, 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(Docbook) if(MAINTAINER_MODE) wrap_xsltproc(lua config_settings variables) wrap_man(docs) endif(MAINTAINER_MODE) conky-1.10.1/doc/README.docs000066400000000000000000000041351262311664100152760ustar00rootroot00000000000000DA DOCS. YO. ============ The main file that contains the bulk of our documentation is docs.xml . We use the DocBook format, which is a really kickass xml-based way of writing documentation, heavily oriented towards programming and computer stuff. There are tags like and

    #fffafa #b4cdcd
    Variable Explanation
    conky-1.10.1/doc/conky-howto.xml000066400000000000000000000151631262311664100164750ustar00rootroot00000000000000 Gentoo Linux Conky Howto Bill Woodford Brenden Matthews This document describes how to install and configure the system monitor known as Conky. 1.0 2006-02-22 Background
    Introduction to Conky

    So you have a Gentoo machine, and have already learned 30 different commands to monitor different aspects of what your computer is doing at the current moment. What do you do from here? Isn't there an easier way to monitor system performance and see what its doing, as well as the resources its using to perform all those tasks? This is what a system monitor, such as Conky, provides.

    What it does

    Unlike other system monitors such as top, Conky can run as a window in an X session, or by drawing to the root window (there is also an option to have Conky display information to stdout, but we won't discuss that here). It displays the information it has gathered through the use of both text, progress bars, and graphs. Also unlike top, the way it is formatted is completely user-configurable. In addition to monitoring the system itself, Conky can also give you information about several music players (such as XMMS, BMPx, Music Player Daemon, and Audacious Media Player), tell you how many new messages are in your mail spool, and plenty more. If the functionality you require isn't in Conky yet, it is a simple matter of writing a script to get the information you would like - some examples of this, which have already been done are RSS feeds, POP3 e-mail message count, local weather, boinc status, and even the status of portage.

    Installing Conky
    Base install

    Gentoo provides an ebuild to quickly and easily install Conky. Pay particular attention to the the USE flags. You'll most likely want X11 support (X), and make sure you select the USE flags for any music players (other than MPD) which you want. XMMS (xmms), Audacious (audacious), BMPx (bmpx), or XMMS support via the xmms-infopipe plugin (infopipe).

    # Example line to append to /etc/portage/package.use if you don't want the default USE flags.
    app-admin/conky xmms infopipe -ipv6
    

    In addition, the truetype USE flag compiles support for TrueType fonts with the use of Xft. Most users will want this as well.

    Once you have your USE flags correctly set up, it's time to install Conky!

    emerge -av conky
    

    You can test Conky to see how it will look by running the command conky in a terminal. This will likely give you a good reference to how it will look and what you want to change, add or even remove.

    $ conky
    

    Once you have an idea of how Conky looks, you can now move on to configuring it!

    Configuring Conky

    By default, Conky will look for a configuration file in the users home directory located at ~/.config/conky/conky.conf This file contains all the configuration options, and the static text, colors and other variables which control what data is shown to the user. Conky also provides a great sample configuration, located at /usr/share/doc/conky-version/Conkyrc.sample.gz Make sure to replace "version" with the specific version of Conky you have installed.

    $ mkdir -p ~/.config/conky
    $ zcat /usr/share/conky-1.6.0/conkyrc.sample.gz >> ~/.config/conky/conky.conf
    
    Make sure to replace "1.6.0" with the specific version of Conky you have installed.

    Now, open up the sample configuration in the text editor of your choice. You may notice that there are two seperate sections of the configuration file. The first section of the file, contains the programs configuration options and controls how it acts. This includes things such as the update_interval, or how often Conky will update the information on the screen. The second section contains the actual text, graphs, and variables which are rendered on the screen. This includes things such as the system uptime ($uptime), cpu usage ($cpu) and anything else you want to be shown. The first section of the file starts right from the beginning, the second section is comprised of everything after the line which says "TEXT". Comments in the file start with #, but keep in mind that even if a line is commented out in the second section of the file, the text will still be rendered to the screen.

    Lists of all the available configuration options and variables are kept at http://conky.sourceforge.net/config_settings.html and http://conky.sourceforge.net/variables.html. Also, there's a few great sample configurations and screenshots of working configurations at http://conky.sourceforge.net/screenshots.html.

    Extending Conky
    Beyond the built-in variables

    So you've gotten this far, and have scoured the Conky documentation for that extra variable which Conky just doesn't seem to have... You're in luck! Conky provides several variables for just this reason! $exec Will run a command every time Conky updates, $execi will run a command at a specified interval and $texeci will run a command in it's own thread at a specified interval.

    ${exec grep 'sudo' /var/log/messages | tail -n 4}
    ${execi 30 ~/scripts/emerge-status.sh
    ${texeci 600 ~/scripts/gmail.pl}
    
    While any command which works in a command shell will work in any of these variables, it is important to keep in mind that the commands must exit. This means that commands like tail -f which keep running will NOT work properly.
    conky-1.10.1/doc/docgen.sh000066400000000000000000000006021262311664100152550ustar00rootroot00000000000000#!/bin/sh xsltproc http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl docs.xml > docs.html && \ db2x_xsltproc -s man docs.xml -o docs.mxml && \ db2x_manxml docs.mxml && \ { echo ".TH CONKY 1 \"August 2005\" \"conky compiled August 2005\" \"User Commands\""; sed 1d < conky.1; } > conky.2 && \ mv conky.2 conky.1 && \ man ./conky.1 | col -b > README && \ mv README ../ conky-1.10.1/doc/docs.xml000066400000000000000000000254231262311664100151440ustar00rootroot00000000000000 ]>
    brenden1@users.sourceforge.net
    Brenden Matthews 2012-05-03
    conky 1 conky A system monitor for X originally based on the torsmo code, but more kickass. It just keeps on given'er. Yeah. conky options Description Conky is a system monitor for X originally based on torsmo. Since its inception, Conky has changed significantly from its predecessor, while maintaining simplicity and configurability. Conky can display just about anything, either on your root desktop or in its own window. Not only does Conky have many built-in objects, it can also display just about any piece of information by using scripts and other external programs. Conky has more than 250 built in objects, including support for a plethora of OS stats (uname, uptime, CPU usage, mem usage, disk usage, "top" like process stats, and network monitoring, just to name a few), built in IMAP and POP3 support, built in support for many popular music players (MPD, XMMS2, BMPx, Audacious), and much much more. Conky can display this info either as text, or using simple progress bars and graph widgets, with different fonts and colours. We are always looking for help, whether its reporting bugs, writing patches, or writing docs. Please use the facilities at SourceForge to make bug reports, feature requests, and submit patches, or stop by #conky on irc.freenode.net if you have questions or want to contribute. Thanks for your interest in Conky. Compiling For users compiling from source on a binary distro, make sure you have the X development libraries installed (Unless you configure your build without X11). This should be a package along the lines of "libx11-dev" or "xorg-x11-dev" for X11 libs, and similar "-dev" format for the other libs required (depending on your build options). You should be able to see which extra packages you need to install by reading errors that you get from running `cmake'. The easiest way to view the available build options is to run `ccmake' or `cmake-gui' from the source tree, but be careful when disabling certain features as you may lose desired functionality. E.g., with BUILD_MATH disabled you won't get errors but logarithmic graphs will be normal graphs and gauges will miss their line. Conky has (for some time) been available in the repositories of most popular distributions. Here are some installation instructions for a few: Gentoo users -- Conky is in Gentoo's Portage... simply use "emerge app-admin/conky" for installation. Debian, etc. users -- Conky should be in your repositories, and can be installed by doing "aptitude install conky". Example to compile and run Conky with default components (note that some build options may differ for your system): Conky has been tested to be compatible with C99 C and C++0x C++, however it has not been tested with anything other than gcc, and is not guaranteed to work with other compilers. TIP: Try configuring Conky with `ccmake' or `cmake-gui' instead of just `cmake'. You Should Know Conky is generally very good on resources. That said, the more you try to make Conky do, the more resources it is going to consume. An easy way to force Conky to reload your ~/.config/conky/conky.conf: "killall -SIGUSR1 conky". Saves you the trouble of having to kill and then restart. You can now also do the same with SIGHUP. Options Command line options override configurations defined in configuration file. &command_options; Configuration Settings Default configuration file location is $HOME/.config/conky/conky.conf or ${sysconfdir}/conky/conky.conf. On most systems, sysconfdir is /etc, and you can find the sample config file there (/etc/conky/conky.conf). You might want to copy it to $HOME/.config/conky/conky.conf and then start modifying it. Other configs can be found at http://conky.sf.net/ &config_settings; Objects/Variables Colours are parsed using XParsecolor(), there might be a list of them: /usr/share/X11/rgb.txt. Colour can be also in #rrggbb format (hex). Some objects may create threads, and sometimes these threads will not be destroyed until Conky terminates. There is no way to destroy or clean up threads while Conky is running. For example, if you use an MPD variable, the MPD thread will keep running until Conky dies. Some threaded objects will use one of the parameters as a 'key', so that you only have 1 relevant thread running (for example, the $curl, $rss and $weather objects launch one thread per URI). &variables; Lua API Conky features a Lua Programming API, and also ships with Lua bindings for some useful libraries. Conky defines certain global functions and variables which can be accessed from Lua code running in Conky. To use Lua Conky, you first need to make sure you have a version of Conky with Lua support enabled (``conky -v'' will report this). Scripts must first be loaded using the lua_load configuration option. You then call functions in Lua via Conky's $lua, $lua_read, and Lua hooks. Be careful when creating threaded objects through the Lua API. You could wind up with a whole bunch of threads running if a thread is created with each iteration. At this time, the Lua API should not be considered stable and may change drastically from one release to another as it matures. NOTE: In order to accommodate certain features in the cairo library's API, Conky will export a few additional functions for the creation of certain structures. These are documented below. &lua; Examples conky Start Conky in its own window with date and clock as text and 30 sec update interval. conky Start Conky to background at coordinates (5, 500). conky Do not start Conky, but have it output the builtin default config file to ~/.config/conky/conky.conf for later customising. Files ${sysconfdir}/conky/conky.conf Default system-wide configuration file. The value of ${sysconfdir} depends on the compile-time options (most likely /etc). ~/.config/conky/rc Default personal configuration file. Bugs Drawing to root or some other desktop window directly doesn't work with all window managers. Especially doesn't work well with Gnome and it has been reported that it doesn't work with KDE either. Nautilus can be disabled from drawing to desktop with program gconf-editor. Uncheck show_desktop in /apps/nautilus/preferences/. There is -w switch in Conky to set some specific window id. You might find xwininfo -tree useful to find the window to draw to. You can also use -o argument which makes Conky to create its own window. If you do try running Conky in its own window, be sure to read up on the own_window_type settings and experiment. See Also http://conky.sourceforge.net/ http://www.sourceforge.net/projects/conky http://wiki.conky.be #conky on irc.freenode.net Copying Copyright (c) 2005-2012 Brenden Matthews, Philip Kovacs, et. al. Any original torsmo code is licensed under the BSD license (see LICENSE.BSD for a copy). All code written since the fork of torsmo is licensed under the GPL (see LICENSE.GPL for a copy), except where noted differently (such as in portmon and audacious code which are LGPL, and prss which is an MIT-style license). Authors The Conky dev team (see AUTHORS for a full list of contributors).
    conky-1.10.1/doc/lua.xml000066400000000000000000000176071262311664100150020ustar00rootroot00000000000000 This function takes a string that is evaluated as per Conky's TEXT section, and then returns a string with the result. Sets Conky's update interval (in seconds) to 'number'. This table contains some information about Conky's window. The following table describes the values contained: drawable visual display width height border_inner_margin border_outer_margin border_width text_start_x text_start_y text_width text_height NOTE: This table is only defined when X support is enabled. This table contains some information about Conky's internal data. The following table describes the values contained: update_interval uptime A string containing the build info for this particular instance of Conky, including the version, build date, and architecture. A string containing the build date for this particular instance of Conky. A string containing the build architecture for this particular instance of Conky. A string containing the version of the current instance of Conky. A string containing the path of the current Conky configuration file. Call this function to return a new cairo_text_extents_t structure. A creation function for this structure is not provided by the cairo API. After calling this, you should use tolua.takeownership() on the return value to ensure ownership is passed properly. Call this function to return a new cairo_font_extents_t structure. A creation function for this structure is not provided by the cairo API. After calling this, you should use tolua.takeownership() on the return value to ensure ownership is passed properly. Call this function to return a new cairo_matrix_t structure. A creation function for this structure is not provided by the cairo API. After calling this, you should use tolua.takeownership() on the return value to ensure ownership is passed properly. conky-1.10.1/doc/lua.xsl000066400000000000000000000030341262311664100147750ustar00rootroot00000000000000 Lua API -

    #fffafa #b4cdcd
    Name Type Details
    conky-1.10.1/doc/variables.xml000066400000000000000000004536361262311664100161770ustar00rootroot00000000000000 ACPI ac adapter state. On linux, the adapter option specifies the subfolder of /sys/class/power_supply containing the state information (tries "AC" and "ADP1" if there is no argument given). Non-linux systems ignore it. ACPI fan state ACPI temperature in C. IP address for an interface, or "No Address" if no address is assigned. IP addresses for an interface (if one - works like addr). Linux only. CPU temperature from therm_adt746x Fan speed from therm_adt746x Align text to centre Right-justify text, with space of N Sets up the connection to apcupsd daemon. Prints nothing, defaults to localhost:3551 Prints the UPS connection type. Current battery capacity in percent. Reason for last transfer from line to battery. Nominal input voltage. Current load in percent. Bar showing current load. Gauge that shows current load. History graph of current load. Prints the model of the UPS. Prints the UPS user-defined name. Prints current status (on-line, on-battery). Current internal temperature. Time left to run on battery. Prints the UPS mode (e.g. standalone). Display APM AC adapter status (FreeBSD, OpenBSD only) Display APM battery life in percent (FreeBSD, OpenBSD only) Display remaining APM battery life in hh:mm:ss or "unknown" if AC adapterstatus is on-line or charging (FreeBSD, OpenBSD only) Progress bar Bitrate of current tune Number of audio channels of current tune Full path and filename of current tune Sampling frequency of current tune Total length of current tune as MM:SS Total length of current tune in seconds The current volume fetched from Audacious Number of tunes in playlist Playlist position of current tune Position of current tune (MM:SS) Position of current tune in seconds Player status (Playing/Paused/Stopped/Not running) Title of current tune with optional maximum length specifier Battery status and remaining percentage capacity of ACPI or APM battery. ACPI battery number can be given as argument (default is BAT0). Battery percentage remaining of ACPI battery in a bar. ACPI battery number can be given as argument (default is BAT0, use all to get the mean percentage remaining for all batteries). Battery percentage remaining for ACPI battery. ACPI battery number can be given as argument (default is BAT0, use all to get the mean percentage remaining for all batteries). Battery status and remaining percentage capacity of ACPI or APM battery. ACPI battery number can be given as argument (default is BAT0). This mode display a short status, which means that C is displayed instead of charging, D for discharging, F for full, N for not present, E for empty and U for unknown. Battery charge/discharge time remaining of ACPI battery. ACPI battery number can be given as argument (default is BAT0). Let 'text_and_other_conky_vars' blink on and off. Album in current BMPx track Artist in current BMPx track Bitrate of the current BMPx track Title of the current BMPx track Track number of the current BMPx track URI of the current BMPx track Amount of memory buffered Amount of memory cached PID of the first process that has string in it's commandline Print aaa status of cmus (all/artist/album). Prints the album of the current cmus song. Prints the artist of the current cmus song. Current time of the current cmus song. Print the file name of the current cmus song Print the date of the current cmus song Print the genre name of the current cmus song Percent of song's progress. cmus' progress bar. Random status of cmus (on/off). Repeat status of cmus (song/all/off). Current state of cmus (playing, paused, stopped etc). Time left of the current cmus song. Prints the title of the current cmus song. Total length of the current cmus song. Print track number of current cmus song. Change drawing color to 'color' which is a name of a color or a hexcode preceded with # (for example #0A1B2C ). If you use ncurses only the following colors are supported: red,green,yellow,blue,magenta,cyan,black,white. Change drawing color to colorN configuration option, where N is a digit between 0 and 9, inclusively. Places the lines of var2 to the right of the lines of var1 separated by the chars that are put between var1 and var2. For example: ${combine ${head /proc/cpuinfo 2} - ${head /proc/meminfo 1}} gives as output "cpuinfo_line1 - meminfo_line1" on line 1 and "cpuinfo_line2 -" on line 2. $combine vars can also be nested to place more vars next to each other. CPU architecture Conky was built for Date Conky was built Conky version CPU usage in percents. For SMP machines, the CPU number can be provided as an argument. ${cpu cpu0} is the total usage, and ${cpu cpuX} (X >= 1) are individual CPUs. Bar that shows CPU usage, height is bar's height in pixels. See $cpu for more info on SMP. Elliptical gauge that shows CPU usage, height and width are gauge's vertical and horizontal axis respectively. See $cpu for more info on SMP. CPU usage graph, with optional colours in hex, minus the #. See $cpu for more info on SMP. Uses a logarithmic scale (to see small numbers) when you use the -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Download data from URI using Curl at the specified interval. The interval may be a positive floating point value (0 is allowed), otherwise defaults to 15 minutes. Most useful when used in conjunction with Lua and the Lua API. This object is threaded, and once a thread is created it can't be explicitly destroyed. One thread will run for each URI specified. You can use any protocol that Curl supports. Number of the desktop on which conky is running or the message "Not running in X" if this is the case. Name of the desktop on which conky is running or the message "Not running in X" if this is the case. Number of desktops or the message "Not running in X" if this is the case. Disk protection status, if supported (needs kernel-patch). Prints either "frozen" or "free " (note the padding). Displays current disk IO. Device is optional, and takes the form of sda for /dev/sda. A block device label can be specified with label:foo. Individual partitions are also allowed. Displays current disk IO for reads. Device as in diskio. Displays current disk IO for writes. Device as in diskio. Disk IO graph, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Uses a logarithmic scale (to see small numbers) when you use -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Disk IO graph for reads, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Device as in diskio. Uses a logarithmic scale (to see small numbers) when you use -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Disk IO graph for writes, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Device as in diskio. Uses a logarithmic scale (to see small numbers) when you use -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). The name of the distribution. It could be that some of the untested distributions will show up wrong or as "unknown", if that's the case post a bug on sourceforge, make sure it contains the name of your distribution, the contents of /proc/version and if there is a file that only exists on your distribution, also add the path of that file in the bug. If there is no such file, please add another way which we can use to identify your distribution. Download speed in suitable IEC units Download speed in KiB with one decimal Download speed graph, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Uses a logarithmic scale (to see small numbers) when you use -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Number of mails marked as draft in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Text to show if any of the above are not true Ends an $if block. Current entropy available for crypto freaks Normalized bar of available entropy for crypto freaks Percentage of entropy available in comparison to the poolsize Total size of system entropy pool for crypto freaks Evaluates given string according to the rules of conky.text interpretation, i.e. parsing any contained text object specifications into their output, any occuring '$$' into a single '$' and so on. The output is then being parsed again. Fetches your currently training skill from the Eve Online API servers (http://www.eve-online.com/) and displays the skill along with the remaining training time. Executes a shell command and displays the output in conky. warning: this takes a lot more resources than other variables. I'd recommend coding wanted behaviour in C and posting a patch. Same as exec, except if the first value return is a value between 0-100, it will use that number for a bar. The size for bars can be controlled via the default_bar_size config setting. Same as exec, except if the first value returned is a value between 0-100, it will use that number for a gauge. The size for gauges can be controlled via the default_gauge_size config setting. Same as execbar, but graphs values. Uses a logaritmic scale when the log option (-l switch) is given (to see small numbers). Values still have to be between 0 and 100. The size for graphs can be controlled via the default_graph_size config setting. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). If -t or -l is your first argument, you may need to preceed it by a space (' '). You may also use double-quotes around the exec argument should you need to execute a command with spaces. For example, ${execgraph "date +'%S'"} to execute `date +'%S'` and graph the result. Without quotes, it would simply print the result of `date`. Same as exec but with specific interval. Interval can't be less than update_interval in configuration. See also $texeci Same as execbar, except with an interval Same as execgauge, but takes an interval arg and gauges values. Same as execgraph, but takes an interval arg and graphs values. If -t or -l is your first argument, you may need to preceed it by a space (' '). Executes a shell command and displays the output in conky. warning: this takes a lot more resources than other variables. I'd recommend coding wanted behaviour in C and posting a patch. This differs from $exec in that it parses the output of the command, so you can insert things like ${color red}hi!${color} in your script and have it correctly parsed by Conky. Caveats: Conky parses and evaluates the output of $execp every time Conky loops, and then destroys all the objects. If you try to use anything like $execi within an $execp statement, it will functionally run at the same interval that the $execp statement runs, as it is created and destroyed at every interval. Same as execp but with specific interval. Interval can't be less than update_interval in configuration. Note that the output from the $execpi command is still parsed and evaluated at every interval. Number of mails marked as flagged in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Specify a different font. This new font will apply to the current line and everything following. You can use a $font with no arguments to change back to the default font (much like with $color) Format time given in seconds. This var only works when the times_in_seconds configuration setting is on. Format is a string that should start and end with a "-char. The "-chars are not part of the output, \w,\d,\h,\m,\s,\(,\) and \\ are replaced by weeks,days,hours,minutes,seconds,(,) and \. If you leave out a unit, it's value will be expressed in the highest unite lower then the one left out. Text between ()-chars will not be visible if a replaced unit in this text is 0. If seconds is a decimal number then you can see the numbers behind the point by using \S followed by a number that specifies the amount of digits behind the point that you want to see (maximum 9). You can also place a 'x' behind \S so you have all digits behind the point and no trailing zero's. (also maximum 9) Number of mails marked as forwarded in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Returns CPU #n's frequency in MHz. CPUs are counted from 1. If omitted, the parameter defaults to 1. Returns CPU #n's frequency in GHz. CPUs are counted from 1. If omitted, the parameter defaults to 1. Bar that shows how much space is used on a file system. height is the height in pixels. fs is any file on that file system. Bar that shows how much space is free on a file system. height is the height in pixels. fs is any file on that file system. Free space on a file system available for users. Free percentage of space on a file system available for users. File system size. File system type. File system used space. Percent of file system used space. The next element will be printed at position 'x'. Displays the default route's interface or "multiple"/"none" accordingly. Displays the default gateway's IP or "multiple"/"none" accordingly. Displays temperature of a selected hard disk drive as reported by the hddtemp daemon. Use hddtemp_host and hddtemp_port to specify a host and port for all hddtemp objects. If no dev parameter is given, the first disk returned by the hddtemp daemon is used. Displays first N lines of supplied text file. The file is checked every 'next_check' update. If next_check is not supplied, Conky defaults to 2. Max of 30 lines can be displayed, or until the text buffer is filled. Horizontal line, height is the height in pixels Hwmon sensor from sysfs (Linux 2.6). Parameter dev may be omitted if you have only one hwmon device. Parameter type is either 'in' or 'vol' meaning voltage; 'fan' meaning fan; 'temp' meaning temperature. Parameter n is number of the sensor. See /sys/class/hwmon/ on your local computer. The optional arguments 'factor' and 'offset' allow precalculation of the raw input, which is being modified as follows: 'input = input * factor + offset'. Note that they have to be given as decimal values (i.e. contain at least one decimal place). I2C sensor from sysfs (Linux 2.6). Parameter dev may be omitted if you have only one I2C device. Parameter type is either 'in' or 'vol' meaning voltage; 'fan' meaning fan; 'temp' meaning temperature. Parameter n is number of the sensor. See /sys/bus/i2c/devices/ on your local computer. The optional arguments 'factor' and 'offset' allow precalculation of the raw input, which is being modified as follows: 'input = input * factor + offset'. Note that they have to be given as decimal values (i.e. contain at least one decimal place). If running the i8k kernel driver for Inspiron laptops, displays whether ac power is on, as listed in /proc/i8k (translated to human-readable). Beware that this is by default not enabled by i8k itself. If running the i8k kernel driver for Inspiron laptops, displays the bios version as listed in /proc/i8k. If running the i8k kernel driver for Inspiron laptops, displays the volume buttons status as listed in /proc/i8k. If running the i8k kernel driver for Inspiron laptops, displays the cpu temperature in Celsius, as reported by /proc/i8k. If running the i8k kernel driver for Inspiron laptops, displays the left fan's rate of rotation, in revolutions per minute as listed in /proc/i8k. Beware, some laptops i8k reports these fans in reverse order. If running the i8k kernel driver for Inspiron laptops, displays the left fan status as listed in /proc/i8k (translated to human-readable). Beware, some laptops i8k reports these fans in reverse order. If running the i8k kernel driver for Inspiron laptops, displays the right fan's rate of rotation, in revolutions per minute as listed in /proc/i8k. Beware, some laptops i8k reports these fans in reverse order. If running the i8k kernel driver for Inspiron laptops, displays the right fan status as listed in /proc/i8k (translated to human-readable). Beware, some laptops i8k reports these fans in reverse order. If running the i8k kernel driver for Inspiron laptops, displays your laptop serial number as listed in /proc/i8k. If running the i8k kernel driver for Inspiron laptops, displays the version formatting of /proc/i8k. If running the IBM ACPI, displays the brigtness of the laptops's LCD (0-7). If running the IBM ACPI, displays the fan speed. If running the IBM ACPI, displays the temperatures from the IBM temperature sensors (N=0..7) Sensor 0 is on the CPU, 3 is on the GPU. If running the IBM ACPI, displays the status of your ThinkLight™. Value is either 'on', 'off' or 'unknown'. If running the IBM ACPI, displays the "master" 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. Convert text from one codeset to another using GNU iconv. Needs to be stopped with iconv_stop. Stop iconv codeset conversion. if conky variable VAR is empty, display everything between $if_empty and the matching $endif if FILE exists, display everything between if_existing and the matching $endif. The optional second parameter checks for FILE containing the specified string and prints everything between $if_existing and the matching $endif. if there is at least one default gateway, display everything between $if_gw and the matching $endif Evaluates the given boolean expression, printing everything between $if_match and the matching $endif depending on whether the evaluation returns true or not. Valid expressions consist of a left side, an operator and a right side. Left and right sides are being parsed for contained text objects before evaluation. Recognised left and right side types are: doubleArgument consists of only digits and a single dot. longArgument consists of only digits. stringArgument is enclosed in quotation marks (") Valid operands are: '>', '<', '>=', '<=', '==', '!='. If mixer exists, display everything between $if_mixer_mute and the matching $endif. If no mixer is specified, "Vol" is used. if MOUNTPOINT is mounted, display everything between $if_mounted and the matching $endif if mpd is playing or paused, display everything between $if_mpd_playing and the matching $endif If PROCESS is running, display everything between $if_running and the corresponding $else or $endif. Note that PROCESS may be either a full command line with arguments (without the directory prefix), or simply the name of an executable. For example, either of the following will be true if there is a running process with the command line /usr/bin/conky -u 5: ${if_running conky -u 5} or ${if_running conky} It is important not to include trailing spaces. For example, ${if_running conky } will be false. when using smapi, if the battery with index INDEX is installed, display everything between $if_smapi_bat_installed and the matching $endif if INTERFACE exists and is up, display everything between $if_up and the matching $endif If it's the UPDATENR-th time that conky updates, display everything between $if_updatenr and the matching $endif. The counter resets when the highest UPDATENR is reached. Example : "{$if_updatenr 1}foo$endif{$if_updatenr 2}bar$endif{$if_updatenr 4}$endif" shows foo 25% of the time followed by bar 25% of the time followed by nothing the other half of the time. Display everything between $if_xmms2_connected and the matching $endif if xmms2 is running. Renders an image from the path specified using Imlib2. Takes 4 optional arguments: a position, a size, a no-cache switch, and a cache flush interval. Changing the x,y position will move the position of the image, and changing the WxH will scale the image. If you specify the no-cache flag (-n), the image will not be cached. Alternately, you can specify the -f int switch to specify a cache flush interval for a particular image. Example: ${image /home/brenden/cheeseburger.jpg -p 20,20 -s 200x200} will render 'cheeseburger.jpg' at (20,20) scaled to 200x200 pixels. Conky does not make any attempt to adjust the position (or any other formatting) of images, they are just rendered as per the arguments passed. The only reason $image is part of the conky.text section, is to allow for runtime modifications, through $execp $lua_parse, or some other method. Displays the number of messages in your global IMAP inbox by default. You can define individual IMAP inboxes separately by passing arguments to this object. Arguments are: "host user pass [-i interval (in seconds)] [-f 'folder'] [-p port] [-e 'command'] [-r retries]". Default port is 143, default folder is 'INBOX', default interval is 5 minutes, and default number of retries before giving up is 5. If the password is supplied as '*', you will be prompted to enter the password when Conky starts. Displays the number of unseen messages in your global IMAP inbox by default. You can define individual IMAP inboxes separately by passing arguments to this object. Arguments are: "host user pass [-i interval (in seconds)] [-f 'folder'] [-p port] [-e 'command'] [-r retries]". Default port is 143, default folder is 'INBOX', default interval is 5 minutes, and default number of retries before giving up is 5. If the password is supplied as '*', you will be prompted to enter the password when Conky starts. Prints the current ioscheduler used for the given disk name (i.e. e.g. "hda" or "sdb") Kernel version Git version numer (DragonFly only) The value of /proc/sys/vm/laptop_mode Displays the number of lines in the given file System load average, 1 is for past 1 minute, 2 for past 5 minutes and 3 for past 15 minutes. Without argument, prints all three values separated by whitespace. Load1 average graph, similar to xload, with optional colours in hex, minus the #. Uses a logarithmic scale (to see small numbers) when you use the -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Executes a Lua function with given parameters, then prints the returned string. See also 'lua_load' on how to load scripts. Conky puts 'conky_' in front of function_name to prevent accidental calls to the wrong function unless you put you place 'conky_' in front of it yourself. Executes a Lua function with given parameters and draws a bar. Expects result value to be an integer between 0 and 100. See also 'lua_load' on how to load scripts. Conky puts 'conky_' in front of function_name to prevent accidental calls to the wrong function unless you put you place 'conky_' in front of it yourself. Executes a Lua function with given parameters and draws a gauge. Expects result value to be an integer between 0 and 100. See also 'lua_load' on how to load scripts. Conky puts 'conky_' in front of function_name to prevent accidental calls to the wrong function unless you put you place 'conky_' in front of it yourself. Executes a Lua function with and draws a graph. Expects result value to be any number, and by default will scale to show the full range. See also 'lua_load' on how to load scripts. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Conky puts 'conky_' in front of function_name to prevent accidental calls to the wrong function unless you put you place 'conky_' in front of it yourself. Executes a Lua function with given parameters as per $lua, then parses and prints the result value as per the syntax for the conky.text section. See also 'lua_load' on how to load scripts. Conky puts 'conky_' in front of function_name to prevent accidental calls to the wrong function unless you put you place 'conky_' in front of it yourself. Machine, i686 for example Mail count in the specified mailbox or your mail spool if not. Both mbox and maildir type mailboxes are supported. You can use a program like fetchmail to get mails from some server using your favourite protocol. See also new_mails. Print a summary of recent messages in an mbox format mailbox. mbox parameter is the filename of the mailbox (can be encapsulated using '"', ie. ${mboxscan -n 10 "/home/brenden/some box"} Amount of memory in use Amount of memory in use, including that used by system buffers and caches Bar that shows amount of memory in use Bar that shows amount of memory in use (including memory used by system buffers and caches) Amount of "dirty" memory (linux only) Amount of free memory including the memory that is very easily freed (buffers/cache) Amount of free memory Gauge that shows amount of memory in use (see cpugauge) Memory usage graph. Uses a logarithmic scale (to see small numbers) when you use the -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Total amount of memory Percentage of memory in use Prints the mixer value as reported by the OS. On Linux, this variable uses the OSS emulation, so you need the proper kernel module loaded. Default mixer is "Vol", but you can specify one of the available OSS controls: "Vol", "Bass", "Trebl", "Synth", "Pcm", "Spkr", "Line", "Mic", "CD", "Mix", "Pcm2 ", "Rec", "IGain", "OGain", "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", "PhoneIn", "PhoneOut", "Video", "Radio" and "Monitor". Displays mixer value in a bar as reported by the OS. See docs for $mixer for details on arguments. Prints the left channel mixer value as reported by the OS. See docs for $mixer for details on arguments. Displays the left channel mixer value in a bar as reported by the OS. See docs for $mixer for details on arguments. Prints the right channel mixer value as reported by the OS. See docs for $mixer for details on arguments. Displays the right channel mixer value in a bar as reported by the OS. See docs for $mixer for details on arguments. Album of the current MOC song Artist of the current MOC song Bitrate in the current MOC song Current time of the current MOC song File name of the current MOC song Rate of the current MOC song The current song name being played in MOC. Current state of MOC; playing, stopped etc. Time left in the current MOC song Title of the current MOC song Total length of the current MOC song Number of the monitor on which conky is running or the message "Not running in X" if this is the case. Number of monitors or the message "Not running in X" if this is the case. Album in current MPD song Artist in current MPD song must be enabled at compile Artist of the album of the current MPD song. Bar of mpd's progress Bitrate of current song Date of current song Song's elapsed time Prints the file name of the current MPD song Song's length Prints the MPD name field Percent of song's progress Random status (On/Off) Repeat status (On/Off) Prints the song name in either the form "artist - title" or file name, depending on whats available Playing, stopped, et cetera. Title of current MPD song Prints the MPD track field MPD's volume Shows the first field of the first row of the result of the query. Print a nameserver from /etc/resolv.conf. Index starts at and defaults to 0. Unread mail count in the specified mailbox or mail spool if not. Both mbox and maildir type mailboxes are supported. Hostname Short hostname (same as 'hostname -s' shell command). Shows text and parses the vars in it, but doesn't update them. Use this for things that do not change while conky is running, like $machine, $conky_version,... By not updating this you can save some resources. Nvidia graficcard support for the XNVCtrl library. Each option can be shortened to the least significant part. Temperatures are printed as float, all other values as integer. threshold temp ambient gpufreq memfreq imagequality Move text over by N pixels. See also $voffset. Change outline color If running on Apple powerbook/ibook, display information on battery status. The item parameter specifies, what information to display. Exactly one item must be specified. Valid items are: status percent time Directory used as rootdirectory by the process (this will be "/" unless the process did a chroot syscall) Command line this process was invoked with Current working directory of the process Contents of a environment-var of the process List of environment-vars that the process can see Path to executed command that started the process The nice value of the process List of files that the process has open The pid of the parent of the process The priority of the process (see 'priority' in "man 5 proc") Total number of bytes read by the process State of the process One of the chars in "RSDZTW" representing the state of the process where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging Filedescriptor binded to the STDERR of the process Filedescriptor binded to the STDIN of the process Filedescriptor binded to the STDOUT of the process Number of threads in process containing this thread List with pid's from threads from this process Amount of time that the process has been scheduled in kernel mode in seconds Amount of time that the process has been scheduled in user mode in seconds Sum of $pid_time_kernelmode and $pid_time_usermode The real uid of the process The effective uid of the process The saved set uid of the process The file system uid of the process The real gid of the process The effective gid of the process The saved set gid of the process The file system gid of the process Peak virtual memory size of the process Virtual memory size of the process Locked memory size of the process Peak resident set size ("high water mark") of the process Resident set size of the process Data segment size of the process Stack segment size of the process Text segment size of the process Shared library code size of the process Page table entries size of the process Total number of bytes written by the process Platform sensor from sysfs (Linux 2.6). Parameter dev may be omitted if you have only one platform device. Platform type is either 'in' or 'vol' meaning voltage; 'fan' meaning fan; 'temp' meaning temperature. Parameter n is number of the sensor. See /sys/bus/platform/devices/ on your local computer. The optional arguments 'factor' and 'offset' allow precalculation of the raw input, which is being modified as follows: 'input = input * factor + offset'. Note that they have to be given as decimal values (i.e. contain at least one decimal place). Displays the number of unseen messages in your global POP3 inbox by default. You can define individual POP3 inboxes separately by passing arguments to this object. Arguments are: "host user pass [-i interval (in seconds)] [-p port] [-e 'command'] [-r retries]". Default port is 110, default interval is 5 minutes, and default number of retries before giving up is 5. If the password is supplied as '*', you will be prompted to enter the password when Conky starts. Displays the amount of space (in MiB, 2^20) used in your global POP3 inbox by default. You can define individual POP3 inboxes separately by passing arguments to this object. Arguments are: "host user pass [-i interval (in seconds)] [-p port] [-e 'command'] [-r retries]". Default port is 110, default interval is 5 minutes, and default number of retries before giving up is 5. If the password is supplied as '*', you will be prompted to enter the password when Conky starts. Total processes (sleeping and running) Connects to a tcp port on a host (default is localhost), reads every char available at the moment and shows them. Connects to a udp port on a host (default is localhost), reads every char available at the moment and shows them. Number of mails marked as replied in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Download and parse RSS feeds. The interval may be a floating point value greater than 0, otherwise defaults to 15 minutes. Action may be one of the following: feed_title, item_title (with num par), item_desc (with num par) and item_titles (when using this action and spaces_in_front is given conky places that many spaces in front of each item). This object is threaded, and once a thread is created it can't be explicitly destroyed. One thread will run for each URI specified. You can use any protocol that Curl supports. Running processes (not sleeping), requires Linux 2.6 Number of running (runnable) threads. Linux only. Scroll 'text' by 'step' characters to the left or right (set 'direction' to 'left' or 'right') showing 'length' number of characters at the same time. The text may also contain variables. 'step' is optional and defaults to 1 if not set. 'direction' is optional and defaults to left if not set. If a var creates output on multiple lines then the lines are placed behind each other separated with a '|'-sign. If you change the textcolor inside $scroll it will automatically have it's old value back at the end of $scroll. The end and the start of text will be separated by 'length' number of spaces. Number of mails marked as seen in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Change shading color when using smapi, display contents of the /sys/devices/platform/smapi directory. ARGS are either '(FILENAME)' or 'bat (INDEX) (FILENAME)' to display the corresponding files' content. This is a very raw method of accessing the smapi values. When available, better use one of the smapi_* variables instead. when using smapi, display the remaining capacity of the battery with index INDEX as a bar. when using smapi, display the remaining capacity in percent of the battery with index INDEX. This is a separate variable because it supports the 'use_spacer' configuration option. when using smapi, display the current power of the battery with index INDEX in watt. This is a separate variable because the original read out value is being converted from mW. The sign of the output reflects charging (positive) or discharging (negative) state. when using smapi, display the current temperature of the battery with index INDEX in degree Celsius. This is a separate variable because the original read out value is being converted from milli degree Celsius. Displays the Sony VAIO fanspeed information if sony-laptop kernel support is enabled. Linux only. Stippled (dashed) horizontal line Displays the data of a stock symbol. The following data 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) Amount of swap in use Bar that shows amount of swap in use Amount of free swap Total amount of swap Percentage of swap in use System name, Linux for example Puts a tab of the specified width, starting from column 'start'. The unit is pixels for both arguments. Displays last N lines of supplied text file. The file is checked every 'next_check' update. If next_check is not supplied, Conky defaults to 2. Max of 30 lines can be 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. TCP port (both IPv6 and IPv4) monitor for specified local ports. Port numbers must be in the range 1 to 65535. Valid items are: count rip rhost rport rservice lip lhost lport lservice The connection index provides you with access to each connection in the port monitor. The monitor will return information for index values from 0 to n-1 connections. Values higher than n-1 are simply ignored. For the "count" item, the connection index must be omitted. It is required for all other items. Examples: ${tcp_portmon 6881 6999 count} ${tcp_portmon 22 22 rip 0} ${tcp_portmon 22 22 rip 9} ${tcp_portmon 1 1024 rhost 0} ${tcp_portmon 1 1024 rport 4} ${tcp_portmon 1 65535 lservice 14} Note that port monitor variables which share the same port range actually refer to the same monitor, so many references to a single port range for different items and different indexes all use the same monitor internally. In other words, the program avoids creating redundant monitors. Evaluate the content of the templateN configuration variable (where N is a value between 0 and 9, inclusively), applying substitutions as described in the documentation of the corresponding configuration variable. The number of arguments is optional, but must match the highest referred index in the template. You can use the same special sequences in each argument as the ones valid for a template definition, e.g. to allow an argument to contain a whitespace. Also simple nesting of templates is possible this way. Here are some examples of template definitions, note they are placed between [[ ... ]] instead of ' ... ': template0 = [[$\1\2]] template1 = [[\1: ${fs_used \2} / ${fs_size \2}]] template2 = [[\1 \2]] The following list shows sample usage of the templates defined above, with the equivalent syntax when not using any template at all: using template same without template ${template0 node name} $nodename ${template1 root /} root: ${fs_free /} / ${fs_size /} ${template1 ${template2\ disk\ root} /} disk root: ${fs_free /} / ${fs_size /}
    Runs a command at an interval inside a thread and displays the output. Same as $execi, except the command is run inside a thread. Use this if you have a slow script to keep Conky updating. You should make the interval slightly longer then the time it takes your script to execute. For example, if you have a script that take 5 seconds to execute, you should make the interval at least 6 seconds. See also $execi. This object will clean up the thread when it is destroyed, so it can safely be used in a nested fashion, though it may not produce the desired behaviour if used this way. Same as execpi, except the command is run inside a thread. Total threads Local time, see man strftime to get more information about format If 'size' is a number followed by a size-unit (kilobyte,mb,GiB,...) then it converts the size to bytes and shows it without unit, otherwise it just shows 'size'. This takes arguments in the form:top (name) (number) Basically, processes are ranked from highest to lowest in terms of cpu usage, which is what (num) represents. The types are: "name", "pid", "cpu", "mem", "mem_res", "mem_vsize", "time", "uid", "user", "io_perc", "io_read" and "io_write". There can be a max of 10 processes listed. Same as top, except sorted by the amount of I/O the process has done during the update interval Same as top, except sorted by mem usage instead of cpu Same as top, except sorted by total CPU time instead of current CPU usage Total download, overflows at 4 GB on Linux with 32-bit arch and there doesn't seem to be a way to know how many times it has already done that before conky has started. Total upload, this one too, may overflow Number of mails marked as trashed in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Local time for specified timezone, see man strftime to get more information about format. The timezone argument is specified in similar fashion as TZ environment variable. For hints, look in /usr/share/zoneinfo. e.g. US/Pacific, Europe/Zurich, etc. Name of group with this gid Username of user with this uid Number of mails not marked as flagged in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Number of mails not marked as forwarded in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Number of mails not marked as replied in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. Number of new or unseen mails in the specified mailbox or mail spool if not. Only maildir type mailboxes are supported, mbox type will return -1. for debugging Upload speed in suitable IEC units Upload speed in KiB with one decimal Upload speed graph, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Uses a logarithmic scale (to see small numbers) when you use the -l switch. Takes the switch '-t' to use a temperature gradient, which makes the gradient values change depending on the amplitude of a particular graph value (try it and see). Uptime Uptime in a shorter format Lists the names of the users logged in Number of users logged in Lists the consoles in use Lists how long users have been logged in for Lists how long the user for the given console has been logged in for Display time in UTC (universal coordinate time). IPv6 addresses for an interface, followed by netmask if -n is specified and scope with -s. Scopes are Global(G), Host-local(H), Link-local(L), Site-local(S), Compat(C) and Unspecified(/). Linux only. Change vertical offset by N pixels. Negative values will cause text to overlap. See also $offset. Returns CPU #n's voltage in mV. CPUs are counted from 1. If omitted, the parameter defaults to 1. Returns CPU #n's voltage in V. CPUs are counted from 1. If omitted, the parameter defaults to 1. Download, parse and display METAR data. For the 'URI', there are two possibilities: http://weather.noaa.gov/pub/data/observations/metar/stations/ http://xoap.weather.com/weather/local/ The first one is free to use but the second requires you to register and obtain your partner ID and license key. These two must be written, separated by a space, into a file called .xoaprc which needs to be placed into your home directory. 'locID' must be a valid location identifier for the required uri. For the NOAA site this must be a valid ICAO (see for instance https://pilotweb.nas.faa.gov/qryhtml/icao/). For the weather.com site this must be a valid location ID (see for instance http://aspnetresources.com/tools/locid.aspx). 'data_type' must be one of the following: last_update The date and time stamp of the data. The result depends on the URI used. For the NOAA site it is date (yyyy/mm/dd) and UTC time. For the weather.com one it is date ([m]m/[d]d/yy) and Local Time of the station. temperature Air temperature (you can use the 'temperature_unit' config setting to change units) cloud_cover The highest cloud cover status pressure Air pressure in millibar wind_speed Wind speed in km/h wind_dir Wind direction wind_dir_DEG Compass wind direction humidity Relative humidity in % weather Any relevant weather event (rain, snow, etc.). This is not used if you are querying the weather.com site since this data is aggregated into the cloud_cover one icon Weather icon (only for www.weather.com). Can be used together with the icon kit provided upon registering to their service. 'delay_in_minutes' (optional, default 30) cannot be less than 30 minutes. This object is threaded, and once a thread is created it can't be explicitly destroyed. One thread will run for each URI specified. Note that these variables are still EXPERIMENTAL and can be subject to many future changes. Download, parse and display weather forecast data for a given day (daytime only). For the 'URI', for the time being only http://xoap.weather.com/weather/local/ is supported. See 'weather' above for details of usage 'locID', see 'weather' above. 'day' is a number from 0 (today) to 4 (3 days after tomorrow). 'data_type' must be one of the following: day date low hi icon forecast wind_speed wind_dir wind_dir_DEG humidity precipitation 'delay_in_minutes' (optional, default 210) cannot be lower than 210 min. This object is threaded, and once a thread is created it can't be explicitly destroyed. One thread will run for each URI specified. You can use any protocol that Curl supports. Note that these variables are still EXPERIMENTAL and can be subject to many future changes. Wireless access point MAC address (Linux only) Wireless bitrate (ie 11 Mb/s) (Linux only) WLAN channel on which device 'net' is listening (Linux only) Wireless access point ESSID (Linux only) Frequency on which device 'net' is listening (Linux only) Wireless link quality bar (Linux only) Wireless link quality (Linux only) Wireless link quality maximum value (Linux only) Wireless link quality in percents (Linux only) Wireless mode (Managed/Ad-Hoc/Master) (Linux only) Displays the number of words in the given file Album in current XMMS2 song Artist in current XMMS2 song Bar of XMMS2's progress Bitrate of current song Comment in current XMMS2 song Returns song's date. Duration of current song Song's elapsed time Genre in current XMMS2 song XMMS2 id of current song Percent of song's progress Returns the XMMS2 playlist. Size of current song Prints the song name in either the form "artist - title" or file name, depending on whats available XMMS2 status (Playing, Paused, Stopped, or Disconnected) Number of times a song was played (presumably). Title in current XMMS2 song Track number in current XMMS2 song Full path to current song
    conky-1.10.1/doc/variables.xsl000066400000000000000000000033671262311664100161750ustar00rootroot00000000000000 Conky Variables Conky Objects -

    #fffafa #b4cdcd
    Variable Arguments () = optional Explanation
    conky-1.10.1/extras/000077500000000000000000000000001262311664100142255ustar00rootroot00000000000000conky-1.10.1/extras/convert.lua000077500000000000000000000122321262311664100164130ustar00rootroot00000000000000#! /usr/bin/lua local usage = [[ Usage: convert.lua old_conkyrc [new_conkyrc] Tries to convert conkyrc from the old v1.x format to the new, lua-based format. Keep in mind that there is no guarantee that the output will work correctly with conky, or that it will be able to convert every conkyrc. However, it should provide a good starting point. Altough you can use this script with only 1 arg and let it overwrite the old config, it's suggested to use 2 args so that the new config is written in a new file (so that you have backup if something went wrong). For more information about the new format, read the wiki page ]]; local function quote(s) if not s:find("[\n'\\]") then return "'" .. s .. "'"; end; local q = ''; while s:find(']' .. q .. ']', 1, true) do q = q .. '='; end; return string.format('[%s[\n%s]%s]', q, s, q); end; local bool_setting = { background = true, disable_auto_reload = true, double_buffer = true, draw_borders = true, draw_graph_borders = true, draw_outline = true, draw_shades = true, extra_newline = true, format_human_readable = true, no_buffers = true, out_to_console = true, out_to_ncurses = true, out_to_stderr = true, out_to_x = true, override_utf8_locale = true, own_window = true, own_window_argb_visual = true, own_window_transparent = true, short_units = true, show_graph_range = true, show_graph_scale = true, times_in_seconds = true, top_cpu_separate = true, uppercase = true, use_xft = true }; local num_setting = { border_inner_margin = true, border_outer_margin = true, border_width = true, cpu_avg_samples = true, diskio_avg_samples = true, gap_x = true, gap_y = true, imlib_cache_flush_interval = true, imlib_cache_size = true, max_port_monitor_connections = true, max_text_width = true, max_user_text = true, maximum_width = true, mpd_port = true, music_player_interval = true, net_avg_samples = true, own_window_argb_value = true, pad_percents = true, stippled_borders = true, text_buffer_size = true, top_name_width = true, total_run_times = true, update_interval = true, update_interval_on_battery = true, xftalpha = true }; local split_setting = { default_bar_size = true, default_gauge_size = true, default_graph_size = true, minimum_size = true }; local colour_setting = { color0 = true, color1 = true, color2 = true, color3 = true, color4 = true, color5 = true, color6 = true, color7 = true, color8 = true, color9 = true, default_color = true, default_outline_color = true, default_shade_color = true, own_window_colour = true }; local function alignment_map(value) local map = { m = 'middle', t = 'top', b = 'bottom', r = 'right', l = 'left' }; if map[value] == nil then return value; else return map[value]; end; end; local function handle(setting, value) setting = setting:lower(); if setting == '' then return ''; end; if split_setting[setting] then local x, y = value:match('^(%S+)%s*(%S*)$'); local ret = setting:gsub('_size', '_width = ') .. x .. ','; if y ~= '' then ret = ret .. ' ' .. setting:gsub('_size', '_height = ') .. y .. ','; end; return '\t' .. ret; end; if bool_setting[setting] then value = value:lower(); if value == 'yes' or value == 'true' or value == '1' or value == '' then value = 'true'; else value = 'false'; end; elseif not num_setting[setting] then if setting == 'alignment' and value:len() == 2 then value = alignment_map(value:sub(1,1)) .. '_' .. alignment_map(value:sub(2,2)); elseif colour_setting[setting] and value:match('^[0-9a-fA-F]+$') then value = '#' .. value; elseif setting == 'xftfont' then setting = 'font'; end; value = quote(value); end; return '\t' .. setting .. ' = ' .. value .. ','; end; local function convert(s) local setting, comment = s:match('^([^#]*)#?(.*)\n$'); if comment ~= '' then comment = '--' .. comment; end; comment = comment .. '\n'; return handle(setting:match('^%s*(%S*)%s*(.-)%s*$')) .. comment; end; local input; local output; if conky == nil then --> standalone program -- 1 arg: arg is input and outputfile -- 2 args: 1st is inputfile, 2nd is outputfile -- 0, 3 or more args: print usage to STDERR and quit if #arg == 1 or #arg == 2 then input = io.input(arg[1]); else io.stderr:write(usage); return; end; else -- we are called from conky, the filename is the first argument input = io.open(..., 'r'); end; local config = input:read('*a'); input:close(); local settings, text = config:match('^(.-)TEXT\n(.*)$'); local converted = 'conky.config = {\n' .. settings:gsub('.-\n', convert) .. '};\n\nconky.text = ' .. quote(text) .. ';\n'; if conky == nil then if #arg == 2 then output = io.output(arg[2]); else output = io.output(arg[1]); end output:write(converted); output:close(); else return assert(loadstring(converted, 'converted config')); end; conky-1.10.1/extras/nano/000077500000000000000000000000001262311664100151605ustar00rootroot00000000000000conky-1.10.1/extras/nano/README000066400000000000000000000001601262311664100160350ustar00rootroot00000000000000Append the contents of conky.nanorc to your $HOME/.nanorc for nano syntax coloring of your $HOME/.conkyrc file. conky-1.10.1/extras/nano/conky.nanorc000066400000000000000000000142721262311664100175130ustar00rootroot00000000000000## ## Syntax highlighting for conkyrc files. ## ## 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_height|default_bar_width|default_color|default_gauge_height|default_gauge_width|default_graph_height|default_graph_width|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_height|minimum_width|mpd_host|mpd_password|mpd_port|music_player_interval|mysql_host|mysql_port|mysql_user|mysql_password|mysql_db|net_avg_samples|no_buffers|nvidia_display|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|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|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|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 "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)" color brightred "^TEXT$" conky-1.10.1/extras/vim/000077500000000000000000000000001262311664100150205ustar00rootroot00000000000000conky-1.10.1/extras/vim/README000066400000000000000000000003751262311664100157050ustar00rootroot00000000000000Vim filetype detection and syntax highlighting scripts for conky. Individual users can place them your personal .vim directory: ~/.vim/ftdetect/conkyrc.vim ~/.vim/syntax/conkyrc.vim Refer to your vim site documentation for system-wide installation. conky-1.10.1/extras/vim/ftdetect/000077500000000000000000000000001262311664100166225ustar00rootroot00000000000000conky-1.10.1/extras/vim/ftdetect/conkyrc.vim000066400000000000000000000002421262311664100210050ustar00rootroot00000000000000" Vim filetype detection file for Conky config files " au BufNewFile,BufRead *conkyrc set filetype=conkyrc au BufNewFile,BufRead conky.conf set filetype=conkyrc conky-1.10.1/extras/vim/syntax/000077500000000000000000000000001262311664100163465ustar00rootroot00000000000000conky-1.10.1/extras/vim/syntax/conkyrc.vim000066400000000000000000000164131262311664100205400ustar00rootroot00000000000000" Vim syntax file " Language: conkyrc " Author: Ciaran McCreesh " Version: 20060307 " Copyright: Copyright (c) 2005 Ciaran McCreesh " Licence: You may redistribute this under the same terms as Vim itself " if exists("b:current_syntax") finish 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_height default_bar_width default_color default_gauge_height default_gauge_width default_graph_height default_graph_width 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_height minimum_width mpd_host mpd_password mpd_port music_player_interval mysql_host mysql_port mysql_user mysql_password mysql_db net_avg_samples no_buffers nvidia_display 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 \ 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 syn match ConkyrcNumber /\S\@. # include(ToLua) add_definitions(-DTOLUA_RELEASE) set(CMAKE_C_FLAGS "-O3 ${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "-ggdb ${CMAKE_C_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS "-O3 ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb ${CMAKE_CXX_FLAGS_DEBUG}") if(BUILD_LUA_CAIRO) include_directories(${luacairo_includes} ${CMAKE_CURRENT_SOURCE_DIR}) # 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(conky-cairo SHARED ${luacairo_src}) set_target_properties(conky-cairo PROPERTIES OUTPUT_NAME "cairo") target_link_libraries(conky-cairo ${luacairo_libs} ${TOLUA_LIBS}) set(lua_libs ${lua_libs} conky-cairo) endif(BUILD_LUA_CAIRO) if(BUILD_LUA_IMLIB2) include_directories(${luaimlib2_includes} ${CMAKE_CURRENT_SOURCE_DIR}) wrap_tolua(luaimlib2_src imlib2.pkg) add_library(conky-imlib2 SHARED ${luaimlib2_src}) set_target_properties(conky-imlib2 PROPERTIES OUTPUT_NAME "imlib2") target_link_libraries(conky-imlib2 ${luaimlib2_libs} ${TOLUA_LIBS}) set(lua_libs ${lua_libs} conky-imlib2) endif(BUILD_LUA_IMLIB2) if(BUILD_LUA_RSVG) include_directories(${luarsvg_includes} ${CMAKE_CURRENT_SOURCE_DIR}) wrap_tolua(luarsvg_src rsvg.pkg) add_library(conky-rsvg SHARED ${luarsvg_src}) set_target_properties(conky-rsvg PROPERTIES OUTPUT_NAME "rsvg") target_link_libraries(conky-rsvg ${luarsvg_libs} ${TOLUA_LIBS}) set(lua_libs ${lua_libs} conky-rsvg) endif(BUILD_LUA_RSVG) if(BUILD_LUA_CAIRO AND BUILD_LUA_IMLIB2) include_directories(${luacairo_includes} ${luaimlib2_includes} ${CMAKE_CURRENT_SOURCE_DIR}) wrap_tolua(luacairo_imlib2_helper_src cairo_imlib2_helper.pkg) add_library(conky-cairo_imlib2_helper SHARED ${luacairo_imlib2_helper_src}) set_target_properties(conky-cairo_imlib2_helper PROPERTIES OUTPUT_NAME "cairo_imlib2_helper") target_link_libraries(conky-cairo_imlib2_helper ${luacairo_libs} ${luaimlib2_libs} ${TOLUA_LIBS}) set(lua_libs ${lua_libs} conky-cairo_imlib2_helper) endif(BUILD_LUA_CAIRO AND BUILD_LUA_IMLIB2) install(TARGETS ${lua_libs} LIBRARY DESTINATION lib${LIB_SUFFIX}/conky ARCHIVE DESTINATION lib${LIB_SUFFIX}/conky ) conky-1.10.1/lua/cairo.pkg000066400000000000000000000725511262311664100153120ustar00rootroot00000000000000$#include $#include $#include $#include $#include $#include /* * This code was mostly copied from cairo.h and cairo-xlib.h with comments * removed. The licence noticed below is present for the sake of clarity. */ /* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California * Copyright © 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is University of Southern * California. * * Contributor(s): * Carl D. Worth */ typedef enum _cairo_antialias { CAIRO_ANTIALIAS_DEFAULT, CAIRO_ANTIALIAS_NONE, CAIRO_ANTIALIAS_GRAY, CAIRO_ANTIALIAS_SUBPIXEL } cairo_antialias_t; typedef struct _cairo_matrix { double xx; double yx; double xy; double yy; double x0; double y0; static tolua_outside cairo_matrix_t* create_cairo_matrix_t @ create(); } cairo_matrix_t; typedef int cairo_bool_t; typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_pattern cairo_pattern_t; typedef struct _cairo_user_data_key { int unused; } cairo_user_data_key_t; typedef enum _cairo_status { CAIRO_STATUS_SUCCESS = 0, CAIRO_STATUS_NO_MEMORY, CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP, CAIRO_STATUS_NO_CURRENT_POINT, CAIRO_STATUS_INVALID_MATRIX, CAIRO_STATUS_INVALID_STATUS, CAIRO_STATUS_NULL_POINTER, CAIRO_STATUS_INVALID_STRING, CAIRO_STATUS_INVALID_PATH_DATA, CAIRO_STATUS_READ_ERROR, CAIRO_STATUS_WRITE_ERROR, CAIRO_STATUS_SURFACE_FINISHED, CAIRO_STATUS_SURFACE_TYPE_MISMATCH, CAIRO_STATUS_PATTERN_TYPE_MISMATCH, CAIRO_STATUS_INVALID_CONTENT, CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL, CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH, CAIRO_STATUS_INVALID_DSC_COMMENT, CAIRO_STATUS_INVALID_INDEX, CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, CAIRO_STATUS_TEMP_FILE_ERROR, CAIRO_STATUS_INVALID_STRIDE, CAIRO_STATUS_FONT_TYPE_MISMATCH, CAIRO_STATUS_USER_FONT_IMMUTABLE, CAIRO_STATUS_USER_FONT_ERROR, CAIRO_STATUS_NEGATIVE_COUNT, CAIRO_STATUS_INVALID_CLUSTERS, CAIRO_STATUS_INVALID_SLANT, CAIRO_STATUS_INVALID_WEIGHT } cairo_status_t; typedef enum _cairo_content { CAIRO_CONTENT_COLOR = 0x1000, CAIRO_CONTENT_ALPHA = 0x2000, CAIRO_CONTENT_COLOR_ALPHA = 0x3000 } cairo_content_t; typedef enum _cairo_operator { CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_OVER, CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_ATOP, CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_DEST_OVER, CAIRO_OPERATOR_DEST_IN, CAIRO_OPERATOR_DEST_OUT, CAIRO_OPERATOR_DEST_ATOP, CAIRO_OPERATOR_XOR, CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE, /* blending modes */ /* source and destination layers are multiplied. This causes the result to be at least as dark as the darker inputs. (Since 1.10) */ CAIRO_OPERATOR_MULTIPLY, /* source and destination are complemented and multiplied. This causes the result to be at least as light as the lighter inputs. (Since 1.10) */ CAIRO_OPERATOR_SCREEN, /* multiplies or screens, depending on the lightness of the destination color. (Since 1.10) */ CAIRO_OPERATOR_OVERLAY, /* replaces the destination with the source if it is darker, otherwise keeps the source. (Since 1.10) */ CAIRO_OPERATOR_DARKEN, /* replaces the destination with the source if it is lighter, otherwise keeps the source. (Since 1.10) */ CAIRO_OPERATOR_LIGHTEN, /* brightens the destination color to reflect the source color. (Since 1.10) */ CAIRO_OPERATOR_COLOR_DODGE, /* darkens the destination color to reflect the source color. (Since 1.10) */ CAIRO_OPERATOR_COLOR_BURN, /* Multiplies or screens, dependent on source color. (Since 1.10) */ CAIRO_OPERATOR_HARD_LIGHT, /* Darkens or lightens, dependent on source color. (Since 1.10) */ CAIRO_OPERATOR_SOFT_LIGHT, /* Takes the difference of the source and destination color. (Since 1.10) */ CAIRO_OPERATOR_DIFFERENCE, /* Produces an effect similar to difference, but with lower contrast. (Since 1.10) */ CAIRO_OPERATOR_EXCLUSION, /* Creates a color with the hue of the source and the saturation and luminosity of the target. (Since 1.10) */ CAIRO_OPERATOR_HSL_HUE, /* Creates a color with the saturation of the source and the hue and luminosity of the target. Painting with this mode onto a gray area produces no change. (Since 1.10) */ CAIRO_OPERATOR_HSL_SATURATION, /* Creates a color with the hue and saturation of the source and the luminosity of the target. This preserves the gray levels of the target and is useful for coloring monochrome images or tinting color images. (Since 1.10) */ CAIRO_OPERATOR_HSL_COLOR, /* Creates a color with the luminosity of the source and the hue and saturation of the target. This produces an inverse effect to CAIRO_OPERATOR_HSL_COLOR. (Since 1.10) */ CAIRO_OPERATOR_HSL_LUMINOSITY } cairo_operator_t; typedef enum _cairo_filter { CAIRO_FILTER_FAST, CAIRO_FILTER_GOOD, CAIRO_FILTER_BEST, CAIRO_FILTER_NEAREST, CAIRO_FILTER_BILINEAR, CAIRO_FILTER_GAUSSIAN } cairo_filter_t; cairo_surface_t *cairo_xlib_surface_create(Display * dpy, Drawable drawable, Visual * visual, int width, int height); cairo_surface_t *cairo_xlib_surface_create_for_bitmap(Display * dpy, Pixmap bitmap, Screen * screen, int width, int height); void cairo_xlib_surface_set_size(cairo_surface_t * surface, int width, int height); void cairo_xlib_surface_set_drawable(cairo_surface_t * surface, Drawable drawable, int width, int height); Display *cairo_xlib_surface_get_display(cairo_surface_t * surface); Drawable cairo_xlib_surface_get_drawable(cairo_surface_t * surface); Screen *cairo_xlib_surface_get_screen(cairo_surface_t * surface); Visual *cairo_xlib_surface_get_visual(cairo_surface_t * surface); int cairo_xlib_surface_get_depth(cairo_surface_t * surface); int cairo_xlib_surface_get_width(cairo_surface_t * surface); int cairo_xlib_surface_get_height(cairo_surface_t * surface); int cairo_version(void); const char *cairo_version_string(void); cairo_t *cairo_create(cairo_surface_t * target); cairo_t *cairo_reference(cairo_t * cr); void cairo_destroy(cairo_t * cr); unsigned int cairo_get_reference_count(cairo_t * cr); void *cairo_get_user_data(cairo_t * cr, const cairo_user_data_key_t * key); cairo_status_t cairo_set_user_data(cairo_t * cr, const cairo_user_data_key_t * key, void *user_data, cairo_destroy_func_t destroy); void cairo_save(cairo_t * cr); void cairo_restore(cairo_t * cr); void cairo_push_group(cairo_t * cr); void cairo_push_group_with_content(cairo_t * cr, cairo_content_t content); cairo_pattern_t *cairo_pop_group(cairo_t * cr); void cairo_pop_group_to_source(cairo_t * cr); void cairo_set_operator(cairo_t * cr, cairo_operator_t op); void cairo_set_source(cairo_t * cr, cairo_pattern_t * source); void cairo_set_source_rgb(cairo_t * cr, double red, double green, double blue); void cairo_set_source_rgba(cairo_t * cr, double red, double green, double blue, double alpha); void cairo_set_source_surface(cairo_t * cr, cairo_surface_t * surface, double x, double y); void cairo_set_tolerance(cairo_t * cr, double tolerance); void cairo_set_antialias(cairo_t * cr, cairo_antialias_t antialias); typedef enum _cairo_fill_rule { CAIRO_FILL_RULE_WINDING, CAIRO_FILL_RULE_EVEN_ODD } cairo_fill_rule_t; void cairo_set_fill_rule(cairo_t * cr, cairo_fill_rule_t fill_rule); void cairo_set_line_width(cairo_t * cr, double width); typedef enum _cairo_line_cap { CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_SQUARE } cairo_line_cap_t; void cairo_set_line_cap(cairo_t * cr, cairo_line_cap_t line_cap); typedef enum _cairo_line_join { CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_ROUND, CAIRO_LINE_JOIN_BEVEL } cairo_line_join_t; void cairo_set_line_join(cairo_t * cr, cairo_line_join_t line_join); 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); void cairo_translate(cairo_t * cr, double tx, double ty); void cairo_scale(cairo_t * cr, double sx, double sy); void cairo_rotate(cairo_t * cr, double angle); void cairo_transform(cairo_t * cr, cairo_matrix_t * matrix); void cairo_set_matrix(cairo_t * cr, cairo_matrix_t * matrix); void cairo_identity_matrix(cairo_t * cr); void cairo_user_to_device(cairo_t * cr, double *x, double *y); void cairo_user_to_device_distance(cairo_t * cr, double *dx, double *dy); void cairo_device_to_user(cairo_t * cr, double *x, double *y); void cairo_device_to_user_distance(cairo_t * cr, double *dx, double *dy); void cairo_new_path(cairo_t * cr); void cairo_move_to(cairo_t * cr, double x, double y); void cairo_new_sub_path(cairo_t * cr); void cairo_line_to(cairo_t * cr, double x, double y); void cairo_curve_to(cairo_t * cr, double x1, double y1, double x2, double y2, double x3, double y3); void cairo_arc(cairo_t * cr, double xc, double yc, double radius, double angle1, double angle2); void cairo_arc_negative(cairo_t * cr, double xc, double yc, double radius, double angle1, double angle2); void cairo_rel_move_to(cairo_t * cr, double dx, double dy); void cairo_rel_line_to(cairo_t * cr, double dx, double dy); void cairo_rel_curve_to(cairo_t * cr, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3); void cairo_rectangle(cairo_t * cr, double x, double y, double width, double height); void cairo_close_path(cairo_t * cr); void cairo_path_extents(cairo_t * cr, double *x1, double *y1, double *x2, double *y2); void cairo_paint(cairo_t * cr); void cairo_paint_with_alpha(cairo_t * cr, double alpha); void cairo_mask(cairo_t * cr, cairo_pattern_t * pattern); void cairo_mask_surface(cairo_t * cr, cairo_surface_t * surface, double surface_x, double surface_y); void cairo_stroke(cairo_t * cr); void cairo_stroke_preserve(cairo_t * cr); void cairo_fill(cairo_t * cr); void cairo_fill_preserve(cairo_t * cr); void cairo_copy_page(cairo_t * cr); void cairo_show_page(cairo_t * cr); cairo_bool_t cairo_in_stroke(cairo_t * cr, double x, double y); cairo_bool_t cairo_in_fill(cairo_t * cr, double x, double y); void cairo_stroke_extents(cairo_t * cr, double *x1, double *y1, double *x2, double *y2); void cairo_fill_extents(cairo_t * cr, double *x1, double *y1, double *x2, double *y2); void cairo_reset_clip(cairo_t * cr); void cairo_clip(cairo_t * cr); void cairo_clip_preserve(cairo_t * cr); void cairo_clip_extents(cairo_t * cr, double *x1, double *y1, double *x2, double *y2); typedef struct _cairo_rectangle { double x, y, width, height; } cairo_rectangle_t; typedef struct _cairo_rectangle_list { cairo_status_t status; cairo_rectangle_t *rectangles; int num_rectangles; } cairo_rectangle_list_t; cairo_rectangle_list_t *cairo_copy_clip_rectangle_list(cairo_t * cr); void cairo_rectangle_list_destroy(cairo_rectangle_list_t * rectangle_list); typedef struct _cairo_scaled_font cairo_scaled_font_t; typedef struct _cairo_font_face cairo_font_face_t; typedef struct { unsigned long index; double x; double y; } cairo_glyph_t; cairo_glyph_t *cairo_glyph_allocate(int num_glyphs); void cairo_glyph_free(cairo_glyph_t * glyphs); typedef struct { int num_bytes; int num_glyphs; } cairo_text_cluster_t; cairo_text_cluster_t *cairo_text_cluster_allocate(int num_clusters); void cairo_text_cluster_free(cairo_text_cluster_t * clusters); typedef enum _cairo_text_cluster_flags { CAIRO_TEXT_CLUSTER_FLAG_BACKWARD = 0x00000001 } cairo_text_cluster_flags_t; typedef struct { double x_bearing; double y_bearing; double width; double height; double x_advance; double y_advance; static tolua_outside cairo_text_extents_t* create_cairo_text_extents_t @ create(); } cairo_text_extents_t; typedef struct { double ascent; double descent; double height; double max_x_advance; double max_y_advance; static tolua_outside cairo_font_extents_t* create_cairo_font_extents_t @ create(); } cairo_font_extents_t; typedef enum _cairo_font_slant { CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_SLANT_OBLIQUE } cairo_font_slant_t; typedef enum _cairo_font_weight { CAIRO_FONT_WEIGHT_NORMAL, CAIRO_FONT_WEIGHT_BOLD } cairo_font_weight_t; typedef enum _cairo_subpixel_order { CAIRO_SUBPIXEL_ORDER_DEFAULT, CAIRO_SUBPIXEL_ORDER_RGB, CAIRO_SUBPIXEL_ORDER_BGR, CAIRO_SUBPIXEL_ORDER_VRGB, CAIRO_SUBPIXEL_ORDER_VBGR } cairo_subpixel_order_t; typedef enum _cairo_hint_style { CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_STYLE_NONE, CAIRO_HINT_STYLE_SLIGHT, CAIRO_HINT_STYLE_MEDIUM, CAIRO_HINT_STYLE_FULL } cairo_hint_style_t; typedef enum _cairo_hint_metrics { CAIRO_HINT_METRICS_DEFAULT, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_METRICS_ON } cairo_hint_metrics_t; typedef struct _cairo_font_options cairo_font_options_t; cairo_font_options_t *cairo_font_options_create(void); cairo_font_options_t *cairo_font_options_copy(cairo_font_options_t * original); void cairo_font_options_destroy(cairo_font_options_t * options); cairo_status_t cairo_font_options_status(cairo_font_options_t * options); void cairo_font_options_merge(cairo_font_options_t * options, cairo_font_options_t * other); cairo_bool_t cairo_font_options_equal(cairo_font_options_t * options, cairo_font_options_t * other); unsigned long cairo_font_options_hash(cairo_font_options_t * options); void cairo_font_options_set_antialias(cairo_font_options_t * options, cairo_antialias_t antialias); cairo_antialias_t cairo_font_options_get_antialias(cairo_font_options_t * options); void cairo_font_options_set_subpixel_order(cairo_font_options_t * options, cairo_subpixel_order_t subpixel_order); cairo_subpixel_order_t cairo_font_options_get_subpixel_order(cairo_font_options_t * options); void cairo_font_options_set_hint_style(cairo_font_options_t * options, cairo_hint_style_t hint_style); cairo_hint_style_t cairo_font_options_get_hint_style(cairo_font_options_t * options); void cairo_font_options_set_hint_metrics(cairo_font_options_t * options, cairo_hint_metrics_t hint_metrics); cairo_hint_metrics_t cairo_font_options_get_hint_metrics(cairo_font_options_t * options); void cairo_select_font_face(cairo_t * cr, const char *family, cairo_font_slant_t slant, cairo_font_weight_t weight); void cairo_set_font_size(cairo_t * cr, double size); void cairo_set_font_matrix(cairo_t * cr, cairo_matrix_t * matrix); void cairo_get_font_matrix(cairo_t * cr, cairo_matrix_t * matrix); void cairo_set_font_options(cairo_t * cr, cairo_font_options_t * options); void cairo_get_font_options(cairo_t * cr, cairo_font_options_t * options); void cairo_set_font_face(cairo_t * cr, cairo_font_face_t * font_face); cairo_font_face_t *cairo_get_font_face(cairo_t * cr); void cairo_set_scaled_font(cairo_t * cr, cairo_scaled_font_t * scaled_font); cairo_scaled_font_t *cairo_get_scaled_font(cairo_t * cr); void cairo_show_text(cairo_t * cr, const char *utf8); void cairo_show_glyphs(cairo_t * cr, const cairo_glyph_t * glyphs, int num_glyphs); void cairo_show_text_glyphs(cairo_t * cr, const char *utf8, int utf8_len, const cairo_glyph_t * glyphs, int num_glyphs, const cairo_text_cluster_t * clusters, int num_clusters, cairo_text_cluster_flags_t cluster_flags); void cairo_text_path(cairo_t * cr, const char *utf8); void cairo_glyph_path(cairo_t * cr, const cairo_glyph_t * glyphs, int num_glyphs); void cairo_text_extents(cairo_t * cr, const char *utf8, cairo_text_extents_t * extents); void cairo_glyph_extents(cairo_t * cr, const cairo_glyph_t * glyphs, int num_glyphs, cairo_text_extents_t * extents); void cairo_font_extents(cairo_t * cr, cairo_font_extents_t * extents); cairo_font_face_t *cairo_font_face_reference(cairo_font_face_t * font_face); void cairo_font_face_destroy(cairo_font_face_t * font_face); unsigned int cairo_font_face_get_reference_count(cairo_font_face_t * font_face); cairo_status_t cairo_font_face_status(cairo_font_face_t * font_face); typedef enum _cairo_font_type { CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, CAIRO_FONT_TYPE_WIN32, CAIRO_FONT_TYPE_QUARTZ, CAIRO_FONT_TYPE_USER } cairo_font_type_t; cairo_font_type_t cairo_font_face_get_type(cairo_font_face_t * font_face); void *cairo_font_face_get_user_data(cairo_font_face_t * font_face, const cairo_user_data_key_t * key); cairo_status_t cairo_font_face_set_user_data(cairo_font_face_t * font_face, const cairo_user_data_key_t * key, void *user_data, cairo_destroy_func_t destroy); cairo_scaled_font_t *cairo_scaled_font_create(cairo_font_face_t * font_face, cairo_matrix_t * font_matrix, cairo_matrix_t * ctm, cairo_font_options_t * options); cairo_scaled_font_t *cairo_scaled_font_reference(cairo_scaled_font_t * scaled_font); void cairo_scaled_font_destroy(cairo_scaled_font_t * scaled_font); unsigned int cairo_scaled_font_get_reference_count(cairo_scaled_font_t * scaled_font); cairo_status_t cairo_scaled_font_status(cairo_scaled_font_t * scaled_font); cairo_font_type_t cairo_scaled_font_get_type(cairo_scaled_font_t * scaled_font); void *cairo_scaled_font_get_user_data(cairo_scaled_font_t * scaled_font, const cairo_user_data_key_t * key); cairo_status_t cairo_scaled_font_set_user_data(cairo_scaled_font_t * scaled_font, const cairo_user_data_key_t * key, void *user_data, cairo_destroy_func_t destroy); void cairo_scaled_font_extents(cairo_scaled_font_t * scaled_font, cairo_font_extents_t * extents); void cairo_scaled_font_text_extents(cairo_scaled_font_t * scaled_font, const char *utf8, cairo_text_extents_t * extents); void cairo_scaled_font_glyph_extents(cairo_scaled_font_t * scaled_font, const cairo_glyph_t * glyphs, int num_glyphs, cairo_text_extents_t * extents); cairo_status_t cairo_scaled_font_text_to_glyphs(cairo_scaled_font_t * scaled_font, double x, double y, const char *utf8, int utf8_len, cairo_glyph_t ** glyphs, int *num_glyphs, cairo_text_cluster_t ** clusters, int *num_clusters, cairo_text_cluster_flags_t * cluster_flags); cairo_font_face_t *cairo_scaled_font_get_font_face(cairo_scaled_font_t * scaled_font); void cairo_scaled_font_get_font_matrix(cairo_scaled_font_t * scaled_font, cairo_matrix_t * font_matrix); void cairo_scaled_font_get_ctm(cairo_scaled_font_t * scaled_font, cairo_matrix_t * ctm); void cairo_scaled_font_get_scale_matrix(cairo_scaled_font_t * scaled_font, cairo_matrix_t * scale_matrix); void cairo_scaled_font_get_font_options(cairo_scaled_font_t * scaled_font, cairo_font_options_t * options); cairo_font_face_t *cairo_toy_font_face_create(const char *family, cairo_font_slant_t slant, cairo_font_weight_t weight); const char *cairo_toy_font_face_get_family(cairo_font_face_t * font_face); cairo_font_slant_t cairo_toy_font_face_get_slant(cairo_font_face_t * font_face); cairo_font_weight_t cairo_toy_font_face_get_weight(cairo_font_face_t * font_face); cairo_font_face_t *cairo_user_font_face_create(void); void cairo_user_font_face_set_init_func(cairo_font_face_t * font_face, cairo_user_scaled_font_init_func_t init_func); void cairo_user_font_face_set_render_glyph_func(cairo_font_face_t * font_face, cairo_user_scaled_font_render_glyph_func_t render_glyph_func); void cairo_user_font_face_set_text_to_glyphs_func(cairo_font_face_t * font_face, cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func); void cairo_user_font_face_set_unicode_to_glyph_func(cairo_font_face_t * font_face, cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func); cairo_user_scaled_font_init_func_t cairo_user_font_face_get_init_func(cairo_font_face_t * font_face); cairo_user_scaled_font_render_glyph_func_t cairo_user_font_face_get_render_glyph_func(cairo_font_face_t * font_face); cairo_user_scaled_font_text_to_glyphs_func_t cairo_user_font_face_get_text_to_glyphs_func(cairo_font_face_t * font_face); cairo_user_scaled_font_unicode_to_glyph_func_t cairo_user_font_face_get_unicode_to_glyph_func(cairo_font_face_t * font_face); cairo_operator_t cairo_get_operator(cairo_t * cr); cairo_pattern_t *cairo_get_source(cairo_t * cr); double cairo_get_tolerance(cairo_t * cr); cairo_antialias_t cairo_get_antialias(cairo_t * cr); cairo_bool_t cairo_has_current_point(cairo_t * cr); void cairo_get_current_point(cairo_t * cr, double *x, double *y); cairo_fill_rule_t cairo_get_fill_rule(cairo_t * cr); double cairo_get_line_width(cairo_t * cr); cairo_line_cap_t cairo_get_line_cap(cairo_t * cr); cairo_line_join_t cairo_get_line_join(cairo_t * cr); double cairo_get_miter_limit(cairo_t * cr); int cairo_get_dash_count(cairo_t * cr); void cairo_get_dash(cairo_t * cr, double *dashes, double *offset); void cairo_get_matrix(cairo_t * cr, cairo_matrix_t * matrix); cairo_surface_t *cairo_get_target(cairo_t * cr); cairo_surface_t *cairo_get_group_target(cairo_t * cr); typedef enum _cairo_path_data_type { CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, CAIRO_PATH_CURVE_TO, CAIRO_PATH_CLOSE_PATH } cairo_path_data_type_t; typedef union _cairo_path_data_t cairo_path_data_t; typedef struct cairo_path { cairo_status_t status; cairo_path_data_t *data; int num_data; } cairo_path_t; cairo_path_t *cairo_copy_path(cairo_t * cr); cairo_path_t *cairo_copy_path_flat(cairo_t * cr); void cairo_append_path(cairo_t * cr, const cairo_path_t * path); void cairo_path_destroy(cairo_path_t * path); cairo_status_t cairo_status(cairo_t * cr); const char *cairo_status_to_string(cairo_status_t status); cairo_surface_t *cairo_surface_create_similar(cairo_surface_t * other, cairo_content_t content, int width, int height); cairo_surface_t *cairo_surface_reference(cairo_surface_t * surface); void cairo_surface_finish(cairo_surface_t * surface); void cairo_surface_destroy(cairo_surface_t * surface); unsigned int cairo_surface_get_reference_count(cairo_surface_t * surface); cairo_status_t cairo_surface_status(cairo_surface_t * surface); typedef enum _cairo_surface_type { CAIRO_SURFACE_TYPE_IMAGE, CAIRO_SURFACE_TYPE_PDF, CAIRO_SURFACE_TYPE_PS, CAIRO_SURFACE_TYPE_XLIB, CAIRO_SURFACE_TYPE_XCB, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_SURFACE_TYPE_WIN32, CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2, CAIRO_SURFACE_TYPE_WIN32_PRINTING, CAIRO_SURFACE_TYPE_QUARTZ_IMAGE } cairo_surface_type_t; cairo_surface_type_t cairo_surface_get_type(cairo_surface_t * surface); cairo_content_t cairo_surface_get_content(cairo_surface_t * surface); cairo_status_t cairo_surface_write_to_png(cairo_surface_t * surface, const char *filename); cairo_status_t cairo_surface_write_to_png_stream(cairo_surface_t * surface, cairo_write_func_t write_func, void *closure); void *cairo_surface_get_user_data(cairo_surface_t * surface, const cairo_user_data_key_t * key); cairo_status_t cairo_surface_set_user_data(cairo_surface_t * surface, const cairo_user_data_key_t * key, void *user_data, cairo_destroy_func_t destroy); void cairo_surface_get_font_options(cairo_surface_t * surface, cairo_font_options_t * options); void cairo_surface_flush(cairo_surface_t * surface); void cairo_surface_mark_dirty(cairo_surface_t * surface); void cairo_surface_mark_dirty_rectangle(cairo_surface_t * surface, int x, int y, int width, int height); void cairo_surface_set_device_offset(cairo_surface_t * surface, double x_offset, double y_offset); void cairo_surface_get_device_offset(cairo_surface_t * surface, double *x_offset, double *y_offset); void cairo_surface_set_fallback_resolution(cairo_surface_t * surface, double x_pixels_per_inch, double y_pixels_per_inch); void cairo_surface_get_fallback_resolution(cairo_surface_t * surface, double *x_pixels_per_inch, double *y_pixels_per_inch); void cairo_surface_copy_page(cairo_surface_t * surface); void cairo_surface_show_page(cairo_surface_t * surface); cairo_bool_t cairo_surface_has_show_text_glyphs(cairo_surface_t * surface); typedef enum _cairo_format { CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, CAIRO_FORMAT_A8, CAIRO_FORMAT_A1 } cairo_format_t; cairo_surface_t *cairo_image_surface_create(cairo_format_t format, int width, int height); int cairo_format_stride_for_width(cairo_format_t format, int width); cairo_surface_t *cairo_image_surface_create_for_data(unsigned char *data, cairo_format_t format, int width, int height, int stride); unsigned char *cairo_image_surface_get_data(cairo_surface_t * surface); cairo_format_t cairo_image_surface_get_format(cairo_surface_t * surface); int cairo_image_surface_get_width(cairo_surface_t * surface); int cairo_image_surface_get_height(cairo_surface_t * surface); int cairo_image_surface_get_stride(cairo_surface_t * surface); cairo_surface_t *cairo_image_surface_create_from_png(const char *filename); cairo_surface_t *cairo_image_surface_create_from_png_stream(cairo_read_func_t read_func, void *closure); cairo_pattern_t *cairo_pattern_create_rgb(double red, double green, double blue); cairo_pattern_t *cairo_pattern_create_rgba(double red, double green, double blue, double alpha); cairo_pattern_t *cairo_pattern_create_for_surface(cairo_surface_t * surface); cairo_pattern_t *cairo_pattern_create_linear(double x0, double y0, double x1, double y1); cairo_pattern_t *cairo_pattern_create_radial(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1); cairo_pattern_t *cairo_pattern_reference(cairo_pattern_t * pattern); void cairo_pattern_destroy(cairo_pattern_t * pattern); unsigned int cairo_pattern_get_reference_count(cairo_pattern_t * pattern); cairo_status_t cairo_pattern_status(cairo_pattern_t * pattern); void *cairo_pattern_get_user_data(cairo_pattern_t * pattern, const cairo_user_data_key_t * key); cairo_status_t cairo_pattern_set_user_data(cairo_pattern_t * pattern, const cairo_user_data_key_t * key, void *user_data, cairo_destroy_func_t destroy); typedef enum _cairo_pattern_type { CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE, CAIRO_PATTERN_TYPE_LINEAR, CAIRO_PATTERN_TYPE_RADIAL } cairo_pattern_type_t; cairo_pattern_type_t cairo_pattern_get_type(cairo_pattern_t * pattern); void cairo_pattern_add_color_stop_rgb(cairo_pattern_t * pattern, double offset, double red, double green, double blue); void cairo_pattern_add_color_stop_rgba(cairo_pattern_t * pattern, double offset, double red, double green, double blue, double alpha); void cairo_pattern_set_matrix(cairo_pattern_t * pattern, cairo_matrix_t * matrix); void cairo_pattern_get_matrix(cairo_pattern_t * pattern, cairo_matrix_t * matrix); typedef enum _cairo_extend { CAIRO_EXTEND_NONE, CAIRO_EXTEND_REPEAT, CAIRO_EXTEND_REFLECT, CAIRO_EXTEND_PAD } cairo_extend_t; void cairo_pattern_set_extend(cairo_pattern_t * pattern, cairo_extend_t extend); cairo_extend_t cairo_pattern_get_extend(cairo_pattern_t * pattern); void cairo_pattern_set_filter(cairo_pattern_t * pattern, cairo_filter_t filter); cairo_filter_t cairo_pattern_get_filter(cairo_pattern_t * pattern); cairo_status_t cairo_pattern_get_rgba(cairo_pattern_t * pattern, double *red, double *green, double *blue, double *alpha); cairo_status_t cairo_pattern_get_surface(cairo_pattern_t * pattern, cairo_surface_t ** surface); cairo_status_t cairo_pattern_get_color_stop_rgba(cairo_pattern_t * pattern, int index, double *offset, double *red, double *green, double *blue, double *alpha); cairo_status_t cairo_pattern_get_color_stop_count(cairo_pattern_t * pattern, int *count); cairo_status_t cairo_pattern_get_linear_points(cairo_pattern_t * pattern, double *x0, double *y0, double *x1, double *y1); cairo_status_t cairo_pattern_get_radial_circles(cairo_pattern_t * pattern, double *x0, double *y0, double *r0, double *x1, double *y1, double *r1); void cairo_matrix_init(cairo_matrix_t * matrix, double xx, double yx, double xy, double yy, double x0, double y0); void cairo_matrix_init_identity(cairo_matrix_t * matrix); void cairo_matrix_init_translate(cairo_matrix_t * matrix, double tx, double ty); void cairo_matrix_init_scale(cairo_matrix_t * matrix, double sx, double sy); void cairo_matrix_init_rotate(cairo_matrix_t * matrix, double radians); void cairo_matrix_translate(cairo_matrix_t * matrix, double tx, double ty); void cairo_matrix_scale(cairo_matrix_t * matrix, double sx, double sy); void cairo_matrix_rotate(cairo_matrix_t * matrix, double radians); cairo_status_t cairo_matrix_invert(cairo_matrix_t * matrix); void cairo_matrix_multiply(cairo_matrix_t * result, cairo_matrix_t * a, cairo_matrix_t * b); void cairo_matrix_transform_distance(cairo_matrix_t * matrix, double *dx, double *dy); void cairo_matrix_transform_point(cairo_matrix_t * matrix, double *x, double *y); void cairo_debug_reset_static_data(void); conky-1.10.1/lua/cairo_imlib2_helper.pkg000066400000000000000000000003241262311664100200740ustar00rootroot00000000000000$#include $#include void cairo_draw_image(const char *, cairo_surface_t *, int, int, double, double, double * return_scale_w, double * return_scale_h); conky-1.10.1/lua/imlib2.pkg000066400000000000000000000400601262311664100153610ustar00rootroot00000000000000$#include $#include $#define _userdata void* typedef void *Imlib_Context; typedef void *Imlib_Image; typedef void *Imlib_Color_Modifier; typedef void *Imlib_Updates; typedef void *Imlib_Font; typedef void *Imlib_Color_Range; typedef void *Imlib_Filter; typedef struct _imlib_color Imlib_Color; typedef void *ImlibPolygon; enum _imlib_operation { IMLIB_OP_COPY, IMLIB_OP_ADD, IMLIB_OP_SUBTRACT, IMLIB_OP_RESHADE }; enum _imlib_text_direction { IMLIB_TEXT_TO_RIGHT = 0, IMLIB_TEXT_TO_LEFT = 1, IMLIB_TEXT_TO_DOWN = 2, IMLIB_TEXT_TO_UP = 3, IMLIB_TEXT_TO_ANGLE = 4 }; enum _imlib_load_error { IMLIB_LOAD_ERROR_NONE, IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST, IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY, IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ, IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT, IMLIB_LOAD_ERROR_PATH_TOO_LONG, IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT, IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY, IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE, IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS, IMLIB_LOAD_ERROR_OUT_OF_MEMORY, IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS, IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE, IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE, IMLIB_LOAD_ERROR_UNKNOWN }; enum _imlib_TTF_encoding { IMLIB_TTF_ENCODING_ISO_8859_1, IMLIB_TTF_ENCODING_ISO_8859_2, IMLIB_TTF_ENCODING_ISO_8859_3, IMLIB_TTF_ENCODING_ISO_8859_4, IMLIB_TTF_ENCODING_ISO_8859_5 }; typedef enum _imlib_operation Imlib_Operation; typedef enum _imlib_load_error Imlib_Load_Error; typedef enum _imlib_load_error ImlibLoadError; typedef enum _imlib_text_direction Imlib_Text_Direction; typedef enum _imlib_TTF_encoding Imlib_TTF_Encoding; typedef struct _imlib_border Imlib_Border; Imlib_Context imlib_context_new(void); void imlib_context_free(Imlib_Context context); void imlib_context_push(Imlib_Context context); void imlib_context_pop(void); Imlib_Context imlib_context_get(void); void imlib_context_set_display(Display * display); void imlib_context_disconnect_display(void); void imlib_context_set_visual(Visual * visual); void imlib_context_set_colormap(Colormap colormap); void imlib_context_set_drawable(Drawable drawable); void imlib_context_set_mask(Pixmap mask); void imlib_context_set_dither_mask(char dither_mask); void imlib_context_set_mask_alpha_threshold(int mask_alpha_threshold); void imlib_context_set_anti_alias(char anti_alias); void imlib_context_set_dither(char dither); void imlib_context_set_blend(char blend); void imlib_context_set_color_modifier(Imlib_Color_Modifier color_modifier); void imlib_context_set_operation(Imlib_Operation operation); void imlib_context_set_font(Imlib_Font font); void imlib_context_set_direction(Imlib_Text_Direction direction); void imlib_context_set_angle(double angle); void imlib_context_set_color(int red, int green, int blue, int alpha); void imlib_context_set_color_hsva(float hue, float saturation, float value, int alpha); void imlib_context_set_color_hlsa(float hue, float lightness, float saturation, int alpha); void imlib_context_set_color_cmya(int cyan, int magenta, int yellow, int alpha); void imlib_context_set_color_range(Imlib_Color_Range color_range); void imlib_context_set_progress_function(Imlib_Progress_Function progress_function); void imlib_context_set_progress_granularity(char progress_granularity); void imlib_context_set_image(Imlib_Image image); void imlib_context_set_cliprect(int x, int y, int w, int h); void imlib_context_set_TTF_encoding(Imlib_TTF_Encoding encoding); Display *imlib_context_get_display(void); Visual *imlib_context_get_visual(void); Colormap imlib_context_get_colormap(void); Drawable imlib_context_get_drawable(void); Pixmap imlib_context_get_mask(void); char imlib_context_get_dither_mask(void); char imlib_context_get_anti_alias(void); int imlib_context_get_mask_alpha_threshold(void); char imlib_context_get_dither(void); char imlib_context_get_blend(void); Imlib_Color_Modifier imlib_context_get_color_modifier(void); Imlib_Operation imlib_context_get_operation(void); Imlib_Font imlib_context_get_font(void); double imlib_context_get_angle(void); Imlib_Text_Direction imlib_context_get_direction(void); void imlib_context_get_color(int *red, int *green, int *blue, int *alpha); void imlib_context_get_color_hsva(float *hue, float *saturation, float *value, int *alpha); void imlib_context_get_color_hlsa(float *hue, float *lightness, float *saturation, int *alpha); void imlib_context_get_color_cmya(int *cyan, int *magenta, int *yellow, int *alpha); Imlib_Color *imlib_context_get_imlib_color(void); Imlib_Color_Range imlib_context_get_color_range(void); Imlib_Progress_Function imlib_context_get_progress_function(void); char imlib_context_get_progress_granularity(void); Imlib_Image imlib_context_get_image(void); void imlib_context_get_cliprect(int *x, int *y, int *w, int *h); Imlib_TTF_Encoding imlib_context_get_TTF_encoding(void); int imlib_get_cache_size(void); void imlib_set_cache_size(int bytes); int imlib_get_color_usage(void); void imlib_set_color_usage(int max); void imlib_flush_loaders(void); int imlib_get_visual_depth(Display * display, Visual * visual); Visual *imlib_get_best_visual(Display * display, int screen, int *depth_return); Imlib_Image imlib_load_image(const char *file); Imlib_Image imlib_load_image_immediately(const char *file); Imlib_Image imlib_load_image_without_cache(const char *file); Imlib_Image imlib_load_image_immediately_without_cache(const char *file); Imlib_Image imlib_load_image_with_error_return(const char *file, Imlib_Load_Error * error_return); void imlib_free_image(void); void imlib_free_image_and_decache(void); int imlib_image_get_width(void); int imlib_image_get_height(void); const char *imlib_image_get_filename(void); int *imlib_image_get_data(void); int *imlib_image_get_data_for_reading_only(void); void imlib_image_put_back_data(unsigned int * data); char imlib_image_has_alpha(void); void imlib_image_set_changes_on_disk(void); void imlib_image_get_border(Imlib_Border * border); void imlib_image_set_border(Imlib_Border * border); void imlib_image_set_format(const char *format); void imlib_image_set_irrelevant_format(char irrelevant); void imlib_image_set_irrelevant_border(char irrelevant); void imlib_image_set_irrelevant_alpha(char irrelevant); char *imlib_image_format(void); void imlib_image_set_has_alpha(char has_alpha); void imlib_image_query_pixel(int x, int y, Imlib_Color * color_return); void imlib_image_query_pixel_hsva(int x, int y, float *hue, float *saturation, float *value, int *alpha); void imlib_image_query_pixel_hlsa(int x, int y, float *hue, float *lightness, float *saturation, int *alpha); void imlib_image_query_pixel_cmya(int x, int y, int *cyan, int *magenta, int *yellow, int *alpha); void imlib_render_pixmaps_for_whole_image(Pixmap * pixmap_return, Pixmap * mask_return); void imlib_render_pixmaps_for_whole_image_at_size(Pixmap * pixmap_return, Pixmap * mask_return, int width, int height); void imlib_free_pixmap_and_mask(Pixmap pixmap); void imlib_render_image_on_drawable(int x, int y); void imlib_render_image_on_drawable_at_size(int x, int y, int width, int height); void imlib_render_image_part_on_drawable_at_size(int source_x, int source_y, int source_width, int source_height, int x, int y, int width, int height); unsigned int imlib_render_get_pixel_color(void); void imlib_blend_image_onto_image(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int destination_width, int destination_height); Imlib_Image imlib_create_image(int width, int height); Imlib_Image imlib_create_image_using_data(int width, int height, unsigned int * data); Imlib_Image imlib_create_image_using_copied_data(int width, int height, unsigned int * data); Imlib_Image imlib_create_image_from_drawable(Pixmap mask, int x, int y, int width, int height, char need_to_grab_x); Imlib_Image imlib_create_image_from_ximage(XImage *image, XImage *mask, int x, int y, int width, int height, char need_to_grab_x); Imlib_Image imlib_create_scaled_image_from_drawable(Pixmap mask, int source_x, int source_y, int source_width, int source_height, int destination_width, int destination_height, char need_to_grab_x, char get_mask_from_shape); char imlib_copy_drawable_to_image(Pixmap mask, int x, int y, int width, int height, int destination_x, int destination_y, char need_to_grab_x); Imlib_Image imlib_clone_image(void); Imlib_Image imlib_create_cropped_image(int x, int y, int width, int height); Imlib_Image imlib_create_cropped_scaled_image(int source_x, int source_y, int source_width, int source_height, int destination_width, int destination_height); Imlib_Updates imlib_updates_clone(Imlib_Updates updates); Imlib_Updates imlib_update_append_rect(Imlib_Updates updates, int x, int y, int w, int h); Imlib_Updates imlib_updates_merge(Imlib_Updates updates, int w, int h); Imlib_Updates imlib_updates_merge_for_rendering(Imlib_Updates updates, int w, int h); void imlib_updates_free(Imlib_Updates updates); Imlib_Updates imlib_updates_get_next(Imlib_Updates updates); void imlib_updates_get_coordinates(Imlib_Updates updates, int *x_return, int *y_return, int *width_return, int *height_return); void imlib_updates_set_coordinates(Imlib_Updates updates, int x, int y, int width, int height); void imlib_render_image_updates_on_drawable(Imlib_Updates updates, int x, int y); Imlib_Updates imlib_updates_init(void); Imlib_Updates imlib_updates_append_updates(Imlib_Updates updates, Imlib_Updates appended_updates); void imlib_image_flip_horizontal(void); void imlib_image_flip_vertical(void); void imlib_image_flip_diagonal(void); void imlib_image_orientate(int orientation); void imlib_image_blur(int radius); void imlib_image_sharpen(int radius); void imlib_image_tile_horizontal(void); void imlib_image_tile_vertical(void); void imlib_image_tile(void); Imlib_Font imlib_load_font(const char *font_name); void imlib_free_font(void); int imlib_insert_font_into_fallback_chain(Imlib_Font font, Imlib_Font fallback_font); void imlib_remove_font_from_fallback_chain(Imlib_Font fallback_font); Imlib_Font imlib_get_prev_font_in_fallback_chain(Imlib_Font fn); Imlib_Font imlib_get_next_font_in_fallback_chain(Imlib_Font fn); void imlib_text_draw(int x, int y, const char *text); void imlib_text_draw_with_return_metrics(int x, int y, const char *text, int *width_return, int *height_return, int *horizontal_advance_return, int *vertical_advance_return); void imlib_get_text_size(const char *text, int *width_return, int *height_return); void imlib_get_text_advance(const char *text, int *horizontal_advance_return, int *vertical_advance_return); int imlib_get_text_inset(const char *text); void imlib_add_path_to_font_path(const char *path); void imlib_remove_path_from_font_path(const char *path); char **imlib_list_font_path(int *number_return); int imlib_text_get_index_and_location(const char *text, int x, int y, int *char_x_return, int *char_y_return, int *char_width_return, int *char_height_return); void imlib_text_get_location_at_index(const char *text, int index, int *char_x_return, int *char_y_return, int *char_width_return, int *char_height_return); char **imlib_list_fonts(int *number_return); void imlib_free_font_list(char **font_list, int number); int imlib_get_font_cache_size(void); void imlib_set_font_cache_size(int bytes); void imlib_flush_font_cache(void); int imlib_get_font_ascent(void); int imlib_get_font_descent(void); int imlib_get_maximum_font_ascent(void); int imlib_get_maximum_font_descent(void); Imlib_Color_Modifier imlib_create_color_modifier(void); void imlib_free_color_modifier(void); void imlib_modify_color_modifier_gamma(double gamma_value); void imlib_modify_color_modifier_brightness(double brightness_value); void imlib_modify_color_modifier_contrast(double contrast_value); void imlib_set_color_modifier_tables(unsigned char * red_table, unsigned char * green_table, unsigned char * blue_table, unsigned char * alpha_table); void imlib_get_color_modifier_tables(unsigned char * red_table, unsigned char * green_table, unsigned char * blue_table, unsigned char * alpha_table); void imlib_reset_color_modifier(void); void imlib_apply_color_modifier(void); void imlib_apply_color_modifier_to_rectangle(int x, int y, int width, int height); Imlib_Updates imlib_image_draw_pixel(int x, int y, char make_updates); Imlib_Updates imlib_image_draw_line(int x1, int y1, int x2, int y2, char make_updates); void imlib_image_draw_rectangle(int x, int y, int width, int height); void imlib_image_fill_rectangle(int x, int y, int width, int height); void imlib_image_copy_alpha_to_image(Imlib_Image image_source, int x, int y); void imlib_image_copy_alpha_rectangle_to_image(Imlib_Image image_source, int x, int y, int width, int height, int destination_x, int destination_y); void imlib_image_scroll_rect(int x, int y, int width, int height, int delta_x, int delta_y); void imlib_image_copy_rect(int x, int y, int width, int height, int new_x, int new_y); ImlibPolygon imlib_polygon_new(void); void imlib_polygon_free(ImlibPolygon poly); void imlib_polygon_add_point(ImlibPolygon poly, int x, int y); void imlib_image_draw_polygon(ImlibPolygon poly, unsigned char closed); void imlib_image_fill_polygon(ImlibPolygon poly); void imlib_polygon_get_bounds(ImlibPolygon poly, int *px1, int *py1, int *px2, int *py2); unsigned char imlib_polygon_contains_point(ImlibPolygon poly, int x, int y); void imlib_image_draw_ellipse(int xc, int yc, int a, int b); void imlib_image_fill_ellipse(int xc, int yc, int a, int b); Imlib_Color_Range imlib_create_color_range(void); void imlib_free_color_range(void); void imlib_add_color_to_color_range(int distance_away); void imlib_image_fill_color_range_rectangle(int x, int y, int width, int height, double angle); void imlib_image_fill_hsva_color_range_rectangle(int x, int y, int width, int height, double angle); void imlib_image_attach_data_value(const char *key, void *data, int value, Imlib_Data_Destructor_Function destructor_function); void *imlib_image_get_attached_data(const char *key); int imlib_image_get_attached_value(const char *key); void imlib_image_remove_attached_data_value(const char *key); void imlib_image_remove_and_free_attached_data_value(const char *key); void imlib_save_image(const char *filename); void imlib_save_image_with_error_return(const char *filename, Imlib_Load_Error * error_return); Imlib_Image imlib_create_rotated_image(double angle); void imlib_rotate_image_from_buffer(double angle, Imlib_Image source_image); void imlib_blend_image_onto_image_at_angle(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int angle_x, int angle_y); void imlib_blend_image_onto_image_skewed(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int h_angle_x, int h_angle_y, int v_angle_x, int v_angle_y); void imlib_render_image_on_drawable_skewed(int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int h_angle_x, int h_angle_y, int v_angle_x, int v_angle_y); void imlib_render_image_on_drawable_at_angle(int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int angle_x, int angle_y); void imlib_image_filter(void); Imlib_Filter imlib_create_filter(int initsize); void imlib_context_set_filter(Imlib_Filter filter); Imlib_Filter imlib_context_get_filter(void); void imlib_free_filter(void); void imlib_filter_set(int xoff, int yoff, int a, int r, int g, int b); void imlib_filter_set_alpha(int xoff, int yoff, int a, int r, int g, int b); void imlib_filter_set_red(int xoff, int yoff, int a, int r, int g, int b); void imlib_filter_set_green(int xoff, int yoff, int a, int r, int g, int b); void imlib_filter_set_blue(int xoff, int yoff, int a, int r, int g, int b); void imlib_filter_constants(int a, int r, int g, int b); void imlib_filter_divisors(int a, int r, int g, int b); void imlib_image_clear(void); void imlib_image_clear_color(int r, int g, int b, int a); conky-1.10.1/lua/libcairo-helper.h000066400000000000000000000025011262311664100167100ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Please see COPYING for details * * Copyright (c) 2005-2012 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 _LIBCAIRO_HELPER_H_ #define _LIBCAIRO_HELPER_H_ #include cairo_text_extents_t *create_cairo_text_extents_t(void) { return calloc(1, sizeof(cairo_text_extents_t)); } cairo_font_extents_t *create_cairo_font_extents_t(void) { return calloc(1, sizeof(cairo_font_extents_t)); } cairo_matrix_t *create_cairo_matrix_t(void) { return calloc(1, sizeof(cairo_matrix_t)); } #endif /* _LIBCAIRO_HELPER_H_ */ conky-1.10.1/lua/libcairo.patch000066400000000000000000000011101262311664100162760ustar00rootroot00000000000000--- 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 conky-1.10.1/lua/libcairo_imlib2_helper.h000066400000000000000000000051071262311664100202350ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Please see COPYING for details * * Copyright (c) 2005-2012 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 _LIBCAIRO_IMAGE_HELPER_H_ #define _LIBCAIRO_IMAGE_HELPER_H_ #include #include void cairo_draw_image(const char * file, cairo_surface_t * cs, int x, int y, double scale_x, double scale_y, double * return_scale_w, double * return_scale_h) { Imlib_Image * image = imlib_load_image(file); if (! image) { return; } imlib_context_set_image(image); int w = imlib_image_get_width(), h = imlib_image_get_height(); double scaled_w = *return_scale_w = scale_x * (double)w , scaled_h = *return_scale_h = scale_y * (double)h; /* create temporary image */ Imlib_Image premul = imlib_create_image(scaled_w, scaled_h); /* FIXME: add error handling */ /* fill with opaque black */ imlib_context_set_image(premul); imlib_context_set_color(0, 0, 0, 255); imlib_image_fill_rectangle(0, 0, scaled_w, scaled_h); /* blend source image on top - * in effect this multiplies the rgb values by alpha */ imlib_blend_image_onto_image(image, 0, 0, 0, w, h, 0, 0, scaled_w, scaled_h); /* and use the alpha channel of the source image */ imlib_image_copy_alpha_to_image(image, 0, 0); /* now pass the result to cairo */ cairo_surface_t * result = cairo_image_surface_create_for_data( (void *) imlib_image_get_data_for_reading_only(), CAIRO_FORMAT_ARGB32, scaled_w, scaled_h, sizeof(DATA32) * scaled_w); cairo_t * cr = cairo_create(cs); cairo_set_source_surface(cr, result, x, y); cairo_paint(cr); imlib_context_set_image(image); imlib_free_image(); imlib_context_set_image(premul); imlib_free_image(); cairo_destroy(cr); cairo_surface_destroy(result); } #endif /* _LIBCAIRO_IMAGE_HELPER_H_ */ conky-1.10.1/lua/librsvg-helper.h000066400000000000000000000042731262311664100166040ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Please see COPYING for details * * Copyright (c) 2005-2012 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 _LIBRSVG_HELPER_H_ #define _LIBRSVG_HELPER_H_ #include #include #include RsvgDimensionData * rsvgDimensionDataCreate(void) { return (RsvgDimensionData *)calloc(1, sizeof(RsvgDimensionData)); } void rsvgDimensionDataGet(RsvgDimensionData * dd, int * width, int * height, double * em, double * ex) { if (dd) { *width = dd->width; *height = dd->height; *em = dd->em; *ex = dd->ex; } } RsvgPositionData * rsvgPositionDataCreate(void) { return (RsvgPositionData *)calloc(1, sizeof(RsvgPositionData)); } void rsvgPositionDataGet(RsvgPositionData * pd, int * x, int * y) { if (pd) { *x = pd->x; *y = pd->y; } } RsvgHandle * rsvg_create_handle_from_file(const char * filename) { GError * error = NULL; RsvgHandle * handle = rsvg_handle_new_from_file(filename, &error); if (error) { g_object_unref(error); if (handle) g_object_unref(handle); handle = NULL; } return handle; } int rsvg_destroy_handle(RsvgHandle * handle) { int status = 0; if (handle) { GError * error = NULL; status = rsvg_handle_close(handle, &error); if (status) g_object_unref(handle); if (error) g_object_unref(error); } return status; } #endif /* _LIBRSVG_HELPER_H_ */ conky-1.10.1/lua/rsvg.pkg000066400000000000000000000100741262311664100151660ustar00rootroot00000000000000/* rsvg.h: SAX-based renderer for SVG files into a GdkPixbuf. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Author: Raph Levien rsvg-cairo.h: SAX-based renderer for SVG files using cairo Copyright (C) 2005 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Author: Carl Worth */ $#include $#include $#include "librsvg-helper.h" typedef struct _RsvgHandle RsvgHandle; typedef struct RsvgHandlePrivate RsvgHandlePrivate; typedef struct _RsvgHandleClass RsvgHandleClass; /** * RsvgDimensionData: * @width: SVG's width, in pixels * @height: SVG's height, in pixels * @em: em * @ex: ex */ typedef struct _RsvgDimensionData { int width; int height; double em; double ex; static tolua_outside RsvgDimensionData * rsvgDimensionDataCreate @ create(); tolua_outside void rsvgDimensionDataGet @ get(int * width, int * height, double * em, double * ex); } RsvgDimensionData; /** * RsvgPositionData: * Position of an SVG fragment. */ typedef struct _RsvgPositionData { int x; int y; static tolua_outside RsvgPositionData * rsvgPositionDataCreate @ create(); tolua_outside void rsvgPositionDataGet @ get(int * x, int * y); } RsvgPositionData; RsvgHandle *rsvg_handle_new (void); int rsvg_handle_write (RsvgHandle * handle, const unsigned char * buf, unsigned long count, GError ** error); int rsvg_handle_close (RsvgHandle * handle, GError ** error); const char *rsvg_handle_get_base_uri (RsvgHandle * handle); void rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri); void rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_data); int rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimension_data, const char *id); int rsvg_handle_get_position_sub (RsvgHandle * handle, RsvgPositionData * position_data, const char *id); int rsvg_handle_has_sub (RsvgHandle * handle, const char *id); RsvgHandle *rsvg_handle_new_with_flags (RsvgHandleFlags flags); RsvgHandle *rsvg_handle_new_from_data (const unsigned char * data, unsigned long data_len, GError ** error); RsvgHandle *rsvg_handle_new_from_file (const char * file_name, GError ** error); int rsvg_handle_render_cairo (RsvgHandle * handle, cairo_t * cr); int rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id); void g_type_init(void); void g_object_unref(gpointer object); RsvgHandle * rsvg_create_handle_from_file(const char *); int rsvg_destroy_handle(RsvgHandle *); conky-1.10.1/src/000077500000000000000000000000001262311664100135065ustar00rootroot00000000000000conky-1.10.1/src/CMakeLists.txt000066400000000000000000000133351262311664100162530ustar00rootroot00000000000000# vim: ts=4 sw=4 noet ai cindent syntax=cmake # # Conky, a system monitor, based on torsmo # # Please see COPYING for details # # Copyright (c) 2005-2012 Brenden Matthews, 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_directories(${conky_includes}) if(BUILD_BUILTIN_CONFIG OR BUILD_OLD_CONFIG) # include config output dir include_directories(${CMAKE_BINARY_DIR}/data) endif(BUILD_BUILTIN_CONFIG OR BUILD_OLD_CONFIG) # ensure build.h and config.h aren't in the way if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.h) message(FATAL_ERROR "You must remove the autotools generated file '${CMAKE_CURRENT_SOURCE_DIR}/config.h' in order to build with CMake.") endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.h) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build.h) message(FATAL_ERROR "You must remove the autotools generated file '${CMAKE_CURRENT_SOURCE_DIR}/build.h' in order to build with CMake.") endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build.h) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/defconfig.h) message(FATAL_ERROR "You must remove the autotools generated file '${CMAKE_CURRENT_SOURCE_DIR}/defconfig.h' in order to build with CMake.") endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/defconfig.h) set(conky_sources c++wrap.cc colours.cc combine.cc common.cc conky.cc core.cc diskio.cc entropy.cc exec.cc fs.cc mail.cc mixer.cc net_stat.cc template.cc mboxscan.cc read_tcpip.cc scroll.cc specials.cc tailhead.cc temphelper.cc text_object.cc timeinfo.cc top.cc algebra.cc prioqueue.cc proc.cc user.cc luamm.cc data-source.cc lua-config.cc setting.cc llua.cc update-cb.cc) # Platform specific sources if(OS_LINUX) set(linux linux.cc users.cc sony.cc i8k.cc) set(optional_sources ${optional_sources} ${linux}) endif(OS_LINUX) if(OS_FREEBSD) set(freebsd freebsd.cc bsdapm.cc) set(optional_sources ${optional_sources} ${freebsd}) endif(OS_FREEBSD) if(OS_DRAGONFLY) set(dragonfly dragonfly.cc bsdapm.cc) set(optional_sources ${optional_sources} ${dragonfly}) endif(OS_DRAGONFLY) if(OS_OPENBSD) set(openbsd openbsd.cc bsdapm.cc) set(optional_sources ${optional_sources} ${openbsd}) endif(OS_OPENBSD) # These below are not actually supported. No idea what their status is. if(OS_SOLARIS) set(solaris solaris.cc) set(optional_sources ${optional_sources} ${solaris}) endif(OS_SOLARIS) if(OS_NETBSD) set(netbsd netbsd.cc) set(optional_sources ${optional_sources} ${netbsd}) endif(OS_NETBSD) # Optional sources if(BUILD_AUDACIOUS) set(audacious audacious.cc) set(optional_sources ${optional_sources} ${audacious}) endif(BUILD_AUDACIOUS) if(BUILD_BMPX) set(bmpx bmpx.cc) set(optional_sources ${optional_sources} ${bmpx}) endif(BUILD_BMPX) if(BUILD_IBM) set(ibm ibm.cc smapi.cc) set(optional_sources ${optional_sources} ${ibm}) endif(BUILD_IBM) if(BUILD_MPD) set(mpd mpd.cc libmpdclient.cc) set(optional_sources ${optional_sources} ${mpd}) endif(BUILD_MPD) if(BUILD_MYSQL) set(mysql mysql.cc) set(optional_sources ${optional_sources} ${mysql}) endif(BUILD_MYSQL) if(BUILD_MOC) set(moc moc.cc) set(optional_sources ${optional_sources} ${moc}) endif(BUILD_MOC) if(BUILD_CMUS) set(cmus cmus.cc) set(optional_sources ${optional_sources} ${cmus}) endif(BUILD_CMUS) if(BUILD_XMMS2) set(xmms2 xmms2.cc) set(optional_sources ${optional_sources} ${xmms2}) endif(BUILD_XMMS2) if(BUILD_PORT_MONITORS) add_library(tcp-portmon libtcp-portmon.cc) set(conky_libs ${conky_libs} tcp-portmon) set(port_monitors tcp-portmon.cc) set(optional_sources ${optional_sources} ${port_monitors}) endif(BUILD_PORT_MONITORS) if(BUILD_X11) set(x11 x11.cc fonts.cc) set(optional_sources ${optional_sources} ${x11}) endif(BUILD_X11) if(BUILD_HDDTEMP) set(hddtemp hddtemp.cc) set(optional_sources ${optional_sources} ${hddtemp}) endif(BUILD_HDDTEMP) if(BUILD_EVE) set(eve eve.cc) set(optional_sources ${optional_sources} ${eve}) endif(BUILD_EVE) if(BUILD_CURL) set(ccurl_thread ccurl_thread.cc) set(optional_sources ${optional_sources} ${ccurl_thread}) endif(BUILD_CURL) if(BUILD_RSS) set(rss rss.cc prss.cc) set(optional_sources ${optional_sources} ${rss}) endif(BUILD_RSS) if(BUILD_WEATHER) set(weather weather.cc) set(optional_sources ${optional_sources} ${weather}) endif(BUILD_WEATHER) if(BUILD_NVIDIA) set(nvidia nvidia.cc) set(optional_sources ${optional_sources} ${nvidia}) endif(BUILD_NVIDIA) if(BUILD_IMLIB2) set(imlib2 imlib2.cc) set(optional_sources ${optional_sources} ${imlib2}) endif(BUILD_IMLIB2) if(BUILD_APCUPSD) set(apcupsd apcupsd.cc) 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}) endif(BUILD_ICONV) if(BUILD_NCURSES) set(optional_sources ${optional_sources} nc.cc) endif(BUILD_NCURSES) add_executable(conky ${conky_sources} ${optional_sources}) target_link_libraries(conky ${conky_libs}) # Install libtcp-portmon too? install(TARGETS conky RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) conky-1.10.1/src/algebra.cc000066400000000000000000000141661262311664100154220ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "algebra.h" #include "logging.h" #include #include #include #include #include /* find the operand in the given expression * returns the index of the first op character or -1 on error */ int find_match_op(const char *expr) { unsigned int idx; for (idx = 0; idx < strlen(expr); idx++) { switch (expr[idx]) { case '=': case '!': if (expr[idx + 1] != '=') return -1; /* fall through */ case '<': case '>': return idx; break; } } return -1; } int get_match_type(const char *expr) { int idx; const char *str; if ((idx = find_match_op(expr)) == -1) return -1; str = expr + idx; if (*str == '=' && *(str + 1) == '=') return OP_EQ; else if (*str == '!' && *(str + 1) == '=') return OP_NEQ; else if (*str == '>') { if (*(str + 1) == '=') return OP_GEQ; return OP_GT; } else if (*str == '<') { if (*(str + 1) == '=') return OP_LEQ; return OP_LT; } return -1; } /* generic compare function * * v is actually the difference of the compared values. For strings * this is equal to the output of str(n)cmp(). Use a macro here, as * it's type-independent. */ #define COMPARE(v, t) \ switch (t) { \ case OP_GT: return (v > 0); \ case OP_LT: return (v < 0); \ case OP_EQ: return (v == 0); \ case OP_GEQ: return (v >= 0); \ case OP_LEQ: return (v <= 0); \ case OP_NEQ: return (v != 0); \ } \ return 0 int lcompare(long a, enum match_type mtype, long b) { DBGP2("comparing longs '%ld' and '%ld'", a, b); COMPARE((a - b), mtype); } int dcompare(double a, enum match_type mtype, double b) { DBGP2("comparing doubles '%.lf' and '%.lf'", a, b); COMPARE((a - b), mtype); } int scompare(const char *a, enum match_type mtype, const char *b) { DBGP2("comparing strings '%s' and '%s'", a, b); COMPARE(strcmp(a, b), mtype); } enum arg_type get_arg_type(const char *arg) { const char *p, *e; p = arg; e = arg + strlen(arg)-1; while (p != e && *e && *e == ' ') e--; while (p != e && *p == ' ') p++; if (*p == '"' && *e == '"') return ARG_STRING; if (*p == '-') //allow negative values p++; while (p <= e) { if (!isdigit(*p)) break; p++; } if (p == e+1) return ARG_LONG; if (*p == '.') { p++; while (p <= e) { if (!isdigit(*p)) return ARG_BAD; p++; } return ARG_DOUBLE; } return ARG_BAD; } char *arg_to_string(const char *arg) { const char *start; int len; start = arg; len = 0; while (*start && *start == ' ') start++; if (!(*(start++) == '"')) return NULL; while (start[len] != '"') len++; return strndup(start, len); } double arg_to_double(const char *arg) { double d; if (sscanf(arg, "%lf", &d) != 1) { NORM_ERR("converting '%s' to double failed", arg); return 0.0; } return d; } long arg_to_long(const char *arg) { long l; if (sscanf(arg, "%ld", &l) != 1) { NORM_ERR("converting '%s' to long failed", arg); return 0; } return l; } int compare(const char *expr) { char *expr_dup; int idx, mtype; enum arg_type type1, type2; long lng_a, lng_b; double dbl_a, dbl_b; idx = find_match_op(expr); mtype = get_match_type(expr); if (!idx || mtype == -1) { NORM_ERR("failed to parse compare string '%s'", expr); return -2; } expr_dup = strdup(expr); expr_dup[idx] = '\0'; if (expr_dup[idx + 1] == '=') expr_dup[++idx] = '\0'; type1 = get_arg_type(expr_dup); type2 = get_arg_type(expr_dup + idx + 1); if (type1 == ARG_BAD || type2 == ARG_BAD) { NORM_ERR("Bad arguments: '%s' and '%s'", expr_dup, (expr_dup + idx + 1)); free(expr_dup); return -2; } if (type1 == ARG_LONG && type2 == ARG_DOUBLE) type1 = ARG_DOUBLE; if (type1 == ARG_DOUBLE && type2 == ARG_LONG) type2 = ARG_DOUBLE; if (type1 != type2) { NORM_ERR("trying to compare args '%s' and '%s' of different type", expr_dup, (expr_dup + idx + 1)); free(expr_dup); return -2; } switch (type1) { case ARG_STRING: { char *a, *b; a = arg_to_string(expr_dup); b = arg_to_string(expr_dup + idx + 1); idx = scompare(a, (enum match_type) mtype, b); free(a); free(b); free(expr_dup); return idx; } case ARG_LONG: lng_a = arg_to_long(expr_dup); lng_b = arg_to_long(expr_dup + idx + 1); free(expr_dup); return lcompare(lng_a, (enum match_type) mtype, lng_b); case ARG_DOUBLE: dbl_a = arg_to_double(expr_dup); dbl_b = arg_to_double(expr_dup + idx + 1); free(expr_dup); return dcompare(dbl_a, (enum match_type) mtype, dbl_b); case ARG_BAD: /* make_gcc_happy() */; } /* not reached */ free(expr_dup); return -2; } int check_if_match(struct text_object *obj) { std::unique_ptr expression(new char[max_user_text.get(*state)]); int val; int result = 1; generate_text_internal(expression.get(), max_user_text.get(*state), *obj->sub); DBGP("parsed arg into '%s'", expression.get()); val = compare(expression.get()); if (val == -2) { NORM_ERR("compare failed for expression '%s'", expression.get()); } else if (!val) { result = 0; } return result; } conky-1.10.1/src/algebra.h000066400000000000000000000030741262311664100152600ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _ALGEBRA_H #define _ALGEBRA_H enum match_type { OP_LT = 1, /* < */ OP_GT = 2, /* > */ OP_EQ = 3, /* == */ OP_LEQ = 4, /* <= */ OP_GEQ = 5, /* >= */ OP_NEQ = 6 /* != */ }; enum arg_type { ARG_BAD = 0, /* something strange */ ARG_STRING = 1, /* "asdf" */ ARG_LONG = 2, /* 123456 */ ARG_DOUBLE = 3 /* 12.456 */ }; int compare(const char *); int check_if_match(struct text_object *); #endif /* _ALGEBRA_H */ conky-1.10.1/src/apcupsd.cc000066400000000000000000000157751262311664100154730ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * apcupsd.c: conky module for APC UPS daemon monitoring * * Copyright (C) 2009 Jaromir Smrcek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #include "conky.h" #include "apcupsd.h" #include "logging.h" #include "text_object.h" #include #include #include #include #include enum _apcupsd_items { APCUPSD_NAME, APCUPSD_MODEL, APCUPSD_UPSMODE, APCUPSD_CABLE, APCUPSD_STATUS, APCUPSD_LINEV, APCUPSD_LOAD, APCUPSD_CHARGE, APCUPSD_TIMELEFT, APCUPSD_TEMP, APCUPSD_LASTXFER, _APCUPSD_COUNT }; /* type for data exchange with main thread */ #define APCUPSD_MAXSTR 32 typedef struct apcupsd_s { char items[_APCUPSD_COUNT][APCUPSD_MAXSTR+1]; /* e.g. items[APCUPSD_STATUS] */ char host[64]; int port; } APCUPSD_S, *PAPCUPSD_S; static APCUPSD_S apcupsd; // // encapsulated recv() // static int net_recv_ex(int sock, void *buf, int size, struct timeval *tv) { fd_set fds; int res; // wait for some data to be read do { errno = 0; FD_ZERO(&fds); FD_SET(sock, &fds); res = select(sock + 1, &fds, NULL, NULL, tv); } while (res < 0 && errno == EINTR); if (res < 0) return 0; if (res == 0) { // timeout errno = ETIMEDOUT; // select was succesfull, errno is now 0 return 0; } // socket ready, read the data do { errno = 0; res = recv(sock, (char*)buf, size, 0); } while (res < 0 && errno == EINTR); if (res < 0) return 0; if (res == 0) { // orderly shutdown errno = ENOTCONN; return 0; } return res; } // // read whole buffer or fail // static int net_recv(int sock, void* buf, int size) { int todo = size; int off = 0; int len; struct timeval tv = { 0, 250000 }; while (todo) { len = net_recv_ex(sock, (char*)buf + off, todo, &tv); if (!len) return 0; todo -= len; off += len; } return 1; } // // get one response line // static int get_line(int sock, char line[], short linesize) { // get the line length short sz; if (!net_recv(sock, &sz, sizeof(sz))) return -1; sz = ntohs(sz); if (!sz) return 0; // get the line while (sz >= linesize) { // this is just a hack (being lazy), this should not happen anyway net_recv(sock, line, linesize); sz -= linesize; } if (!net_recv(sock, line, sz)) return 0; line[sz] = 0; return sz; } #define FILL(NAME,FIELD,FIRST) \ if (!strncmp(NAME, line, sizeof(NAME)-1)) { \ strncpy(apc->items[FIELD], line+11, APCUPSD_MAXSTR); \ /* remove trailing newline and assure termination */ \ apc->items[FIELD][len-11 > APCUPSD_MAXSTR ? APCUPSD_MAXSTR : len-12] = 0; \ if (FIRST) { \ char* c; \ for (c = apc->items[FIELD]; *c; ++c) \ if (*c == ' ' && c > apc->items[FIELD]+2) { \ *c = 0; \ break; \ } \ } \ } // // fills in the data received from a socket // static int fill_items(int sock, PAPCUPSD_S apc) { char line[512]; int len; while ((len = get_line(sock, line, sizeof(line)))) { // fill the right types in FILL("UPSNAME", APCUPSD_NAME, FALSE); FILL("MODEL", APCUPSD_MODEL, FALSE); FILL("UPSMODE", APCUPSD_UPSMODE, FALSE); FILL("CABLE", APCUPSD_CABLE, FALSE); FILL("STATUS", APCUPSD_STATUS, FALSE); FILL("LINEV", APCUPSD_LINEV, TRUE); FILL("LOADPCT", APCUPSD_LOAD, TRUE); FILL("BCHARGE", APCUPSD_CHARGE, TRUE); FILL("TIMELEFT", APCUPSD_TIMELEFT, TRUE); FILL("ITEMP", APCUPSD_TEMP, TRUE); FILL("LASTXFER", APCUPSD_LASTXFER, FALSE); } return len == 0; } // // Conky update function for apcupsd data // int update_apcupsd(void) { int i; APCUPSD_S apc; int sock; for (i = 0; i < _APCUPSD_COUNT; ++i) memcpy(apc.items[i], "N/A", 4); // including \0 do { struct addrinfo hints; struct addrinfo *ai, *rp; int res; short sz = 0; char portbuf[8]; // // connect to apcupsd daemon // memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; snprintf(portbuf, 8, "%d", apcupsd.port); res = getaddrinfo(apcupsd.host, portbuf, &hints, &ai); if (res != 0) { NORM_ERR("APCUPSD getaddrinfo: %s", gai_strerror(res)); break; } for (rp = ai; rp != NULL; rp = rp->ai_next) { sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock == -1) { continue; } if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) { break; } close(sock); } freeaddrinfo(ai); if (rp == NULL) { // no error reporting, the daemon is probably not running break; } // // send status request - "status" - 6B // sz = htons(6); // no waiting to become writeable is really needed if (send(sock, &sz, sizeof(sz), 0) != sizeof(sz) || send(sock, "status", 6, 0) != 6) { perror("send"); break; } // // read the lines of output and put them into the info structure // if (!fill_items(sock, &apc)) break; } while (0); close(sock); // // "atomically" copy the data into working set // memcpy(apcupsd.items, apc.items, sizeof(apcupsd.items)); return 0; } int apcupsd_scan_arg(const char *arg) { char host[64]; int port; if (sscanf(arg, "%63s %d", host, &port) != 2) return 1; apcupsd.port = port; strncpy(apcupsd.host, host, sizeof(apcupsd.host)); return 0; } double apcupsd_loadbarval(struct text_object *obj) { (void)obj; return atof(apcupsd.items[APCUPSD_LOAD]); } #define APCUPSD_PRINT_GENERATOR(name, idx) \ void print_apcupsd_##name(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ snprintf(p, p_max_size, "%s", apcupsd.items[APCUPSD_##idx]); \ } APCUPSD_PRINT_GENERATOR(name, NAME) APCUPSD_PRINT_GENERATOR(model, MODEL) APCUPSD_PRINT_GENERATOR(upsmode, UPSMODE) APCUPSD_PRINT_GENERATOR(cable, CABLE) APCUPSD_PRINT_GENERATOR(status, STATUS) APCUPSD_PRINT_GENERATOR(linev, LINEV) APCUPSD_PRINT_GENERATOR(load, LOAD) APCUPSD_PRINT_GENERATOR(charge, CHARGE) APCUPSD_PRINT_GENERATOR(timeleft, TIMELEFT) APCUPSD_PRINT_GENERATOR(temp, TEMP) APCUPSD_PRINT_GENERATOR(lastxfer, LASTXFER) #undef APCUPSD_PRINT_GENERATOR conky-1.10.1/src/apcupsd.h000066400000000000000000000035511262311664100153220ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * apcupsd.h: conky module for APC UPS daemon monitoring * * Copyright (C) 2009 Jaromir Smrcek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #ifndef APCUPSD_H_ #define APCUPSD_H_ int apcupsd_scan_arg(const char *); /* Service routine for the conky main thread */ int update_apcupsd(void); double apcupsd_loadbarval(struct text_object *); void print_apcupsd_name(struct text_object *, char *, int); void print_apcupsd_model(struct text_object *, char *, int); void print_apcupsd_upsmode(struct text_object *, char *, int); void print_apcupsd_cable(struct text_object *, char *, int); void print_apcupsd_status(struct text_object *, char *, int); void print_apcupsd_linev(struct text_object *, char *, int); void print_apcupsd_load(struct text_object *, char *, int); void print_apcupsd_charge(struct text_object *, char *, int); void print_apcupsd_timeleft(struct text_object *, char *, int); void print_apcupsd_temp(struct text_object *, char *, int); void print_apcupsd_lastxfer(struct text_object *, char *, int); #endif /*APCUPSD_H_*/ conky-1.10.1/src/audacious.cc000066400000000000000000000161001262311664100157700ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * audacious.c: conky support for audacious music player * * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #include #include #include "conky.h" #include "logging.h" #include "audacious.h" #include #include "update-cb.hh" #include #ifdef NEW_AUDACIOUS_FOUND #include #include #include #else /* NEW_AUDACIOUS_FOUND */ #include #define audacious_remote_is_running(x) \ xmms_remote_is_running(x) #define audacious_remote_is_paused(x) \ xmms_remote_is_paused(x) #define audacious_remote_is_playing(x) \ xmms_remote_is_playing(x) #define audacious_remote_get_playlist_pos(x) \ xmms_remote_get_playlist_pos(x) #define audacious_remote_get_playlist_title(x, y) \ xmms_remote_get_playlist_title(x, y) #define audacious_remote_get_playlist_time(x, y) \ xmms_remote_get_playlist_time(x, y) #define audacious_remote_get_output_time(x) \ xmms_remote_get_output_time(x) #define audacious_remote_get_info(w, x, y, z) \ xmms_remote_get_info(w, x, y, z) #define audacious_remote_get_playlist_file(x, y) \ xmms_remote_get_playlist_file(x, y) #define audacious_remote_get_playlist_length(x) \ xmms_remote_get_playlist_length(x) #endif /* NEW_AUDACIOUS_FOUND */ namespace { enum aud_status { AS_NOT_RUNNING, AS_PAUSED, AS_PLAYING, AS_STOPPED }; const char * const as_message[] = { "Not running", "Paused", "Playing", "Stopped" }; struct aud_result { std::string title; std::string filename; int length; // in ms int position; // in ms int bitrate; int frequency; int channels; int playlist_length; int playlist_position; int main_volume; aud_status status; aud_result() : length(0), position(0), bitrate(0), frequency(0), channels(0), playlist_length(0), playlist_position(0), main_volume(0), status(AS_NOT_RUNNING) {} }; class audacious_cb: public conky::callback { typedef conky::callback Base; #ifdef NEW_AUDACIOUS_FOUND DBusGProxy *session; #else gint session; #endif protected: virtual void work(); public: audacious_cb(uint32_t period) : Base(period, false, Tuple()) { #ifdef NEW_AUDACIOUS_FOUND g_type_init(); DBusGConnection *connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); if (!connection) throw std::runtime_error("unable to establish dbus connection"); session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); if (!session) throw std::runtime_error("unable to create dbus proxy"); #else session = 0; #endif /* NEW_AUDACIOUS_FOUND */ } #ifdef NEW_AUDACIOUS_FOUND ~audacious_cb() { /* release reference to dbus proxy */ g_object_unref(session); } #endif }; /* --------------------------------------------------- * Worker thread function for audacious data sampling. * --------------------------------------------------- */ void audacious_cb::work() { aud_result tmp; gchar *psong, *pfilename; psong = NULL; pfilename = NULL; do { if (!audacious_remote_is_running(session)) { tmp.status = AS_NOT_RUNNING; break; } /* Player status */ if (audacious_remote_is_paused(session)) { tmp.status = AS_PAUSED; } else if (audacious_remote_is_playing(session)) { tmp.status = AS_PLAYING; } else { tmp.status = AS_STOPPED; } /* Current song title */ tmp.playlist_position = audacious_remote_get_playlist_pos(session); psong = audacious_remote_get_playlist_title(session, tmp.playlist_position); if (psong) { tmp.title = psong; g_free(psong); } /* Current song length */ tmp.length = audacious_remote_get_playlist_time(session, tmp.playlist_position); /* Current song position */ tmp.position = audacious_remote_get_output_time(session); /* Current song bitrate, frequency, channels */ audacious_remote_get_info(session, &tmp.bitrate, &tmp.frequency, &tmp.channels); /* Current song filename */ pfilename = audacious_remote_get_playlist_file(session, tmp.playlist_position); if (pfilename) { tmp.filename = pfilename; g_free(pfilename); } /* Length of the Playlist (number of songs) */ tmp.playlist_length = audacious_remote_get_playlist_length(session); /* Main volume */ tmp.main_volume = audacious_remote_get_main_volume(session); } while (0); { /* Deliver the refreshed items array to audacious_items. */ std::lock_guard lock(result_mutex); result = tmp; } } aud_result get_res() { uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l ); return conky::register_cb(period)->get_result_copy(); } } void print_audacious_status(struct text_object *, char *p, int p_max_size) { const aud_result &res = get_res(); snprintf(p, p_max_size, "%s", as_message[res.status]); } void print_audacious_title(struct text_object *obj, char *p, int p_max_size) { snprintf(p, std::min(obj->data.i, p_max_size), "%s", get_res().title.c_str()); } void print_audacious_filename(struct text_object *obj, char *p, int p_max_size) { snprintf(p, std::min(obj->data.i, p_max_size), "%s", get_res().filename.c_str()); } double audacious_barval(struct text_object *) { const aud_result &res = get_res(); return (double)res.position / res.length; } #define AUDACIOUS_TIME_GENERATOR(name) \ void print_audacious_##name(struct text_object *, char *p, int p_max_size) \ { \ const aud_result &res = get_res(); \ int sec = res.name / 1000; \ snprintf(p, p_max_size, "%d:%.2d", sec/60, sec%60); \ } \ \ void print_audacious_##name##_seconds(struct text_object *, char *p, int p_max_size) \ { \ snprintf(p, p_max_size, "%d", get_res().name); \ } AUDACIOUS_TIME_GENERATOR(length) AUDACIOUS_TIME_GENERATOR(position) #define AUDACIOUS_INT_GENERATOR(name, offset) \ void print_audacious_##name(struct text_object *, char *p, int p_max_size) \ { \ snprintf(p, p_max_size, "%d", get_res().name + offset); \ } AUDACIOUS_INT_GENERATOR(bitrate, 0) AUDACIOUS_INT_GENERATOR(frequency, 0) AUDACIOUS_INT_GENERATOR(channels, 0) AUDACIOUS_INT_GENERATOR(playlist_length, 0) AUDACIOUS_INT_GENERATOR(playlist_position, 1) AUDACIOUS_INT_GENERATOR(main_volume, 0) #undef AUDACIOUS_PRINT_GENERATOR conky-1.10.1/src/audacious.h000066400000000000000000000037241262311664100156420ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * audacious.h: conky support for audacious music player * * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #ifndef AUDACIOUS_H #define AUDACIOUS_H void print_audacious_status(struct text_object *, char *, int); void print_audacious_title(struct text_object *, char *, int); void print_audacious_length(struct text_object *, char *, int); void print_audacious_length_seconds(struct text_object *, char *, int); void print_audacious_position(struct text_object *, char *, int); void print_audacious_position_seconds(struct text_object *, char *, int); void print_audacious_bitrate(struct text_object *, char *, int); void print_audacious_frequency(struct text_object *, char *, int); void print_audacious_channels(struct text_object *, char *, int); void print_audacious_filename(struct text_object *, char *, int); void print_audacious_playlist_length(struct text_object *, char *, int); void print_audacious_playlist_position(struct text_object *, char *, int); void print_audacious_main_volume(struct text_object *, char *, int); double audacious_barval(struct text_object *); #endif /* AUDACIOUS_H */ conky-1.10.1/src/bmpx.cc000066400000000000000000000106401262311664100147640ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "logging.h" #include #include #define DBUS_TYPE_G_STRING_VALUE_HASHTABLE \ (dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) static DBusGConnection *bus; static DBusGProxy *remote_object; static int connected = 0; static char *unknown = "unknown"; void fail(GError *error, struct information *); void update_bmpx() { GError *error = NULL; struct information *current_info = &info; gint current_track; GHashTable *metadata; if (connected == 0) { g_type_init(); dbus_g_type_specialized_init(); bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); if (bus == NULL) { NORM_ERR("BMPx error 1: %s\n", error->message); fail(error, current_info); return; } remote_object = dbus_g_proxy_new_for_name(bus, BMP_DBUS_SERVICE, BMP_DBUS_PATH__BMP, BMP_DBUS_INTERFACE__BMP); if (!remote_object) { NORM_ERR("BMPx error 2: %s\n", error->message); fail(error, current_info); return; } connected = 1; } if (connected == 1) { if (dbus_g_proxy_call(remote_object, "GetCurrentTrack", &error, G_TYPE_INVALID, G_TYPE_INT, ¤t_track, G_TYPE_INVALID)) { } else { NORM_ERR("BMPx error 3: %s\n", error->message); fail(error, current_info); return; } if (dbus_g_proxy_call(remote_object, "GetMetadataForListItem", &error, G_TYPE_INT, current_track, G_TYPE_INVALID, DBUS_TYPE_G_STRING_VALUE_HASHTABLE, &metadata, G_TYPE_INVALID)) { free_and_zero(current_info->bmpx.title); free_and_zero(current_info->bmpx.artist); free_and_zero(current_info->bmpx.album); current_info->bmpx.title = g_value_dup_string(g_hash_table_lookup(metadata, "title")); current_info->bmpx.artist = g_value_dup_string(g_hash_table_lookup(metadata, "artist")); current_info->bmpx.album = g_value_dup_string(g_hash_table_lookup(metadata, "album")); current_info->bmpx.bitrate = g_value_get_int(g_hash_table_lookup(metadata, "bitrate")); current_info->bmpx.track = g_value_get_int(g_hash_table_lookup(metadata, "track-number")); current_info->bmpx.uri = g_value_get_string(g_hash_table_lookup(metadata, "location")); } else { NORM_ERR("BMPx error 4: %s\n", error->message); fail(error, current_info); return; } g_hash_table_destroy(metadata); } else { fail(error, current_info); } } void fail(GError *error, struct information *current_info) { if (error) { g_error_free(error); } if (current_info->bmpx.title) { g_free(current_info->bmpx.title); current_info->bmpx.title = 0; } if (current_info->bmpx.artist) { g_free(current_info->bmpx.artist); current_info->bmpx.artist = 0; } if (current_info->bmpx.album) { g_free(current_info->bmpx.album); current_info->bmpx.album = 0; } current_info->bmpx.title = unknown; current_info->bmpx.artist = unknown; current_info->bmpx.album = unknown; current_info->bmpx.bitrate = 0; current_info->bmpx.track = 0; } #define BMPX_PRINT_GENERATOR(name, fmt) \ void print_bmpx_##name(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ snprintf(p, p_max_size, fmt, info.bmpx.name); \ } BMPX_PRINT_GENERATOR(title, "%s") BMPX_PRINT_GENERATOR(artist, "%s") BMPX_PRINT_GENERATOR(album, "%s") BMPX_PRINT_GENERATOR(uri, "%s") BMPX_PRINT_GENERATOR(track, "%i") BMPX_PRINT_GENERATOR(bitrate, "%i") #undef BMPX_PRINT_GENERATOR conky-1.10.1/src/bmpx.h000066400000000000000000000027251262311664100146330ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Please see COPYING for details * * Copyright (c) 2005-2012 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 BMPX_H_ #define BMPX_H_ void update_bmpx(void); struct bmpx_s { char *title; char *artist; char *album; char *uri; int bitrate; int track; }; void print_bmpx_title(struct text_object *, char *, int); void print_bmpx_artist(struct text_object *, char *, int); void print_bmpx_album(struct text_object *, char *, int); void print_bmpx_uri(struct text_object *, char *, int); void print_bmpx_track(struct text_object *, char *, int); void print_bmpx_bitrate(struct text_object *, char *, int); #endif /*BMPX_H_*/ conky-1.10.1/src/bsdapm.cc000066400000000000000000000100761262311664100152670ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "text_object.h" #include #include #include #include #define APMDEV "/dev/apm" #define APM_UNKNOWN 255 #ifndef APM_AC_OFF # define APM_AC_OFF 0 #endif #ifndef APM_AC_ON # define APM_AC_ON 1 #endif #ifndef APM_BATT_CHARGING # define APM_BATT_CHARGING 3 #endif static int apm_getinfo(int fd, apm_info_t aip) { #ifdef __OpenBSD__ if (ioctl(fd, APM_IOC_GETPOWER, aip) == -1) { #else if (ioctl(fd, APMIO_GETINFO, aip) == -1) { #endif return -1; } return 0; } void print_apm_adapter(struct text_object *obj, char *p, int p_max_size) { int fd; const char *out; #ifdef __OpenBSD__ struct apm_power_info a_info; #else struct apm_info a_info; #endif (void)obj; fd = open(APMDEV, O_RDONLY); if (fd < 0) { snprintf(p, p_max_size, "ERR"); return; } if (apm_getinfo(fd, &a_info) != 0) { close(fd); snprintf(p, p_max_size, "ERR"); return; } close(fd); #ifdef __OpenBSD__ # define ai_acline ac_state #endif switch (a_info.ai_acline) { case APM_AC_OFF: out = "off-line"; break; case APM_AC_ON: #ifdef __OpenBSD__ # define ai_batt_stat battery_state #endif if (a_info.ai_batt_stat == APM_BATT_CHARGING) { out = "charging"; } else { out = "on-line"; } break; default: out = "unknown"; break; } snprintf(p, p_max_size, "%s", out); } void print_apm_battery_life(struct text_object *obj, char *p, int p_max_size) { int fd; u_int batt_life; const char *out; #ifdef __OpenBSD__ struct apm_power_info a_info; #else struct apm_info a_info; #endif (void)obj; fd = open(APMDEV, O_RDONLY); if (fd < 0) { snprintf(p, p_max_size, "ERR"); return; } if (apm_getinfo(fd, &a_info) != 0) { close(fd); snprintf(p, p_max_size, "ERR"); return; } close(fd); #ifdef __OpenBSD__ # define ai_batt_life battery_life #endif batt_life = a_info.ai_batt_life; if (batt_life == APM_UNKNOWN) { out = "unknown"; } else if (batt_life <= 100) { snprintf(p, p_max_size, "%d%%", batt_life); return; } else { out = "ERR"; } snprintf(p, p_max_size, "%s", out); } void print_apm_battery_time(struct text_object *obj, char *p, int p_max_size) { int fd; int batt_time; #ifdef __OpenBSD__ int h, m; struct apm_power_info a_info; #else int h, m, s; struct apm_info a_info; #endif (void)obj; fd = open(APMDEV, O_RDONLY); if (fd < 0) { snprintf(p, p_max_size, "ERR"); return; } if (apm_getinfo(fd, &a_info) != 0) { close(fd); snprintf(p, p_max_size, "ERR"); return; } close(fd); #ifdef __OpenBSD__ # define ai_batt_time minutes_left #endif batt_time = a_info.ai_batt_time; if (batt_time == -1) { snprintf(p, p_max_size, "unknown"); } else #ifdef __OpenBSD__ { h = batt_time / 60; m = batt_time % 60; snprintf(p, p_max_size, "%2d:%02d", h, m); } #else { h = batt_time; s = h % 60; h /= 60; m = h % 60; h /= 60; snprintf(p, p_max_size, "%2d:%02d:%02d", h, m, s); } #endif } conky-1.10.1/src/bsdapm.h000066400000000000000000000026061262311664100151310ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _BSDAPM_H #define _BSDAPM_H void print_apm_adapter(struct text_object *, char *, int); void print_apm_battery_life(struct text_object *, char *, int); void print_apm_battery_time(struct text_object *, char *, int); #endif /* _BSDAPM_H */ conky-1.10.1/src/build.h.in000066400000000000000000000002311262311664100153570ustar00rootroot00000000000000#ifndef __BUILD_H #define __BUILD_H /* Conky build info */ #define BUILD_DATE "@BUILD_DATE@" #define BUILD_ARCH "@BUILD_ARCH@" #endif /* __BUILD_H */ conky-1.10.1/src/c++wrap.cc000066400000000000000000000041611262311664100152610ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 "config.h" #include "c++wrap.hh" #include /* force use of POSIX strerror_r instead of non-portable GNU specific */ #ifdef _GNU_SOURCE #undef _GNU_SOURCE #endif #include #if __cplusplus <= 199711L #define thread_local __thread #endif #if !defined(HAVE_PIPE2) || !defined(HAVE_O_CLOEXEC) #include namespace { int pipe2_emulate(int pipefd[2], int flags) { if(pipe(pipefd) == -1) return -1; if(flags & O_CLOEXEC) { // we emulate O_CLOEXEC if the system does not have it // not very thread-safe, but at least it works for(int i = 0; i < 2; ++i) { int r = fcntl(pipefd[i], F_GETFD); if(r == -1) return -1; if(fcntl(pipefd[i], F_SETFD, r | FD_CLOEXEC) == -1) return -1; } } return 0; } int (* const pipe2_ptr)(int[2], int) = &pipe2_emulate; } #else int (* const pipe2_ptr)(int[2], int) = &pipe2; #endif std::string strerror_r(int errnum) { static thread_local char buf[100]; if (strerror_r(errnum, buf, sizeof buf) != 0) snprintf(buf, sizeof buf, "Unknown error %i", errnum); return buf; } std::pair pipe2(int flags) { int fd[2]; if(pipe2_ptr(fd, flags) == -1) throw errno_error("pipe2"); else return std::pair(fd[0], fd[1]); } conky-1.10.1/src/c++wrap.hh000066400000000000000000000026271262311664100153000ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 CPPWRAP_HH #define CPPWRAP_HH #ifdef HAVE_O_CLOEXEC #include #else enum { O_CLOEXEC = 02000000 }; #endif #include #include #include #include std::string strerror_r(int errnum); std::pair pipe2(int flags); class errno_error: public std::runtime_error { typedef std::runtime_error Base; public: errno_error(const std::string &prefix, int err_ = errno) : Base(prefix + ": " + strerror_r(err_)), err(err_) {} const int err; }; #endif /* CPPWRAP_HH */ conky-1.10.1/src/ccurl_thread.cc000066400000000000000000000136771262311664100164720ustar00rootroot00000000000000/* -*- 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-2012 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 "ccurl_thread.h" #include "text_object.h" #include #include #ifdef DEBUG #include #endif /* DEBUG */ #include /* * The following code is the conky curl thread lib, which can be re-used to * create any curl-based object (see weather and rss). Below is an * implementation of a curl-only object ($curl) which can also be used as an * example. */ namespace priv { /* callback used by curl for parsing the header data */ size_t curl_internal::parse_header_cb(void *ptr, size_t size, size_t nmemb, void *data) { curl_internal *obj = static_cast(data); const char *value = static_cast(ptr); size_t realsize = size * nmemb; if(realsize > 0 && (value[realsize-1] == '\r' || value[realsize-1] == 0)) --realsize; if (strncmp(value, "Last-Modified: ", 15) == EQUAL) { obj->last_modified = std::string(value + 15, realsize - 15); } else if (strncmp(value,"ETag: ", 6) == EQUAL) { obj->etag = std::string(value + 6, realsize - 6); } return size*nmemb; } /* callback used by curl for writing the received data */ size_t curl_internal::write_cb(void *ptr, size_t size, size_t nmemb, void *data) { curl_internal *obj = static_cast(data); const char *value = static_cast(ptr); size_t realsize = size * nmemb; obj->data += std::string(value, realsize); return realsize; } curl_internal::curl_internal(const std::string &url) : curl(curl_easy_init()) { if(not curl) throw std::runtime_error("curl_easy_init() failed"); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(curl, CURLOPT_HEADERDATA, this); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_USERAGENT, "conky-curl/1.1"); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1000); curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60); // curl's usage of alarm()+longjmp() is a really bad idea for multi-threaded applications curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); } /* fetch our datums */ void curl_internal::do_work() { CURLcode res; struct headers_ { struct curl_slist *h; headers_() : h(NULL) {} ~headers_() { curl_slist_free_all(h); } } headers; data.clear(); if (not last_modified.empty()) { headers.h = curl_slist_append(headers.h, ("If-Modified-Since: " + last_modified).c_str()); last_modified.clear(); } if (not etag.empty()) { headers.h = curl_slist_append(headers.h, ("If-None-Match: " + etag).c_str()); etag.clear(); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers.h); res = curl_easy_perform(curl); if (res == CURLE_OK) { long http_status_code; if (curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status_code) == CURLE_OK) { switch (http_status_code) { case 200: process_data(); break; case 304: break; default: NORM_ERR("curl: no data from server, got HTTP status %ld", http_status_code); break; } } else { NORM_ERR("curl: no HTTP status from server"); } } else { NORM_ERR("curl: could not retrieve data from server"); } } } namespace { class simple_curl_cb: public curl_callback { typedef curl_callback Base; protected: virtual void process_data() { std::lock_guard lock(result_mutex); result = data; } public: simple_curl_cb(uint32_t period, const std::string &uri) : Base(period, Tuple(uri)) {} }; } /* * This is where the $curl section begins. */ struct curl_data { char uri[128]; float interval; }; /* prints result data to text buffer, used by $curl */ void ccurl_process_info(char *p, int p_max_size, const std::string &uri, int interval) { uint32_t period = std::max(lround(interval/active_update_interval()), 1l); auto cb = conky::register_cb(period, uri); strncpy(p, cb->get_result_copy().c_str(), p_max_size); } void curl_parse_arg(struct text_object *obj, const char *arg) { int argc; struct curl_data *cd; float interval = 0; cd = (struct curl_data*)malloc(sizeof(struct curl_data)); memset(cd, 0, sizeof(struct curl_data)); argc = sscanf(arg, "%127s %f", cd->uri, &interval); if (argc < 1) { free(cd); NORM_ERR("wrong number of arguments for $curl"); return; } if (argc == 1) cd->interval = 15*60; else cd->interval = interval > 0 ? interval * 60 : active_update_interval(); obj->data.opaque = cd; } void curl_print(struct text_object *obj, char *p, int p_max_size) { struct curl_data *cd = (struct curl_data *)obj->data.opaque; if (!cd || !cd->uri) { NORM_ERR("error processing Curl data"); return; } ccurl_process_info(p, p_max_size, cd->uri, cd->interval); } void curl_obj_free(struct text_object *obj) { free_and_zero(obj->data.opaque); } conky-1.10.1/src/ccurl_thread.h000066400000000000000000000051131262311664100163160ustar00rootroot00000000000000/* -*- 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-2012 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 _CURL_THREAD_H_ #define _CURL_THREAD_H_ #include #include "update-cb.hh" namespace priv { // factored out stuff that does not depend on the template parameters struct curl_internal { std::string last_modified; std::string etag; std::string data; CURL *curl; static size_t parse_header_cb(void *ptr, size_t size, size_t nmemb, void *data); static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data); void do_work(); // called by do_work() after downloading data from the uri // it should populate the result variable virtual void process_data() = 0; curl_internal(const std::string &url); virtual ~curl_internal() { if(curl) curl_easy_cleanup(curl); } }; } /* * Curl callback class template * the key is an url */ template class curl_callback: public conky::callback, protected priv::curl_internal { typedef conky::callback Base1; typedef priv::curl_internal Base2; protected: virtual void work() { DBGP("reading curl data from '%s'", std::get<0>(Base1::tuple).c_str()); do_work(); } public: curl_callback(uint32_t period, const typename Base1::Tuple &tuple) : Base1(period, false, tuple), Base2(std::get<0>(tuple)) {} }; /* $curl exports begin */ /* runs instance of $curl */ void ccurl_process_info(char *p, int p_max_size, const std::string &uri, int interval); void curl_parse_arg(struct text_object *, const char *); void curl_print(struct text_object *, char *, int); void curl_obj_free(struct text_object *); /* $curl exports end */ #endif /* _CURL_THREAD_H_ */ conky-1.10.1/src/cmus.cc000066400000000000000000000142031262311664100147640ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * CMUS Conky integration * * Please see COPYING for details * * Copyright (c) 2008, Henri Häkkinen * * 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 "text_object.h" #include #include #include #include #include #include #include "update-cb.hh" namespace { struct cmus_result { std::string state; std::string file; std::string title; std::string artist; std::string album; std::string totaltime; std::string curtime; std::string random; std::string repeat; std::string aaa; std::string track; std::string genre; std::string date; float progress; float timeleft; }; class cmus_cb: public conky::callback { typedef conky::callback Base; protected: virtual void work(); public: cmus_cb(uint32_t period) : Base(period, false, Tuple()) {} }; void cmus_cb::work() { cmus_result cmus; FILE *fp; fp = popen("cmus-remote -Q 2>/dev/null", "r"); if (!fp) { cmus.state = "Can't run 'cmus-remote -Q'"; } else { while (1) { char line[255]; char *p; /* Read a line from the pipe and strip the possible '\n'. */ if (!fgets(line, 255, fp)) break; if ((p = strrchr(line, '\n'))) *p = '\0'; /* Parse infos. */ if (strncmp(line, "status ", 7) == 0) cmus.state = line + 7; else if (strncmp(line, "file ", 5) == 0) cmus.file = line + 5; else if (strncmp(line, "tag artist ", 11) == 0) cmus.artist = line + 11; else if (strncmp(line, "tag title ", 10) == 0) cmus.title = line + 10; else if (strncmp(line, "tag album ", 10) == 0) cmus.album = line + 10; else if (strncmp(line, "duration ", 9) == 0) cmus.totaltime = line + 9; else if (strncmp(line, "position ", 9) == 0) { cmus.curtime = line + 9; cmus.timeleft = atoi(cmus.totaltime.c_str()) - atoi(cmus.curtime.c_str()); if (cmus.curtime.size() > 0) cmus.progress = (float) atoi(cmus.curtime.c_str()) / atoi(cmus.totaltime.c_str()); else cmus.progress = 0; } else if (strncmp(line, "set shuffle ", 12) == 0) cmus.random = (strncmp(line+12, "true", 4) == 0 ? "on" : "off" ); else if (strncmp(line, "set repeat ", 11) == 0) cmus.repeat = (strncmp((line+11), "true", 4) == 0 ? "all" : "off" ); else if (strncmp(line, "set repeat_current ", 19) == 0) cmus.repeat = (strncmp((line + 19), "true", 4) == 0 ? "song" : cmus.repeat ); else if (strncmp(line, "set aaa_mode ", 13) == 0) cmus.aaa = line + 13; else if (strncmp(line, "tag tracknumber ", 16) == 0) cmus.track = line + 16; else if (strncmp(line, "tag genre ", 10) == 0) cmus.genre = line + 10; else if (strncmp(line, "tag date ", 9) == 0) cmus.date = line + 9; } } pclose(fp); std::lock_guard l(result_mutex); result = cmus; } } #define CMUS_PRINT_GENERATOR(type, alt) \ void print_cmus_##type(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ uint32_t period = std::max( \ lround(music_player_interval.get(*state)/active_update_interval()), 1l \ ); \ const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); \ snprintf(p, p_max_size, "%s", (cmus.type.length() ? cmus.type.c_str() : alt)); \ } CMUS_PRINT_GENERATOR(state, "Off") CMUS_PRINT_GENERATOR(file, "no file") CMUS_PRINT_GENERATOR(title, "no title") CMUS_PRINT_GENERATOR(artist, "no artist") CMUS_PRINT_GENERATOR(album, "no album") CMUS_PRINT_GENERATOR(random, "") CMUS_PRINT_GENERATOR(repeat, "") CMUS_PRINT_GENERATOR(aaa, "all") CMUS_PRINT_GENERATOR(track, "no track") CMUS_PRINT_GENERATOR(genre, "") CMUS_PRINT_GENERATOR(date, "") uint8_t cmus_percent(struct text_object *obj) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l); const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); return (uint8_t) round(cmus.progress * 100.0f); } double cmus_progress(struct text_object *obj) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l); const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); return (double) cmus.progress; } void print_cmus_totaltime(struct text_object *obj, char *p, int p_max_size) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l); const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); format_seconds_short(p, p_max_size, atol(cmus.totaltime.c_str())); } void print_cmus_timeleft(struct text_object *obj, char *p, int p_max_size) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l); const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); //format_seconds_short(p, p_max_size, atol(cmus.timeleft.c_str())); format_seconds_short(p, p_max_size, (long)cmus.timeleft); } void print_cmus_curtime(struct text_object *obj, char *p, int p_max_size) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l); const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); format_seconds_short(p, p_max_size, atol(cmus.curtime.c_str())); } #undef CMUS_PRINT_GENERATOR conky-1.10.1/src/cmus.h000066400000000000000000000036071262311664100146340ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * CMUS Conky integration * * Please see COPYING for details * * Copyright (c) 2011, Christian Brabandt * * 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 CMUS_H_ #define CMUS_H_ void print_cmus_state(struct text_object *, char *, int); void print_cmus_file(struct text_object *, char *, int); void print_cmus_title(struct text_object *, char *, int); void print_cmus_artist(struct text_object *, char *, int); void print_cmus_album(struct text_object *, char *, int); void print_cmus_totaltime(struct text_object *, char *, int); void print_cmus_timeleft(struct text_object *, char *, int); void print_cmus_curtime(struct text_object *, char *, int); void print_cmus_random(struct text_object *, char *, int); void print_cmus_repeat(struct text_object *, char *, int); void print_cmus_aaa(struct text_object *, char *, int); void print_cmus_track(struct text_object *, char *, int); void print_cmus_genre(struct text_object *, char *, int); void print_cmus_date(struct text_object *, char *, int); void print_cmus_bar(struct text_object *, char *, int); double cmus_progress(struct text_object *obj); uint8_t cmus_percent(struct text_object *obj); #endif /* CMUS_H_ */ conky-1.10.1/src/colours.cc000066400000000000000000000125151262311664100155070ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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" #ifdef BUILD_X11 #include "x11.h" #endif /* precalculated: 31/255, and 63/255 */ #define CONST_8_TO_5_BITS 0.12156862745098 #define CONST_8_TO_6_BITS 0.247058823529412 static short colour_depth = 0; static long redmask, greenmask, bluemask; static void set_up_gradient(void) { int i; #ifdef BUILD_X11 if (out_to_x.get(*state)) { colour_depth = DisplayPlanes(display, screen); } else #endif /* BUILD_X11 */ { colour_depth = 16; } if (colour_depth != 24 && colour_depth != 16) { NORM_ERR("using non-standard colour depth, gradients may look like a " "lolly-pop"); } redmask = 0; greenmask = 0; bluemask = 0; for (i = (colour_depth / 3) - 1; i >= 0; i--) { redmask |= 1 << i; greenmask |= 1 << i; bluemask |= 1 << i; } if (colour_depth % 3 == 1) { greenmask |= 1 << (colour_depth / 3); } redmask = redmask << (2 * colour_depth / 3 + colour_depth % 3); greenmask = greenmask << (colour_depth / 3); } /* adjust colour values depending on colour depth */ unsigned int adjust_colours(unsigned int colour) { double r, g, b; if (colour_depth == 0) { set_up_gradient(); } if (colour_depth == 16) { r = (colour & 0xff0000) >> 16; g = (colour & 0xff00) >> 8; b = colour & 0xff; colour = (int) (r * CONST_8_TO_5_BITS) << 11; colour |= (int) (g * CONST_8_TO_6_BITS) << 5; colour |= (int) (b * CONST_8_TO_5_BITS); } return colour; } /* this function returns the next colour between two colours for a gradient */ unsigned long *do_gradient(int width, unsigned long first_colour, unsigned long last_colour) { int red1, green1, blue1; // first colour int red2, green2, blue2; // last colour int reddiff, greendiff, bluediff; // difference short redshift = (2 * colour_depth / 3 + colour_depth % 3); short greenshift = (colour_depth / 3); unsigned long *colours = (unsigned long*)malloc(width * sizeof(unsigned long)); int i; if (colour_depth == 0) { set_up_gradient(); } red1 = (first_colour & redmask) >> redshift; green1 = (first_colour & greenmask) >> greenshift; blue1 = first_colour & bluemask; red2 = (last_colour & redmask) >> redshift; green2 = (last_colour & greenmask) >> greenshift; blue2 = last_colour & bluemask; reddiff = abs(red1 - red2); greendiff = abs(green1 - green2); bluediff = abs(blue1 - blue2); #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) shared(colours) #endif /* HAVE_OPENMP */ for (i = 0; i < width; i++) { int red3 = 0, green3 = 0, blue3 = 0; // colour components float factor = ((float) i / (width - 1)); /* the '+ 0.5' bit rounds our floats to ints properly */ if (red1 >= red2) { red3 = -(factor * reddiff) - 0.5; } else if (red1 < red2) { red3 = factor * reddiff + 0.5; } if (green1 >= green2) { green3 = -(factor * greendiff) - 0.5; } else if (green1 < green2) { green3 = factor * greendiff + 0.5; } if (blue1 >= blue2) { blue3 = -(factor * bluediff) - 0.5; } else if (blue1 < blue2) { blue3 = factor * bluediff + 0.5; } red3 += red1; green3 += green1; blue3 += blue1; if (red3 < 0) { red3 = 0; } if (green3 < 0) { green3 = 0; } if (blue3 < 0) { blue3 = 0; } if (red3 > bluemask) { red3 = bluemask; } if (green3 > bluemask) { green3 = bluemask; } if (blue3 > bluemask) { blue3 = bluemask; } colours[i] = (red3 << redshift) | (green3 << greenshift) | blue3; } return colours; } #ifdef BUILD_X11 long get_x11_color(const char *name) { XColor color; color.pixel = 0; if (!XParseColor(display, DefaultColormap(display, screen), name, &color)) { /* lets check if it's a hex colour with the # missing in front * if yes, then do something about it */ char newname[DEFAULT_TEXT_BUFFER_SIZE]; newname[0] = '#'; strncpy(&newname[1], name, DEFAULT_TEXT_BUFFER_SIZE - 1); /* now lets try again */ if (!XParseColor(display, DefaultColormap(display, screen), &newname[0], &color)) { NORM_ERR("can't parse X color '%s'", name); return 0xFF00FF; } } if (!XAllocColor(display, DefaultColormap(display, screen), &color)) { NORM_ERR("can't allocate X color '%s'", name); } return (long) color.pixel; } long get_x11_color(const std::string &colour) { return get_x11_color(colour.c_str()); } #endif conky-1.10.1/src/colours.h000066400000000000000000000027141262311664100153510ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _COLOURS_H #define _COLOURS_H unsigned int adjust_colours(unsigned int); unsigned long *do_gradient(int, unsigned long, unsigned long); long get_x11_color(const std::string &colour); // XXX: when everyone uses C++ strings, remove this C version long get_x11_color(const char *); #endif /* _COLOURS_H */ conky-1.10.1/src/combine.cc000066400000000000000000000131111262311664100154260ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "core.h" #include "logging.h" #include "text_object.h" struct combine_data { char *left; char *seperation; char *right; }; void parse_combine_arg(struct text_object *obj, const char *arg) { struct combine_data *cd; unsigned int i,j; unsigned int indenting = 0; //vars can be used as args for other vars int startvar[2]; int endvar[2]; startvar[0] = endvar[0] = startvar[1] = endvar[1] = -1; j=0; for (i=0; arg[i] != 0 && j < 2; i++) { if(startvar[j] == -1) { if(arg[i] == '$') { startvar[j] = i; } }else if(endvar[j] == -1) { if(arg[i] == '{') { indenting++; }else if(arg[i] == '}') { indenting--; } if (indenting == 0 && arg[i+1] < 48) { //<48 has 0, $, and the most used chars not used in varnames but not { or } endvar[j]=i+1; j++; } } } if(startvar[0] >= 0 && endvar[0] >= 0 && startvar[1] >= 0 && endvar[1] >= 0) { cd = (struct combine_data*)malloc(sizeof(struct combine_data)); memset(cd, 0, sizeof(struct combine_data)); cd->left = (char*)malloc(endvar[0]-startvar[0] + 1); cd->seperation = (char*)malloc(startvar[1] - endvar[0] + 1); cd->right= (char*)malloc(endvar[1]-startvar[1] + 1); strncpy(cd->left, arg + startvar[0], endvar[0] - startvar[0]); cd->left[endvar[0] - startvar[0]] = 0; strncpy(cd->seperation, arg + endvar[0], startvar[1] - endvar[0]); cd->seperation[startvar[1] - endvar[0]] = 0; strncpy(cd->right, arg + startvar[1], endvar[1] - startvar[1]); cd->right[endvar[1] - startvar[1]] = 0; obj->sub = (struct text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, cd->left); obj->sub->sub = (struct text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub->sub, cd->right); obj->data.opaque = cd; } else { throw combine_needs_2_args_error(); } } void print_combine(struct text_object *obj, char *p, int p_max_size) { struct combine_data *cd = (struct combine_data *)obj->data.opaque; std::vector> buf; buf.resize(2); buf[0].resize(max_user_text.get(*state)); buf[1].resize(max_user_text.get(*state)); int i, j; long longest=0; int nextstart; int nr_rows[2]; struct llrows { char* row; struct llrows* next; }; struct llrows *ll_rows[2], *current[2]; struct text_object * objsub = obj->sub; if (!cd || !p_max_size) return; p[0]=0; for(i=0; i<2; i++) { nr_rows[i] = 1; nextstart = 0; ll_rows[i] = (struct llrows*)malloc(sizeof(struct llrows)); current[i] = ll_rows[i]; for(j=0; jsub; generate_text_internal(&(buf[i][0]), max_user_text.get(*state), *objsub); for(j=0; buf[i][j] != 0; j++) { if(buf[i][j] == '\t') buf[i][j] = ' '; if(buf[i][j] == '\n') buf[i][j] = 0; //the vars inside combine may not have a \n at the end if(buf[i][j] == 2) { // \002 is used instead of \n to separate lines inside a var buf[i][j] = 0; current[i]->row = strdup(&(buf[i][0])+nextstart); if(i==0 && (long)strlen(current[i]->row) > longest) longest = (long)strlen(current[i]->row); current[i]->next = (struct llrows*)malloc(sizeof(struct llrows)); current[i] = current[i]->next; nextstart = j + 1; nr_rows[i]++; } } current[i]->row = strdup(&(buf[i][0])+nextstart); if(i==0 && (long)strlen(current[i]->row) > longest) longest = (long)strlen(current[i]->row); current[i]->next = NULL; current[i] = ll_rows[i]; } for(j=0; j < (nr_rows[0] > nr_rows[1] ? nr_rows[0] : nr_rows[1] ); j++) { if(current[0]) { strcat(p, current[0]->row); i=strlen(current[0]->row); }else i = 0; while(i < longest) { strcat(p, " "); i++; } if(current[1]) { strcat(p, cd->seperation); strcat(p, current[1]->row); } strcat(p, "\n"); #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for(i=0; i<2; i++) if(current[i]) current[i]=current[i]->next; } #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for(i=0; i<2; i++) { while(ll_rows[i] != NULL) { current[i]=ll_rows[i]; free(current[i]->row); ll_rows[i]=current[i]->next; free(current[i]); } } } void free_combine(struct text_object *obj) { struct combine_data *cd = (struct combine_data *)obj->data.opaque; if (!cd) return; free(cd->left); free(cd->seperation); free(cd->right); free_text_objects(obj->sub->sub); free_and_zero(obj->sub->sub); free_text_objects(obj->sub); free_and_zero(obj->sub); free_and_zero(obj->data.opaque); } conky-1.10.1/src/combine.h000066400000000000000000000025561262311664100153030ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _COMBINE_H #define _COMBINE_H void parse_combine_arg(struct text_object *, const char *); void print_combine(struct text_object *, char *, int); void free_combine(struct text_object *); #endif /* _COMBINE_H */ conky-1.10.1/src/common.cc000066400000000000000000000414701262311664100153130ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "core.h" #include "fs.h" #include "logging.h" #include "net_stat.h" #include "specials.h" #include "temphelper.h" #include "timeinfo.h" #include "top.h" #include #include #include #include #include #include #include #include #include #include #include /* check for OS and include appropriate headers */ #if defined(__linux__) #include "linux.h" #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "freebsd.h" #elif defined(__DragonFly__) #include "dragonfly.h" #elif defined(__OpenBSD__) #include "openbsd.h" #endif #include "update-cb.hh" #ifdef BUILD_CURL #include "ccurl_thread.h" #endif /* BUILD_CURL */ /* folds a string over top of itself, like so: * * if start is "blah", and you call it with count = 1, the result will be "lah" */ void strfold(char *start, int count) { char *curplace; for (curplace = start + count; *curplace != 0; curplace++) { *(curplace - count) = *curplace; } *(curplace - count) = 0; } #ifndef HAVE_STRNDUP // use our own strndup() if it's not available char *strndup(const char *s, size_t n) { if (strlen(s) > n) { char *ret = malloc(n + 1); strncpy(ret, s, n); ret[n] = 0; return ret; } else { return strdup(s); } } #endif /* HAVE_STRNDUP */ int update_uname(void) { uname(&info.uname_s); #if defined(__DragonFly__) { size_t desc_n; char desc[256]; if (sysctlbyname("kern.version", NULL, &desc_n, NULL, 0) == -1 || sysctlbyname("kern.version", desc, &desc_n, NULL, 0) == -1) perror("kern.version"); else { char *start = desc; strsep(&start, " "); strcpy(info.uname_v, strsep(&start, " ")); } if (errno == ENOMEM) printf("desc_n %zu\n", desc_n); } #endif return 0; } double get_time(void) { struct timespec tv; clock_gettime(CLOCK_MONOTONIC, &tv); return tv.tv_sec + (tv.tv_nsec * 1e-9); } /* Converts '~/...' paths to '/home/blah/...' * It's similar to variable_substitute, except only cheques for $HOME and ~/ in path */ std::string to_real_path(const std::string &source) { const char *homedir = getenv("HOME"); if(source.find("~/") == 0) return homedir + source.substr(1); else if(source.find("$HOME/") == 0) return homedir + source.substr(5); else return source; } int open_fifo(const char *file, int *reported) { int fd = 0; fd = open(file, O_RDONLY | O_NONBLOCK); if (fd == -1) { if (!reported || *reported == 0) { NORM_ERR("can't open %s: %s", file, strerror(errno)); if (reported) { *reported = 1; } } return -1; } return fd; } FILE *open_file(const char *file, int *reported) { FILE *fp = 0; fp = fopen(file, "r"); if (!fp) { if (!reported || *reported == 0) { NORM_ERR("can't open %s: %s", file, strerror(errno)); if (reported) { *reported = 1; } } return NULL; } return fp; } std::string variable_substitute(std::string s) { std::string::size_type pos = 0; while((pos = s.find('$', pos)) != std::string::npos) { if(pos + 1 >= s.size()) break; if(s[pos+1] == '$') { s.erase(pos, 1); ++pos; } else { std::string var; std::string::size_type l = 0; if(isalpha(s[pos+1])) { l = 1; while(pos+l < s.size() && isalnum(s[pos+l])) ++l; var = s.substr(pos+1, l-1); } else if(s[pos+1] == '{') { l = s.find('}', pos); if(l == std::string::npos) break; l -= pos - 1; var = s.substr(pos+2, l-3); } else ++pos; if(l) { s.erase(pos, l); const char *val = getenv(var.c_str()); if(val) { s.insert(pos, val); pos += strlen(val); } } } } return s; } void format_seconds(char *buf, unsigned int n, long seconds) { long days; int hours, minutes; if (times_in_seconds.get(*state)) { snprintf(buf, n, "%ld", seconds); return; } days = seconds / 86400; seconds %= 86400; hours = seconds / 3600; seconds %= 3600; minutes = seconds / 60; seconds %= 60; if (days > 0) { snprintf(buf, n, "%ldd %dh %dm", days, hours, minutes); } else { snprintf(buf, n, "%dh %dm %lds", hours, minutes, seconds); } } void format_seconds_short(char *buf, unsigned int n, long seconds) { long days; int hours, minutes; if (times_in_seconds.get(*state)) { snprintf(buf, n, "%ld", seconds); return; } days = seconds / 86400; seconds %= 86400; hours = seconds / 3600; seconds %= 3600; minutes = seconds / 60; seconds %= 60; if (days > 0) { snprintf(buf, n, "%ldd %dh", days, hours); } else if (hours > 0) { snprintf(buf, n, "%dh %dm", hours, minutes); } else { snprintf(buf, n, "%dm %lds", minutes, seconds); } } conky::simple_config_setting no_buffers("no_buffers", true, true); void update_stuff(void) { int i; /* clear speeds, addresses and up status in case device was removed and * doesn't get updated */ #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (i = 0; i < MAX_NET_INTERFACES; i++) { if (netstats[i].dev) { netstats[i].up = 0; netstats[i].recv_speed = 0.0; netstats[i].trans_speed = 0.0; netstats[i].addr.sa_data[2] = 0; netstats[i].addr.sa_data[3] = 0; netstats[i].addr.sa_data[4] = 0; netstats[i].addr.sa_data[5] = 0; } } prepare_update(); conky::run_all_callbacks(); /* XXX: move the following into the update_meminfo() functions? */ if (no_buffers.get(*state)) { info.mem -= info.bufmem; info.memeasyfree += info.bufmem; } } /* Ohkie to return negative values for temperatures */ int round_to_int_temp(float f) { if (f >= 0.0) { return (int) (f + 0.5); } else { return (int) (f - 0.5); } } /* Don't return negative values for cpugraph, bar, gauge, percentage. * Causes unreasonable numbers to show */ unsigned int round_to_int(float f) { if (f >= 0.0) { return (int) (f + 0.5); } else { return 0; } } void scan_loadavg_arg(struct text_object *obj, const char *arg) { obj->data.i = 0; if (arg && !arg[1] && isdigit(arg[0])) { obj->data.i = atoi(arg); if (obj->data.i > 3 || obj->data.i < 1) { NORM_ERR("loadavg arg needs to be in range (1,3)"); obj->data.i = 0; } } /* convert to array index (or the default (-1)) */ obj->data.i--; } void print_loadavg(struct text_object *obj, char *p, int p_max_size) { float *v = info.loadavg; if (obj->data.i < 0) { snprintf(p, p_max_size, "%.2f %.2f %.2f", v[0], v[1], v[2]); } else { snprintf(p, p_max_size, "%.2f", v[obj->data.i]); } } void scan_no_update(struct text_object *obj, const char *arg) { obj->data.s = (char*) malloc(text_buffer_size.get(*state)); evaluate(arg, obj->data.s, text_buffer_size.get(*state)); obj->data.s = (char*) realloc(obj->data.s, strlen(obj->data.s) + 1); } void free_no_update(struct text_object *obj) { free(obj->data.s); } void print_no_update(struct text_object *obj, char *p, int p_max_size) { snprintf(p, p_max_size, "%s", obj->data.s); } #ifdef BUILD_X11 void scan_loadgraph_arg(struct text_object *obj, const char *arg) { char *buf = 0; buf = scan_graph(obj, arg, 0); free_and_zero(buf); } double loadgraphval(struct text_object *obj) { (void)obj; return info.loadavg[0]; } #endif /* BUILD_X11 */ uint8_t cpu_percentage(struct text_object *obj) { if (obj->data.i > info.cpu_count) { NORM_ERR("obj->data.i %i info.cpu_count %i", obj->data.i, info.cpu_count); CRIT_ERR(NULL, NULL, "attempting to use more CPUs than you have!"); } if (info.cpu_usage) { return round_to_int(info.cpu_usage[obj->data.i] * 100.0); } else { return 0; } } double cpu_barval(struct text_object *obj) { if (info.cpu_usage) { return info.cpu_usage[obj->data.i]; } else { return 0.; } } #define PRINT_HR_GENERATOR(name) \ void print_##name(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ human_readable(info.name * 1024, p, p_max_size); \ } PRINT_HR_GENERATOR(mem) PRINT_HR_GENERATOR(memwithbuffers) PRINT_HR_GENERATOR(memeasyfree) PRINT_HR_GENERATOR(memfree) PRINT_HR_GENERATOR(memmax) PRINT_HR_GENERATOR(memdirty) PRINT_HR_GENERATOR(swap) PRINT_HR_GENERATOR(swapfree) PRINT_HR_GENERATOR(swapmax) uint8_t mem_percentage(struct text_object *obj) { (void)obj; return (info.memmax ? round_to_int(info.mem * 100 / info.memmax) : 0); } double mem_barval(struct text_object *obj) { (void)obj; return info.memmax ? ((double)info.mem / info.memmax) : 0; } double mem_with_buffers_barval(struct text_object *obj) { (void)obj; return info.memmax ? ((double)info.memwithbuffers / info.memmax) : 0; } uint8_t swap_percentage(struct text_object *obj) { (void)obj; return (info.swapmax ? round_to_int(info.swap * 100 / info.swapmax) : 0); } double swap_barval(struct text_object *obj) { (void)obj; return info.swapmax ? ((double)info.swap / info.swapmax) : 0; } void print_kernel(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.uname_s.release); } void print_machine(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.uname_s.machine); } void print_nodename(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.uname_s.nodename); } void print_nodename_short(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.uname_s.nodename); for(int i=0; p[i] != 0; i++) { if(p[i] == '.') { p[i] = 0; break; } } } void print_sysname(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.uname_s.sysname); } #if defined(__DragonFly__) void print_version(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.uname_v); } #endif void print_uptime(struct text_object *obj, char *p, int p_max_size) { (void)obj; format_seconds(p, p_max_size, (int)info.uptime); } void print_uptime_short(struct text_object *obj, char *p, int p_max_size) { (void)obj; format_seconds_short(p, p_max_size, (int)info.uptime); } void print_processes(struct text_object *obj, char *p, int p_max_size) { (void)obj; spaced_print(p, p_max_size, "%hu", 4, info.procs); } void print_running_processes(struct text_object *obj, char *p, int p_max_size) { (void)obj; spaced_print(p, p_max_size, "%hu", 4, info.run_procs); } void print_running_threads(struct text_object *obj, char *p, int p_max_size) { (void)obj; spaced_print(p, p_max_size, "%hu", 4, info.run_threads); } void print_threads(struct text_object *obj, char *p, int p_max_size) { (void)obj; spaced_print(p, p_max_size, "%hu", 4, info.threads); } void print_buffers(struct text_object *obj, char *p, int p_max_size) { (void)obj; human_readable(info.buffers * 1024, p, p_max_size); } void print_cached(struct text_object *obj, char *p, int p_max_size) { (void)obj; human_readable(info.cached * 1024, p, p_max_size); } void print_evaluate(struct text_object *obj, char *p, int p_max_size) { evaluate(obj->data.s, p, p_max_size); } int if_empty_iftest(struct text_object *obj) { std::vector buf(max_user_text.get(*state)); int result = 1; generate_text_internal(&(buf[0]), max_user_text.get(*state), *obj->sub); if (strlen(&(buf[0])) != 0) { result = 0; } return result; } static int check_contains(char *f, char *s) { int ret = 0; FILE *where = open_file(f, 0); if (where) { char buf1[256]; while (fgets(buf1, 256, where)) { if (strstr(buf1, s)) { ret = 1; break; } } fclose(where); } else { NORM_ERR("Could not open the file"); } return ret; } int if_existing_iftest(struct text_object *obj) { char *spc; int result = 0; spc = strchr(obj->data.s, ' '); if(spc != NULL) *spc = 0; if (access(obj->data.s, F_OK) == 0) { if(spc == NULL || check_contains(obj->data.s, spc + 1)) result = 1; } if(spc != NULL) *spc = ' '; return result; } int if_running_iftest(struct text_object *obj) { #ifdef __linux__ if (!get_process_by_name(obj->data.s)) { #else if ((obj->data.s) && system(obj->data.s)) { #endif return 0; } return 1; } #ifndef __OpenBSD__ void print_acpitemp(struct text_object *obj, char *p, int p_max_size) { temp_print(p, p_max_size, get_acpi_temperature(obj->data.i), TEMP_CELSIUS); } void free_acpitemp(struct text_object *obj) { close(obj->data.i); } #endif /* !__OpenBSD__ */ void print_freq(struct text_object *obj, char *p, int p_max_size) { static int ok = 1; if (ok) { ok = get_freq(p, p_max_size, "%.0f", 1, obj->data.i); } } void print_freq_g(struct text_object *obj, char *p, int p_max_size) { static int ok = 1; if (ok) { #ifndef __OpenBSD__ ok = get_freq(p, p_max_size, "%'.2f", 1000, obj->data.i); #else /* OpenBSD has no such flag (SUSv2) */ ok = get_freq(p, p_max_size, "%.2f", 1000, obj->data.i); #endif /* __OpenBSD */ } } #ifndef __OpenBSD__ void print_acpifan(struct text_object *obj, char *p, int p_max_size) { (void)obj; get_acpi_fan(p, p_max_size); } void print_acpiacadapter(struct text_object *obj, char *p, int p_max_size) { get_acpi_ac_adapter(p, p_max_size, (const char *)obj->data.opaque); } void print_battery(struct text_object *obj, char *p, int p_max_size) { get_battery_stuff(p, p_max_size, obj->data.s, BATTERY_STATUS); } void print_battery_time(struct text_object *obj, char *p, int p_max_size) { get_battery_stuff(p, p_max_size, obj->data.s, BATTERY_TIME); } uint8_t battery_percentage(struct text_object *obj) { return get_battery_perct(obj->data.s); } void print_battery_short(struct text_object *obj, char *p, int p_max_size) { get_battery_short_status(p, p_max_size, obj->data.s); } #endif /* !__OpenBSD__ */ void print_blink(struct text_object *obj, char *p, int p_max_size) { //blinking like this can look a bit ugly if the chars in the font don't have the same width std::vector buf(max_user_text.get(*state)); static int visible = 1; static int last_len = 0; int i; if (visible) { generate_text_internal(&(buf[0]), max_user_text.get(*state), *obj->sub); last_len = strlen(&(buf[0])); } else { for (i = 0; i < last_len; i++) buf[i] = ' '; } snprintf(p, p_max_size, "%s", &(buf[0])); visible = !visible; } void print_include(struct text_object *obj, char *p, int p_max_size) { std::vector buf(max_user_text.get(*state)); if (!obj->sub) return; generate_text_internal(&(buf[0]), max_user_text.get(*state), *obj->sub); snprintf(p, p_max_size, "%s", &(buf[0])); } #ifdef BUILD_CURL void print_stock(struct text_object *obj, char *p, int p_max_size) { if( ! obj->data.s) { p[0] = 0; return; } ccurl_process_info(p, p_max_size, obj->data.s, 1); } void free_stock(struct text_object *obj) { free(obj->data.s); } #endif /* BUILD_CURL */ void print_to_bytes(struct text_object *obj, char *p, int p_max_size) { std::vector buf(max_user_text.get(*state)); long long bytes; char unit[16]; // 16 because we can also have long names (like mega-bytes) generate_text_internal(&(buf[0]), max_user_text.get(*state), *obj->sub); if(sscanf(&(buf[0]), "%lli%s", &bytes, unit) == 2 && strlen(unit) < 16){ if(strncasecmp("b", unit, 1) == 0) snprintf(&(buf[0]), max_user_text.get(*state), "%lli", bytes); else if(strncasecmp("k", unit, 1) == 0) snprintf(&(buf[0]), max_user_text.get(*state), "%lli", bytes * 1024); else if(strncasecmp("m", unit, 1) == 0) snprintf(&(buf[0]), max_user_text.get(*state), "%lli", bytes * 1024 * 1024); else if(strncasecmp("g", unit, 1) == 0) snprintf(&(buf[0]), max_user_text.get(*state), "%lli", bytes * 1024 * 1024 * 1024); else if(strncasecmp("t", unit, 1) == 0) snprintf(&(buf[0]), max_user_text.get(*state), "%lli", bytes * 1024 * 1024 * 1024 * 1024); } snprintf(p, p_max_size, "%s", &(buf[0])); } void print_updates(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%d", get_total_updates()); } int updatenr_iftest(struct text_object *obj) { if (get_total_updates() % get_updatereset() != obj->data.i - 1) return 0; return 1; } conky-1.10.1/src/common.h000066400000000000000000000142301262311664100151470ustar00rootroot00000000000000/* -*- 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-2012 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 _COMMON_H #define _COMMON_H #include #include #include #include #include #include "text_object.h" #include "setting.hh" char* readfile(const char* filename, int* total_read, char showerror); void print_to_bytes(struct text_object *, char *, int); void strfold(char *start, int count); int check_mount(struct text_object *); void prepare_update(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); int update_load_average(void); void free_all_processes(void); struct process *get_first_process(void); void get_cpu_count(void); double get_time(void); /* Converts '~/...' paths to '/home/blah/...' * It's similar to variable_substitute, except only cheques for $HOME and ~/ in path */ std::string to_real_path(const std::string &source); FILE *open_file(const char *file, int *reported); int open_fifo(const char *file, int *reported); std::string variable_substitute(std::string s); void format_seconds(char *buf, unsigned int n, long t); void format_seconds_short(char *buf, unsigned int n, long t); int round_to_int_temp(float); unsigned int round_to_int(float); extern conky::simple_config_setting no_buffers; int open_acpi_temperature(const char *name); double get_acpi_temperature(int fd); void get_acpi_ac_adapter(char *p_client_buffer, size_t client_buffer_size, const char *adapter); void get_acpi_fan(char *, size_t); void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item); int get_battery_perct(const char *bat); double get_battery_perct_bar(struct text_object *); void get_battery_short_status(char *buf, unsigned int n, const char *bat); void scan_no_update(struct text_object *, const char *); void print_no_update(struct text_object *, char *, int); void free_no_update(struct text_object *); void scan_loadavg_arg(struct text_object *, const char *); void print_loadavg(struct text_object *, char *, int); #ifdef BUILD_X11 void scan_loadgraph_arg(struct text_object *, const char *); double loadgraphval(struct text_object *); #endif /* BUILD_X11 */ uint8_t cpu_percentage(struct text_object *); double cpu_barval(struct text_object *); void print_mem(struct text_object *, char *, int); void print_memwithbuffers(struct text_object *, char *, int); void print_memeasyfree(struct text_object *, char *, int); void print_memfree(struct text_object *, char *, int); void print_memmax(struct text_object *, char *, int); void print_memdirty(struct text_object *, char *, int); void print_swap(struct text_object *, char *, int); void print_swapfree(struct text_object *, char *, int); void print_swapmax(struct text_object *, char *, int); uint8_t mem_percentage(struct text_object *); double mem_barval(struct text_object *); double mem_with_buffers_barval(struct text_object *); uint8_t swap_percentage(struct text_object *); double swap_barval(struct text_object *); void print_kernel(struct text_object *, char *, int); void print_machine(struct text_object *, char *, int); void print_nodename(struct text_object *, char *, int); void print_nodename_short(struct text_object *, char *, int); void print_sysname(struct text_object *, char *, int); #if defined(__DragonFly__) void print_version(struct text_object *obj, char *p, int p_max_size); #endif void print_uptime(struct text_object *, char *, int); void print_uptime_short(struct text_object *, char *, int); void print_processes(struct text_object *, char *, int); void print_running_processes(struct text_object *, char *, int); void print_running_threads(struct text_object *, char *, int); void print_threads(struct text_object *, char *, int); void print_buffers(struct text_object *, char *, int); void print_cached(struct text_object *, char *, int); void print_evaluate(struct text_object *, char *, int); int if_empty_iftest(struct text_object *); int if_existing_iftest(struct text_object *); int if_running_iftest(struct text_object *); #ifndef __OpenBSD__ void print_acpitemp(struct text_object *, char *, int); void free_acpitemp(struct text_object *); #endif /* !__OpenBSD__ */ void print_freq(struct text_object *, char *, int); void print_freq_g(struct text_object *, char *, int); #ifndef __OpenBSD__ void print_acpifan(struct text_object *, char *, int); void print_acpiacadapter(struct text_object *, char *, int); void print_battery(struct text_object *, char *, int); void print_battery_time(struct text_object *, char *, int); uint8_t battery_percentage(struct text_object *); void print_battery_short(struct text_object *, char *, int); #endif /* !__OpenBSD__ */ void print_blink(struct text_object *, char *, int); void print_include(struct text_object *, char *, int); void print_updates(struct text_object *, char *, int); int updatenr_iftest(struct text_object *); #ifdef BUILD_CURL void print_stock(struct text_object *, char *, int); void free_stock(struct text_object *); #endif /* BUILD_CURL */ #endif /* _COMMON_H */ conky-1.10.1/src/conky.cc000066400000000000000000002442451262311664100151530ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "text_object.h" #include "conky.h" #include "common.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_DIRENT_H #include #endif /* HAVE_DIRENT_H */ #include #include #ifdef HAVE_SYS_INOTIFY_H #include #endif /* HAVE_SYS_INOTIFY_H */ #ifdef BUILD_X11 #include "x11.h" #include #ifdef BUILD_XDAMAGE #include #endif #ifdef BUILD_IMLIB2 #include "imlib2.h" #endif /* BUILD_IMLIB2 */ #endif /* BUILD_X11 */ #include #include #include #include #include #include #if defined BUILD_WEATHER_XOAP || defined BUILD_RSS #include #endif #ifdef BUILD_CURL #include #endif /* local headers */ #include "core.h" #include "build.h" #include "colours.h" #include "diskio.h" #include "exec.h" #ifdef BUILD_X11 #include "fonts.h" #endif #ifdef BUILD_ICONV #include "iconv_tools.h" #endif #include "llua.h" #include "logging.h" #include "mail.h" #include "nc.h" #include "net_stat.h" #include "temphelper.h" #include "template.h" #include "timeinfo.h" #include "top.h" #ifdef BUILD_MYSQL #include "mysql.h" #endif /* BUILD_MYSQL */ #ifdef BUILD_NVIDIA #include "nvidia.h" #endif #ifdef BUILD_CURL #include "ccurl_thread.h" #endif /* BUILD_CURL */ #ifdef BUILD_WEATHER_METAR #include "weather.h" #endif /* BUILD_WEATHER_METAR */ #include "lua-config.hh" #include "setting.hh" /* check for OS and include appropriate headers */ #if defined(__linux__) #include "linux.h" #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "freebsd.h" #elif defined(__DragonFly__) #include "dragonfly.h" #elif defined(__OpenBSD__) #include "openbsd.h" #endif #ifdef BUILD_HTTP #include #endif #if defined(__FreeBSD_kernel__) #include #endif #ifdef BUILD_BUILTIN_CONFIG #include "defconfig.h" namespace { const char builtin_config_magic[] = "==builtin=="; } #endif #ifdef BUILD_OLD_CONFIG #include "convertconf.h" #endif #ifndef S_ISSOCK #define S_ISSOCK(x) ((x & S_IFMT) == S_IFSOCK) #endif #define MAX_IF_BLOCK_DEPTH 5 //#define SIGNAL_BLOCKING #undef SIGNAL_BLOCKING /* debugging level, used by logging.h */ int global_debug_level = 0; /* disable inotify auto reload feature if desired */ static conky::simple_config_setting disable_auto_reload("disable_auto_reload", false, false); /* two strings for internal use */ static char *tmpstring1, *tmpstring2; enum spacer_state { NO_SPACER = 0, LEFT_SPACER, RIGHT_SPACER }; template<> conky::lua_traits::Map conky::lua_traits::map = { { "none", NO_SPACER }, { "left", LEFT_SPACER }, { "right", RIGHT_SPACER } }; static conky::simple_config_setting use_spacer("use_spacer", NO_SPACER, false); /* variables holding various config settings */ static conky::simple_config_setting short_units("short_units", false, true); static conky::simple_config_setting format_human_readable("format_human_readable", true, true); static conky::simple_config_setting out_to_stdout("out_to_console", // Default value is false, unless we are building without X #ifdef BUILD_X11 false, #else true, #endif false); static conky::simple_config_setting out_to_stderr("out_to_stderr", false, false); int top_cpu, top_mem, top_time; #ifdef BUILD_IOSTATS int top_io; #endif int top_running; static conky::simple_config_setting extra_newline("extra_newline", false, false); static volatile int g_signal_pending; /* Update interval */ conky::range_config_setting update_interval("update_interval", 0.0, std::numeric_limits::infinity(), 3.0, true); conky::range_config_setting update_interval_on_battery("update_interval_on_battery", 0.0, std::numeric_limits::infinity(), NOBATTERY, true); static bool on_battery = false; double active_update_interval() { return (on_battery?update_interval_on_battery:update_interval).get(*state); } void music_player_interval_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); if(l.isnil(-2)) { l.checkstack(1); l.pushnumber(update_interval.get(l)); l.replace(-3); } Base::lua_setter(l, init); ++s; } music_player_interval_setting music_player_interval; void *global_cpu = NULL; static conky::range_config_setting max_text_width("max_text_width", 0, std::numeric_limits::max(), 0, true); #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) extern kvm_t *kd; #endif int argc_copy; char** argv_copy; /* prototypes for internally used functions */ static void signal_handler(int); static void reload_config(void); static void print_version(void) { std::cout << _(PACKAGE_NAME" " VERSION" compiled " BUILD_DATE" for " BUILD_ARCH"\n" "\nCompiled in features:\n\n" "System config file: " SYSTEM_CONFIG_FILE"\n" "Package library path: " PACKAGE_LIBDIR"\n\n") << _("\n General:\n") #ifdef HAVE_OPENMP << _(" * OpenMP\n") #endif /* HAVE_OPENMP */ #ifdef BUILD_MATH << _(" * math\n") #endif /* BUILD_MATH */ #ifdef BUILD_HDDTEMP << _(" * hddtemp\n") #endif /* BUILD_HDDTEMP */ #ifdef BUILD_PORT_MONITORS << _(" * portmon\n") #endif /* BUILD_PORT_MONITORS */ #ifdef BUILD_HTTP << _(" * HTTP\n") #endif #ifdef BUILD_IPV6 << _(" * IPv6\n") #endif /* BUILD_IPV6 */ #ifdef BUILD_IRC << _(" * IRC\n") #endif #ifdef BUILD_CURL << _(" * Curl\n") #endif /* BUILD_CURL */ #ifdef BUILD_RSS << _(" * RSS\n") #endif /* BUILD_RSS */ #ifdef BUILD_ICAL << _(" * ICal\n") #endif /* BUILD_ICAL */ #ifdef BUILD_ICONV << _(" * iconv\n") #endif /* BUILD_ICONV */ #ifdef BUILD_MYSQL << _(" * MySQL\n") #endif /* BUILD_MYSQL */ #ifdef BUILD_WEATHER_METAR << _(" * Weather (METAR)\n") #endif /* BUILD_WEATHER_METAR */ #ifdef BUILD_WEATHER_XOAP << _(" * Weather (XOAP)\n") #endif /* BUILD_WEATHER_XOAP */ #ifdef BUILD_WLAN << _(" * wireless\n") #endif /* BUILD_WLAN */ #ifdef BUILD_IBM << _(" * support for IBM/Lenovo notebooks\n") #endif /* BUILD_IBM */ #ifdef BUILD_NVIDIA << _(" * nvidia\n") #endif /* BUILD_NVIDIA */ #ifdef BUILD_EVE << _(" * eve-online\n") #endif /* BUILD_EVE */ #ifdef BUILD_BUILTIN_CONFIG << _(" * builtin default configuration\n") #endif /* BUILD_BUILTIN_CONFIG */ #ifdef BUILD_OLD_CONFIG << _(" * old configuration syntax\n") #endif /* BUILD_OLD_CONFIG */ #ifdef BUILD_IMLIB2 << _(" * Imlib2\n") #endif /* BUILD_IMLIB2 */ #ifdef BUILD_MIXER_ALSA << _(" * ALSA mixer support\n") #endif /* BUILD_MIXER_ALSA */ #ifdef BUILD_APCUPSD << _(" * apcupsd\n") #endif /* BUILD_APCUPSD */ #ifdef BUILD_IOSTATS << _(" * iostats\n") #endif /* BUILD_IOSTATS */ #ifdef BUILD_NCURSES << _(" * ncurses\n") #endif /* BUILD_NCURSES */ #ifdef BUILD_I18N << _(" * Internationalization support\n") #endif #ifdef DEBUG << _(" * Debugging extensions\n") #endif #if defined BUILD_LUA_CAIRO || defined BUILD_LUA_IMLIB2 || BUILD_LUA_RSVG << _("\n Lua bindings:\n") #endif #ifdef BUILD_LUA_CAIRO << _(" * Cairo\n") #endif /* BUILD_LUA_CAIRO */ #ifdef BUILD_LUA_IMLIB2 << _(" * Imlib2\n") #endif /* BUILD_LUA_IMLIB2 */ #ifdef BUILD_LUA_RSVG << _(" * RSVG\n") #endif /* BUILD_LUA_RSVG */ #ifdef BUILD_X11 << _(" X11:\n") # ifdef BUILD_XDAMAGE << _(" * Xdamage extension\n") # endif /* BUILD_XDAMAGE */ # ifdef BUILD_XSHAPE << _(" * Xshape extension (click through)\n") # endif /* BUILD_XSHAPE */ # ifdef BUILD_XDBE << _(" * XDBE (double buffer extension)\n") # endif /* BUILD_XDBE */ # ifdef BUILD_XFT << _(" * Xft\n") # endif /* BUILD_XFT */ # ifdef BUILD_ARGB << _(" * ARGB visual\n") # endif /* BUILD_ARGB */ #ifdef OWN_WINDOW << _(" * Own window\n") #endif #endif /* BUILD_X11 */ #if defined BUILD_AUDACIOUS || defined BUILD_BMPX || defined BUILD_CMUS || defined BUILD_MPD || defined BUILD_MOC || defined BUILD_XMMS2 << _("\n Music detection:\n") #endif #ifdef BUILD_AUDACIOUS << _(" * Audacious\n") #endif /* BUILD_AUDACIOUS */ #ifdef BUILD_BMPX << _(" * BMPx\n") #endif /* BUILD_BMPX */ #ifdef BUILD_CMUS << _(" * CMUS\n") #endif /* BUILD_CMUS */ #ifdef BUILD_MPD << _(" * MPD\n") #endif /* BUILD_MPD */ #ifdef BUILD_MOC << _(" * MOC\n") #endif /* BUILD_MOC */ #ifdef BUILD_XMMS2 << _(" * XMMS2\n") #endif /* BUILD_XMMS2 */ << _("\n Default values:\n") << " * Netdevice: " DEFAULTNETDEV"\n" << " * Local configfile: " CONFIG_FILE"\n" #ifdef BUILD_I18N << " * Localedir: " LOCALE_DIR"\n" #endif #ifdef BUILD_HTTP << " * HTTP-port: " << HTTPPORT << "\n" #endif << " * Maximum netdevices: " << MAX_NET_INTERFACES << "\n" << " * Maximum text size: " << MAX_USER_TEXT_DEFAULT << "\n" << " * Size text buffer: " << DEFAULT_TEXT_BUFFER_SIZE << "\n" ; } static const char *suffixes[] = { _nop("B"), _nop("KiB"), _nop("MiB"), _nop("GiB"), _nop("TiB"), _nop("PiB"), "" }; #ifdef BUILD_X11 static void X11_create_window(void); struct _x11_stuff_s { Region region; #ifdef BUILD_XDAMAGE Damage damage; XserverRegion region2, part; int event_base, error_base; #endif } x11_stuff; /* text size */ static int text_start_x, text_start_y; /* text start position in window */ static int text_width = 1, text_height = 1; /* initially 1 so no zero-sized window is created */ #endif /* BUILD_X11 */ /* struct that has all info to be shared between * instances of the same text object */ struct information info; /* path to config file */ std::string current_config; /* set to 1 if you want all text to be in uppercase */ static conky::simple_config_setting stuff_in_uppercase("uppercase", false, true); /* Run how many times? */ static conky::range_config_setting total_run_times("total_run_times", 0, std::numeric_limits::max(), 0, true); /* fork? */ static conky::simple_config_setting fork_to_background("background", false, false); /* set to 0 after the first time conky is run, so we don't fork again after the * first forking */ static int first_pass = 1; conky::range_config_setting cpu_avg_samples("cpu_avg_samples", 1, 14, 2, true); conky::range_config_setting net_avg_samples("net_avg_samples", 1, 14, 2, true); conky::range_config_setting diskio_avg_samples("diskio_avg_samples", 1, 14, 2, true); /* filenames for output */ static conky::simple_config_setting overwrite_file("overwrite_file", std::string(), true); static FILE *overwrite_fpointer = NULL; static conky::simple_config_setting append_file("append_file", std::string(), true); static FILE *append_fpointer = NULL; #ifdef BUILD_HTTP std::string webpage; struct MHD_Daemon *httpd; static conky::simple_config_setting http_refresh("http_refresh", false, true); 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; } class out_to_http_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && do_convert(l, -1).first) { httpd = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, HTTPPORT, NULL, NULL, &sendanswer, NULL, MHD_OPTION_END); } ++s; } virtual void cleanup(lua::state &l) { lua::stack_sentry s(l, -1); if(do_convert(l, -1).first) { MHD_stop_daemon(httpd); httpd = NULL; } l.pop(); } public: out_to_http_setting() : Base("out_to_http", false, false) {} }; static out_to_http_setting out_to_http; #endif #ifdef BUILD_X11 static conky::simple_config_setting show_graph_scale("show_graph_scale", false, false); static conky::simple_config_setting show_graph_range("show_graph_range", false, false); /* Position on the screen */ static conky::simple_config_setting gap_x("gap_x", 5, true); static conky::simple_config_setting gap_y("gap_y", 60, true); /* border */ static conky::simple_config_setting draw_borders("draw_borders", false, false); static conky::simple_config_setting draw_graph_borders("draw_graph_borders", true, false); conky::range_config_setting stippled_borders("stippled_borders", 0, std::numeric_limits::max(), 0, true); static conky::simple_config_setting draw_shades("draw_shades", true, false); static conky::simple_config_setting draw_outline("draw_outline", false, false); #ifdef OWN_WINDOW /* fixed size/pos is set if wm/user changes them */ static int fixed_size = 0, fixed_pos = 0; #endif static conky::range_config_setting minimum_height("minimum_height", 0, std::numeric_limits::max(), 5, true); static conky::range_config_setting minimum_width("minimum_width", 0, std::numeric_limits::max(), 5, true); static conky::range_config_setting maximum_width("maximum_width", 0, std::numeric_limits::max(), 0, true); static bool isutf8(const char* envvar) { char *s = getenv(envvar); if(s) { std::string temp = s; std::transform(temp.begin(), temp.end(), temp.begin(), ::tolower); if( (temp.find("utf-8") != std::string::npos) || (temp.find("utf8") != std::string::npos) ) { return true; } } return false; } /* UTF-8 */ static conky::simple_config_setting utf8_mode("override_utf8_locale", isutf8("LC_ALL") || isutf8("LC_CTYPE") || isutf8("LANG"), false); #endif /* BUILD_X11 */ /* maximum size of config TEXT buffer, i.e. below TEXT line. */ conky::range_config_setting max_user_text("max_user_text", 47, std::numeric_limits::max(), MAX_USER_TEXT_DEFAULT, false); /* maximum size of individual text buffers, ie $exec buffer size */ conky::range_config_setting text_buffer_size("text_buffer_size", DEFAULT_TEXT_BUFFER_SIZE, std::numeric_limits::max(), DEFAULT_TEXT_BUFFER_SIZE, false); /* pad percentages to decimals? */ static conky::simple_config_setting pad_percents("pad_percents", 0, false); static char *global_text = 0; char *get_global_text(void) { return global_text; } long global_text_lines; static int total_updates; static int updatereset; std::unique_ptr state; void set_updatereset(int i) { updatereset = i; } int get_updatereset(void) { return updatereset; } int get_total_updates(void) { return total_updates; } int calc_text_width(const char *s) { size_t slen = strlen(s); #ifdef BUILD_X11 if (not out_to_x.get(*state)) { #endif /* BUILD_X11 */ return slen; #ifdef BUILD_X11 } #ifdef BUILD_XFT if (use_xft.get(*state)) { XGlyphInfo gi; if (utf8_mode.get(*state)) { XftTextExtentsUtf8(display, fonts[selected_font].xftfont, (const FcChar8 *) s, slen, &gi); } else { XftTextExtents8(display, fonts[selected_font].xftfont, (const FcChar8 *) s, slen, &gi); } return gi.xOff; } else #endif /* BUILD_XFT */ { return XTextWidth(fonts[selected_font].font, s, slen); } #endif /* BUILD_X11 */ } /* formatted text to render on screen, generated in generate_text(), * drawn in draw_stuff() */ static char *text_buffer; /* quite boring functions */ 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'; special_index = f(ps, special_index); *pe = '\n'; ps = pe + 1; } } if (ps < pe) { f(ps, special_index); } } static void convert_escapes(char *buf) { char *p = buf, *s = buf; while (*s) { if (*s == '\\') { s++; if (*s == 'n') { *p++ = '\n'; } else if (*s == '\\') { *p++ = '\\'; } s++; } else { *p++ = *s++; } } *p = '\0'; } /* Prints anything normally printed with snprintf according to the current value * of use_spacer. Actually slightly more flexible than snprintf, as you can * safely specify the destination buffer as one of your inputs. */ int spaced_print(char *buf, int size, const char *format, int width, ...) { int len = 0; va_list argp; char *tempbuf; if (size < 1) { return 0; } tempbuf = (char*)malloc(size * sizeof(char)); // Passes the varargs along to vsnprintf va_start(argp, width); vsnprintf(tempbuf, size, format, argp); va_end(argp); switch (use_spacer.get(*state)) { case NO_SPACER: len = snprintf(buf, size, "%s", tempbuf); break; case LEFT_SPACER: len = snprintf(buf, size, "%*s", width, tempbuf); break; case RIGHT_SPACER: len = snprintf(buf, size, "%-*s", width, tempbuf); break; } free(tempbuf); return len; } /* print percentage values * * - i.e., unsigned values between 0 and 100 * - respect the value of pad_percents */ int percent_print(char *buf, int size, unsigned value) { return spaced_print(buf, size, "%u", pad_percents.get(*state), value); } #if defined(__FreeBSD__) unsigned long long llabs(long long num) { if(num < 0) return -num; else return num; } #endif /* converts from bytes to human readable format (K, M, G, T) * * The algorithm always divides by 1024, as unit-conversion of byte * counts suggests. But for output length determination we need to * compare with 1000 here, as we print in decimal form. */ void human_readable(long long num, char *buf, int size) { const char **suffix = suffixes; float fnum; int precision; int width; const char *format; /* Possibly just output as usual, for example for stdout usage */ if (not format_human_readable.get(*state)) { spaced_print(buf, size, "%lld", 6, num); return; } if (short_units.get(*state)) { width = 5; format = "%.*f%.1s"; } else { width = 7; format = "%.*f%-3s"; } if (llabs(num) < 1000LL) { spaced_print(buf, size, format, width, 0, (float)num, _(*suffix)); return; } while (llabs(num / 1024) >= 1000LL && **(suffix + 2)) { num /= 1024; suffix++; } suffix++; fnum = num / 1024.0; /* fnum should now be < 1000, so looks like 'AAA.BBBBB' * * The goal is to always have a significance of 3, by * adjusting the decimal part of the number. Sample output: * 123MiB * 23.4GiB * 5.12B * so the point of alignment resides between number and unit. The * upside of this is that there is minimal padding necessary, though * there should be a way to make alignment take place at the decimal * dot (then with fixed width decimal part). * * Note the repdigits below: when given a precision value, printf() * rounds the float to it, not just cuts off the remaining digits. So * e.g. 99.95 with a precision of 1 gets 100.0, which again should be * printed with a precision of 0. Yay. */ precision = 0; /* print 100-999 without decimal part */ if (fnum < 99.95) precision = 1; /* print 10-99 with one decimal place */ if (fnum < 9.995) precision = 2; /* print 0-9 with two decimal places */ spaced_print(buf, size, format, width, precision, fnum, _(*suffix)); } /* global object list root element */ static struct text_object global_root_object; static long current_text_color; void set_current_text_color(long colour) { current_text_color = colour; } long get_current_text_color(void) { return current_text_color; } static void extract_variable_text(const char *p) { free_text_objects(&global_root_object); free_and_zero(tmpstring1); free_and_zero(tmpstring2); free_and_zero(text_buffer); extract_variable_text_internal(&global_root_object, p); } void parse_conky_vars(struct text_object *root, const char *txt, char *p, int p_max_size) { extract_variable_text_internal(root, txt); generate_text_internal(p, p_max_size, *root); } /* IFBLOCK jumping algorithm * * This is easier as it looks like: * - each IF checks it's condition * - on FALSE: jump * - on TRUE: don't care * - each ELSE jumps unconditionally * - each ENDIF is silently being ignored * * Why this works (or: how jumping works): * Jumping means to overwrite the "obj" variable of the loop and set it to the * target (i.e. the corresponding ELSE or ENDIF). After that, the for-loop does * the rest: as regularly, "obj" is being updated to point to obj->next, so * object parsing continues right after the corresponding ELSE or ENDIF. This * means that if we find an ELSE, it's corresponding IF must not have jumped, * so we need to jump always. If we encounter an ENDIF, it's corresponding IF * or ELSE has not jumped, and there is nothing to do. */ 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; buff_in = (char *)malloc(p_max_size); memset(buff_in, 0, p_max_size); #endif /* BUILD_ICONV */ p[0] = 0; obj = root.next; while (obj && p_max_size > 0) { /* check callbacks for existence and act accordingly */ if (obj->callbacks.print) { (*obj->callbacks.print)(obj, p, p_max_size); } else if (obj->callbacks.iftest) { if (!(*obj->callbacks.iftest)(obj)) { DBGP2("jumping"); if (obj->ifblock_next) obj = obj->ifblock_next; } } else if (obj->callbacks.barval) { new_bar(obj, p, p_max_size, (*obj->callbacks.barval)(obj)); } else if (obj->callbacks.gaugeval) { new_gauge(obj, p, p_max_size, (*obj->callbacks.gaugeval)(obj)); #ifdef BUILD_X11 } else if (obj->callbacks.graphval) { new_graph(obj, p, p_max_size, (*obj->callbacks.graphval)(obj)); #endif /* BUILD_X11 */ } else if (obj->callbacks.percentage) { percent_print(p, p_max_size, (*obj->callbacks.percentage)(obj)); } a = strlen(p); #ifdef BUILD_ICONV iconv_convert(&a, buff_in, p, p_max_size); #endif /* BUILD_ICONV */ p += a; p_max_size -= a; (*p) = 0; obj = obj->next; } #ifdef BUILD_X11 /* load any new fonts we may have had */ load_fonts(utf8_mode.get(*state)); #endif /* BUILD_X11 */ #ifdef BUILD_ICONV free(buff_in); #endif /* BUILD_ICONV */ } void evaluate(const char *text, char *p, int p_max_size) { struct text_object subroot; parse_conky_vars(&subroot, text, p, p_max_size); DBGP2("evaluated '%s' to '%s'", text, p); free_text_objects(&subroot); } double current_update_time, next_update_time, last_update_time; static void generate_text(void) { char *p; unsigned int i, j, k; special_count = 0; /* update info */ current_update_time = get_time(); update_stuff(); /* add things to the buffer */ /* generate text */ p = text_buffer; generate_text_internal(p, max_user_text.get(*state), global_root_object); unsigned int mw = max_text_width.get(*state); unsigned int tbs = text_buffer_size.get(*state); if(mw > 0) { for(i = 0, j = 0; p[i] != 0; i++) { if(p[i] == '\n') j = 0; else if(j == mw) { k = i + strlen(p + i) + 1; if(k < tbs) { while(k != i) { p[k] = p[k-1]; k--; } p[k] = '\n'; j = 0; } else NORM_ERR("The end of the text_buffer is reached, increase \"text_buffer_size\""); } else j++; } } if (stuff_in_uppercase.get(*state)) { char *tmp_p; tmp_p = text_buffer; while (*tmp_p) { *tmp_p = toupper(*tmp_p); tmp_p++; } } double ui = active_update_interval(); next_update_time += ui; if (next_update_time < get_time()) { next_update_time = get_time() + ui; } else if (next_update_time > get_time() + ui) { next_update_time = get_time() + ui; } last_update_time = current_update_time; total_updates++; } int get_string_width(const char *s) { return *s ? calc_text_width(s) : 0; } #ifdef BUILD_X11 static inline int get_border_total() { return border_inner_margin.get(*state) + border_outer_margin.get(*state) + border_width.get(*state); } static int get_string_width_special(char *s, int special_index) { char *p, *final; special_t *current = specials; int idx = 1; int width = 0; long i; if (!s) return 0; if (not out_to_x.get(*state)) return strlen(s); p = strndup(s, text_buffer_size.get(*state)); final = p; for(i = 0; i < special_index; i++) current = current->next; for(i = 0; i < idx; i++) current = current->next; while (*p) { if (*p == SPECIAL_CHAR) { /* shift everything over by 1 so that the special char * doesn't mess up the size calculation */ for (i = 0; i < (long)strlen(p); i++) { *(p + i) = *(p + i + 1); } if (current->type == GRAPH || current->type == GAUGE || current->type == BAR) { width += current->width; } if (current->type == FONT) { //put all following text until the next fontchange/stringend in influenced_by_font but do not include specials char *influenced_by_font=strdup(p); special_t *current_after_font=current; for(i=0; influenced_by_font[i]!=0; i++) { if(influenced_by_font[i] == SPECIAL_CHAR) { //remove specials and stop at fontchange current_after_font=current_after_font->next; if(current_after_font->type == FONT) { influenced_by_font[i]=0; break; } else memmove(&influenced_by_font[i], &influenced_by_font[i+1], strlen(&influenced_by_font[i+1]) + 1); } } //add the length of influenced_by_font in the new font to width int orig_font = selected_font; selected_font=current->font_added; width += calc_text_width(influenced_by_font); selected_font = orig_font; free(influenced_by_font); //make sure there chars counted in the new font are not again counted in the old font int specials_skipped=0; while(i>0) { if(p[specials_skipped]!=1) memmove(&p[specials_skipped], &p[specials_skipped+1], strlen(&p[specials_skipped+1]) + 1); else specials_skipped++; i--; } } idx++; current = current->next; } else { p++; } } if (strlen(final) > 1) { width += calc_text_width(final); } free(final); return width; } static int text_size_updater(char *s, int special_index); int last_font_height; static void update_text_area(void) { int x = 0, y = 0; if (not out_to_x.get(*state)) return; /* update text size if it isn't fixed */ #ifdef OWN_WINDOW if (!fixed_size) #endif { text_width = minimum_width.get(*state); text_height = 0; last_font_height = font_height(); for_each_line(text_buffer, text_size_updater); text_width += 1; if (text_height < minimum_height.get(*state)) { text_height = minimum_height.get(*state); } int mw = maximum_width.get(*state); if (text_width > mw && mw > 0) { text_width = mw; } } alignment align = text_alignment.get(*state); /* get text position on workarea */ switch (align) { case TOP_LEFT: case TOP_RIGHT: case TOP_MIDDLE: y = gap_y.get(*state); break; case BOTTOM_LEFT: case BOTTOM_RIGHT: case BOTTOM_MIDDLE: default: y = workarea[3] - text_height - gap_y.get(*state); break; case MIDDLE_LEFT: case MIDDLE_RIGHT: case MIDDLE_MIDDLE: y = workarea[3] / 2 - text_height / 2 - gap_y.get(*state); break; } switch (align) { case TOP_LEFT: case BOTTOM_LEFT: case MIDDLE_LEFT: default: x = gap_x.get(*state); break; case TOP_RIGHT: case BOTTOM_RIGHT: case MIDDLE_RIGHT: x = workarea[2] - text_width - gap_x.get(*state); break; case TOP_MIDDLE: case BOTTOM_MIDDLE: case MIDDLE_MIDDLE: x = workarea[2] / 2 - text_width / 2 - gap_x.get(*state); break; } #ifdef OWN_WINDOW if (align == NONE) { // Let the WM manage the window x = window.x; y = window.y; fixed_pos = 1; fixed_size = 1; } #endif /* OWN_WINDOW */ #ifdef OWN_WINDOW if (own_window.get(*state) && !fixed_pos) { x += workarea[0]; y += workarea[1]; int border_total = get_border_total(); text_start_x = text_start_y = border_total; window.x = x - border_total; window.y = y - border_total; } else #endif { /* If window size doesn't match to workarea's size, * then window probably includes panels (gnome). * Blah, doesn't work on KDE. */ if (workarea[2] != window.width || workarea[3] != window.height) { y += workarea[1]; x += workarea[0]; } text_start_x = x; text_start_y = y; } /* update lua window globals */ llua_update_window_table(text_start_x, text_start_y, text_width, text_height); } /* drawing stuff */ static int cur_x, cur_y; /* current x and y for drawing */ #endif //draw_mode also without BUILD_X11 because we only need to print to stdout with FG static int draw_mode; /* FG, BG or OUTLINE */ #ifdef BUILD_X11 static long current_color; static int text_size_updater(char *s, int special_index) { int w = 0; char *p; special_t *current = specials; for(int i = 0; i < special_index; i++) current = current->next; if (not out_to_x.get(*state)) return 0; /* get string widths and skip specials */ p = s; while (*p) { if (*p == SPECIAL_CHAR) { *p = '\0'; w += get_string_width(s); *p = SPECIAL_CHAR; if (current->type == BAR || current->type == GAUGE || current->type == GRAPH) { w += current->width; if (current->height > last_font_height) { last_font_height = current->height; last_font_height += font_height(); } } else if (current->type == OFFSET) { if (current->arg > 0) { w += current->arg; } } else if (current->type == VOFFSET) { last_font_height += current->arg; } else if (current->type == GOTO) { if (current->arg > cur_x) { w = (int) current->arg; } } else if (current->type == TAB) { int start = current->arg; int step = current->width; if (!step || step < 0) { step = 10; } w += step - (cur_x - text_start_x - start) % step; } else if (current->type == FONT) { selected_font = current->font_added; if (font_height() > last_font_height) { last_font_height = font_height(); } } special_index++; current = current->next; s = p + 1; } p++; } w += get_string_width(s); if (w > text_width) { text_width = w; } int mw = maximum_width.get(*state); if (text_width > mw && mw > 0) { text_width = mw; } text_height += last_font_height; last_font_height = font_height(); return special_index; } #endif /* BUILD_X11 */ static inline void set_foreground_color(long c) { #ifdef BUILD_X11 if (out_to_x.get(*state)) { #ifdef BUILD_ARGB if (have_argb_visual) { current_color = c | (own_window_argb_value.get(*state) << 24); } else { #endif /* BUILD_ARGB */ current_color = c; #ifdef BUILD_ARGB } #endif /* BUILD_ARGB */ XSetForeground(display, window.gc, current_color); } #endif /* BUILD_X11 */ #ifdef BUILD_NCURSES if (out_to_ncurses.get(*state)) { attron(COLOR_PAIR(c)); } #endif /* BUILD_NCURSES */ UNUSED(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; int max = 0; int added; if (s[0] == '\0') { return; } width_of_s = get_string_width(s); if (out_to_stdout.get(*state) && draw_mode == FG) { printf("%s\n", s); if (extra_newline.get(*state)) fputc('\n', stdout); fflush(stdout); /* output immediately, don't buffer */ } if (out_to_stderr.get(*state) && draw_mode == FG) { fprintf(stderr, "%s\n", s); fflush(stderr); /* output immediately, don't buffer */ } if (draw_mode == FG && overwrite_fpointer) { fprintf(overwrite_fpointer, "%s\n", s); } if (draw_mode == FG && append_fpointer) { fprintf(append_fpointer, "%s\n", s); } #ifdef BUILD_NCURSES if (out_to_ncurses.get(*state) && draw_mode == FG) { printw("%s", s); } #endif #ifdef BUILD_HTTP if (out_to_http.get(*state) && draw_mode == FG) { std::string::size_type origlen = webpage.length(); webpage.append(s); webpage = string_replace_all(webpage, "\n", "
    ", origlen); webpage = string_replace_all(webpage, " ", "  ", origlen); webpage = string_replace_all(webpage, "  ", "  ", origlen); webpage.append("
    "); } #endif int tbs = text_buffer_size.get(*state); memset(tmpstring1, 0, tbs); memset(tmpstring2, 0, tbs); strncpy(tmpstring1, s, tbs - 1); pos = 0; added = 0; #ifdef BUILD_X11 if (out_to_x.get(*state)) { max = ((text_width - width_of_s) / get_string_width(" ")); } #endif /* BUILD_X11 */ /* This code looks for tabs in the text and coverts them to spaces. * The trick is getting the correct number of spaces, and not going * over the window's size without forcing the window larger. */ for (i = 0; i < tbs; i++) { if (tmpstring1[i] == '\t') { i2 = 0; for (i2 = 0; i2 < (8 - (1 + pos) % 8) && added <= max; i2++) { /* guard against overrun */ tmpstring2[MIN(pos + i2, tbs - 1)] = ' '; added++; } pos += i2; } else { /* guard against overrun */ tmpstring2[MIN(pos, tbs - 1)] = tmpstring1[i]; pos++; } } #ifdef BUILD_X11 if (out_to_x.get(*state)) { int mw = maximum_width.get(*state); if (text_width == mw) { /* this means the text is probably pushing the limit, * so we'll chop it */ while (cur_x + get_string_width(tmpstring2) - text_start_x > mw && strlen(tmpstring2) > 0) { tmpstring2[strlen(tmpstring2) - 1] = '\0'; } } } #endif /* BUILD_X11 */ s = tmpstring2; #ifdef BUILD_X11 if (out_to_x.get(*state)) { #ifdef BUILD_XFT if (use_xft.get(*state)) { XColor c; XftColor c2; c.pixel = current_color; // query color on custom colormap XQueryColor(display, window.colourmap, &c); c2.pixel = c.pixel; c2.color.red = c.red; c2.color.green = c.green; c2.color.blue = c.blue; c2.color.alpha = fonts[selected_font].font_alpha; if (utf8_mode.get(*state)) { XftDrawStringUtf8(window.xftdraw, &c2, fonts[selected_font].xftfont, cur_x, cur_y, (const XftChar8 *) s, strlen(s)); } else { XftDrawString8(window.xftdraw, &c2, fonts[selected_font].xftfont, cur_x, cur_y, (const XftChar8 *) s, strlen(s)); } } else #endif { if (utf8_mode.get(*state)) { Xutf8DrawString(display, window.drawable, fonts[selected_font].fontset, window.gc, cur_x, cur_y, s, strlen(s)); } else { XDrawString(display, window.drawable, window.gc, cur_x, cur_y, s, strlen(s)); } } cur_x += width_of_s; } #endif /* BUILD_X11 */ memcpy(tmpstring1, s, tbs); } int draw_each_line_inner(char *s, int special_index, int last_special_applied) { #ifdef BUILD_X11 int font_h = 0; int cur_y_add = 0; int mw = maximum_width.get(*state); #endif /* BUILD_X11 */ char *p = s; int orig_special_index = special_index; #ifdef BUILD_X11 if (out_to_x.get(*state)) { font_h = font_height(); cur_y += font_ascent(); } cur_x = text_start_x; #endif /* BUILD_X11 */ while (*p) { if (*p == SPECIAL_CHAR || last_special_applied > -1) { #ifdef BUILD_X11 int w = 0; #endif /* BUILD_X11 */ /* draw string before special, unless we're dealing multiline * specials */ if (last_special_applied > -1) { special_index = last_special_applied; } else { *p = '\0'; draw_string(s); *p = SPECIAL_CHAR; s = p + 1; } /* draw special */ special_t *current = specials; for(int i = 0; i < special_index; i++) current = current->next; switch (current->type) { #ifdef BUILD_X11 case HORIZONTAL_LINE: { int h = current->height; int mid = font_ascent() / 2; w = text_start_x + text_width - cur_x; XSetLineAttributes(display, window.gc, h, LineSolid, CapButt, JoinMiter); XDrawLine(display, window.drawable, window.gc, cur_x, cur_y - mid / 2, cur_x + w, cur_y - mid / 2); break; } case STIPPLED_HR: { int h = current->height; char tmp_s = current->arg; int mid = font_ascent() / 2; char ss[2] = { tmp_s, tmp_s }; w = text_start_x + text_width - cur_x - 1; XSetLineAttributes(display, window.gc, h, LineOnOffDash, CapButt, JoinMiter); XSetDashes(display, window.gc, 0, ss, 2); XDrawLine(display, window.drawable, window.gc, cur_x, cur_y - mid / 2, cur_x + w, cur_y - mid / 2); break; } case BAR: { int h, by; double bar_usage, scale; if (cur_x - text_start_x > mw && mw > 0) { break; } h = current->height; bar_usage = current->arg; scale = current->scale; by = cur_y - (font_ascent() / 2) - 1; if (h < font_h) { by -= h / 2 - 1; } w = current->width; if (w == 0) { w = text_start_x + text_width - cur_x - 1; } if (w < 0) { w = 0; } XSetLineAttributes(display, window.gc, 1, LineSolid, CapButt, JoinMiter); XDrawRectangle(display, window.drawable, window.gc, cur_x, by, w, h); XFillRectangle(display, window.drawable, window.gc, cur_x, by, w * bar_usage / scale, h); if (h > cur_y_add && h > font_h) { cur_y_add = h; } break; } case GAUGE: /* new GAUGE */ { int h, by = 0; unsigned long last_colour = current_color; #ifdef MATH float angle, px, py; double usage, scale; #endif /* MATH */ if (cur_x - text_start_x > mw && mw > 0) { break; } h = current->height; by = cur_y - (font_ascent() / 2) - 1; if (h < font_h) { by -= h / 2 - 1; } w = current->width; if (w == 0) { w = text_start_x + text_width - cur_x - 1; } if (w < 0) { w = 0; } XSetLineAttributes(display, window.gc, 1, LineSolid, CapButt, JoinMiter); XDrawArc(display, window.drawable, window.gc, cur_x, by, w, h * 2, 0, 180*64); #ifdef MATH usage = current->arg; scale = current->scale; angle = M_PI * usage / scale; px = (float)(cur_x+(w/2.))-(float)(w/2.)*cos(angle); py = (float)(by+(h))-(float)(h)*sin(angle); XDrawLine(display, window.drawable, window.gc, cur_x + (w/2.), by+(h), (int)(px), (int)(py)); #endif /* MATH */ if (h > cur_y_add && h > font_h) { cur_y_add = h; } set_foreground_color(last_colour); break; } case GRAPH: { int h, by, i = 0, j = 0; int colour_idx = 0; unsigned long last_colour = current_color; if (cur_x - text_start_x > mw && mw > 0) { break; } h = current->height; by = cur_y - (font_ascent() / 2) - 1; if (h < font_h) { by -= h / 2 - 1; } w = current->width; if (w == 0) { w = text_start_x + text_width - cur_x - 1; current->graph_width = MAX(w - 1, 0); if (current->graph_width != current->graph_allocated) { w = current->graph_allocated + 1; } } if (w < 0) { w = 0; } if (draw_graph_borders.get(*state)) { XSetLineAttributes(display, window.gc, 1, LineSolid, CapButt, JoinMiter); XDrawRectangle(display, window.drawable, window.gc, cur_x, by, w, h); } XSetLineAttributes(display, window.gc, 1, LineSolid, CapButt, JoinMiter); /* in case we don't have a graph yet */ if (current->graph) { unsigned long *tmpcolour = 0; if (current->last_colour != 0 || current->first_colour != 0) { tmpcolour = do_gradient(w - 1, current->last_colour, current->first_colour); } colour_idx = 0; for (i = w - 2; i > -1; i--) { if (current->last_colour != 0 || current->first_colour != 0) { if (current->tempgrad) { #ifdef DEBUG_lol assert( (int)((float)(w - 2) - current->graph[j] * (w - 2) / (float)current->scale) < w-1 ); assert( (int)((float)(w - 2) - current->graph[j] * (w - 2) / (float)current->scale) > -1 ); if (current->graph[j] == current->scale) { assert( (int)((float)(w - 2) - current->graph[j] * (w - 2) / (float)current->scale) == 0 ); } #endif /* DEBUG_lol */ set_foreground_color(tmpcolour[ (int)((float)(w - 2) - current->graph[j] * (w - 2) / std::max((float)current->scale, 1.0f)) ]); } else { set_foreground_color(tmpcolour[colour_idx++]); } } /* this is mugfugly, but it works */ XDrawLine(display, window.drawable, window.gc, cur_x + i + 1, by + h, cur_x + i + 1, round_to_int((double)by + h - current->graph[j] * (h - 1) / current->scale)); ++j; } free_and_zero(tmpcolour); } if (h > cur_y_add && h > font_h) { cur_y_add = h; } if (show_graph_range.get(*state)) { int tmp_x = cur_x; int tmp_y = cur_y; unsigned short int seconds = active_update_interval() * w; char *tmp_day_str; char *tmp_hour_str; char *tmp_min_str; char *tmp_sec_str; char *tmp_str; unsigned short int timeunits; if (seconds != 0) { timeunits = seconds / 86400; seconds %= 86400; if (timeunits <= 0 || asprintf(&tmp_day_str, _("%dd"), timeunits) == -1) { tmp_day_str = strdup(""); } timeunits = seconds / 3600; seconds %= 3600; if (timeunits <= 0 || asprintf(&tmp_hour_str, _("%dh"), timeunits) == -1) { tmp_hour_str = strdup(""); } timeunits = seconds / 60; seconds %= 60; if (timeunits <= 0 || asprintf(&tmp_min_str, _("%dm"), timeunits) == -1) { tmp_min_str = strdup(""); } if (seconds <= 0 || asprintf(&tmp_sec_str, _("%ds"), seconds) == -1) { tmp_sec_str = strdup(""); } if (asprintf(&tmp_str, "%s%s%s%s", tmp_day_str, tmp_hour_str, tmp_min_str, tmp_sec_str) == -1) tmp_str = strdup(""); free(tmp_day_str); free(tmp_hour_str); free(tmp_min_str); free(tmp_sec_str); } else { tmp_str = strdup(_("Range not possible")); // should never happen, but better safe then sorry } cur_x += (w / 2) - (font_ascent() * (strlen(tmp_str) / 2)); cur_y += font_h / 2; draw_string(tmp_str); free(tmp_str); cur_x = tmp_x; cur_y = tmp_y; } #ifdef MATH if (show_graph_scale.get(*state) && (current->show_scale == 1)) { int tmp_x = cur_x; int tmp_y = cur_y; char *tmp_str; cur_x += font_ascent() / 2; cur_y += font_h / 2; tmp_str = (char *) calloc(log10(floor(current->scale)) + 4, sizeof(char)); sprintf(tmp_str, "%.1f", current->scale); draw_string(tmp_str); free(tmp_str); cur_x = tmp_x; cur_y = tmp_y; } #endif set_foreground_color(last_colour); break; } case FONT: { int old = font_ascent(); cur_y -= font_ascent(); selected_font = current->font_added; set_font(); if (cur_y + font_ascent() < cur_y + old) { cur_y += old; } else { cur_y += font_ascent(); } font_h = font_height(); break; } #endif /* BUILD_X11 */ case FG: if (draw_mode == FG) { set_foreground_color(current->arg); } break; #ifdef BUILD_X11 case BG: if (draw_mode == BG) { set_foreground_color(current->arg); } break; case OUTLINE: if (draw_mode == OUTLINE) { set_foreground_color(current->arg); } break; case OFFSET: w += current->arg; break; case VOFFSET: cur_y += current->arg; break; case GOTO: if (current->arg >= 0) { cur_x = (int) current->arg; #ifdef BUILD_X11 //make sure shades are 1 pixel to the right of the text if(draw_mode == BG) cur_x++; #endif } break; case TAB: { int start = current->arg; int step = current->width; if (!step || step < 0) { step = 10; } w = step - (cur_x - text_start_x - start) % step; break; } case ALIGNR: { /* TODO: add back in "+ window.border_inner_margin" to the end of * this line? */ int pos_x = text_start_x + text_width - get_string_width_special(s, special_index); /* printf("pos_x %i text_start_x %i text_width %i cur_x %i " "get_string_width(p) %i gap_x %i " "current->arg %i window.border_inner_margin %i " "window.border_width %i\n", pos_x, text_start_x, text_width, cur_x, get_string_width_special(s), gap_x, current->arg, window.border_inner_margin, window.border_width); */ if (pos_x > current->arg && pos_x > cur_x) { cur_x = pos_x - current->arg; } break; } case ALIGNC: { int pos_x = (text_width) / 2 - get_string_width_special(s, special_index) / 2 - (cur_x - text_start_x); /* int pos_x = text_start_x + text_width / 2 - get_string_width_special(s) / 2; */ /* printf("pos_x %i text_start_x %i text_width %i cur_x %i " "get_string_width(p) %i gap_x %i " "current->arg %i\n", pos_x, text_start_x, text_width, cur_x, get_string_width(s), gap_x, current->arg); */ if (pos_x > current->arg) { w = pos_x - current->arg; } break; } #endif /* BUILD_X11 */ } #ifdef BUILD_X11 cur_x += w; #endif /* BUILD_X11 */ if (special_index != last_special_applied) { special_index++; } else { special_index = orig_special_index; last_special_applied = -1; } } p++; } #ifdef BUILD_X11 cur_y += cur_y_add; #endif /* BUILD_X11 */ draw_string(s); #ifdef BUILD_NCURSES if (out_to_ncurses.get(*state)) { printw("\n"); } #endif /* BUILD_NCURSES */ #ifdef BUILD_X11 if (out_to_x.get(*state)) cur_y += font_descent(); #endif /* BUILD_X11 */ return special_index; } static int draw_line(char *s, int special_index) { #ifdef BUILD_X11 if (out_to_x.get(*state)) { return draw_each_line_inner(s, special_index, -1); } #endif /* BUILD_X11 */ #ifdef BUILD_NCURSES if (out_to_ncurses.get(*state)) { return draw_each_line_inner(s, special_index, -1); } #endif /* BUILD_NCURSES */ draw_string(s); UNUSED(special_index); return 0; } static void draw_text(void) { #ifdef BUILD_HTTP #define WEBPAGE_START1 "\n" #define WEBPAGE_START2 "Conky

    " #define WEBPAGE_END "

    " if (out_to_http.get(*state)) { webpage = WEBPAGE_START1; if(http_refresh.get(*state)) { webpage.append(""); } webpage.append(WEBPAGE_START2); } #endif #ifdef BUILD_X11 if (out_to_x.get(*state)) { cur_y = text_start_y; int bw = border_width.get(*state); /* draw borders */ if (draw_borders.get(*state) && bw > 0) { if (stippled_borders.get(*state)) { char ss[2] = { stippled_borders.get(*state), stippled_borders.get(*state) }; XSetLineAttributes(display, window.gc, bw, LineOnOffDash, CapButt, JoinMiter); XSetDashes(display, window.gc, 0, ss, 2); } else { XSetLineAttributes(display, window.gc, bw, LineSolid, CapButt, JoinMiter); } int offset = border_inner_margin.get(*state) + bw; XDrawRectangle(display, window.drawable, window.gc, text_start_x - offset, text_start_y - offset, text_width + 2*offset, text_height + 2*offset); } /* draw text */ } setup_fonts(); #endif /* BUILD_X11 */ #ifdef BUILD_NCURSES init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); attron(COLOR_PAIR(COLOR_WHITE)); #endif /* BUILD_NCURSES */ for_each_line(text_buffer, draw_line); #ifdef BUILD_HTTP if (out_to_http.get(*state)) { webpage.append(WEBPAGE_END); } #endif } static void draw_stuff(void) { #ifdef BUILD_IMLIB2 cimlib_render(text_start_x, text_start_y, window.width, window.height); #endif /* BUILD_IMLIB2 */ if (overwrite_file.get(*state).size()) { overwrite_fpointer = fopen(overwrite_file.get(*state).c_str(), "w"); if(!overwrite_fpointer) NORM_ERR("Cannot overwrite '%s'", overwrite_file.get(*state).c_str()); } if (append_file.get(*state).size()) { append_fpointer = fopen(append_file.get(*state).c_str(), "a"); if(!append_fpointer) NORM_ERR("Cannot append to '%s'", append_file.get(*state).c_str()); } #ifdef BUILD_X11 llua_draw_pre_hook(); if (out_to_x.get(*state)) { selected_font = 0; if (draw_shades.get(*state) && !draw_outline.get(*state)) { text_start_x++; text_start_y++; set_foreground_color(default_shade_color.get(*state)); draw_mode = BG; draw_text(); text_start_x--; text_start_y--; } if (draw_outline.get(*state)) { int i, j; selected_font = 0; for (i = -1; i < 2; i++) { for (j = -1; j < 2; j++) { if (i == 0 && j == 0) { continue; } text_start_x += i; text_start_y += j; set_foreground_color(default_outline_color.get(*state)); draw_mode = OUTLINE; draw_text(); text_start_x -= i; text_start_y -= j; } } } set_foreground_color(default_color.get(*state)); } #endif /* BUILD_X11 */ draw_mode = FG; draw_text(); #if defined(BUILD_X11) llua_draw_post_hook(); #if defined(BUILD_XDBE) if (out_to_x.get(*state)) { xdbe_swap_buffers(); } #else if (out_to_x.get(*state)) { xpmdb_swap_buffers(); } #endif #endif /* BUILD_X11 && BUILD_XDBE */ if(overwrite_fpointer) { fclose(overwrite_fpointer); overwrite_fpointer = 0; } if (append_fpointer) { fclose(append_fpointer); append_fpointer = 0; } } #ifdef BUILD_X11 static void clear_text(int exposures) { #ifdef BUILD_XDBE if (use_xdbe.get(*state)) { /* The swap action is XdbeBackground, which clears */ return; } else #else if (use_xpmdb.get(*state)) { return; } else #endif if (display && window.window) { // make sure these are !null /* there is some extra space for borders and outlines */ int border_total = get_border_total(); XClearArea(display, window.window, text_start_x - border_total, text_start_y - border_total, text_width + 2*border_total, text_height + 2*border_total, exposures ? True : 0); } } #endif /* BUILD_X11 */ static int need_to_update; /* update_text() generates new text and clears old text area */ static void update_text(void) { #ifdef BUILD_IMLIB2 cimlib_cleanup(); #endif /* BUILD_IMLIB2 */ generate_text(); #ifdef BUILD_X11 if (out_to_x.get(*state)) clear_text(1); #endif /* BUILD_X11 */ need_to_update = 1; llua_update_info(&info, active_update_interval()); } #ifdef HAVE_SYS_INOTIFY_H int inotify_fd = -1; #endif static void main_loop(void) { int terminate = 0; #ifdef SIGNAL_BLOCKING sigset_t newmask, oldmask; #endif double t; #ifdef HAVE_SYS_INOTIFY_H int inotify_config_wd = -1; #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) #define INOTIFY_BUF_LEN (20 * (INOTIFY_EVENT_SIZE + 16)) + 1 char inotify_buff[INOTIFY_BUF_LEN]; #endif /* HAVE_SYS_INOTIFY_H */ #ifdef SIGNAL_BLOCKING sigemptyset(&newmask); sigaddset(&newmask, SIGINT); sigaddset(&newmask, SIGTERM); sigaddset(&newmask, SIGUSR1); #endif last_update_time = 0.0; next_update_time = get_time(); info.looped = 0; while (terminate == 0 && (total_run_times.get(*state) == 0 || info.looped < total_run_times.get(*state))) { if(update_interval_on_battery.get(*state) != NOBATTERY) { char buf[64]; get_battery_short_status(buf, 64, "BAT0"); on_battery = (buf[0] == 'D'); } info.looped++; #ifdef SIGNAL_BLOCKING /* block signals. we will inspect for pending signals later */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { CRIT_ERR(NULL, NULL, "unable to sigprocmask()"); } #endif #ifdef BUILD_X11 if (out_to_x.get(*state)) { XFlush(display); /* wait for X event or timeout */ if (!XPending(display)) { fd_set fdsr; struct timeval tv; int s; t = next_update_time - get_time(); t = std::min(std::max(t, 0.0), active_update_interval()); tv.tv_sec = (long) t; tv.tv_usec = (long) (t * 1000000) % 1000000; FD_ZERO(&fdsr); FD_SET(ConnectionNumber(display), &fdsr); s = select(ConnectionNumber(display) + 1, &fdsr, 0, 0, &tv); if (s == -1) { if (errno != EINTR) { NORM_ERR("can't select(): %s", strerror(errno)); } } else { /* timeout */ if (s == 0) { update_text(); } } } if (need_to_update) { #ifdef OWN_WINDOW int wx = window.x, wy = window.y; #endif need_to_update = 0; selected_font = 0; update_text_area(); #ifdef OWN_WINDOW if (own_window.get(*state)) { int changed = 0; int border_total = get_border_total(); /* resize window if it isn't right size */ if (!fixed_size && (text_width + 2*border_total != window.width || text_height + 2*border_total != window.height)) { window.width = text_width + 2*border_total; window.height = text_height + 2*border_total; draw_stuff(); /* redraw everything in our newly sized window */ XResizeWindow(display, window.window, window.width, window.height); /* resize window */ set_transparent_background(window.window); #ifdef BUILD_XDBE /* swap buffers */ xdbe_swap_buffers(); #else if (use_xpmdb.get(*state)) { XFreePixmap(display, window.back_buffer); window.back_buffer = XCreatePixmap(display, window.window, window.width, window.height, DefaultDepth(display, screen)); if (window.back_buffer != None) { window.drawable = window.back_buffer; } else { // this is probably reallllly bad NORM_ERR("Failed to allocate back buffer"); } XSetForeground(display, window.gc, 0); XFillRectangle(display, window.drawable, window.gc, 0, 0, window.width, window.height); } #endif changed++; /* update lua window globals */ llua_update_window_table(text_start_x, text_start_y, text_width, text_height); } /* move window if it isn't in right position */ if (!fixed_pos && (window.x != wx || window.y != wy)) { XMoveWindow(display, window.window, window.x, window.y); changed++; } /* update struts */ if (changed && own_window_type.get(*state) == TYPE_PANEL) { int sidenum = -1; fprintf(stderr, _(PACKAGE_NAME": defining struts\n")); fflush(stderr); switch (text_alignment.get(*state)) { case TOP_LEFT: case TOP_RIGHT: case TOP_MIDDLE: { sidenum = 2; break; } case BOTTOM_LEFT: case BOTTOM_RIGHT: case BOTTOM_MIDDLE: { sidenum = 3; break; } case MIDDLE_LEFT: { sidenum = 0; break; } case MIDDLE_RIGHT: { sidenum = 1; break; } case NONE: case MIDDLE_MIDDLE: /* XXX What about these? */; } set_struts(sidenum); } } #endif clear_text(1); #if defined(BUILD_XDBE) if (use_xdbe.get(*state)) { #else if (use_xpmdb.get(*state)) { #endif XRectangle r; int border_total = get_border_total(); r.x = text_start_x - border_total; r.y = text_start_y - border_total; r.width = text_width + 2*border_total; r.height = text_height + 2*border_total; XUnionRectWithRegion(&r, x11_stuff.region, x11_stuff.region); } } /* handle X events */ while (XPending(display)) { XEvent ev; XNextEvent(display, &ev); switch (ev.type) { case Expose: { XRectangle r; r.x = ev.xexpose.x; r.y = ev.xexpose.y; r.width = ev.xexpose.width; r.height = ev.xexpose.height; XUnionRectWithRegion(&r, x11_stuff.region, x11_stuff.region); break; } case PropertyNotify: { if ( ev.xproperty.state == PropertyNewValue ) { get_x11_desktop_info( ev.xproperty.display, ev.xproperty.atom ); } break; } #ifdef OWN_WINDOW case ReparentNotify: /* make background transparent */ if (own_window.get(*state)) { set_transparent_background(window.window); } break; case ConfigureNotify: if (own_window.get(*state)) { /* if window size isn't what expected, set fixed size */ if (ev.xconfigure.width != window.width || ev.xconfigure.height != window.height) { if (window.width != 0 && window.height != 0) { fixed_size = 1; } /* clear old stuff before screwing up * size and pos */ clear_text(1); { XWindowAttributes attrs; if (XGetWindowAttributes(display, window.window, &attrs)) { window.width = attrs.width; window.height = attrs.height; } } int border_total = get_border_total(); text_width = window.width - 2*border_total; text_height = window.height - 2*border_total; int mw = maximum_width.get(*state); if (text_width > mw && mw > 0) { text_width = mw; } } /* if position isn't what expected, set fixed pos * total_updates avoids setting fixed_pos when window * is set to weird locations when started */ /* // this is broken if (total_updates >= 2 && !fixed_pos && (window.x != ev.xconfigure.x || window.y != ev.xconfigure.y) && (ev.xconfigure.x != 0 || ev.xconfigure.y != 0)) { fixed_pos = 1; } */ } break; case ButtonPress: if (own_window.get(*state)) { /* if an ordinary window with decorations */ if ((own_window_type.get(*state) == TYPE_NORMAL && not TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) || own_window_type.get(*state) == TYPE_DESKTOP) { /* allow conky to hold input focus. */ break; } else { /* forward the click to the desktop window */ XUngrabPointer(display, ev.xbutton.time); ev.xbutton.window = window.desktop; ev.xbutton.x = ev.xbutton.x_root; ev.xbutton.y = ev.xbutton.y_root; XSendEvent(display, ev.xbutton.window, False, ButtonPressMask, &ev); XSetInputFocus(display, ev.xbutton.window, RevertToParent, ev.xbutton.time); } } break; case ButtonRelease: if (own_window.get(*state)) { /* if an ordinary window with decorations */ if ((own_window_type.get(*state) == TYPE_NORMAL) && not TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) { /* allow conky to hold input focus. */ break; } else { /* forward the release to the desktop window */ ev.xbutton.window = window.desktop; ev.xbutton.x = ev.xbutton.x_root; ev.xbutton.y = ev.xbutton.y_root; XSendEvent(display, ev.xbutton.window, False, ButtonReleaseMask, &ev); } } break; #endif default: #ifdef BUILD_XDAMAGE if (ev.type == x11_stuff.event_base + XDamageNotify) { XDamageNotifyEvent *dev = (XDamageNotifyEvent *) &ev; XFixesSetRegion(display, x11_stuff.part, &dev->area, 1); XFixesUnionRegion(display, x11_stuff.region2, x11_stuff.region2, x11_stuff.part); } #endif /* BUILD_XDAMAGE */ break; } } #ifdef BUILD_XDAMAGE XDamageSubtract(display, x11_stuff.damage, x11_stuff.region2, None); XFixesSetRegion(display, x11_stuff.region2, 0, 0); #endif /* BUILD_XDAMAGE */ /* XDBE doesn't seem to provide a way to clear the back buffer * without interfering with the front buffer, other than passing * XdbeBackground to XdbeSwapBuffers. That means that if we're * using XDBE, we need to redraw the text even if it wasn't part of * the exposed area. OTOH, if we're not going to call draw_stuff at * all, then no swap happens and we can safely do nothing. */ if (!XEmptyRegion(x11_stuff.region)) { #if defined(BUILD_XDBE) if (use_xdbe.get(*state)) { #else if (use_xpmdb.get(*state)) { #endif XRectangle r; int border_total = get_border_total(); r.x = text_start_x - border_total; r.y = text_start_y - border_total; r.width = text_width + 2*border_total; r.height = text_height + 2*border_total; XUnionRectWithRegion(&r, x11_stuff.region, x11_stuff.region); } XSetRegion(display, window.gc, x11_stuff.region); #ifdef BUILD_XFT if (use_xft.get(*state)) { XftDrawSetClip(window.xftdraw, x11_stuff.region); } #endif draw_stuff(); XDestroyRegion(x11_stuff.region); x11_stuff.region = XCreateRegion(); } } else { #endif /* BUILD_X11 */ t = (next_update_time - get_time()) * 1000000; if(t > 0) usleep((useconds_t)t); update_text(); draw_stuff(); #ifdef BUILD_NCURSES if(out_to_ncurses.get(*state)) { refresh(); clear(); } #endif #ifdef BUILD_X11 } #endif /* BUILD_X11 */ #ifdef SIGNAL_BLOCKING /* unblock signals of interest and let handler fly */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { CRIT_ERR(NULL, NULL, "unable to sigprocmask()"); } #endif switch (g_signal_pending) { case SIGHUP: case SIGUSR1: NORM_ERR("received SIGHUP or SIGUSR1. reloading the config file."); reload_config(); break; case SIGINT: case SIGTERM: NORM_ERR("received SIGINT or SIGTERM to terminate. bye!"); terminate = 1; #ifdef BUILD_X11 if (out_to_x.get(*state)) { XDestroyRegion(x11_stuff.region); x11_stuff.region = NULL; #ifdef BUILD_XDAMAGE XDamageDestroy(display, x11_stuff.damage); XFixesDestroyRegion(display, x11_stuff.region2); XFixesDestroyRegion(display, x11_stuff.part); #endif /* BUILD_XDAMAGE */ } #endif /* BUILD_X11 */ break; default: /* Reaching here means someone set a signal * (SIGXXXX, signal_handler), but didn't write any code * to deal with it. * If you don't want to handle a signal, don't set a handler on * it in the first place. */ if (g_signal_pending) { NORM_ERR("ignoring signal (%d)", g_signal_pending); } break; } #ifdef HAVE_SYS_INOTIFY_H if (!disable_auto_reload.get(*state) && inotify_fd != -1 && inotify_config_wd == -1 && !current_config.empty()) { inotify_config_wd = inotify_add_watch(inotify_fd, current_config.c_str(), IN_MODIFY); } if (!disable_auto_reload.get(*state) && inotify_fd != -1 && inotify_config_wd != -1 && !current_config.empty()) { int len = 0, idx = 0; fd_set descriptors; struct timeval time_to_wait; FD_ZERO(&descriptors); FD_SET(inotify_fd, &descriptors); time_to_wait.tv_sec = time_to_wait.tv_usec = 0; select(inotify_fd + 1, &descriptors, NULL, NULL, &time_to_wait); if (FD_ISSET(inotify_fd, &descriptors)) { /* process inotify events */ len = read(inotify_fd, inotify_buff, INOTIFY_BUF_LEN - 1); inotify_buff[len] = 0; while (len > 0 && idx < len) { struct inotify_event *ev = (struct inotify_event *) &inotify_buff[idx]; if (ev->wd == inotify_config_wd && (ev->mask & IN_MODIFY || ev->mask & IN_IGNORED)) { /* current_config should be reloaded */ NORM_ERR("'%s' modified, reloading...", current_config.c_str()); reload_config(); if (ev->mask & IN_IGNORED) { /* for some reason we get IN_IGNORED here * sometimes, so we need to re-add the watch */ inotify_config_wd = inotify_add_watch(inotify_fd, current_config.c_str(), IN_MODIFY); } break; } else { llua_inotify_query(ev->wd, ev->mask); } idx += INOTIFY_EVENT_SIZE + ev->len; } } } else if (disable_auto_reload.get(*state) && inotify_fd != -1) { inotify_rm_watch(inotify_fd, inotify_config_wd); close(inotify_fd); inotify_fd = inotify_config_wd = -1; } #endif /* HAVE_SYS_INOTIFY_H */ llua_update_info(&info, active_update_interval()); g_signal_pending = 0; } clean_up(NULL, NULL); #ifdef HAVE_SYS_INOTIFY_H if (inotify_fd != -1) { inotify_rm_watch(inotify_fd, inotify_config_wd); close(inotify_fd); inotify_fd = inotify_config_wd = -1; } #endif /* HAVE_SYS_INOTIFY_H */ } void initialisation(int argc, char** argv); /* reload the config file */ static void reload_config(void) { struct stat sb; if (stat(current_config.c_str(), &sb) || (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) { NORM_ERR(_("Config file '%s' is gone, continuing with config from memory.\nIf you recreate this file sent me a SIGUSR1 to tell me about it. ( kill -s USR1 %d )"), current_config.c_str(), getpid()); return; } clean_up(NULL, NULL); state.reset(new lua::state); conky::export_symbols(*state); sleep(1); /* slight pause */ initialisation(argc_copy, argv_copy); } #ifdef BUILD_X11 void clean_up_x11(void) { if(window_created == 1) { int border_total = get_border_total(); XClearArea(display, window.window, text_start_x - border_total, text_start_y - border_total, text_width + 2*border_total, text_height + 2*border_total, 0); } destroy_window(); free_fonts(utf8_mode.get(*state)); if(x11_stuff.region) { XDestroyRegion(x11_stuff.region); x11_stuff.region = NULL; } } #endif void free_specials(special_t *¤t) { if (current) { free_specials(current->next); if(current->type == GRAPH) free(current->graph); delete current; current = NULL; } } void clean_up_without_threads(void *memtofree1, void* memtofree2) { free_and_zero(memtofree1); free_and_zero(memtofree2); free_and_zero(info.cpu_usage); #ifdef BUILD_X11 if(out_to_x.get(*state)) clean_up_x11(); else fonts.clear(); //in set_default_configurations a font is set but not loaded #endif /* BUILD_X11 */ if (info.first_process) { free_all_processes(); info.first_process = NULL; } free_text_objects(&global_root_object); free_and_zero(tmpstring1); free_and_zero(tmpstring2); free_and_zero(text_buffer); free_and_zero(global_text); #ifdef BUILD_PORT_MONITORS tcp_portmon_clear(); #endif llua_shutdown_hook(); #if defined BUILD_WEATHER_XOAP || defined BUILD_RSS xmlCleanupParser(); #endif free_specials(specials); clear_net_stats(); clear_diskio_stats(); free_and_zero(global_cpu); conky::cleanup_config_settings(*state); state.reset(); } void clean_up(void *memtofree1, void* memtofree2) { /* free_update_callbacks(); XXX: some new equivalent of this? */ clean_up_without_threads(memtofree1, memtofree2); } static void set_default_configurations(void) { update_uname(); info.memmax = 0; top_cpu = 0; top_mem = 0; top_time = 0; #ifdef BUILD_IOSTATS top_io = 0; #endif top_running = 0; #ifdef BUILD_XMMS2 info.xmms2.artist = NULL; info.xmms2.album = NULL; info.xmms2.title = NULL; info.xmms2.genre = NULL; info.xmms2.comment = NULL; info.xmms2.url = NULL; info.xmms2.status = NULL; info.xmms2.playlist = NULL; #endif /* BUILD_XMMS2 */ state->pushboolean(true); #ifdef BUILD_X11 out_to_x.lua_set(*state); #else out_to_stdout.lua_set(*state); #endif info.users.number = 1; } #ifdef BUILD_X11 static void X11_create_window(void) { if (out_to_x.get(*state)) { setup_fonts(); load_fonts(utf8_mode.get(*state)); update_text_area(); /* to position text/window on screen */ #ifdef OWN_WINDOW if (own_window.get(*state)) { if (not fixed_pos) XMoveWindow(display, window.window, window.x, window.y); set_transparent_background(window.window); } #endif create_gc(); draw_stuff(); x11_stuff.region = XCreateRegion(); #ifdef BUILD_XDAMAGE if (!XDamageQueryExtension(display, &x11_stuff.event_base, &x11_stuff.error_base)) { NORM_ERR("Xdamage extension unavailable"); } x11_stuff.damage = XDamageCreate(display, window.window, XDamageReportNonEmpty); x11_stuff.region2 = XFixesCreateRegionFromWindow(display, window.window, 0); x11_stuff.part = XFixesCreateRegionFromWindow(display, window.window, 0); #endif /* BUILD_XDAMAGE */ selected_font = 0; update_text_area(); /* to get initial size of the window */ } /* setup lua window globals */ llua_setup_window_table(text_start_x, text_start_y, text_width, text_height); } #endif /* BUILD_X11 */ void load_config_file() { DBGP(_("reading contents from config file '%s'"), current_config.c_str()); lua::state &l = *state; lua::stack_sentry s(l); l.checkstack(2); try { #ifdef BUILD_BUILTIN_CONFIG if(current_config == builtin_config_magic) l.loadstring(defconfig); else #endif l.loadfile(current_config.c_str()); } catch(lua::syntax_error &e) { #define SYNTAX_ERR_READ_CONF "Syntax error (%s) while reading config file. " #ifdef BUILD_OLD_CONFIG NORM_ERR(_(SYNTAX_ERR_READ_CONF), e.what()); NORM_ERR(_("Assuming it's in old syntax and attempting conversion.")); // the strchr thingy skips the first line (#! /usr/bin/lua) l.loadstring(strchr(convertconf, '\n')); l.pushstring(current_config.c_str()); l.call(1, 1); #else char *syntaxerr; asprintf(&syntaxerr, _(SYNTAX_ERR_READ_CONF), e.what()); std::string syntaxerrobj(syntaxerr); free(syntaxerr); throw conky::error(syntaxerrobj); #endif } l.call(0, 0); l.getglobal("conky"); l.getfield(-1, "text"); l.replace(-2); if(l.type(-1) != lua::TSTRING) throw conky::error(_("missing text block in configuration")); /* Remove \\-\n. */ l.gsub(l.tocstring(-1), "\\\n", ""); l.replace(-2); global_text = strdup(l.tocstring(-1)); l.pop(); // XXX: what does this do? // global_text_lines = line + 1; #if 0 #if defined(BUILD_NCURSES) #if defined(BUILD_X11) if (out_to_x.get(*state) && out_to_ncurses.get(*state)) { NORM_ERR("out_to_x and out_to_ncurses are incompatible, turning out_to_ncurses off"); state->pushboolean(false); out_to_ncurses.lua_set(*state); } #endif /* BUILD_X11 */ if ((out_to_stdout.get(*state) || out_to_stderr.get(*state)) && out_to_ncurses.get(*state)) { NORM_ERR("out_to_ncurses conflicts with out_to_console and out_to_stderr, disabling the later ones"); // XXX: this will need some rethinking state->pushboolean(false); out_to_stdout.lua_set(*state); state->pushboolean(false); out_to_stderr.lua_set(*state); } #endif /* BUILD_NCURSES */ #endif } static void print_help(const char *prog_name) { printf("Usage: %s [OPTION]...\n" PACKAGE_NAME " is a system monitor that renders text on desktop or to own transparent\n" "window. Command line options will override configurations defined in config\n" "file.\n" " -v, --version version\n" " -q, --quiet quiet mode\n" " -D, --debug increase debugging output, ie. -DD for more debugging\n" " -c, --config=FILE config file to load\n" #ifdef BUILD_BUILTIN_CONFIG " -C, --print-config print the builtin default config to stdout\n" " e.g. 'conky -C > ~/.conkyrc' will create a new default config\n" #endif " -d, --daemonize daemonize, fork to background\n" " -h, --help help\n" #ifdef BUILD_X11 " -a, --alignment=ALIGNMENT text alignment on screen, {top,bottom,middle}_{left,right,middle}\n" " -f, --font=FONT font to use\n" " -X, --display=DISPLAY X11 display to use\n" #ifdef OWN_WINDOW " -o, --own-window create own window to draw\n" #endif " -b, --double-buffer double buffer (prevents flickering)\n" " -w, --window-id=WIN_ID window id to draw\n" " -x X x position\n" " -y Y y position\n" #endif /* BUILD_X11 */ " -t, --text=TEXT text to render, remember single quotes, like -t '$uptime'\n" " -u, --interval=SECS update interval\n" " -i COUNT number of times to update " PACKAGE_NAME " (and quit)\n" " -p, --pause=SECS pause for SECS seconds at startup before doing anything\n", prog_name ); } inline void reset_optind() { #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) \ || defined(__NetBSD__) || defined(__DragonFly__) optind = optreset = 1; #else optind = 0; #endif } /* : means that character before that takes an argument */ static const char *getopt_string = "vVqdDSs:t:u:i:hc:p:" #ifdef BUILD_X11 "x:y:w:a:f:X:" #ifdef OWN_WINDOW "o" #endif "b" #endif /* BUILD_X11 */ #ifdef BUILD_BUILTIN_CONFIG "C" #endif ; static const struct option longopts[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "quiet", 0, NULL, 'q' }, { "debug", 0, NULL, 'D' }, { "config", 1, NULL, 'c' }, #ifdef BUILD_BUILTIN_CONFIG { "print-config", 0, NULL, 'C' }, #endif { "daemonize", 0, NULL, 'd' }, #ifdef BUILD_X11 { "alignment", 1, NULL, 'a' }, { "font", 1, NULL, 'f' }, { "display", 1, NULL, 'X' }, #ifdef OWN_WINDOW { "own-window", 0, NULL, 'o' }, #endif { "double-buffer", 0, NULL, 'b' }, { "window-id", 1, NULL, 'w' }, #endif /* BUILD_X11 */ { "text", 1, NULL, 't' }, { "interval", 1, NULL, 'u' }, { "pause", 1, NULL, 'p' }, { 0, 0, 0, 0 } }; void set_current_config() { /* load current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */ struct stat s; if (current_config.empty()) { /* Try to use personal config file first */ std::string buf = to_real_path(XDG_CONFIG_FILE); if (stat(buf.c_str(), &s) == 0) current_config = buf; } if (current_config.empty()) { /* Try to use personal config file first */ std::string buf = to_real_path(CONFIG_FILE); if (stat(buf.c_str(), &s) == 0) current_config = buf; } /* Try to use system config file if personal config does not exist */ if (current_config.empty() && (stat(SYSTEM_CONFIG_FILE, &s)==0)) current_config = SYSTEM_CONFIG_FILE; /* No readable config found */ if (current_config.empty()) { #define NOCFGFILEFOUND "no personal or system-wide config file found" #ifdef BUILD_BUILTIN_CONFIG current_config = builtin_config_magic; NORM_ERR(NOCFGFILEFOUND ", using builtin default"); #else throw conky::error(NOCFGFILEFOUND); #endif } // "-" stands for "read from stdin" if(current_config == "-") current_config = "/dev/stdin"; } void initialisation(int argc, char **argv) { struct sigaction act, oact; set_default_configurations(); set_current_config(); load_config_file(); /* handle other command line arguments */ reset_optind(); #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open")) == NULL) { CRIT_ERR(NULL, NULL, "cannot read kvm"); } #endif while (1) { int c = getopt_long(argc, argv, getopt_string, longopts, NULL); int startup_pause; char *conv_end; if (c == -1) { break; } switch (c) { case 'd': state->pushboolean(true); fork_to_background.lua_set(*state); break; #ifdef BUILD_X11 case 'f': state->pushstring(optarg); font.lua_set(*state); break; case 'a': state->pushstring(optarg); text_alignment.lua_set(*state); break; case 'X': state->pushstring(optarg); display_name.lua_set(*state); break; #ifdef OWN_WINDOW case 'o': state->pushboolean(true); own_window.lua_set(*state); break; #endif #ifdef BUILD_XDBE case 'b': state->pushboolean(true); use_xdbe.lua_set(*state); break; #else case 'b': state->pushboolean(true); use_xpmdb.lua_set(*state); break; #endif #endif /* BUILD_X11 */ case 't': free_and_zero(global_text); global_text = strndup(optarg, max_user_text.get(*state)); convert_escapes(global_text); break; case 'u': state->pushinteger(strtol(optarg, &conv_end, 10)); if(*conv_end != 0) { CRIT_ERR(NULL, NULL, "'%s' is a wrong update-interval", optarg); } update_interval.lua_set(*state); break; case 'i': state->pushinteger(strtol(optarg, &conv_end, 10)); if(*conv_end != 0) { CRIT_ERR(NULL, NULL, "'%s' is a wrong number of update-times", optarg); } total_run_times.lua_set(*state); break; #ifdef BUILD_X11 case 'x': state->pushinteger(strtol(optarg, &conv_end, 10)); if(*conv_end != 0) { CRIT_ERR(NULL, NULL, "'%s' is a wrong value for the X-position", optarg); } gap_x.lua_set(*state); break; case 'y': state->pushinteger(strtol(optarg, &conv_end, 10)); if(*conv_end != 0) { CRIT_ERR(NULL, NULL, "'%s' is a wrong value for the Y-position", optarg); } gap_y.lua_set(*state); break; #endif /* BUILD_X11 */ case 'p': if (first_pass) { startup_pause = atoi(optarg); sleep(startup_pause); } break; case '?': throw unknown_arg_throw(); } } conky::set_config_settings(*state); #ifdef BUILD_X11 if(out_to_x.get(*state)) { current_text_color = default_color.get(*state); } #endif /* generate text and get initial size */ extract_variable_text(global_text); free_and_zero(global_text); /* fork */ if (fork_to_background.get(*state) && first_pass) { int pid = fork(); switch (pid) { case -1: NORM_ERR(PACKAGE_NAME": couldn't fork() to background: %s", strerror(errno)); break; case 0: /* child process */ usleep(25000); fprintf(stderr, "\n"); fflush(stderr); break; default: /* parent process */ fprintf(stderr, PACKAGE_NAME": forked to background, pid is %d\n", pid); fflush(stderr); throw fork_throw(); } } text_buffer = (char*)malloc(max_user_text.get(*state)); memset(text_buffer, 0, max_user_text.get(*state)); tmpstring1 = (char*)malloc(text_buffer_size.get(*state)); memset(tmpstring1, 0, text_buffer_size.get(*state)); tmpstring2 = (char*)malloc(text_buffer_size.get(*state)); memset(tmpstring2, 0, text_buffer_size.get(*state)); #ifdef BUILD_X11 X11_create_window(); #endif /* BUILD_X11 */ llua_setup_info(&info, active_update_interval()); #ifdef BUILD_WEATHER_XOAP xmlInitParser(); #endif /* BUILD_WEATHER_XOAP */ /* Set signal handlers */ act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif if ( sigaction(SIGINT, &act, &oact) < 0 || sigaction(SIGALRM, &act, &oact) < 0 || sigaction(SIGUSR1, &act, &oact) < 0 || sigaction(SIGHUP, &act, &oact) < 0 || sigaction(SIGTERM, &act, &oact) < 0) { NORM_ERR("error setting signal handler: %s", strerror(errno)); } llua_startup_hook(); } int main(int argc, char **argv) { #ifdef BUILD_I18N setlocale(LC_ALL, ""); bindtextdomain(PACKAGE_NAME, LOCALE_DIR); textdomain(PACKAGE_NAME); #endif argc_copy = argc; argv_copy = argv; g_signal_pending = 0; clear_net_stats(); #ifdef BUILD_CURL struct curl_global_initializer { curl_global_initializer() { if(curl_global_init(CURL_GLOBAL_ALL)) NORM_ERR("curl_global_init() failed, you may not be able to use curl variables"); } ~curl_global_initializer() { curl_global_cleanup(); } }; curl_global_initializer curl_global; #endif /* handle command line parameters that don't change configs */ #ifdef BUILD_X11 if (!setlocale(LC_CTYPE, "")) { NORM_ERR("Can't set the specified locale!\nCheck LANG, LC_CTYPE, LC_ALL."); } #endif /* BUILD_X11 */ while (1) { int c = getopt_long(argc, argv, getopt_string, longopts, NULL); if (c == -1) { break; } switch (c) { case 'D': global_debug_level++; break; case 'v': case 'V': print_version(); return EXIT_SUCCESS; case 'c': current_config = optarg; break; case 'q': if (!freopen("/dev/null", "w", stderr)) CRIT_ERR(0, 0, "could not open /dev/null as stderr!"); break; case 'h': print_help(argv[0]); return 0; #ifdef BUILD_BUILTIN_CONFIG case 'C': std::cout << defconfig; return 0; #endif #ifdef BUILD_X11 case 'w': window.window = strtol(optarg, 0, 0); break; #endif /* BUILD_X11 */ case '?': return EXIT_FAILURE; } } try { set_current_config(); state.reset(new lua::state); conky::export_symbols(*state); #ifdef BUILD_WEATHER_XOAP /* Load xoap keys, if existing */ load_xoap_keys(); #endif /* BUILD_WEATHER_XOAP */ #ifdef HAVE_SYS_INOTIFY_H // the file descriptor will be automatically closed on exit inotify_fd = inotify_init(); if(inotify_fd != -1) { fcntl(inotify_fd, F_SETFL, fcntl(inotify_fd, F_GETFL) | O_NONBLOCK); fcntl(inotify_fd, F_SETFD, fcntl(inotify_fd, F_GETFD) | FD_CLOEXEC); } #endif /* HAVE_SYS_INOTIFY_H */ initialisation(argc, argv); first_pass = 0; /* don't ever call fork() again */ main_loop(); } catch(fork_throw &e) { return EXIT_SUCCESS; } catch(unknown_arg_throw &e) { return EXIT_FAILURE; } catch(obj_create_error &e) { std::cerr << e.what() << std::endl; clean_up(NULL, NULL); return EXIT_FAILURE; } catch(std::exception &e) { std::cerr << PACKAGE_NAME": " << e.what() << std::endl; return EXIT_FAILURE; } #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) kvm_close(kd); #endif #ifdef LEAKFREE_NCURSES _nc_free_and_exit(0); //hide false memleaks #endif return 0; } static void signal_handler(int sig) { /* signal handler is light as a feather, as it should be. * we will poll g_signal_pending with each loop of conky * and do any signal processing there, NOT here */ g_signal_pending = sig; } conky-1.10.1/src/conky.h000066400000000000000000000174251262311664100150130ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _conky_h_ #define _conky_h_ #define __STDC_FORMAT_MACROS #include /* defines */ #include "common.h" /* at least for struct dns_data */ #include /* struct uname_s */ #include #include #include "luamm.hh" #if defined(HAS_MCHECK_H) #include #endif /* HAS_MCHECK_H */ #undef EQUAL #undef FALSE #undef TRUE #define EQUAL 0 //returnvalue of strcmp-variants when strings are equal #define FALSE 0 #define TRUE 1 #define DEFAULT_BAR_WIDTH_NO_X 10 #if !defined(__GNUC__) # define __attribute__(x) /* nothing */ #endif #ifndef HAVE_STRNDUP // use our own strndup() if it's not available char *strndup(const char *s, size_t n); #endif /* HAVE_STRNDUP */ /* headers of optional features * include them here, so we don't need to run the check * in every code file optionally using the feature */ /* forward define to make gcc happy */ struct text_object; #ifdef BUILD_BMPX #include "bmpx.h" #endif /* BUILD_BMPX */ #ifdef BUILD_EVE #include "eve.h" #endif /* BUILD_EVE */ #ifdef BUILD_HDDTEMP #include "hddtemp.h" #endif /* BUILD_HDDTEMP */ #ifdef BUILD_MOC #include "moc.h" #endif /* BUILD_MOC */ #ifdef BUILD_MPD #include "mpd.h" #endif /* BUILD_MPD */ #ifdef BUILD_MYSQL #include "mysql.h" #endif /* BUILD_MYSQL */ #ifdef BUILD_WEATHER_XOAP #ifndef BUILD_WEATHER_METAR #error "BUILD_WEATHER_METAR needs to be defined if XOAP is defined" #endif /* BUILD_WEATHER_METAR */ #endif /* BUILD_WEATHER_XOAP */ #ifdef BUILD_PORT_MONITORS #include "tcp-portmon.h" #endif #ifdef BUILD_XMMS2 #include "xmms2.h" #endif /* BUILD_XMMS2 */ #ifdef BUILD_APCUPSD #include "apcupsd.h" #endif /* BUILD_APCUPSD */ /* sony support */ #include "sony.h" /* A size for temporary, static buffers to use when * one doesn't know what to choose. Defaults to 256. */ extern conky::range_config_setting text_buffer_size; struct usr_info { char *names; char *times; char *ctime; char *terms; int number; }; #ifdef BUILD_X11 struct monitor_info { int number; int current; }; struct desktop_info { int current; int number; std::string all_names; std::string name; }; struct x11_info { struct monitor_info monitor; struct desktop_info desktop; }; #endif /* BUILD_X11 */ struct conftree { char* string; struct conftree* horz_next; struct conftree* vert_next; struct conftree* back; }; void load_config_file(); char *get_global_text(void); extern long global_text_lines; #define MAX_TEMPLATES 10 char **get_templates(void); /* get_battery_stuff() item selector * needed by conky.c, linux.c and freebsd.c */ enum { BATTERY_STATUS, BATTERY_TIME }; struct information { unsigned int mask; struct utsname uname_s; #if defined(__DragonFly__) char uname_v[256]; /* with git version */ #endif char freq[10]; double uptime; /* memory information in kilobytes */ unsigned long long mem, memwithbuffers, memeasyfree, memfree, memmax, memdirty; unsigned long long swap, swapfree, swapmax; unsigned long long bufmem, buffers, cached; unsigned short procs; unsigned short run_procs; unsigned short threads; unsigned short run_threads; float *cpu_usage; /* struct cpu_stat cpu_summed; what the hell is this? */ int cpu_count; float loadavg[3]; #ifdef BUILD_XMMS2 struct xmms2_s xmms2; #endif /* BUILD_XMMS2 */ #ifdef BUILD_BMPX struct bmpx_s bmpx; #endif /* BUILD_BMPX */ struct usr_info users; struct process *cpu[10]; struct process *memu[10]; struct process *time[10]; #ifdef BUILD_IOSTATS struct process *io[10]; #endif /* BUILD_IOSTATS */ struct process *first_process; unsigned long looped; #ifdef BUILD_X11 struct x11_info x11; #endif /* BUILD_X11 */ short kflags; /* kernel settings, see enum KFLAG */ }; class music_player_interval_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); public: music_player_interval_setting() : Base("music_player_interval", 0, true) {} }; extern music_player_interval_setting music_player_interval; extern conky::range_config_setting cpu_avg_samples; extern conky::range_config_setting net_avg_samples; extern conky::range_config_setting diskio_avg_samples; /* needed by linux.c and top.c -> outsource somewhere */ enum { /* set to true if kernel uses "long" format for /proc/stats */ KFLAG_IS_LONGSTAT = 0x01, /* set to true if kernel shows # of threads for the proc value * in sysinfo() call */ KFLAG_PROC_IS_THREADS = 0x02 /* bits 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 available for future use */ /* KFLAG_NEXT_ONE = 0x04 */ }; #define KFLAG_SETON(a) info.kflags |= a #define KFLAG_SETOFF(a) info.kflags &= (~a) #define KFLAG_FLIP(a) info.kflags ^= a #define KFLAG_ISSET(a) info.kflags & a /* defined in conky.c, needed by top.c */ extern int top_cpu, top_mem, top_time; #ifdef BUILD_IOSTATS extern int top_io; #endif /* BUILD_IOSTATS */ extern int top_running; /* struct that has all info to be shared between * instances of the same text object */ extern struct information info; /* defined in conky.c */ extern double current_update_time, last_update_time; extern conky::range_config_setting update_interval; extern conky::range_config_setting update_interval_on_battery; double active_update_interval(); extern conky::range_config_setting stippled_borders; void set_current_text_color(long colour); long get_current_text_color(void); void set_updatereset(int); int get_updatereset(void); int get_total_updates(void); /* defined in conky.c */ int spaced_print(char *, int, const char *, int, ...) __attribute__((format(printf, 3, 5))); extern int inotify_fd; /* defined in conky.c * evaluates 'text' and places the result in 'p' of max length 'p_max_size' */ void evaluate(const char *text, char *p, int p_max_size); void parse_conky_vars(struct text_object *, const char *, char *, int); void extract_object_args_to_sub(struct text_object *, const char *); void generate_text_internal(char *, int, struct text_object); int percent_print(char *, int, unsigned); void human_readable(long long, char *, int); /* maximum size of config TEXT buffer, i.e. below TEXT line. */ extern conky::range_config_setting max_user_text; /* path to config file */ extern std::string current_config; #define DEFAULT_TEXT_BUFFER_SIZE_S "##DEFAULT_TEXT_BUFFER_SIZE" #define NOBATTERY 0 /* to get rid of 'unused variable' warnings */ #define UNUSED(a) (void)a #define UNUSED_ATTR __attribute__ ((unused)) template void free_and_zero(T *&ptr) { if(ptr) { free(ptr); ptr = NULL; } } extern std::unique_ptr state; extern int argc_copy; extern char** argv_copy; #endif /* _conky_h_ */ conky-1.10.1/src/core.cc000066400000000000000000002202301262311664100147440ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 . * */ /* local headers */ #include "core.h" #include "text_object.h" #include "algebra.h" #include "build.h" #include "bsdapm.h" #include "colours.h" #include "combine.h" #include "diskio.h" #include "entropy.h" #include "exec.h" #include "i8k.h" #ifdef BUILD_IMLIB2 #include "imlib2.h" #endif #include "proc.h" #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 #include "fs.h" #ifdef BUILD_IBM #include "ibm.h" #include "smapi.h" #endif #ifdef BUILD_ICONV #include "iconv_tools.h" #endif #include "llua.h" #include "logging.h" #include "mixer.h" #include "mail.h" #include "mboxscan.h" #include "nc.h" #include "net_stat.h" #ifdef BUILD_NVIDIA #include "nvidia.h" #endif #include "read_tcpip.h" #include "scroll.h" #include "specials.h" #include "temphelper.h" #include "template.h" #include "tailhead.h" #include "timeinfo.h" #include "top.h" #include "user.h" #include "users.h" #ifdef BUILD_CURL #include "ccurl_thread.h" #endif /* BUILD_CURL */ #ifdef BUILD_WEATHER_METAR #include "weather.h" #endif /* BUILD_WEATHER_METAR */ #ifdef BUILD_RSS #include "rss.h" #endif /* BUILD_RSS */ #ifdef BUILD_AUDACIOUS #include "audacious.h" #endif #ifdef BUILD_CMUS #include "cmus.h" #endif /* check for OS and include appropriate headers */ #if defined(__linux__) #include "linux.h" #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "freebsd.h" #elif defined(__DragonFly__) #include "dragonfly.h" #elif defined(__OpenBSD__) #include "openbsd.h" #endif #include #include /* strip a leading /dev/ if any, following symlinks first * * BEWARE: this function returns a pointer to static content * which gets overwritten in consecutive calls. I.e.: * this function is NOT reentrant. */ const char *dev_name(const char *path) { static char buf[255]; /* should be enough for pathnames */ ssize_t buflen; if (!path) return NULL; #define DEV_NAME(x) \ x != NULL && strlen(x) > 5 && strncmp(x, "/dev/", 5) == 0 ? x + 5 : x if ((buflen = readlink(path, buf, 254)) == -1) return DEV_NAME(path); buf[buflen] = '\0'; return DEV_NAME(buf); #undef DEV_NAME } static struct text_object *new_text_object_internal(void) { struct text_object *obj = (text_object*)malloc(sizeof(struct text_object)); memset(obj, 0, sizeof(struct text_object)); return obj; } static struct text_object *create_plain_text(const char *s) { struct text_object *obj; if (s == NULL || *s == '\0') { return NULL; } obj = new_text_object_internal(); obj_be_plain_text(obj, s); return obj; } #ifdef BUILD_CURL void stock_parse_arg(struct text_object *obj, const char *arg) { char stock[8]; char data[16]; obj->data.s = NULL; if(sscanf(arg, "%7s %15s", stock, data) != 2) { NORM_ERR("wrong number of arguments for $stock"); return; } if(!strcasecmp("ask", data)) strcpy(data, "a"); 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: 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 obj->data.s = (char*) malloc(MAX_FINYAH_URL_LENGTH); snprintf(obj->data.s, MAX_FINYAH_URL_LENGTH, "http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=%s", stock, data); } #endif /* BUILD_CURL */ legacy_cb_handle *create_cb_handle(int (*fn)()) { if(fn) return new legacy_cb_handle(conky::register_cb(1, fn)); else return NULL; } /* construct_text_object() creates a new text_object */ struct text_object *construct_text_object(char *s, const char *arg, long line, void **ifblock_opaque, void *free_at_crash) { // struct text_object *obj = new_text_object(); struct text_object *obj = new_text_object_internal(); obj->line = line; /* helper defines for internal use only */ #define __OBJ_HEAD(a, n) if (!strcmp(s, #a)) { \ obj->cb_handle = create_cb_handle(n); #define __OBJ_IF obj_be_ifblock_if(ifblock_opaque, obj) #define __OBJ_ARG(...) if (!arg) { free(s); CRIT_ERR(obj, free_at_crash, __VA_ARGS__); } /* defines to be used below */ #define OBJ(a, n) __OBJ_HEAD(a, n) { #define OBJ_ARG(a, n, ...) __OBJ_HEAD(a, n) __OBJ_ARG(__VA_ARGS__) { #define OBJ_IF(a, n) __OBJ_HEAD(a, n) __OBJ_IF; { #define OBJ_IF_ARG(a, n, ...) __OBJ_HEAD(a, n) __OBJ_ARG(__VA_ARGS__) __OBJ_IF; { #define END } } else #ifdef BUILD_X11 if (s[0] == '#') { obj->data.l = get_x11_color(s); obj->callbacks.print = &new_fg; } else #endif /* BUILD_X11 */ #ifndef __OpenBSD__ OBJ(acpitemp, 0) obj->data.i = open_acpi_temperature(arg); obj->callbacks.print = &print_acpitemp; obj->callbacks.free = &free_acpitemp; END OBJ(acpiacadapter, 0) if(arg) { #ifdef __linux__ if(strpbrk(arg, "/.") != NULL) { /* * a bit of paranoia. screen out funky paths * i hope no device will have a '.' in its name */ NORM_ERR("acpiacadapter: arg must not contain '/' or '.'"); } else obj->data.opaque = strdup(arg); #else NORM_ERR("acpiacadapter: arg is only used on linux"); #endif } obj->callbacks.print = &print_acpiacadapter; obj->callbacks.free = &gen_free_opaque; #endif /* !__OpenBSD__ */ END OBJ(freq, 0) get_cpu_count(); if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0 || atoi(&arg[0]) > info.cpu_count) { obj->data.i = 1; /* NORM_ERR("freq: Invalid CPU number or you don't have that many CPUs! " "Displaying the clock for CPU 1."); */ } else { obj->data.i = atoi(&arg[0]); } obj->callbacks.print = &print_freq; END OBJ(freq_g, 0) get_cpu_count(); if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0 || atoi(&arg[0]) > info.cpu_count) { obj->data.i = 1; /* NORM_ERR("freq_g: Invalid CPU number or you don't have that many " "CPUs! Displaying the clock for CPU 1."); */ } else { obj->data.i = atoi(&arg[0]); } obj->callbacks.print = &print_freq_g; END OBJ_ARG(read_tcp, 0, "read_tcp: Needs \"(host) port\" as argument(s)") parse_read_tcpip_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_read_tcp; obj->callbacks.free = &free_read_tcpip; END OBJ_ARG(read_udp, 0, "read_udp: Needs \"(host) port\" as argument(s)") 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(); if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0 || atoi(&arg[0]) > info.cpu_count) { obj->data.i = 1; /* NORM_ERR("voltage_mv: Invalid CPU number or you don't have that many " "CPUs! Displaying voltage for CPU 1."); */ } else { obj->data.i = atoi(&arg[0]); } obj->callbacks.print = &print_voltage_mv; END OBJ(voltage_v, 0) get_cpu_count(); if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0 || atoi(&arg[0]) > info.cpu_count) { obj->data.i = 1; /* NORM_ERR("voltage_v: Invalid CPU number or you don't have that many " "CPUs! Displaying voltage for CPU 1."); */ } else { obj->data.i = atoi(&arg[0]); } obj->callbacks.print = &print_voltage_v; #ifdef BUILD_WLAN 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; END OBJ(wireless_bitrate, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_wireless_bitrate; END OBJ(wireless_ap, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_wireless_ap; END OBJ(wireless_link_qual, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_wireless_link_qual; END OBJ(wireless_link_qual_max, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_wireless_link_qual_max; END OBJ(wireless_link_qual_perc, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_wireless_link_qual_perc; END OBJ(wireless_link_bar, &update_net_stats) parse_net_stat_bar_arg(obj, arg, free_at_crash); obj->callbacks.barval = &wireless_link_barval; #endif /* BUILD_WLAN */ #endif /* __linux__ */ #ifndef __OpenBSD__ END OBJ(acpifan, 0) obj->callbacks.print = &print_acpifan; END OBJ(battery, 0) char bat[64]; if (arg) { sscanf(arg, "%63s", bat); } else { strcpy(bat, "BAT0"); } obj->data.s = strndup(bat, text_buffer_size.get(*state)); obj->callbacks.print = &print_battery; obj->callbacks.free = &gen_free_opaque; END OBJ(battery_short, 0) char bat[64]; if (arg) { sscanf(arg, "%63s", bat); } else { strcpy(bat, "BAT0"); } obj->data.s = strndup(bat, text_buffer_size.get(*state)); obj->callbacks.print = &print_battery_short; obj->callbacks.free = &gen_free_opaque; END OBJ(battery_time, 0) char bat[64]; if (arg) { sscanf(arg, "%63s", bat); } else { strcpy(bat, "BAT0"); } obj->data.s = strndup(bat, text_buffer_size.get(*state)); obj->callbacks.print = &print_battery_time; obj->callbacks.free = &gen_free_opaque; END OBJ(battery_percent, 0) char bat[64]; if (arg) { sscanf(arg, "%63s", bat); } else { strcpy(bat, "BAT0"); } obj->data.s = strndup(bat, text_buffer_size.get(*state)); obj->callbacks.percentage = &battery_percentage; obj->callbacks.free = &gen_free_opaque; END OBJ(battery_bar, 0) char bat[64]; arg = scan_bar(obj, arg, 100); if (arg && strlen(arg)>0) { sscanf(arg, "%63s", bat); } else { strcpy(bat, "BAT0"); } obj->data.s = strndup(bat, text_buffer_size.get(*state)); obj->callbacks.barval = &get_battery_perct_bar; obj->callbacks.free = &gen_free_opaque; #endif /* !__OpenBSD__ */ #if defined(__linux__) END OBJ_ARG(disk_protect, 0, "disk_protect needs an argument") obj->data.s = strndup(dev_name(arg), text_buffer_size.get(*state)); obj->callbacks.print = &print_disk_protect_queue; obj->callbacks.free = &gen_free_opaque; END OBJ(i8k_version, &update_i8k) obj->callbacks.print = &print_i8k_version; END OBJ(i8k_bios, &update_i8k) obj->callbacks.print = &print_i8k_bios; END OBJ(i8k_serial, &update_i8k) obj->callbacks.print = &print_i8k_serial; END OBJ(i8k_cpu_temp, &update_i8k) obj->callbacks.print = &print_i8k_cpu_temp; END OBJ(i8k_left_fan_status, &update_i8k) obj->callbacks.print = &print_i8k_left_fan_status; END OBJ(i8k_right_fan_status, &update_i8k) obj->callbacks.print = &print_i8k_right_fan_status; END OBJ(i8k_left_fan_rpm, &update_i8k) obj->callbacks.print = &print_i8k_left_fan_rpm; END OBJ(i8k_right_fan_rpm, &update_i8k) obj->callbacks.print = &print_i8k_right_fan_rpm; END OBJ(i8k_ac_status, &update_i8k) obj->callbacks.print = &print_i8k_ac_status; END OBJ(i8k_buttons_status, &update_i8k) obj->callbacks.print = &print_i8k_buttons_status; #if defined(BUILD_IBM) END OBJ(ibm_fan, 0) obj->callbacks.print = &get_ibm_acpi_fan; END OBJ_ARG(ibm_temps, &get_ibm_acpi_temps, "ibm_temps: needs an argument") parse_ibm_temps_arg(obj, arg); obj->callbacks.print = &print_ibm_temps; END OBJ(ibm_volume, 0) obj->callbacks.print = &get_ibm_acpi_volume; END OBJ(ibm_brightness, 0) obj->callbacks.print = &get_ibm_acpi_brightness; END OBJ(ibm_thinklight, 0) obj->callbacks.print = &get_ibm_acpi_thinklight; #endif /* information from sony_laptop kernel module * /sys/devices/platform/sony-laptop */ END OBJ(sony_fanspeed, 0) obj->callbacks.print = &get_sony_fanspeed; END OBJ_IF(if_gw, &update_gateway_info) obj->callbacks.iftest = &gateway_exists; obj->callbacks.free = &free_gateway_info; END OBJ_ARG(ioscheduler, 0, "get_ioscheduler needs an argument (e.g. hda)") obj->data.s = strndup(dev_name(arg), text_buffer_size.get(*state)); obj->callbacks.print = &print_ioscheduler; obj->callbacks.free = &gen_free_opaque; END OBJ(laptop_mode, 0) obj->callbacks.print = &print_laptop_mode; END OBJ_ARG(pb_battery, 0, "pb_battery: needs one argument: status, percent or time") if (strcmp(arg, "status") == EQUAL) { obj->data.i = PB_BATT_STATUS; } else if (strcmp(arg, "percent") == EQUAL) { obj->data.i = PB_BATT_PERCENT; } else if (strcmp(arg, "time") == EQUAL) { obj->data.i = PB_BATT_TIME; } else { NORM_ERR("pb_battery: illegal argument '%s', defaulting to status", arg); obj->data.i = PB_BATT_STATUS; } obj->callbacks.print = get_powerbook_batt_info; #endif /* __linux__ */ #if (defined(__FreeBSD__) || defined(__linux__) || defined(__DragonFly__)) END OBJ_IF_ARG(if_up, 0, "if_up needs an argument") parse_if_up_arg(obj, arg); obj->callbacks.iftest = &interface_up; obj->callbacks.free = &free_if_up; #endif #if defined(__OpenBSD__) END OBJ_ARG(obsd_sensors_temp, 0, "obsd_sensors_temp: needs an argument") parse_obsd_sensor(obj, arg); obj->callbacks.print = &print_obsd_sensors_temp; END OBJ_ARG(obsd_sensors_fan, 0, "obsd_sensors_fan: needs 2 arguments (device and sensor number)") parse_obsd_sensor(obj, arg); obj->callbacks.print = &print_obsd_sensors_fan; END OBJ_ARG(obsd_sensors_volt, 0, "obsd_sensors_volt: needs 2 arguments (device and sensor number)") parse_obsd_sensor(obj, arg); obj->callbacks.print = &print_obsd_sensors_volt; END OBJ(obsd_vendor, 0) obj->callbacks.print = &get_obsd_vendor; END OBJ(obsd_product, 0) obj->callbacks.print = &get_obsd_product; #endif /* __OpenBSD__ */ END OBJ(buffers, &update_meminfo) obj->callbacks.print = &print_buffers; END OBJ(cached, &update_meminfo) obj->callbacks.print = &print_cached; #define SCAN_CPU(__arg, __var) { \ int __offset = 0; \ if (__arg && sscanf(__arg, " cpu%d %n", &__var, &__offset) > 0) \ __arg += __offset; \ else \ __var = 0; \ } END OBJ(cpu, &update_cpu_usage) get_cpu_count(); SCAN_CPU(arg, obj->data.i); obj->callbacks.percentage = &cpu_percentage; DBGP2("Adding $cpu for CPU %d", obj->data.i); #ifdef BUILD_X11 END OBJ(cpugauge, &update_cpu_usage) get_cpu_count(); SCAN_CPU(arg, obj->data.i); scan_gauge(obj, arg, 1); obj->callbacks.gaugeval = &cpu_barval; DBGP2("Adding $cpugauge for CPU %d", obj->data.i); #endif END OBJ(cpubar, &update_cpu_usage) get_cpu_count(); SCAN_CPU(arg, obj->data.i); scan_bar(obj, arg, 1); obj->callbacks.barval = &cpu_barval; DBGP2("Adding $cpubar for CPU %d", obj->data.i); #ifdef BUILD_X11 END OBJ(cpugraph, &update_cpu_usage) get_cpu_count(); char *buf = 0; SCAN_CPU(arg, obj->data.i); buf = scan_graph(obj, arg, 1); DBGP2("Adding $cpugraph for CPU %d", obj->data.i); free_and_zero(buf); obj->callbacks.graphval = &cpu_barval; END OBJ(loadgraph, &update_load_average) scan_loadgraph_arg(obj, arg); obj->callbacks.graphval = &loadgraphval; #endif /* BUILD_X11 */ END OBJ(diskio, &update_diskio) parse_diskio_arg(obj, arg); obj->callbacks.print = &print_diskio; END OBJ(diskio_read, &update_diskio) parse_diskio_arg(obj, arg); obj->callbacks.print = &print_diskio_read; END OBJ(diskio_write, &update_diskio) parse_diskio_arg(obj, arg); obj->callbacks.print = &print_diskio_write; #ifdef BUILD_X11 END OBJ(diskiograph, &update_diskio) parse_diskiograph_arg(obj, arg); obj->callbacks.graphval = &diskiographval; END OBJ(diskiograph_read, &update_diskio) parse_diskiograph_arg(obj, arg); obj->callbacks.graphval = &diskiographval_read; END OBJ(diskiograph_write, &update_diskio) parse_diskiograph_arg(obj, arg); obj->callbacks.graphval = &diskiographval_write; #endif /* BUILD_X11 */ END OBJ(color, 0) #ifdef BUILD_X11 if (out_to_x.get(*state)) { obj->data.l = arg ? get_x11_color(arg) : default_color.get(*state); set_current_text_color(obj->data.l); } #endif /* BUILD_X11 */ #ifdef BUILD_NCURSES if (out_to_ncurses.get(*state)) { obj->data.l = COLOR_WHITE; if(arg) { if(strcasecmp(arg, "red") == 0) { obj->data.l = COLOR_RED; }else if(strcasecmp(arg, "green") == 0) { obj->data.l = COLOR_GREEN; }else if(strcasecmp(arg, "yellow") == 0) { obj->data.l = COLOR_YELLOW; }else if(strcasecmp(arg, "blue") == 0) { obj->data.l = COLOR_BLUE; }else if(strcasecmp(arg, "magenta") == 0) { obj->data.l = COLOR_MAGENTA; }else if(strcasecmp(arg, "cyan") == 0) { obj->data.l = COLOR_CYAN; }else if(strcasecmp(arg, "black") == 0) { obj->data.l = COLOR_BLACK; } } set_current_text_color(obj->data.l); init_pair(obj->data.l, obj->data.l, COLOR_BLACK); } #endif /* BUILD_NCURSES */ obj->callbacks.print = &new_fg; #ifdef BUILD_X11 END OBJ(color0, 0) obj->data.l = color[0].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color1, 0) obj->data.l = color[1].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color2, 0) obj->data.l = color[2].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color3, 0) obj->data.l = color[3].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color4, 0) obj->data.l = color[4].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color5, 0) obj->data.l = color[5].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color6, 0) obj->data.l = color[6].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color7, 0) obj->data.l = color[7].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color8, 0) obj->data.l = color[8].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(color9, 0) obj->data.l = color[9].get(*state); set_current_text_color(obj->data.l); obj->callbacks.print = &new_fg; END OBJ(font, 0) scan_font(obj, arg); obj->callbacks.print = &new_font; obj->callbacks.free = &gen_free_opaque; #endif /* BUILD_X11 */ END OBJ(conky_version, 0) obj_be_plain_text(obj, VERSION); END OBJ(conky_build_date, 0) obj_be_plain_text(obj, BUILD_DATE); END OBJ(conky_build_arch, 0) obj_be_plain_text(obj, BUILD_ARCH); END OBJ(downspeed, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_downspeed; END OBJ(downspeedf, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_downspeedf; #ifdef BUILD_X11 END OBJ(downspeedgraph, &update_net_stats) parse_net_stat_graph_arg(obj, arg, free_at_crash); obj->callbacks.graphval = &downspeedgraphval; #endif /* BUILD_X11 */ END OBJ(else, 0) obj_be_ifblock_else(ifblock_opaque, obj); obj->callbacks.iftest = &gen_false_iftest; END OBJ(endif, 0) obj_be_ifblock_endif(ifblock_opaque, obj); obj->callbacks.print = &gen_print_nothing; END OBJ(eval, 0) obj->data.s = strndup(arg ? arg : "", text_buffer_size.get(*state)); obj->callbacks.print = &print_evaluate; obj->callbacks.free = &gen_free_opaque; #if defined(BUILD_IMLIB2) && defined(BUILD_X11) END OBJ(image, 0) obj->data.s = strndup(arg ? arg : "", text_buffer_size.get(*state)); obj->callbacks.print = &print_image_callback; obj->callbacks.free = &gen_free_opaque; #endif /* BUILD_IMLIB2 */ #ifdef BUILD_MYSQL END OBJ_ARG(mysql, 0, "mysql needs a query") obj->data.s = strdup(arg); obj->callbacks.print = &print_mysql; #endif /* BUILD_MYSQL */ END OBJ_ARG(no_update, 0, "no_update needs arguments") scan_no_update(obj, arg); obj->callbacks.print = &print_no_update; obj->callbacks.free = &free_no_update; END OBJ(exec, 0) scan_exec_arg(obj, arg); obj->parse = false; obj->thread = false; obj->callbacks.print = &print_exec; obj->callbacks.free = &free_exec; END OBJ(execp, 0) scan_exec_arg(obj, arg); obj->parse = true; obj->thread = false; obj->callbacks.print = &print_exec; obj->callbacks.free = &free_exec; END OBJ(execbar, 0) scan_exec_arg(obj, arg); obj->callbacks.barval = &execbarval; obj->callbacks.free = &free_exec; END OBJ(execgauge, 0) scan_exec_arg(obj, arg); obj->callbacks.gaugeval = &execbarval; obj->callbacks.free = &free_exec; #ifdef BUILD_X11 END OBJ(execgraph, 0) scan_execgraph_arg(obj, arg); obj->callbacks.graphval = &execbarval; obj->callbacks.free = &free_exec; #endif /* BUILD_X11 */ END OBJ_ARG(execibar, 0, "execibar needs arguments") scan_execi_bar_arg(obj, arg); obj->callbacks.barval = &execi_barval; obj->callbacks.free = &free_execi; #ifdef BUILD_X11 END OBJ_ARG(execigraph, 0, "execigraph needs arguments") scan_execgraph_arg(obj, arg); obj->callbacks.graphval = &execi_barval; obj->callbacks.free = &free_execi; END OBJ_ARG(execigauge, 0, "execigauge needs arguments") scan_execi_gauge_arg(obj, arg); obj->callbacks.gaugeval = &execi_barval; obj->callbacks.free = &free_execi; #endif /* BUILD_X11 */ END OBJ_ARG(execi, 0, "execi needs arguments") scan_execi_arg(obj, arg); obj->parse = false; obj->thread = false; obj->callbacks.print = &print_execi; obj->callbacks.free = &free_execi; END OBJ_ARG(execpi, 0, "execpi needs arguments") scan_execi_arg(obj, arg); obj->parse = true; obj->thread = false; obj->callbacks.print = &print_execi; obj->callbacks.free = &free_execi; END OBJ_ARG(texeci, 0, "texeci needs arguments") scan_execi_arg(obj, arg); obj->parse = false; obj->thread = true; obj->callbacks.print = &print_execi; obj->callbacks.free = &free_execi; END OBJ_ARG(texecpi, 0, "texecpi needs arguments") scan_execi_arg(obj, arg); obj->parse = true; obj->thread = true; obj->callbacks.print = &print_execi; obj->callbacks.free = &free_execi; END OBJ(fs_bar, &update_fs_stats) init_fs_bar(obj, arg); obj->callbacks.barval = &fs_barval; END OBJ(fs_bar_free, &update_fs_stats) init_fs_bar(obj, arg); obj->callbacks.barval = &fs_free_barval; END OBJ(fs_free, &update_fs_stats) init_fs(obj, arg); obj->callbacks.print = &print_fs_free; END OBJ(fs_used_perc, &update_fs_stats) init_fs(obj, arg); obj->callbacks.percentage = &fs_used_percentage; END OBJ(fs_free_perc, &update_fs_stats) init_fs(obj, arg); obj->callbacks.percentage = &fs_free_percentage; END OBJ(fs_size, &update_fs_stats) init_fs(obj, arg); obj->callbacks.print = &print_fs_size; END OBJ(fs_type, &update_fs_stats) init_fs(obj, arg); obj->callbacks.print = &print_fs_type; END OBJ(fs_used, &update_fs_stats) init_fs(obj, arg); obj->callbacks.print = &print_fs_used; #ifdef BUILD_X11 END OBJ(hr, 0) obj->data.l = arg ? atoi(arg) : 1; obj->callbacks.print = &new_hr; #endif /* BUILD_X11 */ END OBJ(nameserver, &update_dns_data) parse_nameserver_arg(obj, arg); obj->callbacks.print = &print_nameserver; obj->callbacks.free = &free_dns_data; END OBJ(offset, 0) obj->data.l = arg ? atoi(arg) : 1; obj->callbacks.print = &new_offset; END OBJ(voffset, 0) obj->data.l = arg ? atoi(arg) : 1; obj->callbacks.print = &new_voffset; END OBJ_ARG(goto, 0, "goto needs arguments") obj->data.l = atoi(arg); obj->callbacks.print = &new_goto; #ifdef BUILD_X11 END OBJ(tab, 0) scan_tab(obj, arg); obj->callbacks.print = &new_tab; #endif /* BUILD_X11 */ #ifdef __linux__ END OBJ_ARG(i2c, 0, "i2c needs arguments") parse_i2c_sensor(obj, arg); obj->callbacks.print = &print_sysfs_sensor; obj->callbacks.free = &free_sysfs_sensor; END OBJ_ARG(platform, 0, "platform needs arguments") parse_platform_sensor(obj, arg); obj->callbacks.print = &print_sysfs_sensor; obj->callbacks.free = &free_sysfs_sensor; END OBJ_ARG(hwmon, 0, "hwmon needs argumanets") parse_hwmon_sensor(obj, arg); obj->callbacks.print = &print_sysfs_sensor; obj->callbacks.free = &free_sysfs_sensor; #endif /* __linux__ */ END /* we have four different types of top (top, top_mem, top_time and top_io). To * avoid having almost-same code four times, we have this special * handler. */ /* XXX: maybe fiddle them apart later, as print_top() does * nothing else than just that, using an ugly switch(). */ if (strncmp(s, "top", 3) == EQUAL) { if (parse_top_args(s, arg, obj)) { #ifdef __linux__ determine_longstat_file(); #endif obj->cb_handle = create_cb_handle(update_top); } else { free(obj); return NULL; } } else #ifdef __linux__ OBJ(addr, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_addr; END OBJ(addrs, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_addrs; #ifdef BUILD_IPV6 END OBJ(v6addrs, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_v6addrs; #endif /* BUILD_IPV6 */ END #endif /* __linux__ */ OBJ_ARG(tail, 0, "tail needs arguments") init_tailhead("tail", arg, obj, free_at_crash); obj->callbacks.print = &print_tail; obj->callbacks.free = &free_tailhead; END OBJ_ARG(head, 0, "head needs arguments") init_tailhead("head", arg, obj, free_at_crash); obj->callbacks.print = &print_head; obj->callbacks.free = &free_tailhead; END OBJ_ARG(lines, 0, "lines needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_lines; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(words, 0, "words needs a argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_words; obj->callbacks.free = &gen_free_opaque; END OBJ(loadavg, &update_load_average) scan_loadavg_arg(obj, arg); obj->callbacks.print = &print_loadavg; END OBJ_IF_ARG(if_empty, 0, "if_empty needs an argument") obj->sub = (text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, arg); obj->callbacks.iftest = &if_empty_iftest; END OBJ_IF_ARG(if_match, 0, "if_match needs arguments") obj->sub = (text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, arg); obj->callbacks.iftest = &check_if_match; END OBJ_IF_ARG(if_existing, 0, "if_existing needs an argument or two") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.iftest = &if_existing_iftest; obj->callbacks.free = &gen_free_opaque; #ifdef __linux__ END OBJ_IF_ARG(if_mounted, 0, "if_mounted needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.iftest = &check_mount; obj->callbacks.free = &gen_free_opaque; END OBJ_IF_ARG(if_running, &update_top, "if_running needs an argument") top_running = 1; obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.iftest = &if_running_iftest; obj->callbacks.free = &gen_free_opaque; #else END OBJ_IF_ARG(if_running, 0, "if_running needs an argument") char buf[text_buffer_size.get(*state)]; snprintf(buf, text_buffer_size.get(*state), "pidof %s >/dev/null", arg); obj->data.s = strndup(buf, text_buffer_size.get(*state)); /* XXX: maybe use a different callback here */ obj->callbacks.iftest = &if_running_iftest; #endif END OBJ(kernel, 0) obj->callbacks.print = &print_kernel; END OBJ(machine, 0) obj->callbacks.print = &print_machine; #if defined(__DragonFly__) END OBJ(version, 0) obj->callbacks.print = &print_version; #endif END OBJ(mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_mails; obj->callbacks.free = &free_local_mails; END OBJ(new_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_new_mails; obj->callbacks.free = &free_local_mails; END OBJ(seen_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_seen_mails; obj->callbacks.free = &free_local_mails; END OBJ(unseen_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_unseen_mails; obj->callbacks.free = &free_local_mails; END OBJ(flagged_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_flagged_mails; obj->callbacks.free = &free_local_mails; END OBJ(unflagged_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_unflagged_mails; obj->callbacks.free = &free_local_mails; END OBJ(forwarded_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_forwarded_mails; obj->callbacks.free = &free_local_mails; END OBJ(unforwarded_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_unforwarded_mails; obj->callbacks.free = &free_local_mails; END OBJ(replied_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_replied_mails; obj->callbacks.free = &free_local_mails; END OBJ(unreplied_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_unreplied_mails; obj->callbacks.free = &free_local_mails; END OBJ(draft_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_draft_mails; obj->callbacks.free = &free_local_mails; END OBJ(trashed_mails, 0) parse_local_mail_args(obj, arg); obj->callbacks.print = &print_trashed_mails; obj->callbacks.free = &free_local_mails; END OBJ(mboxscan, 0) parse_mboxscan_arg(obj, arg); obj->callbacks.print = &print_mboxscan; obj->callbacks.free = &free_mboxscan; END OBJ(mem, &update_meminfo) obj->callbacks.print = &print_mem; END OBJ(memwithbuffers, &update_meminfo) obj->callbacks.print = &print_memwithbuffers; END OBJ(memeasyfree, &update_meminfo) obj->callbacks.print = &print_memeasyfree; END OBJ(memfree, &update_meminfo) obj->callbacks.print = &print_memfree; END OBJ(memmax, &update_meminfo) obj->callbacks.print = &print_memmax; END OBJ(memperc, &update_meminfo) obj->callbacks.percentage = &mem_percentage; #ifdef __linux__ END OBJ(memdirty, &update_meminfo) obj->callbacks.print = &print_memdirty; #endif #ifdef BUILD_X11 END OBJ(memgauge, &update_meminfo) scan_gauge(obj, arg, 1); obj->callbacks.gaugeval = &mem_barval; #endif END OBJ(membar, &update_meminfo) scan_bar(obj, arg, 1); obj->callbacks.barval = &mem_barval; END OBJ(memwithbuffersbar, &update_meminfo) scan_bar(obj, arg, 1); obj->callbacks.barval = &mem_with_buffers_barval; #ifdef BUILD_X11 END OBJ(memgraph, &update_meminfo) char *buf = 0; buf = scan_graph(obj, arg, 1); free_and_zero(buf); obj->callbacks.graphval = &mem_barval; #endif /* BUILD_X11*/ END OBJ(mixer, 0) parse_mixer_arg(obj, arg); obj->callbacks.percentage = &mixer_percentage; END OBJ(mixerl, 0) parse_mixer_arg(obj, arg); obj->callbacks.percentage = &mixerl_percentage; END OBJ(mixerr, 0) parse_mixer_arg(obj, arg); obj->callbacks.percentage = &mixerr_percentage; END OBJ(mixerbar, 0) scan_mixer_bar(obj, arg); obj->callbacks.barval = &mixer_barval; END OBJ(mixerlbar, 0) scan_mixer_bar(obj, arg); obj->callbacks.barval = &mixerl_barval; END OBJ(mixerrbar, 0) scan_mixer_bar(obj, arg); obj->callbacks.barval = &mixerr_barval; END OBJ_IF(if_mixer_mute, 0) parse_mixer_arg(obj, arg); obj->callbacks.iftest = &check_mixer_muted; #ifdef BUILD_X11 END OBJ(monitor, 0) obj->callbacks.print = &print_monitor; END OBJ(monitor_number, 0) obj->callbacks.print = &print_monitor_number; END OBJ(desktop, 0) obj->callbacks.print = &print_desktop; END OBJ(desktop_number, 0) obj->callbacks.print = &print_desktop_number; END OBJ(desktop_name, 0) obj->callbacks.print = &print_desktop_name; #endif /* BUILD_X11 */ END OBJ_ARG(format_time, 0, "format_time needs a pid as argument") obj->sub = (text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, arg); obj->callbacks.print = &print_format_time; END OBJ(nodename, 0) obj->callbacks.print = &print_nodename; END OBJ(nodename_short, 0) obj->callbacks.print = &print_nodename_short; END OBJ_ARG(cmdline_to_pid, 0, "cmdline_to_pid needs a command line as argument") scan_cmdline_to_pid_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_cmdline_to_pid; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(pid_chroot, 0, "pid_chroot needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_chroot; END OBJ_ARG(pid_cmdline, 0, "pid_cmdline needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_cmdline; END OBJ_ARG(pid_cwd, 0, "pid_cwd needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_cwd; END OBJ_ARG(pid_environ, 0, "pid_environ needs arguments") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_environ; END OBJ_ARG(pid_environ_list, 0, "pid_environ_list needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_environ_list; END OBJ_ARG(pid_exe, 0, "pid_exe needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_exe; END OBJ_ARG(pid_nice, 0, "pid_nice needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_nice; END OBJ_ARG(pid_openfiles, 0, "pid_openfiles needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_openfiles; END OBJ_ARG(pid_parent, 0, "pid_parent needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_parent; END OBJ_ARG(pid_priority, 0, "pid_priority needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_priority; END OBJ_ARG(pid_state, 0, "pid_state needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_state; END OBJ_ARG(pid_state_short, 0, "pid_state_short needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_state_short; END OBJ_ARG(pid_stderr, 0, "pid_stderr needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_stderr; END OBJ_ARG(pid_stdin, 0, "pid_stdin needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_stdin; END OBJ_ARG(pid_stdout, 0, "pid_stdout needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_stdout; END OBJ_ARG(pid_threads, 0, "pid_threads needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_threads; END OBJ_ARG(pid_thread_list, 0, "pid_thread_list needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_thread_list; END OBJ_ARG(pid_time_kernelmode, 0, "pid_time_kernelmode needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_time_kernelmode; END OBJ_ARG(pid_time_usermode, 0, "pid_time_usermode needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_time_usermode; END OBJ_ARG(pid_time, 0, "pid_time needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_time; END OBJ_ARG(pid_uid, 0, "pid_uid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_uid; END OBJ_ARG(pid_euid, 0, "pid_euid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_euid; END OBJ_ARG(pid_suid, 0, "pid_suid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_suid; END OBJ_ARG(pid_fsuid, 0, "pid_fsuid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_fsuid; END OBJ_ARG(pid_gid, 0, "pid_gid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_gid; END OBJ_ARG(pid_egid, 0, "pid_egid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_egid; END OBJ_ARG(pid_sgid, 0, "pid_sgid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_sgid; END OBJ_ARG(pid_fsgid, 0, "pid_fsgid needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_fsgid; END OBJ_ARG(gid_name, 0, "gid_name needs a gid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_gid_name; END OBJ_ARG(uid_name, 0, "uid_name needs a uid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_uid_name; END OBJ_ARG(pid_read, 0, "pid_read needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_read; END OBJ_ARG(pid_vmpeak, 0, "pid_vmpeak needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmpeak; END OBJ_ARG(pid_vmsize, 0, "pid_vmsize needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmsize; END OBJ_ARG(pid_vmlck, 0, "pid_vmlck needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmlck; END OBJ_ARG(pid_vmhwm, 0, "pid_vmhwm needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmhwm; END OBJ_ARG(pid_vmrss, 0, "pid_vmrss needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmrss; END OBJ_ARG(pid_vmdata, 0, "pid_vmdata needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmdata; END OBJ_ARG(pid_vmstk, 0, "pid_vmstk needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmstk; END OBJ_ARG(pid_vmexe, 0, "pid_vmexe needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmexe; END OBJ_ARG(pid_vmlib, 0, "pid_vmlib needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmlib; END OBJ_ARG(pid_vmpte, 0, "pid_vmpte needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmpte; END OBJ_ARG(pid_write, 0, "pid_write needs a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_write; #ifdef __DragonFly__ END OBJ(processes, &update_top) #else END OBJ(processes, &update_total_processes) #endif obj->callbacks.print = &print_processes; #ifdef __linux__ END OBJ(distribution, 0) obj->callbacks.print = &print_distribution; END OBJ(running_processes, &update_top) top_running = 1; obj->callbacks.print = &print_running_processes; END OBJ(threads, &update_threads) obj->callbacks.print = &print_threads; END OBJ(running_threads, &update_stat) obj->callbacks.print = &print_running_threads; #else #if defined(__DragonFly__) END OBJ(running_processes, &update_top) obj->callbacks.print = &print_running_processes; #else END OBJ(running_processes, &update_running_processes) obj->callbacks.print = &print_running_processes; #endif #endif /* __linux__ */ END OBJ(shadecolor, 0) #ifdef BUILD_X11 obj->data.l = arg ? get_x11_color(arg) : default_shade_color.get(*state); obj->callbacks.print = &new_bg; #endif /* BUILD_X11 */ END OBJ(outlinecolor, 0) #ifdef BUILD_X11 obj->data.l = arg ? get_x11_color(arg) : default_outline_color.get(*state); obj->callbacks.print = &new_outline; #endif /* BUILD_X11 */ END OBJ(stippled_hr, 0) #ifdef BUILD_X11 scan_stippled_hr(obj, arg); obj->callbacks.print = &new_stippled_hr; #endif /* BUILD_X11 */ END OBJ(swap, &update_meminfo) obj->callbacks.print = &print_swap; END OBJ(swapfree, &update_meminfo) obj->callbacks.print = &print_swapfree; END OBJ(swapmax, &update_meminfo) obj->callbacks.print = &print_swapmax; END OBJ(swapperc, &update_meminfo) obj->callbacks.percentage = &swap_percentage; END OBJ(swapbar, &update_meminfo) scan_bar(obj, arg, 1); obj->callbacks.barval = &swap_barval; /* XXX: swapgraph, swapgauge? */ END OBJ(sysname, 0) obj->callbacks.print = &print_sysname; END OBJ(time, 0) scan_time(obj, arg); obj->callbacks.print = &print_time; obj->callbacks.free = &free_time; END OBJ(utime, 0) scan_time(obj, arg); obj->callbacks.print = &print_utime; obj->callbacks.free = &free_time; END OBJ(tztime, 0) 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); obj->callbacks.print = &print_iconv_start; obj->callbacks.free = &free_iconv; END OBJ(iconv_stop, 0) init_iconv_stop(); obj->callbacks.print = &print_iconv_stop; #endif END OBJ(totaldown, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_totaldown; END OBJ(totalup, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_totalup; END OBJ(updates, 0) obj->callbacks.print = &print_updates; END OBJ_IF(if_updatenr, 0) obj->data.i = arg ? atoi(arg) : 0; if(obj->data.i == 0) CRIT_ERR(obj, free_at_crash, "if_updatenr needs a number above 0 as argument"); set_updatereset(obj->data.i > get_updatereset() ? obj->data.i : get_updatereset()); obj->callbacks.iftest = &updatenr_iftest; END OBJ(alignr, 0) obj->data.l = arg ? atoi(arg) : 1; obj->callbacks.print = &new_alignr; END OBJ(alignc, 0) obj->data.l = arg ? atoi(arg) : 0; obj->callbacks.print = &new_alignc; END OBJ(upspeed, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_upspeed; END OBJ(upspeedf, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_upspeedf; #ifdef BUILD_X11 END OBJ(upspeedgraph, &update_net_stats) parse_net_stat_graph_arg(obj, arg, free_at_crash); obj->callbacks.graphval = &upspeedgraphval; #endif END OBJ(uptime_short, &update_uptime) obj->callbacks.print = &print_uptime_short; END OBJ(uptime, &update_uptime) obj->callbacks.print = &print_uptime; #if defined(__linux__) END OBJ(user_names, &update_users) obj->callbacks.print = &print_user_names; obj->callbacks.free = &free_user_names; END OBJ(user_times, &update_users) obj->callbacks.print = &print_user_times; obj->callbacks.free = &free_user_times; END OBJ_ARG(user_time, 0, "user time needs a console name as argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_user_time; obj->callbacks.free = &free_user_time; END OBJ(user_terms, &update_users) obj->callbacks.print = &print_user_terms; obj->callbacks.free = &free_user_terms; END OBJ(user_number, &update_users) obj->callbacks.print = &print_user_number; END OBJ(gw_iface, &update_gateway_info) obj->callbacks.print = &print_gateway_iface; obj->callbacks.free = &free_gateway_info; END OBJ(gw_ip, &update_gateway_info) obj->callbacks.print = &print_gateway_ip; obj->callbacks.free = &free_gateway_info; #endif /* !__linux__ */ #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ || defined(__DragonFly__) \ || defined(__OpenBSD__)) && (defined(i386) || defined(__i386__)) END OBJ(apm_adapter, 0) obj->callbacks.print = &print_apm_adapter; END OBJ(apm_battery_life, 0) obj->callbacks.print = &print_apm_battery_life; END OBJ(apm_battery_time, 0) obj->callbacks.print = &print_apm_battery_time; #endif /* __FreeBSD__ */ END OBJ(imap_unseen, 0) parse_imap_mail_args(obj, arg); obj->callbacks.print = &print_imap_unseen; obj->callbacks.free = &free_mail_obj; END OBJ(imap_messages, 0) parse_imap_mail_args(obj, arg); obj->callbacks.print = &print_imap_messages; obj->callbacks.free = &free_mail_obj; END OBJ(pop3_unseen, 0) parse_pop3_mail_args(obj, arg); obj->callbacks.print = &print_pop3_unseen; obj->callbacks.free = &free_mail_obj; END OBJ(pop3_used, 0) parse_pop3_mail_args(obj, arg); obj->callbacks.print = &print_pop3_used; obj->callbacks.free = &free_mail_obj; #ifdef BUILD_IBM END OBJ_ARG(smapi, 0, "smapi needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_smapi; obj->callbacks.free = &gen_free_opaque; END OBJ_IF_ARG(if_smapi_bat_installed, 0, "if_smapi_bat_installed needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.iftest = &smapi_bat_installed; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(smapi_bat_perc, 0, "smapi_bat_perc needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.percentage = &smapi_bat_percentage; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(smapi_bat_temp, 0, "smapi_bat_temp needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_smapi_bat_temp; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(smapi_bat_power, 0, "smapi_bat_power needs an argument") obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_smapi_bat_power; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(smapi_bat_bar, 0, "smapi_bat_bar needs an argument") int cnt; if(sscanf(arg, "%i %n", &obj->data.i, &cnt) <= 0) { NORM_ERR("first argument to smapi_bat_bar must be an integer value"); obj->data.i = -1; } else arg = scan_bar(obj, arg + cnt, 100); obj->callbacks.barval = &smapi_bat_barval; #endif /* BUILD_IBM */ #ifdef BUILD_MPD #define mpd_set_maxlen(name) \ if (arg) { \ int i; \ sscanf(arg, "%d", &i); \ if (i > 0) \ obj->data.i = i + 1; \ else \ NORM_ERR(#name ": invalid length argument"); \ } END OBJ(mpd_artist, 0) mpd_set_maxlen(mpd_artist); obj->callbacks.print = &print_mpd_artist; END OBJ(mpd_albumartist, 0) mpd_set_maxlen(mpd_albumartist); obj->callbacks.print = &print_mpd_albumartist; END OBJ(mpd_title, 0) mpd_set_maxlen(mpd_title); obj->callbacks.print = &print_mpd_title; END OBJ(mpd_date, 0) mpd_set_maxlen(mpd_date); obj->callbacks.print = &print_mpd_date; END OBJ(mpd_random, 0) obj->callbacks.print = &print_mpd_random; END OBJ(mpd_repeat, 0) obj->callbacks.print = &print_mpd_repeat; END OBJ(mpd_elapsed, 0) obj->callbacks.print = &print_mpd_elapsed; END OBJ(mpd_length, 0) obj->callbacks.print = &print_mpd_length; END OBJ(mpd_track, 0) mpd_set_maxlen(mpd_track); obj->callbacks.print = &print_mpd_track; END OBJ(mpd_name, 0) mpd_set_maxlen(mpd_name); obj->callbacks.print = &print_mpd_name; END OBJ(mpd_file, 0) mpd_set_maxlen(mpd_file); obj->callbacks.print = &print_mpd_file; END OBJ(mpd_percent, 0) obj->callbacks.percentage = &mpd_percentage; END OBJ(mpd_album, 0) mpd_set_maxlen(mpd_album); obj->callbacks.print = &print_mpd_album; END OBJ(mpd_vol, 0) obj->callbacks.print = &print_mpd_vol; END OBJ(mpd_bitrate, 0) obj->callbacks.print = &print_mpd_bitrate; END OBJ(mpd_status, 0) obj->callbacks.print = &print_mpd_status; END OBJ(mpd_bar, 0) scan_bar(obj, arg, 1); obj->callbacks.barval = &mpd_barval; END OBJ(mpd_smart, 0) mpd_set_maxlen(mpd_smart); obj->callbacks.print = &print_mpd_smart; END OBJ_IF(if_mpd_playing, 0) obj->callbacks.iftest = &check_mpd_playing; #undef mpd_set_maxlen #endif /* BUILD_MPD */ #ifdef BUILD_MOC END OBJ(moc_state, 0) obj->callbacks.print = &print_moc_state; END OBJ(moc_file, 0) obj->callbacks.print = &print_moc_file; END OBJ(moc_title, 0) obj->callbacks.print = &print_moc_title; END OBJ(moc_artist, 0) obj->callbacks.print = &print_moc_artist; END OBJ(moc_song, 0) obj->callbacks.print = &print_moc_song; END OBJ(moc_album, 0) obj->callbacks.print = &print_moc_album; END OBJ(moc_totaltime, 0) obj->callbacks.print = &print_moc_totaltime; END OBJ(moc_timeleft, 0) obj->callbacks.print = &print_moc_timeleft; END OBJ(moc_curtime, 0) obj->callbacks.print = &print_moc_curtime; END OBJ(moc_bitrate, 0) obj->callbacks.print = &print_moc_bitrate; END OBJ(moc_rate, 0) obj->callbacks.print = &print_moc_rate; #endif /* BUILD_MOC */ #ifdef BUILD_CMUS END OBJ(cmus_state, 0) obj->callbacks.print = &print_cmus_state; END OBJ(cmus_file, 0) obj->callbacks.print = &print_cmus_file; END OBJ(cmus_title, 0) obj->callbacks.print = &print_cmus_title; END OBJ(cmus_artist, 0) obj->callbacks.print = &print_cmus_artist; END OBJ(cmus_album, 0) obj->callbacks.print = &print_cmus_album; END OBJ(cmus_totaltime, 0) obj->callbacks.print = &print_cmus_totaltime; END OBJ(cmus_timeleft, 0) obj->callbacks.print = &print_cmus_timeleft; END OBJ(cmus_curtime, 0) obj->callbacks.print = &print_cmus_curtime; END OBJ(cmus_random, 0) obj->callbacks.print = &print_cmus_random; END OBJ(cmus_state, 0) obj->callbacks.print = &print_cmus_state; END OBJ(cmus_file, 0) obj->callbacks.print = &print_cmus_file; END OBJ(cmus_title, 0) obj->callbacks.print = &print_cmus_title; END OBJ(cmus_artist, 0) obj->callbacks.print = &print_cmus_artist; END OBJ(cmus_album, 0) obj->callbacks.print = &print_cmus_album; END OBJ(cmus_totaltime, 0) obj->callbacks.print = &print_cmus_totaltime; END OBJ(cmus_timeleft, 0) obj->callbacks.print = &print_cmus_timeleft; END OBJ(cmus_curtime, 0) obj->callbacks.print = &print_cmus_curtime; END OBJ(cmus_random, 0) obj->callbacks.print = &print_cmus_random; END OBJ(cmus_repeat, 0) obj->callbacks.print = &print_cmus_repeat; END OBJ(cmus_aaa, 0) obj->callbacks.print = &print_cmus_aaa; END OBJ(cmus_track, 0) obj->callbacks.print = &print_cmus_track; END OBJ(cmus_genre, 0) obj->callbacks.print = &print_cmus_genre; END OBJ(cmus_date, 0) obj->callbacks.print = &print_cmus_date; END OBJ(cmus_progress, 0) scan_bar(obj, arg, 1); obj->callbacks.barval = &cmus_progress; END OBJ(cmus_percent, 0) obj->callbacks.percentage = &cmus_percent; #endif /* BUILD_CMUS */ #ifdef BUILD_XMMS2 END OBJ(xmms2_artist, &update_xmms2) obj->callbacks.print = &print_xmms2_artist; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_album, &update_xmms2) obj->callbacks.print = &print_xmms2_album; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_title, &update_xmms2) obj->callbacks.print = &print_xmms2_title; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_genre, &update_xmms2) obj->callbacks.print = &print_xmms2_genre; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_comment, &update_xmms2) obj->callbacks.print = &print_xmms2_comment; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_url, &update_xmms2) obj->callbacks.print = &print_xmms2_url; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_tracknr, &update_xmms2) obj->callbacks.print = &print_xmms2_tracknr; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_bitrate, &update_xmms2) obj->callbacks.print = &print_xmms2_bitrate; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_date, &update_xmms2) obj->callbacks.print = &print_xmms2_date; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_id, &update_xmms2) obj->callbacks.print = &print_xmms2_id; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_duration, &update_xmms2) obj->callbacks.print = &print_xmms2_duration; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_elapsed, &update_xmms2) obj->callbacks.print = &print_xmms2_elapsed; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_size, &update_xmms2) obj->callbacks.print = &print_xmms2_size; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_status, &update_xmms2) obj->callbacks.print = &print_xmms2_status; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_percent, &update_xmms2) obj->callbacks.print = &print_xmms2_percent; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_bar, &update_xmms2) scan_bar(obj, arg, 1); obj->callbacks.barval = &xmms2_barval; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_smart, &update_xmms2) obj->callbacks.print = &print_xmms2_smart; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_playlist, &update_xmms2) obj->callbacks.print = &print_xmms2_playlist; obj->callbacks.free = &free_xmms2; END OBJ(xmms2_timesplayed, &update_xmms2) obj->callbacks.print = &print_xmms2_timesplayed; obj->callbacks.free = &free_xmms2; END OBJ_IF(if_xmms2_connected, &update_xmms2) obj->callbacks.iftest = &if_xmms2_connected; obj->callbacks.free = &free_xmms2; #endif /* BUILD_XMMS2 */ #ifdef BUILD_AUDACIOUS END OBJ(audacious_status, 0) obj->callbacks.print = &print_audacious_status; END OBJ_ARG(audacious_title, 0, "audacious_title needs an argument") sscanf(arg, "%d", &obj->data.i); if (obj->data.i > 0) { ++ obj->data.i; } else { CRIT_ERR(obj, free_at_crash, "audacious_title: invalid length argument"); } obj->callbacks.print = &print_audacious_title; END OBJ(audacious_length, 0) obj->callbacks.print = &print_audacious_length; END OBJ(audacious_length_seconds, 0) obj->callbacks.print = &print_audacious_length_seconds; END OBJ(audacious_position, 0) obj->callbacks.print = &print_audacious_position; END OBJ(audacious_position_seconds, 0) obj->callbacks.print = &print_audacious_position_seconds; END OBJ(audacious_bitrate, 0) obj->callbacks.print = &print_audacious_bitrate; END OBJ(audacious_frequency, 0) obj->callbacks.print = &print_audacious_frequency; END OBJ(audacious_channels, 0) obj->callbacks.print = &print_audacious_channels; END OBJ(audacious_filename, 0) obj->callbacks.print = &print_audacious_filename; END OBJ(audacious_playlist_length, 0) obj->callbacks.print = &print_audacious_playlist_length; END OBJ(audacious_playlist_position, 0) obj->callbacks.print = &print_audacious_playlist_position; END OBJ(audacious_main_volume, 0) obj->callbacks.print = &print_audacious_main_volume; END OBJ(audacious_bar, 0) scan_bar(obj, arg, 1); obj->callbacks.barval = &audacious_barval; #endif /* BUILD_AUDACIOUS */ #ifdef BUIL_BMPX END OBJ(bmpx_title, &update_bmpx) obj->callbacks.print = &print_bmpx_title; END OBJ(bmpx_artist, &update_bmpx) obj->callbacks.print = &print_bmpx_artist; END OBJ(bmpx_album, &update_bmpx) obj->callbacks.print = &print_bmpx_album; END OBJ(bmpx_track, &update_bmpx) obj->callbacks.print = &print_bmpx_track; END OBJ(bmpx_uri, &update_bmpx) obj->callbacks.print = &print_bmpx_uri; END OBJ(bmpx_bitrate, &update_bmpx) obj->callbacks.print = &print_bmpx_bitrate; #endif /* BUILD_BMPX */ #ifdef BUILD_EVE END OBJ_ARG(eve, 0, "eve needs arguments: ") scan_eve(obj, arg); obj->callbacks.print = &print_eve; obj->callbacks.free = &free_eve; #endif /* BUILD_EVE */ #ifdef BUILD_CURL END OBJ_ARG(curl, 0, "curl needs arguments: ") curl_parse_arg(obj, arg); obj->callbacks.print = &curl_print; obj->callbacks.free = &curl_obj_free; #endif /* BUILD_CURL */ #ifdef BUILD_RSS END OBJ_ARG(rss, 0, "rss needs arguments: [act_par] [spaces in front]") rss_scan_arg(obj, arg); obj->callbacks.print = &rss_print_info; obj->callbacks.free = &rss_free_obj_info; #endif /* BUILD_RSS */ #ifdef BUILD_WEATHER_METAR END OBJ_ARG(weather, 0, "weather needs arguments: [interval in minutes]") scan_weather_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_weather; obj->callbacks.free = &free_weather; #endif /* BUILD_WEATHER_METAR */ #ifdef BUILD_WEATHER_XOAP END OBJ_ARG(weather_forecast, 0, "weather_forecast needs arguments: [interval in minutes]") scan_weather_forecast_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_weather_forecast; obj->callbacks.free = &free_weather; #endif /* BUILD_WEATHER_XOAP */ END OBJ_ARG(lua, 0, "lua needs arguments: [function parameters]") obj->data.s = strndup(arg, text_buffer_size.get(*state)); 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.get(*state)); obj->callbacks.print = &print_lua_parse; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(lua_bar, 0, "lua_bar needs arguments: , [function parameters]") arg = scan_bar(obj, arg, 100); if(arg) { obj->data.s = strndup(arg, text_buffer_size.get(*state)); } else { CRIT_ERR(obj, free_at_crash, "lua_bar needs arguments: , [function parameters]"); } obj->callbacks.barval = &lua_barval; obj->callbacks.free = &gen_free_opaque; #ifdef BUILD_X11 END OBJ_ARG(lua_graph, 0, "lua_graph needs arguments: [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]") char *buf = 0; buf = scan_graph(obj, arg, 100); if (buf) { obj->data.s = buf; } else { CRIT_ERR(obj, free_at_crash, "lua_graph needs arguments: [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]"); } obj->callbacks.graphval = &lua_barval; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(lua_gauge, 0, "lua_gauge needs arguments: , [function parameters]") arg = scan_gauge(obj, arg, 100); if (arg) { obj->data.s = strndup(arg, text_buffer_size.get(*state)); } else { CRIT_ERR(obj, free_at_crash, "lua_gauge needs arguments: , [function parameters]"); } obj->callbacks.gaugeval = &lua_barval; obj->callbacks.free = &gen_free_opaque; #endif /* BUILD_X11 */ #ifdef BUILD_HDDTEMP END OBJ(hddtemp, &update_hddtemp) if (arg) obj->data.s = strndup(arg, text_buffer_size.get(*state)); obj->callbacks.print = &print_hddtemp; obj->callbacks.free = &free_hddtemp; #endif /* BUILD_HDDTEMP */ #ifdef BUILD_PORT_MONITORS END OBJ_ARG(tcp_portmon, &tcp_portmon_update, "tcp_portmon: needs arguments") tcp_portmon_init(obj, arg); obj->callbacks.print = &tcp_portmon_action; obj->callbacks.free = &tcp_portmon_free; #endif /* BUILD_PORT_MONITORS */ END OBJ(entropy_avail, &update_entropy) obj->callbacks.print = &print_entropy_avail; END OBJ(entropy_perc, &update_entropy) obj->callbacks.percentage = &entropy_percentage; END OBJ(entropy_poolsize, &update_entropy) obj->callbacks.print = &print_entropy_poolsize; END OBJ(entropy_bar, &update_entropy) scan_bar(obj, arg, 1); obj->callbacks.barval = &entropy_barval; END OBJ_ARG(blink, 0, "blink needs a argument") obj->sub = (text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, arg); obj->callbacks.print = &print_blink; END OBJ_ARG(to_bytes, 0, "to_bytes needs a argument") obj->sub = (text_object*)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, arg); obj->callbacks.print = &print_to_bytes; #ifdef BUILD_CURL END OBJ_ARG(stock, 0, "stock needs arguments") stock_parse_arg(obj, arg); obj->callbacks.print = &print_stock; obj->callbacks.free = &free_stock; #endif /* BUILD_CURL */ END OBJ(scroll, 0) #ifdef BUILD_X11 /* allocate a follower to reset any color changes */ #endif /* BUILD_X11 */ parse_scroll_arg(obj, arg, free_at_crash, s); obj->callbacks.print = &print_scroll; obj->callbacks.free = &free_scroll; END OBJ(combine, 0) try { parse_combine_arg(obj, arg); } catch(combine_needs_2_args_error &e) { free(obj); throw obj_create_error(e.what()); } obj->callbacks.print = &print_combine; obj->callbacks.free = &free_combine; #ifdef BUILD_NVIDIA END OBJ_ARG(nvidia, 0, "nvidia needs an argument") if (set_nvidia_type(obj, arg)) { CRIT_ERR(obj, free_at_crash, "nvidia: invalid argument" " specified: '%s'\n", arg); } obj->callbacks.print = &print_nvidia_value; obj->callbacks.free = &free_nvidia; #endif /* BUILD_NVIDIA */ #ifdef BUILD_APCUPSD END OBJ_ARG(apcupsd, &update_apcupsd, "apcupsd needs arguments: ") if (apcupsd_scan_arg(arg)) { CRIT_ERR(obj, free_at_crash, "apcupsd needs arguments: "); } obj->callbacks.print = &gen_print_nothing; END OBJ(apcupsd_name, &update_apcupsd) obj->callbacks.print = &print_apcupsd_name; END OBJ(apcupsd_model, &update_apcupsd) obj->callbacks.print = &print_apcupsd_model; END OBJ(apcupsd_upsmode, &update_apcupsd) obj->callbacks.print = &print_apcupsd_upsmode; END OBJ(apcupsd_cable, &update_apcupsd) obj->callbacks.print = &print_apcupsd_cable; END OBJ(apcupsd_status, &update_apcupsd) obj->callbacks.print = &print_apcupsd_status; END OBJ(apcupsd_linev, &update_apcupsd) obj->callbacks.print = &print_apcupsd_linev; END OBJ(apcupsd_load, &update_apcupsd) obj->callbacks.print = &print_apcupsd_load; END OBJ(apcupsd_loadbar, &update_apcupsd) scan_bar(obj, arg, 100); obj->callbacks.barval = &apcupsd_loadbarval; #ifdef BUILD_X11 END OBJ(apcupsd_loadgraph, &update_apcupsd) char* buf = 0; buf = scan_graph(obj, arg, 100); free_and_zero(buf); obj->callbacks.graphval = &apcupsd_loadbarval; END OBJ(apcupsd_loadgauge, &update_apcupsd) scan_gauge(obj, arg, 100); obj->callbacks.gaugeval = &apcupsd_loadbarval; #endif /* BUILD_X11 */ END OBJ(apcupsd_charge, &update_apcupsd) obj->callbacks.print = &print_apcupsd_charge; END OBJ(apcupsd_timeleft, &update_apcupsd) obj->callbacks.print = &print_apcupsd_timeleft; END OBJ(apcupsd_temp, &update_apcupsd) obj->callbacks.print = &print_apcupsd_temp; END OBJ(apcupsd_lastxfer, &update_apcupsd) obj->callbacks.print = &print_apcupsd_lastxfer; #endif /* BUILD_APCUPSD */ END { char *buf = (char *)malloc(text_buffer_size.get(*state)); NORM_ERR("unknown variable '$%s'", s); snprintf(buf, text_buffer_size.get(*state), "${%s}", s); obj_be_plain_text(obj, buf); free(buf); } #undef OBJ #undef OBJ_IF #undef OBJ_ARG #undef OBJ_IF_ARG #undef __OBJ_HEAD #undef __OBJ_IF #undef __OBJ_ARG #undef END return obj; } /* * - assumes that *string is '#' * - removes the part from '#' to the end of line ('\n' or '\0') * - it removes the '\n' * - copies the last char into 'char *last' argument, which should be a pointer * to a char rather than a string. */ static size_t remove_comment(char *string, char *last) { char *end = string; while (*end != '\0' && *end != '\n') { ++end; } if (last) *last = *end; if (*end == '\n') end++; strfold(string, end - string); return end - string; } size_t remove_comments(char *string) { char *curplace; size_t folded = 0; for (curplace = string; *curplace != 0; curplace++) { if (*curplace == '\\' && *(curplace + 1) == '#') { // strcpy can't be used for overlapping strings strfold(curplace, 1); folded += 1; } else if (*curplace == '#') { folded += remove_comment(curplace, 0); } } return folded; } int extract_variable_text_internal(struct text_object *retval, const char *const_p) { struct text_object *obj; char *p, *s, *orig_p; long line; void *ifblock_opaque = NULL; char *tmp_p; char *arg = 0; size_t len = 0; p = strndup(const_p, max_user_text.get(*state) - 1); while (text_contains_templates(p)) { char *tmp; tmp = find_and_replace_templates(p); free(p); p = tmp; } s = orig_p = p; if (strcmp(p, const_p)) { DBGP2("replaced all templates in text: input is\n'%s'\noutput is\n'%s'", const_p, p); } else { DBGP2("no templates to replace"); } memset(retval, 0, sizeof(struct text_object)); line = global_text_lines; while (*p) { if (*p == '\n') { line++; } if (*p == '$') { *p = '\0'; obj = create_plain_text(s); if (obj != NULL) { append_object(retval, obj); } *p = '$'; p++; s = p; if (*p != '$') { char *buf = (char *)malloc(text_buffer_size.get(*state)); const char *var; /* variable is either $foo or ${foo} */ if (*p == '{') { unsigned int brl = 1, brr = 0; p++; s = p; while (*p && brl != brr) { if (*p == '{') { brl++; } if (*p == '}') { brr++; } p++; } p--; } else { s = p; if (*p == '#') { p++; } while (*p && (isalnum((int) *p) || *p == '_')) { p++; } } /* copy variable to buffer */ len = (p - s > (int)text_buffer_size.get(*state)-1) ? (int)text_buffer_size.get(*state)-1 : (p - s); strncpy(buf, s, len); buf[len] = '\0'; if (*p == '}') { p++; } s = p; /* search for variable in environment */ var = getenv(buf); if (var) { obj = create_plain_text(var); if (obj) { append_object(retval, obj); } free(buf); continue; } /* if variable wasn't found in environment, use some special */ arg = 0; /* split arg */ if (strchr(buf, ' ')) { arg = strchr(buf, ' '); *arg = '\0'; arg++; while (isspace((int) *arg)) { arg++; } if (!*arg) { arg = 0; } } /* lowercase variable name */ tmp_p = buf; while (*tmp_p) { *tmp_p = tolower(*tmp_p); tmp_p++; } try { obj = construct_text_object(buf, arg, line, &ifblock_opaque, orig_p); } catch(obj_create_error &e) { free(buf); free(orig_p); throw e; } if (obj != NULL) { append_object(retval, obj); } free(buf); continue; } else { obj = create_plain_text("$"); s = p + 1; if (obj != NULL) { append_object(retval, obj); } } } else if (*p == '\\' && *(p+1) == '#') { strfold(p, 1); } else if (*p == '#') { char c; if (remove_comment(p, &c) && p >= orig_p && c == '\n') { /* if remove_comment removed a newline, we need to 'back up' with p */ p--; } } p++; } obj = create_plain_text(s); if (obj != NULL) { append_object(retval, obj); } if (!ifblock_stack_empty(&ifblock_opaque)) { NORM_ERR("one or more $endif's are missing"); } free(orig_p); return 0; } void extract_object_args_to_sub(struct text_object *obj, const char *args) { obj->sub = (struct text_object *)malloc(sizeof(struct text_object)); memset(obj->sub, 0, sizeof(struct text_object)); extract_variable_text_internal(obj->sub, args); } /* Frees the list of text objects root points to. */ void free_text_objects(struct text_object *root) { struct text_object *obj; if(root && root->prev) { for (obj = root->prev; obj; obj = root->prev) { root->prev = obj->prev; if (obj->callbacks.free) { (*obj->callbacks.free)(obj); } free_text_objects(obj->sub); free_and_zero(obj->sub); free_and_zero(obj->special_data); delete obj->cb_handle; free(obj); } } } conky-1.10.1/src/core.h000066400000000000000000000031141262311664100146060ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _CONKY_CORE_H_ #define _CONKY_CORE_H_ #include "conky.h" struct text_object *construct_text_object(const char *s, const char *arg, long line, void **ifblock_opaque, void *free_at_crash); size_t remove_comments(char *string); int extract_variable_text_internal(struct text_object *retval, const char *const_p); void free_text_objects(struct text_object *root); const char *dev_name(const char *); #endif /* _CONKY_CORE_H_ */ conky-1.10.1/src/data-source.cc000066400000000000000000000117251262311664100162320ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 "data-source.hh" #include #include #include namespace conky { namespace { /* * Returned when there is no data available. * An alternative would be to throw an exception, but if we don't want to react too * aggresively when the user e.g. uses a nonexisting variable, then returning NaN will do * just fine. */ float NaN = std::numeric_limits::quiet_NaN(); typedef std::unordered_map data_sources_t; /* * We cannot construct this object statically, because order of object construction in * different modules is not defined, so register_source could be called before this * object is constructed. Therefore, we create it on the first call to register_source. */ data_sources_t *data_sources; data_source_base& get_data_source(lua::state *l) { if(l->gettop() != 1) throw std::runtime_error("Wrong number of parameters"); l->rawgetfield(lua::REGISTRYINDEX, priv::data_source_metatable); if(not l->getmetatable(-2) or not l->rawequal(-1, -2)) throw std::runtime_error("Invalid parameter"); return *static_cast(l->touserdata(1)); } int data_source_asnumber(lua::state *l) { double x = get_data_source(l).get_number(); l->pushnumber(x); return 1; } int data_source_astext(lua::state *l) { std::string x = get_data_source(l).get_text(); l->pushstring(x); return 1; } const char data_source__index[] = "local table, key = ...;\n" "if key == 'num' then\n" " return conky.asnumber(table);\n" "elseif key == 'text' then\n" " return conky.astext(table);\n" "else\n" " print(string.format([[Invalid data source operation: '%s']], key));\n" " return 0/0;\n" "end\n"; } namespace priv { void do_register_data_source(const std::string &name, const lua::cpp_function &fn) { struct data_source_constructor { data_source_constructor() { data_sources = new data_sources_t(); } ~data_source_constructor() { delete data_sources; data_sources = NULL; } }; static data_source_constructor constructor; bool inserted = data_sources->insert({name, fn}).second; if(not inserted) throw std::logic_error("Data source with name '" + name + "' already registered"); } disabled_data_source::disabled_data_source(lua::state *l, const std::string &name, const std::string &setting) : simple_numeric_source(l, name, &NaN) { // XXX some generic way of reporting errors? NORM_ERR? std::cerr << "Support for variable '" << name << "' has been disabled during compilation. Please recompile with '" << setting << "'" << std::endl; } } double data_source_base::get_number() const { return NaN; } std::string data_source_base::get_text() const { std::ostringstream s; s << get_number(); return s.str(); } register_disabled_data_source::register_disabled_data_source(const std::string &name, const std::string &setting) : register_data_source(name, setting) {} // at least one data source should always be registered, so data_sources will not be null void export_data_sources(lua::state &l) { lua::stack_sentry s(l); l.checkstack(2); l.newmetatable(priv::data_source_metatable); { l.pushboolean(false); l.rawsetfield(-2, "__metatable"); l.pushdestructor(); l.rawsetfield(-2, "__gc"); l.loadstring(data_source__index); l.rawsetfield(-2, "__index"); } l.pop(); l.newtable(); { for(auto i = data_sources->begin(); i != data_sources->end(); ++i) { l.pushfunction(i->second); l.rawsetfield(-2, i->first.c_str()); } } l.rawsetfield(-2, "variables"); l.pushfunction(data_source_asnumber); l.rawsetfield(-2, "asnumber"); l.pushfunction(data_source_astext); l.rawsetfield(-2, "astext"); } } /////////// example data sources, remove after real data sources are available /////// int asdf_ = 47; conky::register_data_source> asdf("asdf", &asdf_); conky::register_disabled_data_source zxcv("zxcv", "BUILD_ZXCV"); conky-1.10.1/src/data-source.hh000066400000000000000000000106051262311664100162400ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 DATA_SOURCE_HH #define DATA_SOURCE_HH #include #include #include #include "luamm.hh" namespace conky { /* * A base class for all data sources. * API consists of two functions: * - get_number should return numeric representation of the data (if available). This can * then be used when drawing graphs, bars, ... The default implementation returns NaN. * - get_text should return textual representation of the data. This is used when simple * displaying the value of the data source. The default implementation converts * get_number() to a string, but you can override to return anything (e.g. add units) */ class data_source_base { public: const std::string name; data_source_base(const std::string &name_) : name(name_) {} virtual ~data_source_base() {} virtual double get_number() const; virtual std::string get_text() const; }; /* * A simple data source that returns the value of some variable. It ignores the lua table. * The source variable can be specified as a fixed parameter to the register_data_source * constructor, or one can create a subclass and then set the source from the subclass * constructor. */ template class simple_numeric_source: public data_source_base { static_assert(std::is_convertible::value, "T must be convertible to double"); const T *source; public: simple_numeric_source(lua::state *, const std::string &name_, const T *source_) : data_source_base(name_), source(source_) {} virtual double get_number() const { return *source; } }; /* * This is a part of the implementation, but it cannot be in .cc file because the template * functions below call it */ namespace priv { const char data_source_metatable[] = "conky::data_source_metatable"; void do_register_data_source(const std::string &name, const lua::cpp_function &fn); class disabled_data_source: public simple_numeric_source { public: disabled_data_source(lua::state *l, const std::string &name, const std::string &setting); }; } /* * Declaring an object of this type at global scope will register a data source with the * given name. Any additional parameters are passed on to the data source constructor. */ template class register_data_source { template static int factory(lua::state *l, const std::string &name, const Args&... args) { T *t = static_cast(l->newuserdata(sizeof(T))); l->insert(1); new(t) T(l, name, args...); l->settop(1); l->rawgetfield(lua::REGISTRYINDEX, priv::data_source_metatable); l->setmetatable(-2); return 1; } public: template register_data_source(const std::string &name, Args&&... args) { priv::do_register_data_source( name, std::bind(&factory, std::placeholders::_1, name, args... )); } }; /* * Use this to declare a data source that has been disabled during compilation. We can then * print a nice error message telling the used which setting to enable. */ class register_disabled_data_source: public register_data_source { public: register_disabled_data_source(const std::string &name, const std::string &setting); }; /* * It expects to have a table at the top of lua stack. It then exports all the data sources * into that table (actually, into a "variables" subtable). */ void export_data_sources(lua::state &l); } #endif /* DATA_SOURCE_HH */ conky-1.10.1/src/diskio.cc000066400000000000000000000143561262311664100153100ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" /* text_buffer_size */ #include "core.h" #include "logging.h" #include "diskio.h" #include "common.h" #include "specials.h" #include "text_object.h" #include #include #include /* this is the root of all per disk stats, * also containing the totals. */ struct diskio_stat stats; void clear_diskio_stats(void) { struct diskio_stat *cur; while (stats.next) { cur = stats.next; stats.next = stats.next->next; free_and_zero(cur->dev); free(cur); } } struct diskio_stat *prepare_diskio_stat(const char *s) { struct stat sb; std::vector stat_name(text_buffer_size.get(*state)), device_name(text_buffer_size.get(*state)), device_s(text_buffer_size.get(*state)); struct diskio_stat *cur = &stats; if (!s) { return &stats; } else { strncpy(&(device_s[0]), s, text_buffer_size.get(*state)); } if (strncmp(&(device_s[0]), "label:", 6) == 0) { snprintf(&(device_name[0]), text_buffer_size.get(*state), "/dev/disk/by-label/%s", &(device_s[6])); char * rpbuf; rpbuf = realpath(&device_name[0], NULL); if (rpbuf) { strncpy(&device_s[0], rpbuf, text_buffer_size.get(*state)); } free(rpbuf); } else { strncpy(&device_s[0], s, text_buffer_size.get(*state)); } #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) if (strncmp(&device_s[0], "/dev/", 5) == 0) { device_s.erase(device_s.begin(), device_s.begin()+5); } #endif strncpy(&(device_name[0]), &device_s[0], text_buffer_size.get(*state)); snprintf(&(stat_name[0]), text_buffer_size.get(*state), "/dev/%s", &(device_name[0])); if (stat(&(stat_name[0]), &sb)) { NORM_ERR("diskio device '%s' does not exist", s); } /* lookup existing */ while (cur->next) { cur = cur->next; if (!strcmp(cur->dev, &(device_name[0]))) { return cur; } } /* no existing found, make a new one */ cur->next = new diskio_stat; cur = cur->next; cur->dev = strndup(&(device_s[0]), text_buffer_size.get(*state)); cur->last = UINT_MAX; cur->last_read = UINT_MAX; cur->last_write = UINT_MAX; return cur; } void parse_diskio_arg(struct text_object *obj, const char *arg) { obj->data.opaque = prepare_diskio_stat(arg); } /* dir indicates the direction: * -1: read * 0: read + write * 1: write */ static void print_diskio_dir(struct text_object *obj, int dir, char *p, int p_max_size) { struct diskio_stat *diskio = (struct diskio_stat *)obj->data.opaque; double val; if (!diskio) return; if (dir < 0) val = diskio->current_read; else if (dir == 0) val = diskio->current; else val = diskio->current_write; /* TODO: move this correction from kB to kB/s elsewhere * (or get rid of it??) */ human_readable((val / active_update_interval()) * 1024LL, p, p_max_size); } void print_diskio(struct text_object *obj, char *p, int p_max_size) { print_diskio_dir(obj, 0, p, p_max_size); } void print_diskio_read(struct text_object *obj, char *p, int p_max_size) { print_diskio_dir(obj, -1, p, p_max_size); } void print_diskio_write(struct text_object *obj, char *p, int p_max_size) { print_diskio_dir(obj, 1, p, p_max_size); } #ifdef BUILD_X11 void parse_diskiograph_arg(struct text_object *obj, const char *arg) { char *buf = 0; buf = scan_graph(obj, arg, 0); obj->data.opaque = prepare_diskio_stat(dev_name(buf)); free_and_zero(buf); } double diskiographval(struct text_object *obj) { struct diskio_stat *diskio = (struct diskio_stat *)obj->data.opaque; return (diskio ? diskio->current : 0); } double diskiographval_read(struct text_object *obj) { struct diskio_stat *diskio = (struct diskio_stat *)obj->data.opaque; return (diskio ? diskio->current_read : 0); } double diskiographval_write(struct text_object *obj) { struct diskio_stat *diskio = (struct diskio_stat *)obj->data.opaque; return (diskio ? diskio->current_write : 0); } #endif /* BUILD_X11 */ void update_diskio_values(struct diskio_stat *ds, unsigned int reads, unsigned int writes) { int i; double sum=0, sum_r=0, sum_w=0; if (reads < ds->last_read || writes < ds->last_write) { /* counter overflow or reset - rebase to sane values */ ds->last = reads+writes; ds->last_read = reads; ds->last_write = writes; } /* since the values in /proc/diskstats are absolute, we have to subtract * our last reading. The numbers stand for "sectors read", and we therefore * have to divide by two to get KB */ ds->sample_read[0] = (reads - ds->last_read) / 2; ds->sample_write[0] = (writes - ds->last_write) / 2; ds->sample[0] = ds->sample_read[0] + ds->sample_write[0]; /* compute averages */ int samples = diskio_avg_samples.get(*state); for (i = 0; i < samples; i++) { sum += ds->sample[i]; sum_r += ds->sample_read[i]; sum_w += ds->sample_write[i]; } ds->current = sum / (double) samples; ds->current_read = sum_r / (double) samples; ds->current_write = sum_w / (double) samples; /* shift sample history */ for (i = samples-1; i > 0; i--) { ds->sample[i] = ds->sample[i-1]; ds->sample_read[i] = ds->sample_read[i-1]; ds->sample_write[i] = ds->sample_write[i-1]; } /* save last */ ds->last_read = reads; ds->last_write = writes; ds->last = ds->last_read + ds->last_write; } conky-1.10.1/src/diskio.h000066400000000000000000000050061262311664100151420ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 DISKIO_H_ #define DISKIO_H_ #include struct diskio_stat { diskio_stat() : next(NULL), current(0), current_read(0), current_write(0), last(UINT_MAX), last_read(UINT_MAX), last_write(UINT_MAX) { memset(sample, 0, sizeof(sample) / sizeof(sample[0])); memset(sample_read, 0, sizeof(sample_read) / sizeof(sample_read[0])); memset(sample_write, 0, sizeof(sample_write) / sizeof(sample_write[0])); } struct diskio_stat *next; char *dev; double sample[15]; double sample_read[15]; double sample_write[15]; double current; double current_read; double current_write; double last; double last_read; double last_write; }; extern struct diskio_stat stats; struct diskio_stat *prepare_diskio_stat(const char *); int update_diskio(void); void clear_diskio_stats(void); void update_diskio_values(struct diskio_stat *, unsigned int, unsigned int); void parse_diskio_arg(struct text_object *, const char *); void print_diskio(struct text_object *, char *, int); void print_diskio_read(struct text_object *, char *, int); void print_diskio_write(struct text_object *, char *, int); #ifdef BUILD_X11 void parse_diskiograph_arg(struct text_object *, const char *); double diskiographval(struct text_object *); double diskiographval_read(struct text_object *); double diskiographval_write(struct text_object *); #endif /* BUILD_X11 */ #endif /* DISKIO_H_ */ conky-1.10.1/src/dragonfly.cc000066400000000000000000000505061262311664100160100ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2011 Andrea Magliano * 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 "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conky.h" #include "dragonfly.h" #include "logging.h" #include "net_stat.h" #include "top.h" #include "diskio.h" #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) #define KELVTOC(x) ((x - 2732) / 10.0) #define MAXSHOWDEVS 16 static short cpu_setup = 0; static int getsysctl(const char *name, void *ptr, size_t len) { size_t nlen = len; if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { fprintf(stderr, "getsysctl(): %s failed '%s'\n", name, strerror(errno)); return -1; } if (nlen != len && errno == ENOMEM) { fprintf(stderr, "getsysctl(): %s failed %zu != %zu\n", name, nlen, len); return -1; } return 0; } static int swapmode(unsigned long *retavail, unsigned long *retfree) { int total, used; size_t len = sizeof(int); if (sysctlbyname("vm.swap_size", &total, &len, NULL, 0) == -1) perror("vm_swap_usage(): vm.swap_size"); else if (sysctlbyname("vm.swap_anon_use", &used, &len, NULL, 0) == -1) perror("vm_swap_usage(): vm.swap_anon_use"); else { int size = getpagesize(); #define CONVERT(v) ((quad_t)(v) * (size / 1024)) *retavail = CONVERT(total); *retfree = CONVERT(total - used); return (int) ((double) used * 100.0 / (double) total); } return 0; } void prepare_update(void) { } int update_uptime(void) { int mib[2] = { CTL_KERN, KERN_BOOTTIME }; struct timeval boottime; time_t now; size_t size = sizeof(boottime); if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) && boottime.tv_sec) { time(&now); info.uptime = now - boottime.tv_sec; } else { fprintf(stderr, "Could not get uptime\n"); info.uptime = 0; } return 0; } int check_mount(char *s) { struct statfs *mntbuf; int i, mntsize; mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); for (i = mntsize - 1; i >= 0; i--) { if (strcmp(mntbuf[i].f_mntonname, s) == 0) { return 1; } } return 0; } int update_meminfo(void) { u_int total_pages, inactive_pages, free_pages; unsigned long swap_avail, swap_free; int pagesize = getpagesize(); if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages)) { fprintf(stderr, "Cannot read sysctl \"vm.stats.vm.v_page_count\"\n"); } if (GETSYSCTL("vm.stats.vm.v_free_count", free_pages)) { fprintf(stderr, "Cannot read sysctl \"vm.stats.vm.v_free_count\"\n"); } if (GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_pages)) { fprintf(stderr, "Cannot read sysctl \"vm.stats.vm.v_inactive_count\"\n"); } info.memmax = total_pages * (pagesize >> 10); info.mem = (total_pages - free_pages - inactive_pages) * (pagesize >> 10); info.memeasyfree = info.memfree = info.memmax - info.mem; if ((swapmode(&swap_avail, &swap_free)) >= 0) { info.swapmax = swap_avail; info.swap = (swap_avail - swap_free); info.swapfree = swap_free; } else { info.swapmax = 0; info.swap = 0; info.swapfree = 0; } return 0; } int update_net_stats(void) { struct net_stat *ns; double delta; long long r, t, last_recv, last_trans; struct ifaddrs *ifap, *ifa; struct if_data *ifd; /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { return 0; } if (getifaddrs(&ifap) < 0) { return 0; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ns = get_net_stat((const char *) ifa->ifa_name, NULL, NULL); if (ifa->ifa_flags & IFF_UP) { struct ifaddrs *iftmp; ns->up = 1; last_recv = ns->recv; last_trans = ns->trans; if (ifa->ifa_addr->sa_family != AF_LINK) { continue; } for (iftmp = ifa->ifa_next; iftmp != NULL && strcmp(ifa->ifa_name, iftmp->ifa_name) == 0; iftmp = iftmp->ifa_next) { if (iftmp->ifa_addr->sa_family == AF_INET) { memcpy(&(ns->addr), iftmp->ifa_addr, iftmp->ifa_addr->sa_len); } } ifd = (struct if_data *) ifa->ifa_data; r = ifd->ifi_ibytes; t = ifd->ifi_obytes; if (r < ns->last_read_recv) { ns->recv += ((long long) 4294967295U - ns->last_read_recv) + r; } else { ns->recv += (r - ns->last_read_recv); } ns->last_read_recv = r; if (t < ns->last_read_trans) { ns->trans += ((long long) 4294967295U - ns->last_read_trans) + t; } else { ns->trans += (t - ns->last_read_trans); } ns->last_read_trans = t; /* calculate speeds */ ns->recv_speed = (ns->recv - last_recv) / delta; ns->trans_speed = (ns->trans - last_trans) / delta; } else { ns->up = 0; } } freeifaddrs(ifap); return 0; } static int kern_proc_all_n() { size_t len = 0; if (sysctlbyname("kern.proc.all_lwp", NULL, &len, NULL, 0) == -1) { perror("kern.proc.all_lwp"); return -1; } if (len % sizeof(struct kinfo_proc)) { fprintf(stderr, "kern_proc(): " "len %% sizeof(struct kinfo_proc) != 0"); return -1; } return len / sizeof(struct kinfo_proc); } static struct kinfo_proc *kern_proc_all(size_t proc_n) { if (proc_n > 0) { size_t len = proc_n * sizeof(struct kinfo_proc); struct kinfo_proc *kp = (struct kinfo_proc *) malloc(len); if (kp) { if (sysctlbyname("kern.proc.all_lwp", kp, &len, NULL, 0) == -1) perror("kern_proc(): kern.proc.all_lwp"); else return kp; free (kp); } else perror("malloc"); } return NULL; } void get_cpu_count(void) { int cpu_count = 0; if (GETSYSCTL("hw.ncpu", cpu_count) == 0) { info.cpu_count = cpu_count; } else { fprintf(stderr, "Cannot get hw.ncpu\n"); info.cpu_count = 0; } info.cpu_usage = (float *) malloc((info.cpu_count + 1) * sizeof(float)); if (info.cpu_usage == NULL) { CRIT_ERR(NULL, NULL, "malloc"); } } struct cpu_info { long oldtotal; long oldused; }; PCPU_STATISTICS_FUNC(cputime, struct kinfo_cputime, uint64_t); static void stat_cpu(struct cpu_info *cpu, struct kinfo_cputime *percpu, float *usage) { long int used = (percpu->cp_user + percpu->cp_nice + percpu->cp_sys + percpu->cp_intr), total = used + percpu->cp_idle; *usage = (total - cpu->oldtotal) && cpu->oldtotal ? ((float) (used - cpu->oldused)) / (total - cpu->oldtotal) : 0; cpu->oldused = used; cpu->oldtotal = total; } int update_cpu_usage(void) { static struct cpu_info *cpu = NULL; extern void* global_cpu; /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */ if ((cpu_setup == 0) || (!info.cpu_usage)) { get_cpu_count(); cpu_setup = 1; } if (!global_cpu) { if (!cpu) cpu = (struct cpu_info *) calloc(sizeof(struct cpu_info), info.cpu_count + 1); global_cpu = cpu; } { size_t percpu_n = info.cpu_count * sizeof(struct kinfo_cputime); struct kinfo_cputime *percpu = (struct kinfo_cputime *) malloc(info.cpu_count * sizeof(struct kinfo_cputime)); if (percpu) { if (sysctlbyname("kern.cputime", percpu, &percpu_n, NULL, 0) == -1 && errno != ENOMEM) { printf("update_cpu_usage(): with %d cpu(s) ", info.cpu_count); perror("kern.cputime"); } else { struct kinfo_cputime total; cputime_pcpu_statistics(&percpu[0], &total, info.cpu_count); { int i; for (i = 0; i < info.cpu_count; i++) stat_cpu(&cpu[i+1], &percpu[i], &info.cpu_usage[i+1]); } stat_cpu(&cpu[0], &total, &info.cpu_usage[0]); } free(percpu); } } return 0; } int update_load_average(void) { double v[3]; getloadavg(v, 3); 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) { int temp; (void)fd; if (GETSYSCTL("hw.acpi.thermal.tz0.temperature", temp)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.thermal.tz0.temperature\"\n"); return 0.0; } return KELVTOC(temp); } static void get_battery_stats(int *battime, int *batcapacity, int *batstate, int *ac) { if (battime && GETSYSCTL("hw.acpi.battery.time", *battime)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.time\"\n"); } if (batcapacity && GETSYSCTL("hw.acpi.battery.life", *batcapacity)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.life\"\n"); } if (batstate && GETSYSCTL("hw.acpi.battery.state", *batstate)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.state\"\n"); } if (ac && GETSYSCTL("hw.acpi.acline", *ac)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.acline\"\n"); } } void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item) { int battime, batcapacity, batstate, ac; (void)bat; get_battery_stats(&battime, &batcapacity, &batstate, &ac); if (batstate != 1 && batstate != 2 && batstate != 0 && batstate != 7) fprintf(stderr, "Unknown battery state %d!\n", batstate); else if (batstate != 1 && ac == 0) fprintf(stderr, "Battery charging while not on AC!\n"); else if (batstate == 1 && ac == 1) fprintf(stderr, "Battery discharing while on AC!\n"); switch (item) { case BATTERY_TIME: if (batstate == 1 && battime != -1) snprintf(buf, n, "%d:%2.2d", battime / 60, battime % 60); break; case BATTERY_STATUS: if (batstate == 1) // Discharging snprintf(buf, n, "remaining %d%%", batcapacity); else snprintf(buf, n, batstate == 2 ? "charging (%d%%)" : (batstate == 7 ? "absent/on AC" : "charged (%d%%)"), batcapacity); break; default: fprintf(stderr, "Unknown requested battery stat %d\n", item); } } static int check_bat(const char *bat) { int batnum, numbatts; char *endptr; if (GETSYSCTL("hw.acpi.battery.units", numbatts)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.units\"\n"); return -1; } if (numbatts <= 0) { fprintf(stderr, "No battery unit detected\n"); return -1; } if (!bat || (batnum = strtol(bat, &endptr, 10)) < 0 || bat == endptr || batnum > numbatts) { fprintf(stderr, "Wrong battery unit %s requested\n", bat ? bat : ""); return -1; } return batnum; } int get_battery_perct(const char *bat) { union acpi_battery_ioctl_arg battio; int batnum, acpifd; int designcap, lastfulcap, batperct; if ((battio.unit = batnum = check_bat(bat)) < 0) return 0; if ((acpifd = open("/dev/acpi", O_RDONLY)) < 0) { fprintf(stderr, "Can't open ACPI device\n"); return 0; } if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1) { fprintf(stderr, "Unable to get info for battery unit %d\n", batnum); return 0; } close(acpifd); designcap = battio.bif.dcap; lastfulcap = battio.bif.lfcap; batperct = (designcap > 0 && lastfulcap > 0) ? (((float) lastfulcap / designcap) * 100) : 0; return batperct > 100 ? 100 : batperct; } double get_battery_perct_bar(struct text_object *obj) { int batperct = get_battery_perct(obj->data.s); return batperct * 2.56 - 1; } int open_acpi_temperature(const char *name) { (void)name; /* Not applicable for FreeBSD. */ return 0; } void get_acpi_ac_adapter(char *p_client_buffer, size_t client_buffer_size, const char *adapter) { int state; (void) adapter; // only linux uses this if (!p_client_buffer || client_buffer_size <= 0) { return; } if (GETSYSCTL("hw.acpi.acline", state)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.acline\"\n"); return; } if (state) { strncpy(p_client_buffer, "Running on AC Power", client_buffer_size); } else { strncpy(p_client_buffer, "Running on battery", client_buffer_size); } } void get_acpi_fan(char *p_client_buffer, size_t client_buffer_size) { /* not implemented */ if (p_client_buffer && client_buffer_size > 0) { memset(p_client_buffer, 0, client_buffer_size); } } /* void */ char get_freq(char *p_client_buffer, size_t client_buffer_size, const char *p_format, int divisor, unsigned int cpu) { int64_t freq; if (p_client_buffer && client_buffer_size > 0 && p_format && divisor > 0) { if (GETSYSCTL("hw.tsc_frequency", freq) == 0) { snprintf(p_client_buffer, client_buffer_size, p_format, (float) freq / (divisor * 1000000)); } else { snprintf(p_client_buffer, client_buffer_size, p_format, 0.0f); } return 1; } return 0; } #if 0 void update_wifi_stats(void) { struct ifreq ifr; /* interface stats */ struct wi_req wireq; struct net_stat *ns; struct ifaddrs *ifap, *ifa; struct ifmediareq ifmr; int s; /* Get iface table */ if (getifaddrs(&ifap) < 0) { return; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ns = get_net_stat((const char *) ifa->ifa_name, NULL, NULL); s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get media type */ bzero(&ifmr, sizeof(ifmr)); strlcpy(ifmr.ifm_name, ifa->ifa_name, IFNAMSIZ); if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { close(s); return; } /* We can monitor only wireless interfaces * which are not in hostap mode */ if ((ifmr.ifm_active & IFM_IEEE80211) && !(ifmr.ifm_active & IFM_IEEE80211_HOSTAP)) { /* Get wi status */ bzero(&ifr, sizeof(ifr)); strlcpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); wireq.wi_type = WI_RID_COMMS_QUALITY; wireq.wi_len = WI_MAX_DATALEN; ifr.ifr_data = (void *) &wireq; if (ioctl(s, SIOCGWAVELAN, (caddr_t) &ifr) < 0) { perror("ioctl (getting wi status)"); exit(1); } /* wi_val[0] = quality * wi_val[1] = signal * wi_val[2] = noise */ ns->linkstatus = (int) wireq.wi_val[1]; } cleanup: close(s); } } #endif int update_diskio(void) { int devs_count, num_selected, num_selections, dn; struct device_selection *dev_select = NULL; long select_generation; static struct statinfo statinfo_cur; char device_name[DEFAULT_TEXT_BUFFER_SIZE]; struct diskio_stat *cur; unsigned int reads, writes; unsigned int total_reads = 0, total_writes = 0; memset(&statinfo_cur, 0, sizeof(statinfo_cur)); statinfo_cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); stats.current = stats.current_read = stats.current_write = 0; if (getdevs(&statinfo_cur) < 0) { free(statinfo_cur.dinfo); return 0; } devs_count = statinfo_cur.dinfo->numdevs; if (selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, statinfo_cur.dinfo->generation, statinfo_cur.dinfo->devices, devs_count, NULL, 0, NULL, 0, DS_SELECT_ONLY, MAXSHOWDEVS, 1) >= 0) { for (dn = 0; dn < devs_count; dn++) { int di; struct devstat *dev; di = dev_select[dn].position; dev = &statinfo_cur.dinfo->devices[di]; snprintf(device_name, DEFAULT_TEXT_BUFFER_SIZE, "%s%d", dev_select[dn].device_name, dev_select[dn].unit_number); total_reads += (reads = dev->bytes_read / 512); total_writes += (writes = dev->bytes_written / 512); for (cur = stats.next; cur; cur = cur->next) { if (cur->dev && !strcmp(device_name, cur->dev)) { update_diskio_values(cur, reads, writes); break; } } } update_diskio_values(&stats, total_reads, total_writes); free(dev_select); } free(statinfo_cur.dinfo); return 0; } static int proc_rusage(struct kinfo_proc *p) { struct kinfo_lwp *lwp = &p->kp_lwp; struct rusage *cru = &p->kp_cru; return (lwp->kl_uticks + lwp->kl_sticks + lwp->kl_iticks) + (cru->ru_stime.tv_sec + cru->ru_utime.tv_sec) * 1000000; } static void proc_count(struct kinfo_proc *kp, size_t proc_n) { size_t i, act = 0, run = 0; for (i = 0; i < proc_n; i++) { struct kinfo_proc *p = &kp[i]; if (!(p->kp_flags & P_SYSTEM)) { struct kinfo_lwp *lwp = &p->kp_lwp; if (!lwp->kl_tid) act++; if (lwp->kl_stat == LSRUN) run++; } } info.procs = act; info.run_procs = run; } static void proc_fill(struct kinfo_proc *kp, size_t proc_n) { size_t i, f = getpagesize(); static long prev_ticks = 0; /* safe as long as in same thread */ for (i = 0; i < proc_n; i++) { struct kinfo_proc *p = &kp[i]; struct kinfo_lwp *lwp = &p->kp_lwp; if (!(p->kp_flags & P_SYSTEM) && p->kp_comm && *p->kp_comm && /* just to be sure */ !lwp->kl_tid) { /* 'main' lwp, the real process (observed) */ struct process *my = get_process(p->kp_pid); long ticks = proc_rusage(p); my->time_stamp = g_time; free_and_zero(my->name); my->name = strdup(p->kp_comm); my->amount = 100.0 * lwp->kl_pctcpu / FSCALE; my->vsize = p->kp_vm_map_size; my->rss = p->kp_vm_rssize * f; my->total_cpu_time = ticks - prev_ticks; prev_ticks = ticks; // printf("\tmy[%p]: %s(%u) %d %d 0x%x 0x%x %f\n", p, // my->name, my->pid, my->vsize, my->rss, // p->kp_flags, lwp->kl_stat, my->amount); } } } void get_top_info(void) { size_t proc_n = kern_proc_all_n(); struct kinfo_proc *kp = kern_proc_all(proc_n); if (kp) { proc_count(kp, proc_n); proc_fill(kp, proc_n); free(kp); } } #if defined(i386) || defined(__i386__) #define APMDEV "/dev/apm" #define APM_UNKNOWN 255 int apm_getinfo(int fd, apm_info_t aip) { if (ioctl(fd, APMIO_GETINFO, aip) == -1) { return -1; } return 0; } char *get_apm_adapter(void) { int fd; struct apm_info a_info; char *out; out = (char *) calloc(16, sizeof(char)); fd = open(APMDEV, O_RDONLY); if (fd < 0) { strncpy(out, "ERR", 16); return out; } if (apm_getinfo(fd, &a_info) != 0) { close(fd); strncpy(out, "ERR", 16); return out; } close(fd); switch (a_info.ai_acline) { case 0: strncpy(out, "off-line", 16); return out; break; case 1: if (a_info.ai_batt_stat == 3) { strncpy(out, "charging", 16); return out; } else { strncpy(out, "on-line", 16); return out; } break; default: strncpy(out, "unknown", 16); return out; break; } } char *get_apm_battery_life(void) { int fd; u_int batt_life; struct apm_info a_info; char *out; out = (char *) calloc(16, sizeof(char)); fd = open(APMDEV, O_RDONLY); if (fd < 0) { strncpy(out, "ERR", 16); return out; } if (apm_getinfo(fd, &a_info) != 0) { close(fd); strncpy(out, "ERR", 16); return out; } close(fd); batt_life = a_info.ai_batt_life; if (batt_life == APM_UNKNOWN) { strncpy(out, "unknown", 16); } else if (batt_life <= 100) { snprintf(out, 16, "%d%%", batt_life); return out; } else { strncpy(out, "ERR", 16); } return out; } char *get_apm_battery_time(void) { int fd; int batt_time; int h, m, s; struct apm_info a_info; char *out; out = (char *) calloc(16, sizeof(char)); fd = open(APMDEV, O_RDONLY); if (fd < 0) { strncpy(out, "ERR", 16); return out; } if (apm_getinfo(fd, &a_info) != 0) { close(fd); strncpy(out, "ERR", 16); return out; } close(fd); batt_time = a_info.ai_batt_time; if (batt_time == -1) { strncpy(out, "unknown", 16); } else { h = batt_time; s = h % 60; h /= 60; m = h % 60; h /= 60; snprintf(out, 16, "%2d:%02d:%02d", h, m, s); } return out; } #endif void get_battery_short_status(char *buffer, unsigned int n, const char *bat) { get_battery_stuff(buffer, n, bat, BATTERY_STATUS); if (0 == strncmp("charging", buffer, 8)) { buffer[0] = 'C'; memmove(buffer + 1, buffer + 8, n - 8); } else if (0 == strncmp("discharging", buffer, 11)) { buffer[0] = 'D'; memmove(buffer + 1, buffer + 11, n - 11); } else if (0 == strncmp("absent/on AC", buffer, 12)) { buffer[0] = 'A'; memmove(buffer + 1, buffer + 12, n - 12); } } int get_entropy_avail(unsigned int *val) { /* Not applicable for FreeBSD as it uses the yarrow prng. */ (void)val; return 1; } int get_entropy_poolsize(unsigned int *val) { /* Not applicable for FreeBSD as it uses the yarrow prng. */ (void)val; return 1; } conky-1.10.1/src/dragonfly.h000066400000000000000000000007051262311664100156460ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */ #ifndef DRAGONFLY_H_ #define DRAGONFLY_H_ #include "common.h" #include #include #include #include #include #if (defined(i386) || defined(__i386__)) #include #endif /* i386 || __i386__ */ int get_entropy_avail(unsigned int *); int get_entropy_poolsize(unsigned int *); #endif /*DRAGONFLY_H_*/ conky-1.10.1/src/entropy.cc000066400000000000000000000044121262311664100155160ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "text_object.h" /* check for OS and include appropriate headers */ #if defined(__linux__) #include "linux.h" #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "freebsd.h" #elif defined(__DragonFly__) #include "dragonfly.h" #elif defined(__OpenBSD__) #include "openbsd.h" #endif struct _entropy { _entropy() : avail(0), poolsize(0) {} unsigned int avail; unsigned int poolsize; }; static _entropy entropy; 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) { (void)obj; snprintf(p, p_max_size, "%u", entropy.avail); } uint8_t entropy_percentage(struct text_object *obj) { (void)obj; return round_to_int((double)entropy.avail * 100.0 / (double)entropy.poolsize); } void print_entropy_poolsize(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%u", entropy.poolsize); } double entropy_barval(struct text_object *obj) { (void)obj; return (double)entropy.avail / entropy.poolsize; } conky-1.10.1/src/entropy.h000066400000000000000000000027121262311664100153610ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _ENTROPY_H #define _ENTROPY_H int update_entropy(void); void print_entropy_avail(struct text_object *, char *, int); uint8_t entropy_percentage(struct text_object *); void print_entropy_poolsize(struct text_object *, char *, int); double entropy_barval(struct text_object *); #endif /* _ENTROPY_H */ conky-1.10.1/src/eve.cc000066400000000000000000000240751262311664100146040ustar00rootroot00000000000000/* -*- 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 * * Copyright (c) 2008 Asbjørn Zweidorff Kjær * Copyright (c) 2005-2012 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 "eve.h" #include "config.h" #include "logging.h" #include "text_object.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conky.h" #define MAXCHARS 4 #define EVE_UPDATE_DELAY 60 typedef struct { char *charid; char *skillname; char *time; char *lastOutput; struct tm ends; struct tm cache; time_t delay; int level; int skill; } Character; struct xmlData { char *data; size_t size; }; struct eve_data { char apikey[65]; char charid[21]; char userid[21]; }; int num_chars = 0; Character eveCharacters[MAXCHARS]; static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { size_t realsize = 0; struct xmlData *data = 0; data = (struct xmlData *)stream; realsize = size * nmemb; data->data = (char *)realloc(data->data, data->size + realsize + 1); if (data->data) { memcpy(&(data->data[data->size]), ptr, realsize); data->size += realsize; data->data[data->size] = '\0'; } return realsize; } int parseTrainingXml(char *data, Character * s) { char *skill, *level, *ends, *cache; xmlNodePtr n; xmlDocPtr doc = 0; xmlNodePtr root = 0; struct tm end_tm, cache_tm; if (!data) return 1; doc = xmlReadMemory(data, strlen(data), "", NULL, 0); root = xmlDocGetRootElement(doc); for (n = root->children; n; n = n->next) { if (n->type == XML_ELEMENT_NODE) { if (!strcasecmp((const char *)n->name, "error")) { return 1; } else if (!strcasecmp((const char *)n->name, "result")) { xmlNodePtr c; for (c = n->children; c; c = c->next) { if (!strcasecmp((const char *)c->name, "trainingEndTime")) { ends = (char *)c->children->content; } else if (!strcasecmp((const char *)c->name, "trainingTypeID")) { if (c->children->content) skill = (char *)c->children->content; } else if (!strcasecmp((const char *)c->name, "trainingToLevel")) { level = (char *)c->children->content; } } } else if (!strcasecmp((const char *)n->name, "cachedUntil")) { cache = (char *)n->children->content; } } } strptime(ends, "%Y-%m-%d %H:%M:%S", &end_tm); strptime(cache, "%Y-%m-%d %H:%M:%S", &cache_tm); s->skill = atoi(skill); s->level = atoi(level); s->ends = end_tm; s->cache = cache_tm; xmlFreeDoc(doc); return 0; } static char *getXmlFromAPI(const char *userid, const char *apikey, const char *charid, const char *url) { struct curl_httppost *post = NULL; struct curl_httppost *last = NULL; struct xmlData chr; char *content; CURL *curl_handle; int rc = 0; chr.data = NULL; chr.size = 0; curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1); curl_easy_setopt(curl_handle, CURLOPT_URL, url); curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chr); if (userid != NULL && apikey != NULL && charid != NULL) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "userID", CURLFORM_COPYCONTENTS, userid, CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "apiKey", CURLFORM_COPYCONTENTS, apikey, CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "characterID", CURLFORM_COPYCONTENTS, charid, CURLFORM_END); curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post); } if ((rc = curl_easy_perform(curl_handle)) != CURLE_OK) { return NULL; } content = strdup(chr.data); curl_easy_cleanup(curl_handle); return content; } static void init_eve(void) { int i; for (i = 0; i < MAXCHARS; i++) { eveCharacters[i].charid = NULL; eveCharacters[i].skillname = NULL; eveCharacters[i].time = NULL; eveCharacters[i].level = 0; eveCharacters[i].skill = 0; eveCharacters[i].delay = 0; } } static int isCacheValid(struct tm cached) { struct timeval tv; struct timezone tz; double offset = 0; time_t now = 0; time_t cache = 0; double diff = 0; gettimeofday(&tv, &tz); offset = (double)(tz.tz_minuteswest * 60); now = time(NULL); cache = mktime(&cached); diff = difftime(cache, now); if (diff < offset) return 0; else return 1; } static char *formatTime(struct tm *ends) { struct timeval tv; struct timezone tz; double offset = 0; time_t now = 0; time_t tEnds = 0; long lin = 0; long lie = 0; long diff = 0; gettimeofday(&tv, &tz); offset = (double)(tz.tz_minuteswest * 60); now = time(NULL); tEnds = mktime(ends); lin = (long)now; lin += (long)offset; lie = (long)tEnds; diff = (lie - lin); if (diff > 0) { int days = (int)(diff / 60 / 60 / 24); int hours = (int)((diff / 60 / 60) - (days * 24)); int minutes = (int)((diff / 60) - ((hours * 60) + (days * 60 * 24))); int seconds = (int)(diff - ((minutes * 60) + (hours * 60 * 60) + (days * 60 * 60 * 24))); char *output = (char*) malloc(100 * sizeof(char)); if (days > 0) sprintf(output, "%dd, %dh, %02dm and %02ds", days, hours, minutes, seconds); else if (hours > 0) sprintf(output, "%dh, %02dm and %02ds", hours, minutes, seconds); else sprintf(output, "%02dm and %02ds", minutes, seconds); return output; } else { char *output = strdup("Done"); return output; } } static void writeSkilltree(char *content, const char *filename) { FILE *fp = fopen(filename, "w"); if (fwrite(content, sizeof(char), strlen(content), fp) < strlen(content)) NORM_ERR("skill tree write failed"); fclose(fp); } static char *getSkillname(const char *file, int skillid) { char *skilltree; char *skill = NULL; xmlNodePtr n; xmlDocPtr doc = 0; xmlNodePtr root = 0; skilltree = getXmlFromAPI(NULL, NULL, NULL, EVEURL_SKILLTREE); writeSkilltree(skilltree, file); free(skilltree); doc = xmlReadFile(file, NULL, 0); unlink(file); if (!doc) return NULL; root = xmlDocGetRootElement(doc); for (n = root->children; n; n = n->next) { xmlNodePtr o; for (o = n->children; o; o = o->next) { xmlNodePtr p; for (p = o->children; p; p = p->next) { xmlNodePtr q; for (q = p->children; q; q = q->next) { xmlNodePtr r; for (r = q->children; r; r = r->next) { xmlElementPtr ele = (xmlElementPtr) r; xmlAttrPtr attr = (xmlAttrPtr) ele->attributes; char *mySkill = NULL; int id; while (attr != NULL) { if (!strcasecmp((const char *)attr->name, "typeName")) { mySkill = strdup((const char *)attr->children->content); } else if (!strcasecmp((const char *)attr->name, "typeID")) { id = atoi((const char *)attr->children->content); } attr = attr->next; } if (id == skillid) { skill = mySkill; goto END; } free(mySkill); } } } } } END: xmlFreeDoc(doc); return skill; } static char *eve(char *userid, char *apikey, char *charid) { Character *chr = NULL; char skillfile[] = "/tmp/.cesfXXXXXX"; int i = 0; char *output = 0; char *timel = 0; char *skill = 0; char *content = 0; time_t now = 0; char *error = 0; int tmp_fd, old_umask; for (i = 0; i < MAXCHARS; i++) { if (eveCharacters[i].charid != NULL) { if (strcasecmp(eveCharacters[i].charid, charid) == 0) { chr = &eveCharacters[i]; break; } } } if (!chr) { if (num_chars == MAXCHARS - 1) return NULL; chr = &eveCharacters[num_chars]; chr->charid = strdup(charid); num_chars++; } if (chr->delay > 0) { now = time(NULL); if (now < chr->delay) { output = strdup("Server error"); return output; } else chr->delay = 0; } if (isCacheValid(chr->cache)) { output = (char *)malloc(200 * sizeof(char)); timel = strdup(formatTime(&chr->ends)); sprintf(output, EVE_OUTPUT_FORMAT, chr->skillname, chr->level, timel); free(timel); return output; } else { content = getXmlFromAPI(userid, apikey, charid, EVEURL_TRAINING); if (content == NULL) { error = strdup("Server error"); now = time(NULL); now += (time_t) 1800; chr->delay = now; return error; } if (parseTrainingXml(content, chr)) { output = strdup("API error"); return output; } timel = formatTime(&chr->ends); old_umask = umask(0066); tmp_fd = mkstemp(skillfile); umask(old_umask); if (tmp_fd == -1) { error = strdup("Cannot create temporary file"); return error; } close(tmp_fd); skill = getSkillname(skillfile, chr->skill); chr->skillname = strdup(skill); output = (char *)malloc(200 * sizeof(char)); sprintf(output, EVE_OUTPUT_FORMAT, chr->skillname, chr->level, timel); free(skill); return output; } } void scan_eve(struct text_object *obj, const char *arg) { int argc; struct eve_data *ed; ed = (struct eve_data *) malloc(sizeof(struct eve_data)); memset(ed, 0, sizeof(struct eve_data)); argc = sscanf(arg, "%20s %64s %20s", ed->userid, ed->apikey, ed->charid); init_eve(); obj->data.opaque = ed; } void print_eve(struct text_object *obj, char *p, int p_max_size) { struct eve_data *ed = (struct eve_data *) obj->data.opaque; if (!ed) return; snprintf(p, p_max_size, "%s", eve(ed->userid, ed->apikey, ed->charid)); } void free_eve(struct text_object *obj) { free_and_zero(obj->data.opaque); } conky-1.10.1/src/eve.h000066400000000000000000000025301262311664100144360ustar00rootroot00000000000000/* -*- 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 * * Copyright (c) 2008 Asbjørn Zweidorff Kjær * Copyright (c) 2005-2012 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 _EVE_H #define _EVE_H #define EVEURL_TRAINING "http://api.eve-online.com/char/SkillInTraining.xml.aspx" #define EVEURL_SKILLTREE "http://api.eve-online.com/eve/Skilltree.xml.aspx" #define EVE_OUTPUT_FORMAT "%s %d in %s" void scan_eve(struct text_object *, const char *); void print_eve(struct text_object *, char *, int); void free_eve(struct text_object *); #endif /* _EVE_H */ conky-1.10.1/src/exec.cc000066400000000000000000000163201262311664100147430ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "core.h" #include "logging.h" #include "specials.h" #include "text_object.h" #include #include #include #include #include #include #include "update-cb.hh" namespace { class exec_cb: public conky::callback { typedef conky::callback Base; protected: virtual void work(); public: exec_cb(uint32_t period, bool wait, const std::string &cmd) : Base(period, wait, Base::Tuple(cmd)) {} }; } struct execi_data { float interval; char *cmd; execi_data() : interval(0), cmd(0) {} }; //our own implementation of popen, the difference : the value of 'childpid' will be filled with //the pid of the running 'command'. This is useful if want to kill it when it hangs while reading //or writing to it. We have to kill it because pclose will wait until the process dies by itself static FILE* pid_popen(const char *command, const char *mode, pid_t *child) { int ends[2]; int parentend, childend; //by running pipe after the strcmp's we make sure that we don't have to create a pipe //and close the ends if mode is something illegal if(strcmp(mode, "r") == 0) { if(pipe(ends) != 0) { return NULL; } parentend = ends[0]; childend = ends[1]; } else if(strcmp(mode, "w") == 0) { if(pipe(ends) != 0) { return NULL; } parentend = ends[1]; childend = ends[0]; } else { return NULL; } *child = fork(); if(*child == -1) { close(parentend); close(childend); return NULL; } else if(*child > 0) { close(childend); waitpid(*child, NULL, 0); } else { //don't read from both stdin and pipe or write to both stdout and pipe if(childend == ends[0]) { close(0); } else { close(1); } close(parentend); //by dupping childend, the returned fd will have close-on-exec turned off if (dup(childend) == -1) perror("dup()"); close(childend); execl("/bin/sh", "sh", "-c", command, (char *) NULL); _exit(EXIT_FAILURE); //child should die here, (normally execl will take care of this but it can fail) } return fdopen(parentend, mode); } void exec_cb::work() { pid_t childpid; std::string buf; std::shared_ptr fp; char b[0x1000]; if(FILE *t = pid_popen(std::get<0>(tuple).c_str(), "r", &childpid)) fp.reset(t, fclose); else return; while(!feof(fp.get()) && !ferror(fp.get())) { int length = fread(b, 1, sizeof b, fp.get()); buf.append(b, length); } if(*buf.rbegin() == '\n') buf.resize(buf.size()-1); std::lock_guard l(result_mutex); result = buf; } //remove backspaced chars, example: "dog^H^H^Hcat" becomes "cat" //string has to end with \0 and it's length should fit in a int #define BACKSPACE 8 static void remove_deleted_chars(char *string){ int i = 0; while(string[i] != 0){ if(string[i] == BACKSPACE){ if(i != 0){ strcpy( &(string[i-1]), &(string[i+1]) ); i--; }else strcpy( &(string[i]), &(string[i+1]) ); //necessary for ^H's at the start of a string }else i++; } } static inline double get_barnum(const char *buf) { double barnum; if (sscanf(buf, "%lf", &barnum) != 1) { NORM_ERR("reading exec value failed (perhaps it's not the " "correct format?)"); return 0.0; } if (barnum > 100.0 || barnum < 0.0) { NORM_ERR("your exec value is not between 0 and 100, " "therefore it will be ignored"); return 0.0; } return barnum; } void scan_exec_arg(struct text_object *obj, const char *arg) { /* XXX: do real bar parsing here */ scan_bar(obj, "", 100); obj->data.s = strndup(arg ? arg : "", text_buffer_size.get(*state)); } void scan_execi_arg(struct text_object *obj, const char *arg) { struct execi_data *ed; int n; ed = new execi_data; if (sscanf(arg, "%f %n", &ed->interval, &n) <= 0) { NORM_ERR("${execi* command}"); delete ed; return; } ed->cmd = strndup(arg + n, text_buffer_size.get(*state)); obj->data.opaque = ed; } void scan_execi_bar_arg(struct text_object *obj, const char *arg) { /* XXX: do real bar parsing here */ scan_bar(obj, "", 100); scan_execi_arg(obj, arg); } #ifdef BUILD_X11 void scan_execi_gauge_arg(struct text_object *obj, const char *arg) { /* XXX: do real gauge parsing here */ scan_gauge(obj, "", 100); scan_execi_arg(obj, arg); } void scan_execgraph_arg(struct text_object *obj, const char *arg) { struct execi_data *ed; char *buf; ed = new execi_data; memset(ed, 0, sizeof(struct execi_data)); buf = scan_graph(obj, arg, 100); if (!buf) { NORM_ERR("missing command argument to execgraph object"); return; } ed->cmd = buf; obj->data.opaque = ed; } #endif /* BUILD_X11 */ void fill_p(const char *buffer, struct text_object *obj, char *p, int p_max_size) { if(obj->parse == true) { evaluate(buffer, p, p_max_size); } else snprintf(p, p_max_size, "%s", buffer); remove_deleted_chars(p); } void print_exec(struct text_object *obj, char *p, int p_max_size) { auto cb = conky::register_cb(1, true, obj->data.s); fill_p(cb->get_result_copy().c_str(), obj, p, p_max_size); } void print_execi(struct text_object *obj, char *p, int p_max_size) { struct execi_data *ed = (struct execi_data *)obj->data.opaque; if (!ed) return; uint32_t period = std::max(lround(ed->interval/active_update_interval()), 1l); auto cb = conky::register_cb(period, !obj->thread, ed->cmd); fill_p(cb->get_result_copy().c_str(), obj, p, p_max_size); } double execbarval(struct text_object *obj) { auto cb = conky::register_cb(1, true, obj->data.s); return get_barnum(cb->get_result_copy().c_str()); } double execi_barval(struct text_object *obj) { struct execi_data *ed = (struct execi_data *)obj->data.opaque; if (!ed) return 0; uint32_t period = std::max(lround(ed->interval/active_update_interval()), 1l); auto cb = conky::register_cb(period, !obj->thread, ed->cmd); return get_barnum(cb->get_result_copy().c_str()); } void free_exec(struct text_object *obj) { free_and_zero(obj->data.s); } void free_execi(struct text_object *obj) { struct execi_data *ed = (struct execi_data *)obj->data.opaque; if (!ed) return; free_and_zero(ed->cmd); delete ed; obj->data.opaque = NULL; } conky-1.10.1/src/exec.h000066400000000000000000000034321262311664100146050ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _EXEC_H #define _EXEC_H #include "text_object.h" void scan_exec_arg(struct text_object *, const char *); void scan_execi_arg(struct text_object *, const char *); void scan_execi_bar_arg(struct text_object *, const char *); void scan_execi_gauge_arg(struct text_object *, const char *); void scan_execgraph_arg(struct text_object *, const char *); void print_exec(struct text_object *, char *, int); void print_execi(struct text_object *, char *, int); double execbarval(struct text_object *); double execi_barval(struct text_object *); void free_exec(struct text_object *); void free_execi(struct text_object *); #endif /* _EXEC_H */ conky-1.10.1/src/fonts.cc000066400000000000000000000116601262311664100151520ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "fonts.h" #include "logging.h" int selected_font = 0; std::vector fonts; char fontloaded = 0; void font_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && out_to_x.get(*state)) { if(fonts.size() == 0) fonts.resize(1); fonts[0].name = do_convert(l, -1).first; } ++s; } font_setting font; #ifdef BUILD_XFT namespace { class xftalpha_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && out_to_x.get(*state)) { fonts[0].font_alpha = do_convert(l, -1).first * 0xffff; } ++s; } public: xftalpha_setting() : Base("xftalpha", 1.0, false) {} }; xftalpha_setting xftalpha; } #endif /* BUILD_XFT */ void set_font(void) { #ifdef BUILD_XFT if (use_xft.get(*state)) return; #endif /* BUILD_XFT */ if (fonts[selected_font].font) { XSetFont(display, window.gc, fonts[selected_font].font->fid); } } void setup_fonts(void) { if (not out_to_x.get(*state)) { return; } #ifdef BUILD_XFT if (use_xft.get(*state)) { if (window.xftdraw) { XftDrawDestroy(window.xftdraw); window.xftdraw = 0; } window.xftdraw = XftDrawCreate(display, window.drawable, window.visual, window.colourmap); } #endif /* BUILD_XFT */ set_font(); } int add_font(const char *data_in) { if (not out_to_x.get(*state)) { return 0; } fonts.push_back(font_list()); fonts.rbegin()->name = data_in; return fonts.size()-1; } void free_fonts(bool utf8) { if (not out_to_x.get(*state)) { return; } for (size_t i = 0; i < fonts.size(); i++) { #ifdef BUILD_XFT if (use_xft.get(*state)) { /* * Do we not need to close fonts with Xft? Unsure. Not freeing the * fonts seems to incur a slight memory leak, but it also prevents * a crash. * * XftFontClose(display, fonts[i].xftfont); */ } else #endif /* BUILD_XFT */ { if (fonts[i].font) { XFreeFont(display, fonts[i].font); } if (utf8 && fonts[i].fontset) { XFreeFontSet(display, fonts[i].fontset); } } } fonts.clear(); selected_font = 0; #ifdef BUILD_XFT if (window.xftdraw) { XftDrawDestroy(window.xftdraw); window.xftdraw = 0; } #endif /* BUILD_XFT */ } void load_fonts(bool utf8) { if (not out_to_x.get(*state)) return; for (size_t i = 0; i < fonts.size(); i++) { #ifdef BUILD_XFT /* load Xft font */ if (use_xft.get(*state)) { if(not fonts[i].xftfont) fonts[i].xftfont = XftFontOpenName(display, screen, fonts[i].name.c_str()); if (fonts[i].xftfont) { continue; } NORM_ERR("can't load Xft font '%s'", fonts[i].name.c_str()); if ((fonts[i].xftfont = XftFontOpenName(display, screen, "courier-12")) != NULL) { continue; } CRIT_ERR(NULL, NULL, "can't load Xft font '%s'", "courier-12"); continue; } #endif if(utf8 && fonts[i].fontset == NULL) { char** missing; int missingnum; char* missingdrawn; fonts[i].fontset = XCreateFontSet(display, fonts[i].name.c_str(), &missing, &missingnum, &missingdrawn); XFreeStringList(missing); if(fonts[i].fontset == NULL) { NORM_ERR("can't load font '%s'", fonts[i].name.c_str()); fonts[i].fontset = XCreateFontSet(display, "fixed", &missing, &missingnum, &missingdrawn); if(fonts[i].fontset == NULL) { CRIT_ERR(NULL, NULL, "can't load font '%s'", "fixed"); } } } /* load normal font */ if (!fonts[i].font && (fonts[i].font = XLoadQueryFont(display, fonts[i].name.c_str())) == NULL) { NORM_ERR("can't load font '%s'", fonts[i].name.c_str()); if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) { CRIT_ERR(NULL, NULL, "can't load font '%s'", "fixed"); } } } } conky-1.10.1/src/fonts.h000066400000000000000000000055451262311664100150210ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 . * */ #ifdef BUILD_X11 #ifndef _FONTS_H #define _FONTS_H #include #include "x11.h" /* for fonts */ struct font_list { std::string name; XFontStruct *font; XFontSet fontset; #ifdef BUILD_XFT XftFont *xftfont; int font_alpha; #endif font_list() : name(), font(NULL), fontset(NULL) #ifdef BUILD_XFT , xftfont(NULL), font_alpha(0xffff) #endif {} }; #ifdef BUILD_XFT #define font_height() (use_xft.get(*state) ? (fonts[selected_font].xftfont->ascent + \ fonts[selected_font].xftfont->descent) \ : (fonts[selected_font].font->max_bounds.ascent + \ fonts[selected_font].font->max_bounds.descent)) #define font_ascent() (use_xft.get(*state) ? fonts[selected_font].xftfont->ascent \ : fonts[selected_font].font->max_bounds.ascent) #define font_descent() (use_xft.get(*state) ? fonts[selected_font].xftfont->descent \ : fonts[selected_font].font->max_bounds.descent) #else #define font_height() (fonts[selected_font].font->max_bounds.ascent + \ fonts[selected_font].font->max_bounds.descent) #define font_ascent() fonts[selected_font].font->max_bounds.ascent #define font_descent() fonts[selected_font].font->max_bounds.descent #endif /* direct access to registered fonts (FIXME: bad encapsulation) */ extern std::vector fonts; extern int selected_font; void setup_fonts(void); void set_font(void); int add_font(const char *); void free_fonts(bool utf8); void load_fonts(bool utf8); class font_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); public: font_setting() : Base("font", "6x10", false) {} }; extern font_setting font; #endif /* _FONTS_H */ #endif /* BUILD_X11 */ conky-1.10.1/src/freebsd.cc000066400000000000000000000442131262311664100154330ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conky.h" #include "freebsd.h" #include "logging.h" #include "net_stat.h" #include "text_object.h" #include "top.h" #include "diskio.h" #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) #define KELVTOC(x) ((x - 2732) / 10.0) #define MAXSHOWDEVS 16 #if 0 #define FREEBSD_DEBUG #endif kvm_t *kd; std::mutex kvm_proc_mutex; __attribute__((gnu_inline)) inline void proc_find_top(struct process **cpu, struct process **mem, struct process **time); static short cpu_setup = 0; static int getsysctl(const char *name, void *ptr, size_t len) { size_t nlen = len; if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { return -1; } if (nlen != len && errno == ENOMEM) { return -1; } return 0; } struct ifmibdata *data = NULL; size_t len = 0; static int swapmode(unsigned long *retavail, unsigned long *retfree) { int n; unsigned long pagesize = getpagesize(); struct kvm_swap swapary[1]; *retavail = 0; *retfree = 0; #define CONVERT(v) ((quad_t)(v) * (pagesize / 1024)) n = kvm_getswapinfo(kd, swapary, 1, 0); if (n < 0 || swapary[0].ksw_total == 0) { return 0; } *retavail = CONVERT(swapary[0].ksw_total); *retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used); n = (int) ((double) swapary[0].ksw_used * 100.0 / (double) swapary[0].ksw_total); return n; } void prepare_update(void) { } int update_uptime(void) { int mib[2] = { CTL_KERN, KERN_BOOTTIME }; struct timeval boottime; time_t now; size_t size = sizeof(boottime); if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) && (boottime.tv_sec != 0)) { time(&now); info.uptime = now - boottime.tv_sec; } else { fprintf(stderr, "Could not get uptime\n"); info.uptime = 0; } return 0; } int check_mount(struct text_object *obj) { struct statfs *mntbuf; int i, mntsize; if (!obj->data.s) return 0; mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); for (i = mntsize - 1; i >= 0; i--) { if (strcmp(mntbuf[i].f_mntonname, obj->data.s) == 0) { return 1; } } return 0; } int update_meminfo(void) { u_int total_pages, inactive_pages, free_pages; unsigned long swap_avail, swap_free; int pagesize = getpagesize(); if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages)) { fprintf(stderr, "Cannot read sysctl \"vm.stats.vm.v_page_count\"\n"); } if (GETSYSCTL("vm.stats.vm.v_free_count", free_pages)) { fprintf(stderr, "Cannot read sysctl \"vm.stats.vm.v_free_count\"\n"); } if (GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_pages)) { fprintf(stderr, "Cannot read sysctl \"vm.stats.vm.v_inactive_count\"\n"); } info.memmax = total_pages * (pagesize >> 10); info.mem = (total_pages - free_pages - inactive_pages) * (pagesize >> 10); info.memwithbuffers = info.mem; info.memeasyfree = info.memfree = info.memmax - info.mem; if ((swapmode(&swap_avail, &swap_free)) >= 0) { info.swapmax = swap_avail; info.swap = (swap_avail - swap_free); info.swapfree = swap_free; } else { info.swapmax = 0; info.swap = 0; info.swapfree = 0; } return 0; } int update_net_stats(void) { struct net_stat *ns; double delta; long long r, t, last_recv, last_trans; struct ifaddrs *ifap, *ifa; struct if_data *ifd; /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { return 0; } if (getifaddrs(&ifap) < 0) { return 0; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ns = get_net_stat((const char *) ifa->ifa_name, NULL, NULL); if (ifa->ifa_flags & IFF_UP) { struct ifaddrs *iftmp; ns->up = 1; last_recv = ns->recv; last_trans = ns->trans; if (ifa->ifa_addr->sa_family != AF_LINK) { continue; } for (iftmp = ifa->ifa_next; iftmp != NULL && strcmp(ifa->ifa_name, iftmp->ifa_name) == 0; iftmp = iftmp->ifa_next) { if (iftmp->ifa_addr->sa_family == AF_INET) { memcpy(&(ns->addr), iftmp->ifa_addr, iftmp->ifa_addr->sa_len); } } ifd = (struct if_data *) ifa->ifa_data; r = ifd->ifi_ibytes; t = ifd->ifi_obytes; if (r < ns->last_read_recv) { ns->recv += ((long long) 4294967295U - ns->last_read_recv) + r; } else { ns->recv += (r - ns->last_read_recv); } ns->last_read_recv = r; if (t < ns->last_read_trans) { ns->trans += ((long long) 4294967295U - ns->last_read_trans) + t; } else { ns->trans += (t - ns->last_read_trans); } ns->last_read_trans = t; /* calculate speeds */ ns->recv_speed = (ns->recv - last_recv) / delta; ns->trans_speed = (ns->trans - last_trans) / delta; } else { ns->up = 0; } } freeifaddrs(ifap); return 0; } int update_total_processes(void) { int n_processes; std::lock_guard guard(kvm_proc_mutex); kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes); info.procs = n_processes; return 0; } int update_running_processes(void) { struct kinfo_proc *p; int n_processes; int i, cnt = 0; std::lock_guard guard(kvm_proc_mutex); p = kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes); for (i = 0; i < n_processes; i++) { #if (__FreeBSD__ < 5) && !defined(__FreeBSD_kernel__) if (p[i].kp_proc.p_stat == SRUN) { #else if (p[i].ki_stat == SRUN) { #endif cnt++; } } info.run_procs = cnt; return 0; } void get_cpu_count(void) { int cpu_count = 0; size_t cpu_count_len = sizeof(cpu_count); if (GETSYSCTL("hw.ncpu", cpu_count) == 0) { info.cpu_count = cpu_count; } else { fprintf(stderr, "Cannot get hw.ncpu\n"); info.cpu_count = 0; } info.cpu_usage = (float *) malloc((info.cpu_count + 1) * sizeof(float)); if (info.cpu_usage == NULL) { CRIT_ERR(NULL, NULL, "malloc"); } } struct cpu_info { long oldtotal; long oldused; }; int update_cpu_usage(void) { int i, j = 0; long used, total; long *cp_time = NULL; size_t cp_len; static struct cpu_info *cpu = NULL; unsigned int malloc_cpu_size = 0; extern void* global_cpu; /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */ if ((cpu_setup == 0) || (!info.cpu_usage)) { get_cpu_count(); cpu_setup = 1; } if (!global_cpu) { malloc_cpu_size = (info.cpu_count + 1) * sizeof(struct cpu_info); cpu = (cpu_info *) malloc(malloc_cpu_size); memset(cpu, 0, malloc_cpu_size); global_cpu = cpu; } /* cpu[0] is overall stats, get it from separate sysctl */ cp_len = CPUSTATES * sizeof(long); cp_time = (long int *) malloc(cp_len); if (sysctlbyname("kern.cp_time", cp_time, &cp_len, NULL, 0) < 0) { fprintf(stderr, "Cannot get kern.cp_time\n"); } total = 0; for (j = 0; j < CPUSTATES; j++) total += cp_time[j]; used = total - cp_time[CP_IDLE]; if ((total - cpu[0].oldtotal) != 0) { info.cpu_usage[0] = ((double) (used - cpu[0].oldused)) / (double) (total - cpu[0].oldtotal); } else { info.cpu_usage[0] = 0; } cpu[0].oldused = used; cpu[0].oldtotal = total; free(cp_time); /* per-core stats */ cp_len = CPUSTATES * sizeof(long) * info.cpu_count; cp_time = (long int *) malloc(cp_len); /* on e.g. i386 SMP we may have more values than actual cpus; this will just drop extra values */ if (sysctlbyname("kern.cp_times", cp_time, &cp_len, NULL, 0) < 0 && errno != ENOMEM) { fprintf(stderr, "Cannot get kern.cp_times\n"); } for (i = 0; i < info.cpu_count; i++) { total = 0; for (j = 0; j < CPUSTATES; j++) total += cp_time[i*CPUSTATES + j]; used = total - cp_time[i*CPUSTATES + CP_IDLE]; if ((total - cpu[i+1].oldtotal) != 0) { info.cpu_usage[i+1] = ((double) (used - cpu[i+1].oldused)) / (double) (total - cpu[i+1].oldtotal); } else { info.cpu_usage[i+1] = 0; } cpu[i+1].oldused = used; cpu[i+1].oldtotal = total; } free(cp_time); return 0; } int update_load_average(void) { double v[3]; getloadavg(v, 3); 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) { int temp; (void)fd; if (GETSYSCTL("hw.acpi.thermal.tz0.temperature", temp)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.thermal.tz0.temperature\"\n"); return 0.0; } return KELVTOC(temp); } static void get_battery_stats(int *battime, int *batcapacity, int *batstate, int *ac) { if (battime && GETSYSCTL("hw.acpi.battery.time", *battime)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.time\"\n"); } if (batcapacity && GETSYSCTL("hw.acpi.battery.life", *batcapacity)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.life\"\n"); } if (batstate && GETSYSCTL("hw.acpi.battery.state", *batstate)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.state\"\n"); } if (ac && GETSYSCTL("hw.acpi.acline", *ac)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.acline\"\n"); } } void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item) { int battime, batcapacity, batstate, ac; (void)bat; get_battery_stats(&battime, &batcapacity, &batstate, &ac); if (batstate != 1 && batstate != 2 && batstate != 0 && batstate != 7) fprintf(stderr, "Unknown battery state %d!\n", batstate); else if (batstate != 1 && ac == 0) fprintf(stderr, "Battery charging while not on AC!\n"); else if (batstate == 1 && ac == 1) fprintf(stderr, "Battery discharing while on AC!\n"); switch (item) { case BATTERY_TIME: if (batstate == 1 && battime != -1) snprintf(buf, n, "%d:%2.2d", battime / 60, battime % 60); break; case BATTERY_STATUS: if (batstate == 1) // Discharging snprintf(buf, n, "remaining %d%%", batcapacity); else snprintf(buf, n, batstate == 2 ? "charging (%d%%)" : (batstate == 7 ? "absent/on AC" : "charged (%d%%)"), batcapacity); break; default: fprintf(stderr, "Unknown requested battery stat %d\n", item); } } static int check_bat(const char *bat) { int batnum, numbatts; char *endptr; if (GETSYSCTL("hw.acpi.battery.units", numbatts)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.battery.units\"\n"); return -1; } if (numbatts <= 0) { fprintf(stderr, "No battery unit detected\n"); return -1; } if (!bat || (batnum = strtol(bat, &endptr, 10)) < 0 || bat == endptr || batnum > numbatts) { fprintf(stderr, "Wrong battery unit %s requested\n", bat ? bat : ""); return -1; } return batnum; } int get_battery_perct(const char *bat) { union acpi_battery_ioctl_arg battio; int batnum, acpifd; int designcap, lastfulcap, batperct; if ((battio.unit = batnum = check_bat(bat)) < 0) return 0; if ((acpifd = open("/dev/acpi", O_RDONLY)) < 0) { fprintf(stderr, "Can't open ACPI device\n"); return 0; } if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1) { fprintf(stderr, "Unable to get info for battery unit %d\n", batnum); return 0; } close(acpifd); designcap = battio.bif.dcap; lastfulcap = battio.bif.lfcap; batperct = (designcap > 0 && lastfulcap > 0) ? (int) (((float) lastfulcap / designcap) * 100) : 0; return batperct > 100 ? 100 : batperct; } double get_battery_perct_bar(struct text_object *obj) { int batperct = get_battery_perct(obj->data.s); return batperct; } int open_acpi_temperature(const char *name) { (void)name; /* Not applicable for FreeBSD. */ return 0; } void get_acpi_ac_adapter(char *p_client_buffer, size_t client_buffer_size, const char *adapter) { int state; (void) adapter; // only linux uses this if (!p_client_buffer || client_buffer_size <= 0) { return; } if (GETSYSCTL("hw.acpi.acline", state)) { fprintf(stderr, "Cannot read sysctl \"hw.acpi.acline\"\n"); return; } if (state) { strncpy(p_client_buffer, "Running on AC Power", client_buffer_size); } else { strncpy(p_client_buffer, "Running on battery", client_buffer_size); } } void get_acpi_fan(char *p_client_buffer, size_t client_buffer_size) { /* not implemented */ if (p_client_buffer && client_buffer_size > 0) { memset(p_client_buffer, 0, client_buffer_size); } } /* void */ char get_freq(char *p_client_buffer, size_t client_buffer_size, const char *p_format, int divisor, unsigned int cpu) { int freq; char *freq_sysctl; if (!p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0) { return 0; } freq_sysctl = (char *) calloc(16, sizeof(char)); if (freq_sysctl == NULL) { exit(-1); } snprintf(freq_sysctl, 16, "dev.cpu.%d.freq", (cpu - 1)); if (GETSYSCTL(freq_sysctl, freq) == 0) { snprintf(p_client_buffer, client_buffer_size, p_format, (float) freq / divisor); } else { snprintf(p_client_buffer, client_buffer_size, p_format, 0.0f); } free(freq_sysctl); return 1; } #if 0 void update_wifi_stats(void) { struct ifreq ifr; /* interface stats */ struct wi_req wireq; struct net_stat *ns; struct ifaddrs *ifap, *ifa; struct ifmediareq ifmr; int s; /* Get iface table */ if (getifaddrs(&ifap) < 0) { return; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ns = get_net_stat((const char *) ifa->ifa_name, NULL, NULL); s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get media type */ bzero(&ifmr, sizeof(ifmr)); strlcpy(ifmr.ifm_name, ifa->ifa_name, IFNAMSIZ); if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { close(s); return; } /* We can monitor only wireless interfaces * which are not in hostap mode */ if ((ifmr.ifm_active & IFM_IEEE80211) && !(ifmr.ifm_active & IFM_IEEE80211_HOSTAP)) { /* Get wi status */ bzero(&ifr, sizeof(ifr)); strlcpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); wireq.wi_type = WI_RID_COMMS_QUALITY; wireq.wi_len = WI_MAX_DATALEN; ifr.ifr_data = (void *) &wireq; if (ioctl(s, SIOCGWAVELAN, (caddr_t) &ifr) < 0) { perror("ioctl (getting wi status)"); exit(1); } /* wi_val[0] = quality * wi_val[1] = signal * wi_val[2] = noise */ ns->linkstatus = (int) wireq.wi_val[1]; } cleanup: close(s); } } #endif int update_diskio(void) { int devs_count, num_selected, num_selections, dn; struct device_selection *dev_select = NULL; long select_generation; static struct statinfo statinfo_cur; char device_name[text_buffer_size.get(*state)]; struct diskio_stat *cur; unsigned int reads, writes; unsigned int total_reads = 0, total_writes = 0; memset(&statinfo_cur, 0, sizeof(statinfo_cur)); statinfo_cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); stats.current = stats.current_read = stats.current_write = 0; if (devstat_getdevs(NULL, &statinfo_cur) < 0) { free(statinfo_cur.dinfo); return 0; } devs_count = statinfo_cur.dinfo->numdevs; if (devstat_selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, statinfo_cur.dinfo->generation, statinfo_cur.dinfo->devices, devs_count, NULL, 0, NULL, 0, DS_SELECT_ONLY, MAXSHOWDEVS, 1) >= 0) { for (dn = 0; dn < devs_count; dn++) { int di; struct devstat *dev; di = dev_select[dn].position; dev = &statinfo_cur.dinfo->devices[di]; snprintf(device_name, text_buffer_size.get(*state), "%s%d", dev_select[dn].device_name, dev_select[dn].unit_number); total_reads += (reads = dev->bytes[DEVSTAT_READ] / 512); total_writes += (writes = dev->bytes[DEVSTAT_WRITE] / 512); for (cur = stats.next; cur; cur = cur->next) { if (cur->dev && !strcmp(device_name, cur->dev)) { update_diskio_values(cur, reads, writes); break; } } } update_diskio_values(&stats, total_reads, total_writes); free(dev_select); } free(statinfo_cur.dinfo); return 0; } /* While topless is obviously better, top is also not bad. */ void get_top_info(void) { struct kinfo_proc *p; struct process *proc; int n_processes; int i; std::lock_guard guard(kvm_proc_mutex); p = kvm_getprocs(kd, KERN_PROC_PROC, 0, &n_processes); for (i = 0; i < n_processes; i++) { if (!((p[i].ki_flag & P_SYSTEM)) && p[i].ki_comm != NULL) { 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.get(*state)); 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; } } } void get_battery_short_status(char *buffer, unsigned int n, const char *bat) { get_battery_stuff(buffer, n, bat, BATTERY_STATUS); if (0 == strncmp("charging", buffer, 8)) { buffer[0] = 'C'; memmove(buffer + 1, buffer + 8, n - 8); } else if (0 == strncmp("discharging", buffer, 11)) { buffer[0] = 'D'; memmove(buffer + 1, buffer + 11, n - 11); } else if (0 == strncmp("absent/on AC", buffer, 12)) { buffer[0] = 'A'; memmove(buffer + 1, buffer + 12, n - 12); } } int get_entropy_avail(unsigned int *val) { /* Not applicable for FreeBSD as it uses the yarrow prng. */ (void)val; return 1; } int get_entropy_poolsize(unsigned int *val) { /* Not applicable for FreeBSD as it uses the yarrow prng. */ (void)val; return 1; } conky-1.10.1/src/freebsd.h000066400000000000000000000006771262311664100153030ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */ #ifndef FREEBSD_H_ #define FREEBSD_H_ #include "common.h" #include #include #include #include #include #if (defined(i386) || defined(__i386__)) #include #endif /* i386 || __i386__ */ int get_entropy_avail(unsigned int *); int get_entropy_poolsize(unsigned int *); #endif /*FREEBSD_H_*/ conky-1.10.1/src/fs.cc000066400000000000000000000147221262311664100144330ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "fs.h" #include "specials.h" #include "text_object.h" #include #include #include #include #include #ifdef HAVE_SYS_STATFS_H #include #endif #if defined(__FreeBSD__) #include "freebsd.h" #elif defined(__DragonFly__) #include "dragonfly.h" #endif #if !defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && \ !defined (__OpenBSD__) && !defined(__FreeBSD__) && !defined(__DragonFly__) #include #endif #define MAX_FS_STATS 64 static struct fs_stat fs_stats_[MAX_FS_STATS]; struct fs_stat *fs_stats = fs_stats_; static void update_fs_stat(struct fs_stat *fs); void get_fs_type(const char *path, char *result); int update_fs_stats(void) { unsigned i; static double last_fs_update = 0.0; if (current_update_time - last_fs_update < 13) return 0; for (i = 0; i < MAX_FS_STATS; ++i) { if (fs_stats[i].set) { update_fs_stat(&fs_stats[i]); } } last_fs_update = current_update_time; return 0; } void clear_fs_stats(void) { unsigned i; for (i = 0; i < MAX_FS_STATS; ++i) { memset(&fs_stats[i], 0, sizeof(struct fs_stat)); } } struct fs_stat *prepare_fs_stat(const char *s) { struct fs_stat *next = 0; unsigned i; /* lookup existing or get new */ for (i = 0; i < MAX_FS_STATS; ++i) { if (fs_stats[i].set) { if (strncmp(fs_stats[i].path, s, DEFAULT_TEXT_BUFFER_SIZE) == 0) { return &fs_stats[i]; } } else { next = &fs_stats[i]; } } /* new path */ if (!next) { NORM_ERR("too many fs stats"); return 0; } strncpy(next->path, s, DEFAULT_TEXT_BUFFER_SIZE); next->set = 1; update_fs_stat(next); return next; } static void update_fs_stat(struct fs_stat *fs) { struct statfs64 s; if (statfs64(fs->path, &s) == 0) { fs->size = (long long)s.f_blocks * s.f_bsize; /* bfree (root) or bavail (non-roots) ? */ fs->avail = (long long)s.f_bavail * s.f_bsize; fs->free = (long long)s.f_bfree * s.f_bsize; get_fs_type(fs->path, fs->type); } else { NORM_ERR("statfs64 '%s': %s", fs->path, strerror(errno)); fs->size = 0; fs->avail = 0; fs->free = 0; strncpy(fs->type, "unknown", DEFAULT_TEXT_BUFFER_SIZE); } } void get_fs_type(const char *path, char *result) { #if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || \ defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__) struct statfs64 s; if (statfs64(path, &s) == 0) { strncpy(result, s.f_fstypename, DEFAULT_TEXT_BUFFER_SIZE); } else { NORM_ERR("statfs64 '%s': %s", path, strerror(errno)); } return; #else /* HAVE_STRUCT_STATFS_F_FSTYPENAME */ struct mntent *me; FILE *mtab = setmntent("/etc/mtab", "r"); char *search_path; int match; char *slash; if (mtab == NULL) { NORM_ERR("setmntent /etc/mtab: %s", strerror(errno)); strncpy(result, "unknown", DEFAULT_TEXT_BUFFER_SIZE); return; } me = getmntent(mtab); // find our path in the mtab search_path = strdup(path); do { while ((match = strcmp(search_path, me->mnt_dir)) && getmntent(mtab)); if (!match) break; fseek(mtab, 0, SEEK_SET); slash = strrchr(search_path, '/'); if (slash == NULL) CRIT_ERR(NULL, NULL, "invalid path '%s'", path); if (strlen(slash) == 1) /* trailing slash */ *(slash) = '\0'; else if (strlen(slash) > 1) *(slash + 1) = '\0'; else CRIT_ERR(NULL, NULL, "found a crack in the matrix!"); } while (strlen(search_path) > 0); free(search_path); endmntent(mtab); if (me && !match) { strncpy(result, me->mnt_type, DEFAULT_TEXT_BUFFER_SIZE); return; } #endif /* HAVE_STRUCT_STATFS_F_FSTYPENAME */ strncpy(result, "unknown", DEFAULT_TEXT_BUFFER_SIZE); } void init_fs_bar(struct text_object *obj, const char *arg) { arg = scan_bar(obj, arg, 1); if (arg) { while (isspace(*arg)) { arg++; } if (*arg == '\0') { arg = "/"; } } else { arg = "/"; } obj->data.opaque = prepare_fs_stat(arg); } static double get_fs_perc(struct text_object *obj, bool get_free) { struct fs_stat *fs = static_cast(obj->data.opaque); double ret = 0.0; if(fs && fs->size) { if(get_free) ret = fs->avail; else ret = fs->size - fs->free; ret /= fs->size; } return ret; } double fs_barval(struct text_object *obj) { return get_fs_perc(obj, false); } double fs_free_barval(struct text_object *obj) { return get_fs_perc(obj, true); } void init_fs(struct text_object *obj, const char *arg) { obj->data.opaque = prepare_fs_stat(arg ? arg : "/"); } uint8_t fs_free_percentage(struct text_object *obj) { return get_fs_perc(obj, true) * 100; } uint8_t fs_used_percentage(struct text_object *obj) { return get_fs_perc(obj, false) * 100; } #define HUMAN_PRINT_FS_GENERATOR(name, expr) \ void print_fs_##name(struct text_object *obj, char *p, int p_max_size) \ { \ struct fs_stat *fs = (struct fs_stat *)obj->data.opaque; \ if (fs) \ human_readable(expr, p, p_max_size); \ } HUMAN_PRINT_FS_GENERATOR(free, fs->avail) HUMAN_PRINT_FS_GENERATOR(size, fs->size) HUMAN_PRINT_FS_GENERATOR(used, fs->size - fs->free) void print_fs_type(struct text_object *obj, char *p, int p_max_size) { struct fs_stat *fs = (struct fs_stat *)obj->data.opaque; if (fs) snprintf(p, p_max_size, "%s", fs->type); } conky-1.10.1/src/fs.h000066400000000000000000000041731262311664100142740ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _FS_H #define _FS_H #include "conky.h" /* DEFAULT_TEXT_BUFFER_SIZE */ /* needed here and by fs.c */ struct fs_stat { char path[DEFAULT_TEXT_BUFFER_SIZE]; char type[DEFAULT_TEXT_BUFFER_SIZE]; long long size; long long avail; long long free; char set; }; /* forward declare to make gcc happy (fs.h <-> text_object.h include) */ struct text_object; void init_fs_bar(struct text_object *, const char *); double fs_barval(struct text_object *); double fs_free_barval(struct text_object *); void init_fs(struct text_object *, const char *); uint8_t fs_free_percentage(struct text_object *); uint8_t fs_used_percentage(struct text_object *); void print_fs_free(struct text_object *, char *, int); 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); int update_fs_stats(void); struct fs_stat *prepare_fs_stat(const char *path); void clear_fs_stats(void); #endif /* _FS_H */ conky-1.10.1/src/hddtemp.cc000066400000000000000000000133301262311664100154420ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "temphelper.h" #include "text_object.h" #include #include #include #include #include #include #include #define BUFLEN 512 static conky::simple_config_setting hddtemp_host("hddtemp_host", "localhost", false); static conky::simple_config_setting hddtemp_port("hddtemp_port", "7634", false); struct hdd_info { hdd_info() : next(0) {} struct hdd_info *next; char *dev; short temp; char unit; }; struct hdd_info hdd_info_head; static void __free_hddtemp_info(struct hdd_info *hdi) { if (hdi->next) __free_hddtemp_info(hdi->next); free(hdi->dev); delete hdi; } static void free_hddtemp_info(void) { DBGP("free_hddtemp_info() called"); if (!hdd_info_head.next) return; __free_hddtemp_info(hdd_info_head.next); hdd_info_head.next = NULL; } static void add_hddtemp_info(char *dev, short temp, char unit) { struct hdd_info *hdi = &hdd_info_head; DBGP("add_hddtemp_info(%s, %d, %c) being called", dev, temp, unit); while (hdi->next) hdi = hdi->next; hdi->next = new hdd_info; memset(hdi->next, 0, sizeof(struct hdd_info)); hdi->next->dev = strdup(dev); hdi->next->temp = temp; hdi->next->unit = unit; } static char *fetch_hddtemp_output(void) { int sockfd; char *buf = NULL; int buflen, offset = 0, rlen; struct addrinfo hints, *result, *rp; int i; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; /* XXX: hddtemp has no ipv6 support (yet?) */ hints.ai_socktype = SOCK_STREAM; if ((i = getaddrinfo(hddtemp_host.get(*state).c_str(), hddtemp_port.get(*state).c_str(), &hints, &result))) { NORM_ERR("getaddrinfo(): %s", gai_strerror(i)); return NULL; } for (rp = result; rp; rp = rp->ai_next) { sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sockfd == -1) continue; if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1) break; close(sockfd); } if (!rp) { NORM_ERR("could not connect to hddtemp host"); goto GET_OUT; } buflen = 1024; buf = (char*)malloc(buflen); while ((rlen = recv(sockfd, buf + offset, buflen - offset - 1, 0)) > 0) { offset += rlen; if (buflen - offset < 1) { buflen += 1024; buf = (char*)realloc(buf, buflen); } } if (rlen < 0) perror("recv"); buf[offset] = '\0'; close(sockfd); GET_OUT: freeaddrinfo(result); return buf; } /* this is an iterator: * set line to NULL in consecutive calls to get the next field * note that exhausing iteration is assumed - otherwise *saveptr * is not being freed! */ static int read_hdd_val(const char *line, char **dev, short *val, char *unit, char **saveptr) { char *line_s, *cval, *endptr; static char *p = 0; if (line) { *saveptr = strdup(line); p = *saveptr; } line_s = *saveptr; again: if(!*p) goto out_fail; /* read the device */ *dev = ++p; if (!(p = strchr(p, line_s[0]))) goto out_fail; *(p++) = '\0'; /* jump over the devname */ if (!(p = strchr(p, line_s[0]))) goto out_fail; /* read the value */ cval = ++p; if (!(p = strchr(p, line_s[0]))) goto out_fail; *(p++) = '\0'; *unit = *(p++); *val = strtol(cval, &endptr, 10); if (*endptr) { if (!(p = strchr(p, line_s[0]))) goto out_fail; p++; goto again; } /* preset p for next call */ p++; return 0; out_fail: free(*saveptr); return 1; } 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 0; last_hddtemp_update = current_update_time; free_hddtemp_info(); if (!(data = fetch_hddtemp_output())) return 0; if (read_hdd_val(data, &dev, &val, &unit, &saveptr)) { free(data); 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) { free_hddtemp_info(); free_and_zero(obj->data.s); } static int get_hddtemp_info(const char *dev, short *val, char *unit) { struct hdd_info *hdi = hdd_info_head.next; /* if no dev is given, just use hdd_info_head->next */ while(dev && hdi) { if (!strcmp(dev, hdi->dev)) break; hdi = hdi->next; } if (!hdi) return 1; *val = hdi->temp; *unit = hdi->unit; return 0; } void print_hddtemp(struct text_object *obj, char *p, int p_max_size) { short val; char unit; if (get_hddtemp_info(obj->data.s, &val, &unit)) { snprintf(p, p_max_size, "N/A"); } else { temp_print(p, p_max_size, (double)val, (unit == 'C' ? TEMP_CELSIUS : TEMP_FAHRENHEIT)); } } conky-1.10.1/src/hddtemp.h000066400000000000000000000022431262311664100153050ustar00rootroot00000000000000/* -*- 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) 2007 Toni Spets * Copyright (c) 2005-2012 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 HDDTEMP_H_ #define HDDTEMP_H_ int update_hddtemp(void); void free_hddtemp(struct text_object *); void print_hddtemp(struct text_object *, char *, int); #endif /*HDDTEMP_H_*/ conky-1.10.1/src/i18n.h000066400000000000000000000022131262311664100144340ustar00rootroot00000000000000/* -*- 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-2012 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 I18N_H_ #define I18N_H_ #define _nop(string) string #ifdef BUILD_I18N #include #define _(string) gettext(string) #else #define _(string) string #endif #endif /*I18N_H_*/ conky-1.10.1/src/i8k.cc000066400000000000000000000104501262311664100145100ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2007 Toni Spets * Copyright (c) 2005-2012 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 #include #include "conky.h" #include "logging.h" #include "temphelper.h" #include "text_object.h" struct _i8k { char *version; char *bios; char *serial; char *cpu_temp; char *left_fan_status; char *right_fan_status; char *left_fan_rpm; char *right_fan_rpm; char *ac_status; char *buttons_status; } i8k; /* FIXME: there should be an ioctl interface to request specific data */ #define PROC_I8K "/proc/i8k" #define I8K_DELIM " " static char *i8k_procbuf = NULL; int update_i8k(void) { FILE *fp; if (!i8k_procbuf) { i8k_procbuf = (char *) malloc(128 * sizeof(char)); } if ((fp = fopen(PROC_I8K, "r")) == NULL) { 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); return 1; } memset(&i8k_procbuf[0], 0, 128); if (fread(&i8k_procbuf[0], sizeof(char), 128, fp) == 0) { NORM_ERR("something wrong with /proc/i8k..."); } fclose(fp); DBGP("read `%s' from /proc/i8k\n", i8k_procbuf); i8k.version = strtok(&i8k_procbuf[0], I8K_DELIM); i8k.bios = strtok(NULL, I8K_DELIM); i8k.serial = strtok(NULL, I8K_DELIM); i8k.cpu_temp = strtok(NULL, I8K_DELIM); i8k.left_fan_status = strtok(NULL, I8K_DELIM); i8k.right_fan_status = strtok(NULL, I8K_DELIM); i8k.left_fan_rpm = strtok(NULL, I8K_DELIM); 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 void print_i8k_fan_status(char *p, int p_max_size, const char *status) { static const char *status_arr[] = { "off", "low", "high", "error" }; int i = status ? atoi(status) : 3; if(i < 0 || i > 3) i = 3; snprintf(p, p_max_size, "%s", status_arr[i]); } void print_i8k_left_fan_status(struct text_object *obj, char *p, int p_max_size) { (void)obj; print_i8k_fan_status(p, p_max_size, i8k.left_fan_status); } void print_i8k_cpu_temp(struct text_object *obj, char *p, int p_max_size) { int cpu_temp; (void)obj; sscanf(i8k.cpu_temp, "%d", &cpu_temp); temp_print(p, p_max_size, (double)cpu_temp, TEMP_CELSIUS); } void print_i8k_right_fan_status(struct text_object *obj, char *p, int p_max_size) { (void)obj; print_i8k_fan_status(p, p_max_size, i8k.right_fan_status); } void print_i8k_ac_status(struct text_object *obj, char *p, int p_max_size) { int ac_status; (void)obj; sscanf(i8k.ac_status, "%d", &ac_status); if (ac_status == -1) { snprintf(p, p_max_size, "disabled (read i8k docs)"); } if (ac_status == 0) { snprintf(p, p_max_size, "off"); } if (ac_status == 1) { snprintf(p, p_max_size, "on"); } } #define I8K_PRINT_GENERATOR(name) \ void print_i8k_##name(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ snprintf(p, p_max_size, "%s", i8k.name); \ } I8K_PRINT_GENERATOR(version) I8K_PRINT_GENERATOR(bios) I8K_PRINT_GENERATOR(serial) I8K_PRINT_GENERATOR(left_fan_rpm) I8K_PRINT_GENERATOR(right_fan_rpm) I8K_PRINT_GENERATOR(buttons_status) #undef I8K_PRINT_GENERATOR conky-1.10.1/src/i8k.h000066400000000000000000000035561262311664100143630ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2007 Toni Spets * Copyright (c) 2005-2012 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 _I8K_H #define _I8K_H 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); void print_i8k_ac_status(struct text_object *, char *, int); void print_i8k_version(struct text_object *, char *, int); void print_i8k_bios(struct text_object *, char *, int); void print_i8k_serial(struct text_object *, char *, int); void print_i8k_left_fan_rpm(struct text_object *, char *, int); void print_i8k_right_fan_rpm(struct text_object *, char *, int); void print_i8k_buttons_status(struct text_object *, char *, int); #endif /* _I8K_H */ conky-1.10.1/src/ibm.cc000066400000000000000000000176761262311664100146050ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2007 Toni Spets * Copyright (c) 2005-2012 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 "config.h" #include "ibm.h" #include "logging.h" #include "temphelper.h" #include #include #include #include #include static int ibm_acpi_temps[8]; /* Here come the IBM ACPI-specific things. For reference, see * http://ibm-acpi.sourceforge.net/README * If IBM ACPI is installed, /proc/acpi/ibm contains the following files: bay beep bluetooth brightness cmos dock driver ecdump fan hotkey led light thermal video volume * The content of these files is described in detail in the aforementioned * README - some of them also in the following functions accessing them. * Peter Tarjan (ptarjan@citromail.hu) */ #define IBM_ACPI_DIR "/proc/acpi/ibm" /* get fan speed on IBM/Lenovo laptops running the ibm acpi. * /proc/acpi/ibm/fan looks like this (3 lines): status: disabled speed: 2944 commands: enable, disable * Peter Tarjan (ptarjan@citromail.hu) */ void get_ibm_acpi_fan(struct text_object *obj, char *p, int p_max_size) { FILE *fp; unsigned int speed = 0; char fan[128]; (void)obj; if (!p || p_max_size <= 0) { return; } snprintf(fan, 127, "%s/fan", IBM_ACPI_DIR); fp = fopen(fan, "r"); if (fp != NULL) { while (!feof(fp)) { char line[256]; if (fgets(line, 255, fp) == NULL) { break; } if (sscanf(line, "speed: %u", &speed)) { break; } } } else { CRIT_ERR(NULL, NULL, "can't open '%s': %s\nYou are not using the IBM ACPI. Remove " "ibm* from your " PACKAGE_NAME" config file.", fan, strerror(errno)); } fclose(fp); snprintf(p, p_max_size, "%d", speed); } /* get the measured temperatures from the temperature sensors * on IBM/Lenovo laptops running the ibm acpi. * There are 8 values in /proc/acpi/ibm/thermal, and according to * http://ibm-acpi.sourceforge.net/README * these mean the following (at least on an IBM R51...) * 0: CPU (also on the T series laptops) * 1: Mini PCI Module (?) * 2: HDD (?) * 3: GPU (also on the T series laptops) * 4: Battery (?) * 5: N/A * 6: Battery (?) * 7: N/A * I'm not too sure about those with the question mark, but the values I'm * reading from *my* thermal file (on a T42p) look realistic for the * hdd and the battery. * #5 and #7 are always -128. * /proc/acpi/ibm/thermal looks like this (1 line): temperatures: 41 43 31 46 33 -128 29 -128 * Peter Tarjan (ptarjan@citromail.hu) */ int get_ibm_acpi_temps(void) { FILE *fp; char thermal[128]; snprintf(thermal, 127, "%s/thermal", IBM_ACPI_DIR); fp = fopen(thermal, "r"); if (fp != NULL) { while (!feof(fp)) { char line[256]; if (fgets(line, 255, fp) == NULL) { break; } if (sscanf(line, "temperatures: %d %d %d %d %d %d %d %d", &ibm_acpi_temps[0], &ibm_acpi_temps[1], &ibm_acpi_temps[2], &ibm_acpi_temps[3], &ibm_acpi_temps[4], &ibm_acpi_temps[5], &ibm_acpi_temps[6], &ibm_acpi_temps[7])) { break; } } } else { CRIT_ERR(NULL, NULL, "can't open '%s': %s\nYou are not using the IBM ACPI. Remove " "ibm* from your " PACKAGE_NAME" config file.", thermal, strerror(errno)); } fclose(fp); return 0; } /* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi. * "Volume" here is none of the mixer volumes, but a "master of masters" * volume adjusted by the IBM volume keys. * /proc/acpi/ibm/fan looks like this (4 lines): level: 4 mute: off commands: up, down, mute commands: level ( is 0-15) * Peter Tarjan (ptarjan@citromail.hu) */ void get_ibm_acpi_volume(struct text_object *obj, char *p, int p_max_size) { FILE *fp; char volume[128]; unsigned int vol = -1; char mute[3] = ""; (void)obj; if (!p || p_max_size <= 0) { return; } snprintf(volume, 127, "%s/volume", IBM_ACPI_DIR); fp = fopen(volume, "r"); if (fp != NULL) { while (!feof(fp)) { char line[256]; unsigned int read_vol = -1; if (fgets(line, 255, fp) == NULL) { break; } if (sscanf(line, "level: %u", &read_vol)) { vol = read_vol; continue; } if (sscanf(line, "mute: %s", mute)) { break; } } } else { CRIT_ERR(NULL, NULL, "can't open '%s': %s\nYou are not using the IBM ACPI. Remove " "ibm* from your " PACKAGE_NAME" config file.", volume, strerror(errno)); } fclose(fp); if (strcmp(mute, "on") == 0) snprintf(p, p_max_size, "%s", "mute"); else snprintf(p, p_max_size, "%d", vol); } /* static FILE *fp = NULL; */ /* get LCD brightness on IBM/Lenovo laptops running the ibm acpi. * /proc/acpi/ibm/brightness looks like this (3 lines): level: 7 commands: up, down commands: level ( is 0-7) * Peter Tarjan (ptarjan@citromail.hu) */ void get_ibm_acpi_brightness(struct text_object *obj, char *p, int p_max_size) { FILE *fp; unsigned int brightness = 0; char filename[128]; (void)obj; if (!p || p_max_size <= 0) { return; } snprintf(filename, 127, "%s/brightness", IBM_ACPI_DIR); fp = fopen(filename, "r"); if (fp != NULL) { while (!feof(fp)) { char line[256]; if (fgets(line, 255, fp) == NULL) { break; } if (sscanf(line, "level: %u", &brightness)) { break; } } } else { CRIT_ERR(NULL, NULL, "can't open '%s': %s\nYou are not using the IBM ACPI. Remove " "ibm* from your " PACKAGE_NAME" config file.", filename, strerror(errno)); } fclose(fp); snprintf(p, p_max_size, "%d", brightness); } /* get ThinkLight status on IBM/Lenovo laptops running the ibm acpi. * /proc/acpi/ibm/light looks like this (2 lines): status: off commands: on, off * http://ibm-acpi.sourceforge.net/README reports that it's also possible to * get "unknown" for a few models that do not make the status available. * Lluis Esquerda (eskerda@gmail.com) */ void get_ibm_acpi_thinklight(struct text_object *obj, char *p, int p_max_size) { FILE *fp; char thinklight[8]; char filename[128]; (void)obj; if (!p || p_max_size <= 0) { return; } snprintf(filename, 127, "%s/light", IBM_ACPI_DIR); fp = fopen(filename, "r"); if (fp != NULL) { while (!feof(fp)) { char line[256]; if (fgets(line, 255, fp) == NULL) { break; } if (sscanf(line, "status: %s", thinklight)) { break; } } } else { CRIT_ERR(NULL, NULL, "can't open '%s': %s\nYou are not using the IBM " "ACPI. Remove ibm* from your " PACKAGE_NAME" config file.", filename, strerror(errno)); } fclose(fp); snprintf(p, p_max_size, "%s", thinklight); } void parse_ibm_temps_arg(struct text_object *obj, const char *arg) { if (!isdigit(arg[0]) || strlen(arg) > 1 || atoi(&arg[0]) >= 8) { obj->data.l = 0; NORM_ERR("Invalid temperature sensor! Sensor number must be 0 to 7. " "Using 0 (CPU temp sensor)."); } else obj->data.l = atoi(arg); } void print_ibm_temps(struct text_object *obj, char *p, int p_max_size) { temp_print(p, p_max_size, ibm_acpi_temps[obj->data.l], TEMP_CELSIUS); } conky-1.10.1/src/ibm.h000066400000000000000000000026151262311664100144320ustar00rootroot00000000000000/* -*- 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-2012 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 _IBM_H #define _IBM_H void get_ibm_acpi_fan(struct text_object *, char *, int); 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); void get_ibm_acpi_thinklight(struct text_object *, char *, int); void parse_ibm_temps_arg(struct text_object *, const char *); void print_ibm_temps(struct text_object *, char *, int); #endif /* _IBM_H */ conky-1.10.1/src/ical.cc000066400000000000000000000125101262311664100147240ustar00rootroot00000000000000/* -*- 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-2012 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); } conky-1.10.1/src/ical.h000066400000000000000000000022401262311664100145650ustar00rootroot00000000000000/* -*- 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-2012 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_*/ conky-1.10.1/src/iconv_tools.cc000066400000000000000000000077271262311664100163700ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "logging.h" #include "text_object.h" #include #include #include #include #define ICONV_CODEPAGE_LENGTH 20 static long iconv_selected; static long iconv_count = 0; static char iconv_converting = 0; static iconv_t **iconv_cd = 0; int register_iconv(iconv_t *new_iconv) { iconv_cd = (void ***) realloc(iconv_cd, sizeof(iconv_t *) * (iconv_count + 1)); if (!iconv_cd) { CRIT_ERR(NULL, NULL, "Out of memory"); } iconv_cd[iconv_count] = (void **) malloc(sizeof(iconv_t)); if (!iconv_cd[iconv_count]) { CRIT_ERR(NULL, NULL, "Out of memory"); } memcpy(iconv_cd[iconv_count], new_iconv, sizeof(iconv_t)); iconv_count++; return iconv_count; } void free_iconv(struct text_object *obj) { long i; (void)obj; if (!iconv_cd) return; for (i = 0; i < iconv_count; i++) { if (iconv_cd[i]) { iconv_close(*iconv_cd[i]); free(iconv_cd[i]); } } free(iconv_cd); iconv_cd = 0; } void iconv_convert(size_t *a, char *buff_in, char *p, size_t p_max_size) { int bytes; size_t dummy1, dummy2; #if defined(__FreeBSD__) || defined(__DragonFly__) const char *ptr = buff_in; #else char *ptr = buff_in; #endif char *outptr = p; if (*a <= 0 || !iconv_converting || iconv_selected <= 0 || iconv_cd[iconv_selected - 1] == (iconv_t) (-1)) return; dummy1 = dummy2 = *a; strncpy(buff_in, p, p_max_size); iconv(*iconv_cd[iconv_selected - 1], NULL, NULL, NULL, NULL); while (dummy1 > 0) { bytes = iconv(*iconv_cd[iconv_selected - 1], &ptr, &dummy1, &outptr, &dummy2); if (bytes == -1) { NORM_ERR("Iconv codeset conversion failed"); break; } } /* It is nessecary when we are converting from multibyte to * singlebyte codepage */ //a = outptr - p; //(*a) = *a - dummy2; (*a) = outptr - p; } void init_iconv_start(struct text_object *obj, void *free_at_crash, const char *arg) { char iconv_from[ICONV_CODEPAGE_LENGTH]; char iconv_to[ICONV_CODEPAGE_LENGTH]; if (iconv_converting) { CRIT_ERR(obj, free_at_crash, "You must stop your last iconv conversion before " "starting another"); } if (sscanf(arg, "%s %s", iconv_from, iconv_to) != 2) { CRIT_ERR(obj, free_at_crash, "Invalid arguments for iconv_start"); } else { iconv_t new_iconv; new_iconv = iconv_open(iconv_to, iconv_from); if (new_iconv == (iconv_t) (-1)) { NORM_ERR("Can't convert from %s to %s.", iconv_from, iconv_to); } else { obj->data.i = register_iconv(&new_iconv); iconv_converting = 1; } } } void init_iconv_stop(void) { iconv_converting = 0; } void print_iconv_start(struct text_object *obj, char *p, int p_max_size) { (void)p; (void)p_max_size; iconv_converting = 1; iconv_selected = obj->data.i; } void print_iconv_stop(struct text_object *obj, char *p, int p_max_size) { (void)obj; (void)p; (void)p_max_size; iconv_converting = 0; iconv_selected = 0; } conky-1.10.1/src/iconv_tools.h000066400000000000000000000030151262311664100162140ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _ICONV_TOOLS_H #define _ICONV_TOOLS_H void free_iconv(struct text_object *); void iconv_convert(size_t *, char *, char *, size_t); void init_iconv_start(struct text_object *, void *, const char *); void init_iconv_stop(void); void print_iconv_start(struct text_object *, char *, int); void print_iconv_stop(struct text_object *, char *, int); #endif /* _ICONV_TOOLS_H */ conky-1.10.1/src/imlib2.cc000066400000000000000000000163521262311664100152020ustar00rootroot00000000000000/* -*- 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-2012 Brenden Matthews, et. al. * 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 "config.h" #include "conky.h" #include "logging.h" #include "text_object.h" #include "imlib2.h" #include #include #include #include #include #include #include "x11.h" struct image_list_s { char name[1024]; Imlib_Image image; int x, y, w, h; int wh_set; char no_cache; int flush_interval; struct image_list_s *next; }; struct image_list_s *image_list_start, *image_list_end; /* areas to update */ Imlib_Updates updates, current_update; /* our virtual framebuffer image we draw into */ Imlib_Image buffer, image; namespace { Imlib_Context context; conky::range_config_setting imlib_cache_flush_interval( "imlib_cache_flush_interval", 0, std::numeric_limits::max(), 0, true ); unsigned int cimlib_cache_flush_last = 0; } void imlib_cache_size_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && out_to_x.get(l)) { image_list_start = image_list_end = NULL; context = imlib_context_new(); imlib_context_push(context); imlib_set_cache_size(do_convert(l, -1).first); /* set the maximum number of colors to allocate for 8bpp and less to 256 */ imlib_set_color_usage(256); /* dither for depths < 24bpp */ imlib_context_set_dither(1); /* set the display , visual, colormap and drawable we are using */ imlib_context_set_display(display); imlib_context_set_visual(window.visual); imlib_context_set_colormap(window.colourmap); imlib_context_set_drawable(window.drawable); } ++s; } void imlib_cache_size_setting::cleanup(lua::state &l) { lua::stack_sentry s(l, -1); if(out_to_x.get(l)) { cimlib_cleanup(); imlib_context_disconnect_display(); imlib_context_pop(); imlib_context_free(context); } } void cimlib_cleanup(void) { struct image_list_s *cur = image_list_start, *last = NULL; while (cur) { last = cur; cur = last->next; free(last); } image_list_start = image_list_end = NULL; } void cimlib_add_image(const char *args) { struct image_list_s *cur = NULL; const char *tmp; cur = (struct image_list_s *)malloc(sizeof(struct image_list_s)); memset(cur, 0, sizeof(struct image_list_s)); if (!sscanf(args, "%1023s", cur->name)) { NORM_ERR("Invalid args for $image. Format is: ' (-p" "x,y) (-s WxH) (-n) (-f interval)' (got '%s')", args); free(cur); return; } strncpy(cur->name, to_real_path(cur->name).c_str(), 1024); cur->name[1023] = 0; // // now we check for optional args tmp = strstr(args, "-p "); if (tmp) { tmp += 3; sscanf(tmp, "%i,%i", &cur->x, &cur->y); } tmp = strstr(args, "-s "); if (tmp) { tmp += 3; if (sscanf(tmp, "%ix%i", &cur->w, &cur->h)) { cur->wh_set = 1; } } tmp = strstr(args, "-n"); if (tmp) { cur->no_cache = 1; } tmp = strstr(args, "-f "); if (tmp) { tmp += 3; if (sscanf(tmp, "%d", &cur->flush_interval)) { cur->no_cache = 0; } } if (cur->flush_interval < 0) { NORM_ERR("Imlib2: flush interval should be >= 0"); cur->flush_interval = 0; } if (image_list_end) { image_list_end->next = cur; image_list_end = cur; } else { image_list_start = image_list_end = cur; } } static void cimlib_draw_image(struct image_list_s *cur, int *clip_x, int *clip_y, int *clip_x2, int *clip_y2) { int w, h; time_t now = time(NULL); static int rep = 0; if (imlib_context_get_drawable() != window.drawable) { imlib_context_set_drawable(window.drawable); } image = imlib_load_image(cur->name); if (!image) { if (!rep) NORM_ERR("Unable to load image '%s'", cur->name); rep = 1; return; } rep = 0; /* reset so disappearing images are reported */ DBGP("Drawing image '%s' at (%i,%i) scaled to %ix%i, " "caching interval set to %i (with -n opt %i)", cur->name, cur->x, cur->y, cur->w, cur->h, cur->flush_interval, cur->no_cache); imlib_context_set_image(image); /* turn alpha channel on */ imlib_image_set_has_alpha(1); w = imlib_image_get_width(); h = imlib_image_get_height(); if (!cur->wh_set) { cur->w = w; cur->h = h; } imlib_context_set_image(buffer); imlib_blend_image_onto_image(image, 1, 0, 0, w, h, cur->x, cur->y, cur->w, cur->h); imlib_context_set_image(image); if (cur->no_cache || (cur->flush_interval && now % cur->flush_interval == 0)) { imlib_free_image_and_decache(); } else { imlib_free_image(); } if (cur->x < *clip_x) *clip_x = cur->x; if (cur->y < *clip_y) *clip_y = cur->y; if (cur->x + cur->w > *clip_x2) *clip_x2 = cur->x + cur->w; if (cur->y + cur->h > *clip_y2) *clip_y2 = cur->y + cur->h; } static void cimlib_draw_all(int *clip_x, int *clip_y, int *clip_x2, int *clip_y2) { struct image_list_s *cur = image_list_start; while (cur) { cimlib_draw_image(cur, clip_x, clip_y, clip_x2, clip_y2); cur = cur->next; } } void cimlib_render(int x, int y, int width, int height) { int clip_x = INT_MAX, clip_y = INT_MAX; int clip_x2 = 0, clip_y2 = 0; time_t now; if (!image_list_start) return; /* are we actually drawing anything? */ /* cheque if it's time to flush our cache */ now = time(NULL); if (imlib_cache_flush_interval.get(*state) && now - imlib_cache_flush_interval.get(*state) > cimlib_cache_flush_last) { int size = imlib_get_cache_size(); imlib_set_cache_size(0); imlib_set_cache_size(size); cimlib_cache_flush_last = now; DBGP("Flushing Imlib2 cache (%li)\n", now); } /* take all the little rectangles to redraw and merge them into * something sane for rendering */ buffer = imlib_create_image(width, height); /* clear our buffer */ imlib_context_set_image(buffer); imlib_image_clear(); /* we can blend stuff now */ imlib_context_set_blend(1); /* turn alpha channel on */ imlib_image_set_has_alpha(1); cimlib_draw_all(&clip_x, &clip_y, &clip_x2, &clip_y2); /* set the buffer image as our current image */ imlib_context_set_image(buffer); /* setup our clip rect */ if (clip_x == INT_MAX) clip_x = 0; if (clip_y == INT_MAX) clip_y = 0; /* render the image at 0, 0 */ imlib_render_image_part_on_drawable_at_size(clip_x, clip_y, clip_x2 - clip_x, clip_y2 - clip_y, x + clip_x, y + clip_y, clip_x2 - clip_x, clip_y2 - clip_y); /* don't need that temporary buffer image anymore */ imlib_free_image(); } void print_image_callback(struct text_object *obj, char *p, int p_max_size) { (void)p; (void)p_max_size; cimlib_add_image(obj->data.s); } conky-1.10.1/src/imlib2.h000066400000000000000000000032541262311664100150410ustar00rootroot00000000000000/* -*- 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-2012 Brenden Matthews, et. al. * 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 _CONKY_IMBLI2_H_ #define _CONKY_IMBLI2_H_ #include void cimlib_add_image(const char *name); void cimlib_set_cache_size(long size); void cimlib_set_cache_flush_interval(long interval); void cimlib_render(int x, int y, int width, int height); void cimlib_cleanup(void); void print_image_callback(struct text_object *, char *, int); class imlib_cache_size_setting: public conky::range_config_setting { typedef conky::range_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); virtual void cleanup(lua::state &l); public: imlib_cache_size_setting() : Base("imlib_cache_size", 0, std::numeric_limits::max(), 4096*1024, true) {} }; #endif /* _CONKY_IMBLI2_H_ */ conky-1.10.1/src/irc.cc000066400000000000000000000135551262311664100146030ustar00rootroot00000000000000/* -*- 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-2012 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; } } conky-1.10.1/src/irc.h000066400000000000000000000022141262311664100144330ustar00rootroot00000000000000/* -*- 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-2012 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_*/ conky-1.10.1/src/libmpdclient.cc000066400000000000000000001565371262311664100165040ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * libmpdclient * (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * This project's homepage is: http://www.musicpd.org * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Music Player Daemon nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "conky.h" #include "libmpdclient.h" #include #include #include #include #include #include #include #ifdef WIN32 # include # include #else # include # include # include # include # include #endif /* (bits + 1) / 3 (plus the sign character) */ #define INTLEN ((sizeof(int) * CHAR_BIT + 1) / 3 + 1) #define LONGLONGLEN ((sizeof(long long) * CHAR_BIT + 1) / 3 + 1) #define COMMAND_LIST 1 #define COMMAND_LIST_OK 2 #ifndef MPD_NO_GAI # ifdef AI_ADDRCONFIG # define MPD_HAVE_GAI # endif #endif #ifndef MSG_DONTWAIT # define MSG_DONTWAIT 0 #endif #ifdef WIN32 # define SELECT_ERRNO_IGNORE (errno == WSAEINTR || errno == WSAEINPROGRESS) # define SENDRECV_ERRNO_IGNORE SELECT_ERRNO_IGNORE #else # define SELECT_ERRNO_IGNORE (errno == EINTR) # define SENDRECV_ERRNO_IGNORE (errno == EINTR || errno == EAGAIN) # define winsock_dll_error(c) 0 # define closesocket(s) close(s) # define WSACleanup() do { /* nothing */ } while (0) #endif #ifdef WIN32 static int winsock_dll_error(mpd_Connection *connection) { WSADATA wsaData; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0 || LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { strcpy(connection->errorStr, "Could not find usable WinSock DLL."); connection->error = MPD_ERROR_SYSTEM; return 1; } return 0; } static int do_connect_fail(mpd_Connection *connection, const struct sockaddr *serv_addr, int addrlen) { int iMode = 1; /* 0 = blocking, else non-blocking */ ioctlsocket(connection->sock, FIONBIO, (u_long FAR *) &iMode); return (connect(connection->sock, serv_addr, addrlen) == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK); } #else /* !WIN32 (sane operating systems) */ static int do_connect_fail(mpd_Connection *connection, const struct sockaddr *serv_addr, int addrlen) { int flags = fcntl(connection->sock, F_GETFL, 0); fcntl(connection->sock, F_SETFL, flags | O_NONBLOCK); return (connect(connection->sock, serv_addr, addrlen) < 0 && errno != EINPROGRESS); } #endif /* !WIN32 */ static int uds_connect(mpd_Connection *connection, const char *host, float timeout) { struct sockaddr_un addr; strncpy(addr.sun_path, host, sizeof(addr.sun_path)-1); addr.sun_family = AF_UNIX; addr.sun_path[sizeof(addr.sun_path)-1] = 0; connection->sock = socket(AF_UNIX, SOCK_STREAM, 0); if (connection->sock < 0) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems creating socket: %s", strerror(errno)); connection->error = MPD_ERROR_SYSTEM; return -1; } mpd_setConnectionTimeout(connection, timeout); /* connect stuff */ if (do_connect_fail(connection, (struct sockaddr *)&addr, SUN_LEN(&addr))) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems connecting socket: %s", strerror(errno)); closesocket(connection->sock); connection->sock = -1; connection->error = MPD_ERROR_SYSTEM; return -1; } return 0; } #ifdef MPD_HAVE_GAI static int mpd_connect(mpd_Connection *connection, const char *host, int port, float timeout) { int error; char service[INTLEN + 1]; struct addrinfo hints; struct addrinfo *res = NULL; struct addrinfo *addrinfo = NULL; if (*host == '/') return uds_connect(connection, host, timeout); /* Setup hints */ hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; snprintf(service, sizeof(service), "%i", port); error = getaddrinfo(host, service, &hints, &addrinfo); if (error) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "host \"%s\" not found: %s", host, gai_strerror(error)); connection->error = MPD_ERROR_UNKHOST; return -1; } for (res = addrinfo; res; res = res->ai_next) { /* create socket */ if (connection->sock > -1) { closesocket(connection->sock); } connection->sock = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); if (connection->sock < 0) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems creating socket: %s", strerror(errno)); connection->error = MPD_ERROR_SYSTEM; freeaddrinfo(addrinfo); return -1; } mpd_setConnectionTimeout(connection, timeout); /* connect stuff */ if (do_connect_fail(connection, res->ai_addr, res->ai_addrlen)) { /* try the next address family */ closesocket(connection->sock); connection->sock = -1; continue; } } freeaddrinfo(addrinfo); if (connection->sock < 0) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems connecting to \"%s\" on port %i: %s", host, port, strerror(errno)); connection->error = MPD_ERROR_CONNPORT; return -1; } return 0; } #else /* !MPD_HAVE_GAI */ static int mpd_connect(mpd_Connection *connection, const char *host, int port, float timeout) { struct hostent he, *he_res = 0; int he_errno; char hostbuff[2048]; struct sockaddr *dest; int destlen; struct sockaddr_in sin; if (*host == '/') return uds_connect(connection, host, timeout); #ifdef HAVE_GETHOSTBYNAME_R if (gethostbyname_r(host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "%s ('%s')", hstrerror(h_errno), host); connection->error = MPD_ERROR_UNKHOST; return -1; } #else /* HAVE_GETHOSTBYNAME_R */ if (!(he_res = gethostbyname(host))) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "host \"%s\" not found", host); connection->error = MPD_ERROR_UNKHOST; return -1; } #endif /* HAVE_GETHOSTBYNAME_R */ memset(&sin, 0, sizeof(struct sockaddr_in)); /* dest.sin_family = he_res->h_addrtype; */ sin.sin_family = AF_INET; sin.sin_port = htons(port); switch (he_res->h_addrtype) { case AF_INET: memcpy((char *) &sin.sin_addr.s_addr, (char *) he_res->h_addr, he_res->h_length); dest = (struct sockaddr *) &sin; destlen = sizeof(struct sockaddr_in); break; default: strcpy(connection->errorStr, "address type is not IPv4"); connection->error = MPD_ERROR_SYSTEM; return -1; break; } if (connection->sock > -1) { closesocket(connection->sock); } if ((connection->sock = socket(dest->sa_family, SOCK_STREAM, 0)) < 0) { strcpy(connection->errorStr, "problems creating socket"); connection->error = MPD_ERROR_SYSTEM; return -1; } mpd_setConnectionTimeout(connection, timeout); /* connect stuff */ if (do_connect_fail(connection, dest, destlen)) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems connecting to \"%s\" on port %i", host, port); connection->error = MPD_ERROR_CONNPORT; return -1; } return 0; } #endif /* !MPD_HAVE_GAI */ const char *mpdTagItemKeys[MPD_TAG_NUM_OF_ITEM_TYPES] = { "Artist", "Album", "Title", "Track", "Name", "Genre", "Date", "Composer", "Performer", "Comment", "Disc", "Filename", "Any" }; static char *mpd_sanitizeArg(const char *arg) { size_t i; char *ret; register const char *c; register char *rc; /* instead of counting in that loop above, * just use a bit more memory and halve running time */ ret = (char*) malloc(strlen(arg) * 2 + 1); c = arg; rc = ret; for (i = strlen(arg) + 1; i != 0; --i) { if (*c == '"' || *c == '\\') { *rc++ = '\\'; } *(rc++) = *(c++); } return ret; } static mpd_ReturnElement *mpd_newReturnElement(const char *name, const char *value) { mpd_ReturnElement *ret = (mpd_ReturnElement*) malloc(sizeof(mpd_ReturnElement)); ret->name = strndup(name, text_buffer_size.get(*state)); ret->value = strndup(value, text_buffer_size.get(*state)); return ret; } static void mpd_freeReturnElement(mpd_ReturnElement *re) { free(re->name); free(re->value); free(re); } void mpd_setConnectionTimeout(mpd_Connection *connection, float timeout) { connection->timeout.tv_sec = (int) timeout; connection->timeout.tv_usec = (int) ((timeout - connection->timeout.tv_sec) * 1e6 + 0.5); } static int mpd_parseWelcome(mpd_Connection *connection, const char *host, int port, /* char *rt, */ char *output) { char *tmp; char *test; int i; if (strncmp(output, MPD_WELCOME_MESSAGE, strlen(MPD_WELCOME_MESSAGE))) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "mpd not running on port %i on host \"%s\"", port, host); connection->error = MPD_ERROR_NOTMPD; return 1; } tmp = &output[strlen(MPD_WELCOME_MESSAGE)]; for (i = 0; i < 3; i++) { if (tmp) { connection->version[i] = strtol(tmp, &test, 10); } if (!tmp || (test[0] != '.' && test[0] != '\0')) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "error parsing version number at \"%s\"", &output[strlen(MPD_WELCOME_MESSAGE)]); connection->error = MPD_ERROR_NOTMPD; return 1; } tmp = ++test; } return 0; } mpd_Connection *mpd_newConnection(const char *host, int port, float timeout) { int err; char *rt; char *output = NULL; mpd_Connection *connection = (mpd_Connection*) malloc(sizeof(mpd_Connection)); struct timeval tv; fd_set fds; strcpy(connection->buffer, ""); connection->buflen = 0; connection->bufstart = 0; strcpy(connection->errorStr, ""); connection->error = 0; connection->doneProcessing = 0; connection->commandList = 0; connection->listOks = 0; connection->doneListOk = 0; connection->sock = -1; connection->returnElement = NULL; connection->request = NULL; if (winsock_dll_error(connection)) { return connection; } if (mpd_connect(connection, host, port, timeout) < 0) { return connection; } while (!(rt = strstr(connection->buffer, "\n"))) { tv.tv_sec = connection->timeout.tv_sec; tv.tv_usec = connection->timeout.tv_usec; FD_ZERO(&fds); FD_SET(connection->sock, &fds); if ((err = select(connection->sock + 1, &fds, NULL, NULL, &tv)) == 1) { int readed; readed = recv(connection->sock, &(connection->buffer[connection->buflen]), MPD_BUFFER_MAX_LENGTH - connection->buflen, 0); if (readed <= 0) { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems getting a response from \"%s\" on port %i : %s", host, port, strerror(errno)); connection->error = MPD_ERROR_NORESPONSE; return connection; } connection->buflen += readed; connection->buffer[connection->buflen] = '\0'; } else if (err < 0) { if (SELECT_ERRNO_IGNORE) { continue; } snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems connecting to \"%s\" on port %i", host, port); connection->error = MPD_ERROR_CONNPORT; return connection; } else { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "timeout in attempting to get a response from \"%s\" on " "port %i", host, port); connection->error = MPD_ERROR_NORESPONSE; return connection; } } *rt = '\0'; output = strndup(connection->buffer, text_buffer_size.get(*state)); strcpy(connection->buffer, rt + 1); connection->buflen = strlen(connection->buffer); if (mpd_parseWelcome(connection, host, port, /* rt, */ output) == 0) { connection->doneProcessing = 1; } free(output); return connection; } void mpd_clearError(mpd_Connection *connection) { connection->error = 0; connection->errorStr[0] = '\0'; } void mpd_closeConnection(mpd_Connection *connection) { if (connection) { closesocket(connection->sock); free_and_zero(connection->returnElement); free_and_zero(connection->request); free(connection); } WSACleanup(); } static void mpd_executeCommand(mpd_Connection *connection, const char *command) { int ret; struct timeval tv; fd_set fds; const char *commandPtr = command; int commandLen = strlen(command); if (!connection->doneProcessing && !connection->commandList) { strcpy(connection->errorStr, "not done processing current command"); connection->error = 1; return; } mpd_clearError(connection); FD_ZERO(&fds); FD_SET(connection->sock, &fds); tv.tv_sec = connection->timeout.tv_sec; tv.tv_usec = connection->timeout.tv_usec; while ((ret = select(connection->sock + 1, NULL, &fds, NULL, &tv) == 1) || (ret == -1 && SELECT_ERRNO_IGNORE)) { ret = send(connection->sock, commandPtr, commandLen, MSG_DONTWAIT); if (ret <= 0) { if (SENDRECV_ERRNO_IGNORE) { continue; } snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems giving command \"%s\"", command); connection->error = MPD_ERROR_SENDING; return; } else { commandPtr += ret; commandLen -= ret; } if (commandLen <= 0) { break; } } if (commandLen > 0) { perror(""); snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "timeout sending command \"%s\"", command); connection->error = MPD_ERROR_TIMEOUT; return; } if (!connection->commandList) { connection->doneProcessing = 0; } else if (connection->commandList == COMMAND_LIST_OK) { connection->listOks++; } } static void mpd_getNextReturnElement(mpd_Connection *connection) { char *output = NULL; char *rt = NULL; char *name = NULL; char *value = NULL; fd_set fds; struct timeval tv; char *tok = NULL; int readed; char *bufferCheck = NULL; int err; int pos; if (connection->returnElement) { mpd_freeReturnElement(connection->returnElement); } connection->returnElement = NULL; if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { strcpy(connection->errorStr, "already done processing current command"); connection->error = 1; return; } bufferCheck = connection->buffer + connection->bufstart; while (connection->bufstart >= connection->buflen || !(rt = strchr(bufferCheck, '\n'))) { if (connection->buflen >= MPD_BUFFER_MAX_LENGTH) { memmove(connection->buffer, connection->buffer + connection->bufstart, connection->buflen - connection->bufstart + 1); connection->buflen -= connection->bufstart; connection->bufstart = 0; } if (connection->buflen >= MPD_BUFFER_MAX_LENGTH) { strcpy(connection->errorStr, "buffer overrun"); connection->error = MPD_ERROR_BUFFEROVERRUN; connection->doneProcessing = 1; connection->doneListOk = 0; return; } bufferCheck = connection->buffer + connection->buflen; tv.tv_sec = connection->timeout.tv_sec; tv.tv_usec = connection->timeout.tv_usec; FD_ZERO(&fds); FD_SET(connection->sock, &fds); if ((err = select(connection->sock + 1, &fds, NULL, NULL, &tv) == 1)) { readed = recv(connection->sock, connection->buffer + connection->buflen, MPD_BUFFER_MAX_LENGTH - connection->buflen, MSG_DONTWAIT); if (readed < 0 && SENDRECV_ERRNO_IGNORE) { continue; } if (readed <= 0) { strcpy(connection->errorStr, "connection closed"); connection->error = MPD_ERROR_CONNCLOSED; connection->doneProcessing = 1; connection->doneListOk = 0; return; } connection->buflen += readed; connection->buffer[connection->buflen] = '\0'; } else if (err < 0 && SELECT_ERRNO_IGNORE) { continue; } else { strcpy(connection->errorStr, "connection timeout"); connection->error = MPD_ERROR_TIMEOUT; connection->doneProcessing = 1; connection->doneListOk = 0; return; } } *rt = '\0'; output = connection->buffer + connection->bufstart; connection->bufstart = rt - connection->buffer + 1; if (strcmp(output, "OK") == 0) { if (connection->listOks > 0) { strcpy(connection->errorStr, "expected more list_OK's"); connection->error = 1; } connection->listOks = 0; connection->doneProcessing = 1; connection->doneListOk = 0; return; } if (strcmp(output, "list_OK") == 0) { if (!connection->listOks) { strcpy(connection->errorStr, "got an unexpected list_OK"); connection->error = 1; } else { connection->doneListOk = 1; connection->listOks--; } return; } if (strncmp(output, "ACK", strlen("ACK")) == 0) { char *test; char *needle; int val; strcpy(connection->errorStr, output); connection->error = MPD_ERROR_ACK; connection->errorCode = MPD_ACK_ERROR_UNK; connection->errorAt = MPD_ERROR_AT_UNK; connection->doneProcessing = 1; connection->doneListOk = 0; needle = strchr(output, '['); if (!needle) { return; } val = strtol(needle + 1, &test, 10); if (*test != '@') { return; } connection->errorCode = val; val = strtol(test + 1, &test, 10); if (*test != ']') { return; } connection->errorAt = val; return; } tok = strchr(output, ':'); if (!tok) { return; } pos = tok - output; value = ++tok; name = output; name[pos] = '\0'; if (value[0] == ' ') { connection->returnElement = mpd_newReturnElement(name, &(value[1])); } else { snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "error parsing: %s:%s", name, value); connection->error = 1; } } void mpd_finishCommand(mpd_Connection *connection) { while (connection && !connection->doneProcessing) { if (connection->doneListOk) { connection->doneListOk = 0; } mpd_getNextReturnElement(connection); } } static void mpd_finishListOkCommand(mpd_Connection *connection) { while (!connection->doneProcessing && connection->listOks && !connection->doneListOk) { mpd_getNextReturnElement(connection); } } int mpd_nextListOkCommand(mpd_Connection *connection) { mpd_finishListOkCommand(connection); if (!connection->doneProcessing) { connection->doneListOk = 0; } if (connection->listOks == 0 || connection->doneProcessing) { return -1; } return 0; } void mpd_sendStatusCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "status\n"); } mpd_Status *mpd_getStatus(mpd_Connection *connection) { mpd_Status *status; /* mpd_executeCommand(connection, "status\n"); if (connection->error) { return NULL; } */ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { return NULL; } if (!connection->returnElement) { mpd_getNextReturnElement(connection); } status = (mpd_Status *) malloc(sizeof(mpd_Status)); status->volume = -1; status->repeat = 0; status->random = 0; status->playlist = -1; status->playlistLength = -1; status->state = -1; status->song = 0; status->songid = 0; status->elapsedTime = 0; status->totalTime = 0; status->bitRate = 0; status->sampleRate = 0; status->bits = 0; status->channels = 0; status->crossfade = -1; status->error = NULL; status->updatingDb = 0; if (connection->error) { free(status); return NULL; } while (connection->returnElement) { mpd_ReturnElement *re = connection->returnElement; if (strcmp(re->name, "volume") == 0) { status->volume = atoi(re->value); } else if (strcmp(re->name, "repeat") == 0) { status->repeat = atoi(re->value); } else if (strcmp(re->name, "random") == 0) { status->random = atoi(re->value); } else if (strcmp(re->name, "playlist") == 0) { status->playlist = strtol(re->value, NULL, 10); } else if (strcmp(re->name, "playlistlength") == 0) { status->playlistLength = atoi(re->value); } else if (strcmp(re->name, "bitrate") == 0) { status->bitRate = atoi(re->value); } else if (strcmp(re->name, "state") == 0) { if (strcmp(re->value, "play") == 0) { status->state = MPD_STATUS_STATE_PLAY; } else if (strcmp(re->value, "stop") == 0) { status->state = MPD_STATUS_STATE_STOP; } else if (strcmp(re->value, "pause") == 0) { status->state = MPD_STATUS_STATE_PAUSE; } else { status->state = MPD_STATUS_STATE_UNKNOWN; } } else if (strcmp(re->name, "song") == 0) { status->song = atoi(re->value); } else if (strcmp(re->name, "songid") == 0) { status->songid = atoi(re->value); } else if (strcmp(re->name, "time") == 0) { char *tok = strchr(re->value, ':'); /* the second strchr below is a safety check */ if (tok && (strchr(tok, 0) > (tok + 1))) { /* atoi stops at the first non-[0-9] char: */ status->elapsedTime = atoi(re->value); status->totalTime = atoi(tok + 1); } } else if (strcmp(re->name, "error") == 0) { status->error = strndup(re->value, text_buffer_size.get(*state)); } else if (strcmp(re->name, "xfade") == 0) { status->crossfade = atoi(re->value); } else if (strcmp(re->name, "updating_db") == 0) { status->updatingDb = atoi(re->value); } else if (strcmp(re->name, "audio") == 0) { char *tok = strchr(re->value, ':'); if (tok && (strchr(tok, 0) > (tok + 1))) { status->sampleRate = atoi(re->value); status->bits = atoi(++tok); tok = strchr(tok, ':'); if (tok && (strchr(tok, 0) > (tok + 1))) { status->channels = atoi(tok + 1); } } } mpd_getNextReturnElement(connection); if (connection->error) { free(status); return NULL; } } if (connection->error) { free(status); return NULL; } else if (status->state < 0) { strcpy(connection->errorStr, "state not found"); connection->error = 1; free(status); return NULL; } return status; } void mpd_freeStatus(mpd_Status *status) { free_and_zero(status->error); free(status); } void mpd_sendStatsCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "stats\n"); } mpd_Stats *mpd_getStats(mpd_Connection *connection) { mpd_Stats *stats; /* mpd_executeCommand(connection, "stats\n"); if (connection->error) { return NULL; } */ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { return NULL; } if (!connection->returnElement) { mpd_getNextReturnElement(connection); } stats = (mpd_Stats *) malloc(sizeof(mpd_Stats)); stats->numberOfArtists = 0; stats->numberOfAlbums = 0; stats->numberOfSongs = 0; stats->uptime = 0; stats->dbUpdateTime = 0; stats->playTime = 0; stats->dbPlayTime = 0; if (connection->error) { free(stats); return NULL; } while (connection->returnElement) { mpd_ReturnElement *re = connection->returnElement; if (strcmp(re->name, "artists") == 0) { stats->numberOfArtists = atoi(re->value); } else if (strcmp(re->name, "albums") == 0) { stats->numberOfAlbums = atoi(re->value); } else if (strcmp(re->name, "songs") == 0) { stats->numberOfSongs = atoi(re->value); } else if (strcmp(re->name, "uptime") == 0) { stats->uptime = strtol(re->value, NULL, 10); } else if (strcmp(re->name, "db_update") == 0) { stats->dbUpdateTime = strtol(re->value, NULL, 10); } else if (strcmp(re->name, "playtime") == 0) { stats->playTime = strtol(re->value, NULL, 10); } else if (strcmp(re->name, "db_playtime") == 0) { stats->dbPlayTime = strtol(re->value, NULL, 10); } mpd_getNextReturnElement(connection); if (connection->error) { free(stats); return NULL; } } if (connection->error) { free(stats); return NULL; } return stats; } void mpd_freeStats(mpd_Stats *stats) { free(stats); } mpd_SearchStats *mpd_getSearchStats(mpd_Connection *connection) { mpd_SearchStats *stats; mpd_ReturnElement *re; if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { return NULL; } if (!connection->returnElement) { mpd_getNextReturnElement(connection); } if (connection->error) { return NULL; } stats = (mpd_SearchStats *) malloc(sizeof(mpd_SearchStats)); stats->numberOfSongs = 0; stats->playTime = 0; while (connection->returnElement) { re = connection->returnElement; if (strcmp(re->name, "songs") == 0) { stats->numberOfSongs = atoi(re->value); } else if (strcmp(re->name, "playtime") == 0) { stats->playTime = strtol(re->value, NULL, 10); } mpd_getNextReturnElement(connection); if (connection->error) { free(stats); return NULL; } } if (connection->error) { free(stats); return NULL; } return stats; } void mpd_freeSearchStats(mpd_SearchStats *stats) { free(stats); } static void mpd_initSong(mpd_Song *song) { song->file = NULL; song->artist = NULL; song->albumartist = NULL; song->album = NULL; song->track = NULL; song->title = NULL; song->name = NULL; song->date = NULL; /* added by Qball */ song->genre = NULL; song->composer = NULL; song->performer = NULL; song->disc = NULL; song->comment = NULL; song->time = MPD_SONG_NO_TIME; song->pos = MPD_SONG_NO_NUM; song->id = MPD_SONG_NO_ID; } static void mpd_finishSong(mpd_Song *song) { free_and_zero(song->file); free_and_zero(song->artist); free_and_zero(song->albumartist); free_and_zero(song->album); free_and_zero(song->title); free_and_zero(song->track); free_and_zero(song->name); free_and_zero(song->date); free_and_zero(song->genre); free_and_zero(song->composer); free_and_zero(song->disc); free_and_zero(song->comment); } mpd_Song *mpd_newSong(void) { mpd_Song *ret = (mpd_Song *) malloc(sizeof(mpd_Song)); mpd_initSong(ret); return ret; } void mpd_freeSong(mpd_Song *song) { mpd_finishSong(song); free(song); } mpd_Song *mpd_songDup(mpd_Song *song) { mpd_Song *ret = mpd_newSong(); if (song->file) { ret->file = strndup(song->file, text_buffer_size.get(*state)); } if (song->artist) { ret->artist = strndup(song->artist, text_buffer_size.get(*state)); } if (song->albumartist) { ret->artist = strndup(song->albumartist, text_buffer_size.get(*state)); } if (song->album) { ret->album = strndup(song->album, text_buffer_size.get(*state)); } if (song->title) { ret->title = strndup(song->title, text_buffer_size.get(*state)); } if (song->track) { ret->track = strndup(song->track, text_buffer_size.get(*state)); } if (song->name) { ret->name = strndup(song->name, text_buffer_size.get(*state)); } if (song->date) { ret->date = strndup(song->date, text_buffer_size.get(*state)); } if (song->genre) { ret->genre = strndup(song->genre, text_buffer_size.get(*state)); } if (song->composer) { ret->composer = strndup(song->composer, text_buffer_size.get(*state)); } if (song->disc) { ret->disc = strndup(song->disc, text_buffer_size.get(*state)); } if (song->comment) { ret->comment = strndup(song->comment, text_buffer_size.get(*state)); } ret->time = song->time; ret->pos = song->pos; ret->id = song->id; return ret; } static void mpd_initDirectory(mpd_Directory *directory) { directory->path = NULL; } static void mpd_finishDirectory(mpd_Directory *directory) { free_and_zero(directory->path); } mpd_Directory *mpd_newDirectory(void) { mpd_Directory *directory = (mpd_Directory *) malloc(sizeof(mpd_Directory)); mpd_initDirectory(directory); return directory; } void mpd_freeDirectory(mpd_Directory *directory) { mpd_finishDirectory(directory); free(directory); } mpd_Directory *mpd_directoryDup(mpd_Directory *directory) { mpd_Directory *ret = mpd_newDirectory(); if (directory->path) { ret->path = strndup(directory->path, text_buffer_size.get(*state)); } return ret; } static void mpd_initPlaylistFile(mpd_PlaylistFile *playlist) { playlist->path = NULL; } static void mpd_finishPlaylistFile(mpd_PlaylistFile *playlist) { free_and_zero(playlist->path); } mpd_PlaylistFile *mpd_newPlaylistFile(void) { mpd_PlaylistFile *playlist = (mpd_PlaylistFile *) malloc(sizeof(mpd_PlaylistFile)); mpd_initPlaylistFile(playlist); return playlist; } void mpd_freePlaylistFile(mpd_PlaylistFile *playlist) { mpd_finishPlaylistFile(playlist); free(playlist); } mpd_PlaylistFile *mpd_playlistFileDup(mpd_PlaylistFile *playlist) { mpd_PlaylistFile *ret = mpd_newPlaylistFile(); if (playlist->path) { ret->path = strndup(playlist->path, text_buffer_size.get(*state)); } return ret; } static void mpd_initInfoEntity(mpd_InfoEntity *entity) { entity->info.directory = NULL; } static void mpd_finishInfoEntity(mpd_InfoEntity *entity) { if (entity->info.directory) { if (entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { mpd_freeDirectory(entity->info.directory); } else if (entity->type == MPD_INFO_ENTITY_TYPE_SONG) { mpd_freeSong(entity->info.song); } else if (entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) { mpd_freePlaylistFile(entity->info.playlistFile); } } } mpd_InfoEntity *mpd_newInfoEntity(void) { mpd_InfoEntity *entity = (mpd_InfoEntity *) malloc(sizeof(mpd_InfoEntity)); mpd_initInfoEntity(entity); return entity; } void mpd_freeInfoEntity(mpd_InfoEntity *entity) { mpd_finishInfoEntity(entity); free(entity); } static void mpd_sendInfoCommand(mpd_Connection *connection, char *command) { mpd_executeCommand(connection, command); } mpd_InfoEntity *mpd_getNextInfoEntity(mpd_Connection *connection) { mpd_InfoEntity *entity = NULL; if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { return NULL; } if (!connection->returnElement) { mpd_getNextReturnElement(connection); } if (connection->returnElement) { if (strcmp(connection->returnElement->name, "file") == 0) { entity = mpd_newInfoEntity(); entity->type = MPD_INFO_ENTITY_TYPE_SONG; entity->info.song = mpd_newSong(); entity->info.song->file = strndup(connection->returnElement->value, text_buffer_size.get(*state)); } else if (strcmp(connection->returnElement->name, "directory") == 0) { entity = mpd_newInfoEntity(); entity->type = MPD_INFO_ENTITY_TYPE_DIRECTORY; entity->info.directory = mpd_newDirectory(); entity->info.directory->path = strndup(connection->returnElement->value, text_buffer_size.get(*state)); } else if (strcmp(connection->returnElement->name, "playlist") == 0) { entity = mpd_newInfoEntity(); entity->type = MPD_INFO_ENTITY_TYPE_PLAYLISTFILE; entity->info.playlistFile = mpd_newPlaylistFile(); entity->info.playlistFile->path = strndup(connection->returnElement->value, text_buffer_size.get(*state)); } else if (strcmp(connection->returnElement->name, "cpos") == 0) { entity = mpd_newInfoEntity(); entity->type = MPD_INFO_ENTITY_TYPE_SONG; entity->info.song = mpd_newSong(); entity->info.song->pos = atoi(connection->returnElement->value); } else { connection->error = 1; strcpy(connection->errorStr, "problem parsing song info"); return NULL; } } else { return NULL; } mpd_getNextReturnElement(connection); while (connection->returnElement) { mpd_ReturnElement *re = connection->returnElement; if (strcmp(re->name, "file") == 0) { return entity; } else if (strcmp(re->name, "directory") == 0) { return entity; } else if (strcmp(re->name, "playlist") == 0) { return entity; } else if (strcmp(re->name, "cpos") == 0) { return entity; } if (entity->type == MPD_INFO_ENTITY_TYPE_SONG && strlen(re->value)) { if (!entity->info.song->artist && strcmp(re->name, "Artist") == 0) { entity->info.song->artist = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->albumartist && strcmp(re->name, "AlbumArtist") == 0) { entity->info.song->albumartist = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->album && strcmp(re->name, "Album") == 0) { entity->info.song->album = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->title && strcmp(re->name, "Title") == 0) { entity->info.song->title = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->track && strcmp(re->name, "Track") == 0) { entity->info.song->track = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->name && strcmp(re->name, "Name") == 0) { entity->info.song->name = strndup(re->value, text_buffer_size.get(*state)); } else if (entity->info.song->time == MPD_SONG_NO_TIME && strcmp(re->name, "Time") == 0) { entity->info.song->time = atoi(re->value); } else if (entity->info.song->pos == MPD_SONG_NO_NUM && strcmp(re->name, "Pos") == 0) { entity->info.song->pos = atoi(re->value); } else if (entity->info.song->id == MPD_SONG_NO_ID && strcmp(re->name, "Id") == 0) { entity->info.song->id = atoi(re->value); } else if (!entity->info.song->date && strcmp(re->name, "Date") == 0) { entity->info.song->date = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->genre && strcmp(re->name, "Genre") == 0) { entity->info.song->genre = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->composer && strcmp(re->name, "Composer") == 0) { entity->info.song->composer = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->performer && strcmp(re->name, "Performer") == 0) { entity->info.song->performer = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->disc && strcmp(re->name, "Disc") == 0) { entity->info.song->disc = strndup(re->value, text_buffer_size.get(*state)); } else if (!entity->info.song->comment && strcmp(re->name, "Comment") == 0) { entity->info.song->comment = strndup(re->value, text_buffer_size.get(*state)); } } else if (entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { } else if (entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) { } mpd_getNextReturnElement(connection); } return entity; } static char *mpd_getNextReturnElementNamed(mpd_Connection *connection, const char *name) { if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { return NULL; } mpd_getNextReturnElement(connection); while (connection->returnElement) { mpd_ReturnElement *re = connection->returnElement; if (strcmp(re->name, name) == 0) { return strndup(re->value, text_buffer_size.get(*state)); } mpd_getNextReturnElement(connection); } return NULL; } char *mpd_getNextTag(mpd_Connection *connection, int type) { if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES || type == MPD_TAG_ITEM_ANY) { return NULL; } if (type == MPD_TAG_ITEM_FILENAME) { return mpd_getNextReturnElementNamed(connection, "file"); } return mpd_getNextReturnElementNamed(connection, mpdTagItemKeys[type]); } char *mpd_getNextArtist(mpd_Connection *connection) { return mpd_getNextReturnElementNamed(connection, "Artist"); } char *mpd_getNextAlbum(mpd_Connection *connection) { return mpd_getNextReturnElementNamed(connection, "Album"); } void mpd_sendPlaylistInfoCommand(mpd_Connection *connection, int songPos) { int len = strlen("playlistinfo") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "playlistinfo \"%i\"\n", songPos); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendPlaylistIdCommand(mpd_Connection *connection, int id) { int len = strlen("playlistid") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "playlistid \"%i\"\n", id); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendPlChangesCommand(mpd_Connection *connection, long long playlist) { int len = strlen("plchanges") + 2 + LONGLONGLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "plchanges \"%lld\"\n", playlist); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendPlChangesPosIdCommand(mpd_Connection *connection, long long playlist) { int len = strlen("plchangesposid") + 2 + LONGLONGLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "plchangesposid \"%lld\"\n", playlist); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendListallCommand(mpd_Connection *connection, const char *dir) { char *sDir = mpd_sanitizeArg(dir); int len = strlen("listall") + 2 + strlen(sDir) + 3; char *string = (char*) malloc(len); snprintf(string, len, "listall \"%s\"\n", sDir); mpd_sendInfoCommand(connection, string); free(string); free(sDir); } void mpd_sendListallInfoCommand(mpd_Connection *connection, const char *dir) { char *sDir = mpd_sanitizeArg(dir); int len = strlen("listallinfo") + 2 + strlen(sDir) + 3; char *string = (char*) malloc(len); snprintf(string, len, "listallinfo \"%s\"\n", sDir); mpd_sendInfoCommand(connection, string); free(string); free(sDir); } void mpd_sendLsInfoCommand(mpd_Connection *connection, const char *dir) { char *sDir = mpd_sanitizeArg(dir); int len = strlen("lsinfo") + 2 + strlen(sDir) + 3; char *string = (char*) malloc(len); snprintf(string, len, "lsinfo \"%s\"\n", sDir); mpd_sendInfoCommand(connection, string); free(string); free(sDir); } void mpd_sendCurrentSongCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "currentsong\n"); } void mpd_sendSearchCommand(mpd_Connection *connection, int table, const char *str) { mpd_startSearch(connection, 0); mpd_addConstraintSearch(connection, table, str); mpd_commitSearch(connection); } void mpd_sendFindCommand(mpd_Connection *connection, int table, const char *str) { mpd_startSearch(connection, 1); mpd_addConstraintSearch(connection, table, str); mpd_commitSearch(connection); } void mpd_sendListCommand(mpd_Connection *connection, int table, const char *arg1) { char st[10]; int len; char *string; if (table == MPD_TABLE_ARTIST) { strcpy(st, "artist"); } else if (table == MPD_TABLE_ALBUM) { strcpy(st, "album"); } else { connection->error = 1; strcpy(connection->errorStr, "unknown table for list"); return; } if (arg1) { char *sanitArg1 = mpd_sanitizeArg(arg1); len = strlen("list") + 1 + strlen(sanitArg1) + 2 + strlen(st) + 3; string = (char*) malloc(len); snprintf(string, len, "list %s \"%s\"\n", st, sanitArg1); free(sanitArg1); } else { len = strlen("list") + 1 + strlen(st) + 2; string = (char*) malloc(len); snprintf(string, len, "list %s\n", st); } mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendAddCommand(mpd_Connection *connection, const char *file) { char *sFile = mpd_sanitizeArg(file); int len = strlen("add") + 2 + strlen(sFile) + 3; char *string = (char*) malloc(len); snprintf(string, len, "add \"%s\"\n", sFile); mpd_executeCommand(connection, string); free(string); free(sFile); } int mpd_sendAddIdCommand(mpd_Connection *connection, const char *file) { int retval = -1; char *sFile = mpd_sanitizeArg(file); int len = strlen("addid") + 2 + strlen(sFile) + 3; char *string = (char*) malloc(len); snprintf(string, len, "addid \"%s\"\n", sFile); mpd_sendInfoCommand(connection, string); free(string); free(sFile); string = mpd_getNextReturnElementNamed(connection, "Id"); if (string) { retval = atoi(string); free(string); } return retval; } void mpd_sendDeleteCommand(mpd_Connection *connection, int songPos) { int len = strlen("delete") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "delete \"%i\"\n", songPos); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendDeleteIdCommand(mpd_Connection *connection, int id) { int len = strlen("deleteid") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "deleteid \"%i\"\n", id); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendSaveCommand(mpd_Connection *connection, const char *name) { char *sName = mpd_sanitizeArg(name); int len = strlen("save") + 2 + strlen(sName) + 3; char *string = (char*) malloc(len); snprintf(string, len, "save \"%s\"\n", sName); mpd_executeCommand(connection, string); free(string); free(sName); } void mpd_sendLoadCommand(mpd_Connection *connection, const char *name) { char *sName = mpd_sanitizeArg(name); int len = strlen("load") + 2 + strlen(sName) + 3; char *string = (char*) malloc(len); snprintf(string, len, "load \"%s\"\n", sName); mpd_executeCommand(connection, string); free(string); free(sName); } void mpd_sendRmCommand(mpd_Connection *connection, const char *name) { char *sName = mpd_sanitizeArg(name); int len = strlen("rm") + 2 + strlen(sName) + 3; char *string = (char*) malloc(len); snprintf(string, len, "rm \"%s\"\n", sName); mpd_executeCommand(connection, string); free(string); free(sName); } void mpd_sendRenameCommand(mpd_Connection *connection, const char *from, const char *to) { char *sFrom = mpd_sanitizeArg(from); char *sTo = mpd_sanitizeArg(to); int len = strlen("rename") + 2 + strlen(sFrom) + 3 + strlen(sTo) + 3; char *string = (char*) malloc(len); snprintf(string, len, "rename \"%s\" \"%s\"\n", sFrom, sTo); mpd_executeCommand(connection, string); free(string); free(sFrom); free(sTo); } void mpd_sendShuffleCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "shuffle\n"); } void mpd_sendClearCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "clear\n"); } void mpd_sendPlayCommand(mpd_Connection *connection, int songPos) { int len = strlen("play") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "play \"%i\"\n", songPos); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendPlayIdCommand(mpd_Connection *connection, int id) { int len = strlen("playid") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "playid \"%i\"\n", id); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendStopCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "stop\n"); } void mpd_sendPauseCommand(mpd_Connection *connection, int pauseMode) { int len = strlen("pause") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "pause \"%i\"\n", pauseMode); mpd_executeCommand(connection, string); free(string); } void mpd_sendNextCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "next\n"); } void mpd_sendMoveCommand(mpd_Connection *connection, int from, int to) { int len = strlen("move") + 2 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "move \"%i\" \"%i\"\n", from, to); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendMoveIdCommand(mpd_Connection *connection, int id, int to) { int len = strlen("moveid") + 2 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "moveid \"%i\" \"%i\"\n", id, to); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendSwapCommand(mpd_Connection *connection, int song1, int song2) { int len = strlen("swap") + 2 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "swap \"%i\" \"%i\"\n", song1, song2); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendSwapIdCommand(mpd_Connection *connection, int id1, int id2) { int len = strlen("swapid") + 2 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "swapid \"%i\" \"%i\"\n", id1, id2); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendSeekCommand(mpd_Connection *connection, int song, int seek_time) { int len = strlen("seek") + 2 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "seek \"%i\" \"%i\"\n", song, seek_time); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendSeekIdCommand(mpd_Connection *connection, int id, int seek_time) { int len = strlen("seekid") + 2 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "seekid \"%i\" \"%i\"\n", id, seek_time); mpd_sendInfoCommand(connection, string); free(string); } void mpd_sendUpdateCommand(mpd_Connection *connection, char *path) { char *sPath = mpd_sanitizeArg(path); int len = strlen("update") + 2 + strlen(sPath) + 3; char *string = (char*) malloc(len); snprintf(string, len, "update \"%s\"\n", sPath); mpd_sendInfoCommand(connection, string); free(string); free(sPath); } int mpd_getUpdateId(mpd_Connection *connection) { char *jobid; int ret = 0; jobid = mpd_getNextReturnElementNamed(connection, "updating_db"); if (jobid) { ret = atoi(jobid); free(jobid); } return ret; } void mpd_sendPrevCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "previous\n"); } void mpd_sendRepeatCommand(mpd_Connection *connection, int repeatMode) { int len = strlen("repeat") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "repeat \"%i\"\n", repeatMode); mpd_executeCommand(connection, string); free(string); } void mpd_sendRandomCommand(mpd_Connection *connection, int randomMode) { int len = strlen("random") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "random \"%i\"\n", randomMode); mpd_executeCommand(connection, string); free(string); } void mpd_sendSetvolCommand(mpd_Connection *connection, int volumeChange) { int len = strlen("setvol") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "setvol \"%i\"\n", volumeChange); mpd_executeCommand(connection, string); free(string); } void mpd_sendVolumeCommand(mpd_Connection *connection, int volumeChange) { int len = strlen("volume") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "volume \"%i\"\n", volumeChange); mpd_executeCommand(connection, string); free(string); } void mpd_sendCrossfadeCommand(mpd_Connection *connection, int seconds) { int len = strlen("crossfade") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "crossfade \"%i\"\n", seconds); mpd_executeCommand(connection, string); free(string); } void mpd_sendPasswordCommand(mpd_Connection *connection, const char *pass) { char *sPass = mpd_sanitizeArg(pass); int len = strlen("password") + 2 + strlen(sPass) + 3; char *string = (char*) malloc(len); snprintf(string, len, "password \"%s\"\n", sPass); mpd_executeCommand(connection, string); free(string); free(sPass); } void mpd_sendCommandListBegin(mpd_Connection *connection) { if (connection->commandList) { strcpy(connection->errorStr, "already in command list mode"); connection->error = 1; return; } connection->commandList = COMMAND_LIST; mpd_executeCommand(connection, "command_list_begin\n"); } void mpd_sendCommandListOkBegin(mpd_Connection *connection) { if (connection->commandList) { strcpy(connection->errorStr, "already in command list mode"); connection->error = 1; return; } connection->commandList = COMMAND_LIST_OK; mpd_executeCommand(connection, "command_list_ok_begin\n"); connection->listOks = 0; } void mpd_sendCommandListEnd(mpd_Connection *connection) { if (!connection->commandList) { strcpy(connection->errorStr, "not in command list mode"); connection->error = 1; return; } connection->commandList = 0; mpd_executeCommand(connection, "command_list_end\n"); } void mpd_sendOutputsCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "outputs\n"); } mpd_OutputEntity *mpd_getNextOutput(mpd_Connection *connection) { mpd_OutputEntity *output = NULL; if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { return NULL; } if (connection->error) { return NULL; } output = (mpd_OutputEntity*) malloc(sizeof(mpd_OutputEntity)); output->id = -10; output->name = NULL; output->enabled = 0; if (!connection->returnElement) { mpd_getNextReturnElement(connection); } while (connection->returnElement) { mpd_ReturnElement *re = connection->returnElement; if (strcmp(re->name, "outputid") == 0) { if (output != NULL && output->id >= 0) { return output; } output->id = atoi(re->value); } else if (strcmp(re->name, "outputname") == 0) { output->name = strndup(re->value, text_buffer_size.get(*state)); } else if (strcmp(re->name, "outputenabled") == 0) { output->enabled = atoi(re->value); } mpd_getNextReturnElement(connection); if (connection->error) { free(output); return NULL; } } return output; } void mpd_sendEnableOutputCommand(mpd_Connection *connection, int outputId) { int len = strlen("enableoutput") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "enableoutput \"%i\"\n", outputId); mpd_executeCommand(connection, string); free(string); } void mpd_sendDisableOutputCommand(mpd_Connection *connection, int outputId) { int len = strlen("disableoutput") + 2 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "disableoutput \"%i\"\n", outputId); mpd_executeCommand(connection, string); free(string); } void mpd_freeOutputElement(mpd_OutputEntity *output) { free(output->name); free(output); } /** odd naming, but it gets the not allowed commands */ void mpd_sendNotCommandsCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "notcommands\n"); } /** odd naming, but it gets the allowed commands */ void mpd_sendCommandsCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "commands\n"); } /** Get the next returned command */ char *mpd_getNextCommand(mpd_Connection *connection) { return mpd_getNextReturnElementNamed(connection, "command"); } void mpd_sendUrlHandlersCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "urlhandlers\n"); } char *mpd_getNextHandler(mpd_Connection *connection) { return mpd_getNextReturnElementNamed(connection, "handler"); } void mpd_sendTagTypesCommand(mpd_Connection *connection) { mpd_executeCommand(connection, "tagtypes\n"); } char *mpd_getNextTagType(mpd_Connection *connection) { return mpd_getNextReturnElementNamed(connection, "tagtype"); } void mpd_startSearch(mpd_Connection *connection, int exact) { if (connection->request) { strcpy(connection->errorStr, "search already in progress"); connection->error = 1; return; } if (exact) { connection->request = strndup("find", text_buffer_size.get(*state)); } else { connection->request = strndup("search", text_buffer_size.get(*state)); } } void mpd_startStatsSearch(mpd_Connection *connection) { if (connection->request) { strcpy(connection->errorStr, "search already in progress"); connection->error = 1; return; } connection->request = strndup("count", text_buffer_size.get(*state)); } void mpd_startPlaylistSearch(mpd_Connection *connection, int exact) { if (connection->request) { strcpy(connection->errorStr, "search already in progress"); connection->error = 1; return; } if (exact) { connection->request = strndup("playlistfind", text_buffer_size.get(*state)); } else { connection->request = strndup("playlistsearch", text_buffer_size.get(*state)); } } void mpd_startFieldSearch(mpd_Connection *connection, int type) { const char *strtype; int len; if (connection->request) { strcpy(connection->errorStr, "search already in progress"); connection->error = 1; return; } if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES) { strcpy(connection->errorStr, "invalid type specified"); connection->error = 1; return; } strtype = mpdTagItemKeys[type]; len = 5 + strlen(strtype) + 1; connection->request = (char*) malloc(len); snprintf(connection->request, len, "list %c%s", tolower(strtype[0]), strtype + 1); } void mpd_addConstraintSearch(mpd_Connection *connection, int type, const char *name) { const char *strtype; char *arg; int len; char *string; if (!connection->request) { strcpy(connection->errorStr, "no search in progress"); connection->error = 1; return; } if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES) { strcpy(connection->errorStr, "invalid type specified"); connection->error = 1; return; } if (name == NULL) { strcpy(connection->errorStr, "no name specified"); connection->error = 1; return; } string = strndup(connection->request, text_buffer_size.get(*state)); strtype = mpdTagItemKeys[type]; arg = mpd_sanitizeArg(name); len = strlen(string) + 1 + strlen(strtype) + 2 + strlen(arg) + 2; connection->request = (char*) realloc(connection->request, len); snprintf(connection->request, len, "%s %c%s \"%s\"", string, tolower(strtype[0]), strtype + 1, arg); free(string); free(arg); } void mpd_commitSearch(mpd_Connection *connection) { int len; if (!connection->request) { strcpy(connection->errorStr, "no search in progress"); connection->error = 1; return; } len = strlen(connection->request) + 2; connection->request = (char*) realloc(connection->request, len); connection->request[len - 2] = '\n'; connection->request[len - 1] = '\0'; mpd_sendInfoCommand(connection, connection->request); free_and_zero(connection->request); } /** * @param connection a MpdConnection * @param path the path to the playlist. * * List the content, with full metadata, of a stored playlist. */ void mpd_sendListPlaylistInfoCommand(mpd_Connection *connection, char *path) { char *arg = mpd_sanitizeArg(path); int len = strlen("listplaylistinfo") + 2 + strlen(arg) + 3; char *query = (char*) malloc(len); snprintf(query, len, "listplaylistinfo \"%s\"\n", arg); mpd_sendInfoCommand(connection, query); free(arg); free(query); } /** * @param connection a MpdConnection * @param path the path to the playlist. * * List the content of a stored playlist. */ void mpd_sendListPlaylistCommand(mpd_Connection *connection, char *path) { char *arg = mpd_sanitizeArg(path); int len = strlen("listplaylist") + 2 + strlen(arg) + 3; char *query = (char*) malloc(len); snprintf(query, len, "listplaylist \"%s\"\n", arg); mpd_sendInfoCommand(connection, query); free(arg); free(query); } void mpd_sendPlaylistClearCommand(mpd_Connection *connection, char *path) { char *sPath = mpd_sanitizeArg(path); int len = strlen("playlistclear") + 2 + strlen(sPath) + 3; char *string = (char*) malloc(len); snprintf(string, len, "playlistclear \"%s\"\n", sPath); mpd_executeCommand(connection, string); free(sPath); free(string); } void mpd_sendPlaylistAddCommand(mpd_Connection *connection, char *playlist, char *path) { char *sPlaylist = mpd_sanitizeArg(playlist); char *sPath = mpd_sanitizeArg(path); int len = strlen("playlistadd") + 2 + strlen(sPlaylist) + 3 + strlen(sPath) + 3; char *string = (char*) malloc(len); snprintf(string, len, "playlistadd \"%s\" \"%s\"\n", sPlaylist, sPath); mpd_executeCommand(connection, string); free(sPlaylist); free(sPath); free(string); } void mpd_sendPlaylistMoveCommand(mpd_Connection *connection, char *playlist, int from, int to) { char *sPlaylist = mpd_sanitizeArg(playlist); int len = strlen("playlistmove") + 2 + strlen(sPlaylist) + 3 + INTLEN + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "playlistmove \"%s\" \"%i\" \"%i\"\n", sPlaylist, from, to); mpd_executeCommand(connection, string); free(sPlaylist); free(string); } void mpd_sendPlaylistDeleteCommand(mpd_Connection *connection, char *playlist, int pos) { char *sPlaylist = mpd_sanitizeArg(playlist); int len = strlen("playlistdelete") + 2 + strlen(sPlaylist) + 3 + INTLEN + 3; char *string = (char*) malloc(len); snprintf(string, len, "playlistdelete \"%s\" \"%i\"\n", sPlaylist, pos); mpd_executeCommand(connection, string); free(sPlaylist); free(string); } conky-1.10.1/src/libmpdclient.h000066400000000000000000000473031262311664100163340ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * libmpdclient * (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * This project's homepage is: http://www.musicpd.org * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Music Player Daemon nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBMPDCLIENT_H #define LIBMPDCLIENT_H #ifdef WIN32 # define __W32API_USE_DLLIMPORT__ 1 #endif #include #include #define MPD_BUFFER_MAX_LENGTH 50000 #define MPD_ERRORSTR_MAX_LENGTH 1000 #define MPD_WELCOME_MESSAGE "OK MPD " #define MPD_ERROR_TIMEOUT 10 /* timeout trying to talk to mpd */ #define MPD_ERROR_SYSTEM 11 /* system error */ #define MPD_ERROR_UNKHOST 12 /* unknown host */ #define MPD_ERROR_CONNPORT 13 /* problems connecting to port on host */ #define MPD_ERROR_NOTMPD 14 /* mpd not running on port at host */ #define MPD_ERROR_NORESPONSE 15 /* no response on attempting to connect */ #define MPD_ERROR_SENDING 16 /* error sending command */ #define MPD_ERROR_CONNCLOSED 17 /* connection closed by mpd */ #define MPD_ERROR_ACK 18 /* ACK returned! */ #define MPD_ERROR_BUFFEROVERRUN 19 /* Buffer was overrun! */ #define MPD_ACK_ERROR_UNK -1 #define MPD_ERROR_AT_UNK -1 #define MPD_ACK_ERROR_NOT_LIST 1 #define MPD_ACK_ERROR_ARG 2 #define MPD_ACK_ERROR_PASSWORD 3 #define MPD_ACK_ERROR_PERMISSION 4 #define MPD_ACK_ERROR_UNKNOWN_CMD 5 #define MPD_ACK_ERROR_NO_EXIST 50 #define MPD_ACK_ERROR_PLAYLIST_MAX 51 #define MPD_ACK_ERROR_SYSTEM 52 #define MPD_ACK_ERROR_PLAYLIST_LOAD 53 #define MPD_ACK_ERROR_UPDATE_ALREADY 54 #define MPD_ACK_ERROR_PLAYER_SYNC 55 #define MPD_ACK_ERROR_EXIST 56 typedef enum mpd_TagItems { MPD_TAG_ITEM_ARTIST, MPD_TAG_ITEM_ALBUMARTIST, MPD_TAG_ITEM_ALBUM, MPD_TAG_ITEM_TITLE, MPD_TAG_ITEM_TRACK, MPD_TAG_ITEM_NAME, MPD_TAG_ITEM_GENRE, MPD_TAG_ITEM_DATE, MPD_TAG_ITEM_COMPOSER, MPD_TAG_ITEM_PERFORMER, MPD_TAG_ITEM_COMMENT, MPD_TAG_ITEM_DISC, MPD_TAG_ITEM_FILENAME, MPD_TAG_ITEM_ANY, MPD_TAG_NUM_OF_ITEM_TYPES } mpd_TagItems; extern const char *mpdTagItemKeys[MPD_TAG_NUM_OF_ITEM_TYPES]; /* internal stuff don't touch this struct */ typedef struct _mpd_ReturnElement { char *name; char *value; } mpd_ReturnElement; /* mpd_Connection * holds info about connection to mpd * use error, and errorStr to detect errors */ typedef struct _mpd_Connection { /* use this to check the version of mpd */ int version[3]; /* IMPORTANT, you want to get the error messages from here */ char errorStr[MPD_ERRORSTR_MAX_LENGTH + 1]; int errorCode; int errorAt; /* this will be set to MPD_ERROR_* if there is an error, 0 if not */ int error; /* DON'T TOUCH any of the rest of this stuff */ int sock; char buffer[MPD_BUFFER_MAX_LENGTH + 1]; int buflen; int bufstart; int doneProcessing; int listOks; int doneListOk; int commandList; mpd_ReturnElement *returnElement; struct timeval timeout; char *request; } mpd_Connection; /* mpd_newConnection * use this to open a new connection * you should use mpd_closeConnection when you're done with the connection, * even if an error has occurred * _timeout_ is the connection timeout period in seconds */ mpd_Connection *mpd_newConnection(const char *host, int port, float timeout); void mpd_setConnectionTimeout(mpd_Connection *connection, float timeout); /* mpd_closeConnection * use this to close a connection and free subsequent memory */ void mpd_closeConnection(mpd_Connection *connection); /* mpd_clearError * clears error */ void mpd_clearError(mpd_Connection *connection); /* STATUS STUFF */ /* use these with status.state to determine what state the player is in */ #define MPD_STATUS_STATE_UNKNOWN 0 #define MPD_STATUS_STATE_STOP 1 #define MPD_STATUS_STATE_PLAY 2 #define MPD_STATUS_STATE_PAUSE 3 /* use this with status.volume to determine if mpd has volume support */ #define MPD_STATUS_NO_VOLUME -1 /* mpd_Status * holds info return from status command */ typedef struct mpd_Status { /* 0-100, or MPD_STATUS_NO_VOLUME when there is no volume support */ int volume; /* 1 if repeat is on, 0 otherwise */ int repeat; /* 1 if random is on, 0 otherwise */ int random; /* playlist length */ int playlistLength; /* playlist, use this to determine when the playlist has changed */ long long playlist; /* use with MPD_STATUS_STATE_* to determine state of player */ int state; /* crossfade setting in seconds */ int crossfade; /* if a song is currently selected (always the case when state is PLAY * or PAUSE), this is the position of the currently playing song in the * playlist, beginning with 0 */ int song; /* Song ID of the currently selected song */ int songid; /* time in seconds that have elapsed in the currently playing/paused song */ int elapsedTime; /* length in seconds of the currently playing/paused song */ int totalTime; /* current bit rate in kbs */ int bitRate; /* audio sample rate */ unsigned int sampleRate; /* audio bits */ int bits; /* audio channels */ int channels; /* 1 if mpd is updating, 0 otherwise */ int updatingDb; /* error */ char *error; } mpd_Status; void mpd_sendStatusCommand(mpd_Connection *connection); /* mpd_getStatus * returns status info, be sure to free it with mpd_freeStatus() * call this after mpd_sendStatusCommand() */ mpd_Status *mpd_getStatus(mpd_Connection *connection); /* mpd_freeStatus * free's status info malloc'd and returned by mpd_getStatus */ void mpd_freeStatus(mpd_Status *status); typedef struct _mpd_Stats { int numberOfArtists; int numberOfAlbums; int numberOfSongs; unsigned long uptime; unsigned long dbUpdateTime; unsigned long playTime; unsigned long dbPlayTime; } mpd_Stats; typedef struct _mpd_SearchStats { int numberOfSongs; unsigned long playTime; } mpd_SearchStats; void mpd_sendStatsCommand(mpd_Connection *connection); mpd_Stats *mpd_getStats(mpd_Connection *connection); void mpd_freeStats(mpd_Stats *stats); mpd_SearchStats *mpd_getSearchStats(mpd_Connection *connection); void mpd_freeSearchStats(mpd_SearchStats *stats); /* SONG STUFF */ #define MPD_SONG_NO_TIME -1 #define MPD_SONG_NO_NUM -1 #define MPD_SONG_NO_ID -1 /* mpd_Song * for storing song info returned by mpd */ typedef struct _mpd_Song { /* filename of song */ char *file; /* artist, maybe NULL if there is no tag */ char *artist; /* albumartist, maybe NULL if there is no tag */ char *albumartist; /* title, maybe NULL if there is no tag */ char *title; /* album, maybe NULL if there is no tag */ char *album; /* track, maybe NULL if there is no tag */ char *track; /* name, maybe NULL if there is no tag; it's the name of the current song, * f.e. the icyName of the stream */ char *name; /* date */ char *date; /* added by qball */ /* Genre */ char *genre; /* Composer */ char *composer; /* Performer */ char *performer; /* Disc */ char *disc; /* Comment */ char *comment; /* length of song in seconds, check that it is not MPD_SONG_NO_TIME */ int time; /* if plchanges/playlistinfo/playlistid used, is the position of the song * in the playlist */ int pos; /* song id for a song in the playlist */ int id; } mpd_Song; /* mpd_newSong * use to allocate memory for a new mpd_Song * file, artist, etc all initialized to NULL * if you're going to assign values to file, artist, etc., be sure to * malloc or strdup the memory * use mpd_freeSong to free the memory for the mpd_Song, it will also * free memory for file, artist, etc, so don't do it yourself */ mpd_Song *mpd_newSong(void); /* mpd_freeSong * use to free memory allocated by mpd_newSong * also it will free memory pointed to by file, artist, etc, so be careful */ void mpd_freeSong(mpd_Song *song); /* mpd_songDup * works like strDup, but for a mpd_Song */ mpd_Song *mpd_songDup(mpd_Song *song); /* DIRECTORY STUFF */ /* mpd_Directory * used to store info from directory (right now just the path) */ typedef struct _mpd_Directory { char *path; } mpd_Directory; /* mpd_newDirectory * allocates memory for a new directory * use mpd_freeDirectory to free this memory */ mpd_Directory *mpd_newDirectory(void); /* mpd_freeDirectory * used to free memory allocated with mpd_newDirectory, and it frees * path of mpd_Directory, so be careful */ void mpd_freeDirectory(mpd_Directory *directory); /* mpd_directoryDup * works like strdup, but for mpd_Directory */ mpd_Directory *mpd_directoryDup(mpd_Directory *directory); /* PLAYLISTFILE STUFF */ /* mpd_PlaylistFile * stores info about playlist file returned by lsinfo */ typedef struct _mpd_PlaylistFile { char *path; } mpd_PlaylistFile; /* mpd_newPlaylistFile * allocates memory for new mpd_PlaylistFile, path is set to NULL * free this memory with mpd_freePlaylistFile */ mpd_PlaylistFile *mpd_newPlaylistFile(void); /* mpd_freePlaylist * free memory allocated for freePlaylistFile * will also free path, so be careful */ void mpd_freePlaylistFile(mpd_PlaylistFile *playlist); /* mpd_playlistFileDup * works like strdup, but for mpd_PlaylistFile */ mpd_PlaylistFile *mpd_playlistFileDup(mpd_PlaylistFile *playlist); /* INFO ENTITY STUFF */ /* the type of entity returned from one of the commands that generates info * use in conjunction with mpd_InfoEntity.type */ #define MPD_INFO_ENTITY_TYPE_DIRECTORY 0 #define MPD_INFO_ENTITY_TYPE_SONG 1 #define MPD_INFO_ENTITY_TYPE_PLAYLISTFILE 2 /* mpd_InfoEntity * stores info on stuff returned info commands */ typedef struct mpd_InfoEntity { /* the type of entity, use with MPD_INFO_ENTITY_TYPE_* to determine * what this entity is (song, directory, etc...) */ int type; /* the actual data you want, mpd_Song, mpd_Directory, etc */ union { mpd_Directory *directory; mpd_Song *song; mpd_PlaylistFile *playlistFile; } info; } mpd_InfoEntity; mpd_InfoEntity *mpd_newInfoEntity(void); void mpd_freeInfoEntity(mpd_InfoEntity *entity); /* INFO COMMANDS AND STUFF */ /* use this function to loop over after calling Info/Listall functions */ mpd_InfoEntity *mpd_getNextInfoEntity(mpd_Connection *connection); /* fetches the currently selected song (the song referenced by status->song * and status->songid */ void mpd_sendCurrentSongCommand(mpd_Connection *connection); /* songNum of -1, means to display the whole list */ void mpd_sendPlaylistInfoCommand(mpd_Connection *connection, int songNum); /* songId of -1, means to display the whole list */ void mpd_sendPlaylistIdCommand(mpd_Connection *connection, int songId); /* use this to get the changes in the playlist since version _playlist_ */ void mpd_sendPlChangesCommand(mpd_Connection *connection, long long playlist); /** * @param connection: A valid and connected mpd_Connection. * @param playlist: The playlist version you want the diff with. * * A more bandwidth efficient version of the mpd_sendPlChangesCommand. * It only returns the pos+id of the changes song. */ void mpd_sendPlChangesPosIdCommand(mpd_Connection *connection, long long playlist); /* recursively fetches all songs/dir/playlists in "dir* * (no metadata is returned) */ void mpd_sendListallCommand(mpd_Connection *connection, const char *dir); /* same as sendListallCommand, but also metadata is returned */ void mpd_sendListallInfoCommand(mpd_Connection *connection, const char *dir); /* non-recursive version of ListallInfo */ void mpd_sendLsInfoCommand(mpd_Connection *connection, const char *dir); #define MPD_TABLE_ARTIST MPD_TAG_ITEM_ARTIST #define MPD_TABLE_ALBUM MPD_TAG_ITEM_ALBUM #define MPD_TABLE_TITLE MPD_TAG_ITEM_TITLE #define MPD_TABLE_FILENAME MPD_TAG_ITEM_FILENAME void mpd_sendSearchCommand(mpd_Connection *connection, int table, const char *str); void mpd_sendFindCommand(mpd_Connection *connection, int table, const char *str); /* LIST TAG COMMANDS */ /* use this function fetch next artist entry, be sure to free the * returned string. * NULL means there are no more. * Best used with sendListArtists */ char *mpd_getNextArtist(mpd_Connection *connection); char *mpd_getNextAlbum(mpd_Connection *connection); char *mpd_getNextTag(mpd_Connection *connection, int type); /* list artist or albums by artist * arg1 should be set to the artist if listing albums by a artist * otherwise NULL for listing all artists or albums */ void mpd_sendListCommand(mpd_Connection *connection, int table, const char *arg1); /* SIMPLE COMMANDS */ void mpd_sendAddCommand(mpd_Connection *connection, const char *file); int mpd_sendAddIdCommand(mpd_Connection *connection, const char *file); void mpd_sendDeleteCommand(mpd_Connection *connection, int songNum); void mpd_sendDeleteIdCommand(mpd_Connection *connection, int songNum); void mpd_sendSaveCommand(mpd_Connection *connection, const char *name); void mpd_sendLoadCommand(mpd_Connection *connection, const char *name); void mpd_sendRmCommand(mpd_Connection *connection, const char *name); void mpd_sendRenameCommand(mpd_Connection *connection, const char *from, const char *to); void mpd_sendShuffleCommand(mpd_Connection *connection); void mpd_sendClearCommand(mpd_Connection *connection); /* use this to start playing at the beginning, useful when in random mode */ #define MPD_PLAY_AT_BEGINNING -1 void mpd_sendPlayCommand(mpd_Connection *connection, int songNum); void mpd_sendPlayIdCommand(mpd_Connection *connection, int songNum); void mpd_sendStopCommand(mpd_Connection *connection); void mpd_sendPauseCommand(mpd_Connection *connection, int pauseMode); void mpd_sendNextCommand(mpd_Connection *connection); void mpd_sendPrevCommand(mpd_Connection *connection); void mpd_sendMoveCommand(mpd_Connection *connection, int from, int to); void mpd_sendMoveIdCommand(mpd_Connection *connection, int from, int to); void mpd_sendSwapCommand(mpd_Connection *connection, int song1, int song2); void mpd_sendSwapIdCommand(mpd_Connection *connection, int song1, int song2); void mpd_sendSeekCommand(mpd_Connection *connection, int song, int seek_time); void mpd_sendSeekIdCommand(mpd_Connection *connection, int song, int seek_time); void mpd_sendRepeatCommand(mpd_Connection *connection, int repeatMode); void mpd_sendRandomCommand(mpd_Connection *connection, int randomMode); void mpd_sendSetvolCommand(mpd_Connection *connection, int volumeChange); /* WARNING: don't use volume command, its depreacted */ void mpd_sendVolumeCommand(mpd_Connection *connection, int volumeChange); void mpd_sendCrossfadeCommand(mpd_Connection *connection, int seconds); void mpd_sendUpdateCommand(mpd_Connection *connection, char *path); /* returns the update job id, call this after a update command */ int mpd_getUpdateId(mpd_Connection *connection); void mpd_sendPasswordCommand(mpd_Connection *connection, const char *pass); /* after executing a command, when you're done with it to get its status * (you want to check connection->error for an error) */ void mpd_finishCommand(mpd_Connection *connection); /* command list stuff, use this to do things like add files very quickly */ void mpd_sendCommandListBegin(mpd_Connection *connection); void mpd_sendCommandListOkBegin(mpd_Connection *connection); void mpd_sendCommandListEnd(mpd_Connection *connection); /* advance to the next listOk * returns 0 if advanced to the next list_OK, * returns -1 if it advanced to an OK or ACK */ int mpd_nextListOkCommand(mpd_Connection *connection); typedef struct _mpd_OutputEntity { int id; char *name; int enabled; } mpd_OutputEntity; void mpd_sendOutputsCommand(mpd_Connection *connection); mpd_OutputEntity *mpd_getNextOutput(mpd_Connection *connection); void mpd_sendEnableOutputCommand(mpd_Connection *connection, int outputId); void mpd_sendDisableOutputCommand(mpd_Connection *connection, int outputId); void mpd_freeOutputElement(mpd_OutputEntity *output); /** * @param connection a #mpd_Connection * * Queries mpd for the allowed commands */ void mpd_sendCommandsCommand(mpd_Connection *connection); /** * @param connection a #mpd_Connection * * Queries mpd for the not allowed commands */ void mpd_sendNotCommandsCommand(mpd_Connection *connection); /** * @param connection a #mpd_Connection * * returns the next supported command. * * @returns a string, needs to be freed */ char *mpd_getNextCommand(mpd_Connection *connection); void mpd_sendUrlHandlersCommand(mpd_Connection *connection); char *mpd_getNextHandler(mpd_Connection *connection); void mpd_sendTagTypesCommand(mpd_Connection *connection); char *mpd_getNextTagType(mpd_Connection *connection); /** * @param connection a MpdConnection * @param path the path to the playlist. * * List the content, with full metadata, of a stored playlist. */ void mpd_sendListPlaylistInfoCommand(mpd_Connection *connection, char *path); /** * @param connection a MpdConnection * @param path the path to the playlist. * * List the content of a stored playlist. */ void mpd_sendListPlaylistCommand(mpd_Connection *connection, char *path); /** * @param connection a #mpd_Connection * @param exact if to match exact * * starts a search * use mpd_addConstraintSearch to add a constraint to the search * use mpd_commitSearch to do the actual search */ void mpd_startSearch(mpd_Connection *connection, int exact); /** * @param connection a #mpd_Connection * @param type * @param name */ void mpd_addConstraintSearch(mpd_Connection *connection, int type, const char *name); /** * @param connection a #mpd_Connection */ void mpd_commitSearch(mpd_Connection *connection); /** * @param connection a #mpd_Connection * @param type The type to search for * * starts a search for fields... f.e. get a list of artists would be: * @code * mpd_startFieldSearch(connection, MPD_TAG_ITEM_ARTIST); * mpd_commitSearch(connection); * @endcode * * or get a list of artist in genre "jazz" would be: * @code * mpd_startFieldSearch(connection, MPD_TAG_ITEM_ARTIST); * mpd_addConstraintSearch(connection, MPD_TAG_ITEM_GENRE, "jazz") * mpd_commitSearch(connection); * @endcode * * mpd_startSearch will return a list of songs * (and you need mpd_getNextInfoEntity) * this will return a list of only one field (the one specified with type) * you need mpd_getNextTag to get the results */ void mpd_startFieldSearch(mpd_Connection *connection, int type); void mpd_startPlaylistSearch(mpd_Connection *connection, int exact); void mpd_startStatsSearch(mpd_Connection *connection); void mpd_sendPlaylistClearCommand(mpd_Connection *connection, char *path); void mpd_sendPlaylistAddCommand(mpd_Connection *connection, char *playlist, char *path); void mpd_sendPlaylistMoveCommand(mpd_Connection *connection, char *playlist, int from, int to); void mpd_sendPlaylistDeleteCommand(mpd_Connection *connection, char *playlist, int pos); #endif conky-1.10.1/src/libtcp-portmon.cc000066400000000000000000000372631262311664100170010ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * libtcp-portmon.c: tcp port monitoring library. * * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #ifdef HAVE_CONFIG_H #include #endif #include "libtcp-portmon.h" #include #include #include #include /* ------------------------------------------------------------------- * IMPLEMENTATION INTERFACE * * Implementation-specific interface begins here. Clients should not * manipulate these structures directly, nor call the defined helper * functions. Use the "Client interface" functions defined at bottom. * ------------------------------------------------------------------- */ namespace { /* ------------------------------------------------------------------------ * A single tcp connection * ------------------------------------------------------------------------ */ struct tcp_connection_t { /* connection's key in monitor hash */ struct in6_addr local_addr; struct in6_addr remote_addr; in_port_t local_port; in_port_t remote_port; }; /* hash function for tcp connections */ struct tcp_connection_hash { size_t operator()(const tcp_connection_t &a) const { size_t hash = 0; size_t i; hash = hash*47 + a.local_port; hash = hash*47 + a.remote_port; for(i = 0; i < sizeof(a.local_addr.s6_addr); ++i) hash = hash*47 + a.local_addr.s6_addr[i]; for(i = 0; i < sizeof(a.remote_addr.s6_addr); ++i) hash = hash*47 + a.remote_addr.s6_addr[i]; return hash; } }; /* comparison function for tcp connections */ bool operator==(const tcp_connection_t &a, const tcp_connection_t &b) { return a.local_port == b.local_port && a.remote_port == b.remote_port && ! std::memcmp(&a.local_addr, &b.local_addr, sizeof(a.local_addr)) && ! std::memcmp(&a.remote_addr.s6_addr, &b.remote_addr, sizeof(a.remote_addr)); } /* ------------------------------------------------------------------------ * A hash table containing tcp connection * * The second parameter provides the mechanism for removing connections if * they are not seen again in subsequent update cycles. * ------------------------------------------------------------------------ */ typedef std::unordered_map connection_hash_t; /* start and end of port monitor range. Set start=end to monitor a single port */ typedef std::pair port_range_t; /* hash function for port ranges */ struct port_range_hash { size_t operator()(const port_range_t &a) const { return a.first*47 + a.second; } }; typedef std::unordered_map monitor_hash_t; } /* -------------- * A port monitor * -------------- */ struct _tcp_port_monitor_t { /* hash table of pointers into connection list */ connection_hash_t hash; /* array of connection pointers for O(1) peeking * these point into the hash table*/ std::vector p_peek; _tcp_port_monitor_t(int max_connections) : hash(), p_peek(max_connections, static_cast(NULL)) { } _tcp_port_monitor_t(const _tcp_port_monitor_t &other) : hash(other.hash), p_peek(other.p_peek.size(), static_cast(NULL)) { // we must rebuild the peek table because the pointers are no longer valid rebuild_peek_table(); } void rebuild_peek_table() { /* Run through the monitor's connections and rebuild the peek table of * connection pointers. This is done so peeking into the monitor can be * done in O(1) time instead of O(n) time for each peek. */ /* zero out the peek array */ std::fill(p_peek.begin(), p_peek.end(), static_cast(NULL)); size_t i = 0; for (connection_hash_t::iterator j = hash.begin(); j != hash.end(); ++j, ++i ) { p_peek[i] = &j->first; } } private: // we don't need this atm const _tcp_port_monitor_t& operator=(const _tcp_port_monitor_t &); }; /* ----------------------------- * A tcp port monitor collection * ----------------------------- */ struct _tcp_port_monitor_collection_t { /* hash table of monitors */ monitor_hash_t hash; }; namespace { /* --------------------------------------- * A port monitor utility function typedef * --------------------------------------- */ typedef void (*tcp_port_monitor_function_ptr_t)(monitor_hash_t::value_type &monitor, void *p_void); void age_tcp_port_monitor(monitor_hash_t::value_type &monitor, void *p_void) { /* Run through the monitor's connections and decrement the age variable. * If the age goes negative, we remove the connection from the monitor. * Function takes O(n) time on the number of connections. */ if (p_void) { /* p_void should be NULL in this context */ return; } for (connection_hash_t::iterator i = monitor.second.hash.begin(); i != monitor.second.hash.end(); ) { if (--i->second >= 0) ++i; else { /* connection is old. remove connection from the hash. */ /* erase shouldn't invalidate iterators */ monitor.second.hash.erase(i++); } } } void rebuild_tcp_port_monitor_peek_table(monitor_hash_t::value_type &monitor, void *p_void) { if (p_void) { /* p_void should be NULL in this context */ return; } monitor.second.rebuild_peek_table(); } void show_connection_to_tcp_port_monitor(monitor_hash_t::value_type &monitor, void *p_void) { /* The monitor gets to look at each connection to see if it falls within * the monitor's port range of interest. Connections of interest are first * looked up in the hash to see if they are already there. If they are, we * reset the age of the connection so it is not deleted. If the connection * is not in the hash, we add it, but only if we haven't exceeded the * maximum connection limit for the monitor. * The function takes O(1) time. */ tcp_connection_t *p_connection; if (!p_void) { return; } /* This p_connection is on caller's stack and not the heap. * If we are interested, we will create a copy of the connection * (on the heap) and add it to our list. */ p_connection = (tcp_connection_t *) p_void; /* inspect the local port number of the connection to see if we're * interested. */ if ((monitor.first.first <= p_connection->local_port) && (p_connection->local_port <= monitor.first.second)) { /* the connection is in the range of the monitor. */ /* first check the hash to see if the connection is already there. */ connection_hash_t::iterator i = monitor.second.hash.find(*p_connection); if (i != monitor.second.hash.end()) { /* it's already in the hash. reset the age of the connection. */ i->second = TCP_CONNECTION_STARTING_AGE; return; } /* Connection is not yet in the hash. * Add it if max_connections not exceeded. */ if (monitor.second.hash.size() < monitor.second.p_peek.size()) { monitor.second.hash.insert(connection_hash_t::value_type(*p_connection, TCP_CONNECTION_STARTING_AGE)); } } } /* ------------------------------------------------------------------------ * Apply a tcp_port_monitor_function_ptr_t function to each port monitor in * the collection. * ------------------------------------------------------------------------ */ void for_each_tcp_port_monitor_in_collection( tcp_port_monitor_collection_t *p_collection, tcp_port_monitor_function_ptr_t p_function, void *p_function_args) { if (!p_collection || !p_function) { return; } /* for each monitor in the collection */ for (monitor_hash_t::iterator i = p_collection->hash.begin(); i != p_collection->hash.end(); ++i) { /* apply the function with the given arguments */ p_function(*i, p_function_args); } } const unsigned char prefix_4on6[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; union sockaddr_in46 { struct sockaddr_in sa4; struct sockaddr_in6 sa6; struct sockaddr sa; }; /* checks whether the address is a IPv4-mapped IPv6 address */ bool is_4on6(const struct in6_addr *addr) { return ! std::memcmp(&addr->s6_addr, prefix_4on6, sizeof(prefix_4on6)); } /* converts the address to appropriate textual representation (IPv6, IPv4 or fqdn) */ void print_host(char *p_buffer, size_t buffer_size, const struct in6_addr *addr, int fqdn) { union sockaddr_in46 sa; socklen_t slen; std::memset(&sa, 0, sizeof(sa)); if(is_4on6(addr)) { sa.sa4.sin_family = AF_INET; std::memcpy(&sa.sa4.sin_addr.s_addr, &addr->s6_addr[12], 4); slen = sizeof(sa.sa4); } else { sa.sa6.sin6_family = AF_INET6; std::memcpy(&sa.sa6.sin6_addr, addr, sizeof(struct in6_addr)); slen = sizeof(sa.sa6); } getnameinfo(&sa.sa, slen, p_buffer, buffer_size, NULL, 0, fqdn?0:NI_NUMERICHOST); } /* converts the textual representation of an IPv4 or IPv6 address to struct in6_addr */ void string_to_addr(struct in6_addr *addr, const char *p_buffer) { size_t i; if(std::strlen(p_buffer) < 32) { //IPv4 address i = sizeof(prefix_4on6); std::memcpy(addr->s6_addr, prefix_4on6, i); } else { i = 0; } for( ; i < sizeof(addr->s6_addr); i+=4, p_buffer+=8) { std::sscanf(p_buffer, "%8x", (unsigned *)&addr->s6_addr[i]); } } /* adds connections from file to the collection */ void process_file(tcp_port_monitor_collection_t *p_collection, const char *file) { std::FILE *fp; char buf[256]; char local_addr[40]; char remote_addr[40]; tcp_connection_t conn; unsigned long inode, uid, state; if ((fp = std::fopen(file, "r")) == NULL) { return; } /* ignore field name line */ if(std::fgets(buf, 255, fp) == NULL) { std::fclose(fp); return; } /* read all tcp connections */ while (std::fgets(buf, sizeof(buf), fp) != NULL) { if (std::sscanf(buf, "%*d: %39[0-9a-fA-F]:%hx %39[0-9a-fA-F]:%hx %lx %*x:%*x %*x:%*x %*x %lu %*d %lu", local_addr, &conn.local_port, remote_addr, &conn.remote_port, (unsigned long *) &state, (unsigned long *) &uid, (unsigned long *) &inode) != 7) { std::fprintf(stderr, "%s: bad file format\n", file); } /** TCP_ESTABLISHED equals 1, but is not (always??) included **/ //if ((inode == 0) || (state != TCP_ESTABLISHED)) { if((inode == 0) || (state != 1)) { continue; } string_to_addr(&conn.local_addr, local_addr); string_to_addr(&conn.remote_addr, remote_addr); /* show the connection to each port monitor. */ for_each_tcp_port_monitor_in_collection(p_collection, &show_connection_to_tcp_port_monitor, (void *) &conn); } std::fclose(fp); } } /* ---------------------------------------------------------------------- * CLIENT INTERFACE * * Clients should call only those functions below this line. * ---------------------------------------------------------------------- */ /* ---------------------------------- * Client operations on port monitors * ---------------------------------- */ /* Clients use this function to get connection data from the indicated * port monitor. * The requested monitor value is copied into a client-supplied char buffer. * Returns 0 on success, -1 otherwise. */ int peek_tcp_port_monitor(const tcp_port_monitor_t *p_monitor, int item, int connection_index, char *p_buffer, size_t buffer_size) { struct sockaddr_in sa; if (!p_monitor || !p_buffer || connection_index < 0) { return -1; } std::memset(p_buffer, 0, buffer_size); std::memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; /* if the connection index is out of range, we simply return with no error, * having first cleared the client-supplied buffer. */ if ( (item != COUNT) && (connection_index >= ssize_t(p_monitor->hash.size())) ) { return 0; } switch (item) { case COUNT: std::snprintf(p_buffer, buffer_size, "%u", unsigned(p_monitor->hash.size())); break; case REMOTEIP: print_host(p_buffer, buffer_size, &p_monitor->p_peek[connection_index]->remote_addr, 0); break; case REMOTEHOST: print_host(p_buffer, buffer_size, &p_monitor->p_peek[connection_index]->remote_addr, 1); break; case REMOTEPORT: std::snprintf(p_buffer, buffer_size, "%d", p_monitor->p_peek[connection_index]->remote_port); break; case REMOTESERVICE: sa.sin_port=htons(p_monitor->p_peek[connection_index]->remote_port); getnameinfo((struct sockaddr *) &sa, sizeof(struct sockaddr_in), NULL, 0, p_buffer, buffer_size, NI_NUMERICHOST); break; case LOCALIP: print_host(p_buffer, buffer_size, &p_monitor->p_peek[connection_index]->local_addr, 0); break; case LOCALHOST: print_host(p_buffer, buffer_size, &p_monitor->p_peek[connection_index]->local_addr, 1); break; case LOCALPORT: std::snprintf(p_buffer, buffer_size, "%d", p_monitor->p_peek[connection_index]->local_port); break; case LOCALSERVICE: sa.sin_port=htons(p_monitor->p_peek[connection_index]->local_port); getnameinfo((struct sockaddr *) &sa, sizeof(struct sockaddr_in), NULL, 0, p_buffer, buffer_size, NI_NUMERICHOST); break; default: return -1; } return 0; } /* -------------------------------- * Client operations on collections * -------------------------------- */ /* Create a monitor collection. Do this one first. */ tcp_port_monitor_collection_t *create_tcp_port_monitor_collection(void) { return new tcp_port_monitor_collection_t(); } /* Destroy the monitor collection (and the monitors inside). * Do this one last. */ void destroy_tcp_port_monitor_collection( tcp_port_monitor_collection_t *p_collection) { delete p_collection; } /* Updates the tcp statistics for all monitors within a collection */ void update_tcp_port_monitor_collection( tcp_port_monitor_collection_t *p_collection) { if (!p_collection) { return; } process_file(p_collection, "/proc/net/tcp"); process_file(p_collection, "/proc/net/tcp6"); /* age the connections in all port monitors. */ for_each_tcp_port_monitor_in_collection(p_collection, &age_tcp_port_monitor, NULL); /* rebuild the connection peek tables of all monitors * so clients can peek in O(1) time */ for_each_tcp_port_monitor_in_collection(p_collection, &rebuild_tcp_port_monitor_peek_table, NULL); } /* Creation of reduntant monitors is silently ignored */ int insert_new_tcp_port_monitor_into_collection( tcp_port_monitor_collection_t *p_collection, in_port_t port_range_begin, in_port_t port_range_end, tcp_port_monitor_args_t *p_creation_args) { if (!p_collection) { return -1; } p_collection->hash.insert( monitor_hash_t::value_type( port_range_t(port_range_begin, port_range_end), tcp_port_monitor_t(p_creation_args->max_port_monitor_connections) ) ); return 0; } /* Clients need a way to find monitors */ tcp_port_monitor_t *find_tcp_port_monitor( tcp_port_monitor_collection_t *p_collection, in_port_t port_range_begin, in_port_t port_range_end) { if (!p_collection) { return NULL; } /* is monitor in hash? */ monitor_hash_t::iterator i = p_collection->hash.find( port_range_t(port_range_begin, port_range_end) ); return i == p_collection->hash.end() ? NULL : &i->second; } conky-1.10.1/src/libtcp-portmon.h000066400000000000000000000113611262311664100166320ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * libtcp-portmon.h: tcp port monitoring library. * * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. */ #ifndef LIBTCP_PORTMON_H #define LIBTCP_PORTMON_H #include #include #include #include #include #include /* connection deleted if unseen again after this # of refreshes */ #define TCP_CONNECTION_STARTING_AGE 1 #define BUILD_PORT_MONITORS_HASH_KEY_SIZE 12 #define MAX_PORT_MONITOR_CONNECTIONS_DEFAULT 256 /* ------------------------------------------------------------------- * IMPLEMENTATION INTERFACE * * Implementation-specific interface begins here. Clients should not * manipulate these structures directly, nor call the defined helper * functions. Use the "Client interface" functions defined at bottom. * ------------------------------------------------------------------- */ /* The inventory of peekable items within the port monitor. */ enum tcp_port_monitor_peekables { COUNT = 0, REMOTEIP, REMOTEHOST, REMOTEPORT, REMOTESERVICE, LOCALIP, LOCALHOST, LOCALPORT, LOCALSERVICE }; /* ------------------------------------------------------------ * A port monitor * * The definition of the struct is hidden because it contains * C++-specific stuff and we want to #include this from C code. * ------------------------------------------------------------ */ typedef struct _tcp_port_monitor_t tcp_port_monitor_t; /* ------------------------------------------------------------ * A tcp port monitor collection * * The definition of the struct is hidden because it contains * C++-specific stuff and we want to #include this from C code. * ------------------------------------------------------------ */ typedef struct _tcp_port_monitor_collection_t tcp_port_monitor_collection_t; /* ---------------------------------------------------------------------- * CLIENT INTERFACE * * Clients should call only those functions below this line. * ---------------------------------------------------------------------- */ /* struct to hold monitor creation arguments */ typedef struct _tcp_port_monitor_args_t { /* monitor supports tracking at most this many connections */ int max_port_monitor_connections; } tcp_port_monitor_args_t; /* ---------------------------------- * Client operations on port monitors * ---------------------------------- */ /* Clients use this function to get connection data from * the indicated port monitor. * The requested monitor value is copied into a client-supplied char buffer. * Returns 0 on success, -1 otherwise. */ int peek_tcp_port_monitor(const tcp_port_monitor_t *p_monitor, /* (item of interest, from tcp_port_monitor_peekables enum) */ int item, /* (0 to number of connections in monitor - 1) */ int connection_index, /* buffer to receive requested value */ char *p_buffer, /* size of p_buffer */ size_t buffer_size); /* -------------------------------- * Client operations on collections * -------------------------------- */ /* Create a monitor collection. Do this one first. */ tcp_port_monitor_collection_t *create_tcp_port_monitor_collection(void); /* Destroy the monitor collection (and everything it contains). * Do this one last. */ void destroy_tcp_port_monitor_collection( tcp_port_monitor_collection_t *p_collection); /* Updates the tcp statitics for all monitors within a collection */ void update_tcp_port_monitor_collection( tcp_port_monitor_collection_t *p_collection); /* Creation of reduntant monitors is silently ignored * Returns 0 on success, -1 otherwise. */ int insert_new_tcp_port_monitor_into_collection( tcp_port_monitor_collection_t *p_collection, in_port_t port_range_begin, in_port_t port_range_end, tcp_port_monitor_args_t *p_creation_args); /* Clients need a way to find monitors */ tcp_port_monitor_t *find_tcp_port_monitor( tcp_port_monitor_collection_t *p_collection, in_port_t port_range_begin, in_port_t port_range_end); #endif conky-1.10.1/src/linux.cc000066400000000000000000002267501262311664100151700ustar00rootroot00000000000000/* -*- 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) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2007 Toni Spets * Copyright (c) 2005-2012 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 "common.h" #include "linux.h" #include "net_stat.h" #include "diskio.h" #include "temphelper.h" #include "proc.h" #include #include #include #include #include #include #include #ifndef HAVE_CLOCK_GETTIME #include #endif #include #include // #include #include #include #include "setting.hh" #include "top.h" #include #include #include #include #include #include #ifdef _NET_IF_H #define _LINUX_IF_H #endif #include #include #include /* The following ifdefs were adapted from gkrellm */ #include #if !defined(MD_MAJOR) #define MD_MAJOR 9 #endif #if !defined(LVM_BLK_MAJOR) #define LVM_BLK_MAJOR 58 #endif #if !defined(NBD_MAJOR) #define NBD_MAJOR 43 #endif #if !defined(DM_MAJOR) #define DM_MAJOR 253 #endif #ifdef BUILD_WLAN #include #endif struct sysfs { int fd; int arg; char devtype[256]; char type[64]; float factor, offset; }; #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. * using a flag in this manner creates less confusing code. */ static int prefer_proc = 0; void prepare_update(void) { } int update_uptime(void) { #ifdef HAVE_SYSINFO if (!prefer_proc) { struct sysinfo s_info; sysinfo(&s_info); info.uptime = (double) s_info.uptime; } else #endif { static int rep = 0; FILE *fp; if (!(fp = open_file("/proc/uptime", &rep))) { info.uptime = 0.0; return 0; } if (fscanf(fp, "%lf", &info.uptime) <= 0) info.uptime = 0; fclose(fp); } return 0; } int check_mount(struct text_object *obj) { int ret = 0; FILE *mtab; if (!obj->data.s) return 0; if ((mtab = fopen("/etc/mtab", "r"))) { char buf1[256], buf2[129]; while (fgets(buf1, 256, mtab)) { sscanf(buf1, "%*s %128s", buf2); if (!strcmp(obj->data.s, buf2)) { ret = 1; break; } } fclose(mtab); } else { NORM_ERR("Could not open mtab"); } return ret; } /* these things are also in sysinfo except Buffers: * (that's why I'm reading them from proc) */ int update_meminfo(void) { FILE *meminfo_fp; static int rep = 0; /* unsigned int a; */ char buf[256]; unsigned long long shmem = 0, sreclaimable = 0; info.mem = info.memwithbuffers = info.memmax = info.memdirty = info.swap = info.swapfree = info.swapmax = info.bufmem = info.buffers = info.cached = info.memfree = info.memeasyfree = 0; if (!(meminfo_fp = open_file("/proc/meminfo", &rep))) { return 0; } while (!feof(meminfo_fp)) { if (fgets(buf, 255, meminfo_fp) == NULL) { break; } if (strncmp(buf, "MemTotal:", 9) == 0) { sscanf(buf, "%*s %llu", &info.memmax); } else if (strncmp(buf, "MemFree:", 8) == 0) { sscanf(buf, "%*s %llu", &info.memfree); } else if (strncmp(buf, "SwapTotal:", 10) == 0) { sscanf(buf, "%*s %llu", &info.swapmax); } else if (strncmp(buf, "SwapFree:", 9) == 0) { sscanf(buf, "%*s %llu", &info.swapfree); } else if (strncmp(buf, "Buffers:", 8) == 0) { sscanf(buf, "%*s %llu", &info.buffers); } else if (strncmp(buf, "Cached:", 7) == 0) { sscanf(buf, "%*s %llu", &info.cached); } else if (strncmp(buf, "Dirty:", 6) == 0) { sscanf(buf, "%*s %llu", &info.memdirty); } else if (strncmp(buf, "Shmem:", 6) == 0) { sscanf(buf, "%*s %llu", &shmem); } else if (strncmp(buf, "SReclaimable:", 13) == 0) { sscanf(buf, "%*s %llu", &sreclaimable); } } info.mem = info.memwithbuffers = info.memmax - info.memfree; info.memeasyfree = info.memfree; info.swap = info.swapmax - info.swapfree; /* Reclaimable memory: does not include shared memory, which is part of cached but unreclaimable. Includes the reclaimable part of the Slab cache though. Note: when shared memory is swapped out, shmem decreases and swapfree decreases - we want this. */ info.bufmem = (info.cached - shmem) + info.buffers + sreclaimable; /* Now (info.mem - info.bufmem) is the *really used* (aka unreclaimable) memory. When this value reaches the size of the physical RAM, and swap is full or non-present, OOM happens. Therefore this is the value users want to monitor, regarding their RAM. */ fclose(meminfo_fp); return 0; } void print_laptop_mode(struct text_object *obj, char *p, int p_max_size) { FILE *fp; int val = -1; (void)obj; if ((fp = fopen("/proc/sys/vm/laptop_mode", "r")) != NULL) { if (fscanf(fp, "%d\n", &val) <= 0) val = 0; fclose(fp); } snprintf(p, p_max_size, "%d", val); } /* my system says: * # cat /sys/block/sda/queue/scheduler * noop [anticipatory] cfq */ void print_ioscheduler(struct text_object *obj, char *p, int p_max_size) { FILE *fp; char buf[128]; if (!obj->data.s) goto out_fail; snprintf(buf, 127, "/sys/block/%s/queue/scheduler", obj->data.s); if ((fp = fopen(buf, "r")) == NULL) goto out_fail; while (fscanf(fp, "%127s", buf) == 1) { if (buf[0] == '[') { buf[strlen(buf) - 1] = '\0'; snprintf(p, p_max_size, "%s", buf + 1); fclose(fp); return; } } fclose(fp); out_fail: snprintf(p, p_max_size, "n/a"); return; } static struct { char *iface; char *ip; int count; } gw_info; #define SAVE_SET_STRING(x, y) \ if (x && strcmp((char *)x, (char *)y)) { \ free(x); \ x = strndup("multiple", text_buffer_size.get(*state)); \ } else if (!x) { \ x = strndup(y, text_buffer_size.get(*state)); \ } void update_gateway_info_failure(const char *reason) { if(reason != NULL) { perror(reason); } //2 pointers to 1 location causes a crash when we try to free them both gw_info.iface = strndup("failed", text_buffer_size.get(*state)); gw_info.ip = strndup("failed", text_buffer_size.get(*state)); } /* 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" int update_gateway_info(void) { FILE *fp; struct in_addr ina; char iface[64]; unsigned long dest, gate, mask; unsigned int flags; free_and_zero(gw_info.iface); free_and_zero(gw_info.ip); gw_info.count = 0; if ((fp = fopen("/proc/net/route", "r")) == NULL) { update_gateway_info_failure("fopen()"); return 0; } /* skip over the table header line, which is always present */ if (fscanf(fp, "%*[^\n]\n") < 0) { fclose(fp); return 0; } while (!feof(fp)) { if(fscanf(fp, RT_ENTRY_FORMAT, iface, &dest, &gate, &flags, &mask) != 5) { update_gateway_info_failure("fscanf()"); break; } if (!(dest || mask) && ((flags & RTF_GATEWAY) || !gate) ) { gw_info.count++; SAVE_SET_STRING(gw_info.iface, iface) ina.s_addr = gate; SAVE_SET_STRING(gw_info.ip, inet_ntoa(ina)) } } fclose(fp); return 0; } void free_gateway_info(struct text_object *obj) { (void)obj; free_and_zero(gw_info.iface); free_and_zero(gw_info.ip); memset(&gw_info, 0, sizeof(gw_info)); } int gateway_exists(struct text_object *obj) { (void)obj; return !!gw_info.count; } void print_gateway_iface(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", gw_info.iface); } void print_gateway_ip(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", gw_info.ip); } int update_net_stats(void) { FILE *net_dev_fp; static int rep = 0; static char first = 1; // FIXME: arbitrary size chosen to keep code simple. int i, i2; unsigned int curtmp1, curtmp2; unsigned int k; struct ifconf conf; char buf[256]; double delta; #ifdef BUILD_WLAN // wireless info variables int skfd, has_bitrate = 0; struct wireless_info *winfo; struct iwreq wrq; #endif /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { return 0; } /* open file and ignore first two lines */ if (!(net_dev_fp = open_file("/proc/net/dev", &rep))) { clear_net_stats(); return 0; } if (!fgets(buf, 255, net_dev_fp) || /* garbage */ !fgets(buf, 255, net_dev_fp)) { /* garbage (field names) */ fclose(net_dev_fp); return 0; } /* read each interface */ for (i2 = 0; i2 < MAX_NET_INTERFACES; i2++) { struct net_stat *ns; char *s, *p; char temp_addr[18]; long long r, t, last_recv, last_trans; if (fgets(buf, 255, net_dev_fp) == NULL) { break; } p = buf; while (isspace((int) *p)) { p++; } s = p; while (*p && *p != ':') { p++; } if (*p == '\0') { continue; } *p = '\0'; p++; ns = get_net_stat(s, NULL, NULL); ns->up = 1; memset(&(ns->addr.sa_data), 0, 14); memset(ns->addrs, 0, 17 * MAX_NET_INTERFACES + 1); /* Up to 17 chars per ip, max MAX_NET_INTERFACES interfaces. Nasty memory usage... */ last_recv = ns->recv; last_trans = ns->trans; /* bytes packets errs drop fifo frame compressed multicast|bytes ... */ sscanf(p, "%lld %*d %*d %*d %*d %*d %*d %*d %lld", &r, &t); /* if recv or trans is less than last time, an overflow happened */ if (r < ns->last_read_recv) { last_recv = 0; } else { ns->recv += (r - ns->last_read_recv); } ns->last_read_recv = r; if (t < ns->last_read_trans) { last_trans = 0; } else { ns->trans += (t - ns->last_read_trans); } ns->last_read_trans = t; /*** ip addr patch ***/ i = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); conf.ifc_buf = (char*)malloc(sizeof(struct ifreq) * MAX_NET_INTERFACES); conf.ifc_len = sizeof(struct ifreq) * MAX_NET_INTERFACES; memset(conf.ifc_buf, 0, conf.ifc_len); ioctl((long) i, SIOCGIFCONF, &conf); for (k = 0; k < conf.ifc_len / sizeof(struct ifreq); k++) { struct net_stat *ns2; if (!(((struct ifreq *) conf.ifc_buf) + k)) break; ns2 = get_net_stat( ((struct ifreq *) conf.ifc_buf)[k].ifr_ifrn.ifrn_name, NULL, NULL); ns2->addr = ((struct ifreq *) conf.ifc_buf)[k].ifr_ifru.ifru_addr; sprintf(temp_addr, "%u.%u.%u.%u, ", ns2->addr.sa_data[2] & 255, ns2->addr.sa_data[3] & 255, ns2->addr.sa_data[4] & 255, ns2->addr.sa_data[5] & 255); if(NULL == strstr(ns2->addrs, temp_addr)) strncpy(ns2->addrs + strlen(ns2->addrs), temp_addr, 17); } close((long) i); free(conf.ifc_buf); /*** end ip addr patch ***/ if (!first) { /* calculate speeds */ ns->net_rec[0] = (ns->recv - last_recv) / delta; ns->net_trans[0] = (ns->trans - last_trans) / delta; } curtmp1 = 0; curtmp2 = 0; // get an average int samples = net_avg_samples.get(*state); #ifdef HAVE_OPENMP #pragma omp parallel for reduction(+:curtmp1, curtmp2) schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (i = 0; i < samples; i++) { curtmp1 = curtmp1 + ns->net_rec[i]; curtmp2 = curtmp2 + ns->net_trans[i]; } ns->recv_speed = curtmp1 / (double) samples; ns->trans_speed = curtmp2 / (double) samples; if (samples > 1) { #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (i = samples; i > 1; i--) { ns->net_rec[i - 1] = ns->net_rec[i - 2]; ns->net_trans[i - 1] = ns->net_trans[i - 2]; } } #ifdef BUILD_WLAN /* update wireless info */ winfo = (struct wireless_info *) malloc(sizeof(struct wireless_info)); memset(winfo, 0, sizeof(struct wireless_info)); skfd = iw_sockets_open(); if (iw_get_basic_config(skfd, s, &(winfo->b)) > -1) { // set present winfo variables if (iw_get_range_info(skfd, s, &(winfo->range)) >= 0) { winfo->has_range = 1; } if (iw_get_stats(skfd, s, &(winfo->stats), &winfo->range, winfo->has_range) >= 0) { winfo->has_stats = 1; } if (iw_get_ext(skfd, s, SIOCGIWAP, &wrq) >= 0) { winfo->has_ap_addr = 1; memcpy(&(winfo->ap_addr), &(wrq.u.ap_addr), sizeof(sockaddr)); } // get bitrate if (iw_get_ext(skfd, s, SIOCGIWRATE, &wrq) >= 0) { memcpy(&(winfo->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); iw_print_bitrate(ns->bitrate, 16, winfo->bitrate.value); has_bitrate = 1; } // get link quality if (winfo->has_range && winfo->has_stats && ((winfo->stats.qual.level != 0) || (winfo->stats.qual.updated & IW_QUAL_DBM))) { if (!(winfo->stats.qual.updated & IW_QUAL_QUAL_INVALID)) { ns->link_qual = winfo->stats.qual.qual; ns->link_qual_max = winfo->range.max_qual.qual; } } // get ap mac if (winfo->has_ap_addr) { iw_sawap_ntop(&winfo->ap_addr, ns->ap); } // get essid if (winfo->b.has_essid) { if (winfo->b.essid_on) { snprintf(ns->essid, 32, "%s", winfo->b.essid); } else { 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]); } iw_sockets_close(skfd); free(winfo); #endif } #ifdef BUILD_IPV6 FILE *file; char v6addr[33]; char devname[21]; unsigned int netmask, scope; struct net_stat *ns; struct v6addr *lastv6; //remove the old v6 addresses otherwise they are listed multiple times for (unsigned int i = 0; i < MAX_NET_INTERFACES; i++) { ns = &netstats[i]; while(ns->v6addrs != NULL) { lastv6 = ns->v6addrs; ns->v6addrs = ns->v6addrs->next; free(lastv6); } } if ((file = fopen(PROCDIR"/net/if_inet6", "r")) != NULL) { while (fscanf(file, "%32s %*02x %02x %02x %*02x %20s\n", v6addr, &netmask, &scope, devname) != EOF) { ns = get_net_stat(devname, NULL, NULL); if(ns->v6addrs == NULL) { lastv6 = (struct v6addr *) malloc(sizeof(struct v6addr)); ns->v6addrs = lastv6; } else { lastv6 = ns->v6addrs; while(lastv6->next) lastv6 = lastv6->next; lastv6->next = (struct v6addr *) malloc(sizeof(struct v6addr)); lastv6 = lastv6->next; } for(int i=0; i<16; i++) sscanf(v6addr+2*i, "%2hhx", &(lastv6->addr.s6_addr[i])); lastv6->netmask = netmask; switch(scope) { case 0: //global lastv6->scope = 'G'; break; case 16: //host-local lastv6->scope = 'H'; break; case 32: //link-local lastv6->scope = 'L'; break; case 64: //site-local lastv6->scope = 'S'; break; case 128: //compat lastv6->scope = 'C'; break; default: lastv6->scope = '?'; } lastv6->next = NULL; } fclose(file); } #endif /* BUILD_IPV6 */ first = 0; fclose(net_dev_fp); return 0; } int result; int update_total_processes(void) { DIR *dir; struct dirent *entry; int ignore1; char ignore2; info.procs = 0; if (!(dir = opendir("/proc"))) { return 0; } while ((entry = readdir(dir))) { if (!entry) { /* Problem reading list of processes */ closedir(dir); info.procs = 0; return 0; } if (sscanf(entry->d_name, "%d%c", &ignore1, &ignore2) == 1) { info.procs++; } } closedir(dir); return 0; } int update_threads(void) { #ifdef HAVE_SYSINFO if (!prefer_proc) { struct sysinfo s_info; sysinfo(&s_info); info.threads = s_info.procs; } else #endif { static int rep = 0; FILE *fp; if (!(fp = open_file("/proc/loadavg", &rep))) { info.threads = 0; 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 struct cpu_info { unsigned long long cpu_user; unsigned long long cpu_system; unsigned long long cpu_nice; unsigned long long cpu_idle; unsigned long long cpu_iowait; unsigned long long cpu_irq; unsigned long long cpu_softirq; unsigned long long cpu_steal; unsigned long long cpu_total; unsigned long long cpu_active_total; unsigned long long cpu_last_total; unsigned long long cpu_last_active_total; double cpu_val[CPU_SAMPLE_COUNT]; }; static short cpu_setup = 0; /* Determine if this kernel gives us "extended" statistics information in * /proc/stat. * Kernels around 2.5 and earlier only reported user, system, nice, and * idle values in proc stat. * Kernels around 2.6 and greater report these PLUS iowait, irq, softirq, * and steal */ void determine_longstat(char *buf) { unsigned long long iowait = 0; KFLAG_SETOFF(KFLAG_IS_LONGSTAT); /* scanf will either return -1 or 1 because there is only 1 assignment */ if (sscanf(buf, "%*s %*d %*d %*d %*d %llu", &iowait) > 0) { KFLAG_SETON(KFLAG_IS_LONGSTAT); } } void determine_longstat_file(void) { #define MAX_PROCSTAT_LINELEN 255 FILE *stat_fp; static int rep = 0; char buf[MAX_PROCSTAT_LINELEN + 1]; if ( not (stat_fp = open_file("/proc/stat", &rep))) return; while ( not feof(stat_fp)) { if (fgets(buf, MAX_PROCSTAT_LINELEN, stat_fp) == NULL) break; if (strncmp(buf, "cpu", 3) == 0) { determine_longstat(buf); break; } } fclose(stat_fp); } void get_cpu_count(void) { FILE *stat_fp; static int rep = 0; char buf[256]; if (info.cpu_usage) { return; } if (!(stat_fp = open_file("/proc/stat", &rep))) { return; } info.cpu_count = 0; while (!feof(stat_fp)) { if (fgets(buf, 255, stat_fp) == NULL) { break; } if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) { if (info.cpu_count == 0) { determine_longstat(buf); } info.cpu_count++; } } info.cpu_usage = (float*)malloc((info.cpu_count + 1) * sizeof(float)); fclose(stat_fp); } #define TMPL_LONGSTAT "%*s %llu %llu %llu %llu %llu %llu %llu %llu" #define TMPL_SHORTSTAT "%*s %llu %llu %llu %llu" int update_stat(void) { FILE *stat_fp; static int rep = 0; static struct cpu_info *cpu = NULL; char buf[256]; int i; unsigned int idx; double curtmp; const char *stat_template = NULL; unsigned int malloc_cpu_size = 0; extern void* global_cpu; static pthread_mutex_t last_stat_update_mutex = PTHREAD_MUTEX_INITIALIZER; static double last_stat_update = 0.0; /* since we use wrappers for this function, the update machinery * can't eliminate double invocations of this function. Check for * them here, otherwise cpu_usage counters are freaking out. */ pthread_mutex_lock(&last_stat_update_mutex); if (last_stat_update == current_update_time) { pthread_mutex_unlock(&last_stat_update_mutex); return 0; } last_stat_update = current_update_time; pthread_mutex_unlock(&last_stat_update_mutex); /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */ if (!cpu_setup || !info.cpu_usage) { get_cpu_count(); cpu_setup = 1; } if (!stat_template) { stat_template = KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGSTAT : TMPL_SHORTSTAT; } if (!global_cpu) { malloc_cpu_size = (info.cpu_count + 1) * sizeof(struct cpu_info); cpu = (struct cpu_info *)malloc(malloc_cpu_size); memset(cpu, 0, malloc_cpu_size); global_cpu = cpu; } if (!(stat_fp = open_file("/proc/stat", &rep))) { info.run_threads = 0; if (info.cpu_usage) { memset(info.cpu_usage, 0, info.cpu_count * sizeof(float)); } return 0; } idx = 0; while (!feof(stat_fp)) { if (fgets(buf, 255, stat_fp) == NULL) { break; } if (strncmp(buf, "procs_running ", 14) == 0) { sscanf(buf, "%*s %hu", &info.run_threads); } else if (strncmp(buf, "cpu", 3) == 0) { double delta; if (isdigit(buf[3])) { idx = atoi(&buf[3]) + 1; } else { idx = 0; } sscanf(buf, stat_template, &(cpu[idx].cpu_user), &(cpu[idx].cpu_nice), &(cpu[idx].cpu_system), &(cpu[idx].cpu_idle), &(cpu[idx].cpu_iowait), &(cpu[idx].cpu_irq), &(cpu[idx].cpu_softirq), &(cpu[idx].cpu_steal)); cpu[idx].cpu_total = cpu[idx].cpu_user + cpu[idx].cpu_nice + cpu[idx].cpu_system + cpu[idx].cpu_idle + cpu[idx].cpu_iowait + cpu[idx].cpu_irq + cpu[idx].cpu_softirq + cpu[idx].cpu_steal; cpu[idx].cpu_active_total = cpu[idx].cpu_total - (cpu[idx].cpu_idle + cpu[idx].cpu_iowait); delta = current_update_time - last_update_time; if (delta <= 0.001) { break; } cpu[idx].cpu_val[0] = (cpu[idx].cpu_active_total - cpu[idx].cpu_last_active_total) / (float) (cpu[idx].cpu_total - cpu[idx].cpu_last_total); curtmp = 0; int samples = cpu_avg_samples.get(*state); #ifdef HAVE_OPENMP #pragma omp parallel for reduction(+:curtmp) schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (i = 0; i < samples; i++) { curtmp = curtmp + cpu[idx].cpu_val[i]; } info.cpu_usage[idx] = curtmp / samples; cpu[idx].cpu_last_total = cpu[idx].cpu_total; cpu[idx].cpu_last_active_total = cpu[idx].cpu_active_total; #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (i = samples - 1; i > 0; i--) { cpu[idx].cpu_val[i] = cpu[idx].cpu_val[i - 1]; } } } fclose(stat_fp); return 0; } int update_running_processes(void) { update_stat(); return 0; } int update_cpu_usage(void) { update_stat(); return 0; } //fscanf() that reads floats with points even if you are using a locale where //floats are with commas int fscanf_no_i18n(FILE *stream, const char *format, ...) { int returncode; va_list ap; #ifdef BUILD_I18N const char *oldlocale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); #endif va_start(ap, format); returncode = vfscanf(stream, format, ap); va_end(ap); #ifdef BUILD_I18N setlocale(LC_NUMERIC, oldlocale); #endif return returncode; } int update_load_average(void) { #ifdef HAVE_GETLOADAVG if (!prefer_proc) { double v[3]; getloadavg(v, 3); info.loadavg[0] = (float) v[0]; info.loadavg[1] = (float) v[1]; info.loadavg[2] = (float) v[2]; } else #endif { static int rep = 0; FILE *fp; if (!(fp = open_file("/proc/loadavg", &rep))) { info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0; return 0; } if (fscanf_no_i18n(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; } /***********************************************************/ /***********************************************************/ /***********************************************************/ static int no_dots(const struct dirent *d) { if (d->d_name[0] == '.') { return 0; } return 1; } static int get_first_file_in_a_directory(const char *dir, char *s, int *rep) { struct dirent **namelist; int i, n; n = scandir(dir, &namelist, no_dots, alphasort); if (n < 0) { if (!rep || !*rep) { NORM_ERR("scandir for %s: %s", dir, strerror(errno)); if (rep) { *rep = 1; } } return 0; } else { if (n == 0) { return 0; } strncpy(s, namelist[0]->d_name, 255); s[255] = '\0'; #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (i = 0; i < n; i++) { free(namelist[i]); } free(namelist); return 1; } } static int open_sysfs_sensor(const char *dir, const char *dev, const char *type, int n, int *divisor, char *devtype) { char path[256]; char buf[256]; int fd; int divfd; memset(buf, 0, sizeof(buf)); /* if device is NULL or *, get first */ if (dev == NULL || strcmp(dev, "*") == 0) { static int rep = 0; if (!get_first_file_in_a_directory(dir, buf, &rep)) { return -1; } dev = buf; } if (strcmp(dir, "/sys/class/hwmon/") == 0) { if (*buf) { /* buf holds result from get_first_file_in_a_directory() above, * e.g. "hwmon0" -- append "/device" */ strcat(buf, "/device"); } else { /* dev holds device number N as a string, * e.g. "0", -- convert to "hwmon0/device" */ sprintf(buf, "hwmon%s/device", dev); dev = buf; } } /* change vol to in, tempf to temp */ if (strcmp(type, "vol") == 0) { type = "in"; } else if (strcmp(type, "tempf") == 0) { type = "temp"; } /* construct path */ snprintf(path, 255, "%s%s/%s%d_input", dir, dev, type, n); /* first, attempt to open file in /device */ fd = open(path, O_RDONLY); if (fd < 0) { /* if it fails, strip the /device from dev and attempt again */ buf[strlen(buf) - 7] = 0; snprintf(path, 255, "%s%s/%s%d_input", dir, dev, type, n); fd = open(path, O_RDONLY); if (fd < 0) { NORM_ERR("can't open '%s': %s\nplease check your device or remove this " "var from " PACKAGE_NAME, path, strerror(errno)); } } strncpy(devtype, path, 255); if (strcmp(type, "in") == 0 || strcmp(type, "temp") == 0 || strcmp(type, "tempf") == 0) { *divisor = 1; } else { *divisor = 0; } /* fan does not use *_div as a read divisor */ if (strcmp("fan", type) == 0) { return fd; } /* test if *_div file exist, open it and use it as divisor */ if (strcmp(type, "tempf") == 0) { snprintf(path, 255, "%s%s/%s%d_div", dir, "one", "two", n); } else { snprintf(path, 255, "%s%s/%s%d_div", dir, dev, type, n); } divfd = open(path, O_RDONLY); if (divfd > 0) { /* read integer */ char divbuf[64]; int divn; divn = read(divfd, divbuf, 63); /* should read until n == 0 but I doubt that kernel will give these * in multiple pieces. :) */ if (divn < 0) { NORM_ERR("open_sysfs_sensor(): can't read from sysfs"); } else { divbuf[divn] = '\0'; *divisor = atoi(divbuf); } close(divfd); } return fd; } static double get_sysfs_info(int *fd, int divisor, char *devtype, char *type) { int val = 0; if (*fd <= 0) { return 0; } lseek(*fd, 0, SEEK_SET); /* read integer */ { char buf[64]; int n; n = read(*fd, buf, 63); /* should read until n == 0 but I doubt that kernel will give these * in multiple pieces. :) */ if (n < 0) { NORM_ERR("get_sysfs_info(): read from %s failed\n", devtype); } else { buf[n] = '\0'; val = atoi(buf); } } close(*fd); /* open file */ *fd = open(devtype, O_RDONLY); if (*fd < 0) { NORM_ERR("can't open '%s': %s", devtype, strerror(errno)); } /* My dirty hack for computing CPU value * Filedil, from forums.gentoo.org */ /* if (strstr(devtype, "temp1_input") != NULL) { return -15.096 + 1.4893 * (val / 1000.0); } */ /* divide voltage and temperature by 1000 */ /* or if any other divisor is given, use that */ if (strcmp(type, "tempf") == 0) { if (divisor > 1) { return ((val / divisor + 40) * 9.0 / 5) - 40; } else if (divisor) { return ((val / 1000.0 + 40) * 9.0 / 5) - 40; } else { return ((val + 40) * 9.0 / 5) - 40; } } else { if (divisor > 1) { return val / divisor; } else if (divisor) { return val / 1000.0; } else { return val; } } } #define HWMON_RESET() {\ buf1[0] = 0; \ factor = 1.0; \ offset = 0.0; } static void parse_sysfs_sensor(struct text_object *obj, const char *arg, const char *path, const char *type) { char buf1[64], buf2[64]; float factor, offset; int n, found = 0; struct sysfs *sf; if (sscanf(arg, "%63s %d %f %f", buf2, &n, &factor, &offset) == 4) found = 1; else HWMON_RESET(); if (!found && sscanf(arg, "%63s %63s %d %f %f", buf1, buf2, &n, &factor, &offset) == 5) found = 1; else if (!found) HWMON_RESET(); if (!found && sscanf(arg, "%63s %63s %d", buf1, buf2, &n) == 3) found = 1; else if (!found) HWMON_RESET(); if (!found && sscanf(arg, "%63s %d", buf2, &n) == 2) found = 1; else if (!found) HWMON_RESET(); if (!found) { obj_be_plain_text(obj, "fail"); return; } DBGP("parsed %s args: '%s' '%s' %d %f %f\n", type, buf1, buf2, n, factor, offset); sf = (struct sysfs*)malloc(sizeof(struct sysfs)); memset(sf, 0, sizeof(struct sysfs)); sf->fd = open_sysfs_sensor(path, (*buf1) ? buf1 : 0, buf2, n, &sf->arg, sf->devtype); strncpy(sf->type, buf2, 63); sf->factor = factor; sf->offset = offset; obj->data.opaque = sf; } #define PARSER_GENERATOR(name, path) \ void parse_##name##_sensor(struct text_object *obj, const char *arg) \ { \ parse_sysfs_sensor(obj, arg, path, #name); \ } PARSER_GENERATOR(i2c, "/sys/bus/i2c/devices/") PARSER_GENERATOR(hwmon, "/sys/class/hwmon/") PARSER_GENERATOR(platform, "/sys/bus/platform/devices/") void print_sysfs_sensor(struct text_object *obj, char *p, int p_max_size) { double r; struct sysfs *sf = (struct sysfs *)obj->data.opaque; if (!sf || sf->fd < 0) return; r = get_sysfs_info(&sf->fd, sf->arg, sf->devtype, sf->type); r = r * sf->factor + sf->offset; if (!strncmp(sf->type, "temp", 4)) { temp_print(p, p_max_size, r, TEMP_CELSIUS); } else if (r >= 100.0 || r == 0) { snprintf(p, p_max_size, "%d", (int) r); } else { snprintf(p, p_max_size, "%.1f", r); } } void free_sysfs_sensor(struct text_object *obj) { struct sysfs *sf = (struct sysfs *)obj->data.opaque; if (!sf) return; if(sf->fd >= 0) close(sf->fd); free_and_zero(obj->data.opaque); } #define CPUFREQ_PREFIX "/sys/devices/system/cpu" #define CPUFREQ_POSTFIX "cpufreq/scaling_cur_freq" /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */ char get_freq(char *p_client_buffer, size_t client_buffer_size, const char *p_format, int divisor, unsigned int cpu) { FILE *f; static int rep = 0; char frequency[32]; char s[256]; double freq = 0; if (!p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0) { return 0; } if (!prefer_proc) { char current_freq_file[128]; snprintf(current_freq_file, 127, "%s/cpu%d/%s", CPUFREQ_PREFIX, cpu - 1, CPUFREQ_POSTFIX); f = fopen(current_freq_file, "r"); if (f) { /* if there's a cpufreq /sys node, read the current frequency from * this node and divide by 1000 to get Mhz. */ if (fgets(s, sizeof(s), f)) { s[strlen(s) - 1] = '\0'; freq = strtod(s, NULL); } fclose(f); snprintf(p_client_buffer, client_buffer_size, p_format, (freq / 1000) / divisor); return 1; } } // open the CPU information file f = open_file("/proc/cpuinfo", &rep); if (!f) { perror(PACKAGE_NAME": Failed to access '/proc/cpuinfo' at get_freq()"); return 0; } // read the file while (fgets(s, sizeof(s), f) != NULL) { #if defined(__i386) || defined(__x86_64) // and search for the cpu mhz if (strncmp(s, "cpu MHz", 7) == 0 && cpu == 0) { #else #if defined(__alpha) // different on alpha if (strncmp(s, "cycle frequency [Hz]", 20) == 0 && cpu == 0) { #else // this is different on ppc for some reason if (strncmp(s, "clock", 5) == 0 && cpu == 0) { #endif // defined(__alpha) #endif // defined(__i386) || defined(__x86_64) // copy just the number strcpy(frequency, strchr(s, ':') + 2); #if defined(__alpha) // strip " est.\n" frequency[strlen(frequency) - 6] = '\0'; // kernel reports in Hz freq = strtod(frequency, NULL) / 1000000; #else // strip \n frequency[strlen(frequency) - 1] = '\0'; freq = strtod(frequency, NULL); #endif break; } if (strncmp(s, "processor", 9) == 0) { cpu--; continue; } } fclose(f); snprintf(p_client_buffer, client_buffer_size, p_format, (float) freq / divisor); return 1; } #define CPUFREQ_VOLTAGE "cpufreq/scaling_voltages" /* /sys/devices/system/cpu/cpu0/cpufreq/scaling_voltages looks something * like this: # frequency voltage 1800000 1340 1600000 1292 1400000 1100 1200000 988 1000000 1116 800000 1004 600000 988 * Peter Tarjan (ptarjan@citromail.hu) */ /* return cpu voltage in mV (use divisor=1) or V (use divisor=1000) */ static char get_voltage(char *p_client_buffer, size_t client_buffer_size, const char *p_format, int divisor, unsigned int cpu) { FILE *f; char s[256]; int freq = 0; int voltage = 0; char current_freq_file[128]; int freq_comp = 0; /* build the voltage file name */ cpu--; snprintf(current_freq_file, 127, "%s/cpu%d/%s", CPUFREQ_PREFIX, cpu, CPUFREQ_POSTFIX); if (!p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0) { return 0; } /* read the current cpu frequency from the /sys node */ f = fopen(current_freq_file, "r"); if (f) { if (fgets(s, sizeof(s), f)) { s[strlen(s) - 1] = '\0'; freq = strtod(s, NULL); } fclose(f); } else { fprintf(stderr, PACKAGE_NAME": Failed to access '%s' at ", current_freq_file); perror("get_voltage()"); if (f) { fclose(f); } return 0; } snprintf(current_freq_file, 127, "%s/cpu%d/%s", CPUFREQ_PREFIX, cpu, CPUFREQ_VOLTAGE); /* use the current cpu frequency to find the corresponding voltage */ f = fopen(current_freq_file, "r"); if (f) { while (!feof(f)) { char line[256]; if (fgets(line, 255, f) == NULL) { break; } sscanf(line, "%d %d", &freq_comp, &voltage); if (freq_comp == freq) { break; } } fclose(f); } else { fprintf(stderr, PACKAGE_NAME": Failed to access '%s' at ", current_freq_file); perror("get_voltage()"); if (f) { fclose(f); } return 0; } snprintf(p_client_buffer, client_buffer_size, p_format, (float) voltage / divisor); return 1; } void print_voltage_mv(struct text_object *obj, char *p, int p_max_size) { static int ok = 1; if (ok) { ok = get_voltage(p, p_max_size, "%.0f", 1, obj->data.i); } } void print_voltage_v(struct text_object *obj, char *p, int p_max_size) { static int ok = 1; if (ok) { ok = get_voltage(p, p_max_size, "%'.3f", 1000, obj->data.i); } } #define ACPI_FAN_DIR "/proc/acpi/fan/" void get_acpi_fan(char *p_client_buffer, size_t client_buffer_size) { static int rep = 0; char buf[256]; char buf2[256]; FILE *fp; if (!p_client_buffer || client_buffer_size <= 0) { return; } /* yeah, slow... :/ */ if (!get_first_file_in_a_directory(ACPI_FAN_DIR, buf, &rep)) { snprintf(p_client_buffer, client_buffer_size, "no fans?"); return; } snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_FAN_DIR, buf); fp = open_file(buf2, &rep); if (!fp) { snprintf(p_client_buffer, client_buffer_size, "can't open fan's state file"); return; } memset(buf, 0, sizeof(buf)); if (fscanf(fp, "%*s %99s", buf) <= 0) perror("fscanf()"); fclose(fp); snprintf(p_client_buffer, client_buffer_size, "%s", buf); } #define SYSFS_AC_ADAPTER_DIR "/sys/class/power_supply" #define ACPI_AC_ADAPTER_DIR "/proc/acpi/ac_adapter/" /* Linux 2.6.25 onwards ac adapter info is in /sys/class/power_supply/AC/ On my system I get the following. /sys/class/power_supply/AC/uevent: PHYSDEVPATH=/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00 PHYSDEVBUS=acpi PHYSDEVDRIVER=ac POWER_SUPPLY_NAME=AC POWER_SUPPLY_TYPE=Mains POWER_SUPPLY_ONLINE=1 Update: it seems the folder name is hardware-dependent. We add an aditional adapter argument, specifying the folder name. Update: on some systems it's /sys/class/power_supply/ADP1 instead of /sys/class/power_supply/AC */ void get_acpi_ac_adapter(char *p_client_buffer, size_t client_buffer_size, const char *adapter) { static int rep = 0; char buf[256]; char buf2[256]; struct stat sb; FILE *fp; if (!p_client_buffer || client_buffer_size <= 0) { return; } if(adapter) snprintf(buf2, sizeof(buf2), "%s/%s/uevent", SYSFS_AC_ADAPTER_DIR, adapter); else{ snprintf(buf2, sizeof(buf2), "%s/AC/uevent", SYSFS_AC_ADAPTER_DIR); if(stat(buf2, &sb) == -1) snprintf(buf2, sizeof(buf2), "%s/ADP1/uevent", SYSFS_AC_ADAPTER_DIR); } if(stat(buf2, &sb) == 0) fp = open_file(buf2, &rep); else fp = 0; if (fp) { /* sysfs processing */ while (!feof(fp)) { if (fgets(buf, sizeof(buf), fp) == NULL) break; if (strncmp(buf, "POWER_SUPPLY_ONLINE=", 20) == 0) { int online = 0; sscanf(buf, "POWER_SUPPLY_ONLINE=%d", &online); snprintf(p_client_buffer, client_buffer_size, "%s-line", (online ? "on" : "off")); break; } } fclose(fp); } else { /* yeah, slow... :/ */ if (!get_first_file_in_a_directory(ACPI_AC_ADAPTER_DIR, buf, &rep)) { snprintf(p_client_buffer, client_buffer_size, "no ac_adapters?"); return; } snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_AC_ADAPTER_DIR, buf); fp = open_file(buf2, &rep); if (!fp) { snprintf(p_client_buffer, client_buffer_size, "No ac adapter found.... where is it?"); return; } memset(buf, 0, sizeof(buf)); if (fscanf(fp, "%*s %99s", buf) <= 0) perror("fscanf()"); fclose(fp); snprintf(p_client_buffer, client_buffer_size, "%s", buf); } } /* /proc/acpi/thermal_zone/THRM/cooling_mode cooling mode: active /proc/acpi/thermal_zone/THRM/polling_frequency /proc/acpi/thermal_zone/THRM/state state: ok /proc/acpi/thermal_zone/THRM/temperature temperature: 45 C /proc/acpi/thermal_zone/THRM/trip_points critical (S5): 73 C passive: 73 C: tc1=4 tc2=3 tsp=40 devices=0xcdf6e6c0 */ #define ACPI_THERMAL_ZONE_DEFAULT "thermal_zone0" #define ACPI_THERMAL_FORMAT "/sys/class/thermal/%s/temp" int open_acpi_temperature(const char *name) { char path[256]; int fd; if (name == NULL || strcmp(name, "*") == 0) { snprintf(path, 255, ACPI_THERMAL_FORMAT, ACPI_THERMAL_ZONE_DEFAULT); } else { snprintf(path, 255, ACPI_THERMAL_FORMAT, name); } fd = open(path, O_RDONLY); if (fd < 0) { NORM_ERR("can't open '%s': %s", path, strerror(errno)); } return fd; } static double last_acpi_temp; static double last_acpi_temp_time; //the maximum length of the string inside a ACPI_THERMAL_FORMAT file including the ending 0 #define MAXTHERMZONELEN 6 double get_acpi_temperature(int fd) { if (fd <= 0) { return 0; } /* don't update acpi temperature too often */ if (current_update_time - last_acpi_temp_time < 11.32) { return last_acpi_temp; } last_acpi_temp_time = current_update_time; /* seek to beginning */ lseek(fd, 0, SEEK_SET); /* read */ { char buf[MAXTHERMZONELEN]; int n; n = read(fd, buf, MAXTHERMZONELEN-1); if (n < 0) { NORM_ERR("can't read fd %d: %s", fd, strerror(errno)); } else { buf[n] = '\0'; sscanf(buf, "%lf", &last_acpi_temp); last_acpi_temp /= 1000; } } return last_acpi_temp; } /* hipo@lepakko hipo $ cat /proc/acpi/battery/BAT1/info present: yes design capacity: 4400 mAh last full capacity: 4064 mAh battery technology: rechargeable design voltage: 14800 mV design capacity warning: 300 mAh design capacity low: 200 mAh capacity granularity 1: 32 mAh capacity granularity 2: 32 mAh model number: 02KT serial number: 16922 battery type: LION OEM info: SANYO */ /* hipo@lepakko conky $ cat /proc/acpi/battery/BAT1/state present: yes capacity state: ok charging state: unknown present rate: 0 mA remaining capacity: 4064 mAh present voltage: 16608 mV */ /* 2213<@jupet�kellari��> jupet@lagi-unstable:~$ cat /proc/apm 2213<@jupet�kellari��> 1.16 1.2 0x03 0x01 0xff 0x10 -1% -1 ? 2213<@jupet�kellari��> (-1 ollee ei akkua kiinni, koska akku on p�yd�ll�) 2214<@jupet�kellari��> jupet@lagi-unstable:~$ cat /proc/apm 2214<@jupet�kellari��> 1.16 1.2 0x03 0x01 0x03 0x09 98% -1 ? 2238<@jupet�kellari��> 1.16 1.2 0x03 0x00 0x00 0x01 100% -1 ? ilman verkkovirtaa 2239<@jupet�kellari��> 1.16 1.2 0x03 0x01 0x00 0x01 99% -1 ? verkkovirralla 2240<@jupet�kellari��> 1.16 1.2 0x03 0x01 0x03 0x09 100% -1 ? verkkovirralla ja monitori p��ll� 2241<@jupet�kellari��> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori p��ll� mutta ilman verkkovirtaa */ /* Kapil Hari Paranjape Linux 2.6.24 onwards battery info is in /sys/class/power_supply/BAT0/ On my system I get the following. /sys/class/power_supply/BAT0/uevent: PHYSDEVPATH=/devices/LNXSYSTM:00/device:00/PNP0A03:00/device:01/PNP0C09:00/PNP0C0A:00 PHYSDEVBUS=acpi PHYSDEVDRIVER=battery POWER_SUPPLY_NAME=BAT0 POWER_SUPPLY_TYPE=Battery POWER_SUPPLY_STATUS=Discharging POWER_SUPPLY_PRESENT=1 POWER_SUPPLY_TECHNOLOGY=Li-ion POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000 POWER_SUPPLY_VOLTAGE_NOW=10780000 POWER_SUPPLY_CURRENT_NOW=13970000 POWER_SUPPLY_ENERGY_FULL_DESIGN=47510000 POWER_SUPPLY_ENERGY_FULL=27370000 POWER_SUPPLY_ENERGY_NOW=11810000 POWER_SUPPLY_MODEL_NAME=IBM-92P1060 POWER_SUPPLY_MANUFACTURER=Panasonic On some systems POWER_SUPPLY_ENERGY_* is replaced by POWER_SUPPLY_CHARGE_* */ /* Tiago Marques Vale Regarding the comment above, since kernel 2.6.36.1 I have POWER_SUPPLY_POWER_NOW instead of POWER_SUPPLY_CURRENT_NOW See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=532000 */ #define SYSFS_BATTERY_BASE_PATH "/sys/class/power_supply" #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery" #define APM_PATH "/proc/apm" #define MAX_BATTERY_COUNT 4 static FILE *sysfs_bat_fp[MAX_BATTERY_COUNT] = { NULL, NULL, NULL, NULL }; static FILE *acpi_bat_fp[MAX_BATTERY_COUNT] = { NULL, NULL, NULL, NULL }; static FILE *apm_bat_fp[MAX_BATTERY_COUNT] = { NULL, NULL, NULL, NULL }; static int batteries_initialized = 0; static char batteries[MAX_BATTERY_COUNT][32]; static int acpi_last_full[MAX_BATTERY_COUNT]; static int acpi_design_capacity[MAX_BATTERY_COUNT]; /* e.g. "charging 75%" */ static char last_battery_str[MAX_BATTERY_COUNT][64]; /* e.g. "3h 15m" */ static char last_battery_time_str[MAX_BATTERY_COUNT][64]; static double last_battery_time[MAX_BATTERY_COUNT]; static int last_battery_perct[MAX_BATTERY_COUNT]; static double last_battery_perct_time[MAX_BATTERY_COUNT]; void init_batteries(void) { int idx; if (batteries_initialized) { return; } #ifdef HAVE_OPENMP #pragma omp parallel for schedule(dynamic,10) #endif /* HAVE_OPENMP */ for (idx = 0; idx < MAX_BATTERY_COUNT; idx++) { batteries[idx][0] = '\0'; } batteries_initialized = 1; } int get_battery_idx(const char *bat) { int idx; for (idx = 0; idx < MAX_BATTERY_COUNT; idx++) { if (!strlen(batteries[idx]) || !strcmp(batteries[idx], bat)) { break; } } /* if not found, enter a new entry */ if (!strlen(batteries[idx])) { snprintf(batteries[idx], 31, "%s", bat); } return idx; } void set_return_value(char *buffer, unsigned int n, int item, int idx); void get_battery_stuff(char *buffer, unsigned int n, const char *bat, int item) { static int idx, rep = 0, rep1 = 0, rep2 = 0; char acpi_path[128]; char sysfs_path[128]; snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat); snprintf(sysfs_path, 127, SYSFS_BATTERY_BASE_PATH "/%s/uevent", bat); init_batteries(); idx = get_battery_idx(bat); /* don't update battery too often */ if (current_update_time - last_battery_time[idx] < 29.5) { set_return_value(buffer, n, item, idx); return; } last_battery_time[idx] = current_update_time; memset(last_battery_str[idx], 0, sizeof(last_battery_str[idx])); memset(last_battery_time_str[idx], 0, sizeof(last_battery_time_str[idx])); /* first try SYSFS if that fails try ACPI */ if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL) { sysfs_bat_fp[idx] = open_file(sysfs_path, &rep); } if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL) { acpi_bat_fp[idx] = open_file(acpi_path, &rep1); } if (sysfs_bat_fp[idx] != NULL) { /* SYSFS */ int present_rate = -1; int remaining_capacity = -1; char charging_state[64]; char present[4]; strcpy(charging_state, "unknown"); while (!feof(sysfs_bat_fp[idx])) { char buf[256]; if (fgets(buf, 256, sysfs_bat_fp[idx]) == NULL) break; /* let's just hope units are ok */ if (strncmp (buf, "POWER_SUPPLY_PRESENT=1", 22) == 0) strcpy(present, "yes"); else if (strncmp (buf, "POWER_SUPPLY_PRESENT=0", 22) == 0) strcpy(present, "no"); else if (strncmp (buf, "POWER_SUPPLY_STATUS=", 20) == 0) sscanf(buf, "POWER_SUPPLY_STATUS=%63s", charging_state); /* present_rate is not the same as the current flowing now but it * is the same value which was used in the past. so we continue the * tradition! */ else if (strncmp(buf, "POWER_SUPPLY_CURRENT_NOW=", 25) == 0) sscanf(buf, "POWER_SUPPLY_CURRENT_NOW=%d", &present_rate); else if (strncmp(buf, "POWER_SUPPLY_POWER_NOW=", 23) == 0) sscanf(buf, "POWER_SUPPLY_POWER_NOW=%d", &present_rate); else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) == 0) sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", &remaining_capacity); else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=", 25) == 0) sscanf(buf, "POWER_SUPPLY_ENERGY_FULL=%d", &acpi_last_full[idx]); else if (strncmp(buf, "POWER_SUPPLY_CHARGE_NOW=", 24) == 0) sscanf(buf, "POWER_SUPPLY_CHARGE_NOW=%d", &remaining_capacity); else if (strncmp(buf, "POWER_SUPPLY_CHARGE_FULL=", 25) == 0) sscanf(buf, "POWER_SUPPLY_CHARGE_FULL=%d", &acpi_last_full[idx]); } fclose(sysfs_bat_fp[idx]); sysfs_bat_fp[idx] = NULL; /* Hellf[i]re notes that remaining capacity can exceed acpi_last_full */ if (remaining_capacity > acpi_last_full[idx]) acpi_last_full[idx] = remaining_capacity; /* normalize to 100% */ /* not present */ if (strcmp(present, "No") == 0) { strncpy(last_battery_str[idx], "not present", 64); } /* charging */ else if (strcmp(charging_state, "Charging") == 0) { if (acpi_last_full[idx] != 0 && present_rate > 0) { /* e.g. charging 75% */ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "charging %i%%", (int) (((float) remaining_capacity / acpi_last_full[idx]) * 100 )); /* e.g. 2h 37m */ format_seconds(last_battery_time_str[idx], sizeof(last_battery_time_str[idx])-1, (long) (((float)(acpi_last_full[idx] - remaining_capacity) / present_rate) * 3600)); } else if (acpi_last_full[idx] != 0 && present_rate <= 0) { snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "charging %d%%", (int) (((float)remaining_capacity / acpi_last_full[idx]) * 100)); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } else { strncpy(last_battery_str[idx], "charging", sizeof(last_battery_str[idx])-1); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } } /* discharging */ else if (strncmp(charging_state, "Discharging", 64) == 0) { if (present_rate > 0) { /* e.g. discharging 35% */ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "discharging %i%%", (int) (((float) remaining_capacity / acpi_last_full[idx]) * 100 )); /* e.g. 1h 12m */ format_seconds(last_battery_time_str[idx], sizeof(last_battery_time_str[idx])-1, (long) (((float) remaining_capacity / present_rate) * 3600)); } else if (present_rate == 0) { /* Thanks to Nexox for this one */ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "full"); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } else { snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "discharging %d%%", (int) (((float)remaining_capacity / acpi_last_full[idx]) * 100)); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } } /* charged */ /* thanks to Lukas Zapletal */ else if (strncmp(charging_state, "Charged", 64) == 0 || strncmp(charging_state, "Full", 64) == 0) { /* Below happens with the second battery on my X40, * when the second one is empty and the first one * being charged. */ if (remaining_capacity == 0) strcpy(last_battery_str[idx], "empty"); else strcpy(last_battery_str[idx], "charged"); } /* unknown, probably full / AC */ else { if (acpi_last_full[idx] != 0 && remaining_capacity != acpi_last_full[idx]) snprintf(last_battery_str[idx], 64, "unknown %d%%", (int) (((float)remaining_capacity / acpi_last_full[idx]) * 100)); else strncpy(last_battery_str[idx], "not present", 64); } } else if (acpi_bat_fp[idx] != NULL) { /* ACPI */ int present_rate = -1; int remaining_capacity = -1; char charging_state[64]; char present[5]; /* read last full capacity if it's zero */ if (acpi_last_full[idx] == 0) { static int rep3 = 0; char path[128]; FILE *fp; snprintf(path, 127, ACPI_BATTERY_BASE_PATH "/%s/info", bat); fp = open_file(path, &rep3); if (fp != NULL) { while (!feof(fp)) { char b[256]; if (fgets(b, 256, fp) == NULL) { break; } if (sscanf(b, "last full capacity: %d", &acpi_last_full[idx]) != 0) { break; } } fclose(fp); } } fseek(acpi_bat_fp[idx], 0, SEEK_SET); strcpy(charging_state, "unknown"); while (!feof(acpi_bat_fp[idx])) { char buf[256]; if (fgets(buf, 256, acpi_bat_fp[idx]) == NULL) { break; } /* let's just hope units are ok */ if (strncmp(buf, "present:", 8) == 0) { sscanf(buf, "present: %4s", present); } else if (strncmp(buf, "charging state:", 15) == 0) { sscanf(buf, "charging state: %63s", charging_state); } else if (strncmp(buf, "present rate:", 13) == 0) { sscanf(buf, "present rate: %d", &present_rate); } else if (strncmp(buf, "remaining capacity:", 19) == 0) { sscanf(buf, "remaining capacity: %d", &remaining_capacity); } } /* Hellf[i]re notes that remaining capacity can exceed acpi_last_full */ if (remaining_capacity > acpi_last_full[idx]) { /* normalize to 100% */ acpi_last_full[idx] = remaining_capacity; } /* not present */ if (strcmp(present, "no") == 0) { strncpy(last_battery_str[idx], "not present", 64); /* charging */ } else if (strcmp(charging_state, "charging") == 0) { if (acpi_last_full[idx] != 0 && present_rate > 0) { /* e.g. charging 75% */ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx]) - 1, "charging %i%%", (int) ((remaining_capacity * 100) / acpi_last_full[idx])); /* e.g. 2h 37m */ format_seconds(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, (long) (((acpi_last_full[idx] - remaining_capacity) * 3600) / present_rate)); } else if (acpi_last_full[idx] != 0 && present_rate <= 0) { snprintf(last_battery_str[idx], sizeof(last_battery_str[idx]) - 1, "charging %d%%", (int) ((remaining_capacity * 100) / acpi_last_full[idx])); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } else { strncpy(last_battery_str[idx], "charging", sizeof(last_battery_str[idx]) - 1); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } /* discharging */ } else if (strncmp(charging_state, "discharging", 64) == 0) { if (present_rate > 0) { /* e.g. discharging 35% */ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx]) - 1, "discharging %i%%", (int) ((remaining_capacity * 100) / acpi_last_full[idx])); /* e.g. 1h 12m */ format_seconds(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, (long) ((remaining_capacity * 3600) / present_rate)); } else if (present_rate == 0) { /* Thanks to Nexox for this one */ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx]) - 1, "charged"); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } else { snprintf(last_battery_str[idx], sizeof(last_battery_str[idx]) - 1, "discharging %d%%", (int) ((remaining_capacity * 100) / acpi_last_full[idx])); snprintf(last_battery_time_str[idx], sizeof(last_battery_time_str[idx]) - 1, "unknown"); } /* charged */ } else if (strncmp(charging_state, "charged", 64) == 0) { /* thanks to Lukas Zapletal */ /* Below happens with the second battery on my X40, * when the second one is empty and the first one being charged. */ if (remaining_capacity == 0) { strcpy(last_battery_str[idx], "empty"); } else { strcpy(last_battery_str[idx], "charged"); } /* unknown, probably full / AC */ } else { if (strncmp(charging_state, "Full", 64) == 0) { strncpy(last_battery_str[idx], "charged", 64); } else if (acpi_last_full[idx] != 0 && remaining_capacity != acpi_last_full[idx]) { snprintf(last_battery_str[idx], 64, "unknown %d%%", (int) ((remaining_capacity * 100) / acpi_last_full[idx])); } else { strncpy(last_battery_str[idx], "not present", 64); } } fclose(acpi_bat_fp[idx]); acpi_bat_fp[idx] = NULL; } else { /* APM */ if (apm_bat_fp[idx] == NULL) { apm_bat_fp[idx] = open_file(APM_PATH, &rep2); } if (apm_bat_fp[idx] != NULL) { unsigned int ac, status, flag; int life; if (fscanf(apm_bat_fp[idx], "%*s %*s %*x %x %x %x %d%%", &ac, &status, &flag, &life) <= 0) goto read_bat_fp_end; if (life == -1) { /* could check now that there is ac */ snprintf(last_battery_str[idx], 64, "not present"); /* could check that status == 3 here? */ } else if (ac && life != 100) { snprintf(last_battery_str[idx], 64, "charging %d%%", life); } else { snprintf(last_battery_str[idx], 64, "%d%%", life); } read_bat_fp_end: /* it seemed to buffer it so file must be closed (or could use * syscalls directly but I don't feel like coding it now) */ fclose(apm_bat_fp[idx]); apm_bat_fp[idx] = NULL; } } set_return_value(buffer, n, item, idx); } void set_return_value(char *buffer, unsigned int n, int item, int idx) { switch (item) { case BATTERY_STATUS: snprintf(buffer, n, "%s", last_battery_str[idx]); break; case BATTERY_TIME: snprintf(buffer, n, "%s", last_battery_time_str[idx]); break; default: break; } } void get_battery_short_status(char *buffer, unsigned int n, const char *bat) { get_battery_stuff(buffer, n, bat, BATTERY_STATUS); if (0 == strncmp("charging", buffer, 8)) { buffer[0] = 'C'; memmove(buffer + 1, buffer + 8, n - 8); } else if (0 == strncmp("discharging", buffer, 11)) { buffer[0] = 'D'; memmove(buffer + 1, buffer + 11, n - 11); } else if (0 == strncmp("charged", buffer, 7)) { buffer[0] = 'F'; memmove(buffer + 1, buffer + 7, n - 7); } else if (0 == strncmp("not present", buffer, 11)) { buffer[0] = 'N'; memmove(buffer + 1, buffer + 11, n - 11); } else if (0 == strncmp("empty", buffer, 5)) { buffer[0] = 'E'; memmove(buffer + 1, buffer + 5, n - 5); } else if (0 == strncmp("unknown", buffer, 7)) { buffer[0] = 'U'; memmove(buffer + 1, buffer + 7, n - 7); } // Otherwise, don't shorten. } int _get_battery_perct(const char *bat) { static int rep = 0; int idx; char acpi_path[128]; char sysfs_path[128]; int remaining_capacity = -1; snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat); snprintf(sysfs_path, 127, SYSFS_BATTERY_BASE_PATH "/%s/uevent", bat); idx = get_battery_idx(bat); /* don't update battery too often */ if (current_update_time - last_battery_perct_time[idx] < 30) { return last_battery_perct[idx]; } last_battery_perct_time[idx] = current_update_time; /* Only check for SYSFS or ACPI */ if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL) { sysfs_bat_fp[idx] = open_file(sysfs_path, &rep); rep = 0; } if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL) { acpi_bat_fp[idx] = open_file(acpi_path, &rep); } if (sysfs_bat_fp[idx] != NULL) { /* SYSFS */ while (!feof(sysfs_bat_fp[idx])) { char buf[256]; if (fgets(buf, 256, sysfs_bat_fp[idx]) == NULL) break; if (strncmp(buf, "POWER_SUPPLY_CHARGE_NOW=", 24) == 0) { sscanf(buf, "POWER_SUPPLY_CHARGE_NOW=%d", &remaining_capacity); } else if (strncmp(buf, "POWER_SUPPLY_CHARGE_FULL=",25) == 0) { sscanf(buf, "POWER_SUPPLY_CHARGE_FULL=%d", &acpi_design_capacity[idx]); } else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) == 0) { sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", &remaining_capacity); } else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=",25) == 0) { sscanf(buf, "POWER_SUPPLY_ENERGY_FULL=%d", &acpi_design_capacity[idx]); } } fclose(sysfs_bat_fp[idx]); sysfs_bat_fp[idx] = NULL; } else if (acpi_bat_fp[idx] != NULL) { /* ACPI */ /* read last full capacity if it's zero */ if (acpi_design_capacity[idx] == 0) { static int rep2; char path[128]; FILE *fp; snprintf(path, 127, ACPI_BATTERY_BASE_PATH "/%s/info", bat); fp = open_file(path, &rep2); if (fp != NULL) { while (!feof(fp)) { char b[256]; if (fgets(b, 256, fp) == NULL) { break; } if (sscanf(b, "last full capacity: %d", &acpi_design_capacity[idx]) != 0) { break; } } fclose(fp); } } fseek(acpi_bat_fp[idx], 0, SEEK_SET); while (!feof(acpi_bat_fp[idx])) { char buf[256]; if (fgets(buf, 256, acpi_bat_fp[idx]) == NULL) { break; } if (buf[0] == 'r') { sscanf(buf, "remaining capacity: %d", &remaining_capacity); } } } if (remaining_capacity < 0) { return 0; } /* compute the battery percentage */ last_battery_perct[idx] = (int) (((float) remaining_capacity / acpi_design_capacity[idx]) * 100); if (last_battery_perct[idx] > 100) last_battery_perct[idx] = 100; return last_battery_perct[idx]; } int get_battery_perct(const char *bat) { int idx, n = 0, total_capacity = 0, remaining_capacity;; #define BATTERY_LEN 8 char battery[BATTERY_LEN]; init_batteries(); /* Check if user asked for the mean percentage of all batteries. */ if (!strcmp(bat, "all")) { for (idx = 0; idx < MAX_BATTERY_COUNT; idx++) { snprintf(battery, BATTERY_LEN - 1, "BAT%d", idx); #undef BATTERY_LEN remaining_capacity = _get_battery_perct(battery); if (remaining_capacity > 0) { total_capacity += remaining_capacity; n++; } } if (n == 0) return 0; else return total_capacity / n; } else { return _get_battery_perct(bat); } } double get_battery_perct_bar(struct text_object *obj) { int idx; get_battery_perct(obj->data.s); idx = get_battery_idx(obj->data.s); return last_battery_perct[idx]; } /* On Apple powerbook and ibook: $ cat /proc/pmu/battery_0 flags : 00000013 charge : 3623 max_charge : 3720 current : 388 voltage : 16787 time rem. : 900 $ cat /proc/pmu/info PMU driver version : 2 PMU firmware version : 0c AC Power : 1 Battery count : 1 */ /* defines as in */ #define PMU_BATT_PRESENT 0x00000001 #define PMU_BATT_CHARGING 0x00000002 static FILE *pmu_battery_fp; static FILE *pmu_info_fp; static char pb_battery_info[3][32]; static double pb_battery_info_update; #define PMU_PATH "/proc/pmu" void get_powerbook_batt_info(struct text_object *obj, char *buffer, int n) { static int rep = 0; const char *batt_path = PMU_PATH "/battery_0"; const char *info_path = PMU_PATH "/info"; unsigned int flags; int charge, max_charge, ac = -1; long timeval = -1; /* don't update battery too often */ if (current_update_time - pb_battery_info_update < 29.5) { snprintf(buffer, n, "%s", pb_battery_info[obj->data.i]); return; } pb_battery_info_update = current_update_time; if (pmu_battery_fp == NULL) { pmu_battery_fp = open_file(batt_path, &rep); if (pmu_battery_fp == NULL) { return; } } if (pmu_battery_fp != NULL) { rewind(pmu_battery_fp); while (!feof(pmu_battery_fp)) { char buf[32]; if (fgets(buf, sizeof(buf), pmu_battery_fp) == NULL) { break; } if (buf[0] == 'f') { sscanf(buf, "flags : %8x", &flags); } else if (buf[0] == 'c' && buf[1] == 'h') { sscanf(buf, "charge : %d", &charge); } else if (buf[0] == 'm') { sscanf(buf, "max_charge : %d", &max_charge); } else if (buf[0] == 't') { sscanf(buf, "time rem. : %ld", &timeval); } } } if (pmu_info_fp == NULL) { pmu_info_fp = open_file(info_path, &rep); if (pmu_info_fp == NULL) { return; } } if (pmu_info_fp != NULL) { rewind(pmu_info_fp); while (!feof(pmu_info_fp)) { char buf[32]; if (fgets(buf, sizeof(buf), pmu_info_fp) == NULL) { break; } if (buf[0] == 'A') { sscanf(buf, "AC Power : %d", &ac); } } } /* update status string */ if ((ac && !(flags & PMU_BATT_PRESENT))) { strncpy(pb_battery_info[PB_BATT_STATUS], "AC", sizeof(pb_battery_info[PB_BATT_STATUS])); } else if (ac && (flags & PMU_BATT_PRESENT) && !(flags & PMU_BATT_CHARGING)) { strncpy(pb_battery_info[PB_BATT_STATUS], "charged", sizeof(pb_battery_info[PB_BATT_STATUS])); } else if ((flags & PMU_BATT_PRESENT) && (flags & PMU_BATT_CHARGING)) { strncpy(pb_battery_info[PB_BATT_STATUS], "charging", sizeof(pb_battery_info[PB_BATT_STATUS])); } else { strncpy(pb_battery_info[PB_BATT_STATUS], "discharging", sizeof(pb_battery_info[PB_BATT_STATUS])); } /* update percentage string */ if (timeval == 0 && ac && (flags & PMU_BATT_PRESENT) && !(flags & PMU_BATT_CHARGING)) { snprintf(pb_battery_info[PB_BATT_PERCENT], sizeof(pb_battery_info[PB_BATT_PERCENT]), "100%%"); } else if (timeval == 0) { snprintf(pb_battery_info[PB_BATT_PERCENT], sizeof(pb_battery_info[PB_BATT_PERCENT]), "unknown"); } else { snprintf(pb_battery_info[PB_BATT_PERCENT], sizeof(pb_battery_info[PB_BATT_PERCENT]), "%d%%", (charge * 100) / max_charge); } /* update time string */ if (timeval == 0) { /* fully charged or battery not present */ snprintf(pb_battery_info[PB_BATT_TIME], sizeof(pb_battery_info[PB_BATT_TIME]), "unknown"); } else if (timeval < 60 * 60) { /* don't show secs */ format_seconds_short(pb_battery_info[PB_BATT_TIME], sizeof(pb_battery_info[PB_BATT_TIME]), timeval); } else { format_seconds(pb_battery_info[PB_BATT_TIME], sizeof(pb_battery_info[PB_BATT_TIME]), timeval); } snprintf(buffer, n, "%s", pb_battery_info[obj->data.i]); } #define ENTROPY_AVAIL_PATH "/proc/sys/kernel/random/entropy_avail" int get_entropy_avail(unsigned int *val) { static int rep = 0; FILE *fp; if (!(fp = open_file(ENTROPY_AVAIL_PATH, &rep))) return 1; if (fscanf(fp, "%u", val) != 1) return 1; fclose(fp); return 0; } #define ENTROPY_POOLSIZE_PATH "/proc/sys/kernel/random/poolsize" int get_entropy_poolsize(unsigned int *val) { static int rep = 0; FILE *fp; if (!(fp = open_file(ENTROPY_POOLSIZE_PATH, &rep))) return 1; if (fscanf(fp, "%u", val) != 1) return 1; fclose(fp); return 0; } void print_disk_protect_queue(struct text_object *obj, char *p, int p_max_size) { FILE *fp; char path[128]; int state; snprintf(path, 127, "/sys/block/%s/device/unload_heads", obj->data.s); if (access(path, F_OK)) { snprintf(path, 127, "/sys/block/%s/queue/protect", obj->data.s); } if ((fp = fopen(path, "r")) == NULL) { snprintf(p, p_max_size, "n/a "); return; } if (fscanf(fp, "%d\n", &state) != 1) { fclose(fp); snprintf(p, p_max_size, "failed"); return; } fclose(fp); snprintf(p, p_max_size, (state > 0) ? "frozen" : "free "); } std::unordered_map dev_list; /* Same as sf #2942117 but memoized using a linked list */ int is_disk(char *dev) { std::string orig(dev); std::string syspath("/sys/block/"); char *slash; auto i = dev_list.find(orig); if(i != dev_list.end()) return i->second; while ((slash = strchr(dev, '/'))) *slash = '!'; syspath += dev; return dev_list[orig] = !(access(syspath.c_str(), F_OK)); } int update_diskio(void) { FILE *fp; static int rep = 0; char buf[512], devbuf[64]; unsigned int major, minor; int col_count = 0; struct diskio_stat *cur; unsigned int reads, writes; unsigned int total_reads = 0, total_writes = 0; stats.current = 0; stats.current_read = 0; stats.current_write = 0; if (!(fp = open_file("/proc/diskstats", &rep))) { return 0; } /* read reads and writes from all disks (minor = 0), including cd-roms * and floppies, and sum them up */ while (fgets(buf, 512, fp)) { col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u", &major, &minor, devbuf, &reads, &writes); /* ignore subdevices (they have only 3 matching entries in their line) * and virtual devices (LVM, network block devices, RAM disks, Loopback) * * XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */ if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR && major != RAMDISK_MAJOR && major != LOOP_MAJOR && major != DM_MAJOR) { /* check needed for kernel >= 2.6.31, see sf #2942117 */ if (is_disk(devbuf)) { total_reads += reads; total_writes += writes; } } else { col_count = sscanf(buf, "%u %u %s %*u %u %*u %u", &major, &minor, devbuf, &reads, &writes); if (col_count != 5) { continue; } } cur = stats.next; while (cur && strcmp(devbuf, cur->dev)) cur = cur->next; if (cur) update_diskio_values(cur, reads, writes); } 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) { (void)obj; int i, bytes_read; char* buf; struct stat sb; if(stat("/etc/arch-release", &sb) == 0) { snprintf(p, p_max_size, "Arch Linux"); return; } snprintf(p, p_max_size, "Unknown"); buf = readfile("/proc/version", &bytes_read, 1); if(buf) { /* I am assuming the distribution name is the first string in /proc/version that: - is preceded by a '(' - starts with a capital - is followed by a space and a number but i am not sure if this is always true... */ for(i=1; i= 'A' && buf[i] <= 'Z') break; } if(i < bytes_read) { snprintf(p, p_max_size, "%s", &buf[i]); for(i=1; p[i]; i++) { if(p[i-1] == ' ' && p[i] >= '0' && p[i] <= '9') { p[i-1] = 0; break; } } } free(buf); } } /****************************************** * 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, BUFFER_LEN - 1); 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 cmdline[BUFFER_LEN] = { 0 }, cmdline_filename[BUFFER_LEN], cmdline_procname[BUFFER_LEN]; char basename[BUFFER_LEN] = { 0 }; char tmpstr[BUFFER_LEN] = { 0 }; char state[4]; int ps, cmdline_ps; unsigned long user_time = 0; unsigned long kernel_time = 0; int rc; char *r, *q; int endl; int nice_val; char *lparen, *rparen; struct stat process_stat; snprintf(filename, sizeof(filename), PROCFS_TEMPLATE, process->pid); snprintf(cmdline_filename, sizeof(cmdline_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; } if (fstat(ps, &process_stat) != 0) return; process->uid=process_stat.st_uid; /* Mark process as up-to-date. */ process->time_stamp = g_time; rc = read(ps, line, BUFFER_LEN - 1); close(ps); if (rc < 0) { return; } /* Read /proc//cmdline */ cmdline_ps = open(cmdline_filename, O_RDONLY); if (cmdline_ps < 0) { /* The process must have finished in the last few jiffies! */ return; } endl = read(cmdline_ps, cmdline, BUFFER_LEN - 1); close(cmdline_ps); if (endl < 0) { return; } /* Some processes have null-separated arguments (see proc(5)); let's fix it */ int i = endl; while (i && cmdline[i-1] == 0) { /* Skip past any trailing null characters */ --i; } while (i--) { /* Replace null character between arguments with a space */ if (cmdline[i] == 0) { cmdline[i] = ' '; } } cmdline[endl] = 0; /* We want to transform for example "/usr/bin/python program.py" to "python program.py" * 1. search for first space * 2. search for last / before first space * 3. copy string from its position */ char *space_ptr = strchr(cmdline, ' '); if (space_ptr == NULL) { strcpy(tmpstr, cmdline); } else { long int space_pos = space_ptr - cmdline; strncpy(tmpstr, cmdline, space_pos); tmpstr[space_pos] = 0; } char *slash_ptr = strrchr(tmpstr, '/'); if (slash_ptr == NULL) { strncpy(cmdline_procname, cmdline, BUFFER_LEN); } else { long int slash_pos = slash_ptr - tmpstr; strncpy(cmdline_procname, cmdline + slash_pos + 1, BUFFER_LEN - slash_pos); cmdline_procname[BUFFER_LEN - slash_pos] = 0; } /* 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'; strncpy(basename, procname, strlen(procname) + 1); if (strlen(procname) < strlen(cmdline_procname)) strncpy(procname, cmdline_procname, strlen(cmdline_procname) + 1); rc = sscanf(rparen + 1, "%3s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu " "%lu %*s %*s %*s %d %*s %*s %*s %llu %llu", 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; free_and_zero(process->name); free_and_zero(process->basename); process->name = strndup(procname, text_buffer_size.get(*::state)); process->basename = strndup(basename, text_buffer_size.get(*::state)); 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, BUFFER_LEN - 1); 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) { /* compute each process cpu usage */ calculate_stats(get_process(pid)); } } 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 */ } conky-1.10.1/src/linux.h000066400000000000000000000040551262311664100150220ustar00rootroot00000000000000/* -*- 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-2012 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 _LINUX_H #define _LINUX_H #include "common.h" 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); 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); void print_gateway_ip(struct text_object *, char *, int); enum { PB_BATT_STATUS, PB_BATT_PERCENT, PB_BATT_TIME }; void get_powerbook_batt_info(struct text_object *, char *, int); void parse_i2c_sensor(struct text_object *, const char *); void parse_hwmon_sensor(struct text_object *, const char *); void parse_platform_sensor(struct text_object *, const char *); void print_sysfs_sensor(struct text_object *, char *, int ); void free_sysfs_sensor(struct text_object *); int get_entropy_avail(unsigned int *); int get_entropy_poolsize(unsigned int *); int update_stat(void); void print_distribution(struct text_object *, char *, int); void determine_longstat_file(void); #endif /* _LINUX_H */ conky-1.10.1/src/llua.cc000066400000000000000000000354641262311664100147660ustar00rootroot00000000000000/* -*- 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 * * Copyright (c) 2009 Toni Spets * Copyright (c) 2005-2012 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 "llua.h" #include "logging.h" #include "build.h" #ifdef BUILD_LUA_EXTRAS extern "C" { #include } #endif /* BUILD_LUA_EXTRAS */ #ifdef HAVE_SYS_INOTIFY_H #include void llua_append_notify(const char *name); void llua_rm_notifies(void); static int llua_block_notify = 0; #endif /* HAVE_SYS_INOTIFY_H */ static void llua_load(const char *script); lua_State *lua_L = NULL; namespace { class lua_load_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: void lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init) { std::string files = do_convert(l, -1).first; while(not files.empty()) { std::string::size_type pos = files.find(' '); if(pos > 0) { std::string file(files, 0, pos); llua_load(file.c_str()); } files.erase(0, pos==std::string::npos ? pos : pos+1); } } ++s; } void cleanup(lua::state &l) { lua::stack_sentry s(l, -1); #ifdef HAVE_SYS_INOTIFY_H llua_rm_notifies(); #endif /* HAVE_SYS_INOTIFY_H */ if(!lua_L) return; lua_close(lua_L); lua_L = NULL; } public: lua_load_setting() : Base("lua_load", std::string(), false) {} }; lua_load_setting lua_load; conky::simple_config_setting lua_startup_hook("lua_startup_hook", std::string(), true); conky::simple_config_setting lua_shutdown_hook("lua_shutdown_hook", std::string(), true); #ifdef BUILD_X11 conky::simple_config_setting lua_draw_hook_pre("lua_draw_hook_pre", std::string(), true); conky::simple_config_setting lua_draw_hook_post("lua_draw_hook_post", std::string(), true); #endif } static int llua_conky_parse(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ char *str; char *buf = (char*)calloc(1, max_user_text.get(*state)); if (n != 1) { lua_pushstring(L, "incorrect arguments, conky_parse(string) takes exactly 1 argument"); lua_error(L); } if (!lua_isstring(L, 1)) { lua_pushstring(L, "incorrect argument (expecting a string)"); lua_error(L); } str = strdup(lua_tostring(L, 1)); evaluate(str, buf, max_user_text.get(*state)); lua_pushstring(L, buf); free(str); free(buf); return 1; /* number of results */ } static int llua_conky_set_update_interval(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ if (n != 1) { lua_pushstring(L, "incorrect arguments, conky_set_update_interval(number) takes exactly 1 argument"); lua_error(L); } if (!lua_isnumber(L, 1)) { lua_pushstring(L, "incorrect argument (expecting a number)"); lua_error(L); } state->pushnumber(lua_tonumber(L, 1)); update_interval.lua_set(*state); return 0; /* number of results */ } void llua_init(void) { const char *libs = PACKAGE_LIBDIR"/lib?.so;"; char *old_path, *new_path; if (lua_L) return; lua_L = luaL_newstate(); /* add our library path to the lua package.cpath global var */ luaL_openlibs(lua_L); lua_getglobal(lua_L, "package"); lua_getfield(lua_L, -1, "cpath"); old_path = strdup(lua_tostring(lua_L, -1)); new_path = (char*)malloc(strlen(old_path) + strlen(libs) + 1); strcpy(new_path, libs); strcat(new_path, old_path); lua_pushstring(lua_L, new_path); lua_setfield(lua_L, -3, "cpath"); lua_pop(lua_L, 2); free(old_path); free(new_path); lua_pushstring(lua_L, PACKAGE_NAME" " VERSION" compiled " BUILD_DATE" for " BUILD_ARCH); lua_setglobal(lua_L, "conky_build_info"); lua_pushstring(lua_L, VERSION); lua_setglobal(lua_L, "conky_version"); lua_pushstring(lua_L, BUILD_DATE); lua_setglobal(lua_L, "conky_build_date"); lua_pushstring(lua_L, BUILD_ARCH); lua_setglobal(lua_L, "conky_build_arch"); lua_pushstring(lua_L, current_config.c_str()); lua_setglobal(lua_L, "conky_config"); lua_pushcfunction(lua_L, &llua_conky_parse); lua_setglobal(lua_L, "conky_parse"); lua_pushcfunction(lua_L, &llua_conky_set_update_interval); lua_setglobal(lua_L, "conky_set_update_interval"); #if defined(BUILD_X11) && defined(BUILD_LUA_EXTRAS) /* register tolua++ user types */ tolua_open(lua_L); tolua_usertype(lua_L, "Drawable"); tolua_usertype(lua_L, "Visual"); tolua_usertype(lua_L, "Display"); #endif /* BUILD_X11 */ } void llua_load(const char *script) { int error; llua_init(); std::string path = to_real_path(script); error = luaL_dofile(lua_L, path.c_str()); if (error) { NORM_ERR("llua_load: %s", lua_tostring(lua_L, -1)); lua_pop(lua_L, 1); #ifdef HAVE_SYS_INOTIFY_H } else if (!llua_block_notify && inotify_fd != -1) { llua_append_notify(path.c_str()); #endif /* HAVE_SYS_INOTIFY_H */ } } /* * 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...] retc: the number of return values expected */ static char *llua_do_call(const char *string, int retc) { static char func[64]; int argc = 0; size_t len = 0; const char *ptr = tokenize(string, &len); /* proceed only if the function name is present */ if (!len) { return NULL; } /* call only conky_ prefixed functions */ if(strncmp(ptr, LUAPREFIX, strlen(LUAPREFIX)) != 0) { snprintf(func, sizeof func, "%s", LUAPREFIX); } else *func = 0; strncat(func, ptr, std::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 */ while( ptr = tokenize(ptr, &len), len) { lua_pushlstring(lua_L, ptr, len); argc++; } 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); return NULL; } return func; } #if 0 /* * same as llua_do_call() except passes everything after func as one arg. */ static char *llua_do_read_call(const char *function, const char *arg, int retc) { static char func[64]; snprintf(func, 64, "conky_%s", function); /* push the function name to stack */ lua_getglobal(lua_L, func); /* push function parameter to the stack */ lua_pushstring(lua_L, arg); if (lua_pcall(lua_L, 1, retc, 0) != 0) { NORM_ERR("llua_do_call: function %s execution failed: %s", func, lua_tostring(lua_L, -1)); lua_pop(lua_L, -1); return NULL; } return func; } #endif /* call a function with args, and return a string from it (must be free'd) */ static char *llua_getstring(const char *args) { char *func; char *ret = NULL; if(!lua_L) return NULL; func = llua_do_call(args, 1); if (func) { if (!lua_isstring(lua_L, -1)) { NORM_ERR("llua_getstring: function %s didn't return a string, result discarded", func); } else { ret = strdup(lua_tostring(lua_L, -1)); lua_pop(lua_L, 1); } } return ret; } #if 0 /* call a function with args, and return a string from it (must be free'd) */ static char *llua_getstring_read(const char *function, const char *arg) { char *func; char *ret = NULL; if(!lua_L) return NULL; func = llua_do_read_call(function, arg, 1); if (func) { if(!lua_isstring(lua_L, -1)) { NORM_ERR("llua_getstring_read: function %s didn't return a string, result discarded", func); } else { ret = strdup(lua_tostring(lua_L, -1)); lua_pop(lua_L, 1); } } return ret; } #endif /* call a function with args, and put the result in ret */ static int llua_getnumber(const char *args, double *ret) { char *func; if(!lua_L) return 0; func = llua_do_call(args, 1); if(func) { if(!lua_isnumber(lua_L, -1)) { NORM_ERR("llua_getnumber: function %s didn't return a number, result discarded", func); } else { *ret = lua_tonumber(lua_L, -1); lua_pop(lua_L, 1); return 1; } } return 0; } #ifdef HAVE_SYS_INOTIFY_H struct _lua_notify_s { int wd; char name[DEFAULT_TEXT_BUFFER_SIZE]; struct _lua_notify_s *next; }; static struct _lua_notify_s *lua_notifies = 0; static struct _lua_notify_s *llua_notify_list_do_alloc(const char *name) { struct _lua_notify_s *ret = (struct _lua_notify_s *)malloc(sizeof(struct _lua_notify_s)); memset(ret, 0, sizeof(struct _lua_notify_s)); strncpy(ret->name, name, DEFAULT_TEXT_BUFFER_SIZE); return ret; } void llua_append_notify(const char *name) { /* do it */ struct _lua_notify_s *new_tail = 0; if (!lua_notifies) { /* empty, fresh new digs */ new_tail = lua_notifies = llua_notify_list_do_alloc(name); } else { struct _lua_notify_s *tail = lua_notifies; while (tail->next) { tail = tail->next; } // should be @ the end now new_tail = llua_notify_list_do_alloc(name); tail->next = new_tail; } new_tail->wd = inotify_add_watch(inotify_fd, new_tail->name, IN_MODIFY); } void llua_rm_notifies(void) { /* git 'er done */ struct _lua_notify_s *head = lua_notifies; struct _lua_notify_s *next = 0; if (!lua_notifies) return; inotify_rm_watch(inotify_fd, head->wd); if (head->next) next = head->next; free(head); while (next) { head = next; next = head->next; inotify_rm_watch(inotify_fd, head->wd); free(head); } lua_notifies = 0; } void llua_inotify_query(int wd, int mask) { struct _lua_notify_s *head = lua_notifies; if (mask & IN_MODIFY || mask & IN_IGNORED) { /* for whatever reason, i keep getting IN_IGNORED when the file is * modified */ while (head) { if (head->wd == wd) { llua_block_notify = 1; llua_load(head->name); llua_block_notify = 0; NORM_ERR("Lua script '%s' reloaded", head->name); if (mask & IN_IGNORED) { /* for some reason we get IN_IGNORED here * sometimes, so we need to re-add the watch */ head->wd = inotify_add_watch(inotify_fd, head->name, IN_MODIFY); } return; } head = head->next; } } } #endif /* HAVE_SYS_INOTIFY_H */ void llua_set_number(const char *key, double value) { lua_pushnumber(lua_L, value); lua_setfield(lua_L, -2, key); } void llua_startup_hook(void) { if (!lua_L || lua_startup_hook.get(*state).empty()) return; llua_do_call(lua_startup_hook.get(*state).c_str(), 0); } void llua_shutdown_hook(void) { if (!lua_L || lua_shutdown_hook.get(*state).empty()) return; llua_do_call(lua_shutdown_hook.get(*state).c_str(), 0); } #ifdef BUILD_X11 void llua_draw_pre_hook(void) { if (!lua_L || lua_draw_hook_pre.get(*state).empty()) return; llua_do_call(lua_draw_hook_pre.get(*state).c_str(), 0); } void llua_draw_post_hook(void) { if (!lua_L || lua_draw_hook_post.get(*state).empty()) return; llua_do_call(lua_draw_hook_post.get(*state).c_str(), 0); } #ifdef BUILD_LUA_EXTRAS void llua_set_userdata(const char *key, const char *type, void *value) { tolua_pushusertype(lua_L, value, type); lua_setfield(lua_L, -2, key); } #endif /* BUILD_LUA_EXTRAS */ void llua_setup_window_table(int text_start_x, int text_start_y, int text_width, int text_height) { if (!lua_L) return; lua_newtable(lua_L); if (out_to_x.get(*state)) { #ifdef BUILD_LUA_EXTRAS llua_set_userdata("drawable", "Drawable", (void*)&window.drawable); llua_set_userdata("visual", "Visual", window.visual); llua_set_userdata("display", "Display", display); #endif /* BUILD_LUA_EXTRAS */ llua_set_number("width", window.width); llua_set_number("height", window.height); llua_set_number("border_inner_margin", border_inner_margin.get(*state)); llua_set_number("border_outer_margin", border_outer_margin.get(*state)); llua_set_number("border_width", border_width.get(*state)); llua_set_number("text_start_x", text_start_x); llua_set_number("text_start_y", text_start_y); llua_set_number("text_width", text_width); llua_set_number("text_height", text_height); lua_setglobal(lua_L, "conky_window"); } } void llua_update_window_table(int text_start_x, int text_start_y, int text_width, int text_height) { if (!lua_L) return; lua_getglobal(lua_L, "conky_window"); if (lua_isnil(lua_L, -1)) { /* window table isn't populated yet */ lua_pop(lua_L, 1); return; } llua_set_number("width", window.width); llua_set_number("height", window.height); llua_set_number("text_start_x", text_start_x); llua_set_number("text_start_y", text_start_y); llua_set_number("text_width", text_width); llua_set_number("text_height", text_height); lua_setglobal(lua_L, "conky_window"); } #endif /* BUILD_X11 */ void llua_setup_info(struct information *i, double u_interval) { if (!lua_L) return; lua_newtable(lua_L); llua_set_number("update_interval", u_interval); llua_set_number("uptime", i->uptime); lua_setglobal(lua_L, "conky_info"); } void llua_update_info(struct information *i, double u_interval) { if (!lua_L) return; lua_getglobal(lua_L, "conky_info"); if (lua_isnil(lua_L, -1)) { /* window table isn't populated yet */ lua_pop(lua_L, 1); return; } llua_set_number("update_interval", u_interval); llua_set_number("uptime", i->uptime); lua_setglobal(lua_L, "conky_info"); } void print_lua(struct text_object *obj, char *p, int p_max_size) { char *str = llua_getstring(obj->data.s); if (str) { snprintf(p, p_max_size, "%s", str); free(str); } } void print_lua_parse(struct text_object *obj, char *p, int p_max_size) { char *str = llua_getstring(obj->data.s); if (str) { evaluate(str, p, p_max_size); free(str); } } double lua_barval(struct text_object *obj) { double per; if (llua_getnumber(obj->data.s, &per)) { return per; } return 0; } conky-1.10.1/src/llua.h000066400000000000000000000036741262311664100146260ustar00rootroot00000000000000/* -*- 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 * * Copyright (c) 2009 Toni Spets * Copyright (c) 2005-2012 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 LUA_H_ #define LUA_H_ extern "C" { #include #include #include } #include #ifdef BUILD_X11 #include "x11.h" #endif /* BUILD_X11 */ #define LUAPREFIX "conky_" #ifdef HAVE_SYS_INOTIFY_H /* check our lua inotify status */ void llua_inotify_query(int wd, int mask); #endif /* HAVE_SYS_INOTIFY_H */ void llua_startup_hook(void); void llua_shutdown_hook(void); #ifdef BUILD_X11 void llua_draw_pre_hook(void); void llua_draw_post_hook(void); void llua_setup_window_table(int text_start_x, int text_start_y, int text_width, int text_height); void llua_update_window_table(int text_start_x, int text_start_y, int text_width, int text_height); #endif /* BUILD_X11 */ void llua_setup_info(struct information *i, double u_interval); void llua_update_info(struct information *i, double u_interval); void print_lua(struct text_object *, char *, int); void print_lua_parse(struct text_object *, char *, int); double lua_barval(struct text_object *); #endif /* LUA_H_*/ conky-1.10.1/src/logging.h000066400000000000000000000067251262311664100153170ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _LOGGING_H #define _LOGGING_H #include #include #include "i18n.h" class fork_throw : public std::runtime_error { public: fork_throw() : std::runtime_error("Fork happened") {} fork_throw(const std::string &msg) : std::runtime_error(msg) {} }; class unknown_arg_throw : public std::runtime_error { public: unknown_arg_throw() : std::runtime_error("Unknown argumunt given") {} unknown_arg_throw(const std::string &msg) : std::runtime_error(msg) {} }; class combine_needs_2_args_error : public std::runtime_error { public: combine_needs_2_args_error() : std::runtime_error("combine needs arguments: ") {} combine_needs_2_args_error(const std::string &msg) : std::runtime_error(msg) {} }; class obj_create_error : public std::runtime_error { public: obj_create_error() : std::runtime_error("Failed to create object") {} obj_create_error(const std::string &msg) : std::runtime_error(msg) {} }; void clean_up(void *memtofree1, void* memtofree2); void clean_up_without_threads(void *memtofree1, void* memtofree2); template void gettextize_format(const char *format, Args&&... args) { fprintf(stderr, _(format), args...); } // explicit specialization for no arguments to avoid the // "format not a string literal and no format arguments" warning inline void gettextize_format(const char *format) { fputs(_(format), stderr); } #define NORM_ERR(...) do { \ fprintf(stderr, PACKAGE_NAME": "); \ gettextize_format(__VA_ARGS__); \ fputs("\n", stderr); \ } while(0) /* critical error */ #define CRIT_ERR(memtofree1, memtofree2, ...) \ { NORM_ERR(__VA_ARGS__); clean_up(memtofree1, memtofree2); exit(EXIT_FAILURE); } #define THREAD_CRIT_ERR(memtofree1, memtofree2, ...) \ { NORM_ERR(__VA_ARGS__); clean_up_without_threads(memtofree1, memtofree2); return; } namespace conky { class error : public std::runtime_error { public: error(const std::string &msg) : std::runtime_error(msg) {} }; } /* debugging output */ extern int global_debug_level; #define __DBGP(level, ...) do {\ if (global_debug_level > level) { \ fprintf(stderr, "DEBUG(%d) [" __FILE__ ":%d]: ", level, __LINE__); \ gettextize_format(__VA_ARGS__); \ fputs("\n", stderr); \ } \ } while(0) #define DBGP(...) __DBGP(0, __VA_ARGS__) #define DBGP2(...) __DBGP(1, __VA_ARGS__) #endif /* _LOGGING_H */ conky-1.10.1/src/lua-config.cc000066400000000000000000000023141262311664100160410ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 "lua-config.hh" #include "data-source.hh" #include "setting.hh" namespace conky { void export_symbols(lua::state &l) { lua::stack_sentry s(l); l.checkstack(3); l.newtable(); { export_data_sources(l); l.newtable(); l.rawsetfield(-2, "config"); } l.setglobal("conky"); } } conky-1.10.1/src/lua-config.hh000066400000000000000000000020361262311664100160540ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 LUA_CONFIG_HH #define LUA_CONFIG_HH #include "luamm.hh" namespace conky { void export_symbols(lua::state &l); } #endif /* LUA_CONFIG_HH */ conky-1.10.1/src/luamm.cc000066400000000000000000000307321262311664100151350ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * luamm: C++ binding for lua * * Copyright (C) 2010 Pavel Labath et al. * * 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 "luamm.hh" namespace lua { namespace { #if LUA_VERSION_NUM >= 502 // These two functions were deprecated in 5.2. Limited backwards compatibility is // provided by macros. We want them as real functions, because we take their addresses. #undef lua_equal int lua_equal(lua_State *L, int index1, int index2) { return lua_compare(L, index1, index2, LUA_OPEQ); } #undef lua_lessthan int lua_lessthan(lua_State *L, int index1, int index2) { return lua_compare(L, index1, index2, LUA_OPLT); } #endif // keys for storing values in lua registry const char cpp_exception_metatable[] = "lua::cpp_exception_metatable"; const char cpp_function_metatable [] = "lua::cpp_function_metatable"; const char lua_exception_namespace[] = "lua::lua_exception_namespace"; const char this_cpp_object [] = "lua::this_cpp_object"; // converts C++ exceptions to strings, so lua can do something with them int exception_to_string(lua_State *l) { std::exception_ptr *ptr = static_cast(lua_touserdata(l, -1)); assert(ptr); try { std::rethrow_exception(*ptr); } catch(std::exception &e) { lua_pushstring(l, e.what()); } catch(...) { lua_pushstring(l, ptr->__cxa_exception_type()->name()); } return 1; } int absindex(lua_State *l, int index) throw() { return index<0 && -index<=lua_gettop(l) ? lua_gettop(l)+1+index : index; } // Just like getfield(), only without calling metamethods (or throwing random exceptions) inline void rawgetfield(lua_State *l, int index, const char *k) throw(std::bad_alloc) { index = absindex(l, index); if(not lua_checkstack(l, 1)) throw std::bad_alloc(); lua_pushstring(l, k); lua_rawget(l, index); } // Just like setfield(), only without calling metamethods (or throwing random exceptions) inline void rawsetfield(lua_State *l, int index, const char *k) throw(std::bad_alloc) { index = absindex(l, index); if(not lua_checkstack(l, 2)) throw std::bad_alloc(); lua_pushstring(l, k); lua_insert(l, -2); lua_rawset(l, index); } int closure_trampoline(lua_State *l) { lua_checkstack(l, 2); rawgetfield(l, REGISTRYINDEX, this_cpp_object); assert(lua_islightuserdata(l, -1)); state *L = static_cast( lua_touserdata(l, -1) ); lua_pop(l, 1); try { cpp_function *fn = static_cast( L->touserdata(lua_upvalueindex(1)) ); assert(fn); return (*fn)(L); } catch(lua::exception &e) { // rethrow lua errors as such e.push_lua_error(L); } catch(...) { // C++ exceptions (pointers to them, actually) are stored as lua userdata and // then thrown L->createuserdata(std::current_exception()); L->rawgetfield(REGISTRYINDEX, cpp_exception_metatable); L->setmetatable(-2); } // lua_error does longjmp(), so destructors for objects in this function will not be // called return lua_error(l); } /* * This function is called when lua encounters an error outside of any protected * environment * Throwing the exception through lua code appears to work, even if it was compiled * without -fexceptions. If it turns out, it fails in some conditions, it could be * replaced with some longjmp() magic. But that shouldn't be necessary, as this function * will not be called under normal conditions (we execute everything in protected mode). */ int panic_throw(lua_State *l) { if(not lua_checkstack(l, 1)) throw std::bad_alloc(); rawgetfield(l, REGISTRYINDEX, this_cpp_object); assert(lua_islightuserdata(l, -1)); state *L = static_cast( lua_touserdata(l, -1) ); lua_pop(l, 1); throw lua::exception(L); } // protected mode wrappers for various lua functions int safe_concat_trampoline(lua_State *l) { lua_concat(l, lua_gettop(l)); return 1; } template int safe_compare_trampoline(lua_State *l) { int r = compare(l, 1, 2); lua_pop(l, 2); lua_pushinteger(l, r); return 1; } int safe_gc_trampoline(lua_State *l) { int what = lua_tointeger(l, -2); int data = lua_tointeger(l, -1); lua_pop(l, 2); lua_pushinteger(l, lua_gc(l, what, data)); return 1; } template int safe_misc_trampoline(lua_State *l) { misc(l, 1); return nresults; } // Overloaded for Lua 5.3+ as lua_gettable and others return an int template int safe_misc_trampoline(lua_State *l) { misc(l, 1); return nresults; } int safe_next_trampoline(lua_State *l) { int r = lua_next(l, 1); lua_checkstack(l, 1); lua_pushinteger(l, r); return r ? 3 : 1; } } std::string exception::get_error_msg(state *L) { static const std::string default_msg("Unknown lua exception"); try { return L->tostring(-1); } catch(not_string_error &e) { return default_msg; } } exception::exception(state *l) : std::runtime_error(get_error_msg(l)), L(l) { L->checkstack(1); L->rawgetfield(REGISTRYINDEX, lua_exception_namespace); L->insert(-2); key = L->ref(-2); L->pop(1); } exception::~exception() throw() { if(not L) return; L->checkstack(1); L->rawgetfield(REGISTRYINDEX, lua_exception_namespace); L->unref(-1, key); L->pop(); } void exception::push_lua_error(state *l) { if(l != L) throw std::runtime_error("Cannot transfer exceptions between different lua contexts"); l->checkstack(2); l->rawgetfield(REGISTRYINDEX, lua_exception_namespace); l->rawgeti(-1, key); l->replace(-2); } state::state() { if(lua_State *l = luaL_newstate()) cobj.reset(l, &lua_close); else { // docs say this can happen only in case of a memory allocation error throw std::bad_alloc(); } // set our panic function lua_atpanic(cobj.get(), panic_throw); checkstack(2); // store a pointer to ourselves pushlightuserdata(this); rawsetfield(REGISTRYINDEX, this_cpp_object); // a metatable for C++ exceptions travelling through lua code newmetatable(cpp_exception_metatable); lua_pushcfunction(cobj.get(), &exception_to_string); rawsetfield(-2, "__tostring"); pushboolean(false); rawsetfield(-2, "__metatable"); pushdestructor(); rawsetfield(-2, "__gc"); pop(); // a metatable for C++ functions callable from lua code newmetatable(cpp_function_metatable); pushboolean(false); rawsetfield(-2, "__metatable"); pushdestructor(); rawsetfield(-2, "__gc"); pop(); // while they're travelling through C++ code, lua exceptions will reside here newtable(); rawsetfield(REGISTRYINDEX, lua_exception_namespace); luaL_openlibs(cobj.get()); } void state::call(int nargs, int nresults, int errfunc) { int r = lua_pcall(cobj.get(), nargs, nresults, errfunc); if(r == 0) return; if(r == LUA_ERRMEM) { // memory allocation error, cross your fingers throw std::bad_alloc(); } checkstack(3); rawgetfield(REGISTRYINDEX, cpp_exception_metatable); if(getmetatable(-2)) { if(rawequal(-1, -2)) { // it's a C++ exception, rethrow it std::exception_ptr *ptr = static_cast(touserdata(-3)); assert(ptr); /* * we create a copy, so we can pop the object without fearing the exception will * be collected by lua's GC */ std::exception_ptr t(*ptr); ptr = NULL; pop(3); std::rethrow_exception(t); } pop(2); } // it's a lua exception, wrap it if(r == LUA_ERRERR) throw lua::errfunc_error(this); else throw lua::exception(this); } void state::checkstack(int extra) throw(std::bad_alloc) { if(not lua_checkstack(cobj.get(), extra)) throw std::bad_alloc(); } void state::concat(int n) { assert(n>=0); checkstack(1); lua_pushcfunction(cobj.get(), safe_concat_trampoline); insert(-n-1); call(n, 1, 0); } bool state::equal(int index1, int index2) { // avoid pcall overhead in trivial cases if( rawequal(index1, index2) ) return true; return safe_compare(&safe_compare_trampoline, index1, index2); } int state::gc(int what, int data) { checkstack(3); lua_pushcfunction(cobj.get(), safe_gc_trampoline); pushinteger(what); pushinteger(data); call(2, 1, 0); assert(isnumber(-1)); int r = tointeger(-1); pop(); return r; } void state::getfield(int index, const char *k) { checkstack(1); index = absindex(index); pushstring(k); gettable(index); } void state::getglobal(const char *name) { #if LUA_VERSION_NUM >= 502 checkstack(1); pushinteger(LUA_RIDX_GLOBALS); gettable(REGISTRYINDEX); getfield(-1, name); replace(-2); #else getfield(LUA_GLOBALSINDEX, name); #endif } void state::gettable(int index) { checkstack(2); pushvalue(index); insert(-2); lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_gettable, 1>)); insert(-3); call(2, 1, 0); } bool state::lessthan(int index1, int index2) { return safe_compare(&safe_compare_trampoline<&lua_lessthan>, index1, index2); } void state::loadfile(const char *filename) throw(lua::syntax_error, lua::file_error, std::bad_alloc) { switch(luaL_loadfile(cobj.get(), filename)) { case 0: return; case LUA_ERRSYNTAX: throw lua::syntax_error(this); case LUA_ERRFILE: throw lua::file_error(this); case LUA_ERRMEM: throw std::bad_alloc(); default: assert(0); } } void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc) { switch(luaL_loadstring(cobj.get(), s)) { case 0: return; case LUA_ERRSYNTAX: throw lua::syntax_error(this); case LUA_ERRMEM: throw std::bad_alloc(); default: assert(0); } } bool state::next(int index) { checkstack(2); pushvalue(index); insert(-2); lua_pushcfunction(cobj.get(), &safe_next_trampoline); insert(-3); call(2, MULTRET, 0); assert(isnumber(-1)); int r = tointeger(-1); pop(); return r; } void state::pushclosure(const cpp_function &fn, int n) { checkstack(2); createuserdata(fn); rawgetfield(REGISTRYINDEX, cpp_function_metatable); setmetatable(-2); insert(-n-1); lua_pushcclosure(cobj.get(), &closure_trampoline, n+1); } void state::rawgetfield(int index, const char *k) throw(std::bad_alloc) { lua::rawgetfield(cobj.get(), index, k); } void state::rawsetfield(int index, const char *k) throw(std::bad_alloc) { lua::rawsetfield(cobj.get(), index, k); } bool state::safe_compare(lua_CFunction trampoline, int index1, int index2) { // if one of the indexes is invalid, return false if(isnone(index1) || isnone(index2)) return false; // convert relative indexes into absolute index1 = absindex(index1); index2 = absindex(index2); checkstack(3); lua_pushcfunction(cobj.get(), trampoline); pushvalue(index1); pushvalue(index2); call(2, 1, 0); assert(isnumber(-1)); int r = tointeger(-1); pop(); return r; } void state::setfield(int index, const char *k) { checkstack(1); index = absindex(index); pushstring(k); insert(-2); settable(index); } void state::setglobal(const char *name) { #if LUA_VERSION_NUM >= 502 stack_sentry s(*this, -1); checkstack(1); pushinteger(LUA_RIDX_GLOBALS); gettable(REGISTRYINDEX); insert(-2); setfield(-2, name); pop(); #else setfield(LUA_GLOBALSINDEX, name); #endif } void state::settable(int index) { checkstack(2); pushvalue(index); insert(-3); lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_settable, 0>)); insert(-4); call(3, 0, 0); } std::string state::tostring(int index) throw(lua::not_string_error) { size_t len; const char *str = lua_tolstring(cobj.get(), index, &len); if(not str) throw not_string_error(); return std::string(str, len); } } conky-1.10.1/src/luamm.hh000066400000000000000000000321201262311664100151400ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * luamm: C++ binding for lua * * Copyright (C) 2010 Pavel Labath et al. * * 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 LUAMM_HH #define LUAMM_HH #include #include #include #include #include namespace lua { class state; typedef lua_Integer integer; typedef lua_Number number; typedef std::function cpp_function; enum { REGISTRYINDEX = LUA_REGISTRYINDEX }; enum { GCSTOP = LUA_GCSTOP, GCRESTART = LUA_GCRESTART, GCCOLLECT = LUA_GCCOLLECT, GCCOUNT = LUA_GCCOUNT, GCCOUNTB = LUA_GCCOUNTB, GCSTEP = LUA_GCSTEP, GCSETPAUSE = LUA_GCSETPAUSE, GCSETSTEPMUL = LUA_GCSETSTEPMUL }; enum { MULTRET = LUA_MULTRET }; enum Type { TBOOLEAN = LUA_TBOOLEAN, TFUNCTION = LUA_TFUNCTION, TLIGHTUSERDATA = LUA_TLIGHTUSERDATA, TNIL = LUA_TNIL, TNONE = LUA_TNONE, TNUMBER = LUA_TNUMBER, TSTRING = LUA_TSTRING, TTABLE = LUA_TTABLE, TTHREAD = LUA_TTHREAD, TUSERDATA = LUA_TUSERDATA }; // we reserve one upvalue for the function pointer inline int upvalueindex(int n) { return lua_upvalueindex(n+1); } /* * Lua error()s are wrapped in this class when rethrown into C++ code. what() returns the * error message. push_lua_error() pushes the error onto lua stack. The error can only be * pushed into the same state it was generated in. */ class exception: public std::runtime_error { /* * We only allow moving, to avoid complications with multiple references. It shouldn't be * difficult to modify this to work with copying, if that proves unavoidable. */ state *L; int key; static std::string get_error_msg(state *L); exception(const exception &) = delete; const exception& operator=(const exception &) = delete; public: exception(exception &&other) : std::runtime_error(std::move(other)), L(other.L), key(other.key) { other.L = NULL; } explicit exception(state *l); virtual ~exception() throw(); void push_lua_error(state *l); }; class not_string_error: public std::runtime_error { public: not_string_error() : std::runtime_error("Cannot convert value to a string") {} }; // the name says it all class syntax_error: public lua::exception { syntax_error(const syntax_error &) = delete; const syntax_error& operator=(const syntax_error &) = delete; public: syntax_error(state *L) : lua::exception(L) {} syntax_error(syntax_error &&other) : lua::exception(std::move(other)) {} }; // loadfile() encountered an error while opening/reading the file class file_error: public lua::exception { file_error(const file_error &) = delete; const file_error& operator=(const file_error &) = delete; public: file_error(state *L) : lua::exception(L) {} file_error(file_error &&other) : lua::exception(std::move(other)) {} }; // double fault, lua encountered an error while running the error handler function class errfunc_error: public lua::exception { errfunc_error(const errfunc_error &) = delete; const errfunc_error& operator=(const errfunc_error &) = delete; public: errfunc_error(state *L) : lua::exception(L) {} errfunc_error(errfunc_error &&other) : lua::exception(std::move(other)) {} }; // a fancy wrapper around lua_State class state: private std::mutex { std::shared_ptr cobj; // destructor for C++ objects stored as lua userdata template static int destroy_cpp_object(lua_State *l) { T *ptr = static_cast(lua_touserdata(l, -1)); assert(ptr); try { // throwing exceptions in destructors is a bad idea // but we catch (and ignore) them, just in case ptr->~T(); } catch(...) { } return 0; } bool safe_compare(lua_CFunction trampoline, int index1, int index2); public: state(); /* * Lua functions come in three flavours * a) functions that never throw an exception * b) functions that throw only in case of a memory allocation error * c) functions that throw other kinds of errors * * Calls to type a functions are simply forwarded to the C api. * Type c functions are executed in protected mode, to make sure they don't longjmp() * over us (and our destructors). This add a certain amount overhead. If you care about * performance, try using the raw versions (if possible). * Type b functions are not executed in protected mode atm. as memory allocation errors * don't happen that often (as opposed to the type c, where the user get deliberately set * a metamethod that throws an error). That means those errors will do something * undefined, but hopefully that won't be a problem. * * Semantics are mostly identical to those of the underlying C api. Any deviation is * noted in the respective functions comment. The most important difference is that * instead of return values, we use exceptions to indicate errors. The lua and C++ * exception mechanisms are integrated. That means one can throw a C++ exception and * catch it in lua (with pcall). Lua error()s can be caught in C++ as exceptions of type * lua::exception. */ // type a, never throw int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; } bool getmetatable(int index) throw() { return lua_getmetatable(cobj.get(), index); } int gettop() throw() { return lua_gettop(cobj.get()); } void insert(int index) throw() { lua_insert(cobj.get(), index); } bool isboolean(int index) throw() { return lua_isboolean(cobj.get(), index); } bool isfunction(int index) throw() { return lua_isfunction(cobj.get(), index); } bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj.get(), index); } bool isnil(int index) throw() { return lua_isnil(cobj.get(), index); } bool isnone(int index) throw() { return lua_isnone(cobj.get(), index); } bool isnumber(int index) throw() { return lua_isnumber(cobj.get(), index); } bool isstring(int index) throw() { return lua_isstring(cobj.get(), index); } void pop(int n = 1) throw() { lua_pop(cobj.get(), n); } void pushboolean(bool b) throw() { lua_pushboolean(cobj.get(), b); } void pushinteger(integer n) throw() { lua_pushinteger(cobj.get(), n); } void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj.get(), p); } void pushnil() throw() { lua_pushnil(cobj.get()); } void pushnumber(number n) throw() { lua_pushnumber(cobj.get(), n); } void pushvalue(int index) throw() { lua_pushvalue(cobj.get(), index); } void rawget(int index) throw() { lua_rawget(cobj.get(), index); } void rawgeti(int index, int n) throw() { lua_rawgeti(cobj.get(), index, n); } bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj.get(), index1, index2); } void replace(int index) throw() { lua_replace(cobj.get(), index); } // lua_setmetatable returns int, but docs don't specify it's meaning :/ int setmetatable(int index) throw() { return lua_setmetatable(cobj.get(), index); } void settop(int index) throw() { return lua_settop(cobj.get(), index); } bool toboolean(int index) throw() { return lua_toboolean(cobj.get(), index); } integer tointeger(int index) throw() { return lua_tointeger(cobj.get(), index); } number tonumber(int index) throw() { return lua_tonumber(cobj.get(), index); } void* touserdata(int index) throw() { return lua_touserdata(cobj.get(), index); } Type type(int index) throw() { return static_cast(lua_type(cobj.get(), index)); } // typename is a reserved word :/ const char* type_name(Type tp) throw() { return lua_typename(cobj.get(), tp); } void unref(int t, int ref) throw() { return luaL_unref(cobj.get(), t, ref); } // type b, throw only on memory allocation errors // checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of // that sitution void checkstack(int extra) throw(std::bad_alloc); const char* gsub(const char *s, const char *p, const char *r) { return luaL_gsub(cobj.get(), s, p, r); } bool newmetatable(const char *tname) { return luaL_newmetatable(cobj.get(), tname); } void newtable() { lua_newtable(cobj.get()); } void *newuserdata(size_t size) { return lua_newuserdata(cobj.get(), size); } // cpp_function can be anything that std::function can handle, everything else remains // identical void pushclosure(const cpp_function &fn, int n); void pushfunction(const cpp_function &fn) { pushclosure(fn, 0); } void pushstring(const char *s) { lua_pushstring(cobj.get(), s); } void pushstring(const char *s, size_t len) { lua_pushlstring(cobj.get(), s, len); } void pushstring(const std::string &s) { lua_pushlstring(cobj.get(), s.c_str(), s.size()); } void rawgetfield(int index, const char *k) throw(std::bad_alloc); void rawset(int index) { lua_rawset(cobj.get(), index); } void rawsetfield(int index, const char *k) throw(std::bad_alloc); int ref(int t) { return luaL_ref(cobj.get(), t); } // len recieves length, if not null. Returned value may contain '\0' const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); } // Don't use pushclosure() to create a __gc function. The problem is that lua calls them // in an unspecified order, and we may end up destroying the object holding the // std::function before we get a chance to call it. This pushes a function that simply // calls ~T when the time comes. Only set it as __gc on userdata of type T. template void pushdestructor() { lua_pushcfunction(cobj.get(), &destroy_cpp_object); } // type c, throw everything but the kitchen sink // call() is a protected mode call, we don't allow unprotected calls void call(int nargs, int nresults, int errfunc = 0); void concat(int n); bool equal(int index1, int index2); int gc(int what, int data); void getfield(int index, const char *k); void getglobal(const char *name); void gettable(int index); bool lessthan(int index1, int index2); void loadfile(const char *filename) throw(lua::syntax_error, lua::file_error, std::bad_alloc); void loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc); bool next(int index); // register is a reserved word :/ void register_fn(const char *name, const cpp_function &f) { pushfunction(f); setglobal(name); } void setfield(int index, const char *k); void setglobal(const char *name); void settable(int index); // lua_tostring uses NULL to indicate conversion error, since there is no such thing as a // NULL std::string, we throw an exception. Returned value may contain '\0' std::string tostring(int index) throw(lua::not_string_error); // allocate a new lua userdata of appropriate size, and create a object in it // pushes the userdata on stack and returns the pointer template T* createuserdata(Args&&... args); using std::mutex::lock; using std::mutex::unlock; using std::mutex::try_lock; }; /* * Can be used to automatically pop temporary values off the lua stack on exit from the * function/block (e.g. via an exception). It's destructor makes sure the stack contains * exactly n items. The constructor initializes n to l.gettop()+n_, but that can be later * changed with the overloaded operators. It is an error if stack contains less than n * elements at entry into the destructor. * * Proposed stack discipline for functions is this: * - called function always pops parameters off the stack. * - if functions returns normally, it's return values are on the stack. * - if function throws an exception, there are no return values on the stack. * The last point differs from lua C api, which return an error message on the stack. But * since we have exception.what() for that, putting the message on the stack is not * necessary. */ class stack_sentry { state *L; int n; stack_sentry(const stack_sentry &) = delete; const stack_sentry& operator=(const stack_sentry &) = delete; public: explicit stack_sentry(state &l, int n_ = 0) throw() : L(&l), n(l.gettop()+n_) { assert(n >= 0); } ~stack_sentry() throw() { assert(L->gettop() >= n); L->settop(n); } void operator++() throw() { ++n; } void operator--() throw() { --n; assert(n >= 0); } void operator+=(int n_) throw() { n+=n_; } void operator-=(int n_) throw() { n-=n_; assert(n >= 0); } }; template T* state::createuserdata(Args&&... args) { stack_sentry s(*this); void *t = newuserdata(sizeof(T)); new(t) T(std::forward(args)...); ++s; return static_cast(t); } } #endif /* LUAMM_HH */ conky-1.10.1/src/mail.cc000066400000000000000000000616341262311664100147510ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "mail.h" #include "conky.h" #include "common.h" #include "logging.h" #include "text_object.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "update-cb.hh" struct local_mail_s { char *mbox; int mail_count; int new_mail_count; int seen_mail_count; int unseen_mail_count; int flagged_mail_count; int unflagged_mail_count; int forwarded_mail_count; int unforwarded_mail_count; int replied_mail_count; int unreplied_mail_count; int draft_mail_count; int trashed_mail_count; float interval; time_t last_mtime; double last_update; }; std::pair priv::current_mail_spool_setting::do_convert(lua::state &l, int index) { auto ret = Base::do_convert(l, index); if(ret.second) ret.first = variable_substitute(ret.first); return ret; } priv::current_mail_spool_setting current_mail_spool; namespace { enum { DEFAULT_MAIL_INTERVAL = 300 /*seconds*/ }; enum { MP_USER, MP_PASS, MP_FOLDER, MP_COMMAND, MP_HOST, MP_PORT }; struct mail_result { unsigned long unseen; unsigned long used; unsigned long messages; mail_result() : unseen(0), used(0), messages(0) {} }; class mail_cb: public conky::callback { typedef conky::callback Base; protected: addrinfo *ai; uint16_t fail; uint16_t retries; void resolve_host() { struct addrinfo hints; char portbuf[8]; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf(portbuf, 8, "%" SCNu16, get()); if(int res = getaddrinfo(get().c_str(), portbuf, &hints, &ai)) throw std::runtime_error(std::string("IMAP getaddrinfo: ") + gai_strerror(res)); } int connect() { for (struct addrinfo *rp = ai; rp != NULL; rp = rp->ai_next) { int sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sockfd == -1) { continue; } if (::connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1) { return sockfd; } close(sockfd); } throw std::runtime_error("Unable to connect to mail server"); } virtual void merge(callback_base &&other) { mail_cb &&o = dynamic_cast(other); if(retries < o.retries) { retries = o.retries; fail = 0; } Base::merge(std::move(other)); } mail_cb(uint32_t period, const Tuple &tuple, uint16_t retries_) : Base(period, false, tuple, true), ai(NULL), fail(0), retries(retries_) {} ~mail_cb() { if(ai) freeaddrinfo(ai); } }; struct mail_param_ex: public mail_cb::Tuple { uint16_t retries; uint32_t period; mail_param_ex() : retries(0), period(1) {} }; class imap_cb: public mail_cb { typedef mail_cb Base; void check_status(char *recvbuf); void unseen_command(unsigned long old_unseen, unsigned long old_messages); protected: virtual void work(); public: imap_cb(uint32_t period, const Tuple &tuple, uint16_t retries_) : Base(period, tuple, retries_) {} }; class pop3_cb: public mail_cb { typedef mail_cb Base; protected: virtual void work(); public: pop3_cb(uint32_t period, const Tuple &tuple, uint16_t retries_) : Base(period, tuple, retries_) {} }; struct mail_param_ex *global_mail; } static void update_mail_count(struct local_mail_s *mail) { struct stat st; if (mail == NULL) { return; } /* TODO: use that fine file modification notify on Linux 2.4 */ /* don't check mail so often (9.5s is minimum interval) */ if (current_update_time - mail->last_update < 9.5) { return; } else { mail->last_update = current_update_time; } if (stat(mail->mbox, &st)) { static int rep = 0; if (!rep) { NORM_ERR("can't stat %s: %s", mail->mbox, strerror(errno)); rep = 1; } return; } #if HAVE_DIRENT_H /* maildir format */ if (S_ISDIR(st.st_mode)) { DIR *dir; char *dirname; struct dirent *dirent; char *mailflags; mail->mail_count = mail->new_mail_count = 0; mail->seen_mail_count = mail->unseen_mail_count = 0; mail->flagged_mail_count = mail->unflagged_mail_count = 0; mail->forwarded_mail_count = mail->unforwarded_mail_count = 0; mail->replied_mail_count = mail->unreplied_mail_count = 0; mail->draft_mail_count = mail->trashed_mail_count = 0; dirname = (char *) malloc(sizeof(char) * (strlen(mail->mbox) + 5)); if (!dirname) { NORM_ERR("malloc"); return; } strcpy(dirname, mail->mbox); strcat(dirname, "/"); /* checking the cur subdirectory */ strcat(dirname, "cur"); dir = opendir(dirname); if (!dir) { NORM_ERR("cannot open directory"); free(dirname); return; } dirent = readdir(dir); while (dirent) { /* . and .. are skipped */ if (dirent->d_name[0] != '.') { mail->mail_count++; mailflags = (char *) malloc(sizeof(char) * strlen(strrchr(dirent->d_name, ','))); if (!mailflags) { NORM_ERR("malloc"); free(dirname); return; } strcpy(mailflags, strrchr(dirent->d_name, ',')); if (!strchr(mailflags, 'T')) { /* The message is not in the trash */ if (strchr(mailflags, 'S')) { /*The message has been seen */ mail->seen_mail_count++; } else { mail->unseen_mail_count++; } if (strchr(mailflags, 'F')) { /*The message was flagged */ mail->flagged_mail_count++; } else { mail->unflagged_mail_count++; } if (strchr(mailflags, 'P')) { /*The message was forwarded */ mail->forwarded_mail_count++; } else { mail->unforwarded_mail_count++; } if (strchr(mailflags, 'R')) { /*The message was replied */ mail->replied_mail_count++; } else { mail->unreplied_mail_count++; } if (strchr(mailflags, 'D')) { /*The message is a draft */ mail->draft_mail_count++; } } else { mail->trashed_mail_count++; } free(mailflags); } dirent = readdir(dir); } closedir(dir); dirname[strlen(dirname) - 3] = '\0'; strcat(dirname, "new"); dir = opendir(dirname); if (!dir) { NORM_ERR("cannot open directory"); free(dirname); return; } dirent = readdir(dir); while (dirent) { /* . and .. are skipped */ if (dirent->d_name[0] != '.') { mail->new_mail_count++; mail->mail_count++; mail->unseen_mail_count++; /* new messages cannot have been seen */ } dirent = readdir(dir); } closedir(dir); free(dirname); return; } #endif /* mbox format */ if (st.st_mtime != mail->last_mtime) { /* yippee, modification time has changed, let's read mail count! */ static int rep; FILE *fp; int reading_status = 0; /* could lock here but I don't think it's really worth it because * this isn't going to write mail spool */ mail->new_mail_count = mail->mail_count = 0; /* these flags are not supported for mbox */ mail->seen_mail_count = mail->unseen_mail_count = -1; mail->flagged_mail_count = mail->unflagged_mail_count = -1; mail->forwarded_mail_count = mail->unforwarded_mail_count = -1; mail->replied_mail_count = mail->unreplied_mail_count = -1; mail->draft_mail_count = mail->trashed_mail_count = -1; fp = open_file(mail->mbox, &rep); if (!fp) { return; } /* NOTE: adds mail as new if there isn't Status-field at all */ while (!feof(fp)) { char buf[128]; int was_new = 0; if (fgets(buf, 128, fp) == NULL) { break; } if (strncmp(buf, "From ", 5) == 0) { /* ignore MAILER-DAEMON */ if (strncmp(buf + 5, "MAILER-DAEMON ", 14) != 0) { mail->mail_count++; was_new = 0; if (reading_status == 1) { mail->new_mail_count++; } else { reading_status = 1; } } } else { if (reading_status == 1 && strncmp(buf, "X-Mozilla-Status:", 17) == 0) { int xms = strtol(buf + 17, NULL, 16); /* check that mail isn't marked for deletion */ if (xms & 0x0008) { mail->trashed_mail_count++; reading_status = 0; /* Don't check whether the trashed email is unread */ continue; } /* check that mail isn't already read */ if (!(xms & 0x0001)) { mail->new_mail_count++; was_new = 1; } /* check for an additional X-Status header */ reading_status = 2; continue; } if (reading_status == 1 && strncmp(buf, "Status:", 7) == 0) { /* check that mail isn't already read */ if (strchr(buf + 7, 'R') == NULL) { mail->new_mail_count++; was_new = 1; } reading_status = 2; continue; } if (reading_status >= 1 && strncmp(buf, "X-Status:", 9) == 0) { /* check that mail isn't marked for deletion */ if (strchr(buf + 9, 'D') != NULL) { mail->trashed_mail_count++; /* If the mail was previously detected as new, subtract it from the new mail count */ if (was_new) mail->new_mail_count--; } reading_status = 0; continue; } } /* skip until \n */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, 128, fp)) break; } } fclose(fp); if (reading_status) { mail->new_mail_count++; } mail->last_mtime = st.st_mtime; } } void parse_local_mail_args(struct text_object *obj, const char *arg) { float n1; char mbox[256]; struct local_mail_s *locmail; if (!arg) { n1 = 9.5; strncpy(mbox, current_mail_spool.get(*state).c_str(), sizeof(mbox)); } else { if (sscanf(arg, "%s %f", mbox, &n1) != 2) { n1 = 9.5; strncpy(mbox, arg, sizeof(mbox)); } } std::string dst = variable_substitute(mbox); locmail = (struct local_mail_s*)malloc(sizeof(struct local_mail_s)); memset(locmail, 0, sizeof(struct local_mail_s)); locmail->mbox = strndup(dst.c_str(), text_buffer_size.get(*state)); locmail->interval = n1; obj->data.opaque = locmail; } #define PRINT_MAILS_GENERATOR(x) \ void print_##x##mails(struct text_object *obj, char *p, int p_max_size) \ { \ struct local_mail_s *locmail = (struct local_mail_s *)obj->data.opaque; \ if (!locmail) \ return; \ update_mail_count(locmail); \ snprintf(p, p_max_size, "%d", locmail->x##mail_count); \ } PRINT_MAILS_GENERATOR() PRINT_MAILS_GENERATOR(new_) PRINT_MAILS_GENERATOR(seen_) PRINT_MAILS_GENERATOR(unseen_) PRINT_MAILS_GENERATOR(flagged_) PRINT_MAILS_GENERATOR(unflagged_) PRINT_MAILS_GENERATOR(forwarded_) PRINT_MAILS_GENERATOR(unforwarded_) PRINT_MAILS_GENERATOR(replied_) PRINT_MAILS_GENERATOR(unreplied_) PRINT_MAILS_GENERATOR(draft_) PRINT_MAILS_GENERATOR(trashed_) void free_local_mails(struct text_object *obj) { struct local_mail_s *locmail = (struct local_mail_s *)obj->data.opaque; if (!locmail) return; free_and_zero(locmail->mbox); free_and_zero(obj->data.opaque); } #define MAXDATASIZE 1000 namespace { enum mail_type { POP3_TYPE, IMAP_TYPE }; } std::unique_ptr parse_mail_args(mail_type type, const char *arg) { using std::get; std::unique_ptr mail; char *tmp; char host[129]; char user[129]; char pass[129]; if (sscanf(arg, "%128s %128s %128s", host, user, pass) != 3) { if (type == POP3_TYPE) { NORM_ERR("Scanning POP3 args failed"); } else if (type == IMAP_TYPE) { NORM_ERR("Scanning IMAP args failed"); } return mail; } // see if password needs prompting if (pass[0] == '*' && pass[1] == '\0') { int fp = fileno(stdin); struct termios term; tcgetattr(fp, &term); term.c_lflag &= ~ECHO; tcsetattr(fp, TCSANOW, &term); printf("Enter mailbox password (%s@%s): ", user, host); if (scanf("%128s", pass) != 1) pass[0] = 0; printf("\n"); term.c_lflag |= ECHO; tcsetattr(fp, TCSANOW, &term); } mail.reset(new mail_param_ex); get(*mail) = host; get(*mail) = user; get(*mail) = pass; // now we check for optional args tmp = (char*)strstr(arg, "-r "); if (tmp) { tmp += 3; sscanf(tmp, "%" SCNu16, &mail->retries); } else { mail->retries = 5; // 5 retries after failure } float interval = DEFAULT_MAIL_INTERVAL; tmp = (char*)strstr(arg, "-i "); if (tmp) { tmp += 3; sscanf(tmp, "%f", &interval); } mail->period = std::max(lround(interval/active_update_interval()), 1l); tmp = (char*)strstr(arg, "-p "); if (tmp) { tmp += 3; sscanf(tmp, "%" SCNu16, &get(*mail)); } else { if (type == POP3_TYPE) { get(*mail) = 110; // default pop3 port } else if (type == IMAP_TYPE) { get(*mail) = 143; // default imap port } } if (type == IMAP_TYPE) { tmp = (char*)strstr(arg, "-f "); if (tmp) { int len = 0; tmp += 3; if (tmp[0] == '\'') { len = (char*)strstr(tmp + 1, "'") - tmp - 1; tmp++; } get(*mail).assign(tmp, len); } else { get(*mail) = "INBOX"; // default imap inbox } } tmp = (char*)strstr(arg, "-e "); if (tmp) { int len = 0; tmp += 3; if (tmp[0] == '\'') { len = (char*)strstr(tmp + 1, "'") - tmp - 1; } get(*mail).assign(tmp + 1, len); } return mail; } void parse_imap_mail_args(struct text_object *obj, const char *arg) { static int rep = 0; if (!arg) { if (!global_mail && !rep) { // something is wrong, warn once then stop NORM_ERR("There's a problem with your mail settings. " "Check that the global mail settings are properly defined" " (line %li).", obj->line); rep = 1; return; } obj->data.opaque = global_mail; return; } // process obj->data.opaque = parse_mail_args(IMAP_TYPE, arg).release(); } void parse_pop3_mail_args(struct text_object *obj, const char *arg) { static int rep = 0; if (!arg) { if (!global_mail && !rep) { // something is wrong, warn once then stop NORM_ERR("There's a problem with your mail settings. " "Check that the global mail settings are properly defined" " (line %li).", obj->line); rep = 1; return; } obj->data.opaque = global_mail; return; } // process obj->data.opaque = parse_mail_args(POP3_TYPE, arg).release(); } namespace { class mail_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; mail_type type; protected: virtual void lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && !global_mail) { const std::string &t = do_convert(l, -1).first; if(t.size()) global_mail = parse_mail_args(type, t.c_str()).release(); } ++s; } virtual void cleanup(lua::state &l) { lua::stack_sentry s(l, -1); delete global_mail; global_mail = NULL; l.pop(); } public: mail_setting(const std::string &name, mail_type type_) : Base(name), type(type_) {} }; mail_setting imap("imap", IMAP_TYPE); mail_setting pop3("pop3", POP3_TYPE); } void free_mail_obj(struct text_object *obj) { if (!obj->data.opaque) return; if (obj->data.opaque != global_mail) { mail_param_ex *mail = static_cast(obj->data.opaque); delete mail; obj->data.opaque = 0; } } static void command(int sockfd, const std::string &cmd, char *response, const char *verify) { struct timeval fetchtimeout; fd_set fdset; ssize_t total = 0; int numbytes = 0; if (send(sockfd, cmd.c_str(), cmd.length(), 0) == -1) throw std::runtime_error("send: " + strerror_r(errno)); DBGP2("command() command: %s", cmd.c_str()); while(1) { fetchtimeout.tv_sec = 60; // 60 second timeout i guess fetchtimeout.tv_usec = 0; FD_ZERO(&fdset); FD_SET(sockfd, &fdset); if(select(sockfd + 1, &fdset, NULL, NULL, &fetchtimeout) == 0) throw std::runtime_error("select: read timeout"); if ((numbytes = recv(sockfd, response + total, MAXDATASIZE - 1 - total, 0)) == -1) throw std::runtime_error("recv: " + strerror_r(errno)); total += numbytes; response[total] = '\0'; DBGP2("command() received: %s", response); if (strstr(response, verify) != NULL) return; if(numbytes == 0) throw std::runtime_error("Unexpected response from server"); } } void imap_cb::check_status(char *recvbuf) { char *reply; reply = (char*)strstr(recvbuf, " (MESSAGES "); if (!reply || strlen(reply) < 2) std::runtime_error("Unexpected response from server"); reply += 2; *strchr(reply, ')') = '\0'; std::lock_guard lock(result_mutex); if(sscanf(reply, "MESSAGES %lu UNSEEN %lu", &result.messages, &result.unseen) != 2) throw std::runtime_error(std::string("Error parsing response: ") + recvbuf); } void imap_cb::unseen_command(unsigned long old_unseen, unsigned long old_messages) { if (!get().empty() && (result.unseen > old_unseen || (result.messages > old_messages && result.unseen > 0))) { if (system(get().c_str()) == -1) { perror("system()"); } } } void imap_cb::work() { int sockfd, numbytes; char recvbuf[MAXDATASIZE]; unsigned long old_unseen = ULONG_MAX; unsigned long old_messages = ULONG_MAX; bool has_idle = false; while (fail < retries) { struct timeval fetchtimeout; int res; fd_set fdset; if(not ai) resolve_host(); try { sockfd = connect(); command(sockfd, "", recvbuf, "* OK"); command(sockfd, "abc CAPABILITY\r\n", recvbuf, "abc OK"); if (strstr(recvbuf, " IDLE ") != NULL) has_idle = true; std::ostringstream str; str << "a1 login " << get() << " {" << get().length() << "}\r\n"; command(sockfd, str.str(), recvbuf, "+"); command(sockfd, get() + "\r\n", recvbuf, "a1 OK"); command(sockfd, "a2 STATUS \"" + get() + "\" (MESSAGES UNSEEN)\r\n", recvbuf, "a2 OK"); check_status(recvbuf); unseen_command(old_unseen, old_messages); fail = 0; old_unseen = result.unseen; old_messages = result.messages; if(not has_idle) { try { command(sockfd, "a3 LOGOUT\r\n", recvbuf, "a3 OK"); } catch(std::runtime_error &) {} close(sockfd); return; } command(sockfd, "a4 SELECT \"" + get() + "\"\r\n", recvbuf, "a4 OK"); command(sockfd, "a5 IDLE\r\n", recvbuf, "+ idling"); recvbuf[0] = '\0'; while (1) { /* * RFC 2177 says we have to re-idle every 29 minutes. * We'll do it every 20 minutes to be safe. */ fetchtimeout.tv_sec = 1200; fetchtimeout.tv_usec = 0; DBGP2("idling..."); FD_ZERO(&fdset); FD_SET(sockfd, &fdset); FD_SET(donefd(), &fdset); res = select(std::max(sockfd, donefd()) + 1, &fdset, NULL, NULL, &fetchtimeout); if ((res == -1 && errno == EINTR) || FD_ISSET(donefd(), &fdset)) { try { command(sockfd, "DONE\r\n", recvbuf, "a5 OK"); command(sockfd, "a3 LOGOUT\r\n", recvbuf, "a3 OK"); } catch(std::runtime_error &) {} close(sockfd); return; } else if (res > 0) { if((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) throw std::runtime_error("recv idling"); } else throw std::runtime_error(""); recvbuf[numbytes] = '\0'; DBGP2("imap_thread() received: %s", recvbuf); unsigned long messages, recent = 0; bool force_check = 0; if (strlen(recvbuf) > 2) { char *buf = recvbuf; buf = (char*)strstr(buf, "EXISTS"); while (buf && strlen(buf) > 1 && strstr(buf + 1, "EXISTS")) { buf = (char*)strstr(buf + 1, "EXISTS"); } if (buf) { // back up until we reach '*' while (buf >= recvbuf && buf[0] != '*') { buf--; } if (sscanf(buf, "* %lu EXISTS\r\n", &messages) == 1) { std::lock_guard lock(result_mutex); if (result.messages != messages) { force_check = 1; result.messages = messages; } } } buf = recvbuf; buf = (char*)strstr(buf, "RECENT"); while (buf && strlen(buf) > 1 && strstr(buf + 1, "RECENT")) { buf = (char*)strstr(buf + 1, "RECENT"); } if (buf) { // back up until we reach '*' while (buf >= recvbuf && buf[0] != '*') { buf--; } if (sscanf(buf, "* %lu RECENT\r\n", &recent) != 1) { recent = 0; } } } /* check if we got a BYE from server */ if (strstr(recvbuf, "* BYE")) { // need to re-connect throw std::runtime_error(""); } /* * check if we got a FETCH from server, recent was * something other than 0, or we had a timeout */ if (recent > 0 || strstr(recvbuf, " FETCH ") || fetchtimeout.tv_sec == 0 || force_check) { // re-check messages and unseen command(sockfd, "DONE\r\n", recvbuf, "a5 OK"); command(sockfd, "a2 STATUS \"" + get() + "\" (MESSAGES UNSEEN)\r\n", recvbuf, "a2 OK"); check_status(recvbuf); command(sockfd, "a5 IDLE\r\n", recvbuf, "+ idling"); } unseen_command(old_unseen, old_messages); fail = 0; old_unseen = result.unseen; old_messages = result.messages; } } catch(std::runtime_error &e) { if(sockfd != -1) close(sockfd); freeaddrinfo(ai); ai = NULL; ++fail; if(*e.what()) NORM_ERR("Error while communicating with IMAP server: %s", e.what()); NORM_ERR("Trying IMAP connection again for %s@%s (try %u/%u)", get().c_str(), get().c_str(), fail+1, retries); sleep(fail); /* sleep more for the more failures we have */ } if(is_done()) return; } } void print_imap_unseen(struct text_object *obj, char *p, int p_max_size) { struct mail_param_ex *mail = (struct mail_param_ex *)obj->data.opaque; if (!mail) return; auto cb = conky::register_cb(mail->period, *mail, mail->retries); snprintf(p, p_max_size, "%lu", cb->get_result_copy().unseen); } void print_imap_messages(struct text_object *obj, char *p, int p_max_size) { struct mail_param_ex *mail = (struct mail_param_ex *)obj->data.opaque; if (!mail) return; auto cb = conky::register_cb(mail->period, *mail, mail->retries); snprintf(p, p_max_size, "%lu", cb->get_result_copy().messages); } void pop3_cb::work() { int sockfd; char recvbuf[MAXDATASIZE]; char *reply; unsigned long old_unseen = ULONG_MAX; while (fail < retries) { if(not ai) resolve_host(); try { sockfd = connect(); command(sockfd, "", recvbuf, "+OK "); command(sockfd, "USER " + get() + "\r\n", recvbuf, "+OK "); command(sockfd, "PASS " + get() + "\r\n", recvbuf, "+OK "); command(sockfd, "STAT\r\n", recvbuf, "+OK "); // now we get the data reply = recvbuf + 4; { std::lock_guard lock(result_mutex); sscanf(reply, "%lu %lu", &result.unseen, &result.used); } command(sockfd, "QUIT\r\n", recvbuf, "+OK"); if (get().length() > 1 && result.unseen > old_unseen) { // new mail goodie if (system(get().c_str()) == -1) { perror("system()"); } } fail = 0; old_unseen = result.unseen; return; } catch(std::runtime_error &e) { if(sockfd != -1) close(sockfd); freeaddrinfo(ai); ai = NULL; ++fail; if(*e.what()) NORM_ERR("Error while communicating with POP3 server: %s", e.what()); NORM_ERR("Trying POP3 connection again for %s@%s (try %u/%u)", get().c_str(), get().c_str(), fail+1, retries); sleep(fail); /* sleep more for the more failures we have */ } if(is_done()) return; } } void print_pop3_unseen(struct text_object *obj, char *p, int p_max_size) { struct mail_param_ex *mail = (struct mail_param_ex *)obj->data.opaque; if (!mail) return; auto cb = conky::register_cb(mail->period, *mail, mail->retries); snprintf(p, p_max_size, "%lu", cb->get_result_copy().unseen); } void print_pop3_used(struct text_object *obj, char *p, int p_max_size) { struct mail_param_ex *mail = (struct mail_param_ex *)obj->data.opaque; if (!mail) return; auto cb = conky::register_cb(mail->period, *mail, mail->retries); snprintf(p, p_max_size, "%.1f", cb->get_result_copy().used / 1024.0 / 1024.0); } conky-1.10.1/src/mail.h000066400000000000000000000051021262311664100145770ustar00rootroot00000000000000/* -*- 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-2012 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 _MAIL_H #define _MAIL_H #include "setting.hh" void parse_local_mail_args(struct text_object *, const char *); #define PRINT_MAILS_PROTO_GENERATOR(x) \ void print_##x##mails(struct text_object *, char *, int); PRINT_MAILS_PROTO_GENERATOR() PRINT_MAILS_PROTO_GENERATOR(new_) PRINT_MAILS_PROTO_GENERATOR(seen_) PRINT_MAILS_PROTO_GENERATOR(unseen_) PRINT_MAILS_PROTO_GENERATOR(flagged_) PRINT_MAILS_PROTO_GENERATOR(unflagged_) PRINT_MAILS_PROTO_GENERATOR(forwarded_) PRINT_MAILS_PROTO_GENERATOR(unforwarded_) PRINT_MAILS_PROTO_GENERATOR(replied_) PRINT_MAILS_PROTO_GENERATOR(unreplied_) PRINT_MAILS_PROTO_GENERATOR(draft_) PRINT_MAILS_PROTO_GENERATOR(trashed_) void free_local_mails(struct text_object *obj); void parse_global_imap_mail_args(const char *); void parse_global_pop3_mail_args(const char *); void parse_imap_mail_args(struct text_object *, const char *); void parse_pop3_mail_args(struct text_object *, const char *); void free_mail_obj(struct text_object *); void print_imap_unseen(struct text_object *, char *, int); void print_imap_messages(struct text_object *, char *, int); void print_pop3_unseen(struct text_object *, char *, int); void print_pop3_used(struct text_object *, char *, int); namespace priv { class current_mail_spool_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual std::pair do_convert(lua::state &l, int index); public: current_mail_spool_setting() : Base("current_mail_spool", "$MAIL", true) {} }; } extern priv::current_mail_spool_setting current_mail_spool; #endif /* _MAIL_H */ conky-1.10.1/src/mboxscan.cc000066400000000000000000000240551262311664100156350ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2006 Marco Candrian * Copyright (c) 2005-2012 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 "mail.h" #include "text_object.h" #include #include #include #include #define FROM_WIDTH 10 #define SUBJECT_WIDTH 22 #define PRINT_MAILS 5 #define TIME_DELAY 5 struct ring_list { char *from; char *subject; struct ring_list *previous; struct ring_list *next; }; static time_t last_ctime; /* needed for mutt at least */ static time_t last_mtime; /* not sure what to test: testing both now */ static double last_update; static int args_ok = 0; static int from_width; static int subject_width; static int print_num_mails; static int time_delay; static char mbox_mail_spool[DEFAULT_TEXT_BUFFER_SIZE]; static void mbox_scan(char *args, char *output, size_t max_len) { int i, u, flag; int force_rescan = 0; std::unique_ptr buf_(new char[text_buffer_size.get(*state)]); char *buf = buf_.get(); struct stat statbuf; struct ring_list *curr = 0, *prev = 0, *startlist = 0; FILE *fp; /* output was set to 1 after malloc'ing in conky.c */ /* -> beeing able to test it here for catching SIGUSR1 */ if (output[0] == 1) { force_rescan = 1; output[0] = '\0'; } if (!args_ok || force_rescan) { char *substr = strstr(args, "-n"); if (substr) { if (sscanf(substr, "-n %i", &print_num_mails) != 1) { print_num_mails = PRINT_MAILS; } } else { print_num_mails = PRINT_MAILS; } if (print_num_mails < 1) { print_num_mails = 1; } substr = strstr(args, "-t"); if (substr) { if (sscanf(substr, "-t %i", &time_delay) != 1) { time_delay = TIME_DELAY; } } else { time_delay = TIME_DELAY; } substr = strstr(args, "-fw"); if (substr) { if (sscanf(substr, "-fw %i", &from_width) != 1) { from_width = FROM_WIDTH; } } else { from_width = FROM_WIDTH; } substr = strstr(args, "-sw"); if (substr) { if (sscanf(substr, "-sw %i", &subject_width) != 1) { subject_width = SUBJECT_WIDTH; } } else { subject_width = SUBJECT_WIDTH; } /* encapsulated with "'s find first occurrence of " */ if (args[strlen(args) - 1] == '"') { char *start; strncpy(mbox_mail_spool, args, DEFAULT_TEXT_BUFFER_SIZE); start = strchr(mbox_mail_spool, '"') + 1; start[(long) (strrchr(mbox_mail_spool, '"') - start)] = '\0'; strncpy(mbox_mail_spool, start, DEFAULT_TEXT_BUFFER_SIZE); } else { char *copy_args = strndup(args, text_buffer_size.get(*state)); char *tmp = strtok(copy_args, " "); char *start = tmp; while (tmp) { tmp = strtok(NULL, " "); if (tmp) { start = tmp; } } strncpy(mbox_mail_spool, start, DEFAULT_TEXT_BUFFER_SIZE); free(copy_args); } if (strlen(mbox_mail_spool) < 1) { CRIT_ERR(NULL, NULL, "Usage: ${mboxscan [-n ] " "[-fw ] [-sw ] " "[-t mbox]}"); } /* allowing $MAIL in the config */ if (!strcmp(mbox_mail_spool, "$MAIL")) { strcpy(mbox_mail_spool, current_mail_spool.get(*state).c_str()); } if (stat(mbox_mail_spool, &statbuf)) { CRIT_ERR(NULL, NULL, "can't stat %s: %s", mbox_mail_spool, strerror(errno)); } args_ok = 1; /* args-computing necessary only once */ } /* if time_delay not yet reached, then return */ if (current_update_time - last_update < time_delay && !force_rescan) { return; } last_update = current_update_time; /* mbox still exists? and get stat-infos */ if (stat(mbox_mail_spool, &statbuf)) { NORM_ERR("can't stat %s: %s", mbox_mail_spool, strerror(errno)); output[0] = '\0'; /* delete any output */ return; } /* modification time has not changed, so skip scanning the box */ if (statbuf.st_ctime == last_ctime && statbuf.st_mtime == last_mtime && !force_rescan) { return; } last_ctime = statbuf.st_ctime; last_mtime = statbuf.st_mtime; /* build up double-linked ring-list to hold data, while scanning down the * mbox */ for (i = 0; i < print_num_mails; i++) { curr = (struct ring_list *) malloc(sizeof(struct ring_list)); curr->from = (char *) malloc(from_width + 1); curr->subject = (char *) malloc(subject_width + 1); curr->from[0] = '\0'; curr->subject[0] = '\0'; if (i == 0) { startlist = curr; } if (i > 0) { curr->previous = prev; prev->next = curr; } prev = curr; } /* connect end to start for an endless loop-ring */ startlist->previous = curr; curr->next = startlist; /* mbox */ fp = fopen(mbox_mail_spool, "r"); if (!fp) { return; } /* first find a "From " to set it to 0 for header-sarchings */ flag = 1; while (!feof(fp)) { if (fgets(buf, text_buffer_size.get(*state), fp) == NULL) { break; } if (strncmp(buf, "From ", 5) == 0) { curr = curr->next; /* skip until \n */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, text_buffer_size.get(*state), fp)) break; } flag = 0; /* in the headers now */ continue; } if (flag == 1) { /* in the body, so skip */ continue; } if (buf[0] == '\n') { /* beyond the headers now (empty line), skip until \n */ /* then search for new mail ("From ") */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, text_buffer_size.get(*state), fp)) break; } flag = 1; /* in the body now */ continue; } if ((strncmp(buf, "X-Status: ", 10) == 0) || (strncmp(buf, "Status: R", 9) == 0)) { /* Mail was read or something, so skip that message */ flag = 1; /* search for next From */ curr->subject[0] = '\0'; curr->from[0] = '\0'; /* (will get current again on new 'From ' finding) */ curr = curr->previous; /* Skip until \n */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, text_buffer_size.get(*state), fp)) break; } continue; } /* that covers ^From: and ^from: ^From: */ if (strncmp(buf + 1, "rom:", 4) == 0) { i = 0; u = 6; /* no "From: " string needed, so skip */ while (1) { if (buf[u] == '"') { /* no quotes around names */ u++; continue; } /* some are: From: */ if (buf[u] == '<' && i > 1) { curr->from[i] = '\0'; /* skip until \n */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, text_buffer_size.get(*state), fp)) break; } break; } if (buf[u] == '\n') { curr->from[i] = '\0'; break; } if (buf[u] == '\0') { curr->from[i] = '\0'; break; } if (i >= from_width) { curr->from[i] = '\0'; /* skip until \n */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, text_buffer_size.get(*state), fp)) break; } break; } /* nothing special so just set it */ curr->from[i++] = buf[u++]; } } /* that covers ^Subject: and ^subject: and ^Subjec: */ if (strncmp(buf + 1, "ubject:", 7) == 0) { i = 0; u = 9; /* no "Subject: " string needed, so skip */ while (1) { if (buf[u] == '\n') { curr->subject[i] = '\0'; break; } if (buf[u] == '\0') { curr->subject[i] = '\0'; break; } if (i >= subject_width) { curr->subject[i] = '\0'; /* skip until \n */ while (strchr(buf, '\n') == NULL && !feof(fp)) { if (!fgets(buf, text_buffer_size.get(*state), fp)) break; } break; } /* nothing special so just set it */ curr->subject[i++] = buf[u++]; } } } fclose(fp); output[0] = '\0'; i = print_num_mails; while (i) { struct ring_list *tmp; if (curr->from[0] != '\0') { if (i != print_num_mails) { snprintf(buf, text_buffer_size.get(*state), "\nF: %-*s S: %-*s", from_width, curr->from, subject_width, curr->subject); } else { /* first time - no \n in front */ snprintf(buf, text_buffer_size.get(*state), "F: %-*s S: %-*s", from_width, curr->from, subject_width, curr->subject); } } else { snprintf(buf, text_buffer_size.get(*state), "\n"); } strncat(output, buf, max_len - strlen(output)); tmp = curr; curr = curr->previous; free(tmp->from); free(tmp->subject); free(tmp); i--; } } struct mboxscan_data { char *args; char *output; }; void parse_mboxscan_arg(struct text_object *obj, const char *arg) { struct mboxscan_data *msd; msd = (mboxscan_data*) malloc(sizeof(struct mboxscan_data)); memset(msd, 0, sizeof(struct mboxscan_data)); msd->args = strndup(arg, text_buffer_size.get(*state)); msd->output = (char *) malloc(text_buffer_size.get(*state)); /* if '1' (in mboxscan.c) then there was SIGUSR1, hmm */ msd->output[0] = 1; obj->data.opaque = msd; } void print_mboxscan(struct text_object *obj, char *p, int p_max_size) { struct mboxscan_data *msd = (mboxscan_data*) obj->data.opaque; if (!msd) return; mbox_scan(msd->args, msd->output, text_buffer_size.get(*state)); snprintf(p, p_max_size, "%s", msd->output); } void free_mboxscan(struct text_object *obj) { struct mboxscan_data *msd = (mboxscan_data*) obj->data.opaque; if (!msd) return; free_and_zero(msd->args); free_and_zero(msd->output); free_and_zero(obj->data.opaque); } conky-1.10.1/src/mboxscan.h000066400000000000000000000025001262311664100154660ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2006 Marco Candrian * Copyright (c) 2005-2012 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 _MBOXSCAN_H_ #define _MBOXSCAN_H_ void parse_mboxscan_arg(struct text_object *, const char *); void print_mboxscan(struct text_object *, char *, int); void free_mboxscan(struct text_object *); #endif /* _MBOXSCAN_H_ */ conky-1.10.1/src/mixer.cc000066400000000000000000000072411262311664100151450ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "specials.h" #include "text_object.h" #include #include #include #include #ifdef HAVE_LINUX_SOUNDCARD_H #include #else #ifdef __OpenBSD__ #include #else #include #endif /* __OpenBSD__ */ #endif /* HAVE_LINUX_SOUNDCARD_H */ #define MIXER_DEV "/dev/mixer" static int mixer_fd; static const char *devs[] = SOUND_DEVICE_NAMES; int mixer_init(const char *name) { unsigned int i; if (name == 0 || name[0] == '\0') { name = "vol"; } /* open mixer */ if (mixer_fd <= 0) { mixer_fd = open(MIXER_DEV, O_RDONLY); if (mixer_fd == -1) { NORM_ERR("can't open %s: %s", MIXER_DEV, strerror(errno)); return -1; } } for (i = 0; i < sizeof(devs) / sizeof(const char *); i++) { if (strcasecmp(devs[i], name) == 0) { return i; } } return -1; } static int mixer_get(int i) { static char rep = 0; int val = -1; if (ioctl(mixer_fd, MIXER_READ(i), &val) == -1) { if (!rep) { NORM_ERR("mixer ioctl: %s", strerror(errno)); } rep = 1; return 0; } rep = 0; return val; } static int mixer_get_avg(int i) { int v = mixer_get(i); return ((v >> 8) + (v & 0xFF)) / 2; } static int mixer_get_left(int i) { return mixer_get(i) >> 8; } static int mixer_get_right(int i) { return mixer_get(i) & 0xFF; } int mixer_is_mute(int i) { return !mixer_get(i); } #define mixer_to_255(i, x) x void parse_mixer_arg(struct text_object *obj, const char *arg) { obj->data.l = mixer_init(arg); } uint8_t mixer_percentage(struct text_object *obj) { return mixer_get_avg(obj->data.l); } uint8_t mixerl_percentage(struct text_object *obj) { return mixer_get_left(obj->data.l); } uint8_t mixerr_percentage(struct text_object *obj) { return mixer_get_right(obj->data.l); } int check_mixer_muted(struct text_object *obj) { if (!mixer_is_mute(obj->data.l)) return 0; return 1; } void scan_mixer_bar(struct text_object *obj, const char *arg) { char buf1[64]; int n; if (arg && sscanf(arg, "%63s %n", buf1, &n) >= 1) { obj->data.i = mixer_init(buf1); scan_bar(obj, arg + n, 100); } else { obj->data.i = mixer_init(NULL); scan_bar(obj, arg, 100); } } double mixer_barval(struct text_object *obj) { return mixer_to_255(obj->data.i, mixer_get_avg(obj->data.i)); } double mixerl_barval(struct text_object *obj) { return mixer_to_255(obj->data.i, mixer_get_left(obj->data.i)); } double mixerr_barval(struct text_object *obj) { return mixer_to_255(obj->data.i, mixer_get_right(obj->data.i)); } conky-1.10.1/src/mixer.h000066400000000000000000000032531262311664100150060ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2007 Toni Spets * Copyright (c) 2005-2012 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 MIXER_H_ #define MIXER_H_ void parse_mixer_arg(struct text_object *, const char *); uint8_t mixer_percentage(struct text_object *obj); uint8_t mixerl_percentage(struct text_object *obj); uint8_t mixerr_percentage(struct text_object *obj); int check_mixer_muted(struct text_object *); void scan_mixer_bar(struct text_object *, const char *); double mixer_barval(struct text_object *); double mixerl_barval(struct text_object *); double mixerr_barval(struct text_object *); #endif /*MIXER_H_*/ conky-1.10.1/src/moc.cc000066400000000000000000000072031262311664100145750ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * MOC Conky integration * * Please see COPYING for details * * Copyright (c) 2008, Henri Häkkinen * * 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 "text_object.h" #include #include #include #include #include #include "update-cb.hh" namespace { struct moc_result { std::string state; std::string file; std::string title; std::string artist; std::string song; std::string album; std::string totaltime; std::string timeleft; std::string curtime; std::string bitrate; std::string rate; }; class moc_cb: public conky::callback { typedef conky::callback Base; protected: virtual void work(); public: moc_cb(uint32_t period) : Base(period, false, Tuple()) {} }; void moc_cb::work() { moc_result moc; FILE *fp; fp = popen("mocp -i", "r"); if (!fp) { moc.state = "Can't run 'mocp -i'"; } else { while (1) { char line[100]; char *p; /* Read a line from the pipe and strip the possible '\n'. */ if (!fgets(line, 100, fp)) break; if ((p = strrchr(line, '\n'))) *p = '\0'; /* Parse infos. */ if (strncmp(line, "State:", 6) == 0) moc.state = line + 7; else if (strncmp(line, "File:", 5) == 0) moc.file = line + 6; else if (strncmp(line, "Title:", 6) == 0) moc.title = line + 7; else if (strncmp(line, "Artist:", 7) == 0) moc.artist = line + 8; else if (strncmp(line, "SongTitle:", 10) == 0) moc.song = line + 11; else if (strncmp(line, "Album:", 6) == 0) moc.album = line + 7; else if (strncmp(line, "TotalTime:", 10) == 0) moc.totaltime = line + 11; else if (strncmp(line, "TimeLeft:", 9) == 0) moc.timeleft = line + 10; else if (strncmp(line, "CurrentTime:", 12) == 0) moc.curtime = line + 13; else if (strncmp(line, "Bitrate:", 8) == 0) moc.bitrate = line + 9; else if (strncmp(line, "Rate:", 5) == 0) moc.rate = line + 6; } } pclose(fp); std::lock_guard l(result_mutex); result = moc; } } #define MOC_PRINT_GENERATOR(type, alt) \ void print_moc_##type(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ uint32_t period = std::max( \ lround(music_player_interval.get(*state)/active_update_interval()), 1l \ ); \ const moc_result &moc = conky::register_cb(period)->get_result_copy(); \ snprintf(p, p_max_size, "%s", (moc.type.length() ? moc.type.c_str() : alt)); \ } MOC_PRINT_GENERATOR(state, "??") MOC_PRINT_GENERATOR(file, "no file") MOC_PRINT_GENERATOR(title, "no title") MOC_PRINT_GENERATOR(artist, "no artist") MOC_PRINT_GENERATOR(song, "no song") MOC_PRINT_GENERATOR(album, "no album") MOC_PRINT_GENERATOR(totaltime, "0:00") MOC_PRINT_GENERATOR(timeleft, "0:00") MOC_PRINT_GENERATOR(curtime, "0:00") MOC_PRINT_GENERATOR(bitrate, "0Kbps") MOC_PRINT_GENERATOR(rate, "0KHz") #undef MOC_PRINT_GENERATOR conky-1.10.1/src/moc.h000066400000000000000000000030421262311664100144340ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * MOC Conky integration * * Please see COPYING for details * * Copyright (c) 2008, Henri Häkkinen * * 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 MOC_H_ #define MOC_H_ void print_moc_state(struct text_object *, char *, int); void print_moc_file(struct text_object *, char *, int); void print_moc_title(struct text_object *, char *, int); void print_moc_artist(struct text_object *, char *, int); void print_moc_song(struct text_object *, char *, int); void print_moc_album(struct text_object *, char *, int); void print_moc_totaltime(struct text_object *, char *, int); void print_moc_timeleft(struct text_object *, char *, int); void print_moc_curtime(struct text_object *, char *, int); void print_moc_bitrate(struct text_object *, char *, int); void print_moc_rate(struct text_object *, char *, int); #endif /* MOC_H_ */ conky-1.10.1/src/mpd.cc000066400000000000000000000236131262311664100146020ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 #include "conky.h" #include "logging.h" #include "timeinfo.h" #include "libmpdclient.h" #include "mpd.h" #include "update-cb.hh" namespace { /* this is true if the current host was set from MPD_HOST */ bool mpd_environment_host = false; class mpd_host_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); public: mpd_host_setting() : Base("mpd_host", "localhost", false) {} }; void mpd_host_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); if(l.isnil(-2)) { // get the value from environment mpd_environment_host = true; const char *t = getenv("MPD_HOST"); if(t) { l.checkstack(1); const char *h = strchr(t, '@'); if(h) { if(h[1]) l.pushstring(h+1); } else l.pushstring(t); l.replace(-3); } } Base::lua_setter(l, init); ++s; } class mpd_password_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); public: mpd_password_setting() : Base("mpd_password", std::string(), false) {} }; void mpd_password_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); /* for security, dont use environment password when user specifies host in config */ if(l.isnil(-2) && mpd_environment_host) { // get the value from environment const char *t = getenv("MPD_HOST"); if(t) { const char *p = strchr(t, '@'); if(p) { l.checkstack(1); l.pushstring(t, p-t); l.replace(-3); } } } Base::lua_setter(l, init); ++s; } conky::range_config_setting mpd_port("mpd_port", 1, 65535, 6600, false); mpd_host_setting mpd_host; mpd_password_setting mpd_password; struct mpd_result { std::string title; std::string artist; std::string albumartist; std::string album; std::string date; std::string status; std::string random; std::string repeat; std::string track; std::string name; std::string file; int is_playing; int vol; float progress; int bitrate; int length; int elapsed; }; class mpd_cb: public conky::callback { typedef conky::callback Base; mpd_Connection *conn; protected: virtual void work(); public: mpd_cb(uint32_t period) : Base(period, false, Tuple()), conn(NULL) {} ~mpd_cb() { if(conn) mpd_closeConnection(conn); } }; void mpd_cb::work() { mpd_Status *status; mpd_InfoEntity *entity; mpd_result mpd_info; do { if (!conn) conn = mpd_newConnection(mpd_host.get(*state).c_str(), mpd_port.get(*state), 10); if (mpd_password.get(*state).size()) { mpd_sendPasswordCommand(conn, mpd_password.get(*state).c_str()); mpd_finishCommand(conn); } if (conn->error) { NORM_ERR("MPD error: %s\n", conn->errorStr); mpd_closeConnection(conn); conn = 0; mpd_info.status = "MPD not responding"; break; } mpd_sendStatusCommand(conn); if ((status = mpd_getStatus(conn)) == NULL) { NORM_ERR("MPD error: %s\n", conn->errorStr); mpd_closeConnection(conn); conn = 0; mpd_info.status = "MPD not responding"; } mpd_finishCommand(conn); if (!conn || conn->error) { // fprintf(stderr, "%s\n", conn->errorStr); mpd_closeConnection(conn); conn = 0; break; } mpd_info.vol = status->volume; if (status->random == 0) { mpd_info.random = "Off"; } else if (status->random == 1) { mpd_info.random = "On"; } else { mpd_info.random = ""; } if (status->repeat == 0) { mpd_info.repeat = "Off"; } else if (status->repeat == 1) { mpd_info.repeat = "On"; } else { mpd_info.repeat = ""; } /* if (status->error) { printf("error: %s\n", status->error); } */ switch (status->state) { case MPD_STATUS_STATE_PLAY: mpd_info.status = "Playing"; break; case MPD_STATUS_STATE_STOP: mpd_info.status = "Stopped"; break; case MPD_STATUS_STATE_PAUSE: mpd_info.status = "Paused"; break; default: mpd_info.status = ""; break; } if (status->state == MPD_STATUS_STATE_PLAY || status->state == MPD_STATUS_STATE_PAUSE) { mpd_info.is_playing = 1; mpd_info.bitrate = status->bitRate; mpd_info.progress = (float) status->elapsedTime / status->totalTime; mpd_info.elapsed = status->elapsedTime; mpd_info.length = status->totalTime; } else { mpd_info.progress = 0; mpd_info.is_playing = 0; mpd_info.elapsed = 0; } if (conn->error) { // fprintf(stderr, "%s\n", conn->errorStr); mpd_closeConnection(conn); conn = 0; break; } mpd_sendCurrentSongCommand(conn); while ((entity = mpd_getNextInfoEntity(conn))) { mpd_Song *song = entity->info.song; if (entity->type != MPD_INFO_ENTITY_TYPE_SONG) { mpd_freeInfoEntity(entity); continue; } #define SETSTRING(a,b) \ if (b) a=b; else a=""; SETSTRING(mpd_info.artist, song->artist); SETSTRING(mpd_info.album, song->album); SETSTRING(mpd_info.title, song->title); SETSTRING(mpd_info.date, song->date); SETSTRING(mpd_info.track, song->track); SETSTRING(mpd_info.name, song->name); SETSTRING(mpd_info.file, song->file); if (entity != NULL) { mpd_freeInfoEntity(entity); entity = NULL; } } mpd_finishCommand(conn); if (conn && conn->error) { // fprintf(stderr, "%s\n", conn->errorStr); mpd_closeConnection(conn); conn = 0; break; } if (conn->error) { // fprintf(stderr, "%s\n", conn->errorStr); mpd_closeConnection(conn); conn = 0; break; } mpd_freeStatus(status); /* if (conn) { mpd_closeConnection(conn); conn = 0; } */ } while (0); std::lock_guard lock(Base::result_mutex); result = mpd_info; // don't forget to save results! } mpd_result get_mpd() { uint32_t period = std::max( lround(music_player_interval.get(*state)/active_update_interval()), 1l ); return conky::register_cb(period)->get_result_copy(); } } static inline void format_media_player_time(char *buf, const int size, int seconds) { int days, hours, minutes; if (times_in_seconds.get(*state)) { snprintf(buf, size, "%d", seconds); return; } days = seconds / (24 * 60 * 60); seconds %= (24 * 60 * 60); hours = seconds / (60 * 60); seconds %= (60 * 60); minutes = seconds / 60; seconds %= 60; if (days > 0) { snprintf(buf, size, "%i days %i:%02i:%02i", days, hours, minutes, seconds); } else if (hours > 0) { snprintf(buf, size, "%i:%02i:%02i", hours, minutes, seconds); } else { snprintf(buf, size, "%i:%02i", minutes, seconds); } } void print_mpd_elapsed(struct text_object *obj, char *p, int p_max_size) { (void)obj; format_media_player_time(p, p_max_size, get_mpd().elapsed); } void print_mpd_length(struct text_object *obj, char *p, int p_max_size) { (void)obj; format_media_player_time(p, p_max_size, get_mpd().length); } uint8_t mpd_percentage(struct text_object *obj) { (void)obj; return round_to_int(get_mpd().progress * 100.0f); } double mpd_barval(struct text_object *obj) { (void)obj; return get_mpd().progress; } void print_mpd_smart(struct text_object *obj, char *p, int p_max_size) { const mpd_result &mpd_info = get_mpd(); int len = obj->data.i; if (len == 0 || len > p_max_size) len = p_max_size; memset(p, 0, p_max_size); if (mpd_info.artist.size() && mpd_info.title.size()) { snprintf(p, len, "%s - %s", mpd_info.artist.c_str(), mpd_info.title.c_str()); } else if (get_mpd().title.size()) { snprintf(p, len, "%s", mpd_info.title.c_str()); } else if (mpd_info.artist.size()) { snprintf(p, len, "%s", mpd_info.artist.c_str()); } else if (mpd_info.file.size()) { snprintf(p, len, "%s", mpd_info.file.c_str()); } else { *p = 0; } } int check_mpd_playing(struct text_object *obj) { (void)obj; return get_mpd().is_playing; } #define MPD_PRINT_GENERATOR(name, fmt, acc) \ void print_mpd_##name(struct text_object *obj, char *p, int p_max_size) \ { \ if (obj->data.i && obj->data.i < p_max_size) \ p_max_size = obj->data.i; \ snprintf(p, p_max_size, fmt, get_mpd().name acc); \ } MPD_PRINT_GENERATOR(title, "%s", .c_str()) MPD_PRINT_GENERATOR(artist, "%s", .c_str()) MPD_PRINT_GENERATOR(albumartist, "%s", .c_str()) MPD_PRINT_GENERATOR(album, "%s", .c_str()) MPD_PRINT_GENERATOR(date, "%s", .c_str()) MPD_PRINT_GENERATOR(random, "%s", .c_str()) MPD_PRINT_GENERATOR(repeat, "%s", .c_str()) MPD_PRINT_GENERATOR(track, "%s", .c_str()) MPD_PRINT_GENERATOR(name, "%s", .c_str()) MPD_PRINT_GENERATOR(file, "%s", .c_str()) MPD_PRINT_GENERATOR(vol, "%d", ) MPD_PRINT_GENERATOR(bitrate, "%d", ) MPD_PRINT_GENERATOR(status, "%s", .c_str()) #undef MPD_PRINT_GENERATOR conky-1.10.1/src/mpd.h000066400000000000000000000040661262311664100144450ustar00rootroot00000000000000/* -*- 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-2012 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 MPD_H_ #define MPD_H_ /* text object functions */ void print_mpd_elapsed(struct text_object *, char *, int); void print_mpd_length(struct text_object *, char *, int); uint8_t mpd_percentage(struct text_object *); double mpd_barval(struct text_object *); void print_mpd_smart(struct text_object *, char *, int); void print_mpd_title(struct text_object *, char *, int); void print_mpd_artist(struct text_object *, char *, int); void print_mpd_albumartist(struct text_object *, char *, int); void print_mpd_album(struct text_object *, char *, int); void print_mpd_date(struct text_object *, char *, int); void print_mpd_random(struct text_object *, char *, int); void print_mpd_repeat(struct text_object *, char *, int); void print_mpd_track(struct text_object *, char *, int); void print_mpd_name(struct text_object *, char *, int); void print_mpd_file(struct text_object *, char *, int); void print_mpd_vol(struct text_object *, char *, int); void print_mpd_bitrate(struct text_object *, char *, int); void print_mpd_status(struct text_object *, char *, int); int check_mpd_playing(struct text_object *); #endif /*MPD_H_*/ conky-1.10.1/src/mysql.cc000066400000000000000000000051301262311664100151610ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 "mysql.h" #include #include "setting.hh" namespace { conky::simple_config_setting host("mysql_host", "localhost", false); conky::range_config_setting port("mysql_port", 0, 0xffff, 0, false); conky::simple_config_setting user("mysql_user", "root", false); conky::simple_config_setting password("mysql_password", std::string(), false); conky::simple_config_setting db("mysql_db", "mysql", false); } void print_mysql(struct text_object *obj, char *p, int p_max_size) { MYSQL *conn = mysql_init(NULL); if(conn == NULL) { NORM_ERR("Can't initialize MySQL"); mysql_library_end(); return; } if (!mysql_real_connect(conn, host.get(*state).c_str(), user.get(*state).c_str(), password.get(*state).c_str(), db.get(*state).c_str(), port.get(*state), NULL, 0)) { NORM_ERR("MySQL: %s", mysql_error(conn)); mysql_close(conn); mysql_library_end(); return; } if(mysql_query(conn, obj->data.s)) { NORM_ERR("MySQL: %s", mysql_error(conn)); mysql_close(conn); mysql_library_end(); return; } MYSQL_RES *res = mysql_use_result(conn); if(res == NULL) { NORM_ERR("MySQL: %s", mysql_error(conn)); mysql_close(conn); mysql_library_end(); return; } MYSQL_ROW row = mysql_fetch_row(res); if(row) { snprintf(p, p_max_size, "%s", row[0]); } else { NORM_ERR("MySQL: '%s' returned no results", obj->data.s); } mysql_free_result(res); mysql_close(conn); mysql_library_end(); } conky-1.10.1/src/mysql.h000066400000000000000000000020671262311664100150310ustar00rootroot00000000000000/* -*- 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-2012 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 MYSQL_H_ #define MYSQL_H_ void print_mysql(struct text_object *, char *, int); #endif /*MYSQL_H_*/ conky-1.10.1/src/nc.cc000066400000000000000000000012071262311664100144150ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp */ #include #include "nc.h" namespace priv { void out_to_ncurses_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && do_convert(l, -1).first) { initscr(); start_color(); } ++s; } void out_to_ncurses_setting::cleanup(lua::state &l) { lua::stack_sentry s(l, -1); if(do_convert(l, -1).first) endwin(); l.pop(); } } priv::out_to_ncurses_setting out_to_ncurses; conky-1.10.1/src/nc.h000066400000000000000000000013341262311664100142600ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp */ #if defined(BUILD_NCURSES) && !defined(CONKY_NC_H) #define CONKY_NC_H #include #include "setting.hh" #ifdef LEAKFREE_NCURSES extern "C" { void _nc_free_and_exit(int); } #endif namespace priv { class out_to_ncurses_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); virtual void cleanup(lua::state &l); public: out_to_ncurses_setting() : Base("out_to_ncurses", false, false) {} }; } extern priv::out_to_ncurses_setting out_to_ncurses; #endif /* CONKY_NC_H */ conky-1.10.1/src/net_stat.cc000066400000000000000000000324021262311664100156370ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "logging.h" #include "specials.h" #include "net/if.h" #include "text_object.h" #include "net_stat.h" #include #include #include #include #include /* network interface stuff */ enum if_up_strictness_ { IFUP_UP, IFUP_LINK, IFUP_ADDR }; template<> conky::lua_traits::Map conky::lua_traits::map = { { "up", IFUP_UP }, { "link", IFUP_LINK }, { "address", IFUP_ADDR } }; static conky::simple_config_setting if_up_strictness("if_up_strictness", IFUP_UP, true); struct net_stat netstats[MAX_NET_INTERFACES]; struct net_stat *get_net_stat(const char *dev, void *free_at_crash1, void *free_at_crash2) { unsigned int i; if (!dev) { return 0; } /* find interface stat */ for (i = 0; i < MAX_NET_INTERFACES; i++) { if (netstats[i].dev && strcmp(netstats[i].dev, dev) == 0) { return &netstats[i]; } } /* wasn't found? add it */ for (i = 0; i < MAX_NET_INTERFACES; i++) { if (netstats[i].dev == 0) { netstats[i].dev = strndup(dev, text_buffer_size.get(*state)); return &netstats[i]; } } CRIT_ERR(free_at_crash1, free_at_crash2, "too many interfaces used (limit is %d)", MAX_NET_INTERFACES); return 0; } void parse_net_stat_arg(struct text_object *obj, const char *arg, void *free_at_crash) { bool shownetmask = false; bool showscope = false; char nextarg[21]; //longest arg possible is a devname (max 20 chars) int i=0; struct net_stat *netstat = NULL; if (!arg) arg = DEFAULTNETDEV; while(sscanf(arg+i, " %20s", nextarg) == 1) { if(strcmp(nextarg, "-n") == 0 || strcmp(nextarg, "--netmask") == 0) shownetmask = true; else if(strcmp(nextarg, "-s") == 0 || strcmp(nextarg, "--scope") == 0) showscope = true; else if(nextarg[0]=='-') { //multiple flags in 1 arg for(int j=1; nextarg[j] != 0; j++) { if(nextarg[j]=='n') shownetmask = true; if(nextarg[j]=='s') showscope = true; } } else netstat = get_net_stat(nextarg, obj, free_at_crash); i+=strlen(nextarg); //skip this arg while( ! (isspace(arg[i]) || arg[i] == 0)) i++; //and skip the spaces in front of it } if(netstat == NULL) netstat = get_net_stat(DEFAULTNETDEV, obj, free_at_crash); #ifdef BUILD_IPV6 netstat->v6show_nm = shownetmask; netstat->v6show_sc = showscope; #endif /* BUILD_IPV6 */ obj->data.opaque = netstat; } void parse_net_stat_bar_arg(struct text_object *obj, const char *arg, void *free_at_crash) { if (arg) { arg = scan_bar(obj, arg, 1); obj->data.opaque = get_net_stat(arg, obj, free_at_crash); } else { // default to DEFAULTNETDEV char *buf = strndup(DEFAULTNETDEV, text_buffer_size.get(*state)); obj->data.opaque = get_net_stat(buf, obj, free_at_crash); free(buf); } } void print_downspeed(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; human_readable(ns->recv_speed, p, p_max_size); } void print_downspeedf(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; spaced_print(p, p_max_size, "%.1f", 8, ns->recv_speed / 1024.0); } void print_upspeed(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; human_readable(ns->trans_speed, p, p_max_size); } void print_upspeedf(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; spaced_print(p, p_max_size, "%.1f", 8, ns->trans_speed / 1024.0); } void print_totaldown(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; human_readable(ns->recv, p, p_max_size); } void print_totalup(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; human_readable(ns->trans, p, p_max_size); } void print_addr(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->addr.sa_data[2] & 255) == 0 && (ns->addr.sa_data[3] & 255) == 0 && (ns->addr.sa_data[4] & 255) == 0 && (ns->addr.sa_data[5] & 255) == 0) { snprintf(p, p_max_size, "No Address"); } else { snprintf(p, p_max_size, "%u.%u.%u.%u", ns->addr.sa_data[2] & 255, ns->addr.sa_data[3] & 255, ns->addr.sa_data[4] & 255, ns->addr.sa_data[5] & 255); } } #ifdef __linux__ void print_addrs(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; if (NULL != ns->addrs && strlen(ns->addrs) > 2) { ns->addrs[strlen(ns->addrs) - 2] = 0; /* remove ", " from end of string */ strncpy(p, ns->addrs, p_max_size); } else { strncpy(p, "0.0.0.0", p_max_size); } } #ifdef BUILD_IPV6 void print_v6addrs(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; char tempaddress[INET6_ADDRSTRLEN]; struct v6addr *current_v6 = ns->v6addrs; if (!ns) return; if(p_max_size == 0) return; if( ! ns->v6addrs) { snprintf(p, p_max_size, "No Address"); return; } *p=0; while(current_v6) { inet_ntop(AF_INET6, &(current_v6->addr), tempaddress, INET6_ADDRSTRLEN); strncat(p, tempaddress, p_max_size); //netmask if(ns->v6show_nm) { char netmaskstr[5]; //max 5 chars (/128 + null-terminator) sprintf(netmaskstr, "/%u", current_v6->netmask); strncat(p, netmaskstr, p_max_size); } //scope if(ns->v6show_sc) { char scopestr[3]; sprintf(scopestr, "(%c)", current_v6->scope); strncat(p, scopestr, p_max_size); } //next (or last) address current_v6 = current_v6->next; if(current_v6) strncat(p, ", ", p_max_size); } } #endif /* BUILD_IPV6 */ #endif /* __linux__ */ #ifdef BUILD_X11 void parse_net_stat_graph_arg(struct text_object *obj, const char *arg, void *free_at_crash) { char *buf = 0; buf = scan_graph(obj, arg, 0); // default to DEFAULTNETDEV if (buf) { obj->data.opaque = get_net_stat(buf, obj, free_at_crash); free(buf); return; } obj->data.opaque = get_net_stat(DEFAULTNETDEV, obj, free_at_crash); } double downspeedgraphval(struct text_object *obj) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; return (ns ? (ns->recv_speed / 1024.0) : 0); } double upspeedgraphval(struct text_object *obj) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; return (ns ? (ns->trans_speed / 1024.0) : 0); } #endif /* BUILD_X11 */ #ifdef BUILD_WLAN void print_wireless_essid(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) { for(unsigned int i = 0; *(netstats[i].dev) != 0; i++) { if(*(netstats[i].essid) != 0) { snprintf(p, p_max_size, "%s", netstats[i].essid); return; } } return; } snprintf(p, p_max_size, "%s", ns->essid); } void print_wireless_mode(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; 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; if (!ns) return; snprintf(p, p_max_size, "%s", ns->bitrate); } void print_wireless_ap(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; snprintf(p, p_max_size, "%s", ns->ap); } void print_wireless_link_qual(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; spaced_print(p, p_max_size, "%d", 4, ns->link_qual); } void print_wireless_link_qual_max(struct text_object *obj, char *p, int p_max_size) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return; spaced_print(p, p_max_size, "%d", 4, ns->link_qual_max); } void print_wireless_link_qual_perc(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->link_qual_max > 0) { spaced_print(p, p_max_size, "%.0f", 5, (double) ns->link_qual / ns->link_qual_max * 100); } else { spaced_print(p, p_max_size, "unk", 5); } } double wireless_link_barval(struct text_object *obj) { struct net_stat *ns = (struct net_stat *)obj->data.opaque; if (!ns) return 0; return (double)ns->link_qual / ns->link_qual_max; } #endif /* BUILD_WLAN */ void clear_net_stats(void) { #ifdef BUILD_IPV6 struct v6addr *nextv6; #endif /* BUILD_IPV6 */ int i; for (i = 0; i < MAX_NET_INTERFACES; i++) { free_and_zero(netstats[i].dev); #ifdef BUILD_IPV6 while(netstats[i].v6addrs) { nextv6 = netstats[i].v6addrs; netstats[i].v6addrs = netstats[i].v6addrs->next; free_and_zero(nextv6); } #endif /* BUILD_IPV6 */ } memset(netstats, 0, sizeof(netstats)); } void parse_if_up_arg(struct text_object *obj, const char *arg) { obj->data.opaque = strndup(arg, text_buffer_size.get(*state)); } void free_if_up(struct text_object *obj) { free_and_zero(obj->data.opaque); } /* We should check if this is ok with OpenBSD and NetBSD as well. */ int interface_up(struct text_object *obj) { int fd; struct ifreq ifr; char *dev = (char*)obj->data.opaque; if (!dev) return 0; if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { CRIT_ERR(NULL, NULL, "could not create sockfd"); return 0; } strncpy(ifr.ifr_name, dev, IFNAMSIZ); if (ioctl(fd, SIOCGIFFLAGS, &ifr)) { /* if device does not exist, treat like not up */ if (errno != ENODEV && errno != ENXIO) perror("SIOCGIFFLAGS"); goto END_FALSE; } if (!(ifr.ifr_flags & IFF_UP)) /* iface is not up */ goto END_FALSE; if (if_up_strictness.get(*state) == IFUP_UP) goto END_TRUE; if (!(ifr.ifr_flags & IFF_RUNNING)) goto END_FALSE; if (if_up_strictness.get(*state) == IFUP_LINK) goto END_TRUE; if (ioctl(fd, SIOCGIFADDR, &ifr)) { perror("SIOCGIFADDR"); goto END_FALSE; } if (((struct sockaddr_in *)&(ifr.ifr_ifru.ifru_addr))->sin_addr.s_addr) goto END_TRUE; END_FALSE: close(fd); return 0; END_TRUE: close(fd); return 1; } struct _dns_data { _dns_data() : nscount(0), ns_list(0) {} int nscount; char **ns_list; }; static _dns_data dns_data; void free_dns_data(struct text_object *obj) { int i; (void)obj; for (i = 0; i < dns_data.nscount; i++) free(dns_data.ns_list[i]); free(dns_data.ns_list); memset(&dns_data, 0, sizeof(dns_data)); } int update_dns_data(void) { FILE *fp; char line[256]; //static double last_dns_update = 0.0; /* 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 0; last_dns_update = current_update_time; */ free_dns_data(NULL); if ((fp = fopen("/etc/resolv.conf", "r")) == NULL) return 0; while(!feof(fp)) { if (fgets(line, 255, fp) == NULL) { break; } if (!strncmp(line, "nameserver ", 11)) { line[strlen(line) - 1] = '\0'; // remove trailing newline dns_data.nscount++; dns_data.ns_list = (char**)realloc(dns_data.ns_list, dns_data.nscount * sizeof(char *)); dns_data.ns_list[dns_data.nscount - 1] = strndup(line + 11, text_buffer_size.get(*state)); } } fclose(fp); return 0; } void parse_nameserver_arg(struct text_object *obj, const char *arg) { obj->data.l = arg ? atoi(arg) : 0; } void print_nameserver(struct text_object *obj, char *p, int p_max_size) { if (dns_data.nscount > obj->data.l) snprintf(p, p_max_size, "%s", dns_data.ns_list[obj->data.l]); } conky-1.10.1/src/net_stat.h000066400000000000000000000101051262311664100154750ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _NET_STAT_H #define _NET_STAT_H #include /* struct sockaddr */ #ifdef BUILD_IPV6 struct v6addr { struct in6_addr addr; unsigned int netmask; char scope; struct v6addr *next; }; #endif /* BUILD_IPV6 */ struct net_stat { char *dev; int up; long long last_read_recv, last_read_trans; long long recv, trans; double recv_speed, trans_speed; struct sockaddr addr; #ifdef BUILD_IPV6 struct v6addr *v6addrs; bool v6show_nm; bool v6show_sc; #endif /* BUILD_IPV6 */ #if defined(__linux__) char addrs[17 * MAX_NET_INTERFACES + 1]; #endif /* __linux__ */ 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; int link_qual_max; char ap[18]; }; extern struct net_stat netstats[]; struct net_stat *get_net_stat(const char *, void *, void *); void parse_net_stat_arg(struct text_object *, const char *, void *); void parse_net_stat_bar_arg(struct text_object *, const char *, void *); void print_downspeed(struct text_object *, char *, int); void print_downspeedf(struct text_object *, char *, int); void print_upspeed(struct text_object *, char *, int); void print_upspeedf(struct text_object *, char *, int); void print_totaldown(struct text_object *, char *, int); void print_totalup(struct text_object *, char *, int); void print_addr(struct text_object *, char *, int); #ifdef __linux__ void print_addrs(struct text_object *, char *, int); #ifdef BUILD_IPV6 void print_v6addrs(struct text_object *, char *, int); #endif /* BUILD_IPV6 */ #endif /* __linux__ */ #ifdef BUILD_X11 void parse_net_stat_graph_arg(struct text_object *, const char *, void *); double downspeedgraphval(struct text_object *); 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); void print_wireless_link_qual(struct text_object *, char *, int); void print_wireless_link_qual_max(struct text_object *, char *, int); void print_wireless_link_qual_perc(struct text_object *, char *, int); double wireless_link_barval(struct text_object *); #endif /* BUILD_WLAN */ void clear_net_stats(void); void parse_if_up_arg(struct text_object *, const char *); int interface_up(struct text_object *); void free_if_up(struct text_object *); void free_dns_data(struct text_object *); int update_dns_data(void); void parse_nameserver_arg(struct text_object *, const char *); void print_nameserver(struct text_object *, char *, int); #endif /* _NET_STAT_H */ conky-1.10.1/src/netbsd.cc000066400000000000000000000175611262311664100153060ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "netbsd.h" #include "net_stat.h" static kvm_t *kd = NULL; int kd_init = 0, nkd_init = 0; u_int32_t sensvalue; char errbuf[_POSIX2_LINE_MAX]; static int init_kvm(void) { if (kd_init) { return 0; } kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (kd == NULL) { warnx("cannot kvm_openfiles: %s", errbuf); return -1; } kd_init = 1; return 0; } static int swapmode(int *retavail, int *retfree) { int n; struct swapent *sep; *retavail = 0; *retfree = 0; n = swapctl(SWAP_NSWAP, 0, 0); if (n < 1) { warn("could not get swap information"); return 0; } sep = (struct swapent *) malloc(n * (sizeof(*sep))); if (sep == NULL) { warn("memory allocation failed"); return 0; } if (swapctl(SWAP_STATS, (void *) sep, n) < n) { warn("could not get swap stats"); return 0; } for (; n > 0; n--) { *retavail += (int) dbtob(sep[n - 1].se_nblks); *retfree += (int) dbtob(sep[n - 1].se_nblks - sep[n - 1].se_inuse); } *retavail = (int) (*retavail / 1024); *retfree = (int) (*retfree / 1024); return 1; } void prepare_update() { } void update_uptime() { int mib[2] = { CTL_KERN, KERN_BOOTTIME }; struct timeval boottime; time_t now; int size = sizeof(boottime); if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) && (boottime.tv_sec != 0)) { time(&now); info.uptime = now - boottime.tv_sec; } else { warn("could not get uptime"); info.uptime = 0; } } int check_mount(struct text_object *obj) { /* stub */ (void)obj; return 0; } void update_meminfo() { int mib[] = { CTL_VM, VM_UVMEXP2 }; int total_pages, inactive_pages, free_pages; int swap_avail, swap_free; const int pagesize = getpagesize(); struct uvmexp_sysctl uvmexp; size_t size = sizeof(uvmexp); if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) { warn("could not get memory info"); return; } total_pages = uvmexp.npages; free_pages = uvmexp.free; inactive_pages = uvmexp.inactive; info.memmax = (total_pages * pagesize) >> 10; info.mem = ((total_pages - free_pages - inactive_pages) * pagesize) >> 10; info.memwithbuffers = info.mem; info.memeasyfree = info.memfree = info.memmax - info.mem; if (swapmode(&swap_avail, &swap_free) >= 0) { info.swapmax = swap_avail; info.swap = (swap_avail - swap_free); info.swapfree = swap_free; } } void update_net_stats() { int i; double delta; struct ifnet ifnet; struct ifnet_head ifhead; /* interfaces are in a tail queue */ u_long ifnetaddr; static struct nlist namelist[] = { { "_ifnet" }, { NULL } }; static kvm_t *nkd; if (!nkd_init) { nkd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); if (nkd == NULL) { warnx("cannot kvm_openfiles: %s", errbuf); warnx("maybe you need to setgid kmem this program?"); return; } else if (kvm_nlist(nkd, namelist) != 0) { warn("cannot kvm_nlist"); return; } else { nkd_init = 1; } } if (kvm_read(nkd, (u_long) namelist[0].n_value, (void *) &ifhead, sizeof(ifhead)) < 0) { warn("cannot kvm_read"); return; } /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { return; } for (i = 0, ifnetaddr = (u_long) ifhead.tqh_first; ifnet.if_list.tqe_next && i < 16; ifnetaddr = (u_long) ifnet.if_list.tqe_next, i++) { struct net_stat *ns; long long last_recv, last_trans; kvm_read(nkd, (u_long) ifnetaddr, (void *) &ifnet, sizeof(ifnet)); ns = get_net_stat(ifnet.if_xname, NULL, NULL); ns->up = 1; last_recv = ns->recv; last_trans = ns->trans; if (ifnet.if_ibytes < ns->last_read_recv) { ns->recv += ((long long) 4294967295U - ns->last_read_recv) + ifnet.if_ibytes; } else { ns->recv += (ifnet.if_ibytes - ns->last_read_recv); } ns->last_read_recv = ifnet.if_ibytes; if (ifnet.if_obytes < ns->last_read_trans) { ns->trans += ((long long) 4294967295U - ns->last_read_trans) + ifnet.if_obytes; } else { ns->trans += (ifnet.if_obytes - ns->last_read_trans); } ns->last_read_trans = ifnet.if_obytes; ns->recv += (ifnet.if_ibytes - ns->last_read_recv); ns->last_read_recv = ifnet.if_ibytes; ns->trans += (ifnet.if_obytes - ns->last_read_trans); ns->last_read_trans = ifnet.if_obytes; ns->recv_speed = (ns->recv - last_recv) / delta; ns->trans_speed = (ns->trans - last_trans) / delta; } } void update_total_processes() { /* It's easier to use kvm here than sysctl */ int n_processes; info.procs = 0; if (init_kvm() < 0) { return; } else { kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &n_processes); } info.procs = n_processes; } void update_running_processes() { struct kinfo_proc2 *p; int n_processes; int i, cnt = 0; info.run_procs = 0; if (init_kvm() < 0) { return; } else { 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_stat == LSRUN || p[i].p_stat == LSIDL || p[i].p_stat == LSONPROC) { cnt++; } } } info.run_procs = cnt; } struct cpu_load_struct { unsigned long load[5]; }; struct cpu_load_struct fresh = { {0, 0, 0, 0, 0} }; long cpu_used, oldtotal, oldused; void update_cpu_usage() { long used, total; static u_int64_t cp_time[CPUSTATES]; size_t len = sizeof(cp_time); info.cpu_usage = 0; if (sysctlbyname("kern.cp_time", &cp_time, &len, NULL, 0) < 0) { warn("cannot get kern.cp_time"); } fresh.load[0] = cp_time[CP_USER]; fresh.load[1] = cp_time[CP_NICE]; fresh.load[2] = cp_time[CP_SYS]; fresh.load[3] = cp_time[CP_IDLE]; fresh.load[4] = cp_time[CP_IDLE]; used = fresh.load[0] + fresh.load[1] + fresh.load[2]; total = fresh.load[0] + fresh.load[1] + fresh.load[2] + fresh.load[3]; if ((total - oldtotal) != 0) { info.cpu_usage = ((double) (used - oldused)) / (double) (total - oldtotal); } else { info.cpu_usage = 0; } oldused = used; oldtotal = total; } void update_load_average() { double v[3]; getloadavg(v, 3); info.loadavg[0] = (float) v[0]; info.loadavg[1] = (float) v[1]; info.loadavg[2] = (float) v[2]; } double get_acpi_temperature(int fd) { return -1; } void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item) { } int open_acpi_temperature(const char *name) { return -1; } void get_acpi_ac_adapter(char *p_client_buffer, size_t client_buffer_size, const char *adapter) { (void) adapter; // only linux uses this if (!p_client_buffer || client_buffer_size <= 0) { return; } /* not implemented */ memset(p_client_buffer, 0, client_buffer_size); } /* char *get_acpi_fan() */ void get_acpi_fan(char *p_client_buffer, size_t client_buffer_size) { if (!p_client_buffer || client_buffer_size <= 0) { return; } /* not implemented */ memset(p_client_buffer, 0, client_buffer_size); } int get_entropy_avail(unsigned int *val) { return 1; } int get_entropy_poolsize(unsigned int *val) { return 1; } conky-1.10.1/src/netbsd.h000066400000000000000000000012361262311664100151400ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */ #ifndef NETBSD_H_ #define NETBSD_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conky.h" #include "common.h" int get_entropy_avail(unsigned int *); int get_entropy_poolsize(unsigned int *); #endif /*NETBSD_H_*/ conky-1.10.1/src/nvidia.cc000066400000000000000000000107641262311664100152770ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2008 Markus Meissner * Copyright (c) 2005-2012 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 "nvidia.h" #include "temphelper.h" #include "x11.h" #include const int nvidia_query_to_attr[] = {NV_CTRL_GPU_CORE_TEMPERATURE, NV_CTRL_GPU_CORE_THRESHOLD, NV_CTRL_AMBIENT_TEMPERATURE, NV_CTRL_GPU_CURRENT_CLOCK_FREQS, NV_CTRL_GPU_CURRENT_CLOCK_FREQS, NV_CTRL_IMAGE_SETTINGS}; typedef enum _QUERY_ID { NV_TEMP, NV_TEMP_THRESHOLD, NV_TEMP_AMBIENT, NV_GPU_FREQ, NV_MEM_FREQ, NV_IMAGE_QUALITY } QUERY_ID; struct nvidia_s { int interval; int print_as_float; QUERY_ID type; }; static Display *nvdisplay; namespace { class nvidia_display_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); virtual void cleanup(lua::state &l); public: nvidia_display_setting() : Base("nvidia_display", std::string(), false) {} }; void nvidia_display_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); std::string str = do_convert(l, -1).first; if(str.size()) { if ((nvdisplay = XOpenDisplay(str.c_str())) == NULL) { CRIT_ERR(NULL, NULL, "can't open nvidia display: %s", XDisplayName(str.c_str())); } } ++s; } void nvidia_display_setting::cleanup(lua::state &l) { lua::stack_sentry s(l, -1); if(nvdisplay) { XCloseDisplay(nvdisplay); nvdisplay = NULL; } l.pop(); } nvidia_display_setting nvidia_display; } static int get_nvidia_value(QUERY_ID qid){ int tmp; Display *dpy = nvdisplay ? nvdisplay : display; if(!dpy || !XNVCTRLQueryAttribute(dpy, 0, 0, nvidia_query_to_attr[qid], &tmp)){ return -1; } /* FIXME: when are the low 2 bytes of NV_GPU_FREQ needed? */ if (qid == NV_GPU_FREQ) return tmp >> 16; if (qid == NV_MEM_FREQ) return tmp & 0xFFFF; return tmp; } int set_nvidia_type(struct text_object *obj, const char *arg) { struct nvidia_s *nvs; obj->data.opaque = malloc(sizeof(struct nvidia_s)); nvs = static_cast(obj->data.opaque); memset(nvs, 0, sizeof(struct nvidia_s)); switch(arg[0]) { case 't': // temp or threshold nvs->print_as_float = 1; if (arg[1] == 'e') nvs->type = NV_TEMP; else if (arg[1] == 'h') nvs->type = NV_TEMP_THRESHOLD; else return 1; break; case 'a': // ambient temp nvs->print_as_float = 1; nvs->type = NV_TEMP_AMBIENT; break; case 'g': // gpufreq nvs->type = NV_GPU_FREQ; break; case 'm': // memfreq nvs->type = NV_MEM_FREQ; break; case 'i': // imagequality nvs->type = NV_IMAGE_QUALITY; break; default: return 1; } return 0; } void print_nvidia_value(struct text_object *obj, char *p, int p_max_size) { int value; struct nvidia_s *nvs = static_cast(obj->data.opaque); if (!nvs || (value = get_nvidia_value(nvs->type)) == -1) { snprintf(p, p_max_size, "N/A"); return; } if (nvs->type == NV_TEMP) temp_print(p, p_max_size, (double)value, TEMP_CELSIUS); else if (nvs->print_as_float && value > 0 && value < 100) snprintf(p, p_max_size, "%.1f", (float)value); else snprintf(p, p_max_size, "%d", value); } void free_nvidia(struct text_object *obj) { free_and_zero(obj->data.opaque); } conky-1.10.1/src/nvidia.h000066400000000000000000000025201262311664100151300ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2008 Markus Meissner * Copyright (c) 2005-2012 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 NVIDIA_CONKY_H #define NVIDIA_CONKY_H int set_nvidia_type(struct text_object *, const char *); void print_nvidia_value(struct text_object *, char *, int); void free_nvidia(struct text_object *); #endif conky-1.10.1/src/openbsd.cc000066400000000000000000000377021262311664100154600ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2007 Toni Spets * Copyright (c) 2005-2012 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conky.h" #include "diskio.h" #include "logging.h" #include "net_stat.h" #include "openbsd.h" #include "top.h" #define MAXSHOWDEVS 16 #define LOG1024 10 #define pagetok(size) ((size) << pageshift) inline void proc_find_top(struct process **cpu, struct process **mem); static short cpu_setup = 0; static kvm_t *kd = 0; struct ifmibdata *data = NULL; size_t len = 0; int init_kvm = 0; int init_sensors = 0; static int kvm_init() { if (init_kvm) { return 1; } kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); if (kd == NULL) { NORM_ERR("error opening kvm"); } else { init_kvm = 1; } return 1; } /* note: swapmode taken from 'top' source */ /* swapmode is rewritten by Tobias Weingartner * to be based on the new swapctl(2) system call. */ static int swapmode(int *used, int *total) { struct swapent *swdev; int nswap, rnswap, i; nswap = swapctl(SWAP_NSWAP, 0, 0); if (nswap == 0) { return 0; } swdev = malloc(nswap * sizeof(*swdev)); if (swdev == NULL) { return 0; } rnswap = swapctl(SWAP_STATS, swdev, nswap); if (rnswap == -1) { return 0; } /* if rnswap != nswap, then what? */ /* Total things up */ *total = *used = 0; for (i = 0; i < nswap; i++) { if (swdev[i].se_flags & SWF_ENABLE) { *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE)); *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE)); } } free(swdev); return 1; } int check_mount(struct text_object *obj) { /* stub */ (void)obj; return 0; } void update_uptime() { int mib[2] = { CTL_KERN, KERN_BOOTTIME }; struct timeval boottime; time_t now; size_t size = sizeof(boottime); if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) && (boottime.tv_sec != 0)) { time(&now); info.uptime = now - boottime.tv_sec; } else { NORM_ERR("Could not get uptime"); info.uptime = 0; } } void update_meminfo() { static int mib[2] = { CTL_VM, VM_METER }; struct vmtotal vmtotal; size_t size; int pagesize, pageshift, swap_avail, swap_used; pagesize = getpagesize(); pageshift = 0; while (pagesize > 1) { pageshift++; pagesize >>= 1; } /* we only need the amount of log(2)1024 for our conversion */ pageshift -= LOG1024; /* get total -- systemwide main memory usage structure */ size = sizeof(vmtotal); if (sysctl(mib, 2, &vmtotal, &size, NULL, 0) < 0) { warn("sysctl failed"); bzero(&vmtotal, sizeof(vmtotal)); } info.memmax = pagetok(vmtotal.t_rm) + pagetok(vmtotal.t_free); info.mem = info.memwithbuffers = pagetok(vmtotal.t_rm); info.memeasyfree = info.memfree = info.memmax - info.mem; if ((swapmode(&swap_used, &swap_avail)) >= 0) { info.swapmax = swap_avail; info.swap = swap_used; info.swapfree = swap_avail - swap_used; } else { info.swapmax = 0; info.swap = 0; info.swapfree = 0; } } void update_net_stats() { struct net_stat *ns; double delta; long long r, t, last_recv, last_trans; struct ifaddrs *ifap, *ifa; struct if_data *ifd; /* get delta */ delta = current_update_time - last_update_time; if (delta <= 0.0001) { return; } if (getifaddrs(&ifap) < 0) { return; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ns = get_net_stat((const char *) ifa->ifa_name, NULL, NULL); if (ifa->ifa_flags & IFF_UP) { struct ifaddrs *iftmp; ns->up = 1; last_recv = ns->recv; last_trans = ns->trans; if (ifa->ifa_addr->sa_family != AF_LINK) { continue; } for (iftmp = ifa->ifa_next; iftmp != NULL && strcmp(ifa->ifa_name, iftmp->ifa_name) == 0; iftmp = iftmp->ifa_next) { if (iftmp->ifa_addr->sa_family == AF_INET) { memcpy(&(ns->addr), iftmp->ifa_addr, iftmp->ifa_addr->sa_len); } } ifd = (struct if_data *) ifa->ifa_data; r = ifd->ifi_ibytes; t = ifd->ifi_obytes; if (r < ns->last_read_recv) { ns->recv += ((long long) 4294967295U - ns->last_read_recv) + r; } else { ns->recv += (r - ns->last_read_recv); } ns->last_read_recv = r; if (t < ns->last_read_trans) { ns->trans += (long long) 4294967295U - ns->last_read_trans + t; } else { ns->trans += (t - ns->last_read_trans); } ns->last_read_trans = t; /* calculate speeds */ ns->recv_speed = (ns->recv - last_recv) / delta; ns->trans_speed = (ns->trans - last_trans) / delta; } else { ns->up = 0; } } freeifaddrs(ifap); } void update_total_processes() { int n_processes; kvm_init(); kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes); info.procs = n_processes; } void update_running_processes() { struct kinfo_proc2 *p; int n_processes; int i, cnt = 0; kvm_init(); int max_size = sizeof(struct kinfo_proc2); p = kvm_getproc2(kd, KERN_PROC_ALL, 0, max_size, &n_processes); for (i = 0; i < n_processes; i++) { if (p[i].p_stat == SRUN) { cnt++; } } info.run_procs = cnt; } /* new SMP code can be enabled by commenting the following line */ #define OLDCPU #ifdef OLDCPU struct cpu_load_struct { unsigned long load[5]; }; struct cpu_load_struct fresh = { {0, 0, 0, 0, 0} }; long cpu_used, oldtotal, oldused; #else #include int64_t *fresh = NULL; /* XXX is 8 enough? - What's the constant for MAXCPU? */ /* allocate this with malloc would be better */ int64_t oldtotal[8], oldused[8]; #endif void get_cpu_count() { int cpu_count = 1; /* default to 1 cpu */ #ifndef OLDCPU int mib[2] = { CTL_HW, HW_NCPU }; size_t len = sizeof(cpu_count); if (sysctl(mib, 2, &cpu_count, &len, NULL, 0) != 0) { NORM_ERR("error getting cpu count, defaulting to 1"); } #endif info.cpu_count = cpu_count; info.cpu_usage = malloc(info.cpu_count * sizeof(float)); if (info.cpu_usage == NULL) { CRIT_ERR(NULL, NULL, "malloc"); } #ifndef OLDCPU assert(fresh == NULL); /* XXX Is this leaking memory? */ /* XXX Where shall I free this? */ if (NULL == (fresh = calloc(cpu_count, sizeof(int64_t) * CPUSTATES))) { CRIT_ERR(NULL, NULL, "calloc"); } #endif } void update_cpu_usage() { #ifdef OLDCPU int mib[2] = { CTL_KERN, KERN_CPTIME }; long used, total; long cp_time[CPUSTATES]; size_t len = sizeof(cp_time); #else size_t size; unsigned int i; #endif /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */ if ((cpu_setup == 0) || (!info.cpu_usage)) { get_cpu_count(); cpu_setup = 1; } #ifdef OLDCPU if (sysctl(mib, 2, &cp_time, &len, NULL, 0) < 0) { NORM_ERR("Cannot get kern.cp_time"); } fresh.load[0] = cp_time[CP_USER]; fresh.load[1] = cp_time[CP_NICE]; fresh.load[2] = cp_time[CP_SYS]; fresh.load[3] = cp_time[CP_IDLE]; fresh.load[4] = cp_time[CP_IDLE]; used = fresh.load[0] + fresh.load[1] + fresh.load[2]; total = fresh.load[0] + fresh.load[1] + fresh.load[2] + fresh.load[3]; if ((total - oldtotal) != 0) { info.cpu_usage[0] = ((double) (used - oldused)) / (double) (total - oldtotal); } else { info.cpu_usage[0] = 0; } oldused = used; oldtotal = total; #else if (info.cpu_count > 1) { size = CPUSTATES * sizeof(int64_t); for (i = 0; i < info.cpu_count; i++) { int cp_time_mib[] = { CTL_KERN, KERN_CPTIME2, i }; if (sysctl(cp_time_mib, 3, &(fresh[i * CPUSTATES]), &size, NULL, 0) < 0) { NORM_ERR("sysctl kern.cp_time2 failed"); } } } else { int cp_time_mib[] = { CTL_KERN, KERN_CPTIME }; long cp_time_tmp[CPUSTATES]; size = sizeof(cp_time_tmp); if (sysctl(cp_time_mib, 2, cp_time_tmp, &size, NULL, 0) < 0) { NORM_ERR("sysctl kern.cp_time failed"); } for (i = 0; i < CPUSTATES; i++) { fresh[i] = (int64_t) cp_time_tmp[i]; } } /* XXX Do sg with this int64_t => long => double ? float hell. */ for (i = 0; i < info.cpu_count; i++) { int64_t used, total; int at = i * CPUSTATES; used = fresh[at + CP_USER] + fresh[at + CP_NICE] + fresh[at + CP_SYS]; total = used + fresh[at + CP_IDLE]; if ((total - oldtotal[i]) != 0) { info.cpu_usage[i] = ((double) (used - oldused[i])) / (double) (total - oldtotal[i]); } else { info.cpu_usage[i] = 0; } oldused[i] = used; oldtotal[i] = total; } #endif } void update_load_average() { double v[3]; getloadavg(v, 3); info.loadavg[0] = (float) v[0]; info.loadavg[1] = (float) v[1]; info.loadavg[2] = (float) v[2]; } #define OBSD_MAX_SENSORS 256 static struct obsd_sensors_struct { int device; float temp[MAXSENSORDEVICES][OBSD_MAX_SENSORS]; unsigned int fan[MAXSENSORDEVICES][OBSD_MAX_SENSORS]; float volt[MAXSENSORDEVICES][OBSD_MAX_SENSORS]; } obsd_sensors; static conky::simple_config_setting sensor_device("sensor_device", 0, false); /* read sensors from sysctl */ void update_obsd_sensors() { int sensor_cnt, dev, numt, mib[5] = { CTL_HW, HW_SENSORS, 0, 0, 0 }; struct sensor sensor; struct sensordev sensordev; size_t slen, sdlen; enum sensor_type type; slen = sizeof(sensor); sdlen = sizeof(sensordev); sensor_cnt = 0; dev = obsd_sensors.device; // FIXME: read more than one device /* for (dev = 0; dev < MAXSENSORDEVICES; dev++) { */ mib[2] = dev; if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) { if (errno != ENOENT) { warn("sysctl"); } return; // continue; } for (type = 0; type < SENSOR_MAX_TYPES; type++) { mib[3] = type; for (numt = 0; numt < sensordev.maxnumt[type]; numt++) { mib[4] = numt; if (sysctl(mib, 5, &sensor, &slen, NULL, 0) == -1) { if (errno != ENOENT) { warn("sysctl"); } continue; } if (sensor.flags & SENSOR_FINVALID) { continue; } switch (type) { case SENSOR_TEMP: obsd_sensors.temp[dev][sensor.numt] = (sensor.value - 273150000) / 1000000.0; break; case SENSOR_FANRPM: obsd_sensors.fan[dev][sensor.numt] = sensor.value; break; case SENSOR_VOLTS_DC: obsd_sensors.volt[dev][sensor.numt] = sensor.value / 1000000.0; break; default: break; } sensor_cnt++; } } /* } */ init_sensors = 1; } void parse_obsd_sensor(struct text_object *obj, const char *arg) { if (!isdigit(arg[0]) || atoi(&arg[0]) < 0 || atoi(&arg[0]) > OBSD_MAX_SENSORS - 1) { obj->data.l = 0; NORM_ERR("Invalid sensor number!"); } else obj->data.l = atoi(&arg[0]); } void print_obsd_sensors_temp(struct text_object *obj, char *p, int p_max_size) { obsd_sensors.device = sensor_device.get(*state); update_obsd_sensors(); temp_print(p, p_max_size, obsd_sensors.temp[obsd_sensors.device][obj->data.l], TEMP_CELSIUS); } void print_obsd_sensors_fan(struct text_object *obj, char *p, int p_max_size) { obsd_sensors.device = sensor_device.get(*state); update_obsd_sensors(); snprintf(p, p_max_size, "%d", obsd_sensors.fan[obsd_sensors.device][obj->data.l]); } void print_obsd_sensors_volt(struct text_object *obj, char *p, int p_max_size) { obsd_sensors.device = sensor_device.get(*state); update_obsd_sensors(); snprintf(p, p_max_size, "%.2f", obsd_sensors.volt[obsd_sensors.device][obj->data.l]); } /* chipset vendor */ void get_obsd_vendor(struct text_object *obj, char *buf, size_t client_buffer_size) { int mib[2]; char vendor[64]; size_t size = sizeof(vendor); (void)obj; mib[0] = CTL_HW; mib[1] = HW_VENDOR; if (sysctl(mib, 2, vendor, &size, NULL, 0) == -1) { NORM_ERR("error reading vendor"); snprintf(buf, client_buffer_size, "unknown"); } else { snprintf(buf, client_buffer_size, "%s", vendor); } } /* chipset name */ void get_obsd_product(struct text_object *obj, char *buf, size_t client_buffer_size) { int mib[2]; char product[64]; size_t size = sizeof(product); (void)obj; mib[0] = CTL_HW; mib[1] = HW_PRODUCT; if (sysctl(mib, 2, product, &size, NULL, 0) == -1) { NORM_ERR("error reading product"); snprintf(buf, client_buffer_size, "unknown"); } else { snprintf(buf, client_buffer_size, "%s", product); } } /* void */ char get_freq(char *p_client_buffer, size_t client_buffer_size, const char *p_format, int divisor, unsigned int cpu) { int freq = cpu; int mib[2] = { CTL_HW, HW_CPUSPEED }; if (!p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0) { return 0; } size_t size = sizeof(freq); if (sysctl(mib, 2, &freq, &size, NULL, 0) == 0) { snprintf(p_client_buffer, client_buffer_size, p_format, (float) freq / divisor); } else { snprintf(p_client_buffer, client_buffer_size, p_format, 0.0f); } return 1; } #if 0 /* deprecated, will rewrite this soon in update_net_stats() -hifi */ void update_wifi_stats() { struct net_stat *ns; struct ifaddrs *ifap, *ifa; struct ifmediareq ifmr; struct ieee80211_nodereq nr; struct ieee80211_bssid bssid; int s, ibssid; /* Get iface table */ if (getifaddrs(&ifap) < 0) { return; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ns = get_net_stat((const char *) ifa->ifa_name); s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get media type */ bzero(&ifmr, sizeof(ifmr)); strlcpy(ifmr.ifm_name, ifa->ifa_name, IFNAMSIZ); if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { close(s); return; } /* We can monitor only wireless interfaces * which are not in hostap mode */ if ((ifmr.ifm_active & IFM_IEEE80211) && !(ifmr.ifm_active & IFM_IEEE80211_HOSTAP)) { /* Get wi status */ memset(&bssid, 0, sizeof(bssid)); strlcpy(bssid.i_name, ifa->ifa_name, sizeof(bssid.i_name)); ibssid = ioctl(s, SIOCG80211BSSID, &bssid); bzero(&nr, sizeof(nr)); bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr)); strlcpy(nr.nr_ifname, ifa->ifa_name, sizeof(nr.nr_ifname)); if (ioctl(s, SIOCG80211NODE, &nr) == 0 && nr.nr_rssi) { ns->linkstatus = nr.nr_rssi; } } cleanup: close(s); } } #endif void clear_diskio_stats() { } struct diskio_stat *prepare_diskio_stat(const char *s) { } void update_diskio() { return; /* XXX: implement? hifi: not sure how */ } /* While topless is obviously better, top is also not bad. */ void get_top_info(void) { struct kinfo_proc2 *p; struct process *proc; int n_processes; int i; kvm_init(); 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) { 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 */ } } } /* empty stubs so conky links */ void prepare_update() { } int get_entropy_avail(unsigned int *val) { return 1; } int get_entropy_poolsize(unsigned int *val) { return 1; } conky-1.10.1/src/openbsd.h000066400000000000000000000015231262311664100153120ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */ #ifndef OPENBSD_H_ #define OPENBSD_H_ #include "common.h" #include #include #include #include void parse_obsd_sensor(struct text_object *, const char *); void print_obsd_sensors_temp(struct text_object *, char *, int); void print_obsd_sensors_fan(struct text_object *, char *, int); void print_obsd_sensors_volt(struct text_object *, char *, int); void get_obsd_vendor(struct text_object *, char *buf, size_t client_buffer_size); void get_obsd_product(struct text_object *, char *buf, size_t client_buffer_size); #if defined(i386) || defined(__i386__) typedef struct apm_power_info *apm_info_t; #endif int get_entropy_avail(unsigned int *); int get_entropy_poolsize(unsigned int *); #endif /*OPENBSD_H_*/ conky-1.10.1/src/prioqueue.cc000066400000000000000000000125721262311664100160420ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * prioqueue: a simple priority queue implementation * * The queue organises it's data internally using a doubly linked * list, into which elements are inserted at the right position. This * is definitely not the best algorithm for a priority queue, but it * fits best for the given purpose, i.e. the top process sorting. * This means we have a rather little amount of total elements (~200 * on a normal system), which are to be inserted into a queue of only * the few top-most elements (10 at the current state). Additionally, * at each update interval, the queue is drained completely and * refilled from scratch. * * Copyright (C) 2009 Phil Sutter * * Initially based on the former implementation of sorted processes in * top.c, Copyright (C) 2005 David Carter * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "conky.h" #include /* INT_MAX */ #include #include struct prio_elem { struct prio_elem *next, *prev; void *data; }; struct prio_queue { /* Compare a and b. Return: * <0 if a should come before b, * >0 if b should come before a, * 0 if don't care */ int (*compare)(void *a, void *b); /* Free element payload. Called when dropping elements. */ void (*free)(void *a); /* Maximum size of queue. The first * elements in the list take precedence. */ int max_size; /* The pointers to the actual list. */ struct prio_elem *head, *tail; /* The current number of elements in the list. */ int cur_size; }; /* nop callback to save us from conditional calling */ static void pq_free_nop(void *a) { (void)a; } struct prio_queue *init_prio_queue(void) { struct prio_queue *retval; retval = (struct prio_queue *) malloc(sizeof(struct prio_queue)); memset(retval, 0, sizeof(struct prio_queue)); /* use pq_free_nop by default */ retval->free = &pq_free_nop; /* Default to maximum possible size as restricted * by the used data type. This also saves us from * checking if caller has set this field or not. */ retval->max_size = INT_MAX; return retval; } void pq_set_compare(struct prio_queue *queue, int (*pqcompare)(void *a, void *b)) { if (pqcompare) queue->compare = pqcompare; } void pq_set_free(struct prio_queue *queue, void (*pqfree)(void *a)) { if (pqfree) queue->free = pqfree; } void pq_set_max_size(struct prio_queue *queue, int max_size) { if (max_size >= 0) queue->max_size = max_size; } int pq_get_cur_size(struct prio_queue *queue) { return queue->cur_size; } static struct prio_elem *init_prio_elem(void *data) { struct prio_elem *retval; retval = (struct prio_elem *) malloc(sizeof(struct prio_elem)); memset(retval, 0, sizeof(struct prio_elem)); retval->data = data; return retval; } void insert_prio_elem(struct prio_queue *queue, void *data) { struct prio_elem *cur; /* queue->compare is a must-have */ if (!queue->compare) return; /* empty queue, insert the first item */ if (!queue->cur_size) { queue->cur_size++; queue->head = queue->tail = init_prio_elem(data); return; } /* short-cut 1: new item is lower than all others */ if (queue->compare(queue->tail->data, data) <= 0) { if (queue->cur_size < queue->max_size) { queue->cur_size++; queue->tail->next = init_prio_elem(data); queue->tail->next->prev = queue->tail; queue->tail = queue->tail->next; } else /* list was already full */ (*queue->free)(data); return; } /* short-cut 2: we have a new maximum */ if (queue->compare(queue->head->data, data) >= 0) { queue->cur_size++; queue->head->prev = init_prio_elem(data); queue->head->prev->next = queue->head; queue->head = queue->head->prev; goto check_cur_size; } /* find the actual position if short-cuts failed */ for (cur = queue->head->next; cur; cur = cur->next) { if (queue->compare(cur->data, data) >= 0) { queue->cur_size++; cur->prev->next = init_prio_elem(data); cur->prev->next->prev = cur->prev; cur->prev->next->next = cur; cur->prev = cur->prev->next; break; } } check_cur_size: /* drop the lowest item if queue overrun */ if (queue->cur_size > queue->max_size) { queue->cur_size--; queue->tail = queue->tail->prev; (*queue->free)(queue->tail->next->data); free_and_zero(queue->tail->next); } } void *pop_prio_elem(struct prio_queue *queue) { struct prio_elem *tmp; void *data; if (queue->cur_size <= 0) return NULL; tmp = queue->head; data = tmp->data; queue->head = queue->head->next; queue->cur_size--; if (queue->head) queue->head->prev = NULL; else /* list is now empty */ queue->tail = NULL; free(tmp); return data; } void free_prio_queue(struct prio_queue *queue) { void *data; while((data = pop_prio_elem(queue))) (*queue->free)(data); free(queue); } conky-1.10.1/src/prioqueue.h000066400000000000000000000043531262311664100157020ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * prioqueue: a simple priority queue implementation * * Copyright (C) 2009 Phil Sutter * * Initially based on the former implementation of sorted processes in * top.c, Copyright (C) 2005 David Carter * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef _PRIOQUEUE_H #define _PRIOQUEUE_H /* forward-define for private data */ struct prio_queue; /* typedef for a distinct prioqueue object */ typedef struct prio_queue *prio_queue_t; /* initialise a prioqueue object (mandatory) */ prio_queue_t init_prio_queue(void); /* set the compare function (mandatory) * (*compare) shall return: * <0 if a should come before b, * >0 if b should come before a, * 0 if doesn't matter */ void pq_set_compare(prio_queue_t, int (*compare)(void *a, void *b)); /* set the data free function (optional) * (*free) will be called when: * - dropping elements from the end of a limited size queue and * - free_prio_queue() finds leftover elements in the given queue */ void pq_set_free(prio_queue_t, void (*free)(void *)); /* set a maximum queue size (optional) (defaults to INT_MAX) */ void pq_set_max_size(prio_queue_t, int); /* insert an element into the given queue */ void insert_prio_elem(prio_queue_t, void *); /* return the number of elements in the queue */ int pq_get_cur_size(prio_queue_t queue); /* pop the top-most element from the queue * returns NULL if queue is empty */ void *pop_prio_elem(prio_queue_t); /* clear and free the given queue */ void free_prio_queue(prio_queue_t); #endif /* _PRIOQUEUE_H */ conky-1.10.1/src/proc.cc000066400000000000000000000670651262311664100147760ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "core.h" #include "logging.h" #include "proc.h" #include #include #include #include pid_t strtopid(const char *s) { long t; if(sscanf(s, "%ld", &t) != 1) return -1; return t; } char* readfile(const char* filename, int* total_read, char showerror) { FILE* file; char* buf = NULL; int bytes_read; *total_read = 0; file = fopen(filename, "r"); if(file) { do { buf = (char *) realloc(buf, *total_read + READSIZE + 1); bytes_read = fread(buf + *total_read, 1, READSIZE, file); *total_read += bytes_read; buf[*total_read] = 0; }while(bytes_read != 0); fclose(file); } else if(showerror != 0) { NORM_ERR(READERR, filename); } return buf; } void pid_readlink(char *file, char *p, int p_max_size) { std::unique_ptr buf(new char[p_max_size]); memset(buf.get(), 0, p_max_size); if(readlink(file, buf.get(), p_max_size) >= 0) { snprintf(p, p_max_size, "%s", buf.get()); } else { NORM_ERR(READERR, file); } } struct ll_string { char *string; struct ll_string* next; }; struct ll_string* addnode(struct ll_string* end, char* string) { struct ll_string* current = (struct ll_string*) malloc(sizeof(struct ll_string)); current->string = strdup(string); current->next = NULL; if(end != NULL) end->next = current; return current; } void freelist(struct ll_string* front) { if(front != NULL) { free(front->string); if(front->next != NULL) { freelist(front->next); } free(front); } } int inlist(struct ll_string* front, char* string) { struct ll_string* current; for(current = front; current != NULL; current = current->next) { if(strcmp(current->string, string) == 0) { return 1; } } return 0; } void print_pid_chroot(struct text_object *obj, char *p, int p_max_size) { char pathbuf[64]; std::unique_ptr buf(new char[max_user_text.get(*state)]); generate_text_internal(buf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/root", strtopid(buf.get())); pid_readlink(pathbuf, p, p_max_size); } void print_pid_cmdline(struct text_object *obj, char *p, int p_max_size) { char* buf; int i, bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(*(objbuf.get()) != 0) { snprintf(pathbuf, 64, PROCDIR "/%d/cmdline", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { for(i = 0; i < bytes_read-1; i++) { if(buf[i] == 0) { buf[i] = ' '; } } snprintf(p, p_max_size, "%s", buf); free(buf); } } else { NORM_ERR("$pid_cmdline didn't receive a argument"); } } void print_pid_cwd(struct text_object *obj, char *p, int p_max_size) { std::unique_ptr buf(new char[p_max_size]); int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/cwd", strtopid(objbuf.get())); bytes_read = readlink(pathbuf, buf.get(), p_max_size); if(bytes_read != -1) { buf[bytes_read] = 0; snprintf(p, p_max_size, "%s", buf.get()); } else { NORM_ERR(READERR, pathbuf); } } void print_pid_environ(struct text_object *obj, char *p, int p_max_size) { int i, total_read; pid_t pid; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); char *buf, *var=strdup(obj->data.s);; generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(sscanf(objbuf.get(), "%d %s", &pid, var) == 2) { for(i = 0; var[i] != 0; i++) { var[i] = toupper(var[i]); } snprintf(pathbuf, 64, PROCDIR "/%d/environ", pid); buf = readfile(pathbuf, &total_read, 1); if(buf != NULL) { for(i = 0; i < total_read; i += strlen(buf + i) + 1) { if(strncmp(buf + i, var, strlen(var)) == 0 && *(buf + i + strlen(var)) == '=') { snprintf(p, p_max_size, "%s", buf + i + strlen(var) + 1); free(buf); free(var); return; } } free(buf); } *p = 0; } free(var); } void print_pid_environ_list(struct text_object *obj, char *p, int p_max_size) { char *buf = NULL; char *buf2; int bytes_read, total_read; int i = 0; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/environ", strtopid(objbuf.get())); buf = readfile(pathbuf, &total_read, 1); if(buf != NULL) { for(bytes_read = 0; bytes_read < total_read; buf[i-1] = ';') { buf2 = strdup(buf+bytes_read); bytes_read += strlen(buf2)+1; sscanf(buf2, "%[^=]", buf+i); free(buf2); i = strlen(buf) + 1; } buf[i-1] = 0; snprintf(p, p_max_size, "%s", buf); free(buf); } } void print_pid_exe(struct text_object *obj, char *p, int p_max_size) { char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/exe", strtopid(objbuf.get())); pid_readlink(pathbuf, p, p_max_size); } void print_pid_nice(struct text_object *obj, char *p, int p_max_size) { char *buf = NULL; int bytes_read; long int nice_value; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(*(obj->data.s) != 0) { snprintf(pathbuf, 64, PROCDIR "/%d/stat", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %*d %ld", &nice_value); snprintf(p, p_max_size, "%ld", nice_value); free(buf); } } else { NORM_ERR("$pid_nice didn't receive a argument"); } } void print_pid_openfiles(struct text_object *obj, char *p, int p_max_size) { DIR* dir; struct dirent *entry; std::unique_ptr buf(new char[p_max_size]); int length, totallength = 0; struct ll_string* files_front = NULL; struct ll_string* files_back = NULL; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); dir = opendir(objbuf.get()); if(dir != NULL) { while ((entry = readdir(dir))) { if(entry->d_name[0] != '.') { snprintf(buf.get(), p_max_size, "%d/%s", strtopid(objbuf.get()), entry->d_name); length = readlink(buf.get(), buf.get(), p_max_size); buf[length] = 0; if(inlist(files_front, buf.get()) == 0) { files_back = addnode(files_back, buf.get()); snprintf(p + totallength, p_max_size - totallength, "%s; " , buf.get()); totallength += length + strlen("; "); } if(files_front == NULL) { files_front = files_back; } } } closedir(dir); freelist(files_front); p[totallength - strlen("; ")] = 0; } else { p[0] = 0; } } void print_pid_parent(struct text_object *obj, char *p, int p_max_size) { #define PARENT_ENTRY "PPid:\t" #define PARENTNOTFOUND "Can't find the process parent in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, PARENT_ENTRY); if(begin != NULL) { begin += strlen(PARENT_ENTRY); end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(PARENTNOTFOUND, pathbuf); } free(buf); } } void print_pid_priority(struct text_object *obj, char *p, int p_max_size) { char *buf = NULL; int bytes_read; long int priority; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(*(objbuf.get()) != 0) { snprintf(pathbuf, 64, PROCDIR "/%d/stat", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %ld", &priority); snprintf(p, p_max_size, "%ld", priority); free(buf); } } else { NORM_ERR("$pid_priority didn't receive a argument"); } } void print_pid_state(struct text_object *obj, char *p, int p_max_size) { #define STATE_ENTRY "State:\t" #define STATENOTFOUND "Can't find the process state in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, STATE_ENTRY); if(begin != NULL) { begin += strlen(STATE_ENTRY) + 3; // +3 will strip the char representing the short state and the space and '(' that follow end = strchr(begin, '\n'); if(end != NULL) { *(end-1) = 0; // -1 strips the ')' } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(STATENOTFOUND, pathbuf); } free(buf); } } void print_pid_state_short(struct text_object *obj, char *p, int p_max_size) { char *begin, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, STATE_ENTRY); if(begin != NULL) { snprintf(p, p_max_size, "%c", *begin); } else { NORM_ERR(STATENOTFOUND, pathbuf); } free(buf); } } void print_pid_stderr(struct text_object *obj, char *p, int p_max_size) { char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/fd/2", strtopid(objbuf.get())); pid_readlink(pathbuf, p, p_max_size); } void print_pid_stdin(struct text_object *obj, char *p, int p_max_size) { std::unique_ptr objbuf(new char[max_user_text.get(*state)]); char pathbuf[64]; generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/fd/0", strtopid(objbuf.get())); pid_readlink(pathbuf, p, p_max_size); } void print_pid_stdout(struct text_object *obj, char *p, int p_max_size) { char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/fd/1", strtopid(objbuf.get())); pid_readlink(pathbuf, p, p_max_size); } void scan_cmdline_to_pid_arg(struct text_object *obj, const char *arg, void* free_at_crash) { unsigned int i; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); /* FIXME */ generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(strlen(arg) > 0) { obj->data.s = strdup(arg); for(i = 0; obj->data.s[i] != 0; i++) { while(obj->data.s[i] == ' ' && obj->data.s[i + 1] == ' ') { memmove(obj->data.s + i, obj->data.s + i + 1, strlen(obj->data.s + i + 1) + 1); } } if(obj->data.s[i - 1] == ' ') { obj->data.s[i - 1] = 0; } } else { CRIT_ERR(obj, free_at_crash, "${cmdline_to_pid commandline}"); } } void print_cmdline_to_pid(struct text_object *obj, char *p, int p_max_size) { DIR* dir; struct dirent *entry; char *buf; int bytes_read, i; char pathbuf[64]; dir = opendir(PROCDIR); if(dir != NULL) { while ((entry = readdir(dir))) { snprintf(pathbuf, 64, PROCDIR "/%s/cmdline", entry->d_name); buf = readfile(pathbuf, &bytes_read, 0); if(buf != NULL) { for(i = 0; i < bytes_read - 1; i++) { if(buf[i] == 0) buf[i] = ' '; } if(strstr(buf, obj->data.s) != NULL) { snprintf(p, p_max_size, "%s", entry->d_name); free(buf); closedir(dir); return; } free(buf); } } closedir(dir); } else { NORM_ERR(READERR, PROCDIR); } } void print_pid_threads(struct text_object *obj, char *p, int p_max_size) { #define THREADS_ENTRY "Threads:\t" #define THREADSNOTFOUND "Can't find the number of the threads of the process in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, THREADS_ENTRY); if(begin != NULL) { begin += strlen(THREADS_ENTRY); end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(THREADSNOTFOUND, pathbuf); } free(buf); } } void print_pid_thread_list(struct text_object *obj, char *p, int p_max_size) { DIR* dir; struct dirent *entry; int totallength = 0; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/task", strtopid(objbuf.get())); dir = opendir(pathbuf); if(dir != NULL) { while ((entry = readdir(dir))) { if(entry->d_name[0] != '.') { snprintf(p + totallength, p_max_size - totallength, "%s," , entry->d_name); totallength += strlen(entry->d_name)+1; } } closedir(dir); if(p[totallength - 1] == ',') p[totallength - 1] = 0; } else { p[0] = 0; } } void print_pid_time_kernelmode(struct text_object *obj, char *p, int p_max_size) { char *buf = NULL; int bytes_read; unsigned long int umtime; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(*(objbuf.get()) != 0) { snprintf(pathbuf, 64, PROCDIR "/%d/stat", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu", &umtime); snprintf(p, p_max_size, "%.2f", (float) umtime / 100); free(buf); } } else { NORM_ERR("$pid_time_kernelmode didn't receive a argument"); } } void print_pid_time_usermode(struct text_object *obj, char *p, int p_max_size) { char *buf = NULL; int bytes_read; unsigned long int kmtime; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(*(objbuf.get()) != 0) { snprintf(pathbuf, 64, PROCDIR "/%d/stat", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %lu", &kmtime); snprintf(p, p_max_size, "%.2f", (float) kmtime / 100); free(buf); } } else { NORM_ERR("$pid_time_usermode didn't receive a argument"); } } void print_pid_time(struct text_object *obj, char *p, int p_max_size) { char *buf = NULL; int bytes_read; unsigned long int umtime, kmtime; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if(*(objbuf.get()) != 0) { snprintf(pathbuf, 64, PROCDIR "/%d/stat", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu", &umtime, &kmtime); snprintf(p, p_max_size, "%.2f", (float) (umtime + kmtime) / 100); free(buf); } } else { NORM_ERR("$pid_time didn't receive a argument"); } } #define UID_ENTRY "Uid:\t" void print_pid_uid(struct text_object *obj, char *p, int p_max_size) { #define UIDNOTFOUND "Can't find the process real uid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, UID_ENTRY); if(begin != NULL) { begin += strlen(UID_ENTRY); end = strchr(begin, '\t'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(UIDNOTFOUND, pathbuf); } free(buf); } } void print_pid_euid(struct text_object *obj, char *p, int p_max_size) { #define EUIDNOTFOUND "Can't find the process effective uid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, UID_ENTRY); if(begin != NULL) { begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; end = strchr(begin, '\t'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(EUIDNOTFOUND, pathbuf); } free(buf); } } void print_pid_suid(struct text_object *obj, char *p, int p_max_size) { #define SUIDNOTFOUND "Can't find the process saved set uid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, UID_ENTRY); if(begin != NULL) { begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; end = strchr(begin, '\t'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(SUIDNOTFOUND, pathbuf); } free(buf); } } void print_pid_fsuid(struct text_object *obj, char *p, int p_max_size) { #define FSUIDNOTFOUND "Can't find the process file system uid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, UID_ENTRY); if(begin != NULL) { begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(FSUIDNOTFOUND, pathbuf); } free(buf); } } #define GID_ENTRY "Gid:\t" void print_pid_gid(struct text_object *obj, char *p, int p_max_size) { #define GIDNOTFOUND "Can't find the process real gid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, GID_ENTRY); if(begin != NULL) { begin += strlen(GID_ENTRY); end = strchr(begin, '\t'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(GIDNOTFOUND, pathbuf); } free(buf); } } void print_pid_egid(struct text_object *obj, char *p, int p_max_size) { #define EGIDNOTFOUND "Can't find the process effective gid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, GID_ENTRY); if(begin != NULL) { begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; end = strchr(begin, '\t'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(EGIDNOTFOUND, pathbuf); } free(buf); } } void print_pid_sgid(struct text_object *obj, char *p, int p_max_size) { #define SGIDNOTFOUND "Can't find the process saved set gid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, GID_ENTRY); if(begin != NULL) { begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; end = strchr(begin, '\t'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(SGIDNOTFOUND, pathbuf); } free(buf); } } void print_pid_fsgid(struct text_object *obj, char *p, int p_max_size) { #define FSGIDNOTFOUND "Can't find the process file system gid in '%s'" char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, GID_ENTRY); if(begin != NULL) { begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; begin = strchr(begin, '\t'); begin++; end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(FSGIDNOTFOUND, pathbuf); } free(buf); } } void internal_print_pid_vm(struct text_object *obj, char *p, int p_max_size, const char* entry, const char* errorstring) { char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/status", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, entry); if(begin != NULL) { begin += strlen(entry); while(*begin == '\t' || *begin == ' ') { begin++; } end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(errorstring, pathbuf); } free(buf); } } void print_pid_vmpeak(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmPeak:\t", "Can't find the process peak virtual memory size in '%s'"); } void print_pid_vmsize(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmSize:\t", "Can't find the process virtual memory size in '%s'"); } void print_pid_vmlck(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmLck:\t", "Can't find the process locked memory size in '%s'"); } void print_pid_vmhwm(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmHWM:\t", "Can't find the process peak resident set size in '%s'"); } void print_pid_vmrss(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmHWM:\t", "Can't find the process resident set size in '%s'"); } void print_pid_vmdata(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmData:\t", "Can't find the process data segment size in '%s'"); } void print_pid_vmstk(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmData:\t", "Can't find the process stack segment size in '%s'"); } void print_pid_vmexe(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmData:\t", "Can't find the process text segment size in '%s'"); } void print_pid_vmlib(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmLib:\t", "Can't find the process shared library code size in '%s'"); } void print_pid_vmpte(struct text_object *obj, char *p, int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmPTE:\t", "Can't find the process page table entries size in '%s'"); } #define READ_ENTRY "read_bytes: " #define READNOTFOUND "Can't find the amount of bytes read in '%s'" void print_pid_read(struct text_object *obj, char *p, int p_max_size) { char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/io", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, READ_ENTRY); if(begin != NULL) { end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(READNOTFOUND, pathbuf); } free(buf); } } #define WRITE_ENTRY "write_bytes: " #define WRITENOTFOUND "Can't find the amount of bytes written in '%s'" void print_pid_write(struct text_object *obj, char *p, int p_max_size) { char *begin, *end, *buf = NULL; int bytes_read; char pathbuf[64]; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); snprintf(pathbuf, 64, PROCDIR "/%d/io", strtopid(objbuf.get())); buf = readfile(pathbuf, &bytes_read, 1); if(buf != NULL) { begin = strstr(buf, WRITE_ENTRY); if(begin != NULL) { end = strchr(begin, '\n'); if(end != NULL) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(WRITENOTFOUND, pathbuf); } free(buf); } } conky-1.10.1/src/proc.h000066400000000000000000000104741262311664100146300ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 CONKY_PROC_H #define CONKY_PROC_H #define PROCDIR "/proc" #define READERR "Can't read '%s'" #define READSIZE 128 void print_pid_chroot(struct text_object *obj, char *p, int p_max_size); void print_pid_cmdline(struct text_object *obj, char *p, int p_max_size); void print_pid_cwd(struct text_object *obj, char *p, int p_max_size); void print_pid_environ(struct text_object *obj, char *p, int p_max_size); void print_pid_environ_list(struct text_object *obj, char *p, int p_max_size); void print_pid_exe(struct text_object *obj, char *p, int p_max_size); void print_pid_nice(struct text_object *obj, char *p, int p_max_size); void print_pid_openfiles(struct text_object *obj, char *p, int p_max_size); void print_pid_parent(struct text_object *obj, char *p, int p_max_size); void print_pid_priority(struct text_object *obj, char *p, int p_max_size); void print_pid_state(struct text_object *obj, char *p, int p_max_size); void print_pid_state_short(struct text_object *obj, char *p, int p_max_size); void print_pid_stderr(struct text_object *obj, char *p, int p_max_size); void print_pid_stdin(struct text_object *obj, char *p, int p_max_size); void print_pid_stdout(struct text_object *obj, char *p, int p_max_size); void print_pid_threads(struct text_object *obj, char *p, int p_max_size); void print_pid_thread_list(struct text_object *obj, char *p, int p_max_size); void print_pid_time_kernelmode(struct text_object *obj, char *p, int p_max_size); void print_pid_time_usermode(struct text_object *obj, char *p, int p_max_size); void print_pid_time(struct text_object *obj, char *p, int p_max_size); void print_pid_uid(struct text_object *obj, char *p, int p_max_size); void print_pid_euid(struct text_object *obj, char *p, int p_max_size); void print_pid_suid(struct text_object *obj, char *p, int p_max_size); void print_pid_fsuid(struct text_object *obj, char *p, int p_max_size); void print_pid_gid(struct text_object *obj, char *p, int p_max_size); void print_pid_egid(struct text_object *obj, char *p, int p_max_size); void print_pid_sgid(struct text_object *obj, char *p, int p_max_size); void print_pid_fsgid(struct text_object *obj, char *p, int p_max_size); void print_pid_read(struct text_object *obj, char *p, int p_max_size); void print_pid_vmpeak(struct text_object *obj, char *p, int p_max_size); void print_pid_vmsize(struct text_object *obj, char *p, int p_max_size); void print_pid_vmlck(struct text_object *obj, char *p, int p_max_size); void print_pid_vmhwm(struct text_object *obj, char *p, int p_max_size); void print_pid_vmrss(struct text_object *obj, char *p, int p_max_size); void print_pid_vmdata(struct text_object *obj, char *p, int p_max_size); void print_pid_vmstk(struct text_object *obj, char *p, int p_max_size); void print_pid_vmexe(struct text_object *obj, char *p, int p_max_size); void print_pid_vmlib(struct text_object *obj, char *p, int p_max_size); void print_pid_vmpte(struct text_object *obj, char *p, int p_max_size); void print_pid_write(struct text_object *obj, char *p, int p_max_size); void scan_cmdline_to_pid_arg(struct text_object *obj, const char *arg, void* free_at_crash); void print_cmdline_to_pid(struct text_object *obj, char *p, int p_max_size); #endif /* CONKY_PROC_H */ conky-1.10.1/src/prss.cc000066400000000000000000000132101262311664100150010ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * Copyright (c) 2007 Mikko Sysikaski * Toni Spets * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include "conky.h" #include "prss.h" #include "logging.h" #include #include #ifndef PARSE_OPTIONS #define PARSE_OPTIONS 0 #endif void prss_parse_doc(PRSS *result, xmlDocPtr doc); PRSS::PRSS(const std::string &xml_data) : version(NULL), title(NULL), link(NULL), description(NULL), language(NULL), generator(NULL), managingEditor(NULL), webMaster(NULL), docs(NULL), lastBuildDate(NULL), pubDate(NULL), copyright(NULL), ttl(NULL), items(NULL), item_count(0) { std::unique_ptr doc( xmlReadMemory(xml_data.c_str(), xml_data.length(), "", NULL, PARSE_OPTIONS), xmlFreeDoc); if (!doc) throw std::runtime_error("Unable to parse rss data"); prss_parse_doc(this, doc.get()); } void free_rss_items(PRSS *data) { int i; if(data->items) { for (i = 0; i < data->item_count; i++) { #define CLEAR(a) free_and_zero(data->items[i].a); CLEAR(title); CLEAR(link); CLEAR(description); CLEAR(category); CLEAR(pubDate); CLEAR(guid); #undef CLEAR } free_and_zero(data->items); data->item_count = 0; } } PRSS::~PRSS() { free_rss_items(this); free(version); free(title); free(link); free(description); free(language); free(pubDate); free(lastBuildDate); free(generator); free(docs); free(managingEditor); free(webMaster); free(copyright); free(ttl); } static inline void prss_null_item(PRSS_Item *i) { memset(i, 0, sizeof(PRSS_Item)); } static inline void read_item(PRSS_Item *res, xmlNodePtr data) { prss_null_item(res); for (; data; data = data->next) { xmlNodePtr child; if (data->type != XML_ELEMENT_NODE) { continue; } child = data->children; if (!child) { continue; } #define ASSIGN(a) if (strcasecmp((const char*)data->name, #a) == EQUAL) { \ free_and_zero(res->a); \ res->a = strdup((const char*)child->content); \ continue; \ } ASSIGN(title); ASSIGN(link); ASSIGN(description); ASSIGN(category); ASSIGN(pubDate); ASSIGN(guid); #undef ASSIGN } } static inline void read_element(PRSS *res, xmlNodePtr n) { xmlNodePtr child; if (n->type != XML_ELEMENT_NODE) { return; } child = n->children; if (!child) { return; } #define ASSIGN(a) if (strcasecmp((const char*)n->name, #a) == EQUAL) { \ free_and_zero(res->a); \ res->a = strdup((const char*)child->content); \ return; \ } ASSIGN(title); ASSIGN(link); ASSIGN(description); ASSIGN(language); ASSIGN(pubDate); ASSIGN(lastBuildDate); ASSIGN(generator); ASSIGN(docs); ASSIGN(managingEditor); ASSIGN(webMaster); ASSIGN(copyright); ASSIGN(ttl); #undef ASSIGN if (!strcasecmp((const char*)n->name, "item")) { read_item(&res->items[res->item_count++], n->children); } } static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root) { xmlNodePtr channel = root->children; xmlNodePtr n; int items = 0; DBGP("parsing rss 2.0 or <1 doc"); while (channel && (channel->type != XML_ELEMENT_NODE || strcmp((const char *) channel->name, "channel"))) { channel = channel->next; } if (!channel) { return 0; } for (n = channel->children; n; n = n->next) { if (n->type == XML_ELEMENT_NODE && !strcmp((const char *) n->name, "item")) { ++items; } } free_and_zero(res->version); res->version = strndup("2.0", text_buffer_size.get(*state)); free_rss_items(res); res->items = (PRSS_Item*) malloc(items * sizeof(PRSS_Item)); res->item_count = 0; for (n = channel->children; n; n = n->next) { read_element(res, n); } return 1; } static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root) { int items = 0; xmlNodePtr n; DBGP("parsing rss 1.0 doc"); for (n = root->children; n; n = n->next) { if (n->type == XML_ELEMENT_NODE) { if (!strcmp((const char *) n->name, "item")) { ++items; } else if (!strcmp((const char *) n->name, "channel")) { xmlNodePtr i; for (i = n->children; i; i = i->next) { read_element(res, i); } } } } free_and_zero(res->version); res->version = strndup("1.0", text_buffer_size.get(*state)); free_rss_items(res); res->items = (PRSS_Item*) malloc(items * sizeof(PRSS_Item)); res->item_count = 0; for (n = root->children; n; n = n->next) { if (n->type == XML_ELEMENT_NODE && !strcmp((const char *) n->name, "item")) { read_item(&res->items[res->item_count++], n->children); } } return 1; } void prss_parse_doc(PRSS *result, xmlDocPtr doc) { xmlNodePtr root = xmlDocGetRootElement(doc); do { if (root->type == XML_ELEMENT_NODE) { if (!strcmp((const char *) root->name, "RDF")) { // RSS 1.0 document parse_rss_1_0(result, root); return; } else if (!strcmp((const char *) root->name, "rss")) { // RSS 2.0 or <1.0 document parse_rss_2_0(result, root); return; } } root = root->next; } while (root); return; } conky-1.10.1/src/prss.h000066400000000000000000000027341262311664100146540ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * Copyright (c) 2007 Mikko Sysikaski * Toni Spets * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef PRSS_H #define PRSS_H #include typedef struct PRSS_Item_ { char *title; char *link; char *description; char *category; char *pubDate; char *guid; } PRSS_Item; struct PRSS { char *version; char *title; char *link; char *description; char *language; char *generator; char *managingEditor; char *webMaster; char *docs; char *lastBuildDate; char *pubDate; char *copyright; char *ttl; PRSS_Item *items; int item_count; PRSS(const std::string &xml_data); ~PRSS(); }; #endif /* PRSS_H */ conky-1.10.1/src/read_tcpip.cc000066400000000000000000000154541262311664100161400ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "text_object.h" #include #include #include #include #include #include #include #include #include struct read_tcpip_data { char *host; unsigned int port; }; void parse_read_tcpip_arg(struct text_object *obj, const char *arg, void *free_at_crash) { struct read_tcpip_data *rtd; rtd = (struct read_tcpip_data *) malloc(sizeof(struct read_tcpip_data)); memset(rtd, 0, sizeof(struct read_tcpip_data)); rtd->host = (char *) malloc(text_buffer_size.get(*state)); sscanf(arg, "%s", rtd->host); sscanf(arg+strlen(rtd->host), "%u", &(rtd->port)); if(rtd->port == 0) { rtd->port = atoi(rtd->host); strcpy(rtd->host,"localhost"); } if(rtd->port < 1 || rtd->port > 65535) CRIT_ERR(obj, free_at_crash, "read_tcp and read_udp need a port from 1 to 65535 as argument"); rtd->port = htons(rtd->port); 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; fd_set readfds; struct timeval tv; struct read_tcpip_data *rtd = (struct read_tcpip_data *) obj->data.opaque; struct addrinfo hints; struct addrinfo* airesult, *rp; char portbuf[8]; if (!rtd) return; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = protocol==IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM; hints.ai_flags = 0; hints.ai_protocol = protocol; snprintf(portbuf, 8, "%d", rtd->port); if (getaddrinfo(rtd->host, portbuf, &hints, &airesult)) { NORM_ERR("%s: Problem with resolving the hostname", protocol == IPPROTO_TCP ? "read_tcp" : "read_udp"); return; } for (rp = airesult; rp != NULL; rp = rp->ai_next) { sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock == -1) { continue; } if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) { break; } close(sock); return; } freeaddrinfo(airesult); if (rp == NULL) { if(protocol == IPPROTO_TCP) { NORM_ERR("read_tcp: Couldn't create a connection"); } else { NORM_ERR("read_udp: Couldn't listen"); //other error because udp is connectionless } return; } if(protocol == IPPROTO_UDP) { //when using udp send a zero-length packet to let the other end know of our existence if(write(sock, NULL, 0) < 0) { NORM_ERR("read_udp: Couldn't create a empty package"); } } FD_ZERO(&readfds); FD_SET(sock, &readfds); tv.tv_sec = 1; tv.tv_usec = 0; if(select(sock + 1, &readfds, NULL, NULL, &tv) > 0){ received = recv(sock, p, p_max_size, 0); if(received != -1) p[received] = 0; else p[0] = 0; } close(sock); } void print_read_tcp(struct text_object *obj, char *p, int p_max_size) { print_read_tcpip(obj, p, p_max_size, IPPROTO_TCP); } void print_read_udp(struct text_object *obj, char *p, int p_max_size) { print_read_tcpip(obj, p, p_max_size, IPPROTO_UDP); } void free_read_tcpip(struct text_object *obj) { struct read_tcpip_data *rtd = (struct read_tcpip_data *) obj->data.opaque; if (!rtd) return; 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); } conky-1.10.1/src/read_tcpip.h000066400000000000000000000031571262311664100157770ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _READ_TCP_H #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 */ conky-1.10.1/src/rss.cc000066400000000000000000000120271262311664100146260ustar00rootroot00000000000000/* -*- 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) 2007 Toni Spets * Copyright (c) 2005-2012 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 "prss.h" #include "text_object.h" #include "ccurl_thread.h" #include #include #include #include struct rss_data { char uri[128]; char action[64]; int act_par; float interval; unsigned int nrspaces; }; namespace { class rss_cb: public curl_callback> { typedef curl_callback> Base; protected: virtual void process_data() { try { std::shared_ptr tmp(new PRSS(data)); std::unique_lock lock(Base::result_mutex); Base::result = tmp; } catch(std::runtime_error &e) { NORM_ERR("%s", e.what()); } } public: rss_cb(uint32_t period, const std::string &uri) : Base(period, Base::Tuple(uri)) {} }; } static void rss_process_info(char *p, int p_max_size, const std::string &uri, char *action, int act_par, int interval, unsigned int nrspaces) { char *str; uint32_t period = std::max(lround(interval/active_update_interval()), 1l); auto cb = conky::register_cb(period, uri); assert(act_par >= 0 && action); std::shared_ptr data = cb->get_result_copy(); if (!data || data->item_count < 1) { *p = 0; } else { /* * XXX: Refactor this so that we can retrieve any of the fields in the * PRSS struct (in prss.h). */ if (strcmp(action, "feed_title") == EQUAL) { str = data->title; if (str && strlen(str) > 0) { // remove trailing new line if one exists if (str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } snprintf(p, p_max_size, "%s", str); } } else if (strcmp(action, "item_title") == EQUAL) { if (act_par < data->item_count) { str = data->items[act_par].title; // remove trailing new line if one exists if (str && strlen(str) > 0) { if (str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } snprintf(p, p_max_size, "%s", str); } } } else if (strcmp(action, "item_desc") == EQUAL) { if (act_par < data->item_count) { str = data->items[act_par].description; // remove trailing new line if one exists if (str && strlen(str) > 0) { if (str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } snprintf(p, p_max_size, "%s", str); } } } else if (strcmp(action, "item_titles") == EQUAL) { if (data->item_count > 0) { int itmp; int show; //'tmpspaces' is a string with spaces too be placed in front of each title char *tmpspaces = (char*)malloc(nrspaces + 1); memset(tmpspaces, ' ', nrspaces); tmpspaces[nrspaces]=0; if (act_par > data->item_count) { show = data->item_count; } else { show = act_par; } for (itmp = 0; itmp < show; itmp++) { PRSS_Item *item = &data->items[itmp]; str = item->title; if (str) { // don't add new line before first item if (itmp > 0) { strncat(p, "\n", p_max_size); } /* remove trailing new line if one exists, * we have our own */ if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } strncat(p, tmpspaces, p_max_size); strncat(p, str, p_max_size); } } free(tmpspaces); } } else { NORM_ERR("rss: Invalid action '%s'", action); } } } void rss_scan_arg(struct text_object *obj, const char *arg) { int argc; struct rss_data *rd; rd = (struct rss_data *)malloc(sizeof(struct rss_data)); memset(rd, 0, sizeof(struct rss_data)); argc = sscanf(arg, "%127s %f %63s %d %u", rd->uri, &rd->interval, rd->action, &rd->act_par, &rd->nrspaces); if (argc < 3) { NORM_ERR("wrong number of arguments for $rss"); free(rd); return; } obj->data.opaque = rd; } void rss_print_info(struct text_object *obj, char *p, int p_max_size) { struct rss_data *rd = (struct rss_data *)obj->data.opaque; if (!rd) { NORM_ERR("error processing RSS data"); return; } rss_process_info(p, p_max_size, rd->uri, rd->action, rd->act_par, rd->interval, rd->nrspaces); } void rss_free_obj_info(struct text_object *obj) { free_and_zero(obj->data.opaque); } conky-1.10.1/src/rss.h000066400000000000000000000022311262311664100144640ustar00rootroot00000000000000/* -*- 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-2012 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 RSS_H_ #define RSS_H_ void rss_scan_arg(struct text_object *, const char *); void rss_print_info(struct text_object *, char *, int); void rss_free_obj_info(struct text_object *); #endif /*RSS_H_*/ conky-1.10.1/src/scroll.cc000066400000000000000000000131461262311664100153200ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "core.h" #include "logging.h" #include "specials.h" #include "text_object.h" #include "x11.h" #include #define SCROLL_LEFT true #define SCROLL_RIGHT false struct scroll_data { char *text; unsigned int show; unsigned int step; signed int start; long resetcolor; bool direction; }; void parse_scroll_arg(struct text_object *obj, const char *arg, void *free_at_crash, char *free_at_crash2) { struct scroll_data *sd; int n1 = 0, n2 = 0; char dirarg[6]; sd = (struct scroll_data *)malloc(sizeof(struct scroll_data)); memset(sd, 0, sizeof(struct scroll_data)); sd->resetcolor = get_current_text_color(); sd->step = 1; sd->direction = SCROLL_LEFT; if (arg && sscanf(arg, "%5s %n", dirarg, &n1) == 1) { if (strcasecmp(dirarg, "right") == 0 || strcasecmp(dirarg, "r") == 0) sd->direction = SCROLL_RIGHT; else if ( strcasecmp(dirarg, "left") != 0 && strcasecmp(dirarg, "l") != 0) n1 = 0; } if (!arg || sscanf(arg + n1, "%u %n", &sd->show, &n2) <= 0) { free(sd); #ifdef BUILD_X11 free(obj->next); #endif free(free_at_crash2); CRIT_ERR(obj, free_at_crash, "scroll needs arguments: [left|right] [] "); } n1 += n2; if(sscanf(arg + n1, "%u %n", &sd->step, &n2) == 1) { n1 += n2; } else { sd->step = 1; } sd->text = (char*)malloc(strlen(arg + n1) + sd->show + 1); if (strlen(arg) > sd->show) { for(n2 = 0; (unsigned int) n2 < sd->show; n2++) { sd->text[n2] = ' '; } sd->text[n2] = 0; } else sd->text[0] = 0; strcat(sd->text, arg + n1); sd->start = 0; obj->sub = (struct text_object *)malloc(sizeof(struct text_object)); extract_variable_text_internal(obj->sub, sd->text); obj->data.opaque = sd; #ifdef BUILD_X11 /* add a color object right after scroll to reset any color changes */ #endif /* BUILD_X11 */ } void print_scroll(struct text_object *obj, char *p, int p_max_size) { struct scroll_data *sd = (struct scroll_data *)obj->data.opaque; unsigned int j, colorchanges = 0, frontcolorchanges = 0, visibcolorchanges = 0, strend; char *pwithcolors; std::vector buf(max_user_text.get(*state)); if (!sd) return; generate_text_internal(&(buf[0]), max_user_text.get(*state), *obj->sub); for(j = 0; buf[j] != 0; j++) { switch(buf[j]) { case '\n': //place all the lines behind each other with LINESEPARATOR between them #define LINESEPARATOR '|' buf[j]=LINESEPARATOR; break; case SPECIAL_CHAR: colorchanges++; break; } } //no scrolling necessary if the length of the text to scroll is too short if (strlen(&(buf[0])) - colorchanges <= sd->show) { snprintf(p, p_max_size, "%s", &(buf[0])); return; } //make sure a colorchange at the front is not part of the string we are going to show while(buf[sd->start] == SPECIAL_CHAR) { sd->start++; } //place all chars that should be visible in p, including colorchanges for(j=0; j < sd->show + visibcolorchanges; j++) { p[j] = buf[sd->start + j]; if(p[j] == SPECIAL_CHAR) { visibcolorchanges++; } //if there is still room fill it with spaces if( ! p[j]) break; } for(; j < sd->show + visibcolorchanges; j++) { p[j] = ' '; } p[j] = 0; //count colorchanges in front of the visible part and place that many colorchanges in front of the visible part for(j = 0; j < (unsigned) sd->start; j++) { if(buf[j] == SPECIAL_CHAR) frontcolorchanges++; } pwithcolors=(char*)malloc(strlen(p) + 4 + colorchanges - visibcolorchanges); for(j = 0; j < frontcolorchanges; j++) { pwithcolors[j] = SPECIAL_CHAR; } pwithcolors[j] = 0; strcat(pwithcolors,p); strend = strlen(pwithcolors); //and place the colorchanges not in front or in the visible part behind the visible part for(j = 0; j < colorchanges - frontcolorchanges - visibcolorchanges; j++) { pwithcolors[strend + j] = SPECIAL_CHAR; } pwithcolors[strend + j] = 0; strcpy(p, pwithcolors); free(pwithcolors); //scroll if(sd->direction == SCROLL_LEFT) { sd->start += sd->step; if(buf[sd->start] == 0 || (unsigned) sd->start > strlen(&(buf[0]))) { sd->start = 0; } } else { if(sd->start < 1) { sd->start = strlen(&(buf[0])); } sd->start -= sd->step; } #ifdef BUILD_X11 //reset color when scroll is finished if (out_to_x.get(*state)) new_special(p + strlen(p), FG)->arg = sd->resetcolor; #endif } void free_scroll(struct text_object *obj) { struct scroll_data *sd = (struct scroll_data *)obj->data.opaque; if (!sd) return; free_and_zero(sd->text); free_text_objects(obj->sub); free_and_zero(obj->sub); free_and_zero(obj->data.opaque); } conky-1.10.1/src/scroll.h000066400000000000000000000025701262311664100151610ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _SCROLL_H #define _SCROLL_H void parse_scroll_arg(struct text_object *, const char *, void *, char *); void print_scroll(struct text_object *, char *, int); void free_scroll(struct text_object *); #endif /* _SCROLL_H */ conky-1.10.1/src/semaphore.hh000066400000000000000000000033201262311664100160100ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 SEMAPHORE_HH #define SEMAPHORE_HH #include #include #include #include #include class semaphore { sem_t sem; semaphore(const semaphore &) = delete; semaphore& operator=(const semaphore &) = delete; public: semaphore(unsigned int value = 0) throw(std::logic_error) { if(sem_init(&sem, 0, value)) throw std::logic_error(strerror(errno)); } ~semaphore() throw() { sem_destroy(&sem); } void post() throw(std::overflow_error) { if(sem_post(&sem)) throw std::overflow_error(strerror(errno)); } void wait() throw() { while(sem_wait(&sem)) { if(errno != EINTR) abort(); } } bool trywait() throw() { while(sem_trywait(&sem)) { if(errno == EAGAIN) return false; else if(errno != EINTR) abort(); } return true; } }; #endif conky-1.10.1/src/setting.cc000066400000000000000000000150461262311664100155000ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 "setting.hh" #include #include #include #include namespace conky { namespace { typedef std::unordered_map settings_map; typedef std::vector settings_vector; /* * We cannot construct this object statically, because order of object construction in * different modules is not defined, so config_setting_base could be called before this * object is constructed. Therefore, we create it on the first call to * config_setting_base constructor. */ settings_map *settings; /* * Returns the setting record corresponding to the value at the specified index. If the * value is not valid, returns NULL and prints an error. */ priv::config_setting_base* get_setting(lua::state &l, int index) { lua::Type type = l.type(index); if(type != lua::TSTRING) { NORM_ERR("invalid setting of type '%s'", l.type_name(type)); return NULL; } const std::string &name = l.tostring(index); auto iter = settings->find(name); if(iter == settings->end()) { NORM_ERR("Unknown setting '%s'", name.c_str()); return NULL; } return iter->second; } // returns a vector of all settings, sorted in order of registration settings_vector make_settings_vector() { settings_vector ret; ret.reserve(settings->size()); for(auto i = settings->begin(); i != settings->end(); ++i) ret.push_back(i->second); sort(ret.begin(), ret.end(), &priv::config_setting_base::seq_compare); return ret; } /* * Returns the seq_no for the new setting object. Also constructs settings object * if needed. */ size_t get_next_seq_no() { struct settings_constructor { settings_constructor() { settings = new settings_map; } ~settings_constructor() { delete settings; settings = NULL; } }; static settings_constructor constructor; return settings->size(); } } namespace priv { config_setting_base::config_setting_base(const std::string &name_) : name(name_), seq_no(get_next_seq_no()) { bool inserted = settings->insert({name, this}).second; if(not inserted) throw std::logic_error("Setting with name '" + name + "' already registered"); } void config_setting_base::lua_set(lua::state &l) { std::lock_guard guard(l); lua::stack_sentry s(l, -1); l.checkstack(2); l.getglobal("conky"); l.rawgetfield(-1, "config"); l.replace(-2); l.insert(-2); l.setfield(-2, name.c_str()); l.pop(); } /* * Performs the actual assignment of settings. Calls the setting-specific setter after * some sanity-checking. * stack on entry: | ..., new_config_table, key, value, old_value | * stack on exit: | ..., new_config_table | */ void config_setting_base::process_setting(lua::state &l, bool init) { lua::stack_sentry s(l, -3); config_setting_base *ptr = get_setting(l, -3); if(not ptr) return; ptr->lua_setter(l, init); l.pushvalue(-2); l.insert(-2); l.rawset(-4); } /* * Called when user sets a new value for a setting * stack on entry: | config_table, key, value | * stack on exit: | | */ int config_setting_base::config__newindex(lua::state *l) { lua::stack_sentry s(*l, -3); l->checkstack(1); l->getmetatable(-3); l->replace(-4); l->pushvalue(-2); l->rawget(-4); process_setting(*l, false); return 0; } /* * conky.config will not be a table, but a userdata with some metamethods we do this * because we want to control access to the settings we use the metatable for storing the * settings, that means having a setting whose name starts with "__" is a bad idea * stack on entry: | ... | * stack on exit: | ... new_config_table | */ void config_setting_base::make_conky_config(lua::state &l) { lua::stack_sentry s(l); l.checkstack(3); l.newuserdata(1); l.newtable(); { l.pushboolean(false); l.rawsetfield(-2, "__metatable"); l.pushvalue(-1); l.rawsetfield(-2, "__index"); l.pushfunction(&priv::config_setting_base::config__newindex); l.rawsetfield(-2, "__newindex"); } l.setmetatable(-2); ++s; } } void set_config_settings(lua::state &l) { lua::stack_sentry s(l); l.checkstack(6); // Force creation of settings map. In the off chance we have no settings. get_next_seq_no(); l.getglobal("conky"); { if(l.type(-1) != lua::TTABLE) throw std::runtime_error("conky must be a table"); l.rawgetfield(-1, "config"); { if(l.type(-1) != lua::TTABLE) throw std::runtime_error("conky.config must be a table"); priv::config_setting_base::make_conky_config(l); l.rawsetfield(-3, "config"); l.rawgetfield(-2, "config"); l.getmetatable(-1); l.replace(-2); { const settings_vector &v = make_settings_vector(); for(size_t i = 0; i < v.size(); ++i) { l.pushstring(v[i]->name); l.rawgetfield(-3, v[i]->name.c_str()); l.pushnil(); priv::config_setting_base::process_setting(l, true); } } l.pop(); // print error messages for unknown settings l.pushnil(); while(l.next(-2)) { l.pop(); get_setting(l, -1); } } l.pop(); } l.pop(); } void cleanup_config_settings(lua::state &l) { lua::stack_sentry s(l); l.checkstack(2); l.getglobal("conky"); l.rawgetfield(-1, "config"); l.replace(-2); const settings_vector &v = make_settings_vector(); for(size_t i = v.size(); i > 0; --i) { l.getfield(-1, v[i-1]->name.c_str()); v[i-1]->cleanup(l); } l.pop(); } /////////// example settings, remove after real settings are available /////// range_config_setting asdf("asdf", 42, 47, 45, true); } conky-1.10.1/src/setting.hh000066400000000000000000000247301262311664100155120ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 SETTING_HH #define SETTING_HH #include #include #include #include "logging.h" #include "luamm.hh" namespace conky { /* * Checks settings, and does initial calls to the setters. * Should be called after reading the user config. * stack on entry: | ... | * stack on exit: | ... | */ void set_config_settings(lua::state &l); /* * Calls cleanup functions. * Should be called before exit/restart. * stack on entry: | ... | * stack on exit: | ... | */ void cleanup_config_settings(lua::state &l); template::value, bool floating_point = std::is_floating_point::value, bool is_enum = std::is_enum::value> struct lua_traits { // integral is here to force the compiler to evaluate the assert at instantiation time static_assert(is_integral && false, "Only specializations for enum, string, integral and floating point types are available"); }; // specialization for integral types template struct lua_traits { static const lua::Type type = lua::TNUMBER; typedef lua::integer Type; static inline std::pair convert(lua::state &l, int index, const std::string &) { return {l.tointeger(index), true}; } }; // specialization for floating point types template struct lua_traits { static const lua::Type type = lua::TNUMBER; typedef lua::number Type; static inline std::pair convert(lua::state &l, int index, const std::string &) { return {l.tonumber(index), true}; } }; // specialization for std::string template<> struct lua_traits { static const lua::Type type = lua::TSTRING; typedef std::string Type; static inline std::pair convert(lua::state &l, int index, const std::string &) { return {l.tostring(index), true}; } }; // specialization for bool template<> struct lua_traits { static const lua::Type type = lua::TBOOLEAN; typedef bool Type; static inline std::pair convert(lua::state &l, int index, const std::string &) { return {l.toboolean(index), true}; } }; // specialization for enums // to use this, one first has to declare string<->value map template struct lua_traits { static const lua::Type type = lua::TSTRING; typedef T Type; typedef std::initializer_list> Map; static Map map; static std::pair convert(lua::state &l, int index, const std::string &name) { std::string val = l.tostring(index); for(auto i = map.begin(); i != map.end(); ++i) { if(i->first == val) return {i->second, true}; } std::string msg = "Invalid value '" + val + "' for setting '" + name + "'. Valid values are: "; for(auto i = map.begin(); i != map.end(); ++i) { if(i != map.begin()) msg += ", "; msg += "'" + i->first + "'"; } msg += "."; NORM_ERR("%s", msg.c_str()); return {T(), false}; } }; namespace priv { class config_setting_base { private: static void process_setting(lua::state &l, bool init); static int config__newindex(lua::state *l); static void make_conky_config(lua::state &l); // copying is a REALLY bad idea config_setting_base(const config_setting_base &) = delete; config_setting_base& operator=(const config_setting_base &) = delete; protected: /* * Set the setting, if the value is sane * stack on entry: | ... potential_new_value old_value | * stack on exit: | ... real_new_value | * real_new_value can be the old value if the new value doesn't make sense */ virtual void lua_setter(lua::state &l, bool init) = 0; /* * Called on exit/restart. * stack on entry: | ... new_value | * stack on exit: | ... | */ virtual void cleanup(lua::state &l) { l.pop(); } public: const std::string name; const size_t seq_no; static bool seq_compare(const config_setting_base *a, const config_setting_base *b) { return a->seq_no < b->seq_no; } explicit config_setting_base(const std::string &name_); virtual ~config_setting_base() {} /* * Set the setting manually. * stack on entry: | ... new_value | * stack on exit: | ... | */ void lua_set(lua::state &l); friend void conky::set_config_settings(lua::state &l); friend void conky::cleanup_config_settings(lua::state &l); }; } // If you need some very exotic setting, derive it from this class. Otherwise, scroll down. template class config_setting_template: public priv::config_setting_base { public: explicit config_setting_template(const std::string &name_) : config_setting_base(name_) {} // get the value of the setting as a C++ type T get(lua::state &l); protected: /* * Convert the value into a C++ type. * stack on entry: | ... value | * stack on exit: | ... | */ virtual T getter(lua::state &l) = 0; }; template T config_setting_template::get(lua::state &l) { std::lock_guard guard(l); lua::stack_sentry s(l); l.checkstack(2); l.getglobal("conky"); l.getfield(-1, "config"); l.replace(-2); l.getfield(-1, name.c_str()); l.replace(-2); return getter(l); } /* * Declares a setting in the conky.config table. * Getter function is used to translate the lua value into C++. It recieves the value on the * lua stack. It should pop it and return the C++ value. In case the value is nil, it should * return a predefined default value. Translation into basic types works with the help of * lua_traits template above * The lua_setter function is called when someone tries to set the value. It recieves the * new and the old value on the stack (old one is on top). It should return the new value for * the setting. It doesn't have to be the value the user set, if e.g. the value doesn't make * sense. The second parameter is true if the assignment occurs during the initial parsing of * the config file, and false afterwards. Some settings obviously cannot be changed (easily?) * when conky is running, but some (e.g. x/y position of the window) can. */ template> class simple_config_setting: public config_setting_template { typedef config_setting_template Base; public: simple_config_setting(const std::string &name_, const T &default_value_ = T(), bool modifiable_ = false) : Base(name_), default_value(default_value_), modifiable(modifiable_) {} protected: const T default_value; const bool modifiable; virtual std::pair do_convert(lua::state &l, int index); virtual void lua_setter(lua::state &l, bool init); virtual T getter(lua::state &l) { lua::stack_sentry s(l, -1); auto ret = do_convert(l, -1); l.pop(); // setter function should make sure the value is valid assert(ret.second); return ret.first; } }; template std::pair simple_config_setting::do_convert(lua::state &l, int index) { if(l.isnil(index)) return {default_value, true}; if(l.type(index) != Traits::type) { NORM_ERR("Invalid value of type '%s' for setting '%s'. " "Expected value of type '%s'.", l.type_name(l.type(index)), Base::name.c_str(), l.type_name(Traits::type) ); return {default_value, false}; } return Traits::convert(l, index, Base::name); } template void simple_config_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); bool ok = true; if(!init && !modifiable) { NORM_ERR("Setting '%s' is not modifiable", Base::name.c_str()); ok = false; } if(ok && do_convert(l, -2).second) l.pop(); else l.replace(-2); ++s; } template bool between(Signed1 value, Signed2 min, typename std::enable_if::value, Signed2>::type max) { return value >= min && value <= max; } template bool between(Signed1 value, Unsigned2 min, typename std::enable_if::value, Unsigned2>::type max) { return value >= 0 && static_cast::type>(value) >= min && static_cast::type>(value) <= max; } // Just like simple_config_setting, except that in only accepts value in the [min, max] range template> class range_config_setting: public simple_config_setting { typedef simple_config_setting Base; const T min; const T max; public: range_config_setting(const std::string &name_, const T &min_ = std::numeric_limits::min(), const T &max_ = std::numeric_limits::max(), const T &default_value_ = T(), bool modifiable_ = false) : Base(name_, default_value_, modifiable_), min(min_), max(max_) { assert(min <= Base::default_value && Base::default_value <= max); } protected: virtual std::pair do_convert(lua::state &l, int index) { auto ret = Base::do_convert(l, index); if(ret.second && !between(ret.first, min, max)) { NORM_ERR("Value is out of range for setting '%s'", Base::name.c_str()); // we ignore out-of-range values. an alternative would be to clamp them. do we // want to do that? ret.second = false; } return ret; } }; /////////// example settings, remove after real settings are available /////// extern range_config_setting asdf; } #endif /* SETTING_HH */ conky-1.10.1/src/smapi.cc000066400000000000000000000116101262311664100151250ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * smapi.c: conky support for IBM Thinkpad smapi * * Copyright (C) 2007 Phil Sutter * * This library 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 2 of the License, or * (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #include "conky.h" /* text_buffer_size, PACKAGE_NAME, maybe more */ #include #include "temphelper.h" #include "logging.h" #include #include #include #include #include #define SYS_SMAPI_PATH "/sys/devices/platform/smapi" static int smapi_read_int(const char *path) { FILE *fp; int i = 0; if ((fp = fopen(path, "r"))) { if (fscanf(fp, "%i\n", &i) < 0) perror("fscanf()"); fclose(fp); } return i; } static int smapi_bat_installed_internal(int idx) { char path[128]; struct stat sb; int ret = 0; snprintf(path, 127, SYS_SMAPI_PATH "/BAT%i", idx); if (!stat(path, &sb) && (sb.st_mode & S_IFMT) == S_IFDIR) { snprintf(path, 127, SYS_SMAPI_PATH "/BAT%i/installed", idx); ret = (smapi_read_int(path) == 1) ? 1 : 0; } return ret; } static char *smapi_read_str(const char *path) { FILE *fp; char str[256] = "failed"; if ((fp = fopen(path, "r")) != NULL) { if (fscanf(fp, "%255s\n", str) < 0) perror("fscanf()"); fclose(fp); } return strndup(str, text_buffer_size.get(*state)); } static char *smapi_get_str(const char *fname) { char path[128]; if(snprintf(path, 127, SYS_SMAPI_PATH "/%s", fname) < 0) return NULL; return smapi_read_str(path); } static char *smapi_get_bat_str(int idx, const char *fname) { char path[128]; if(snprintf(path, 127, SYS_SMAPI_PATH "/BAT%i/%s", idx, fname) < 0) return NULL; return smapi_read_str(path); } static int smapi_get_bat_int(int idx, const char *fname) { char path[128]; if(snprintf(path, 127, SYS_SMAPI_PATH "/BAT%i/%s", idx, fname) < 0) return 0; return smapi_read_int(path); } static char *smapi_get_bat_val(const char *args) { char fname[128]; int idx, cnt; if(sscanf(args, "%i %n", &idx, &cnt) <= 0 || snprintf(fname, 127, "%s", (args + cnt)) < 0) { NORM_ERR("smapi: wrong arguments, should be 'bat,,'"); return NULL; } if(!smapi_bat_installed_internal(idx)) return NULL; return smapi_get_bat_str(idx, fname); } static char *smapi_get_val(const char *args) { char str[128]; if(!args || sscanf(args, "%127s", str) <= 0) return NULL; if(!strcmp(str, "bat")) return smapi_get_bat_val(args + 4); return smapi_get_str(str); } void print_smapi(struct text_object *obj, char *p, int p_max_size) { char *s; if (!obj->data.s) return; s = smapi_get_val(obj->data.s); snprintf(p, p_max_size, "%s", s); free(s); } uint8_t smapi_bat_percentage(struct text_object *obj) { int idx, val = 0; if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { val = smapi_bat_installed_internal(idx) ? smapi_get_bat_int(idx, "remaining_percent") : 0; } else NORM_ERR("argument to smapi_bat_perc must be an integer"); return val; } void print_smapi_bat_temp(struct text_object *obj, char *p, int p_max_size) { int idx, val; if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { val = smapi_bat_installed_internal(idx) ? smapi_get_bat_int(idx, "temperature") : 0; /* temperature is in milli degree celsius */ temp_print(p, p_max_size, val / 1000, TEMP_CELSIUS); } else NORM_ERR("argument to smapi_bat_temp must be an integer"); } void print_smapi_bat_power(struct text_object *obj, char *p, int p_max_size) { int idx, val; if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { val = smapi_bat_installed_internal(idx) ? smapi_get_bat_int(idx, "power_now") : 0; /* power_now is in mW, set to W with one digit precision */ snprintf(p, p_max_size, "%.1f", ((double)val / 1000)); } else NORM_ERR("argument to smapi_bat_power must be an integer"); } double smapi_bat_barval(struct text_object *obj) { if (obj->data.i >= 0 && smapi_bat_installed_internal(obj->data.i)) return smapi_get_bat_int(obj->data.i, "remaining_percent"); return 0; } int smapi_bat_installed(struct text_object *obj) { int idx; if(obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { if(!smapi_bat_installed_internal(idx)) { return 0; } } else NORM_ERR("argument to if_smapi_bat_installed must be an integer"); return 1; } conky-1.10.1/src/smapi.h000066400000000000000000000024711262311664100147740ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * smapi.h: conky support for IBM Thinkpad smapi * * Copyright (C) 2007 Phil Sutter * * This library 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 2 of the License, or * (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #ifndef _SMAPI_H #define _SMAPI_H void print_smapi(struct text_object *, char *, int); uint8_t smapi_bat_percentage(struct text_object *); void print_smapi_bat_temp(struct text_object *, char *, int); void print_smapi_bat_power(struct text_object *, char *, int); double smapi_bat_barval(struct text_object *); int smapi_bat_installed(struct text_object *obj); #endif /* _SMAPI_H */ conky-1.10.1/src/solaris.cc000066400000000000000000000037561262311664100155040ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 . * */ /* doesn't work, feel free to finish this */ #include "conky.h" #include "common.h" #include static kstat_ctl_t *kstat; static int kstat_updated; static void update_kstat() { if (kstat == NULL) { kstat = kstat_open(); if (kstat == NULL) { NORM_ERR("can't open kstat: %s", strerror(errno)); } } if (kstat_chain_update(kstat) == -1) { perror("kstat_chain_update"); return; } } void prepare_update() { kstat_updated = 0; } double get_uptime() { kstat_t *ksp; update_kstat(); ksp = kstat_lookup(kstat, "unix", -1, "system_misc"); if (ksp != NULL) { if (kstat_read(kstat, ksp, NULL) >= 0) { kstat_named_t *knp; knp = (kstat_named_t *) kstat_data_lookup(ksp, "boot_time"); if (knp != NULL) { return get_time() - (double) knp->value.ui32; } } } } void update_meminfo() { /* TODO */ } int check_mount(struct text_object *obj) { /* stub */ (void)obj; return 0; } conky-1.10.1/src/sony.cc000066400000000000000000000046051262311664100150120ustar00rootroot00000000000000/* -*- 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-2012 Brenden Matthews, Philip Kovacs, et. al. * Copyright (c) 2009 Yeon-Hyeong Yang * (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 . * */ /* conky support for information from sony_laptop kernel module * information from sony_laptop kernel module * /sys/devices/platform/sony-laptop * I mimicked the methods from ibm.c * Yeon-Hyeong Yang */ #include "conky.h" #include "config.h" #include "sony.h" #include "logging.h" #include "text_object.h" #include #include #include #include #define SONY_LAPTOP_DIR "/sys/devices/platform/sony-laptop" /* fanspeed in SONY_LAPTOP_DIR contains an integer value for fanspeed (0~255). * I don't know the exact measurement unit, though. I may assume that 0 for * 'fan stopped' and 255 for 'maximum fan speed'. */ void get_sony_fanspeed(struct text_object *obj, char *p_client_buffer, int client_buffer_size) { FILE *fp; unsigned int speed = 0; char fan[128]; (void)obj; if (!p_client_buffer || client_buffer_size <= 0) { return; } snprintf(fan, 127, "%s/fanspeed", SONY_LAPTOP_DIR); fp = fopen(fan, "r"); if (fp != NULL) { while (!feof(fp)) { char line[256]; if (fgets(line, 255, fp) == NULL) { break; } if (sscanf(line, "%u", &speed)) { break; } } } else { CRIT_ERR(NULL, NULL, "can't open '%s': %s\nEnable sony support or remove " "sony* from your " PACKAGE_NAME" config file.", fan, strerror(errno)); } fclose(fp); snprintf(p_client_buffer, client_buffer_size, "%d", speed); } conky-1.10.1/src/sony.h000066400000000000000000000024611262311664100146520ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Please see COPYING for details * * Copyright (c) 2005-2012 Brenden Matthews, Philip Kovacs, et. al. * Copyright (c) 2009 Yeon-Hyeong Yang * (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 . * */ /* conky support for information from sony_laptop kernel module * information from sony_laptop kernel module * /sys/devices/platform/sony-laptop * I mimicked the methods from ibm.c * Yeon-Hyeong Yang */ #ifndef _SONY_H #define _SONY_H void get_sony_fanspeed(struct text_object *, char *, int); #endif /* _SONY_H */ conky-1.10.1/src/specials.cc000066400000000000000000000414721262311664100156300ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "colours.h" #ifdef BUILD_X11 #include "fonts.h" #endif /* BUILD_X11 */ #include "logging.h" #include "nc.h" #include "specials.h" #include #ifdef HAVE_SYS_PARAM_H #include #endif /* HAVE_SYS_PARAM_H */ #include #include struct special_t *specials = NULL; int special_count; namespace { conky::range_config_setting default_bar_width("default_bar_width", 0, std::numeric_limits::max(), 0, false); conky::range_config_setting default_bar_height("default_bar_height", 0, std::numeric_limits::max(), 6, false); #ifdef BUILD_X11 conky::range_config_setting default_graph_width("default_graph_width", 0, std::numeric_limits::max(), 0, false); conky::range_config_setting default_graph_height("default_graph_height", 0, std::numeric_limits::max(), 25, false); conky::range_config_setting default_gauge_width("default_gauge_width", 0, std::numeric_limits::max(), 40, false); conky::range_config_setting default_gauge_height("default_gauge_height", 0, std::numeric_limits::max(), 25, false); #endif /* BUILD_X11 */ conky::simple_config_setting console_graph_ticks("console_graph_ticks", " ,_,=,#", false); } /* special data types flags */ #define SF_SCALED (1 << 0) #define SF_SHOWLOG (1 << 1) /* * Special data typedefs */ struct bar { char flags; int width, height; double scale; }; struct gauge { char flags; int width, height; double scale; }; struct graph { char flags; int width, height; unsigned int first_colour, last_colour; double scale; char tempgrad; }; struct stippled_hr { int height, arg; }; struct tab { int width, arg; }; /* * Scanning arguments to various special text objects */ #ifdef BUILD_X11 const char *scan_gauge(struct text_object *obj, const char *args, double scale) { struct gauge *g; g = (struct gauge *)malloc(sizeof(struct gauge)); memset(g, 0, sizeof(struct gauge)); /*width and height*/ g->width = default_gauge_width.get(*state); g->height = default_gauge_height.get(*state); if (scale) g->scale = scale; else g->flags |= SF_SCALED; /* gauge's argument is either height or height,width */ if (args) { int n = 0; if (sscanf(args, "%d,%d %n", &g->height, &g->width, &n) <= 1) { if (sscanf(args, "%d %n", &g->height, &n) == 2) { g->width = g->height; /*square gauge*/ } } args += n; } obj->special_data = g; return args; } #endif const char *scan_bar(struct text_object *obj, const char *args, double scale) { struct bar *b; b = (struct bar *)malloc(sizeof(struct bar)); memset(b, 0, sizeof(struct bar)); /* zero width means all space that is available */ b->width = default_bar_width.get(*state); b->height = default_bar_height.get(*state); if (scale) b->scale = scale; else b->flags |= SF_SCALED; /* bar's argument is either height or height,width */ if (args) { int n = 0; if (sscanf(args, "%d,%d %n", &b->height, &b->width, &n) <= 1) { sscanf(args, "%d %n", &b->height, &n); } args += n; } obj->special_data = b; return args; } #ifdef BUILD_X11 void scan_font(struct text_object *obj, const char *args) { if (args && *args) obj->data.s = strndup(args, DEFAULT_TEXT_BUFFER_SIZE); } char *scan_graph(struct text_object *obj, const char *args, double defscale) { struct graph *g; char buf[1024]; memset(buf, 0, 1024); g = (struct graph *)malloc(sizeof(struct graph)); memset(g, 0, sizeof(struct graph)); obj->special_data = g; /* zero width means all space that is available */ g->width = default_graph_width.get(*state); g->height = default_graph_height.get(*state); g->first_colour = 0; g->last_colour = 0; g->scale = defscale; g->tempgrad = FALSE; if (args) { if (strstr(args, " " TEMPGRAD) || strncmp(args, TEMPGRAD, strlen(TEMPGRAD)) == 0) { g->tempgrad = TRUE; } if (strstr(args, " " LOGGRAPH) || strncmp(args, LOGGRAPH, strlen(LOGGRAPH)) == 0) { g->flags |= SF_SHOWLOG; } if (sscanf(args, "%d,%d %x %x %lf", &g->height, &g->width, &g->first_colour, &g->last_colour, &g->scale) == 5) { return NULL; } g->scale = defscale; if (sscanf(args, "%d,%d %x %x", &g->height, &g->width, &g->first_colour, &g->last_colour) == 4) { return NULL; } if (sscanf(args, "%1023s %d,%d %x %x %lf", buf, &g->height, &g->width, &g->first_colour, &g->last_colour, &g->scale) == 6) { return strndup(buf, text_buffer_size.get(*state)); } g->scale = defscale; if (sscanf(args, "%1023s %d,%d %x %x", buf, &g->height, &g->width, &g->first_colour, &g->last_colour) == 5) { return strndup(buf, text_buffer_size.get(*state)); } buf[0] = '\0'; g->height = 25; g->width = 0; if (sscanf(args, "%x %x %lf", &g->first_colour, &g->last_colour, &g->scale) == 3) { return NULL; } g->scale = defscale; if (sscanf(args, "%x %x", &g->first_colour, &g->last_colour) == 2) { return NULL; } if (sscanf(args, "%1023s %x %x %lf", buf, &g->first_colour, &g->last_colour, &g->scale) == 4) { return strndup(buf, text_buffer_size.get(*state)); } g->scale = defscale; if (sscanf(args, "%1023s %x %x", buf, &g->first_colour, &g->last_colour) == 3) { return strndup(buf, text_buffer_size.get(*state)); } buf[0] = '\0'; g->first_colour = 0; g->last_colour = 0; if (sscanf(args, "%d,%d %lf", &g->height, &g->width, &g->scale) == 3) { return NULL; } g->scale = defscale; if (sscanf(args, "%d,%d", &g->height, &g->width) == 2) { return NULL; } if (sscanf(args, "%1023s %d,%d %lf", buf, &g->height, &g->width, &g->scale) < 4) { g->scale = defscale; //TODO: check the return value and throw an error? sscanf(args, "%1023s %d,%d", buf, &g->height, &g->width); } /* escape quotes at end in case of execgraph */ if (*buf == '"') { char *_ptr; size_t _size; if ((_ptr = const_cast(strrchr(args, '"')))) { _size = _ptr - args - 1; } _size = _size < 1024 ? _size : 1023; strncpy(buf, args + 1, _size); buf[_size] = 0; } #undef g return strndup(buf, text_buffer_size.get(*state)); } if (buf[0] == '\0') { return NULL; } else { return strndup(buf, text_buffer_size.get(*state)); } } #endif /* BUILD_X11 */ /* * Printing various special text objects */ struct special_t *new_special_t_node() { special_t *newnode = new special_t; memset(newnode, 0, sizeof *newnode); return newnode; } struct special_t *new_special(char *buf, enum special_types t) { special_t* current; buf[0] = SPECIAL_CHAR; buf[1] = '\0'; if(!specials) specials = new_special_t_node(); current = specials; for(int i=0; i < special_count; i++) { if(current->next == NULL) current->next = new_special_t_node(); current = current->next; } current->type = t; special_count++; return current; } void new_gauge_in_shell(struct text_object *obj, char *p, int p_max_size, double usage) { static const char *gaugevals[] = { "_. ", "\\. ", " | ", " ./", " ._" }; struct gauge *g = (struct gauge *)obj->special_data; snprintf(p, p_max_size, "%s", gaugevals[round_to_int(usage * 4 / g->scale)]); } #ifdef BUILD_X11 void new_gauge_in_x11(struct text_object *obj, char *buf, double usage) { struct special_t *s = 0; struct gauge *g = (struct gauge *)obj->special_data; if (not out_to_x.get(*state)) return; if (!g) return; s = new_special(buf, GAUGE); s->arg = usage; s->width = g->width; s->height = g->height; s->scale = g->scale; } #endif /* BUILD_X11 */ void new_gauge(struct text_object *obj, char *p, int p_max_size, double usage) { struct gauge *g = (struct gauge *)obj->special_data; if (!p_max_size || !g) return; if (g->flags & SF_SCALED) g->scale = MAX(g->scale, usage); else usage = MIN(g->scale, usage); #ifdef BUILD_X11 if (out_to_x.get(*state)) new_gauge_in_x11(obj, p, usage); else #endif /* BUILD_X11 */ new_gauge_in_shell(obj, p, p_max_size, usage); } #ifdef BUILD_X11 void new_font(struct text_object *obj, char *p, int p_max_size) { struct special_t *s; int tmp = selected_font; if (not out_to_x.get(*state)) return; if (!p_max_size) return; s = new_special(p, FONT); if (obj->data.s) { if (s->font_added >= (int)fonts.size() || !s->font_added || obj->data.s != fonts[s->font_added].name ) { selected_font = s->font_added = add_font(obj->data.s); selected_font = tmp; } } else { selected_font = s->font_added = 0; selected_font = tmp; } } static void graph_append(struct special_t *graph, double f, char showaslog) { int i; /* do nothing if we don't even have a graph yet */ if (!graph->graph) return; if (showaslog) { #ifdef MATH f = log10(f + 1); #endif } if (!graph->scaled && f > graph->scale) { f = graph->scale; } /* shift all the data by 1 */ for (i = graph->graph_allocated - 1; i > 0; i--) { graph->graph[i] = graph->graph[i - 1]; } graph->graph[0] = f; /* add new data */ if(graph->scaled) { graph->scale = *std::max_element(graph->graph + 0, graph->graph + graph->graph_width); if(graph->scale < 1e-47) { /* avoid NaN's when the graph is all-zero (e.g. before the first update) * there is nothing magical about 1e-47 here */ graph->scale = 1e-47; } } } void new_graph_in_shell(struct special_t *s, char *buf, int buf_max_size) { // Split config string on comma to avoid the hassle of dealing with the // idiosyncrasies of multi-byte unicode on different platforms. // TODO: Parse config string once and cache result. const std::string ticks = console_graph_ticks.get(*state); std::stringstream ss(ticks); std::string tickitem; std::vector tickitems; while (std::getline(ss, tickitem, ',')) { tickitems.push_back(tickitem); } char *p = buf; char *buf_max = buf + (sizeof(char) * buf_max_size); double scale = (tickitems.size() - 1) / s->scale; for (int i = s->graph_allocated -1; i >= 0; i--) { const unsigned int v = round_to_int(s->graph[i] * scale); const char *tick = tickitems[v].c_str(); size_t itemlen = tickitems[v].size(); for (unsigned int j = 0; j < itemlen; j++) { *p++ = tick[j]; if (p == buf_max) goto graph_buf_end; } } graph_buf_end: *p = '\0'; } void new_graph(struct text_object *obj, char *buf, int buf_max_size, double val) { struct special_t *s = 0; struct graph *g = (struct graph *)obj->special_data; if (!g || !buf_max_size) return; s = new_special(buf, GRAPH); s->width = g->width; if (s->width) s->graph_width = s->width; if (s->graph_width != s->graph_allocated) { double *graph = static_cast(realloc(s->graph, s->graph_width * sizeof(double))); DBGP("reallocing graph from %d to %d", s->graph_allocated, s->graph_width); if (!s->graph) { /* initialize */ memset(graph, 0, s->graph_width * sizeof(double)); s->scale = 100; } else { if (s->graph_width > s->graph_allocated) { /* initialize the new region */ memset(graph + (s->graph_allocated * sizeof(double)), 0, (s->graph_width - s->graph_allocated) * sizeof(double)); } } s->graph = graph; s->graph_allocated = s->graph_width; } s->height = g->height; s->first_colour = adjust_colours(g->first_colour); s->last_colour = adjust_colours(g->last_colour); if (g->scale != 0) { s->scaled = 0; s->scale = g->scale; s->show_scale = 0; } else { s->scaled = 1; s->scale = 1; s->show_scale = 1; } s->tempgrad = g->tempgrad; #ifdef MATH if (g->flags & SF_SHOWLOG) { s->scale = log10(s->scale + 1); } #endif graph_append(s, val, g->flags & SF_SHOWLOG); if (not out_to_x.get(*state)) new_graph_in_shell(s, buf, buf_max_size); } void new_hr(struct text_object *obj, char *p, int p_max_size) { if (not out_to_x.get(*state)) return; if (!p_max_size) return; new_special(p, HORIZONTAL_LINE)->height = obj->data.l; } void scan_stippled_hr(struct text_object *obj, const char *arg) { struct stippled_hr *sh; sh = (struct stippled_hr *)malloc(sizeof(struct stippled_hr)); memset(sh, 0, sizeof(struct stippled_hr)); sh->arg = stippled_borders.get(*state); sh->height = 1; if (arg) { if (sscanf(arg, "%d %d", &sh->arg, &sh->height) != 2) { sscanf(arg, "%d", &sh->height); } } if (sh->arg <= 0) { sh->arg = 1; } obj->special_data = sh; } void new_stippled_hr(struct text_object *obj, char *p, int p_max_size) { struct special_t *s = 0; struct stippled_hr *sh = (struct stippled_hr *)obj->special_data; if (not out_to_x.get(*state)) return; if (!sh || !p_max_size) return; s = new_special(p, STIPPLED_HR); s->height = sh->height; s->arg = sh->arg; } #endif /* BUILD_X11 */ void new_fg(struct text_object *obj, char *p, int p_max_size) { #ifdef BUILD_X11 if (out_to_x.get(*state)) new_special(p, FG)->arg = obj->data.l; #endif /* BUILD_X11 */ #ifdef BUILD_NCURSES if (out_to_ncurses.get(*state)) new_special(p, FG)->arg = obj->data.l; #endif /* BUILD_NCURSES */ UNUSED(obj); UNUSED(p); UNUSED(p_max_size); } #ifdef BUILD_X11 void new_bg(struct text_object *obj, char *p, int p_max_size) { if (not out_to_x.get(*state)) return; if (!p_max_size) return; new_special(p, BG)->arg = obj->data.l; } #endif /* BUILD_X11 */ static void new_bar_in_shell(struct text_object *obj, char* buffer, int buf_max_size, double usage) { struct bar *b = (struct bar *)obj->special_data; int width, i, scaledusage; if (!b) return; width = b->width; if (!width) width = DEFAULT_BAR_WIDTH_NO_X; if (width > buf_max_size) width = buf_max_size; scaledusage = round_to_int( usage * width / b->scale); for (i = 0; i < scaledusage; i++) buffer[i] = '#'; for (; i < width; i++) buffer[i] = '_'; buffer[i] = 0; } #ifdef BUILD_X11 static void new_bar_in_x11(struct text_object *obj, char *buf, double usage) { struct special_t *s = 0; struct bar *b = (struct bar *)obj->special_data; if (not out_to_x.get(*state)) return; if (!b) return; s = new_special(buf, BAR); s->arg = usage; s->width = b->width; s->height = b->height; s->scale = b->scale; } #endif /* BUILD_X11 */ /* usage is in range [0,255] */ void new_bar(struct text_object *obj, char *p, int p_max_size, double usage) { struct bar *b = (struct bar *)obj->special_data; if (!p_max_size || !b) return; if (b->flags & SF_SCALED) b->scale = MAX(b->scale, usage); else usage = MIN(b->scale, usage); #ifdef BUILD_X11 if (out_to_x.get(*state)) new_bar_in_x11(obj, p, usage); else #endif /* BUILD_X11 */ new_bar_in_shell(obj, p, p_max_size, usage); } void new_outline(struct text_object *obj, char *p, int p_max_size) { if (!p_max_size) return; new_special(p, OUTLINE)->arg = obj->data.l; } void new_offset(struct text_object *obj, char *p, int p_max_size) { if (!p_max_size) return; new_special(p, OFFSET)->arg = obj->data.l; } void new_voffset(struct text_object *obj, char *p, int p_max_size) { if (!p_max_size) return; new_special(p, VOFFSET)->arg = obj->data.l; } void new_alignr(struct text_object *obj, char *p, int p_max_size) { if (!p_max_size) return; new_special(p, ALIGNR)->arg = obj->data.l; } // A postive offset pushes the text further left void new_alignc(struct text_object *obj, char *p, int p_max_size) { if (!p_max_size) return; new_special(p, ALIGNC)->arg = obj->data.l; } void new_goto(struct text_object *obj, char *p, int p_max_size) { if (!p_max_size) return; new_special(p, GOTO)->arg = obj->data.l; } void scan_tab(struct text_object *obj, const char *arg) { struct tab *t; t = (struct tab *)malloc(sizeof(struct tab)); memset(t, 0, sizeof(struct tab)); t->width = 10; t->arg = 0; if (arg) { if (sscanf(arg, "%d %d", &t->width, &t->arg) != 2) { sscanf(arg, "%d", &t->arg); } } if (t->width <= 0) { t->width = 1; } obj->special_data = t; } void new_tab(struct text_object *obj, char *p, int p_max_size) { struct special_t *s = 0; struct tab *t = (struct tab *)obj->special_data; if (!t || !p_max_size) return; s = new_special(p, TAB); s->width = t->width; s->arg = t->arg; } conky-1.10.1/src/specials.h000066400000000000000000000066601262311664100154720ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _SPECIALS_H #define _SPECIALS_H /* special stuff in text_buffer */ #define SPECIAL_CHAR '\x01' // don't use spaces in LOGGRAPH or NORMGRAPH if you change them #define LOGGRAPH "-l" #define TEMPGRAD "-t" enum special_types { NONSPECIAL = 0, HORIZONTAL_LINE = 1, STIPPLED_HR, BAR, FG, BG, OUTLINE, ALIGNR, ALIGNC, GAUGE, GRAPH, OFFSET, VOFFSET, FONT, GOTO, TAB }; struct special_t { int type; short height; short width; double arg; double *graph; double scale; /* maximum value */ short show_scale; int graph_width; int graph_allocated; int scaled; /* auto adjust maximum */ unsigned long first_colour; // for graph gradient unsigned long last_colour; short font_added; char tempgrad; struct special_t *next; }; /* direct access to the registered specials (FIXME: bad encapsulation) */ extern struct special_t *specials; extern int special_count; /* forward declare to avoid mutual inclusion between specials.h and text_object.h */ struct text_object; /* scanning special arguments */ const char *scan_bar(struct text_object *, const char *, double); const char *scan_gauge(struct text_object *, const char *, double); #ifdef BUILD_X11 void scan_font(struct text_object *, const char *); char *scan_graph(struct text_object *, const char *, double); void scan_tab(struct text_object *, const char *); void scan_stippled_hr(struct text_object *, const char*); /* printing specials */ void new_font(struct text_object *, char *, int); void new_graph(struct text_object *, char *, int, double); void new_hr(struct text_object *, char *, int); void new_stippled_hr(struct text_object *, char *, int); #endif /* BUILD_X11 */ void new_gauge(struct text_object *, char *, int, double); void new_bar(struct text_object *, char *, int, double); void new_fg(struct text_object *, char *, int); void new_bg(struct text_object *, char *, int); void new_outline(struct text_object *, char *, int); void new_offset(struct text_object *, char *, int); void new_voffset(struct text_object *, char *, int); void new_alignr(struct text_object *, char *, int); void new_alignc(struct text_object *, char *, int); void new_goto(struct text_object *, char *, int); void new_tab(struct text_object *, char *, int); struct special_t *new_special(char *buf, enum special_types t); #endif /* _SPECIALS_H */ conky-1.10.1/src/tailhead.cc000066400000000000000000000147111262311664100155740ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "common.h" #include "text_object.h" #include "logging.h" #include #include #include #include #include #include #define MAX_HEADTAIL_LINES 30 #define DEFAULT_MAX_HEADTAIL_USES 2 struct headtail { int wantedlines; std::string logfile; char *buffer; int current_use; int max_uses; int reported; headtail() : wantedlines(0), buffer(NULL), current_use(0), max_uses(0), reported(0) {} ~headtail() { free(buffer); } }; static void tailstring(char *string, int endofstring, int wantedlines) { int i, linescounted = 0; string[endofstring] = 0; if(endofstring > 0) { if(string[endofstring-1] == '\n') { //work with or without \n at end of file string[endofstring-1] = 0; } for(i = endofstring - 1; i >= 0 && linescounted < wantedlines; i--) { if(string[i] == '\n') { linescounted++; } } if(i > 0) { strfold(string, i+2); } } } void free_tailhead(struct text_object *obj) { struct headtail *ht = (struct headtail *)obj->data.opaque; obj->data.opaque = NULL; delete ht; } void init_tailhead(const char* type, const char* arg, struct text_object *obj, void* free_at_crash) { unsigned int args; struct headtail *ht = new headtail; std::unique_ptr tmp(new char[DEFAULT_TEXT_BUFFER_SIZE]); memset(tmp.get(), 0, DEFAULT_TEXT_BUFFER_SIZE); ht->max_uses = DEFAULT_MAX_HEADTAIL_USES; // XXX: Buffer overflow ? args = sscanf(arg, "%s %d %d", tmp.get(), &ht->wantedlines, &ht->max_uses); if (args < 2 || args > 3) { free_tailhead(obj); CRIT_ERR(obj, free_at_crash, "%s needs a file as 1st and a number of lines as 2nd argument", type); } if (ht->max_uses < 1) { free_tailhead(obj); CRIT_ERR(obj, free_at_crash, "invalid arg for %s, next_check must be larger than 0", type); } if (ht->wantedlines > 0 && ht->wantedlines <= MAX_HEADTAIL_LINES) { ht->logfile = to_real_path(tmp.get()); ht->buffer = NULL; ht->current_use = 0; } else { free_tailhead(obj); CRIT_ERR(obj, free_at_crash, "invalid arg for %s, number of lines must be between 1 and %d", type, MAX_HEADTAIL_LINES); } obj->data.opaque = ht; } static void print_tailhead(const char* type, struct text_object *obj, char *p, int p_max_size) { int fd, i, endofstring = 0, linescounted = 0; FILE *fp; struct stat st; struct headtail *ht = (struct headtail *)obj->data.opaque; if (!ht) return; //empty the buffer and reset the counter if we used it the max number of times if(ht->buffer && ht->current_use >= ht->max_uses - 1) { free_and_zero(ht->buffer); ht->current_use = 0; } //use the buffer if possible if(ht->buffer) { strcpy(p, ht->buffer); ht->current_use++; }else{ //otherwise find the needed data if(stat(ht->logfile.c_str(), &st) == 0) { if (S_ISFIFO(st.st_mode)) { fd = open_fifo(ht->logfile.c_str(), &ht->reported); if(fd != -1) { if(strcmp(type, "head") == 0) { for(i = 0; linescounted < ht->wantedlines; i++) { if (read(fd, p + i, 1) <= 0) break; if(p[i] == '\n') { linescounted++; } } p[i] = 0; } else if(strcmp(type, "tail") == 0) { i = read(fd, p, p_max_size - 1); tailstring(p, i, ht->wantedlines); } else { CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); } } close(fd); } else { fp = open_file(ht->logfile.c_str(), &ht->reported); if(fp != NULL) { if(strcmp(type, "head") == 0) { for(i = 0; i < ht->wantedlines; i++) { if (!fgets(p + endofstring, p_max_size - endofstring, fp)) break; endofstring = strlen(p); } } else if(strcmp(type, "tail") == 0) { fseek(fp, - p_max_size, SEEK_END); i = fread(p, 1, p_max_size - 1, fp); tailstring(p, i, ht->wantedlines); } else { CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); } fclose(fp); } } ht->buffer = strdup(p); } else { CRIT_ERR(NULL, NULL, "$%s can't find information about %s", type, ht->logfile.c_str()); } } return; } void print_head(struct text_object *obj, char *p, int p_max_size) { print_tailhead("head", obj, p, p_max_size); } void print_tail(struct text_object *obj, char *p, int p_max_size) { print_tailhead("tail", obj, p, p_max_size); } /* FIXME: use something more general (see also tail.c, head.c */ #define BUFSZ 0x1000 void print_lines(struct text_object *obj, char *p, int p_max_size) { static int rep = 0; FILE *fp = open_file(obj->data.s, &rep); char buf[BUFSZ]; int j, lines; if (!fp) { snprintf(p, p_max_size, "File Unreadable"); return; } lines = 0; while(fgets(buf, BUFSZ, fp) != NULL){ for(j = 0; buf[j] != 0; j++) { if(buf[j] == '\n') { lines++; } } } snprintf(p, p_max_size, "%d", lines); fclose(fp); } void print_words(struct text_object *obj, char *p, int p_max_size) { static int rep = 0; FILE *fp = open_file(obj->data.s, &rep); char buf[BUFSZ]; int j, words; char inword = 0; if(!fp) { snprintf(p, p_max_size, "File Unreadable"); return; } words = 0; while(fgets(buf, BUFSZ, fp) != NULL){ for(j = 0; buf[j] != 0; j++) { if(!isspace(buf[j])) { if(!inword) { words++; inword = 1; } } else { inword = 0; } } } snprintf(p, p_max_size, "%d", words); fclose(fp); } conky-1.10.1/src/tailhead.h000066400000000000000000000030411262311664100154300ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _TAILHEAD_H #define _TAILHEAD_H void free_tailhead(struct text_object *); void init_tailhead(const char *, const char *, struct text_object *, void *); void print_head(struct text_object *, char *, int); void print_tail(struct text_object *, char *, int); void print_lines(struct text_object *, char *, int); void print_words(struct text_object *, char *, int); #endif /* _TAILHEAD_H */ conky-1.10.1/src/tcp-portmon.cc000066400000000000000000000117261262311664100163060ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * tcp-portmon.c - libtcp-portmon hooks * * Copyright (C) 2008 Phil Sutter * * 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 "tcp-portmon.h" #include "text_object.h" #include "libtcp-portmon.h" static tcp_port_monitor_collection_t *pmc = NULL; static conky::range_config_setting max_port_monitor_connections("max_port_monitor_connections", 0, std::numeric_limits::max(), MAX_PORT_MONITOR_CONNECTIONS_DEFAULT, false); int tcp_portmon_init(struct text_object *obj, const char *arg) { int argc, port_begin, port_end, item, connection_index; char itembuf[32]; struct tcp_port_monitor_data *pmd; memset(itembuf, 0, sizeof(itembuf)); connection_index = 0; /* massive argument checking */ argc = sscanf(arg, "%d %d %31s %d", &port_begin, &port_end, itembuf, &connection_index); if ((argc != 3) && (argc != 4)) { CRIT_ERR(NULL, NULL, "tcp_portmon: requires 3 or 4 arguments"); } if ((port_begin < 1) || (port_begin > 65535) || (port_end < 1) || (port_end > 65535)) { CRIT_ERR(NULL, NULL, "tcp_portmon: port values must be from 1 to 65535"); } if (port_begin > port_end) { CRIT_ERR(NULL, NULL, "tcp_portmon: starting port must be <= ending port"); } if (strncmp(itembuf, "count", 31) == EQUAL) { item = COUNT; } else if (strncmp(itembuf, "rip", 31) == EQUAL) { item = REMOTEIP; } else if (strncmp(itembuf, "rhost", 31) == EQUAL) { item = REMOTEHOST; } else if (strncmp(itembuf, "rport", 31) == EQUAL) { item = REMOTEPORT; } else if (strncmp(itembuf, "rservice", 31) == EQUAL) { item = REMOTESERVICE; } else if (strncmp(itembuf, "lip", 31) == EQUAL) { item = LOCALIP; } else if (strncmp(itembuf, "lhost", 31) == EQUAL) { item = LOCALHOST; } else if (strncmp(itembuf, "lport", 31) == EQUAL) { item = LOCALPORT; } else if (strncmp(itembuf, "lservice", 31) == EQUAL) { item = LOCALSERVICE; } else { CRIT_ERR(NULL, NULL, "tcp_portmon: invalid item specified"); } if ((argc == 3) && (item != COUNT)) { CRIT_ERR(NULL, NULL, "tcp_portmon: 3 argument form valid only for \"count\" " "item"); } if ((argc == 4) && (connection_index < 0)) { CRIT_ERR(NULL, NULL, "tcp_portmon: connection index must be non-negative"); } /* ok, args looks good. save the text object data */ pmd = (tcp_port_monitor_data*)malloc(sizeof(struct tcp_port_monitor_data)); memset(pmd, 0, sizeof(struct tcp_port_monitor_data)); pmd->port_range_begin = (in_port_t) port_begin; pmd->port_range_end = (in_port_t) port_end; pmd->item = item; pmd->connection_index = connection_index; obj->data.opaque = pmd; /* if the port monitor collection hasn't been created, * we must create it */ if (!pmc) { pmc = create_tcp_port_monitor_collection(); if (!pmc) { CRIT_ERR(NULL, NULL, "tcp_portmon: unable to create port monitor " "collection"); } } /* if a port monitor for this port does not exist, * create one and add it to the collection */ if (find_tcp_port_monitor(pmc, port_begin, port_end) == NULL) { tcp_port_monitor_args_t pma; memset(&pma, 0, sizeof pma); pma.max_port_monitor_connections = max_port_monitor_connections.get(*state); /* add the newly created monitor to the collection */ if (insert_new_tcp_port_monitor_into_collection(pmc, port_begin, port_end, &pma) != 0) { CRIT_ERR(NULL, NULL, "tcp_portmon: unable to add port monitor to " "collection"); } } return 0; } void tcp_portmon_action(struct text_object *obj, char *p, int p_max_size) { struct tcp_port_monitor_data *pmd = (tcp_port_monitor_data*)obj->data.opaque; tcp_port_monitor_t *p_monitor; if (!pmd) return; /* grab a pointer to this port monitor */ p_monitor = find_tcp_port_monitor(pmc, pmd->port_range_begin, pmd->port_range_end); if (!p_monitor) { snprintf(p, p_max_size, "monitor not found"); return; } /* now grab the text of interest */ if (peek_tcp_port_monitor(p_monitor, pmd->item, pmd->connection_index, p, p_max_size) != 0) { snprintf(p, p_max_size, "monitor peek error"); } } int tcp_portmon_update(void) { update_tcp_port_monitor_collection(pmc); return 0; } int tcp_portmon_clear(void) { destroy_tcp_port_monitor_collection(pmc); pmc = NULL; return 0; } void tcp_portmon_free(struct text_object *obj) { free_and_zero(obj->data.opaque); } conky-1.10.1/src/tcp-portmon.h000066400000000000000000000027751262311664100161540ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * tcp-portmon.h - libtcp-portmon hooks protoypes * * Copyright (C) 2008 Phil Sutter * * 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 _TCP_PORTMON_H #define _TCP_PORTMON_H #include "libtcp-portmon.h" struct tcp_port_monitor_data { /* starting port to monitor */ in_port_t port_range_begin; /* ending port to monitor */ in_port_t port_range_end; /* enum from libtcp-portmon.h, e.g. COUNT, etc. */ int item; /* 0 to n-1 connections. */ int connection_index; }; /* forward declare to make gcc happy */ struct text_object; int tcp_portmon_init(struct text_object *, const char *); void tcp_portmon_action(struct text_object *, char *, int); int tcp_portmon_update(void); int tcp_portmon_clear(void); void tcp_portmon_free(struct text_object *); #endif /* _TCP_PORTMON_H */ conky-1.10.1/src/temphelper.cc000066400000000000000000000041131262311664100161610ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * temphelper.c: aid in converting temperature units * * Copyright (C) 2008 Phil Sutter * * This library 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 2 of the License, or * (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #include "config.h" #include #include #include #include #include #include "temphelper.h" #include "conky.h" template<> conky::lua_traits::Map conky::lua_traits::map = { { "celsius", TEMP_CELSIUS }, { "fahrenheit", TEMP_FAHRENHEIT } }; static conky::simple_config_setting output_unit("temperature_unit", TEMP_CELSIUS, true); static double fahrenheit_to_celsius(double n) { return ((n - 32) * 5 / 9); } static double celsius_to_fahrenheit(double n) { return ((n * 9 / 5) + 32); } static double convert_temp_output(double n, enum TEMP_UNIT input_unit) { if (input_unit == output_unit.get(*state)) return n; switch(output_unit.get(*state)) { case TEMP_CELSIUS: return fahrenheit_to_celsius(n); case TEMP_FAHRENHEIT: return celsius_to_fahrenheit(n); } /* NOT REACHED */ return 0.0; } int temp_print(char *p, size_t p_max_size, double n, enum TEMP_UNIT input_unit) { int out; size_t plen; out = round_to_int_temp(convert_temp_output(n, input_unit)); plen = spaced_print(p, p_max_size, "%d", 3, out); return !(plen >= p_max_size); } conky-1.10.1/src/temphelper.h000066400000000000000000000021571262311664100160310ustar00rootroot00000000000000/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=cpp * * temphelper.h: aid in converting temperature units * * Copyright (C) 2008 Phil Sutter * * This library 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 2 of the License, or * (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA. * */ #ifndef TEMPHELPER_H #define TEMPHELPER_H enum TEMP_UNIT { TEMP_CELSIUS, TEMP_FAHRENHEIT }; int temp_print(char *, size_t, double, enum TEMP_UNIT); #endif /* TEMPHELPER_H */ conky-1.10.1/src/template.cc000066400000000000000000000150311262311664100156300ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 namespace { conky::simple_config_setting _template[10] = { { "template0", std::string(), true }, { "template1", std::string(), true }, { "template2", std::string(), true }, { "template3", std::string(), true }, { "template4", std::string(), true }, { "template5", std::string(), true }, { "template6", std::string(), true }, { "template7", std::string(), true }, { "template8", std::string(), true }, { "template9", std::string(), true } }; } /* backslash_escape - do the actual substitution task for template objects * * The field templates is used for substituting the \N occurences. Set it to * NULL to leave them as they are. */ static char *backslash_escape(const char *src, char **templates, unsigned int template_count) { char *src_dup; const char *p; unsigned int dup_idx = 0, dup_len; dup_len = strlen(src) + 1; src_dup = (char*) malloc(dup_len * sizeof(char)); p = src; while (*p) { switch (*p) { case '\\': if (!*(p + 1)) break; if (*(p + 1) == '\\') { src_dup[dup_idx++] = '\\'; p++; } else if (*(p + 1) == ' ') { src_dup[dup_idx++] = ' '; p++; } else if (*(p + 1) == 'n') { src_dup[dup_idx++] = '\n'; p++; } else if (templates) { unsigned int tmpl_num; int digits; if ((sscanf(p + 1, "%u%n", &tmpl_num, &digits) <= 0) || (tmpl_num > template_count)) break; if (tmpl_num == 0) CRIT_ERR(NULL, NULL, "invalid template argument \\0; arguments must start at \\1"); dup_len += strlen(templates[tmpl_num - 1]); src_dup = (char*) realloc(src_dup, dup_len * sizeof(char)); sprintf(src_dup + dup_idx, "%s", templates[tmpl_num - 1]); dup_idx += strlen(templates[tmpl_num - 1]); p += digits; } break; default: src_dup[dup_idx++] = *p; break; } p++; } src_dup[dup_idx] = '\0'; src_dup = (char*) realloc(src_dup, (strlen(src_dup) + 1) * sizeof(char)); return src_dup; } /* handle_template_object - core logic of the template object * * use config variables like this: * template1 = "$\1\2" * template2 = "\1: ${fs_bar 4,100 \2} ${fs_used \2} / ${fs_size \2}" * * and use them like this: * ${template1 node name} * ${template2 root /} * ${template2 cdrom /mnt/cdrom} */ static char *handle_template(const char *tmpl, const char *args) { char *args_dup = NULL; char *p, *p_old; char **argsp = NULL; unsigned int argcnt = 0, template_idx, i; char *eval_text; if ((sscanf(tmpl, "template%u", &template_idx) != 1) || (template_idx >= MAX_TEMPLATES)) return NULL; if(args) { args_dup = strdup(args); p = args_dup; while (*p) { while (*p && (*p == ' ' && (p == args_dup || *(p - 1) != '\\'))) p++; if (p > args_dup && *(p - 1) == '\\') p--; p_old = p; while (*p && (*p != ' ' || (p > args_dup && *(p - 1) == '\\'))) p++; if (*p) { (*p) = '\0'; p++; } argsp = (char**) realloc(argsp, ++argcnt * sizeof(char *)); argsp[argcnt - 1] = p_old; } for (i = 0; i < argcnt; i++) { char *tmp; tmp = backslash_escape(argsp[i], NULL, 0); DBGP2("%s: substituted arg '%s' to '%s'", tmpl, argsp[i], tmp); argsp[i] = tmp; } } eval_text = backslash_escape(_template[template_idx].get(*state).c_str(), argsp, argcnt); DBGP("substituted %s, output is '%s'", tmpl, eval_text); free(args_dup); for (i = 0; i < argcnt; i++) free(argsp[i]); free(argsp); return eval_text; } /* Search inbuf and replace all found template object references * with the substituted value. */ char *find_and_replace_templates(const char *inbuf) { char *outbuf, *indup, *p, *o, *templ, *args, *tmpl_out; int stack, outlen; outlen = strlen(inbuf) + 1; o = outbuf = (char*) calloc(outlen, sizeof(char)); memset(outbuf, 0, outlen * sizeof(char)); p = indup = strdup(inbuf); while (*p) { while (*p && *p != '$') *(o++) = *(p++); if (!(*p)) break; if (strncmp(p, "$template", strlen("$template")) && strncmp(p, "${template", strlen("${template"))) { *(o++) = *(p++); continue; } if (*(p + 1) == '{') { p += 2; templ = p; while (*p && !isspace(*p) && *p != '{' && *p != '}') p++; if (*p == '}') args = NULL; else args = p; stack = 1; while (*p && stack > 0) { if (*p == '{') stack++; else if (*p == '}') stack--; p++; } if (stack == 0) { // stack is empty. that means the previous char was }, so we zero it *(p - 1) = '\0'; } else { // we ran into the end of string without finding a closing }, bark CRIT_ERR(NULL, NULL, "cannot find a closing '}' in template expansion"); } } else { templ = p + 1; p += strlen("$template"); while (*p && isdigit(*p)) p++; args = NULL; } tmpl_out = handle_template(templ, args); if (tmpl_out) { outlen += strlen(tmpl_out); *o = '\0'; outbuf = (char*) realloc(outbuf, outlen * sizeof(char)); strcat (outbuf, tmpl_out); free(tmpl_out); o = outbuf + strlen(outbuf); } else { NORM_ERR("failed to handle template '%s' with args '%s'", templ, args); } } *o = '\0'; outbuf = (char*) realloc(outbuf, (strlen(outbuf) + 1) * sizeof(char)); free(indup); return outbuf; } /* check text for any template object references */ int text_contains_templates(const char *text) { if (strcasestr(text, "${template") != NULL) return 1; if (strcasestr(text, "$template") != NULL) return 1; return 0; } conky-1.10.1/src/template.h000066400000000000000000000024551262311664100155000ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _TEMPLATE_H #define _TEMPLATE_H char *find_and_replace_templates(const char *); int text_contains_templates(const char *); #endif /* _TEMPLATE_H */ conky-1.10.1/src/text_object.cc000066400000000000000000000130571262311664100163350ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 "config.h" #include "text_object.h" #include "logging.h" #include #include #include void gen_free_opaque(struct text_object *obj) { free_and_zero(obj->data.opaque); } int gen_false_iftest(struct text_object *obj) { (void)obj; return 0; } void gen_print_nothing(struct text_object *obj, char *p, int p_max_size) { (void)obj; (void)p; (void)p_max_size; } void gen_print_obj_data_s(struct text_object *obj, char *p, int p_max_size) { if (!obj->data.s) return; snprintf(p, p_max_size, "%s", obj->data.s); } /* text_object_list * * this list is special. it looks like this: * NULL <-- obj1 <--> obj2 <--> ... <--> objN --> NULL * ^-------root_object----------^ * directions are reversed here * * why this is cool: * - root_object points both to the start and end of the list * - while traversing, the end of the list is always a NULL pointer * (this works in BOTH directions) */ /* append an object or list of objects to the given root object's list */ int append_object(struct text_object *root, struct text_object *obj) { struct text_object *end; /* hook in start of list to append */ end = root->prev; obj->prev = end; /* update pointers of the list to append to */ if (end) { if (end->next) CRIT_ERR(NULL, NULL, "huston, we have a lift-off"); end->next = obj; } else { root->next = obj; } /* find end of appended list to point root->prev there */ while (obj->next) obj = obj->next; root->prev = obj; return 0; } /* ifblock handlers for the object list * * - each if points to it's else or endif * - each else points to it's endif * */ /* possible ifblock types * only used internally, so no need to make this public */ enum ifblock_type { IFBLOCK_IF = 1, IFBLOCK_ELSE, IFBLOCK_ENDIF }; /* linked list of ifblock objects, building a stack * only used internally, so no need to make this public */ struct ifblock_stack_obj { enum ifblock_type type; struct text_object *obj; struct ifblock_stack_obj *next; }; /* push an ifblock object onto the stack * in fact, this does a lot more: * - IFBLOCK_IF is just pushed onto the stack * - IFBLOCK_ELSE updates the "next" pointer of the upmost * object in the stack and is then pushed onto the stack * - IFBLOCK_ENDIF updates the "next" pointer of the upmost * object in the stack and then triggers stack popping of * any optional IFBLOCK_ELSE along with it's IFBLOCK_IF */ static int push_ifblock(struct ifblock_stack_obj **ifblock_stack_top, struct text_object *obj, enum ifblock_type type) { struct ifblock_stack_obj *stackobj; switch (type) { case IFBLOCK_ENDIF: if (!(*ifblock_stack_top)) CRIT_ERR(NULL, NULL, "got an endif without matching if"); (*ifblock_stack_top)->obj->ifblock_next = obj; /* if there's some else in between, remove and free it */ if ((*ifblock_stack_top)->type == IFBLOCK_ELSE) { stackobj = *ifblock_stack_top; *ifblock_stack_top = stackobj->next; free(stackobj); } /* finally remove and free the if object */ stackobj = *ifblock_stack_top; *ifblock_stack_top = stackobj->next; free(stackobj); break; case IFBLOCK_ELSE: if (!(*ifblock_stack_top)) CRIT_ERR(NULL, NULL, "got an else without matching if"); (*ifblock_stack_top)->obj->ifblock_next = obj; /* fall through */ case IFBLOCK_IF: stackobj = (ifblock_stack_obj*) malloc(sizeof(struct ifblock_stack_obj)); stackobj->type = type; stackobj->obj = obj; stackobj->next = *ifblock_stack_top; *ifblock_stack_top = stackobj; break; default: CRIT_ERR(NULL, NULL, "push_ifblock() missuse detected!"); } return 0; } /* public functions for client use */ int obj_be_ifblock_if(void **opaque, struct text_object *obj) { return push_ifblock((struct ifblock_stack_obj **)opaque, obj, IFBLOCK_IF); } int obj_be_ifblock_else(void **opaque, struct text_object *obj) { return push_ifblock((struct ifblock_stack_obj **)opaque, obj, IFBLOCK_ELSE); } int obj_be_ifblock_endif(void **opaque, struct text_object *obj) { return push_ifblock((struct ifblock_stack_obj **)opaque, obj, IFBLOCK_ENDIF); } /* check if ifblock stack is empty * if so, return true (!= 0) */ int ifblock_stack_empty(void **opaque) { return *opaque == NULL; } void obj_be_plain_text(struct text_object *obj, const char *text) { obj->data.s = strdup(text); memset(&obj->callbacks, 0, sizeof(obj->callbacks)); obj->callbacks.print = &gen_print_obj_data_s; obj->callbacks.free = &gen_free_opaque; } conky-1.10.1/src/text_object.h000066400000000000000000000105421262311664100161730ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _TEXT_OBJECT_H #define _TEXT_OBJECT_H #include /* uint8_t */ #include "config.h" /* for the defines */ #include "specials.h" /* enum special_types */ #include "update-cb.hh" /* text object callbacks */ struct obj_cb { /* text object: print obj's output to p */ void (*print)(struct text_object *obj, char *p, int p_max_size); /* ifblock object: return zero to trigger jumping */ int (*iftest)(struct text_object *obj); /* meter objects: * The following functions return the current meter-type value * in a range between 0 and the value passed to the appropriate * scan_* function. Or, if named function has been called with * a value of 0, make use of auto-scaling (i.e., scaling to the * maximum value seen so far). */ double (*barval)(struct text_object *obj); double (*gaugeval)(struct text_object *obj); double (*graphval)(struct text_object *obj); /* percentage object: return value in range [0, 100] */ uint8_t (*percentage)(struct text_object *obj); /* free obj's data */ void (*free)(struct text_object *obj); }; /* generic free opaque callback * can be used to simply free obj->data.opaque or obj->data.s */ void gen_free_opaque(struct text_object *); /* generic iftest returning false (i.e. trigger jumping) * used for the else object */ int gen_false_iftest(struct text_object *); /* generic nothing printer callback printing nothing * used for the endif object */ void gen_print_nothing(struct text_object *, char *, int); /* generic obj->data.s printer * used by the $text object */ void gen_print_obj_data_s(struct text_object *, char *, int); class legacy_cb: public conky::callback { typedef conky::callback Base; protected: virtual void work() { std::get<0>(tuple)(); } public: legacy_cb(uint32_t period, int (*fn)()) : Base(period, true, Base::Tuple(fn)) {} }; typedef conky::callback_handle legacy_cb_handle; struct text_object { struct text_object *next, *prev; /* doubly linked list of text objects */ struct text_object *sub; /* for objects parsing text into objects */ struct text_object *ifblock_next; /* jump target for ifblock objects */ union { void *opaque; /* new style generic per object data */ char *s; /* some string */ int i; /* some integer */ long l; /* some long integer */ } data; void *special_data; long line; struct obj_cb callbacks; bool parse; //if this true then data.s should still be parsed bool thread; //if this true then data.s should be set by a seperate thread legacy_cb_handle *cb_handle; }; /* text object list helpers */ int append_object(struct text_object *root, struct text_object *obj); /* ifblock helpers * * Opaque is a pointer to the address of the ifblock stack's top object. * Calling clients should pass the address of a defined void pointer which * was initialised to NULL (empty stack). * */ int obj_be_ifblock_if(void **opaque, struct text_object *); int obj_be_ifblock_else(void **opaque, struct text_object *); int obj_be_ifblock_endif(void **opaque, struct text_object *); int ifblock_stack_empty(void **opaque); /* make the given object be a plain text object printing given string */ void obj_be_plain_text(struct text_object *, const char *); #endif /* _TEXT_OBJECT_H */ conky-1.10.1/src/timeinfo.cc000066400000000000000000000203311262311664100156260ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "timeinfo.h" #include "conky.h" #include "text_object.h" #include #include #include #include #include "logging.h" #include struct tztime_s { char *tz; /* timezone variable */ char *fmt; /* time display formatting */ }; conky::simple_config_setting times_in_seconds("times_in_seconds", false, false); void scan_time(struct text_object *obj, const char *arg) { obj->data.opaque = strndup(arg ? arg : "%F %T", text_buffer_size.get(*state)); } void scan_tztime(struct text_object *obj, const char *arg) { char buf1[256], buf2[256], *fmt, *tz; struct tztime_s *ts; fmt = tz = NULL; if (arg) { int nArgs = sscanf(arg, "%255s %255[^\n]", buf1, buf2); switch (nArgs) { case 2: fmt = buf2; case 1: tz = buf1; } } ts = (tztime_s*) malloc(sizeof(struct tztime_s)); memset(ts, 0, sizeof(struct tztime_s)); ts->fmt = strndup(fmt ? fmt : "%F %T", text_buffer_size.get(*state)); ts->tz = tz ? strndup(tz, text_buffer_size.get(*state)) : NULL; obj->data.opaque = ts; } void print_time(struct text_object *obj, char *p, int p_max_size) { time_t t = time(NULL); struct tm *tm = localtime(&t); setlocale(LC_TIME, ""); strftime(p, p_max_size, (char *)obj->data.opaque, tm); } void print_utime(struct text_object *obj, char *p, int p_max_size) { time_t t = time(NULL); struct tm *tm = gmtime(&t); setlocale(LC_TIME, ""); strftime(p, p_max_size, (char *)obj->data.opaque, tm); } void print_tztime(struct text_object *obj, char *p, int p_max_size) { char *oldTZ = NULL; time_t t; struct tm *tm; struct tztime_s *ts = (tztime_s*) obj->data.opaque; if (!ts) return; if (ts->tz) { oldTZ = getenv("TZ"); setenv("TZ", ts->tz, 1); tzset(); } t = time(NULL); tm = localtime(&t); setlocale(LC_TIME, ""); strftime(p, p_max_size, ts->fmt, tm); if (oldTZ) { setenv("TZ", oldTZ, 1); tzset(); } else { unsetenv("TZ"); } // Needless to free oldTZ since getenv gives ptr to static data } void free_time(struct text_object *obj) { free_and_zero(obj->data.opaque); } void free_tztime(struct text_object *obj) { struct tztime_s *ts = (tztime_s*) obj->data.opaque; if (!ts) return; free_and_zero(ts->tz); free_and_zero(ts->fmt); free_and_zero(obj->data.opaque); } /* a safer asprintf() * - no need to check for errors * - exit conky on memory allocation failure * - XXX: no return value at all, otherwise this * could be used globally */ #define safe_asprintf(bufp, ...) { \ int __v; \ if ((__v = asprintf(bufp, __VA_ARGS__)) == -1) { \ fprintf(stderr, "%s: memory allocation failed\n", __func__); \ exit(__v); \ } \ } //all chars after the ending " and between the seconds and the starting " are silently //ignored, this is wanted behavior, not a bug, so don't "fix" this. static void do_format_time(struct text_object *obj, char *p, unsigned int p_max_size) { double seconds; char *currentchar, *temp; unsigned int output_length = 0; int minutes, hours, days, weeks; char show_minutes = 0, show_hours = 0, show_days = 0, show_weeks = 0, hidestring; if (not times_in_seconds.get(*state)) { NORM_ERR("Enable \"times_in_seconds\" to use $format_time"); return; } errno = 0; seconds = strtod(obj->data.s, ¤tchar); if(errno == 0 && obj->data.s != currentchar) { while(*currentchar != 0 && *currentchar != '"') { currentchar++; } if(*currentchar != 0) { currentchar++; minutes = seconds / 60; seconds -= minutes * 60; hours = minutes / 60; minutes %= 60; days = hours / 24; hours %= 24; weeks = days / 7; days %= 7; for(temp = currentchar; *temp != 0 && *temp != '"'; temp++) { if(*temp=='\\') { switch(*(temp+1)) { case '\\': temp++; break; case 'w': show_weeks = 1; break; case 'd': show_days = 1; break; case 'h': show_hours = 1; break; case 'm': show_minutes = 1; break; } } } if(show_weeks == 0) days += weeks * 7; if(show_days == 0) hours += days * 24; if(show_hours == 0) minutes += hours * 60; if(show_minutes == 0) seconds += minutes * 60; hidestring = 0; while(output_length < p_max_size - 1) { if(*currentchar != 0 && *currentchar != '"') { temp = NULL; if(*currentchar == '\\' && hidestring == 0) { currentchar++; switch(*currentchar){ case 'w': safe_asprintf(&temp, "%d", weeks); break; case 'd': safe_asprintf(&temp, "%d", days); break; case 'h': safe_asprintf(&temp, "%d", hours); break; case 'm': safe_asprintf(&temp, "%d", minutes); break; case 's': safe_asprintf(&temp, "%d", (int) seconds); break; case 'S': currentchar++; if(*currentchar >= '0' && *currentchar <= '9') { safe_asprintf(&temp, "%.*f", (*currentchar) - '0', seconds); } else if(*currentchar == 'x') { if(seconds == (int) seconds ) { safe_asprintf(&temp, "%d", (int) seconds); } else { safe_asprintf(&temp, "%.9f", seconds); while(*(temp + strlen(temp) - 1) == '0' || *(temp + strlen(temp) - 1) == '.') { *(temp + strlen(temp) - 1) = 0; } } }else{ currentchar--; NORM_ERR("$format_time needs a digit behind 'S' to specify precision"); } break; case '\\': case '(': case ')': p[output_length] = *currentchar; output_length++; break; default: NORM_ERR("$format_time doesn't have a special char '%c'", *currentchar); } } else if(*currentchar == '(') { for(temp = currentchar + 1; *temp != 0 && *temp != ')'; temp++) { if(*(temp-1) == '\\') { switch(*temp) { case 'w': if(weeks == 0) hidestring = 1; break; case 'd': if(days == 0) hidestring = 1; break; case 'h': if(hours == 0) hidestring = 1; break; case 'm': if(minutes == 0) hidestring = 1; break; case 's': case 'S': if(seconds == 0) hidestring = 1; break; } } } temp = NULL; } else if(*currentchar == ')') { hidestring = 0; } else if(hidestring == 0) { p[output_length] = *currentchar; output_length++; } if(temp) { if(output_length + strlen(temp) < p_max_size - 1) { strcpy(p + output_length, temp); output_length += strlen(temp); } else NORM_ERR("The format string for $format_time is too long"); free(temp); } currentchar++; } else break; } p[output_length] = 0; } else { NORM_ERR("$format_time needs a output-format starting with a \"-char as 2nd argument"); } } else { NORM_ERR("$format_time didn't receive a time in seconds as first argument"); } } void print_format_time(struct text_object *obj, char *p, int p_max_size) { std::unique_ptr buf(new char[max_user_text.get(*state)]); generate_text_internal(buf.get(), max_user_text.get(*state), *obj->sub); obj->data.s = buf.get(); do_format_time(obj, p, p_max_size); } conky-1.10.1/src/timeinfo.h000066400000000000000000000036151262311664100154760ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _TIMEINFO_H #define _TIMEINFO_H #include "setting.hh" extern conky::simple_config_setting times_in_seconds; /* since time and utime are quite equal, certain functions * are shared in between both text object types. */ /* parse args passed to *time objects */ void scan_time(struct text_object *, const char *); void scan_tztime(struct text_object *, const char *); /* print the time */ void print_time(struct text_object *, char *, int); void print_utime(struct text_object *, char *, int); void print_tztime(struct text_object *, char *, int); void print_format_time(struct text_object *obj, char *p, int p_max_size); /* free object data */ void free_time(struct text_object *); void free_tztime(struct text_object *); #endif /* _TIMEINFO_H */ conky-1.10.1/src/top.cc000066400000000000000000000422751262311664100146310ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005 Adi Zaimi, Dan Piponi , * Dave Clark * Copyright (c) 2005-2012 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 "prioqueue.h" #include "top.h" #include "logging.h" /* hash table size - always a power of 2 */ #define HTABSIZE 256 struct process *first_process = 0; unsigned long g_time = 0; /* a simple hash table to speed up find_process() */ struct proc_hash_entry { struct proc_hash_entry *next; struct process *proc; }; static struct proc_hash_entry proc_hash_table[HTABSIZE]; static void hash_process(struct process *p) { struct proc_hash_entry *phe; static char first_run = 1; int bucket; /* better make sure all next pointers are zero upon first access */ if (first_run) { memset(proc_hash_table, 0, sizeof(struct proc_hash_entry) * HTABSIZE); first_run = 0; } /* get the bucket index */ bucket = p->pid & (HTABSIZE - 1); /* insert a new element on bucket's top */ phe = (struct proc_hash_entry *)malloc(sizeof(struct proc_hash_entry)); phe->proc = p; phe->next = proc_hash_table[bucket].next; proc_hash_table[bucket].next = phe; } static void unhash_process(struct process *p) { struct proc_hash_entry *phe, *tmp; /* get the bucket head */ phe = &proc_hash_table[p->pid & (HTABSIZE - 1)]; /* find the entry pointing to p and drop it */ while (phe->next) { if (phe->next->proc == p) { tmp = phe->next; phe->next = phe->next->next; free(tmp); return; } phe = phe->next; } } static void __unhash_all_processes(struct proc_hash_entry *phe) { if (phe->next) __unhash_all_processes(phe->next); free(phe->next); } static void unhash_all_processes(void) { int i; for (i = 0; i < HTABSIZE; i++) { __unhash_all_processes(&proc_hash_table[i]); proc_hash_table[i].next = NULL; } } struct process *get_first_process(void) { return first_process; } void free_all_processes(void) { struct process *next = NULL, *pr = first_process; while (pr) { next = pr->next; free_and_zero(pr->name); free_and_zero(pr->basename); free(pr); pr = next; } first_process = NULL; /* drop the whole hash table */ unhash_all_processes(); } struct process *get_process_by_name(const char *name) { struct process *p = first_process; while (p) { /* Try matching against the full command line first. If that fails, * fall back to the basename. */ if ((p->name && !strcmp(p->name, name)) || (p->basename && !strcmp(p->basename, name))) return p; p = p->next; } return 0; } static struct process *find_process(pid_t pid) { struct proc_hash_entry *phe; phe = &proc_hash_table[pid & (HTABSIZE - 1)]; while (phe->next) { if (phe->next->proc->pid == pid) return phe->next->proc; phe = phe->next; } return NULL; } static struct process *new_process(pid_t pid) { struct process *p = (struct process *) malloc(sizeof(struct process)); /* Do stitching necessary for doubly linked list */ p->previous = NULL; p->next = first_process; if (p->next) { p->next->previous = p; } first_process = p; p->pid = pid; p->name = 0; p->basename = 0; p->amount = 0; p->user_time = 0; p->total = 0; p->kernel_time = 0; p->previous_user_time = ULONG_MAX; p->previous_kernel_time = ULONG_MAX; p->total_cpu_time = 0; p->vsize = 0; p->rss = 0; #ifdef BUILD_IOSTATS p->read_bytes = 0; p->previous_read_bytes = ULLONG_MAX; p->write_bytes = 0; p->previous_write_bytes = ULLONG_MAX; p->io_perc = 0; #endif /* BUILD_IOSTATS */ p->time_stamp = 0; p->counted = 1; p->changed = 0; /* process_find_name(p); */ /* add the process to the hash table */ hash_process(p); return p; } /* Get / create a new process object and insert it into the process list */ struct process *get_process(pid_t pid) { struct process *p = find_process(pid); return p ? p : new_process(pid); } /****************************************** * Functions * ******************************************/ /****************************************** * Destroy and remove a process * ******************************************/ static void delete_process(struct process *p) { #if defined(PARANOID) assert(p->id == 0x0badfeed); /* * Ensure that deleted processes aren't reused. */ p->id = 0x007babe; #endif /* defined(PARANOID) */ /* * Maintain doubly linked list. */ if (p->next) p->next->previous = p->previous; if (p->previous) p->previous->next = p->next; else first_process = p->next; free_and_zero(p->name); free_and_zero(p->basename); /* remove the process from the hash table */ unhash_process(p); free(p); } /****************************************** * Strip dead process entries * ******************************************/ static void process_cleanup(void) { struct process *p = first_process; while (p) { struct process *current = p; #if defined(PARANOID) assert(p->id == 0x0badfeed); #endif /* defined(PARANOID) */ p = p->next; /* Delete processes that have died */ if (current->time_stamp != g_time) { delete_process(current); } } } /****************************************** * Find the top processes * ******************************************/ /* cpu comparison function for prio queue */ static int compare_cpu(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; if (b->amount > a->amount) { return 1; } else if (a->amount > b->amount) { return -1; } else { return 0; } } /* mem comparison function for prio queue */ static int compare_mem(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; if (b->rss > a->rss) { return 1; } else if (a->rss > b->rss) { return -1; } else { return 0; } } /* CPU time comparision function for prio queue */ static int compare_time(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; if (b->total_cpu_time > a->total_cpu_time) { return 1; } else if (b->total_cpu_time < a->total_cpu_time) { return -1; } else { return 0; } } #ifdef BUILD_IOSTATS /* I/O comparision function for prio queue */ static int compare_io(void *va, void *vb) { struct process *a = (struct process *)va, *b = (struct process *)vb; if (b->io_perc > a->io_perc) { return 1; } else if (a->io_perc > b->io_perc) { return -1; } else { return 0; } } #endif /* BUILD_IOSTATS */ /* ****************************************************************** * * Get a sorted list of the top cpu hogs and top mem hogs. * * Results are stored in the cpu,mem arrays in decreasing order[0-9]. * * ****************************************************************** */ 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; #ifdef BUILD_IOSTATS prio_queue_t io_queue; #endif struct process *cur_proc = NULL; int i; if (!top_cpu && !top_mem && !top_time #ifdef BUILD_IOSTATS && !top_io #endif /* BUILD_IOSTATS */ && !top_running ) { return; } cpu_queue = init_prio_queue(); pq_set_compare(cpu_queue, &compare_cpu); pq_set_max_size(cpu_queue, MAX_SP); mem_queue = init_prio_queue(); pq_set_compare(mem_queue, &compare_mem); pq_set_max_size(mem_queue, MAX_SP); time_queue = init_prio_queue(); pq_set_compare(time_queue, &compare_time); pq_set_max_size(time_queue, MAX_SP); #ifdef BUILD_IOSTATS io_queue = init_prio_queue(); pq_set_compare(io_queue, &compare_io); pq_set_max_size(io_queue, MAX_SP); #endif /* 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 */ cur_proc = first_process; while (cur_proc != NULL) { if (top_cpu) { insert_prio_elem(cpu_queue, cur_proc); } if (top_mem) { insert_prio_elem(mem_queue, cur_proc); } if (top_time) { insert_prio_elem(time_queue, cur_proc); } #ifdef BUILD_IOSTATS if (top_io) { insert_prio_elem(io_queue, cur_proc); } #endif /* BUILD_IOSTATS */ cur_proc = cur_proc->next; } for (i = 0; i < MAX_SP; i++) { if (top_cpu) cpu[i] = (process*)pop_prio_elem(cpu_queue); if (top_mem) mem[i] = (process*)pop_prio_elem(mem_queue); if (top_time) ptime[i] = (process*)pop_prio_elem(time_queue); #ifdef BUILD_IOSTATS if (top_io) io[i] = (process*)pop_prio_elem(io_queue); #endif /* BUILD_IOSTATS */ } free_prio_queue(cpu_queue); free_prio_queue(mem_queue); free_prio_queue(time_queue); #ifdef BUILD_IOSTATS free_prio_queue(io_queue); #endif /* BUILD_IOSTATS */ } int update_top(void) { // XXX: this was a separate callback. and it should be again, as soon as it's possible update_meminfo(); 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]; unsigned long nt; // narrow time, for speed on 32-bit unsigned cc; // centiseconds unsigned nn; // multi-purpose whatever nt = timeval; cc = nt % 100; // centiseconds past second nt /= 100; // total seconds nn = nt % 60; // seconds past the minute nt /= 60; // total minutes if (width >= snprintf(buf, sizeof buf, "%lu:%02u.%02u", nt, nn, cc)) { return strndup(buf, text_buffer_size.get(*state)); } if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) { return strndup(buf, text_buffer_size.get(*state)); } nn = nt % 60; // minutes past the hour nt /= 60; // total hours if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) { return strndup(buf, text_buffer_size.get(*state)); } nn = nt; // now also hours if (width >= snprintf(buf, sizeof buf, "%uh", nn)) { return strndup(buf, text_buffer_size.get(*state)); } nn /= 24; // now days if (width >= snprintf(buf, sizeof buf, "%ud", nn)) { return strndup(buf, text_buffer_size.get(*state)); } nn /= 7; // now weeks if (width >= snprintf(buf, sizeof buf, "%uw", nn)) { return strndup(buf, text_buffer_size.get(*state)); } // well shoot, this outta' fit... return strndup("", text_buffer_size.get(*state)); } struct top_data { struct process **list; int num; int was_parsed; char *s; }; static conky::range_config_setting top_name_width("top_name_width", 0, std::numeric_limits::max(), 15, true); static conky::simple_config_setting top_name_verbose("top_name_verbose", false, true); static void print_top_name(struct text_object *obj, char *p, int p_max_size) { struct top_data *td = (struct top_data *)obj->data.opaque; int width; if (!td || !td->list || !td->list[td->num]) return; width = MIN(p_max_size, (int)top_name_width.get(*state) + 1); if (top_name_verbose.get(*state)) { /* print the full command line */ snprintf(p, width + 1, "%-*s", width, td->list[td->num]->name); } else { /* print only the basename (i.e. executable name) */ snprintf(p, width + 1, "%-*s", width, td->list[td->num]->basename); } } static void print_top_mem(struct text_object *obj, char *p, int p_max_size) { struct top_data *td = (struct top_data *)obj->data.opaque; int width; if (!td || !td->list || !td->list[td->num]) return; width = MIN(p_max_size, 7); snprintf(p, width, "%6.2f", (float) ((float)td->list[td->num]->rss / info.memmax) / 10); } static void print_top_time(struct text_object *obj, char *p, int p_max_size) { struct top_data *td = (struct top_data *)obj->data.opaque; int width; char *timeval; if (!td || !td->list || !td->list[td->num]) return; width = MIN(p_max_size, 10); timeval = format_time(td->list[td->num]->total_cpu_time, 9); snprintf(p, width, "%9s", timeval); free(timeval); } static void print_top_user(struct text_object *obj, char *p, int p_max_size) { struct top_data *td = (struct top_data *)obj->data.opaque; if (!td || !td->list || !td->list[td->num]) return; snprintf(p, p_max_size, "%.8s", getpwuid(td->list[td->num]->uid)->pw_name); } #define PRINT_TOP_GENERATOR(name, width, fmt, field) \ static void print_top_##name(struct text_object *obj, char *p, int p_max_size) \ { \ struct top_data *td = (struct top_data *)obj->data.opaque; \ if (!td || !td->list || !td->list[td->num]) \ return; \ snprintf(p, MIN(p_max_size, width), fmt, td->list[td->num]->field); \ } #define PRINT_TOP_HR_GENERATOR(name, field, denom) \ static void print_top_##name(struct text_object *obj, char *p, int p_max_size) \ { \ struct top_data *td = (struct top_data *)obj->data.opaque; \ if (!td || !td->list || !td->list[td->num]) \ return; \ human_readable(td->list[td->num]->field / denom, p, p_max_size); \ } PRINT_TOP_GENERATOR(cpu, 7, "%6.2f", amount) PRINT_TOP_GENERATOR(pid, 6, "%5i", pid) PRINT_TOP_GENERATOR(uid, 6, "%5i", uid) PRINT_TOP_HR_GENERATOR(mem_res, rss, 1) PRINT_TOP_HR_GENERATOR(mem_vsize, vsize, 1) #ifdef BUILD_IOSTATS PRINT_TOP_HR_GENERATOR(read_bytes, read_bytes, active_update_interval()) PRINT_TOP_HR_GENERATOR(write_bytes, write_bytes, active_update_interval()) PRINT_TOP_GENERATOR(io_perc, 7, "%6.2f", io_perc) #endif /* BUILD_IOSTATS */ static void free_top(struct text_object *obj) { struct top_data *td = (struct top_data *)obj->data.opaque; if (!td) return; free_and_zero(td->s); free_and_zero(obj->data.opaque); } int parse_top_args(const char *s, const char *arg, struct text_object *obj) { struct top_data *td; char buf[64]; int n; if (!arg) { NORM_ERR("top needs arguments"); return 0; } obj->data.opaque = td = (struct top_data *)malloc(sizeof(struct top_data)); memset(td, 0, sizeof(struct top_data)); if (s[3] == 0) { td->list = info.cpu; top_cpu = 1; } else if (strcmp(&s[3], "_mem") == EQUAL) { td->list = info.memu; top_mem = 1; } else if (strcmp(&s[3], "_time") == EQUAL) { td->list = info.time; top_time = 1; #ifdef BUILD_IOSTATS } else if (strcmp(&s[3], "_io") == EQUAL) { td->list = info.io; top_io = 1; #endif /* BUILD_IOSTATS */ } else { #ifdef BUILD_IOSTATS NORM_ERR("Must be top, top_mem, top_time or top_io"); #else /* BUILD_IOSTATS */ NORM_ERR("Must be top, top_mem or top_time"); #endif /* BUILD_IOSTATS */ free_and_zero(obj->data.opaque); return 0; } td->s = strndup(arg, text_buffer_size.get(*state)); if (sscanf(arg, "%63s %i", buf, &n) == 2) { if (strcmp(buf, "name") == EQUAL) { obj->callbacks.print = &print_top_name; } else if (strcmp(buf, "cpu") == EQUAL) { obj->callbacks.print = &print_top_cpu; } else if (strcmp(buf, "pid") == EQUAL) { obj->callbacks.print = &print_top_pid; } else if (strcmp(buf, "mem") == EQUAL) { obj->callbacks.print = &print_top_mem; } else if (strcmp(buf, "time") == EQUAL) { obj->callbacks.print = &print_top_time; } else if (strcmp(buf, "mem_res") == EQUAL) { obj->callbacks.print = &print_top_mem_res; } else if (strcmp(buf, "mem_vsize") == EQUAL) { obj->callbacks.print = &print_top_mem_vsize; } else if (strcmp(buf, "uid") == EQUAL) { obj->callbacks.print = &print_top_uid; } else if (strcmp(buf, "user") == EQUAL) { obj->callbacks.print = &print_top_user; #ifdef BUILD_IOSTATS } else if (strcmp(buf, "io_read") == EQUAL) { obj->callbacks.print = &print_top_read_bytes; } else if (strcmp(buf, "io_write") == EQUAL) { obj->callbacks.print = &print_top_write_bytes; } else if (strcmp(buf, "io_perc") == EQUAL) { obj->callbacks.print = &print_top_io_perc; #endif /* BUILD_IOSTATS */ } else { NORM_ERR("invalid type arg for top"); #ifdef BUILD_IOSTATS NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize, " "io_read, io_write, io_perc"); #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; return 1; } conky-1.10.1/src/top.h000066400000000000000000000070511262311664100144640ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005 Adi Zaimi, Dan Piponi , * Dave Clark * Copyright (c) 2005-2012 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 _top_h_ #define _top_h_ /* Ensure there's an operating system defined. * compile with gcc -DOS ... * There is *no* default because every OS has it's own way of revealing * CPU/memory usage. */ /****************************************** * Includes * ******************************************/ #include "conky.h" #include "text_object.h" #define CPU_THRESHHOLD 0 /* threshhold for the cpu diff to appear */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /****************************************** * Defines * ******************************************/ /* XXX: I shouldn't really use this BUFFER_LEN variable but scanf is so lame * and it'll take me a while to write a replacement. */ #define BUFFER_LEN 1024 #define MAX_SP 10 // number of elements to sort /****************************************** * Process class * ******************************************/ struct process { struct process *next; struct process *previous; pid_t pid; char *name; char *basename; uid_t uid; float amount; // User and kernel times are in hundredths of seconds unsigned long user_time; unsigned long total; unsigned long kernel_time; unsigned long previous_user_time; unsigned long previous_kernel_time; unsigned long total_cpu_time; unsigned long long vsize; unsigned long long rss; #ifdef BUILD_IOSTATS unsigned long long read_bytes; unsigned long long previous_read_bytes; unsigned long long write_bytes; unsigned long long previous_write_bytes; float io_perc; #endif unsigned int time_stamp; unsigned int counted; unsigned int changed; }; struct sorted_process { struct sorted_process *greater; struct sorted_process *less; struct process *proc; }; /* lookup a program by it's name */ struct process *get_process_by_name(const char *); int parse_top_args(const char *s, const char *arg, struct text_object *obj); int update_top(void); void get_top_info(void); extern struct process *first_process; extern unsigned long g_time; struct process *get_process(pid_t pid); #endif /* _top_h_ */ conky-1.10.1/src/update-cb.cc000066400000000000000000000064701262311664100156700ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 "config.h" #include "logging.h" #include "update-cb.hh" #include #include namespace conky { namespace { semaphore sem_wait; enum {UNUSED_MAX = 5}; } namespace priv { callback_base::~callback_base() { stop(); } void callback_base::stop() { if(thread) { done = true; sem_start.post(); if(pipefd.second >= 0) if(write(pipefd.second, "X", 1) != 1) NORM_ERR("can't write 'X' to pipefd %d: %s", pipefd.second, strerror(errno)); thread->join(); delete thread; thread = NULL; } if(pipefd.first >= 0) { close(pipefd.first); pipefd.first = -1; } if(pipefd.second >= 0) { close(pipefd.second); pipefd.second = -1; } } inline size_t callback_base::get_hash(const handle &h) { return h->hash; } inline bool callback_base::is_equal(const handle &a, const handle &b) { if(a->hash != b->hash) return false; if(typeid(*a) != typeid(*b)) return false; return *a == *b; } void callback_base::merge(callback_base &&other) { if(other.period < period) { period = other.period; remaining = 0; } assert(wait == other.wait); unused = 0; } callback_base::handle callback_base::do_register_cb(const handle &h) { const auto &p = callbacks.insert(h); if(not p.second) (*p.first)->merge(std::move(*h)); return *p.first; } void callback_base::run() { if(not thread) thread = new std::thread(&callback_base::start_routine, this); sem_start.post(); } void callback_base::start_routine() { for(;;) { sem_start.wait(); if(done) return; // clear any remaining posts in case the previous iteration was very slow // (this should only happen if wait == false) while(sem_start.trywait()); work(); if(wait) sem_wait.post(); } } callback_base::Callbacks callback_base::callbacks(1, get_hash, is_equal); } void run_all_callbacks() { using priv::callback_base; size_t wait = 0; for(auto i = callback_base::callbacks.begin(); i != callback_base::callbacks.end(); ) { callback_base &cb = **i; if(cb.remaining-- == 0) { if(!i->unique() || ++cb.unused < UNUSED_MAX) { cb.remaining = cb.period-1; cb.run(); if(cb.wait) ++wait; } } if(cb.unused == UNUSED_MAX) { auto t = i; ++i; callback_base::callbacks.erase(t); } else ++i; } while(wait-- > 0) sem_wait.wait(); } } conky-1.10.1/src/update-cb.hh000066400000000000000000000167511262311664100157050ustar00rootroot00000000000000/* -*- 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) 2010 Pavel Labath et al. * * 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 UPDATE_CB_HH #define UPDATE_CB_HH #include #include #include // the following probably requires a is-gcc-4.7.0 check #include #include #include #include #include "c++wrap.hh" #include "semaphore.hh" namespace conky { // forward declarations template class callback_handle; void run_all_callbacks(); template callback_handle register_cb(uint32_t period, Params&&... params); namespace priv { class callback_base { typedef callback_handle handle; typedef std::unordered_set Callbacks; semaphore sem_start; std::thread *thread; const size_t hash; uint32_t period; uint32_t remaining; std::pair pipefd; const bool wait; bool done; uint8_t unused; callback_base(const callback_base &) = delete; callback_base& operator=(const callback_base &) = delete; virtual bool operator==(const callback_base &) = 0; void run(); void start_routine(); void stop(); static void deleter(callback_base *ptr) { ptr->stop(); delete ptr; } // a list of registered callbacks static Callbacks callbacks; // used by the callbacks list static inline size_t get_hash(const handle &h); static inline bool is_equal(const handle &a, const handle &b); static handle do_register_cb(const handle &h); template friend callback_handle conky::register_cb(uint32_t period, Params&&... params); friend void conky::run_all_callbacks(); template friend class conky::callback_handle; protected: callback_base(size_t hash_, uint32_t period_, bool wait_, bool use_pipe) : thread(NULL), hash(hash_), period(period_), remaining(0), pipefd(use_pipe ? pipe2(O_CLOEXEC) : std::pair(-1, -1)), wait(wait_), done(false), unused(0) {} int donefd() { return pipefd.first; } bool is_done() { return done; } // to be implemented by descendant classes virtual void work() = 0; // called when two registered objects evaulate as equal, the latter is removed // afterwards virtual void merge(callback_base &&); public: std::mutex result_mutex; virtual ~callback_base(); }; } template class callback_handle: private std::shared_ptr { typedef std::shared_ptr Base; callback_handle(Callback *ptr) : Base(ptr, &priv::callback_base::deleter) {} callback_handle(Base &&ptr) : Base(std::move(ptr)) {} public: using Base::operator->; using Base::operator*; friend void conky::run_all_callbacks(); template friend callback_handle register_cb(uint32_t period, Params&&... params); }; template callback_handle register_cb(uint32_t period, Params&&... params) { return std::dynamic_pointer_cast(priv::callback_base::do_register_cb( priv::callback_base::handle( new Callback(period, std::forward(params)...) ) )); } namespace priv { template struct hash_tuple { typedef std::tuple Tuple; typedef typename std::tuple_element::type Element; static inline size_t hash(const Tuple &tuple) { return std::hash()(std::get(tuple)) + 47 * hash_tuple::hash(tuple); } }; template struct hash_tuple<0, Elements...> { static inline size_t hash(const std::tuple &) { return 0; } }; } /* * To create a callback, inherit from this class. The Result template parameter should be the * type of your output, so that your users can retrieve it with the get_result* functions. * * get_result() returns a reference to the internal variable. It can be used without locking * if the object has wait set to true (wait=true means that the run_all_callbacks() waits for * the callback to finish work()ing before returning). If object has wait=false then the user * must first lock the result_mutex. * * get_result_copy() returns a copy of the result object and it handles the necessary * locking. Don't call it if you hold a lock on the result_mutex. * * You should implement the work() function to do the actual updating and store the result in * the result variable (lock the mutex while you are doing it, especially if you have * wait=false). * * The Keys... template parameters are parameters for your work function. E.g., a curl * callback can have one parameter - the url to retrieve,. hddtemp may have two - host and * port number of the hddtemp server, etc. The register_cb() function make sure that there * exists only one object (of the same type) with the same values for all the keys. * * Callbacks are registered with the register_cb() function. You pass the class name as the * template parameter, and any additional parameters to the constructor as function * parameters. The period parameter specifies how often the callback will run. It should be * left for the user to decide that. register_cb() returns a pointer to the newly created * object. As long as someone holds a pointer to the object, the callback will be run. * * run_all_callbacks() runs the registered callbacks (with the specified periodicity). It * should be called from somewhere inside the main loop, according to the update_interval * setting. It waits for the callbacks which have wait=true. It leaves the rest to run in * background. */ template class callback: public priv::callback_base { virtual bool operator==(const callback_base &other) { return tuple == dynamic_cast(other).tuple; } public: typedef std::tuple Tuple; protected: const Tuple tuple; Result result; template typename std::add_lvalue_reference< const typename std::tuple_element::type >::type get() { return std::get(tuple); } public: callback(uint32_t period_, bool wait_, const Tuple &tuple_, bool use_pipe = false) : callback_base(priv::hash_tuple::hash(tuple_), period_, wait_, use_pipe), tuple(tuple_) {} const Result& get_result() { return result; } Result get_result_copy() { std::lock_guard l(result_mutex); return result; } }; } #endif /* UPDATE_CB_HH */ conky-1.10.1/src/user.cc000066400000000000000000000047361262311664100150050ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "logging.h" #include #include #include #include "conky.h" #include void print_uid_name(struct text_object *obj, char *p, int p_max_size) { struct passwd *pw; uid_t uid; char* firstinvalid; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); errno = 0; uid = strtol(objbuf.get(), &firstinvalid, 10); if (errno == 0 && objbuf.get() != firstinvalid) { pw = getpwuid(uid); if(pw != NULL) { snprintf(p, p_max_size, "%s", pw->pw_name); } else { NORM_ERR("The uid %d doesn't exist", uid); } } else { NORM_ERR("$uid_name didn't receive a uid as argument"); } } void print_gid_name(struct text_object *obj, char *p, int p_max_size) { struct group *grp; gid_t gid; char* firstinvalid; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); errno = 0; gid = strtol(objbuf.get(), &firstinvalid, 10); if (errno == 0 && objbuf.get() != firstinvalid) { grp = getgrgid(gid); if(grp != NULL) { snprintf(p, p_max_size, "%s", grp->gr_name); } else { NORM_ERR("The gid %d doesn't exist", gid); } } else { NORM_ERR("$gid_name didn't receive a gid as argument"); } } conky-1.10.1/src/user.h000066400000000000000000000025261262311664100146420ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * vim: ts=4 sw=4 noet ai cindent syntax=c * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _USER_H #define _USER_H void print_gid_name(struct text_object *obj, char *p, int p_max_size); void print_uid_name(struct text_object *obj, char *p, int p_max_size); #endif /* _USER_H */ conky-1.10.1/src/users.cc000066400000000000000000000147721262311664100151710ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 #include #include #define BUFLEN 512 static void user_name(char *ptr) { const struct utmp *usr = 0; setutent(); while ((usr = getutent()) != NULL) { if (usr->ut_type == USER_PROCESS) { if (strlen(ptr) + strlen(usr->ut_name) + 1 <= BUFLEN) { strncat(ptr, usr->ut_name, UT_NAMESIZE); } } } } static void user_num(int *ptr) { const struct utmp *usr; int users_num = 0; setutent(); while ((usr = getutent()) != NULL) { if (usr->ut_type == USER_PROCESS) { ++users_num; } } *ptr = users_num; } static void user_term(char *ptr) { const struct utmp *usr; setutent(); while ((usr = getutent()) != NULL) { if (usr->ut_type == USER_PROCESS) { if (strlen(ptr) + strlen(usr->ut_line) + 1 <= BUFLEN) { strncat(ptr, usr->ut_line, UT_LINESIZE); } } } } static void user_time(char *ptr) { const struct utmp *usr; time_t log_in, real, diff; char buf[BUFLEN] = ""; setutent(); while ((usr = getutent()) != NULL) { if (usr->ut_type == USER_PROCESS) { log_in = usr->ut_time; time(&real); diff = difftime(real, log_in); format_seconds(buf, BUFLEN, diff); if (strlen(ptr) + strlen(buf) + 1 <= BUFLEN) { strncat(ptr, buf, BUFLEN-strlen(ptr)-1); } } } } static void tty_user_time(char *ptr, char *tty) { time_t real, diff, log_in; char buf[BUFLEN] = ""; struct utmp *usr, line; setutent(); strcpy(line.ut_line, tty); usr = getutline(&line); if (usr == NULL ) { return; } log_in = usr->ut_time; time(&real); diff = difftime(real, log_in); format_seconds(buf, BUFLEN, diff); strncpy(ptr, buf, BUFLEN-1); } static void users_alloc(struct information *ptr) { if (ptr->users.names == NULL) { ptr->users.names = (char*)malloc(text_buffer_size.get(*state)); } if (ptr->users.terms == NULL) { ptr->users.terms = (char*)malloc(text_buffer_size.get(*state)); } if (ptr->users.times == NULL) { ptr->users.times = (char*)malloc(text_buffer_size.get(*state)); } } static void update_user_time(char *tty) { struct information *current_info = &info; char temp[BUFLEN] = ""; if (current_info->users.ctime == NULL) { current_info->users.ctime = (char*)malloc(text_buffer_size.get(*state)); } tty_user_time(temp, tty); if (temp != NULL) { free_and_zero(current_info->users.ctime); current_info->users.ctime = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.ctime, temp, text_buffer_size.get(*state)); } else { free_and_zero(current_info->users.ctime); current_info->users.ctime = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.ctime, "broken", text_buffer_size.get(*state)); } } int update_users(void) { struct information *current_info = &info; char temp[BUFLEN] = ""; int t; users_alloc(current_info); user_name(temp); if (temp != NULL) { free_and_zero(current_info->users.names); current_info->users.names = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.names, temp, text_buffer_size.get(*state)); } else { free_and_zero(current_info->users.names); current_info->users.names = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.names, "broken", text_buffer_size.get(*state)); } user_num(&t); if (t != 0) { if (current_info->users.number) { current_info->users.number = 0; } current_info->users.number = t; } else { current_info->users.number = 0; } temp[0] = 0; user_term(temp); if (temp != NULL) { free_and_zero(current_info->users.terms); current_info->users.terms = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.terms, temp, text_buffer_size.get(*state)); } else { free_and_zero(current_info->users.terms); current_info->users.terms = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.terms, "broken", text_buffer_size.get(*state)); } user_time(temp); if (temp != NULL) { free_and_zero(current_info->users.times); current_info->users.times = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.times, temp, text_buffer_size.get(*state)); } else { free_and_zero(current_info->users.times); current_info->users.times = (char*)malloc(text_buffer_size.get(*state)); strncpy(current_info->users.times, "broken", text_buffer_size.get(*state)); } return 0; } void print_user_names(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.users.names); } void print_user_terms(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.users.terms); } void print_user_times(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%s", info.users.times); } void print_user_time(struct text_object *obj, char *p, int p_max_size) { update_user_time(obj->data.s); snprintf(p, p_max_size, "%s", info.users.ctime); } void print_user_number(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%d", info.users.number); } void free_user_names(struct text_object *obj) { (void)obj; free_and_zero(info.users.names); } void free_user_terms(struct text_object *obj) { (void)obj; free_and_zero(info.users.terms); } void free_user_times(struct text_object *obj) { (void)obj; free_and_zero(info.users.times); } void free_user_time(struct text_object *obj) { free_and_zero(info.users.ctime); free_and_zero(obj->data.s); } conky-1.10.1/src/users.h000066400000000000000000000032701262311664100150220ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 _USERS_H #define _USERS_H int update_users(void); void print_user_names(struct text_object *, char *, int); void print_user_terms(struct text_object *, char *, int); void print_user_times(struct text_object *, char *, int); void print_user_time(struct text_object *, char *, int); void print_user_number(struct text_object *, char *, int); void free_user_names(struct text_object *); void free_user_terms(struct text_object *); void free_user_times(struct text_object *); void free_user_time(struct text_object *); #endif /* _USERS_H */ conky-1.10.1/src/weather.cc000066400000000000000000000614061262311664100154630ustar00rootroot00000000000000/* -*- 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-2012 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 "config.h" #include "conky.h" #include "logging.h" #include "weather.h" #include "temphelper.h" #include "text_object.h" #include "ccurl_thread.h" #include #include #include #include #include #include #ifdef BUILD_WEATHER_XOAP #include #include #endif /* BUILD_WEATHER_XOAP */ /* WEATHER data */ class weather { void parse_token(const char *token); #ifdef BUILD_WEATHER_XOAP void parse_cc(xmlXPathContextPtr xpathCtx); void parse_weather_xml(const std::string &data); #endif public: std::string lastupd; #ifdef BUILD_WEATHER_XOAP std::string xoap_t; std::string icon; #endif /* BUILD_WEATHER_XOAP */ int temp; int dew; int cc; int bar; int wind_s; int wind_d; int hmid; int wc; weather() : temp(0), dew(0), cc(0), bar(0), wind_s(0), wind_d(0), hmid(0), wc(0) {} weather(const std::string &); }; #ifdef BUILD_WEATHER_XOAP #define FORECAST_DAYS 5 struct weather_forecast_day { std::string icon; std::string xoap_t; std::string day; std::string date; int hi; int low; int wind_s; int wind_d; int hmid; int ppcp; weather_forecast_day() : hi(0), low(0), wind_s(0), wind_d(0), hmid(0), ppcp(0) {} }; class weather_forecast: public std::array { void parse_df(xmlXPathContextPtr xpathCtx); public: weather_forecast() = default; weather_forecast(const std::string &); }; /* Xpath expressions for BUILD_WEATHER_XOAP xml parsing */ #define NUM_XPATH_EXPRESSIONS_CC 8 const char *xpath_expression_cc[NUM_XPATH_EXPRESSIONS_CC] = { "/weather/cc/lsup", "/weather/cc/tmp", "/weather/cc/t", "/weather/cc/bar/r", "/weather/cc/wind/s", "/weather/cc/wind/d", "/weather/cc/hmid", "/weather/cc/icon" }; #define NUM_XPATH_EXPRESSIONS_DF 10 const char *xpath_expression_df[NUM_XPATH_EXPRESSIONS_DF] = { "/weather/dayf/day[*]/hi", "/weather/dayf/day[*]/low", "/weather/dayf/day[*]/part[1]/icon", "/weather/dayf/day[*]/part[1]/t", "/weather/dayf/day[*]/part[1]/wind/s","/weather/dayf/day[*]/part[1]/wind/d", "/weather/dayf/day[*]/part[1]/ppcp", "/weather/dayf/day[*]/part[1]/hmid", "/weather/dayf/day[*]/@t", "/weather/dayf/day[*]/@dt" }; #endif /* BUILD_WEATHER_XOAP */ /* Possible sky conditions */ #define NUM_CC_CODES 6 const char *CC_CODES[NUM_CC_CODES] = { "SKC", "CLR", "FEW", "SCT", "BKN", "OVC" }; /* Possible weather modifiers */ #define NUM_WM_CODES 9 const char *WM_CODES[NUM_WM_CODES] = { "VC", "MI", "BC", "PR", "TS", "BL", "SH", "DR", "FZ" }; /* Possible weather conditions */ #define NUM_WC_CODES 17 const char *WC_CODES[NUM_WC_CODES] = { "DZ", "RA", "GR", "GS", "SN", "SG", "FG", "HZ", "FU", "BR", "DU", "SA", "FC", "PO", "SQ", "SS", "DS" }; struct weather_data { char uri[128]; char data_type[32]; int interval; }; #ifdef BUILD_WEATHER_XOAP struct weather_forecast_data { char uri[128]; unsigned int day; char data_type[32]; int interval; }; #endif int rel_humidity(int dew_point, int air) { const float a = 17.27f; const float b = 237.7f; float diff = a*(dew_point/(b+dew_point)-air/(b+air)); #ifdef MATH return (int)(100.f*expf(diff)); #else return (int)(16.666667163372f*(6.f+diff*(6.f+diff*(3.f+diff)))); #endif /* MATH */ } #ifdef BUILD_WEATHER_XOAP void weather_forecast::parse_df(xmlXPathContextPtr xpathCtx) { int i, j, k; char *content = NULL; xmlXPathObjectPtr xpathObj; xpathObj = xmlXPathEvalExpression((const xmlChar *)"/error/err", xpathCtx); if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0 && xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE) { content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]); NORM_ERR("XOAP error: %s", content); xmlFree(content); xmlXPathFreeObject(xpathObj); return; } xmlXPathFreeObject(xpathObj); for (i = 0; i < NUM_XPATH_EXPRESSIONS_DF; i++) { xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath_expression_df[i], xpathCtx); if (xpathObj != NULL) { xmlNodeSetPtr nodes = xpathObj->nodesetval; k = 0; for (j = 0; j < nodes->nodeNr; ++j) { if (nodes->nodeTab[j]->type == XML_ELEMENT_NODE) { content = (char *)xmlNodeGetContent(nodes->nodeTab[k]); switch(i) { case 0: (*this)[k].hi = atoi(content); break; case 1: (*this)[k].low = atoi(content); break; case 2: (*this)[k].icon = content; case 3: (*this)[k].xoap_t = content; break; case 4: (*this)[k].wind_s = atoi(content); break; case 5: (*this)[k].wind_d = atoi(content); break; case 6: (*this)[k].ppcp = atoi(content); break; case 7: (*this)[k].hmid = atoi(content); } } else if (nodes->nodeTab[j]->type == XML_ATTRIBUTE_NODE) { content = (char *)xmlNodeGetContent(nodes->nodeTab[k]); switch(i) { case 8: (*this)[k].day = content; break; case 9: (*this)[k].date = content; } } xmlFree(content); if (++k == FORECAST_DAYS) break; } } xmlXPathFreeObject(xpathObj); } return; } weather_forecast::weather_forecast(const std::string &data) { xmlDocPtr doc; xmlXPathContextPtr xpathCtx; if (!(doc = xmlReadMemory(data.c_str(), data.length(), "", NULL, 0))) { NORM_ERR("weather_forecast: can't read xml data"); return; } xpathCtx = xmlXPathNewContext(doc); if(xpathCtx == NULL) { NORM_ERR("weather_forecast: unable to create new XPath context"); xmlFreeDoc(doc); return; } parse_df(xpathCtx); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return; } void weather::parse_cc(xmlXPathContextPtr xpathCtx) { int i; char *content; xmlXPathObjectPtr xpathObj; xpathObj = xmlXPathEvalExpression((const xmlChar *)"/error/err", xpathCtx); if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0 && xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE) { content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]); NORM_ERR("XOAP error: %s", content); xmlFree(content); xmlXPathFreeObject(xpathObj); return; } xmlXPathFreeObject(xpathObj); for (i = 0; i < NUM_XPATH_EXPRESSIONS_CC; i++) { xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath_expression_cc[i], xpathCtx); if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr >0 && xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE) { content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]); switch(i) { case 0: lastupd = content; break; case 1: temp = atoi(content); break; case 2: xoap_t = content; break; case 3: bar = atoi(content); break; case 4: wind_s = atoi(content); break; case 5: wind_d = atoi(content); break; case 6: hmid = atoi(content); break; case 7: icon = content; } xmlFree(content); } xmlXPathFreeObject(xpathObj); } return; } void weather::parse_weather_xml(const std::string &data) { xmlDocPtr doc; xmlXPathContextPtr xpathCtx; if (!(doc = xmlReadMemory(data.c_str(), data.length(), "", NULL, 0))) { NORM_ERR("weather: can't read xml data"); return; } xpathCtx = xmlXPathNewContext(doc); if(xpathCtx == NULL) { NORM_ERR("weather: unable to create new XPath context"); xmlFreeDoc(doc); return; } parse_cc(xpathCtx); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return; } #endif /* BUILD_WEATHER_XOAP */ /* * Horrible hack to avoid using regexes * */ void weather::parse_token(const char *token) { int i; char s_tmp[64]; switch (strlen(token)) { //Check all tokens 2 chars long case 2: //Check if token is a weather condition for (i=0; i<2; i++) { if (!isalpha(token[i])) break; } if (i==2) { for(i=0; i class weather_cb: public curl_callback { typedef curl_callback Base; protected: virtual void process_data() { Result tmp(Base::data); std::unique_lock lock(Base::result_mutex); Base::result = tmp; } public: weather_cb(uint32_t period, const std::string &uri) : Base(period, typename Base::Tuple(uri)) {} }; } void wind_deg_to_dir(char *p, int p_max_size, int wind_deg) { if ((wind_deg >= 349) || (wind_deg < 12)) { strncpy(p, "N", p_max_size); } else if (wind_deg < 33) { strncpy(p, "NNE", p_max_size); } else if (wind_deg < 57) { strncpy(p, "NE", p_max_size); } else if (wind_deg < 79) { strncpy(p, "ENE", p_max_size); } else if (wind_deg < 102) { strncpy(p, "E", p_max_size); } else if (wind_deg < 124) { strncpy(p, "ESE", p_max_size); } else if (wind_deg < 147) { strncpy(p, "SE", p_max_size); } else if (wind_deg < 169) { strncpy(p, "SSE", p_max_size); } else if (wind_deg < 192) { strncpy(p, "S", p_max_size); } else if (wind_deg < 214) { strncpy(p, "SSW", p_max_size); } else if (wind_deg < 237) { strncpy(p, "SW", p_max_size); } else if (wind_deg < 259) { strncpy(p, "WSW", p_max_size); } else if (wind_deg < 282) { strncpy(p, "W", p_max_size); } else if (wind_deg < 304) { strncpy(p, "WNW", p_max_size); } else if (wind_deg < 327) { strncpy(p, "NW", p_max_size); } else if (wind_deg < 349) { strncpy(p, "NNW", p_max_size); }; } #ifdef BUILD_WEATHER_XOAP static void weather_forecast_process_info(char *p, int p_max_size, const std::string &uri, unsigned int day, char *data_type, int interval) { uint32_t period = std::max(lround(interval/active_update_interval()), 1l); auto cb = conky::register_cb>(period, uri); std::lock_guard lock(cb->result_mutex); const weather_forecast &data = cb->get_result(); if (strcmp(data_type, "hi") == EQUAL) { temp_print(p, p_max_size, data[day].hi, TEMP_CELSIUS); } else if (strcmp(data_type, "low") == EQUAL) { temp_print(p, p_max_size, data[day].low, TEMP_CELSIUS); } else if (strcmp(data_type, "icon") == EQUAL) { strncpy(p, data[day].icon.c_str(), p_max_size); } else if (strcmp(data_type, "forecast") == EQUAL) { strncpy(p, data[day].xoap_t.c_str(), p_max_size); } else if (strcmp(data_type, "wind_speed") == EQUAL) { snprintf(p, p_max_size, "%d", data[day].wind_s); } else if (strcmp(data_type, "wind_dir") == EQUAL) { wind_deg_to_dir(p, p_max_size, data[day].wind_d); } else if (strcmp(data_type, "wind_dir_DEG") == EQUAL) { snprintf(p, p_max_size, "%d", data[day].wind_d); } else if (strcmp(data_type, "humidity") == EQUAL) { snprintf(p, p_max_size, "%d", data[day].hmid); } else if (strcmp(data_type, "precipitation") == EQUAL) { snprintf(p, p_max_size, "%d", data[day].ppcp); } else if (strcmp(data_type, "day") == EQUAL) { strncpy(p, data[day].day.c_str(), p_max_size); } else if (strcmp(data_type, "date") == EQUAL) { strncpy(p, data[day].date.c_str(), p_max_size); } } #endif /* BUILD_WEATHER_XOAP */ static void weather_process_info(char *p, int p_max_size, const std::string &uri, char *data_type, int interval) { static const char *wc[] = { "", "drizzle", "rain", "hail", "soft hail", "snow", "snow grains", "fog", "haze", "smoke", "mist", "dust", "sand", "funnel cloud tornado", "dust/sand", "squall", "sand storm", "dust storm" }; uint32_t period = std::max(lround(interval/active_update_interval()), 1l); auto cb = conky::register_cb>(period, uri); std::lock_guard lock(cb->result_mutex); const weather *data = &cb->get_result(); if (strcmp(data_type, "last_update") == EQUAL) { strncpy(p, data->lastupd.c_str(), p_max_size); } else if (strcmp(data_type, "temperature") == EQUAL) { temp_print(p, p_max_size, data->temp, TEMP_CELSIUS); } else if (strcmp(data_type, "cloud_cover") == EQUAL) { #ifdef BUILD_WEATHER_XOAP if (data->xoap_t[0] != '\0') { char *s = p; strncpy(p, data->xoap_t.c_str(), p_max_size); while (*s) { *s = tolower(*s); s++; } } else #endif /* BUILD_WEATHER_XOAP */ if (data->cc == 0) { strncpy(p, "", p_max_size); } else if (data->cc < 3) { strncpy(p, "clear", p_max_size); } else if (data->cc < 5) { strncpy(p, "partly cloudy", p_max_size); } else if (data->cc == 5) { strncpy(p, "cloudy", p_max_size); } else if (data->cc == 6) { strncpy(p, "overcast", p_max_size); } else if (data->cc == 7) { strncpy(p, "towering cumulus", p_max_size); } else { strncpy(p, "cumulonimbus", p_max_size); } #ifdef BUILD_WEATHER_XOAP } else if (strcmp(data_type, "icon") == EQUAL) { strncpy(p, data->icon.c_str(), p_max_size); #endif /* BUILD_WEATHER_XOAP */ } else if (strcmp(data_type, "pressure") == EQUAL) { snprintf(p, p_max_size, "%d", data->bar); } else if (strcmp(data_type, "wind_speed") == EQUAL) { snprintf(p, p_max_size, "%d", data->wind_s); } else if (strcmp(data_type, "wind_dir") == EQUAL) { wind_deg_to_dir(p, p_max_size, data->wind_d); } else if (strcmp(data_type, "wind_dir_DEG") == EQUAL) { snprintf(p, p_max_size, "%d", data->wind_d); } else if (strcmp(data_type, "humidity") == EQUAL) { snprintf(p, p_max_size, "%d", data->hmid); } else if (strcmp(data_type, "weather") == EQUAL) { strncpy(p, wc[data->wc], p_max_size); } } #ifdef BUILD_WEATHER_XOAP /* xoap suffix for weather from weather.com */ namespace { std::string xoap_cc; std::string xoap_df; } #endif /* BUILD_WEATHER_XOAP */ static int process_weather_uri(char *uri, char *locID, int dayf UNUSED_ATTR) { /* locID MUST BE upper-case */ char *tmp_p = locID; while (*tmp_p) { *tmp_p = toupper(*tmp_p); tmp_p++; } /* Construct complete uri */ #ifdef BUILD_WEATHER_XOAP if (strstr(uri, "xoap.weather.com")) { if ((dayf == 0) && (xoap_cc.length() != 0)) { strcat(uri, locID); strcat(uri, xoap_cc.c_str()); } else if ((dayf == 1) && (xoap_df.length() != 0)) { strcat(uri, locID); strcat(uri, xoap_df.c_str()); } else { return 0; } } else #endif /* BUILD_WEATHER_XOAP */ if (strstr(uri, "weather.noaa.gov")) { strcat(uri, locID); strcat(uri, ".TXT"); } else if (!strstr(uri, "localhost") && !strstr(uri, "127.0.0.1")) { return -1; } return 0; } #ifdef BUILD_WEATHER_XOAP /* * TODO: make the xoap keys file readable from the config file * make the keys directly readable from the config file * make the xoap keys file giveable as a command line option */ void load_xoap_keys(void) { FILE *fp; char *par = (char *) malloc(11 * sizeof(char)); char *key = (char *) malloc(17 * sizeof(char)); std::string xoap = to_real_path(XOAP_FILE); fp = fopen(xoap.c_str(), "r"); if (fp != NULL) { if (fscanf(fp, "%10s %16s", par, key) == 2) { xoap_cc = std::string("?cc=*&link=xoap&prod=xoap&par=") + par + "&key=" + key + "&unit=m"; /* TODO: Use FORECAST_DAYS instead of 5 */ xoap_df = std::string("?dayf=5&link=xoap&prod=xoap&par=") + par + "&key=" + key + "&unit=m"; } fclose(fp); } free(par); free(key); } void scan_weather_forecast_arg(struct text_object *obj, const char *arg, void *free_at_crash) { int argc; struct weather_forecast_data *wfd; float interval = 0; char *locID = (char *) malloc(9 * sizeof(char)); wfd = (struct weather_forecast_data *)malloc(sizeof(struct weather_forecast_data)); memset(wfd, 0, sizeof(struct weather_forecast_data)); argc = sscanf(arg, "%119s %8s %1u %31s %f", wfd->uri, locID, &wfd->day, wfd->data_type, &interval); if (argc < 4) { free(locID); free(wfd); CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather_forecast"); } if (process_weather_uri(wfd->uri, locID, 1)) { free(locID); free(wfd); CRIT_ERR(obj, free_at_crash, \ "could not recognize the weather forecast uri"); } /* Limit the day between 0 (today) and FORECAST_DAYS */ if (wfd->day >= FORECAST_DAYS) { wfd->day = FORECAST_DAYS-1; } /* Limit the data retrieval interval to 3 hours and an half */ if (interval < 210) { interval = 210; } /* Convert to seconds */ wfd->interval = interval * 60; free(locID); DBGP("weather_forecast: fetching %s for day %d from %s every %d seconds", \ wfd->data_type, wfd->day, wfd->uri, wfd->interval); obj->data.opaque = wfd; } void print_weather_forecast(struct text_object *obj, char *p, int p_max_size) { struct weather_forecast_data *wfd = (struct weather_forecast_data *)obj->data.opaque; if (!wfd || !wfd->uri) { NORM_ERR("error processing weather forecast data, check that you have a valid XOAP key if using XOAP."); return; } weather_forecast_process_info(p, p_max_size, wfd->uri, wfd->day, wfd->data_type, wfd->interval); } #endif /* BUILD_WEATHER_XOAP */ void scan_weather_arg(struct text_object *obj, const char *arg, void *free_at_crash) { int argc; struct weather_data *wd; char *locID = (char *) malloc(9 * sizeof(char)); float interval = 0; wd = (struct weather_data *)malloc(sizeof(struct weather_data)); memset(wd, 0, sizeof(struct weather_data)); argc = sscanf(arg, "%119s %8s %31s %f", wd->uri, locID, wd->data_type, &interval); if (argc < 3) { free(locID); free(wd); CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather"); } if (process_weather_uri(wd->uri, locID, 0)) { free(locID); free(wd); CRIT_ERR(obj, free_at_crash, \ "could not recognize the weather uri"); } /* Limit the data retrieval interval to half hour min */ if (interval < 30) { interval = 30; } /* Convert to seconds */ wd->interval = interval * 60; free(locID); DBGP("weather: fetching %s from %s every %d seconds", \ wd->data_type, wd->uri, wd->interval); obj->data.opaque = wd; } void print_weather(struct text_object *obj, char *p, int p_max_size) { struct weather_data *wd = (struct weather_data *)obj->data.opaque; if (!wd || !wd->uri) { NORM_ERR("error processing weather data, check that you have a valid XOAP key if using XOAP."); return; } weather_process_info(p, p_max_size, wd->uri, wd->data_type, wd->interval); } void free_weather(struct text_object *obj) { free_and_zero(obj->data.opaque); } conky-1.10.1/src/weather.h000066400000000000000000000031301262311664100153130ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 WEATHER_H_ #define WEATHER_H_ #ifdef BUILD_WEATHER_XOAP void load_xoap_keys(void); void scan_weather_forecast_arg(struct text_object *, const char *, void *); void print_weather_forecast(struct text_object *, char *, int); #endif /* BUILD_WEATHER_XOAP */ void scan_weather_arg(struct text_object *, const char *, void *); void print_weather(struct text_object *, char *, int); void free_weather(struct text_object *); #endif /* WEATHER_H_ */ conky-1.10.1/src/x11.cc000066400000000000000000001015041262311664100144270ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen * Copyright (c) 2005-2012 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 "config.h" #include "conky.h" #include "logging.h" #include "common.h" #include "x11.h" #include #include #include #include #ifdef BUILD_IMLIB2 #include "imlib2.h" #endif /* BUILD_IMLIB2 */ #ifndef OWN_WINDOW #include #endif #ifdef BUILD_XFT #include #endif #ifdef BUILD_XSHAPE #include #include #endif #ifdef BUILD_ARGB bool have_argb_visual; #endif /* BUILD_ARGB */ /* some basic X11 stuff */ Display *display = NULL; int display_width; int display_height; int screen; /* workarea from _NET_WORKAREA, this is where window / text is aligned */ int workarea[4]; /* Window stuff */ struct conky_window window; char window_created = 0; /* local prototypes */ static void update_workarea(void); static Window find_desktop_window(Window *p_root, Window *p_desktop); static Window find_subwindow(Window win, int w, int h); static void init_X11(); static void deinit_X11(); static void init_window(lua::state &l, bool own); /********************* ************************/ namespace priv { void out_to_x_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && do_convert(l, -1).first) init_X11(); ++s; } void out_to_x_setting::cleanup(lua::state &l) { lua::stack_sentry s(l, -1); if(do_convert(l, -1).first) deinit_X11(); l.pop(); } void own_window_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init) { if(do_convert(l, -1).first) { #ifndef OWN_WINDOW std::cerr << "Support for the own_window setting has been " "disabled during compilation\n"; l.pop(); l.pushboolean(false); #endif } if(out_to_x.get(l)) init_window(l, do_convert(l, -1).first); else { // own_window makes no sense when not drawing to X l.pop(); l.pushboolean(false); } } ++s; } #ifdef BUILD_XDBE bool use_xdbe_setting::set_up(lua::state &l) { // double_buffer makes no sense when not drawing to X if(not out_to_x.get(l)) return false; int major, minor; if (not XdbeQueryExtension(display, &major, &minor)) { NORM_ERR("No compatible double buffer extension found"); return false; } window.back_buffer = XdbeAllocateBackBufferName(display, window.window, XdbeBackground); if (window.back_buffer != None) { window.drawable = window.back_buffer; } else { NORM_ERR("Failed to allocate back buffer"); return false; } XFlush(display); return true; } void use_xdbe_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && do_convert(l, -1).first) { if(not set_up(l)) { l.pop(); l.pushboolean(false); } fprintf(stderr, PACKAGE_NAME": drawing to %s buffer\n", do_convert(l, -1).first?"double":"single"); } ++s; } #else bool use_xpmdb_setting::set_up(lua::state &l) { // double_buffer makes no sense when not drawing to X if(not out_to_x.get(l)) return false; window.back_buffer = XCreatePixmap(display, window.window, window.width+1, window.height+1, DefaultDepth(display, screen)); if (window.back_buffer != None) { window.drawable = window.back_buffer; } else { NORM_ERR("Failed to allocate back buffer"); return false; } XFlush(display); return true; } void use_xpmdb_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); Base::lua_setter(l, init); if(init && do_convert(l, -1).first) { if(not set_up(l)) { l.pop(); l.pushboolean(false); } fprintf(stderr, PACKAGE_NAME": drawing to %s buffer\n", do_convert(l, -1).first?"double":"single"); } ++s; } #endif void colour_setting::lua_setter(lua::state &l, bool init) { lua::stack_sentry s(l, -2); if(not out_to_x.get(l)) { // ignore if we're not using X l.replace(-2); } else Base::lua_setter(l, init); ++s; } } template<> conky::lua_traits::Map conky::lua_traits::map = { { "top_left", TOP_LEFT }, { "top_right", TOP_RIGHT }, { "top_middle", TOP_MIDDLE }, { "bottom_left", BOTTOM_LEFT }, { "bottom_right", BOTTOM_RIGHT }, { "bottom_middle", BOTTOM_MIDDLE }, { "middle_left", MIDDLE_LEFT }, { "middle_middle", MIDDLE_MIDDLE }, { "middle_right", MIDDLE_RIGHT }, { "none", NONE } }; #ifdef OWN_WINDOW template<> conky::lua_traits::Map conky::lua_traits::map = { { "normal", TYPE_NORMAL }, { "dock", TYPE_DOCK }, { "panel", TYPE_PANEL }, { "desktop", TYPE_DESKTOP }, { "override", TYPE_OVERRIDE } }; template<> conky::lua_traits::Map conky::lua_traits::map = { { "undecorated", HINT_UNDECORATED }, { "below", HINT_BELOW }, { "above", HINT_ABOVE }, { "sticky", HINT_STICKY }, { "skip_taskbar", HINT_SKIP_TASKBAR }, { "skip_pager", HINT_SKIP_PAGER } }; std::pair window_hints_traits::convert(lua::state &l, int index, const std::string &name) { typedef conky::lua_traits Traits; lua::stack_sentry s(l); l.checkstack(1); std::string hints = l.tostring(index); // add a sentinel to simplify the following loop hints += ','; size_t pos = 0; size_t newpos; uint16_t ret = 0; while((newpos = hints.find_first_of(", ", pos)) != std::string::npos) { if(newpos > pos) { l.pushstring(hints.substr(pos, newpos-pos)); auto t = conky::lua_traits::convert(l, -1, name); if(not t.second) return {0, false}; SET_HINT(ret, t.first); l.pop(); } pos = newpos+1; } return {ret, true}; } #endif namespace { // used to set the default value for own_window_title std::string gethostnamecxx() { update_uname(); return info.uname_s.nodename; } } /* * The order of these settings cannot be completely arbitrary. Some of them depend on others, and * the setters are called in the order in which they are defined. The order should be: * display_name -> out_to_x -> everything colour related * -> border_*, own_window_*, etc -> own_window -> double_buffer -> imlib_cache_size */ conky::simple_config_setting text_alignment("alignment", BOTTOM_LEFT, false); conky::simple_config_setting display_name("display", std::string(), false); priv::out_to_x_setting out_to_x; priv::colour_setting color[10] = { { "color0", 0xffffff }, { "color1", 0xffffff }, { "color2", 0xffffff }, { "color3", 0xffffff }, { "color4", 0xffffff }, { "color5", 0xffffff }, { "color6", 0xffffff }, { "color7", 0xffffff }, { "color8", 0xffffff }, { "color9", 0xffffff } }; priv::colour_setting default_color("default_color", 0xffffff); priv::colour_setting default_shade_color("default_shade_color", 0x000000); priv::colour_setting default_outline_color("default_outline_color", 0x000000); conky::range_config_setting border_inner_margin("border_inner_margin", 0, std::numeric_limits::max(), 3, true); conky::range_config_setting border_outer_margin("border_outer_margin", 0, std::numeric_limits::max(), 1, true); conky::range_config_setting border_width("border_width", 0, std::numeric_limits::max(), 1, true); #ifdef BUILD_XFT conky::simple_config_setting use_xft("use_xft", false, false); #endif #ifdef OWN_WINDOW conky::simple_config_setting set_transparent("own_window_transparent", false, false); conky::simple_config_setting own_window_class("own_window_class", PACKAGE_NAME, false); conky::simple_config_setting own_window_title("own_window_title", PACKAGE_NAME " (" + gethostnamecxx()+")", false); conky::simple_config_setting own_window_type("own_window_type", TYPE_NORMAL, false); conky::simple_config_setting own_window_hints("own_window_hints", 0, false); priv::colour_setting background_colour("own_window_colour", 0); #ifdef BUILD_ARGB conky::simple_config_setting use_argb_visual("own_window_argb_visual", false, false); conky::range_config_setting own_window_argb_value("own_window_argb_value", 0, 255, 255, false); #endif #endif /*OWN_WINDOW*/ priv::own_window_setting own_window; #ifdef BUILD_XDBE priv::use_xdbe_setting use_xdbe; #else priv::use_xpmdb_setting use_xpmdb; #endif #ifdef BUILD_IMLIB2 /* * the only reason this is not in imlib2.cc is so that we can be sure it's setter executes after * use_xdbe */ imlib_cache_size_setting imlib_cache_size; #endif /******************** ************************/ #ifdef DEBUG /* WARNING, this type not in Xlib spec */ static int __attribute__((noreturn)) x11_error_handler(Display *d, XErrorEvent *err) { NORM_ERR("X Error: type %i Display %lx XID %li serial %lu error_code %i request_code %i minor_code %i other Display: %lx\n", err->type, (long unsigned)err->display, (long)err->resourceid, err->serial, err->error_code, err->request_code, err->minor_code, (long unsigned)d ); abort(); } static int __attribute__((noreturn)) x11_ioerror_handler(Display *d) { NORM_ERR("X Error: Display %lx\n", (long unsigned)d ); exit(1); } #endif /* DEBUG */ /* X11 initializer */ static void init_X11() { if (!display) { const std::string &dispstr = display_name.get(*state).c_str(); // passing NULL to XOpenDisplay should open the default display const char *disp = dispstr.size() ? dispstr.c_str() : NULL; if ((display = XOpenDisplay(disp)) == NULL) { throw std::runtime_error(std::string("can't open display: ") + XDisplayName(disp)); } } info.x11.monitor.number = 1; info.x11.monitor.current = 0; info.x11.desktop.current = 1; info.x11.desktop.number = 1; info.x11.desktop.all_names.clear(); info.x11.desktop.name.clear(); screen = DefaultScreen(display); display_width = DisplayWidth(display, screen); display_height = DisplayHeight(display, screen); get_x11_desktop_info(display, 0); update_workarea(); #ifdef DEBUG _Xdebug = 1; /* WARNING, this type not in Xlib spec */ XSetErrorHandler(&x11_error_handler); XSetIOErrorHandler(&x11_ioerror_handler); #endif /* DEBUG */ } static void deinit_X11() { XCloseDisplay(display); display = NULL; } static void update_workarea(void) { /* default work area is display */ workarea[0] = 0; workarea[1] = 0; workarea[2] = display_width; workarea[3] = display_height; } /* Find root window and desktop window. * Return desktop window on success, * and set root and desktop byref return values. * Return 0 on failure. */ static Window find_desktop_window(Window *p_root, Window *p_desktop) { Atom type; int format, i; unsigned long nitems, bytes; unsigned int n; Window root = RootWindow(display, screen); Window win = root; Window troot, parent, *children; unsigned char *buf = NULL; if (!p_root || !p_desktop) { return 0; } /* some window managers set __SWM_VROOT to some child of root window */ XQueryTree(display, root, &troot, &parent, &children, &n); for (i = 0; i < (int) n; i++) { if (XGetWindowProperty(display, children[i], ATOM(__SWM_VROOT), 0, 1, False, XA_WINDOW, &type, &format, &nitems, &bytes, &buf) == Success && type == XA_WINDOW) { win = *(Window *) buf; XFree(buf); XFree(children); fprintf(stderr, PACKAGE_NAME": desktop window (%lx) found from __SWM_VROOT property\n", win); fflush(stderr); *p_root = win; *p_desktop = win; return win; } if (buf) { XFree(buf); buf = 0; } } XFree(children); /* get subwindows from root */ win = find_subwindow(root, -1, -1); update_workarea(); win = find_subwindow(win, workarea[2], workarea[3]); if (buf) { XFree(buf); buf = 0; } if (win != root) { fprintf(stderr, PACKAGE_NAME": desktop window (%lx) is subwindow of root window (%lx)\n", win, root); } else { fprintf(stderr, PACKAGE_NAME": desktop window (%lx) is root window\n", win); } fflush(stderr); *p_root = root; *p_desktop = win; return win; } #ifdef OWN_WINDOW namespace { /* helper function for set_transparent_background() */ void do_set_background(Window win, int argb) { unsigned long colour = background_colour.get(*state) | (argb<<24); XSetWindowBackground(display, win, colour); } } /* if no argb visual is configured sets background to ParentRelative for the Window and all parents, else real transparency is used */ void set_transparent_background(Window win) { #ifdef BUILD_ARGB if (have_argb_visual) { // real transparency do_set_background(win, set_transparent.get(*state) ? 0 : own_window_argb_value.get(*state)); } else { #endif /* BUILD_ARGB */ // pseudo transparency if (set_transparent.get(*state)) { Window parent = win; unsigned int i; for (i = 0; i < 50 && parent != RootWindow(display, screen); i++) { Window r, *children; unsigned int n; XSetWindowBackgroundPixmap(display, parent, ParentRelative); XQueryTree(display, parent, &r, &parent, &children, &n); XFree(children); } } else do_set_background(win, 0); #ifdef BUILD_ARGB } #endif /* BUILD_ARGB */ } #endif #ifdef BUILD_ARGB static int get_argb_visual(Visual** visual, int *depth) { /* code from gtk project, gdk_screen_get_rgba_visual */ XVisualInfo visual_template; XVisualInfo *visual_list; int nxvisuals = 0, i; visual_template.screen = screen; visual_list = XGetVisualInfo (display, VisualScreenMask, &visual_template, &nxvisuals); for (i = 0; i < nxvisuals; i++) { if (visual_list[i].depth == 32 && (visual_list[i].red_mask == 0xff0000 && visual_list[i].green_mask == 0x00ff00 && visual_list[i].blue_mask == 0x0000ff)) { *visual = visual_list[i].visual; *depth = visual_list[i].depth; DBGP("Found ARGB Visual"); XFree(visual_list); return 1; } } // no argb visual available DBGP("No ARGB Visual found"); XFree(visual_list); return 0; } #endif /* BUILD_ARGB */ void destroy_window(void) { #ifdef BUILD_XFT if(window.xftdraw) { XftDrawDestroy(window.xftdraw); } #endif /* BUILD_XFT */ if(window.gc) { XFreeGC(display, window.gc); } memset(&window, 0, sizeof(struct conky_window)); } static void init_window(lua::state &l __attribute__((unused)), bool own) { // own is unused if OWN_WINDOW is not defined (void) own; window_created = 1; #ifdef OWN_WINDOW if (own) { int depth = 0, flags = CWOverrideRedirect | CWBackingStore; Visual *visual = NULL; if (!find_desktop_window(&window.root, &window.desktop)) { return; } #ifdef BUILD_ARGB if (use_argb_visual.get(l) && get_argb_visual(&visual, &depth)) { have_argb_visual = true; window.visual = visual; window.colourmap = XCreateColormap(display, DefaultRootWindow(display), window.visual, AllocNone); } else { #endif /* BUILD_ARGB */ window.visual = DefaultVisual(display, screen); window.colourmap = DefaultColormap(display, screen); depth = CopyFromParent; visual = CopyFromParent; #ifdef BUILD_ARGB } #endif /* BUILD_ARGB */ int b = border_inner_margin.get(l) + border_width.get(l) + border_outer_margin.get(l); /* Sanity check to avoid making an invalid 0x0 window */ if (b == 0) { b = 1; } if (own_window_type.get(l) == TYPE_OVERRIDE) { /* An override_redirect True window. * No WM hints or button processing needed. */ XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, Always, 0L, 0L, False, StructureNotifyMask | ExposureMask, 0L, True, 0, 0 }; #ifdef BUILD_ARGB if (have_argb_visual) { attrs.colormap = window.colourmap; flags |= CWBorderPixel | CWColormap; } else { #endif /* BUILD_ARGB */ flags |= CWBackPixel; #ifdef BUILD_ARGB } #endif /* BUILD_ARGB */ /* Parent is desktop window (which might be a child of root) */ window.window = XCreateWindow(display, window.desktop, window.x, window.y, b, b, 0, depth, InputOutput, visual, flags, &attrs); XLowerWindow(display, window.window); fprintf(stderr, PACKAGE_NAME": window type - override\n"); fflush(stderr); } else { /* own_window_type.get(l) != TYPE_OVERRIDE */ /* A window managed by the window manager. * Process hints and buttons. */ XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, Always, 0L, 0L, False, StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 }; XClassHint classHint; XWMHints wmHint; Atom xa; #ifdef BUILD_ARGB if (have_argb_visual) { attrs.colormap = window.colourmap; flags |= CWBorderPixel | CWColormap; } else { #endif /* BUILD_ARGB */ flags |= CWBackPixel; #ifdef BUILD_ARGB } #endif /* BUILD_ARGB */ if (own_window_type.get(l) == TYPE_DOCK) { window.x = window.y = 0; } /* Parent is root window so WM can take control */ window.window = XCreateWindow(display, window.root, window.x, window.y, b, b, 0, depth, InputOutput, visual, flags, &attrs); // class_name must be a named local variable, so that c_str() remains valid until we // call XmbSetWMProperties(). We use const_cast because, for whatever reason, // res_name is not declared as const char *. XmbSetWMProperties hopefully doesn't // modify the value (hell, even their own example app assigns a literal string // constant to the field) const std::string &class_name = own_window_class.get(l); classHint.res_name = const_cast(class_name.c_str()); classHint.res_class = classHint.res_name; uint16_t hints = own_window_hints.get(l); wmHint.flags = InputHint | StateHint; /* allow decorated windows to be given input focus by WM */ wmHint.input = TEST_HINT(hints, HINT_UNDECORATED) ? False : True; #ifdef BUILD_XSHAPE if (!wmHint.input) { int event_base, error_base; if (XShapeQueryExtension(display, &event_base, &error_base)) { int major_version = 0, minor_version = 0; XShapeQueryVersion(display, &major_version, &minor_version); if ((major_version > 1) || ((major_version == 1) && (minor_version >=1))) { Region empty_region = XCreateRegion(); XShapeCombineRegion(display, window.window, ShapeInput, 0, 0, empty_region, ShapeSet); XDestroyRegion(empty_region); } else { NORM_ERR("Input shapes are not supported"); } } else { NORM_ERR("No shape extension found"); } } #endif if (own_window_type.get(l) == TYPE_DOCK || own_window_type.get(l) == TYPE_PANEL) { wmHint.initial_state = WithdrawnState; } else { wmHint.initial_state = NormalState; } XmbSetWMProperties(display, window.window, NULL, NULL, argv_copy, argc_copy, NULL, &wmHint, &classHint); XStoreName(display, window.window, own_window_title.get(l).c_str() ); /* Sets an empty WM_PROTOCOLS property */ XSetWMProtocols(display, window.window, NULL, 0); /* Set window type */ if ((xa = ATOM(_NET_WM_WINDOW_TYPE)) != None) { Atom prop; switch (own_window_type.get(l)) { case TYPE_DESKTOP: prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP); fprintf(stderr, PACKAGE_NAME": window type - desktop\n"); fflush(stderr); break; case TYPE_DOCK: prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); fprintf(stderr, PACKAGE_NAME": window type - dock\n"); fflush(stderr); break; case TYPE_PANEL: prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); fprintf(stderr, PACKAGE_NAME": window type - panel\n"); fflush(stderr); break; case TYPE_NORMAL: default: prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); fprintf(stderr, PACKAGE_NAME": window type - normal\n"); fflush(stderr); break; } XChangeProperty(display, window.window, xa, XA_ATOM, 32, PropModeReplace, (unsigned char *) &prop, 1); } /* Set desired hints */ /* Window decorations */ if (TEST_HINT(hints, HINT_UNDECORATED)) { /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n"); fflush(stderr); */ xa = ATOM(_MOTIF_WM_HINTS); if (xa != None) { long prop[5] = { 2, 0, 0, 0, 0 }; XChangeProperty(display, window.window, xa, xa, 32, PropModeReplace, (unsigned char *) prop, 5); } } /* Below other windows */ if (TEST_HINT(hints, HINT_BELOW)) { /* fprintf(stderr, PACKAGE_NAME": hint - below\n"); fflush(stderr); */ xa = ATOM(_WIN_LAYER); if (xa != None) { long prop = 0; XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, PropModeAppend, (unsigned char *) &prop, 1); } xa = ATOM(_NET_WM_STATE); if (xa != None) { Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); XChangeProperty(display, window.window, xa, XA_ATOM, 32, PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Above other windows */ if (TEST_HINT(hints, HINT_ABOVE)) { /* fprintf(stderr, PACKAGE_NAME": hint - above\n"); fflush(stderr); */ xa = ATOM(_WIN_LAYER); if (xa != None) { long prop = 6; XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, PropModeAppend, (unsigned char *) &prop, 1); } xa = ATOM(_NET_WM_STATE); if (xa != None) { Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); XChangeProperty(display, window.window, xa, XA_ATOM, 32, PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Sticky */ if (TEST_HINT(hints, HINT_STICKY)) { /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n"); fflush(stderr); */ xa = ATOM(_NET_WM_DESKTOP); if (xa != None) { CARD32 xa_prop = 0xFFFFFFFF; XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, PropModeAppend, (unsigned char *) &xa_prop, 1); } xa = ATOM(_NET_WM_STATE); if (xa != None) { Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); XChangeProperty(display, window.window, xa, XA_ATOM, 32, PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Skip taskbar */ if (TEST_HINT(hints, HINT_SKIP_TASKBAR)) { /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n"); fflush(stderr); */ xa = ATOM(_NET_WM_STATE); if (xa != None) { Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR); XChangeProperty(display, window.window, xa, XA_ATOM, 32, PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Skip pager */ if (TEST_HINT(hints, HINT_SKIP_PAGER)) { /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n"); fflush(stderr); */ xa = ATOM(_NET_WM_STATE); if (xa != None) { Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER); XChangeProperty(display, window.window, xa, XA_ATOM, 32, PropModeAppend, (unsigned char *) &xa_prop, 1); } } } fprintf(stderr, PACKAGE_NAME": drawing to created window (0x%lx)\n", window.window); fflush(stderr); XMapWindow(display, window.window); } else #endif /* OWN_WINDOW */ { XWindowAttributes attrs; if (!window.window) { window.window = find_desktop_window(&window.root, &window.desktop); } window.visual = DefaultVisual(display, screen); window.colourmap = DefaultColormap(display, screen); if (XGetWindowAttributes(display, window.window, &attrs)) { window.width = attrs.width; window.height = attrs.height; } fprintf(stderr, PACKAGE_NAME": drawing to desktop window\n"); } /* Drawable is same as window. This may be changed by double buffering. */ window.drawable = window.window; XFlush(display); XSelectInput(display, window.window, ExposureMask | PropertyChangeMask #ifdef OWN_WINDOW | (own_window.get(l) ? (StructureNotifyMask | ButtonPressMask | ButtonReleaseMask) : 0) #endif ); } static Window find_subwindow(Window win, int w, int h) { unsigned int i, j; Window troot, parent, *children; unsigned int n; /* search subwindows with same size as display or work area */ for (i = 0; i < 10; i++) { XQueryTree(display, win, &troot, &parent, &children, &n); for (j = 0; j < n; j++) { XWindowAttributes attrs; if (XGetWindowAttributes(display, children[j], &attrs)) { /* Window must be mapped and same size as display or * work space */ if (attrs.map_state != 0 && ((attrs.width == display_width && attrs.height == display_height) || (attrs.width == w && attrs.height == h))) { win = children[j]; break; } } } XFree(children); if (j == n) { break; } } return win; } void create_gc(void) { XGCValues values; values.graphics_exposures = 0; values.function = GXcopy; window.gc = XCreateGC(display, window.drawable, GCFunction | GCGraphicsExposures, &values); } //Get current desktop number static inline void get_x11_desktop_current(Display *current_display, Window root, Atom atom) { Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = NULL; struct information *current_info = &info; if (atom == None) return; if ( (XGetWindowProperty( current_display, root, atom, 0, 1L, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after, &prop ) == Success ) && (actual_type == XA_CARDINAL) && (nitems == 1L) && (actual_format == 32) ) { current_info->x11.desktop.current = prop[0]+1; } if(prop) { XFree(prop); } } //Get total number of available desktops static inline void get_x11_desktop_number(Display *current_display, Window root, Atom atom) { Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = NULL; struct information *current_info = &info; if (atom == None) return; if ( (XGetWindowProperty( current_display, root, atom, 0, 1L, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after, &prop ) == Success ) && (actual_type == XA_CARDINAL) && (nitems == 1L) && (actual_format == 32) ) { current_info->x11.desktop.number = prop[0]; } if(prop) { XFree(prop); } } //Get all desktop names static inline void get_x11_desktop_names(Display *current_display, Window root, Atom atom) { Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = NULL; struct information *current_info = &info; if (atom == None) return; if ( (XGetWindowProperty( current_display, root, atom, 0, (~0L), False, ATOM(UTF8_STRING), &actual_type, &actual_format, &nitems, &bytes_after, &prop ) == Success ) && (actual_type == ATOM(UTF8_STRING)) && (nitems > 0L) && (actual_format == 8) ) { current_info->x11.desktop.all_names.assign(reinterpret_cast(prop), nitems); } if(prop) { XFree(prop); } } //Get current desktop name static inline void get_x11_desktop_current_name(const std::string &names) { struct information *current_info = &info; unsigned int i = 0, j = 0; int k = 0; while ( i < names.size() ) { if ( names[i++] == '\0' ) { if ( ++k == current_info->x11.desktop.current ) { current_info->x11.desktop.name.assign(names.c_str()+j); break; } j = i; } } } void get_x11_desktop_info(Display *current_display, Atom atom) { Window root; static Atom atom_current, atom_number, atom_names; struct information *current_info = &info; XWindowAttributes window_attributes; root = RootWindow(current_display, current_info->x11.monitor.current); /* Check if we initialise else retrieve changed property */ if (atom == 0) { atom_current = XInternAtom(current_display, "_NET_CURRENT_DESKTOP", True); atom_number = XInternAtom(current_display, "_NET_NUMBER_OF_DESKTOPS", True); atom_names = XInternAtom(current_display, "_NET_DESKTOP_NAMES", True); get_x11_desktop_current(current_display, root, atom_current); get_x11_desktop_number(current_display, root, atom_number); get_x11_desktop_names(current_display, root, atom_names); get_x11_desktop_current_name(current_info->x11.desktop.all_names); /* Set the PropertyChangeMask on the root window, if not set */ XGetWindowAttributes(display, root, &window_attributes); if (!(window_attributes.your_event_mask & PropertyChangeMask)) { XSetWindowAttributes attributes; attributes.event_mask = window_attributes.your_event_mask | PropertyChangeMask; XChangeWindowAttributes(display, root, CWEventMask, &attributes); XGetWindowAttributes(display, root, &window_attributes); } } else { if (atom == atom_current) { get_x11_desktop_current(current_display, root, atom_current); get_x11_desktop_current_name(current_info->x11.desktop.all_names); } else if (atom == atom_number) { get_x11_desktop_number(current_display, root, atom_number); } else if (atom == atom_names) { get_x11_desktop_names(current_display, root, atom_names); get_x11_desktop_current_name(current_info->x11.desktop.all_names); } } } static const char NOT_IN_X[] = "Not running in X"; void print_monitor(struct text_object *obj, char *p, int p_max_size) { (void)obj; if(not out_to_x.get(*state)) { strncpy(p, NOT_IN_X, p_max_size); return; } snprintf(p, p_max_size, "%d", XDefaultScreen(display)); } void print_monitor_number(struct text_object *obj, char *p, int p_max_size) { (void)obj; if(not out_to_x.get(*state)) { strncpy(p, NOT_IN_X, p_max_size); return; } snprintf(p, p_max_size, "%d", XScreenCount(display)); } void print_desktop(struct text_object *obj, char *p, int p_max_size) { (void)obj; if(not out_to_x.get(*state)) { strncpy(p, NOT_IN_X, p_max_size); return; } snprintf(p, p_max_size, "%d", info.x11.desktop.current); } void print_desktop_number(struct text_object *obj, char *p, int p_max_size) { (void)obj; if(not out_to_x.get(*state)) { strncpy(p, NOT_IN_X, p_max_size); return; } snprintf(p, p_max_size, "%d", info.x11.desktop.number); } void print_desktop_name(struct text_object *obj, char *p, int p_max_size) { (void)obj; if(not out_to_x.get(*state)) { strncpy(p, NOT_IN_X, p_max_size); } else { strncpy(p, info.x11.desktop.name.c_str(), p_max_size); } } #ifdef OWN_WINDOW /* reserve window manager space */ void set_struts(int sidenum) { Atom strut; if ((strut = ATOM(_NET_WM_STRUT)) != None) { /* reserve space at left, right, top, bottom */ signed long sizes[12] = {0}; int i; /* define strut depth */ switch (sidenum) { case 0: /* left side */ sizes[0] = window.x + window.width; break; case 1: /* right side */ sizes[1] = display_width - window.x; break; case 2: /* top side */ sizes[2] = window.y + window.height; break; case 3: /* bottom side */ sizes[3] = display_height - window.y; break; } /* define partial strut length */ if (sidenum <= 1) { sizes[4 + (sidenum*2)] = window.y; sizes[5 + (sidenum*2)] = window.y + window.height; } else if (sidenum <= 3) { sizes[4 + (sidenum*2)] = window.x; sizes[5 + (sidenum*2)] = window.x + window.width; } /* check constraints */ for (i = 0; i < 12; i++) { if (sizes[i] < 0) { sizes[i] = 0; } else { if (i <= 1 || i >= 8) { if (sizes[i] > display_width) { sizes[i] = display_width; } } else { if (sizes[i] > display_height) { sizes[i] = display_height; } } } } XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &sizes, 4); if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) { XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &sizes, 12); } } } #endif /* OWN_WINDOW */ #ifdef BUILD_XDBE void xdbe_swap_buffers(void) { if (use_xdbe.get(*state)) { XdbeSwapInfo swap; swap.swap_window = window.window; swap.swap_action = XdbeBackground; XdbeSwapBuffers(display, &swap, 1); } } #else void xpmdb_swap_buffers(void) { if (use_xpmdb.get(*state)) { XCopyArea(display, window.back_buffer, window.window, window.gc, 0, 0, window.width, window.height, 0, 0); XSetForeground(display, window.gc, 0); XFillRectangle(display, window.drawable, window.gc, 0, 0, window.width, window.height); XFlush(display); } } #endif /* BUILD_XDBE */ conky-1.10.1/src/x11.h000066400000000000000000000145571262311664100143040ustar00rootroot00000000000000/* -*- 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-2012 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 . * */ #ifdef BUILD_X11 #ifndef X11_H_ #define X11_H_ #include #include #ifdef BUILD_XFT #include #endif #ifdef BUILD_XDBE #include #endif #include "setting.hh" #include "colours.h" #define ATOM(a) XInternAtom(display, #a, False) #ifdef OWN_WINDOW enum window_type { TYPE_NORMAL = 0, TYPE_DOCK, TYPE_PANEL, TYPE_DESKTOP, TYPE_OVERRIDE }; enum window_hints { HINT_UNDECORATED = 0, HINT_BELOW, HINT_ABOVE, HINT_STICKY, HINT_SKIP_TASKBAR, HINT_SKIP_PAGER }; #define SET_HINT(mask, hint) (mask |= (1 << (hint))) #define TEST_HINT(mask, hint) (mask & (1 << (hint))) #endif struct conky_window { Window root, window, desktop; Drawable drawable; Visual *visual; Colormap colourmap; GC gc; #ifdef BUILD_XDBE XdbeBackBuffer back_buffer; #else Pixmap back_buffer; #endif #ifdef BUILD_XFT XftDraw *xftdraw; #endif int width; int height; #ifdef OWN_WINDOW int x; int y; #endif }; #if defined(BUILD_ARGB) && defined(OWN_WINDOW) /* true if use_argb_visual=true and argb visual was found*/ extern bool have_argb_visual; #endif extern Display *display; extern int display_width; extern int display_height; extern int screen; extern int workarea[4]; extern struct conky_window window; extern char window_created; void destroy_window(void); void create_gc(void); void set_transparent_background(Window win); void get_x11_desktop_info(Display *display, Atom atom); void set_struts(int); void print_monitor(struct text_object *, char *, int); void print_monitor_number(struct text_object *, char *, int); void print_desktop(struct text_object *, char *, int); void print_desktop_number(struct text_object *, char *, int); void print_desktop_name(struct text_object *, char *, int); #ifdef BUILD_XDBE void xdbe_swap_buffers(void); #else void xpmdb_swap_buffers(void); #endif /* BUILD_XDBE */ /* alignments */ enum alignment { TOP_LEFT, TOP_RIGHT, TOP_MIDDLE, BOTTOM_LEFT, BOTTOM_RIGHT, BOTTOM_MIDDLE, MIDDLE_LEFT, MIDDLE_MIDDLE, MIDDLE_RIGHT, NONE }; extern conky::simple_config_setting text_alignment; namespace priv { class out_to_x_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); virtual void cleanup(lua::state &l); public: out_to_x_setting() : Base("out_to_x", true, false) {} }; class own_window_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); public: own_window_setting() : Base("own_window", false, false) {} }; class use_xdbe_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; bool set_up(lua::state &l); protected: virtual void lua_setter(lua::state &l, bool init); public: use_xdbe_setting() : Base("double_buffer", false, false) {} }; class use_xpmdb_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; bool set_up(lua::state &l); protected: virtual void lua_setter(lua::state &l, bool init); public: use_xpmdb_setting() : Base("double_buffer", false, false) {} }; struct colour_traits { static const lua::Type type = lua::TSTRING; typedef unsigned long Type; static inline std::pair convert(lua::state &l, int index, const std::string &) { return {get_x11_color(l.tostring(index)), true}; } }; class colour_setting: public conky::simple_config_setting { typedef conky::simple_config_setting Base; protected: virtual void lua_setter(lua::state &l, bool init); public: colour_setting(const std::string &name_, unsigned long default_value_ = 0) : Base(name_, default_value_, true) {} }; } extern priv::out_to_x_setting out_to_x; extern conky::simple_config_setting display_name; extern priv::colour_setting color[10]; extern priv::colour_setting default_color; extern priv::colour_setting default_shade_color; extern priv::colour_setting default_outline_color; extern conky::range_config_setting border_inner_margin; extern conky::range_config_setting border_outer_margin; extern conky::range_config_setting border_width; #ifdef BUILD_XFT extern conky::simple_config_setting use_xft; #endif #ifdef OWN_WINDOW extern conky::simple_config_setting set_transparent; extern conky::simple_config_setting own_window_class; extern conky::simple_config_setting own_window_title; extern conky::simple_config_setting own_window_type; struct window_hints_traits { static const lua::Type type = lua::TSTRING; typedef uint16_t Type; static std::pair convert(lua::state &l, int index, const std::string &name); }; extern conky::simple_config_setting own_window_hints; #ifdef BUILD_ARGB extern conky::simple_config_setting use_argb_visual; /* range of 0-255 for alpha */ extern conky::range_config_setting own_window_argb_value; #endif #endif /*OWN_WINDOW*/ extern priv::own_window_setting own_window; #ifdef BUILD_XDBE extern priv::use_xdbe_setting use_xdbe; #else extern priv::use_xpmdb_setting use_xpmdb; #endif #endif /*X11_H_*/ #endif /* BUILD_X11 */ conky-1.10.1/src/xmms2.cc000066400000000000000000000277261262311664100151010ustar00rootroot00000000000000/* -*- 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 * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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" xmmsc_connection_t *xmms2_conn; #define CONN_INIT 0 #define CONN_OK 1 #define CONN_NO 2 static void xmms_alloc(struct information *ptr) { if (ptr->xmms2.artist == NULL) { ptr->xmms2.artist = (char*) malloc(text_buffer_size.get(*state)); } if (ptr->xmms2.album == NULL) { ptr->xmms2.album = (char*) malloc(text_buffer_size.get(*state)); } if (ptr->xmms2.title == NULL) { ptr->xmms2.title = (char*) malloc(text_buffer_size.get(*state)); } if (ptr->xmms2.genre == NULL) { ptr->xmms2.genre = (char*) malloc(text_buffer_size.get(*state)); } if (ptr->xmms2.comment == NULL) { ptr->xmms2.comment = (char*) malloc(text_buffer_size.get(*state)); } if (ptr->xmms2.url == NULL) { ptr->xmms2.url = (char*) malloc(text_buffer_size.get(*state)); } if (ptr->xmms2.date == NULL) { ptr->xmms2.date = (char*) malloc(text_buffer_size.get(*state)); } ptr->xmms2.artist[0] = '\0'; ptr->xmms2.album[0] = '\0'; ptr->xmms2.title[0] = '\0'; ptr->xmms2.genre[0] = '\0'; ptr->xmms2.comment[0] = '\0'; ptr->xmms2.url[0] = '\0'; ptr->xmms2.date[0] = '\0'; ptr->xmms2.tracknr = 0; ptr->xmms2.id = 0; ptr->xmms2.bitrate = 0; ptr->xmms2.duration = 0; ptr->xmms2.elapsed = 0; ptr->xmms2.size = 0; ptr->xmms2.progress = 0; ptr->xmms2.timesplayed = -1; } void free_xmms2(struct text_object *obj) { (void)obj; free_and_zero(info.xmms2.artist); free_and_zero(info.xmms2.album); free_and_zero(info.xmms2.title); free_and_zero(info.xmms2.genre); free_and_zero(info.xmms2.comment); free_and_zero(info.xmms2.url); free_and_zero(info.xmms2.date); free_and_zero(info.xmms2.status); free_and_zero(info.xmms2.playlist); } void connection_lost(void *p) { struct information *ptr = (struct information*) p; ptr->xmms2.conn_state = CONN_NO; fprintf(stderr,"XMMS2 connection failed. %s\n", xmmsc_get_last_error(xmms2_conn)); xmms_alloc(ptr); strncpy(ptr->xmms2.status, "Disconnected", text_buffer_size.get(*state) - 1); ptr->xmms2.playlist[0] = '\0'; ptr->xmms2.id = 0; } int handle_curent_id(xmmsv_t *value, void *p) { struct information *ptr = (struct information*) p; xmmsv_t *val, *infos, *dict_entry; xmmsc_result_t *res; const char *errbuf; int current_id; const char *charval; int intval; if (xmmsv_get_error(value, &errbuf)) { fprintf(stderr,"XMMS2 server error. %s\n", errbuf); return TRUE; } if (xmmsv_get_int(value, ¤t_id) && current_id > 0) { res = xmmsc_medialib_get_info(xmms2_conn, current_id); xmmsc_result_wait(res); val = xmmsc_result_get_value(res); if (xmmsv_get_error(val, &errbuf)) { fprintf(stderr,"XMMS2 server error. %s\n", errbuf); return TRUE; } xmms_alloc(ptr); ptr->xmms2.id = current_id; infos = xmmsv_propdict_to_dict(val, NULL); if (xmmsv_dict_get(infos, "artist", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.artist, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "title", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.title, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "album", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.album, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "genre", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.genre, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "comment", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.comment, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "url", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.url, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "date", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) strncpy(ptr->xmms2.date, charval, text_buffer_size.get(*state) - 1); if (xmmsv_dict_get(infos, "tracknr", &dict_entry) && xmmsv_get_int(dict_entry, &intval)) ptr->xmms2.tracknr = intval; if (xmmsv_dict_get(infos, "duration", &dict_entry) && xmmsv_get_int(dict_entry, &intval)) ptr->xmms2.duration = intval; if (xmmsv_dict_get(infos, "bitrate", &dict_entry) && xmmsv_get_int(dict_entry, &intval)) ptr->xmms2.bitrate = intval / 1000; if (xmmsv_dict_get(infos, "size", &dict_entry) && xmmsv_get_int(dict_entry, &intval)) ptr->xmms2.size = (float) intval / 1048576; if (xmmsv_dict_get(infos, "timesplayed", &dict_entry) && xmmsv_get_int(dict_entry, &intval)) ptr->xmms2.timesplayed = intval; xmmsv_unref(infos); xmmsc_result_unref(res); } return TRUE; } int handle_playtime(xmmsv_t *value, void *p) { struct information *ptr = (struct information*) p; int play_time; const char *errbuf; if (xmmsv_get_error(value, &errbuf)) { fprintf(stderr,"XMMS2 server error. %s\n", errbuf); return TRUE; } if (xmmsv_get_int(value, &play_time)) { ptr->xmms2.elapsed = play_time; ptr->xmms2.progress = (float) play_time / ptr->xmms2.duration; ptr->xmms2.percent = (int)(ptr->xmms2.progress*100); } return TRUE; } int handle_playback_state_change(xmmsv_t *value, void *p) { struct information *ptr = (struct information*) p; int pb_state = 0; const char *errbuf; if (xmmsv_get_error(value, &errbuf)) { fprintf(stderr,"XMMS2 server error. %s\n", errbuf); return TRUE; } if (ptr->xmms2.status == NULL) { ptr->xmms2.status = (char*) malloc(text_buffer_size.get(*state)); ptr->xmms2.status[0] = '\0'; } if (xmmsv_get_int(value, &pb_state)) { switch (pb_state) { case XMMS_PLAYBACK_STATUS_PLAY: strncpy(ptr->xmms2.status, "Playing", text_buffer_size.get(*state) - 1); break; case XMMS_PLAYBACK_STATUS_PAUSE: strncpy(ptr->xmms2.status, "Paused", text_buffer_size.get(*state) - 1); break; case XMMS_PLAYBACK_STATUS_STOP: strncpy(ptr->xmms2.status, "Stopped", text_buffer_size.get(*state) - 1); ptr->xmms2.elapsed = ptr->xmms2.progress = ptr->xmms2.percent = 0; break; default: strncpy(ptr->xmms2.status, "Unknown", text_buffer_size.get(*state) - 1); } } return TRUE; } int handle_playlist_loaded(xmmsv_t *value, void *p) { struct information *ptr = (struct information*) p; const char *c, *errbuf; if (xmmsv_get_error(value, &errbuf)) { fprintf(stderr,"XMMS2 server error. %s\n", errbuf); return TRUE; } if (ptr->xmms2.playlist == NULL) { ptr->xmms2.playlist = (char*) malloc(text_buffer_size.get(*state)); ptr->xmms2.playlist[0] = '\0'; } if (xmmsv_get_string(value, &c)) { strncpy(ptr->xmms2.playlist, c, text_buffer_size.get(*state) - 1); } return TRUE; } int handle_medialib_changed(xmmsv_t *value, void *p) { struct information *ptr = (struct information*) p; const char *errbuf; int current_id; if (xmmsv_get_error(value, &errbuf)) { fprintf(stderr,"XMMS2 server error. %s\n", errbuf); return TRUE; } if (xmmsv_get_int(value, ¤t_id) && current_id > 0 && ptr->xmms2.id == (unsigned int)current_id) { return handle_curent_id(value, ptr); } return TRUE; } int update_xmms2(void) { struct information *current_info = &info; /* initialize connection */ if (current_info->xmms2.conn_state == CONN_INIT) { if (xmms2_conn == NULL) { xmms2_conn = xmmsc_init(PACKAGE_NAME); } /* did init fail? */ if (xmms2_conn == NULL) { fprintf(stderr,"XMMS2 init failed. %s\n", xmmsc_get_last_error(xmms2_conn)); return 0; } /* init ok but not connected yet.. */ current_info->xmms2.conn_state = CONN_NO; /* clear all values */ xmms_alloc(current_info); } /* connect */ if (current_info->xmms2.conn_state == CONN_NO) { char *path = getenv("XMMS_PATH"); 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 0; } /* set callbacks */ xmmsc_disconnect_callback_set(xmms2_conn, connection_lost, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_playback_current_id, handle_curent_id, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_signal_playback_playtime, handle_playtime, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_playback_status, handle_playback_state_change, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_playlist_loaded, handle_playlist_loaded, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_medialib_entry_changed, handle_medialib_changed, current_info); /* get playback status, current id and active playlist */ XMMS_CALLBACK_SET(xmms2_conn, xmmsc_playback_current_id, handle_curent_id, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_playback_status, handle_playback_state_change, current_info); XMMS_CALLBACK_SET(xmms2_conn, xmmsc_playlist_current_active, handle_playlist_loaded, current_info); /* everything seems to be ok */ current_info->xmms2.conn_state = CONN_OK; } /* handle callbacks */ if (current_info->xmms2.conn_state == CONN_OK) { xmmsc_io_in_handle(xmms2_conn); if (xmmsc_io_want_out(xmms2_conn)) xmmsc_io_out_handle(xmms2_conn); } return 0; } void print_xmms2_tracknr(struct text_object *obj, char *p, int p_max_size) { (void)obj; if (info.xmms2.tracknr != -1) { snprintf(p, p_max_size, "%i", info.xmms2.tracknr); } } void print_xmms2_elapsed(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%02d:%02d", info.xmms2.elapsed / 60000, (info.xmms2.elapsed / 1000) % 60); } void print_xmms2_duration(struct text_object *obj, char *p, int p_max_size) { (void)obj; snprintf(p, p_max_size, "%02d:%02d", info.xmms2.duration / 60000, (info.xmms2.duration / 1000) % 60); } double xmms2_barval(struct text_object *obj) { (void)obj; return info.xmms2.progress; } void print_xmms2_smart(struct text_object *obj, char *p, int p_max_size) { (void)obj; int artist_len = strlen(info.xmms2.artist); int title_len = strlen(info.xmms2.title); if (artist_len < 2 && title_len < 2) { snprintf(p, p_max_size, "%s", info.xmms2.url); } else if (artist_len < 1) { snprintf(p, p_max_size, "%s", info.xmms2.title); } else { snprintf(p, p_max_size, "%s - %s", info.xmms2.artist, info.xmms2.title); } } #define XMMS2_PRINT_GENERATOR(name, fmt) \ void print_xmms2_##name(struct text_object *obj, char *p, int p_max_size) \ { \ (void)obj; \ snprintf(p, p_max_size, fmt, info.xmms2.name); \ } XMMS2_PRINT_GENERATOR(artist, "%s") XMMS2_PRINT_GENERATOR(album, "%s") XMMS2_PRINT_GENERATOR(title, "%s") XMMS2_PRINT_GENERATOR(genre, "%s") XMMS2_PRINT_GENERATOR(comment, "%s") XMMS2_PRINT_GENERATOR(url, "%s") XMMS2_PRINT_GENERATOR(status, "%s") XMMS2_PRINT_GENERATOR(date, "%s") XMMS2_PRINT_GENERATOR(bitrate, "%i") XMMS2_PRINT_GENERATOR(id, "%u") XMMS2_PRINT_GENERATOR(size, "%2.1f") XMMS2_PRINT_GENERATOR(playlist, "%s") XMMS2_PRINT_GENERATOR(timesplayed, "%i") XMMS2_PRINT_GENERATOR(percent, "%i") #undef XMMS2_PRINT_GENERATOR int if_xmms2_connected(struct text_object *obj) { (void)obj; return info.xmms2.conn_state == CONN_OK; } conky-1.10.1/src/xmms2.h000066400000000000000000000052051262311664100147270ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- * * Conky, a system monitor, based on torsmo * * Any original torsmo code is licensed under the BSD license * * All code written since the fork of torsmo is licensed under the GPL * * Please see COPYING for details * * Copyright (c) 2005-2012 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 XMMS2_H_ #define XMMS2_H_ #include struct xmms2_s { char *artist; char *album; char *title; char *genre; char *comment; char *url; char *date; char *playlist; int tracknr; int bitrate; unsigned int id; int duration; int elapsed; int timesplayed; float size; float progress; int percent; char *status; int conn_state; }; int update_xmms2(void); void print_xmms2_tracknr(struct text_object *, char *, int); void print_xmms2_elapsed(struct text_object *, char *, int); void print_xmms2_duration(struct text_object *, char *, int); double xmms2_barval(struct text_object *); void print_xmms2_smart(struct text_object *, char *, int); void print_xmms2_artist(struct text_object *, char *, int); void print_xmms2_album(struct text_object *, char *, int); void print_xmms2_title(struct text_object *, char *, int); void print_xmms2_genre(struct text_object *, char *, int); void print_xmms2_comment(struct text_object *, char *, int); void print_xmms2_url(struct text_object *, char *, int); void print_xmms2_status(struct text_object *, char *, int); void print_xmms2_date(struct text_object *, char *, int); void print_xmms2_bitrate(struct text_object *, char *, int); void print_xmms2_id(struct text_object *, char *, int); void print_xmms2_size(struct text_object *, char *, int); void print_xmms2_playlist(struct text_object *, char *, int); void print_xmms2_timesplayed(struct text_object *, char *, int); void print_xmms2_percent(struct text_object *, char *, int); int if_xmms2_connected(struct text_object *); void free_xmms2(struct text_object *); #endif /*XMMS2_H_*/ conky-1.10.1/text2c.sh000077500000000000000000000024501262311664100144700ustar00rootroot00000000000000#!/bin/sh # # text2c.sh - convert a text file to C code # # Copyright (C) 2008 Phil Sutter # # 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 . # Invocation is as follows: # $1: text file # $2: output file # $3: name of variable # # The output will be a char **, with each field containing a single line of $1. # Additionally, a macro with the name print_$3 will be defined, with acts as # a parameter-less function, printing the text to stdout. [ $# -eq 3 ] || { echo "Usage: `basename $0` " exit 1 } outupper="`basename "$2" | tr '[a-z-.]' '[A-Z__]'`" ( printf "const char %s[] = \n" "$3" sed -e 's/["\]/\\&/g' -e 's/^/ "/' -e 's/$/\\n"/' -e '$s/$/;/' "$1" ) > "$2"