Fix for segfault in top_name stuff.
[monky] / src / core.c
index eef425d..e0e7218 100644 (file)
@@ -10,7 +10,7 @@
  * Please see COPYING for details
  *
  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
- * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
+ * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al.
  *     (see AUTHORS)
  * All rights reserved.
  *
 #include "colours.h"
 #include "combine.h"
 #include "diskio.h"
+#include "entropy.h"
 #include "exec.h"
+#include "i8k.h"
+#include "proc.h"
 #ifdef X11
 #include "fonts.h"
 #endif
@@ -74,9 +77,6 @@
 #include "openbsd.h"
 #endif
 
-/* OS specific prototypes to be implemented by linux.c & Co. */
-void update_entropy(void);
-
 #include <string.h>
 #include <ctype.h>
 
@@ -153,14 +153,26 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                obj->data.l = get_x11_color(s);
        } else
 #endif /* X11 */
-#ifdef __OpenBSD__
-       OBJ(freq, 0)
-#else
+#ifndef __OpenBSD__
        OBJ(acpitemp, 0)
                obj->data.i = open_acpi_temperature(arg);
        END OBJ(acpiacadapter, 0)
-       END OBJ(freq, 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
+               }
 #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) {
@@ -265,8 +277,9 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                obj->data.s = strndup(bat, text_buffer_size);
        END OBJ(battery_bar, 0)
                char bat[64];
-               if (arg) {
-                       arg = scan_bar(obj, arg);
+
+               arg = scan_bar(obj, arg);
+               if (arg && strlen(arg)>0) {
                        sscanf(arg, "%63s", bat);
                } else {
                        strcpy(bat, "BAT0");
@@ -339,12 +352,10 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
        END OBJ(cpu, &update_cpu_usage)
                SCAN_CPU(arg, obj->data.i);
                DBGP2("Adding $cpu for CPU %d", obj->data.i);
-#ifdef X11
        END OBJ(cpugauge, &update_cpu_usage)
                SCAN_CPU(arg, obj->data.i);
                scan_gauge(obj, arg);
                DBGP2("Adding $cpugauge for CPU %d", obj->data.i);
-#endif /* X11 */
        END OBJ(cpubar, &update_cpu_usage)
                SCAN_CPU(arg, obj->data.i);
                scan_bar(obj, arg);
@@ -360,18 +371,18 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                scan_loadgraph_arg(obj, arg);
 #endif /* X11 */
        END OBJ(diskio, &update_diskio)
-               parse_diskio_arg(obj, arg);
+               parse_diskio_arg(obj, dev_name(arg));
        END OBJ(diskio_read, &update_diskio)
-               parse_diskio_arg(obj, arg);
+               parse_diskio_arg(obj, dev_name(arg));
        END OBJ(diskio_write, &update_diskio)
-               parse_diskio_arg(obj, arg);
+               parse_diskio_arg(obj, dev_name(arg));
 #ifdef X11
        END OBJ(diskiograph, &update_diskio)
-               parse_diskiograph_arg(obj, arg);
+               parse_diskiograph_arg(obj, dev_name(arg));
        END OBJ(diskiograph_read, &update_diskio)
-               parse_diskiograph_arg(obj, arg);
+               parse_diskiograph_arg(obj, dev_name(arg));
        END OBJ(diskiograph_write, &update_diskio)
-               parse_diskiograph_arg(obj, arg);
+               parse_diskiograph_arg(obj, dev_name(arg));
 #endif /* X11 */
        END OBJ(color, 0)
 #ifdef X11
@@ -439,8 +450,14 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                obj->data.s = scan_font(arg);
 #endif /* X11 */
        END OBJ(conky_version, 0)
+               obj->type = OBJ_text;
+               obj->data.s = strdup(VERSION);
        END OBJ(conky_build_date, 0)
+               obj->type = OBJ_text;
+               obj->data.s = strdup(BUILD_DATE);
        END OBJ(conky_build_arch, 0)
+               obj->type = OBJ_text;
+               obj->data.s = strdup(BUILD_ARCH);
        END OBJ(downspeed, &update_net_stats)
                parse_net_stat_arg(obj, arg, free_at_crash);
        END OBJ(downspeedf, &update_net_stats)
@@ -465,9 +482,9 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                scan_exec_arg(obj, arg);
        END OBJ(execbar, 0)
                scan_exec_arg(obj, arg);
-#ifdef X11
        END OBJ(execgauge, 0)
                scan_exec_arg(obj, arg);
+#ifdef X11
        END OBJ(execgraph, 0)
                scan_execgraph_arg(obj, arg);
 #endif /* X11 */
@@ -476,9 +493,9 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
 #ifdef X11
        END OBJ_ARG(execigraph, 0, "execigraph needs arguments")
                scan_execgraph_arg(obj, arg);
+#endif /* X11 */
        END OBJ_ARG(execigauge, 0, "execigauge needs arguments")
                scan_execi_arg(obj, arg);
-#endif /* X11 */
        END OBJ_ARG(execi, 0, "execi needs arguments")
                scan_execi_arg(obj, arg);
        END OBJ_ARG(execpi, 0, "execpi needs arguments")
@@ -524,8 +541,11 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                parse_platform_sensor(obj, arg);
        END OBJ_ARG(hwmon, 0, "hwmon needs argumanets")
                parse_hwmon_sensor(obj, arg);
+       END OBJ(addr, &update_net_stats)
+               parse_net_stat_arg(obj, arg, free_at_crash);
+       END OBJ(addrs, &update_net_stats)
+               parse_net_stat_arg(obj, arg, free_at_crash);
 #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
@@ -536,13 +556,8 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                if (!parse_top_args(s, arg, obj)) {
                        return NULL;
                }
-       } else OBJ(addr, &update_net_stats)
-               parse_net_stat_arg(obj, arg, free_at_crash);
-#if defined(__linux__)
-       END OBJ(addrs, &update_net_stats)
-               parse_net_stat_arg(obj, arg, free_at_crash);
-#endif /* __linux__ */
-       END OBJ_ARG(tail, 0, "tail needs arguments")
+       } else
+               OBJ_ARG(tail, 0, "tail needs arguments")
                init_tailhead("tail", arg, obj, free_at_crash);
        END OBJ_ARG(head, 0, "head needs arguments")
                init_tailhead("head", arg, obj, free_at_crash);
@@ -568,9 +583,9 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                obj->data.s = strndup(arg, text_buffer_size);
 #else
        END OBJ_IF_ARG(if_running, 0, "if_running needs an argument")
-               char buf[256];
+               char buf[text_buffer_size];
 
-               snprintf(buf, 256, "pidof %s >/dev/null", arg);
+               snprintf(buf, text_buffer_size, "pidof %s >/dev/null", arg);
                obj->data.s = strndup(buf, text_buffer_size);
 #endif
        END OBJ(kernel, 0)
@@ -606,10 +621,8 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
        END OBJ(memfree, &update_meminfo)
        END OBJ(memmax, &update_meminfo)
        END OBJ(memperc, &update_meminfo)
-#ifdef X11
        END OBJ(memgauge, &update_meminfo)
                scan_gauge(obj, arg);
-#endif /* X11*/
        END OBJ(membar, &update_meminfo)
                scan_bar(obj, arg);
 #ifdef X11
@@ -625,14 +638,12 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                parse_mixer_arg(obj, arg);
        END OBJ(mixerr, 0)
                parse_mixer_arg(obj, arg);
-#ifdef X11
        END OBJ(mixerbar, 0)
                scan_mixer_bar(obj, arg);
        END OBJ(mixerlbar, 0)
                scan_mixer_bar(obj, arg);
        END OBJ(mixerrbar, 0)
                scan_mixer_bar(obj, arg);
-#endif
        END OBJ_IF(if_mixer_mute, 0)
                parse_mixer_arg(obj, arg);
 #ifdef X11
@@ -642,10 +653,148 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
        END OBJ(desktop_number, &update_x11info)
        END OBJ(desktop_name, &update_x11info)
 #endif
+       END OBJ_ARG(format_time, 0, "format_time needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
        END OBJ(nodename, 0)
+       END OBJ(nodename_short, 0)
+       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);
+       END OBJ_ARG(pid_chroot, 0, "pid_chroot needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_cmdline, 0, "pid_cmdline needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_cwd, 0, "pid_cwd needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_environ, 0, "pid_environ needs arguments")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_environ_list, 0, "pid_environ_list needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_exe, 0, "pid_exe needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_nice, 0, "pid_nice needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_openfiles, 0, "pid_openfiles needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_parent, 0, "pid_parent needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_priority, 0, "pid_priority needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_state, 0, "pid_state needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_state_short, 0, "pid_state_short needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_stderr, 0, "pid_stderr needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_stdin, 0, "pid_stdin needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_stdout, 0, "pid_stdout needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_threads, 0, "pid_threads needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_thread_list, 0, "pid_thread_list needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_time_kernelmode, 0, "pid_time_kernelmode needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_time_usermode, 0, "pid_time_usermode needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_time, 0, "pid_time needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_uid, 0, "pid_uid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_euid, 0, "pid_euid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_suid, 0, "pid_suid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_fsuid, 0, "pid_fsuid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_gid, 0, "pid_gid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_egid, 0, "pid_egid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_sgid, 0, "pid_sgid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_fsgid, 0, "pid_fsgid needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(gid_name, 0, "gid_name needs a gid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(uid_name, 0, "uid_name needs a uid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_read, 0, "pid_read needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmpeak, 0, "pid_vmpeak needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmsize, 0, "pid_vmsize needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmlck, 0, "pid_vmlck needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmhwm, 0, "pid_vmhwm needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmrss, 0, "pid_vmrss needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmdata, 0, "pid_vmdata needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmstk, 0, "pid_vmstk needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmexe, 0, "pid_vmexe needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmlib, 0, "pid_vmlib needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_vmpte, 0, "pid_vmpte needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
+       END OBJ_ARG(pid_write, 0, "pid_write needs a pid as argument")
+               obj->sub = malloc(sizeof(struct text_object));
+               extract_variable_text_internal(obj->sub, arg);
        END OBJ(processes, &update_total_processes)
-       END OBJ(running_processes, &update_running_processes)
+       END OBJ(running_processes, &update_top)
+               top_running = 1;
+#ifdef __linux__
        END OBJ(threads, &update_threads)
+       END OBJ(running_threads, &update_stat)
+#else
+       END OBJ(running_processes, &update_running_processes)
+#endif /* __linux__ */
        END OBJ(shadecolor, 0)
 #ifdef X11
                obj->data.l = arg ? get_x11_color(arg) : default_bg_color;
@@ -700,18 +849,16 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
 #endif
        END OBJ(uptime_short, &update_uptime)
        END OBJ(uptime, &update_uptime)
+#if defined(__linux__)
        END OBJ(user_names, &update_users)
        END OBJ(user_times, &update_users)
+       END OBJ_ARG(user_time, 0, "user time needs a console name as argument")
+               obj->data.s = strndup(arg, text_buffer_size);
        END OBJ(user_terms, &update_users)
        END OBJ(user_number, &update_users)
-#if defined(__linux__)
        END OBJ(gw_iface, &update_gateway_info)
        END OBJ(gw_ip, &update_gateway_info)
 #endif /* !__linux__ */
-#ifndef __OpenBSD__
-       END OBJ(adt746xcpu, 0)
-       END OBJ(adt746xfan, 0)
-#endif /* !__OpenBSD__ */
 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
                || defined(__OpenBSD__)) && (defined(i386) || defined(__i386__))
        END OBJ(apm_adapter, 0)
@@ -737,7 +884,6 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                obj->data.s = strndup(arg, text_buffer_size);
        END OBJ_ARG(smapi_bat_power, 0, "smapi_bat_power needs an argument")
                obj->data.s = strndup(arg, text_buffer_size);
-#ifdef X11
        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) {
@@ -745,7 +891,6 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                        obj->data.i = -1;
                } else
                        arg = scan_bar(obj, arg + cnt);
-#endif /* X11 */
 #endif /* IBM */
 #ifdef MPD
 #define mpd_set_maxlen(name) \
@@ -822,10 +967,8 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
        END OBJ(xmms2_size, &update_xmms2)
        END OBJ(xmms2_status, &update_xmms2)
        END OBJ(xmms2_percent, &update_xmms2)
-#ifdef X11
        END OBJ(xmms2_bar, &update_xmms2)
                scan_bar(obj, arg);
-#endif /* X11 */
        END OBJ(xmms2_smart, &update_xmms2)
        END OBJ(xmms2_playlist, &update_xmms2)
        END OBJ(xmms2_timesplayed, &update_xmms2)
@@ -851,10 +994,8 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
        END OBJ(audacious_playlist_length, &update_audacious)
        END OBJ(audacious_playlist_position, &update_audacious)
        END OBJ(audacious_main_volume, &update_audacious)
-#ifdef X11
        END OBJ(audacious_bar, &update_audacious)
                scan_bar(obj, arg);
-#endif /* X11 */
 #endif
 #ifdef BMPX
        END OBJ(bmpx_title, &update_bmpx)
@@ -911,6 +1052,7 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                } else {
                        CRIT_ERR(obj, free_at_crash, "lua_graph needs arguments: <function name> [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]");
                }
+#endif /* X11 */
        END OBJ_ARG(lua_gauge, 0, "lua_gauge needs arguments: <height>,<width> <function name> [function parameters]")
                arg = scan_gauge(obj, arg);
                if (arg) {
@@ -918,7 +1060,6 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                } else {
                        CRIT_ERR(obj, free_at_crash, "lua_gauge needs arguments: <height>,<width> <function name> [function parameters]");
                }
-#endif /* X11 */
 #endif /* HAVE_LUA */
 #ifdef HDDTEMP
        END OBJ(hddtemp, &update_hddtemp)
@@ -989,20 +1130,20 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                char* buf = 0;
                buf = scan_graph(obj, arg, 0);
                if (buf) free(buf);
+#endif /* X11 */
        END OBJ(apcupsd_loadgauge, &update_apcupsd)
                scan_gauge(obj, arg);
-#endif /* X11 */
        END OBJ(apcupsd_charge, &update_apcupsd)
        END OBJ(apcupsd_timeleft, &update_apcupsd)
        END OBJ(apcupsd_temp, &update_apcupsd)
        END OBJ(apcupsd_lastxfer, &update_apcupsd)
 #endif /* APCUPSD */
        END {
-               char buf[256];
+               char buf[text_buffer_size];
 
                NORM_ERR("unknown variable %s", s);
                obj->type = OBJ_text;
-               snprintf(buf, 256, "${%s}", s);
+               snprintf(buf, text_buffer_size, "${%s}", s);
                obj->data.s = strndup(buf, text_buffer_size);
        }
 #undef OBJ
@@ -1072,9 +1213,9 @@ int extract_variable_text_internal(struct text_object *retval, const char *const
        s = orig_p = p;
 
        if (strcmp(p, const_p)) {
-               DBGP("replaced all templates in text: input is\n'%s'\noutput is\n'%s'", const_p, p);
+               DBGP2("replaced all templates in text: input is\n'%s'\noutput is\n'%s'", const_p, p);
        } else {
-               DBGP("no templates to replace");
+               DBGP2("no templates to replace");
        }
 
        memset(retval, 0, sizeof(struct text_object));
@@ -1096,7 +1237,7 @@ int extract_variable_text_internal(struct text_object *retval, const char *const
                        s = p;
 
                        if (*p != '$') {
-                               char buf[256];
+                               char buf[text_buffer_size];
                                const char *var;
 
                                /* variable is either $foo or ${foo} */
@@ -1126,7 +1267,7 @@ int extract_variable_text_internal(struct text_object *retval, const char *const
                                }
 
                                /* copy variable to buffer */
-                               len = (p - s > 255) ? 255 : (p - s);
+                               len = ((unsigned int) (p - s) > text_buffer_size - 1) ? text_buffer_size - 1 : (unsigned int) (p - s);
                                strncpy(buf, s, len);
                                buf[len] = '\0';
 
@@ -1187,7 +1328,7 @@ int extract_variable_text_internal(struct text_object *retval, const char *const
                        strfold(p, 1);
                } else if (*p == '#') {
                        char c;
-                       if (remove_comment(p, &c) && p > orig_p && c == '\n') {
+                       if (remove_comment(p, &c) && p >= orig_p && c == '\n') {
                                /* if remove_comment removed a newline, we need to 'back up' with p */
                                p--;
                        }
@@ -1227,6 +1368,9 @@ void free_text_objects(struct text_object *root, int internal)
                        case OBJ_acpitemp:
                                close(data.i);
                                break;
+                       case OBJ_acpiacadapter:
+                               free(data.opaque);
+                               break;
 #endif /* !__OpenBSD__ */
 #ifdef __linux__
                        case OBJ_i2c:
@@ -1235,6 +1379,62 @@ void free_text_objects(struct text_object *root, int internal)
                                free_sysfs_sensor(obj);
                                break;
 #endif /* __linux__ */
+                       case OBJ_cmdline_to_pid:
+                               free(data.s);
+                               break;
+                       case OBJ_format_time:
+                       case OBJ_pid_environ:
+                       case OBJ_pid_chroot:
+                       case OBJ_pid_cmdline:
+                       case OBJ_pid_cwd:
+                       case OBJ_pid_environ_list:
+                       case OBJ_pid_exe:
+                       case OBJ_pid_nice:
+                       case OBJ_pid_openfiles:
+                       case OBJ_pid_parent:
+                       case OBJ_pid_priority:
+                       case OBJ_pid_state:
+                       case OBJ_pid_state_short:
+                       case OBJ_pid_stderr:
+                       case OBJ_pid_stdin:
+                       case OBJ_pid_stdout:
+                       case OBJ_pid_threads:
+                       case OBJ_pid_thread_list:
+                       case OBJ_pid_time_kernelmode:
+                       case OBJ_pid_time_usermode:
+                       case OBJ_pid_time:
+                       case OBJ_pid_uid:
+                       case OBJ_pid_euid:
+                       case OBJ_pid_suid:
+                       case OBJ_pid_fsuid:
+                       case OBJ_pid_gid:
+                       case OBJ_pid_egid:
+                       case OBJ_pid_sgid:
+                       case OBJ_pid_fsgid:
+                       case OBJ_pid_read:
+                       case OBJ_pid_vmpeak:
+                       case OBJ_pid_vmsize:
+                       case OBJ_pid_vmlck:
+                       case OBJ_pid_vmhwm:
+                       case OBJ_pid_vmrss:
+                       case OBJ_pid_vmdata:
+                       case OBJ_pid_vmstk:
+                       case OBJ_pid_vmexe:
+                       case OBJ_pid_vmlib:
+                       case OBJ_pid_vmpte:
+                       case OBJ_pid_write:
+                       case OBJ_gid_name:
+                               if(obj->sub) {
+                                       free_text_objects(obj->sub, 1);
+                                       free(obj->sub);
+                               }
+                               break;
+                       case OBJ_uid_name:
+                               if(obj->sub) {
+                                       free_text_objects(obj->sub, 1);
+                                       free(obj->sub);
+                               }
+                               break;
                        case OBJ_read_tcp:
                                free_read_tcp(obj);
                                break;
@@ -1290,8 +1490,8 @@ void free_text_objects(struct text_object *root, int internal)
                                break;
                        case OBJ_exec:
                        case OBJ_execbar:
-#ifdef X11
                        case OBJ_execgauge:
+#ifdef X11
                        case OBJ_execgraph:
 #endif
                        case OBJ_execp:
@@ -1431,8 +1631,8 @@ void free_text_objects(struct text_object *root, int internal)
                        case OBJ_lua_bar:
 #ifdef X11
                        case OBJ_lua_graph:
-                       case OBJ_lua_gauge:
 #endif /* X11 */
+                       case OBJ_lua_gauge:
                                free(data.s);
                                break;
 #endif /* HAVE_LUA */
@@ -1455,13 +1655,14 @@ void free_text_objects(struct text_object *root, int internal)
                        case OBJ_texeci:
 #ifdef X11
                        case OBJ_execigraph:
-                       case OBJ_execigauge:
 #endif /* X11 */
+                       case OBJ_execigauge:
                                free_execi(obj);
                                break;
                        case OBJ_nameserver:
                                free_dns_data();
                                break;
+#ifdef __linux__
                        case OBJ_top:
                        case OBJ_top_mem:
                        case OBJ_top_time:
@@ -1470,6 +1671,7 @@ void free_text_objects(struct text_object *root, int internal)
 #endif
                                free_top(obj, internal);
                                break;
+#endif /* __linux__ */
 #ifdef HDDTEMP
                        case OBJ_hddtemp:
                                if (data.s) {
@@ -1502,6 +1704,15 @@ void free_text_objects(struct text_object *root, int internal)
                                        info.users.times = 0;
                                }
                                break;
+                       case OBJ_user_time:
+                               if (info.users.ctime) {
+                                       free(info.users.ctime);
+                                       info.users.ctime = 0;
+                               }
+                               if (data.s) {
+                                       free(data.s);
+                               }
+                               break;
 #ifdef IBM
                        case OBJ_smapi:
                        case OBJ_smapi_bat_perc:
@@ -1580,8 +1791,8 @@ void free_text_objects(struct text_object *root, int internal)
                        case OBJ_apcupsd_loadbar:
 #ifdef X11
                        case OBJ_apcupsd_loadgraph:
-                       case OBJ_apcupsd_loadgauge:
 #endif /* X11 */
+                       case OBJ_apcupsd_loadgauge:
                        case OBJ_apcupsd_charge:
                        case OBJ_apcupsd_timeleft:
                        case OBJ_apcupsd_temp:
@@ -1608,6 +1819,8 @@ void free_text_objects(struct text_object *root, int internal)
                                break;
 #endif /* X11 */
                }
+               if(obj->special_data)
+                       free(obj->special_data);
                free(obj);
        }
 #undef data