Don't pass mouse clicks when window is desktop type.
[monky] / src / conky.c
index 3e82ac5..8668d6d 100644 (file)
@@ -1,4 +1,6 @@
-/* Conky, a system monitor, based on torsmo
+/* -*- 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
  *
@@ -23,6 +25,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
+ * vim: ts=4 sw=4 noet ai cindent syntax=c
+ *
  */
 
 #include "config.h"
 #include <netdb.h>
 #include <fcntl.h>
 #include <getopt.h>
+#ifdef NCURSES
+#include <ncurses.h>
+#endif
+#ifdef XOAP
+#include <libxml/parser.h>
+#endif /* XOAP */
 
 /* local headers */
 #include "algebra.h"
@@ -147,7 +157,10 @@ enum x_initialiser_state x_initialised = NO;
 static volatile int g_signal_pending;
 /* Update interval */
 double update_interval;
+double update_interval_old;
+double update_interval_bat;
 void *global_cpu = NULL;
+pid_t childpid = 0;
 
 int argc_copy;
 char** argv_copy;
@@ -216,7 +229,7 @@ static void print_version(void)
                   "  * RSS\n"
 #endif /* RSS */
 #ifdef WEATHER
-                  "  * Weather (NOAA)\n"
+                  "  * Weather (METAR)\n"
 #ifdef XOAP
                   "  * Weather (XOAP)\n"
 #endif /* XOAP */
@@ -260,7 +273,7 @@ static void print_version(void)
 #endif /* HAVE_LUA */
        );
 
-       exit(0);
+       exit(EXIT_SUCCESS);
 }
 
 static const char *suffixes[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "" };
@@ -325,11 +338,6 @@ static int cpu_avg_samples, net_avg_samples, diskio_avg_samples;
 char *overwrite_file = NULL; FILE *overwrite_fpointer = NULL;
 char *append_file = NULL; FILE *append_fpointer = NULL;
 
-/* xoap suffix for weather from weather.com */
-#ifdef WEATHER
-static char *xoap = NULL;
-#endif /* WEATHER */
-
 #ifdef X11
 
 static int show_graph_scale;
@@ -451,7 +459,7 @@ int check_contains(char *f, char *s)
                }
                fclose(where);
        } else {
-               ERR("Could not open the file");
+               NORM_ERR("Could not open the file");
        }
        return ret;
 }
@@ -642,16 +650,71 @@ static void human_readable(long long num, char *buf, int size)
 /* global object list root element */
 static struct text_object global_root_object;
 
+//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
+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);
+               }
+               dup(childend);  //by dupping childend, the returned fd will have close-on-exec turned off
+               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);
+}
+
 static inline void read_exec(const char *data, char *buf, const int size)
 {
-       FILE *fp = popen(data, "r");
-       int length = fread(buf, 1, size, fp);
+       FILE *fp;
 
-       pclose(fp);
-       buf[length] = '\0';
-       if (length > 0 && buf[length - 1] == '\n') {
-               buf[length - 1] = '\0';
+       alarm(update_interval);
+       fp = pid_popen(data, "r", &childpid);
+       if(fp) {
+               int length;
+
+               length = fread(buf, 1, size, fp);
+               pclose(fp);
+               buf[length] = '\0';
+               if (length > 0 && buf[length - 1] == '\n') {
+                       buf[length - 1] = '\0';
+               }
+       } else {
+               buf[0] = '\0';
        }
+       alarm(0);
 }
 
 void *threaded_exec(void *) __attribute__((noreturn));
@@ -745,7 +808,7 @@ static void free_text_objects(struct text_object *root, int internal)
                        case OBJ_unreplied_mails:
                        case OBJ_draft_mails:
                        case OBJ_trashed_mails:
-                               free(data.local_mail.box);
+                               free(data.local_mail.mbox);
                                break;
                        case OBJ_imap_unseen:
                                if (!obj->char_b) {
@@ -778,9 +841,12 @@ static void free_text_objects(struct text_object *root, int internal)
                                free(data.ifblock.s);
                                free(data.ifblock.str);
                                break;
+                       case OBJ_head:
                        case OBJ_tail:
-                               free(data.tail.logfile);
-                               free(data.tail.buffer);
+                               free(data.headtail.logfile);
+                               if(data.headtail.buffer) {
+                                       free(data.headtail.buffer);
+                               }
                                break;
                        case OBJ_text:
                        case OBJ_font:
@@ -929,6 +995,12 @@ static void free_text_objects(struct text_object *root, int internal)
                                free(data.weather.data_type);
                                break;
 #endif
+#ifdef XOAP
+                       case OBJ_weather_forecast:
+                               free(data.weather_forecast.uri);
+                               free(data.weather_forecast.data_type);
+                               break;
+#endif
 #ifdef HAVE_LUA
                        case OBJ_lua:
                        case OBJ_lua_parse:
@@ -1066,10 +1138,13 @@ static void free_text_objects(struct text_object *root, int internal)
                                free_moc();
                                break;
 #endif /* MOC */
+                       case OBJ_include:
                        case OBJ_blink:
                        case OBJ_to_bytes:
-                               free_text_objects(obj->sub, 1);
-                               free(obj->sub);
+                               if(obj->sub) {
+                                       free_text_objects(obj->sub, 1);
+                                       free(obj->sub);
+                               }
                                break;
                        case OBJ_scroll:
                                free(data.scroll.text);
@@ -1194,15 +1269,15 @@ static int parse_top_args(const char *s, const char *arg, struct text_object *ob
 #endif
        } else {
 #ifdef IOSTATS
-               ERR("Must be top, top_mem, top_time or top_io");
+               NORM_ERR("Must be top, top_mem, top_time or top_io");
 #else
-               ERR("Must be top, top_mem or top_time");
+               NORM_ERR("Must be top, top_mem or top_time");
 #endif
                return 0;
        }
 
        if (!arg) {
-               ERR("top needs arguments");
+               NORM_ERR("top needs arguments");
                return 0;
        }
 
@@ -1230,23 +1305,23 @@ static int parse_top_args(const char *s, const char *arg, struct text_object *ob
                        obj->data.top.type = TOP_IO_PERC;
 #endif
                } else {
-                       ERR("invalid type arg for top");
+                       NORM_ERR("invalid type arg for top");
 #ifdef IOSTATS
-                       ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize, "
+                       NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize, "
                                        "io_read, io_write, io_perc");
 #else
-                       ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize");
+                       NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize");
 #endif
                        return 0;
                }
                if (n < 1 || n > 10) {
-                       ERR("invalid num arg for top. Must be between 1 and 10.");
+                       NORM_ERR("invalid num arg for top. Must be between 1 and 10.");
                        return 0;
                } else {
                        obj->data.top.num = n - 1;
                }
        } else {
-               ERR("invalid argument count for top");
+               NORM_ERR("invalid argument count for top");
                return 0;
        }
        return 1;
@@ -1254,6 +1329,53 @@ static int parse_top_args(const char *s, const char *arg, struct text_object *ob
 
 long current_text_color;
 
+struct conftree {
+       char* string;
+       struct conftree* horz_next;
+       struct conftree* vert_next;
+       struct conftree* back;
+};
+
+//adds newstring to to the tree unless you can already see it when travelling back.
+//if it's possible to attach it then it returns a pointer to the leaf, else it returns NULL
+struct conftree* conftree_add(struct conftree* previous, const char* newstring) {
+       struct conftree* node;
+       struct conftree* node2;
+
+       for(node = previous; node != NULL; node = node->back) {
+               if(strcmp(node->string, newstring) == 0) {
+                       return NULL;
+               }
+       }
+       node = malloc(sizeof(struct conftree));
+       if (previous != NULL) {
+               if(previous->vert_next == NULL) {
+                       previous->vert_next = node;
+               } else {
+                       for(node2 = previous->vert_next; node2->horz_next != NULL; node2 = node2->horz_next ) { }
+                       node2->horz_next = node;
+               }
+       }
+       node->string = strdup(newstring);
+       node->horz_next = NULL;
+       node->vert_next = NULL;
+       node->back = previous;
+       return node;
+}
+
+void conftree_empty(struct conftree* tree) {
+       if(tree) {
+               conftree_empty(tree->horz_next);
+               conftree_empty(tree->vert_next);
+               free(tree->string);
+               free(tree);
+       }
+}
+
+struct conftree *currentconffile;
+
+char load_config_file(const char *);
+
 /* construct_text_object() creates a new text_object */
 static struct text_object *construct_text_object(const char *s,
                const char *arg, long line, void **ifblock_opaque, void *free_at_crash)
@@ -1293,7 +1415,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0
                                || (unsigned int) atoi(&arg[0]) > info.cpu_count) {
                        obj->data.cpu_index = 1;
-                       /* ERR("freq: Invalid CPU number or you don't have that many CPUs! "
+                       /* NORM_ERR("freq: Invalid CPU number or you don't have that many CPUs! "
                                "Displaying the clock for CPU 1."); */
                } else {
                        obj->data.cpu_index = atoi(&arg[0]);
@@ -1304,7 +1426,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0
                                || (unsigned int) atoi(&arg[0]) > info.cpu_count) {
                        obj->data.cpu_index = 1;
-                       /* ERR("freq_g: Invalid CPU number or you don't have that many "
+                       /* NORM_ERR("freq_g: Invalid CPU number or you don't have that many "
                                "CPUs! Displaying the clock for CPU 1."); */
                } else {
                        obj->data.cpu_index = atoi(&arg[0]);
@@ -1332,7 +1454,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0
                                || (unsigned int) atoi(&arg[0]) > info.cpu_count) {
                        obj->data.cpu_index = 1;
-                       /* ERR("voltage_mv: Invalid CPU number or you don't have that many "
+                       /* NORM_ERR("voltage_mv: Invalid CPU number or you don't have that many "
                                "CPUs! Displaying voltage for CPU 1."); */
                } else {
                        obj->data.cpu_index = atoi(&arg[0]);
@@ -1343,7 +1465,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || !isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) == 0
                                || (unsigned int) atoi(&arg[0]) > info.cpu_count) {
                        obj->data.cpu_index = 1;
-                       /* ERR("voltage_v: Invalid CPU number or you don't have that many "
+                       /* NORM_ERR("voltage_v: Invalid CPU number or you don't have that many "
                                "CPUs! Displaying voltage for CPU 1."); */
                } else {
                        obj->data.cpu_index = atoi(&arg[0]);
@@ -1504,7 +1626,7 @@ static struct text_object *construct_text_object(const char *s,
                }
                if (!isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) >= 8) {
                        obj->data.sensor = 0;
-                       ERR("Invalid temperature sensor! Sensor number must be 0 to 7. "
+                       NORM_ERR("Invalid temperature sensor! Sensor number must be 0 to 7. "
                                "Using 0 (CPU temp sensor).");
                }
                obj->data.sensor = atoi(&arg[0]);
@@ -1530,7 +1652,7 @@ static struct text_object *construct_text_object(const char *s,
                } else if (arg && strcmp(arg, "time") == EQUAL) {
                        obj->data.i = PB_BATT_TIME;
                } else {
-                       ERR("pb_battery: needs one argument: status, percent or time");
+                       NORM_ERR("pb_battery: needs one argument: status, percent or time");
                        free(obj);
                        return NULL;
                }
@@ -1539,7 +1661,7 @@ static struct text_object *construct_text_object(const char *s,
 #if (defined(__FreeBSD__) || defined(__linux__))
        END OBJ_IF(if_up, 0)
                if (!arg) {
-                       ERR("if_up needs an argument");
+                       NORM_ERR("if_up needs an argument");
                        obj->data.ifblock.s = 0;
                } else {
                        obj->data.ifblock.s = strndup(arg, text_buffer_size);
@@ -1553,7 +1675,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!isdigit(arg[0]) || atoi(&arg[0]) < 0
                                || atoi(&arg[0]) > OBSD_MAX_SENSORS - 1) {
                        obj->data.sensor = 0;
-                       ERR("Invalid temperature sensor number!");
+                       NORM_ERR("Invalid temperature sensor number!");
                }
                obj->data.sensor = atoi(&arg[0]);
        END OBJ(obsd_sensors_fan, 0)
@@ -1564,7 +1686,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!isdigit(arg[0]) || atoi(&arg[0]) < 0
                                || atoi(&arg[0]) > OBSD_MAX_SENSORS - 1) {
                        obj->data.sensor = 0;
-                       ERR("Invalid fan sensor number!");
+                       NORM_ERR("Invalid fan sensor number!");
                }
                obj->data.sensor = atoi(&arg[0]);
        END OBJ(obsd_sensors_volt, 0)
@@ -1575,7 +1697,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!isdigit(arg[0]) || atoi(&arg[0]) < 0
                                || atoi(&arg[0]) > OBSD_MAX_SENSORS - 1) {
                        obj->data.sensor = 0;
-                       ERR("Invalid voltage sensor number!");
+                       NORM_ERR("Invalid voltage sensor number!");
                }
                obj->data.sensor = atoi(&arg[0]);
        END OBJ(obsd_vendor, 0)
@@ -1667,6 +1789,30 @@ static struct text_object *construct_text_object(const char *s,
                        current_text_color = obj->data.l;
                }
 #endif /* X11 */
+#ifdef NCURSES
+               if (output_methods & TO_NCURSES) {
+                       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;
+                               }
+                       }
+                       current_text_color = obj->data.l;
+                       init_pair(obj->data.l, obj->data.l, COLOR_BLACK);
+               }
+#endif /* NCURSES */
        END OBJ(color0, 0)
                obj->data.l = color0;
                current_text_color = obj->data.l;
@@ -1742,7 +1888,6 @@ static struct text_object *construct_text_object(const char *s,
                obj->data.s = strndup(arg ? arg : "", text_buffer_size);
        END OBJ(image, 0)
                obj->data.s = strndup(arg ? arg : "", text_buffer_size);
-#ifdef HAVE_POPEN
        END OBJ(exec, 0)
                obj->data.s = strndup(arg ? arg : "", text_buffer_size);
        END OBJ(execp, 0)
@@ -1765,7 +1910,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
 
-                       ERR("${execibar <interval> command}");
+                       NORM_ERR("${execibar <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
                        obj->data.s = strndup(buf, text_buffer_size);
@@ -1780,7 +1925,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
 
-                       ERR("${execigraph <interval> command}");
+                       NORM_ERR("${execigraph <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
                        obj->data.s = strndup(buf, text_buffer_size);
@@ -1794,7 +1939,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
 
-                       ERR("${execigauge <interval> command}");
+                       NORM_ERR("${execigauge <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
                        obj->data.s = strndup(buf, text_buffer_size);
@@ -1808,7 +1953,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
 
-                       ERR("${execi <interval> command}");
+                       NORM_ERR("${execi <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
                        obj->data.s = strndup(buf, text_buffer_size);
@@ -1822,7 +1967,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
 
-                       ERR("${execi <interval> command}");
+                       NORM_ERR("${execi <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
                        obj->data.s = strndup(buf, text_buffer_size);
@@ -1836,7 +1981,7 @@ static struct text_object *construct_text_object(const char *s,
                        if (!arg || sscanf(arg, "%f %n", &obj->data.texeci.interval, &n) <= 0) {
                                char buf[256];
 
-                               ERR("${texeci <interval> command}");
+                               NORM_ERR("${texeci <interval> command}");
                                obj->type = OBJ_text;
                                snprintf(buf, 256, "${%s}", s);
                                obj->data.s = strndup(buf, text_buffer_size);
@@ -1845,17 +1990,16 @@ static struct text_object *construct_text_object(const char *s,
                                obj->data.texeci.buffer = malloc(text_buffer_size);
                        }
                        obj->data.texeci.p_timed_thread = NULL;
-       END     OBJ(pre_exec, 0)
+       END OBJ(pre_exec, 0)
                obj->type = OBJ_text;
-       if (arg) {
-               char buf[2048];
+               if (arg) {
+                       char buf[2048];
 
-               read_exec(arg, buf, sizeof(buf));
-               obj->data.s = strndup(buf, text_buffer_size);
-       } else {
-               obj->data.s = strndup("", text_buffer_size);
-       }
-#endif
+                       read_exec(arg, buf, sizeof(buf));
+                       obj->data.s = strndup(buf, text_buffer_size);
+               } else {
+                       obj->data.s = strndup("", text_buffer_size);
+               }
        END OBJ(fs_bar, INFO_FS)
                SIZE_DEFAULTS(bar);
                arg = scan_bar(arg, &obj->data.fsbar.w, &obj->data.fsbar.h);
@@ -1926,7 +2070,7 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(goto, 0)
 
                if (!arg) {
-                       ERR("goto needs arguments");
+                       NORM_ERR("goto needs arguments");
                        obj->type = OBJ_text;
                        obj->data.s = strndup("${goto}", text_buffer_size);
                        return NULL;
@@ -1955,7 +2099,7 @@ static struct text_object *construct_text_object(const char *s,
                int n, found = 0;
 
                if (!arg) {
-                       ERR("i2c needs arguments");
+                       NORM_ERR("i2c needs arguments");
                        obj->type = OBJ_text;
                        // obj->data.s = strndup("${i2c}", text_buffer_size);
                        return NULL;
@@ -1972,7 +2116,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!found && sscanf(arg, "%63s %d", buf2, &n) == 2) found = 1; else if (!found) HWMON_RESET();
 
                if (!found) {
-                       ERR("i2c failed to parse arguments");
+                       NORM_ERR("i2c failed to parse arguments");
                        obj->type = OBJ_text;
                        return NULL;
                }
@@ -1989,7 +2133,7 @@ static struct text_object *construct_text_object(const char *s,
                int n, found = 0;
 
                if (!arg) {
-                       ERR("platform needs arguments");
+                       NORM_ERR("platform needs arguments");
                        obj->type = OBJ_text;
                        return NULL;
                }
@@ -2000,11 +2144,11 @@ static struct text_object *construct_text_object(const char *s,
                if (!found && sscanf(arg, "%63s %d", buf2, &n) == 2) found = 1; else if (!found) HWMON_RESET();
 
                if (!found) {
-                       ERR("platform failed to parse arguments");
+                       NORM_ERR("platform failed to parse arguments");
                        obj->type = OBJ_text;
                        return NULL;
                }
-               DBGP("parsed platform args: '%s' '%s' %d %f %f\n", buf1, buf2, n, factor, offset);
+               DBGP("parsed platform args: '%s' '%s' %d %f %f", buf1, buf2, n, factor, offset);
                obj->data.sysfs.fd = open_platform_sensor((*buf1) ? buf1 : 0, buf2, n,
                                &obj->data.sysfs.arg, obj->data.sysfs.devtype);
                strncpy(obj->data.sysfs.type, buf2, 63);
@@ -2017,7 +2161,7 @@ static struct text_object *construct_text_object(const char *s,
                int n, found = 0;
 
                if (!arg) {
-                       ERR("hwmon needs argumanets");
+                       NORM_ERR("hwmon needs argumanets");
                        obj->type = OBJ_text;
                        return NULL;
                }
@@ -2030,7 +2174,7 @@ static struct text_object *construct_text_object(const char *s,
 #undef HWMON_RESET
 
                if (!found) {
-                       ERR("hwmon failed to parse arguments");
+                       NORM_ERR("hwmon failed to parse arguments");
                        obj->type = OBJ_text;
                        return NULL;
                }
@@ -2072,15 +2216,9 @@ static struct text_object *construct_text_object(const char *s,
                }
 #endif /* __linux__ */
        END OBJ(tail, 0)
-               if (init_tail_object(obj, arg)) {
-                       obj->type = OBJ_text;
-                       obj->data.s = strndup("${tail}", text_buffer_size);
-               }
+               init_tailhead("tail", arg, obj, free_at_crash);
        END OBJ(head, 0)
-               if (init_head_object(obj, arg)) {
-                       obj->type = OBJ_text;
-                       obj->data.s = strndup("${head}", text_buffer_size);
-               }
+               init_tailhead("head", arg, obj, free_at_crash);
        END OBJ(lines, 0)
                if (arg) {
                        obj->data.s = strndup(arg, text_buffer_size);
@@ -2113,7 +2251,7 @@ static struct text_object *construct_text_object(const char *s,
                obj->data.loadavg[2] = (r >= 3) ? (unsigned char) c : 0;
        END OBJ_IF(if_empty, 0)
                if (!arg) {
-                       ERR("if_empty needs an argument");
+                       NORM_ERR("if_empty needs an argument");
                        obj->data.ifblock.s = 0;
                } else {
                        obj->data.ifblock.s = strndup(arg, text_buffer_size);
@@ -2123,7 +2261,7 @@ static struct text_object *construct_text_object(const char *s,
                }
        END OBJ_IF(if_match, 0)
                if (!arg) {
-                       ERR("if_match needs arguments");
+                       NORM_ERR("if_match needs arguments");
                        obj->data.ifblock.s = 0;
                } else {
                        obj->data.ifblock.s = strndup(arg, text_buffer_size);
@@ -2133,7 +2271,7 @@ static struct text_object *construct_text_object(const char *s,
                }
        END OBJ_IF(if_existing, 0)
                if (!arg) {
-                       ERR("if_existing needs an argument or two");
+                       NORM_ERR("if_existing needs an argument or two");
                        obj->data.ifblock.s = NULL;
                        obj->data.ifblock.str = NULL;
                } else {
@@ -2151,7 +2289,7 @@ static struct text_object *construct_text_object(const char *s,
                DBGP("if_existing: '%s' '%s'", obj->data.ifblock.s, obj->data.ifblock.str);
        END OBJ_IF(if_mounted, 0)
                if (!arg) {
-                       ERR("if_mounted needs an argument");
+                       NORM_ERR("if_mounted needs an argument");
                        obj->data.ifblock.s = 0;
                } else {
                        obj->data.ifblock.s = strndup(arg, text_buffer_size);
@@ -2169,14 +2307,14 @@ static struct text_object *construct_text_object(const char *s,
                        obj->data.ifblock.s = strndup(buf, text_buffer_size);
 #endif
                } else {
-                       ERR("if_running needs an argument");
+                       NORM_ERR("if_running needs an argument");
                        obj->data.ifblock.s = 0;
                }
        END OBJ(kernel, 0)
        END OBJ(machine, 0)
        END OBJ(mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
@@ -2185,203 +2323,203 @@ static struct text_object *construct_text_object(const char *s,
                           is a copy of the former if undefined
                           but the latter should take precedence
                           if defined */
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(new_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(seen_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(unseen_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(flagged_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(unflagged_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(forwarded_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(unforwarded_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(replied_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(unreplied_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(draft_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(trashed_mails, 0)
                float n1;
-               char box[256], dst[256];
+               char mbox[256], dst[256];
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, current_mail_spool, sizeof(box));
+                       strncpy(mbox, current_mail_spool, sizeof(mbox));
                } else {
-                       if (sscanf(arg, "%s %f", box, &n1) != 2) {
+                       if (sscanf(arg, "%s %f", mbox, &n1) != 2) {
                                n1 = 9.5;
-                               strncpy(box, arg, sizeof(box));
+                               strncpy(mbox, arg, sizeof(mbox));
                        }
                }
 
-               variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strndup(dst, text_buffer_size);
+               variable_substitute(mbox, dst, sizeof(dst));
+               obj->data.local_mail.mbox = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(mboxscan, 0)
                obj->data.mboxscan.args = (char *) malloc(text_buffer_size);
@@ -2512,7 +2650,7 @@ static struct text_object *construct_text_object(const char *s,
 
                                new_iconv = iconv_open(iconv_to, iconv_from);
                                if (new_iconv == (iconv_t) (-1)) {
-                                       ERR("Can't convert from %s to %s.", iconv_from, iconv_to);
+                                       NORM_ERR("Can't convert from %s to %s.", iconv_from, iconv_to);
                                } else {
                                        obj->a = register_iconv(&new_iconv);
                                        iconv_converting = 1;
@@ -2641,10 +2779,10 @@ static struct text_object *construct_text_object(const char *s,
                if (arg)
                        obj->data.s = strndup(arg, text_buffer_size);
                else
-                       ERR("smapi needs an argument");
+                       NORM_ERR("smapi needs an argument");
        END OBJ_IF(if_smapi_bat_installed, 0)
                if (!arg) {
-                       ERR("if_smapi_bat_installed needs an argument");
+                       NORM_ERR("if_smapi_bat_installed needs an argument");
                        obj->data.ifblock.s = 0;
                } else
                        obj->data.ifblock.s = strndup(arg, text_buffer_size);
@@ -2652,31 +2790,31 @@ static struct text_object *construct_text_object(const char *s,
                if (arg)
                        obj->data.s = strndup(arg, text_buffer_size);
                else
-                       ERR("smapi_bat_perc needs an argument");
+                       NORM_ERR("smapi_bat_perc needs an argument");
        END OBJ(smapi_bat_temp, 0)
                if (arg)
                        obj->data.s = strndup(arg, text_buffer_size);
                else
-                       ERR("smapi_bat_temp needs an argument");
+                       NORM_ERR("smapi_bat_temp needs an argument");
        END OBJ(smapi_bat_power, 0)
                if (arg)
                        obj->data.s = strndup(arg, text_buffer_size);
                else
-                       ERR("smapi_bat_power needs an argument");
+                       NORM_ERR("smapi_bat_power needs an argument");
 #ifdef X11
        END OBJ(smapi_bat_bar, 0)
                SIZE_DEFAULTS(bar);
                if(arg) {
                        int cnt;
                        if(sscanf(arg, "%i %n", &obj->data.i, &cnt) <= 0) {
-                               ERR("first argument to smapi_bat_bar must be an integer value");
+                               NORM_ERR("first argument to smapi_bat_bar must be an integer value");
                                obj->data.i = -1;
                        } else {
                                obj->b = 4;
                                arg = scan_bar(arg + cnt, &obj->a, &obj->b);
                        }
                } else
-                       ERR("smapi_bat_bar needs an argument");
+                       NORM_ERR("smapi_bat_bar needs an argument");
 #endif /* X11 */
 #endif /* IBM */
 #ifdef MPD
@@ -2687,7 +2825,7 @@ static struct text_object *construct_text_object(const char *s,
                        if (i > 0) \
                                obj->data.i = i + 1; \
                        else \
-                               ERR(#name ": invalid length argument"); \
+                               NORM_ERR(#name ": invalid length argument"); \
                }
        END OBJ(mpd_artist, INFO_MPD)
                mpd_set_maxlen(mpd_artist);
@@ -2829,7 +2967,7 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(curl, 0)
                if (arg) {
                        int argc;
-                       float interval;
+                       float interval = 0;
                        char *uri = (char *) malloc(128 * sizeof(char));
 
                        argc = sscanf(arg, "%127s %f", uri, &interval);
@@ -2837,7 +2975,7 @@ static struct text_object *construct_text_object(const char *s,
                                obj->data.curl.uri = uri;
                                obj->data.curl.interval = interval > 0 ? interval * 60 : 15*60;
                        } else {
-                               ERR("wrong number of arguments for $curl");
+                               NORM_ERR("wrong number of arguments for $curl");
                        }
                } else {
                        CRIT_ERR(obj, free_at_crash, "curl needs arguments: <uri> <interval in minutes>");
@@ -2846,22 +2984,22 @@ static struct text_object *construct_text_object(const char *s,
 #ifdef RSS
        END OBJ(rss, 0)
                if (arg) {
-                       float interval;
-                       int argc, act_par;
+                       float interval = 0;
+                       int argc, act_par = 0;
                        unsigned int nrspaces = 0;
                        char *uri = (char *) malloc(128 * sizeof(char));
                        char *action = (char *) malloc(64 * sizeof(char));
 
                        argc = sscanf(arg, "%127s %f %63s %d %u", uri, &interval, action,
                                        &act_par, &nrspaces);
-                       if (argc == 5) {
+                       if (argc >= 3) {
                                obj->data.rss.uri = uri;
                                obj->data.rss.interval = interval > 0 ? interval * 60 : 15*60;
                                obj->data.rss.action = action;
                                obj->data.rss.act_par = act_par;
                                obj->data.rss.nrspaces = nrspaces;
                        } else {
-                               ERR("wrong number of arguments for $rss");
+                               NORM_ERR("wrong number of arguments for $rss");
                        }
                } else {
                        CRIT_ERR(obj, free_at_crash, "rss needs arguments: <uri> <interval in minutes> <action> "
@@ -2872,35 +3010,18 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(weather, 0)
                if (arg) {
                        int argc;
-                       float interval;
+                       float interval = 0;
                        char *locID = (char *) malloc(9 * sizeof(char));
                        char *uri = (char *) malloc(128 * sizeof(char));
                        char *data_type = (char *) malloc(32 * sizeof(char));
-                       char *tmp_p;
 
                        argc = sscanf(arg, "%119s %8s %31s %f", uri, locID, data_type, &interval);
 
                        if (argc >= 3) {
-                               /* locID MUST BE upper-case */
-                               tmp_p = locID;
-                               while (*tmp_p) {
-                                       *tmp_p = toupper(*tmp_p);
-                                       tmp_p++;
-                               }
-
-                               /* Construct complete uri */
-                               if (strstr(uri, "xoap.weather.com")) {
-                                       if(xoap != NULL) {
-                                               strcat(uri, locID);
-                                               strcat(uri, xoap);
-                                       } else {
-                                               free(uri);
-                                               uri = NULL;
-                                       }
-                               } else if (strstr(uri, "weather.noaa.gov")) {
-                                       strcat(uri, locID);
-                                       strcat(uri, ".TXT");
-                               } else  if (!strstr(uri, "localhost") && !strstr(uri, "127.0.0.1")) {
+                               if (process_weather_uri(uri, locID, 0)) {
+                                       free(data_type);
+                                       free(uri);
+                                       free(locID);
                                        CRIT_ERR(obj, free_at_crash, \
                                                        "could not recognize the weather uri");
                                }
@@ -2920,12 +3041,66 @@ static struct text_object *construct_text_object(const char *s,
                                DBGP("weather: fetching %s from %s every %d seconds", \
                                                data_type, uri, obj->data.weather.interval);
                        } else {
-                               ERR("wrong number of arguments for $weather");
+                               free(data_type);
+                               free(uri);
+                               free(locID);
+                               CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather");
                        }
                } else {
                        CRIT_ERR(obj, free_at_crash, "weather needs arguments: <uri> <locID> <data_type> [interval in minutes]");
                }
 #endif
+#ifdef XOAP
+       END OBJ(weather_forecast, 0)
+               if (arg) {
+                       int argc;
+                       unsigned int day;
+                       float interval = 0;
+                       char *locID = (char *) malloc(9 * sizeof(char));
+                       char *uri = (char *) malloc(128 * sizeof(char));
+                       char *data_type = (char *) malloc(32 * sizeof(char));
+
+                       argc = sscanf(arg, "%119s %8s %1u %31s %f", uri, locID, &day, data_type, &interval);
+
+                       if (argc >= 4) {
+                               if (process_weather_uri(uri, locID, 1)) {
+                                       free(data_type);
+                                       free(uri);
+                                       free(locID);
+                                       CRIT_ERR(obj, free_at_crash, \
+                                                       "could not recognize the weather forecast uri");
+                               }
+
+                               obj->data.weather_forecast.uri = uri;
+                               obj->data.weather_forecast.data_type = data_type;
+
+                               /* Limit the day between 0 (today) and FORECAST_DAYS */
+                               if (day >= FORECAST_DAYS) {
+                                       day = FORECAST_DAYS-1;
+                               }
+                               obj->data.weather_forecast.day = day;
+
+                               /* Limit the data retrieval interval to 3 hours and an half */
+                               if (interval < 210) {
+                                       interval = 210;
+                               }
+
+                               /* Convert to seconds */
+                               obj->data.weather_forecast.interval = interval * 60;
+                               free(locID);
+
+                               DBGP("weather_forecast: fetching %s for day %d from %s every %d seconds", \
+                                        data_type, day, uri, obj->data.weather_forecast.interval);
+                       } else {
+                               free(data_type);
+                               free(uri);
+                               free(locID);
+                               CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather_forecast");
+                       }
+               } else {
+                       CRIT_ERR(obj, free_at_crash, "weather_forecast needs arguments: <uri> <locID> <day> <data_type> [interval in minutes]");
+               }
+#endif
 #ifdef HAVE_LUA
        END OBJ(lua, 0)
                if (arg) {
@@ -2984,7 +3159,7 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(hddtemp, 0)
                if (scan_hddtemp(arg, &obj->data.hddtemp.dev,
                                 &obj->data.hddtemp.addr, &obj->data.hddtemp.port)) {
-                       ERR("hddtemp needs arguments");
+                       NORM_ERR("hddtemp needs arguments");
                        obj->type = OBJ_text;
                        obj->data.s = strndup("${hddtemp}", text_buffer_size);
                        obj->data.hddtemp.update_time = 0;
@@ -3001,6 +3176,24 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(entropy_bar, INFO_ENTROPY)
                SIZE_DEFAULTS(bar);
                scan_bar(arg, &obj->a, &obj->b);
+       END OBJ(include, 0)
+               if(arg) {
+                       struct conftree *leaf = conftree_add(currentconffile, arg);
+                       if(leaf) {
+                               if( load_config_file(arg) == TRUE) {
+                                       obj->sub = malloc(sizeof(struct text_object));
+                                       currentconffile = leaf;
+                                       extract_variable_text_internal(obj->sub, global_text);
+                                       currentconffile = leaf->back;
+                               } else {
+                                       NORM_ERR("Can't load configfile '%s'.", arg);
+                               }
+                       } else {
+                               NORM_ERR("You are trying to load '%s' recursively, I'm only going to load it once to prevent an infinite loop.", arg);
+                       }
+               } else {
+                       CRIT_ERR(obj, free_at_crash, "include needs a argument");
+               }
        END OBJ(blink, 0)
                if(arg) {
                        obj->sub = malloc(sizeof(struct text_object));
@@ -3142,7 +3335,7 @@ static struct text_object *construct_text_object(const char *s,
        END {
                char buf[256];
 
-               ERR("unknown variable %s", s);
+               NORM_ERR("unknown variable %s", s);
                obj->type = OBJ_text;
                snprintf(buf, 256, "${%s}", s);
                obj->data.s = strndup(buf, text_buffer_size);
@@ -3340,7 +3533,7 @@ static char *find_and_replace_templates(const char *inbuf)
                        free(tmpl_out);
                        o = outbuf + strlen(outbuf);
                } else {
-                       ERR("failed to handle template '%s' with args '%s'", templ, args);
+                       NORM_ERR("failed to handle template '%s' with args '%s'", templ, args);
                }
        }
        *o = '\0';
@@ -3358,19 +3551,6 @@ static int text_contains_templates(const char *text)
        return 0;
 }
 
-/* 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"
- */
-static void strfold(char *start, int count)
-{
-       char *curplace;
-       for (curplace = start + count; *curplace != 0; curplace++) {
-               *(curplace - count) = *curplace;
-       }
-       *(curplace - count) = 0;
-}
-
 /*
  * - assumes that *string is '#'
  * - removes the part from '#' to the end of line ('\n' or '\0')
@@ -3554,7 +3734,7 @@ static int extract_variable_text_internal(struct text_object *retval, const char
        }
 
        if (!ifblock_stack_empty(&ifblock_opaque)) {
-               ERR("one or more $endif's are missing");
+               NORM_ERR("one or more $endif's are missing");
        }
 
        free(orig_p);
@@ -3580,11 +3760,10 @@ static void extract_variable_text(const char *p)
        extract_variable_text_internal(&global_root_object, p);
 }
 
-void parse_conky_vars(struct text_object *root, char *txt, char *p, struct information *cur)
+void parse_conky_vars(struct text_object *root, const char *txt, char *p, struct information *cur)
 {
        extract_variable_text_internal(root, txt);
        generate_text_internal(p, max_user_text, *root, cur);
-       return;
 }
 
 static inline struct mail_s *ensure_mail_thread(struct text_object *obj,
@@ -3597,12 +3776,12 @@ static inline struct mail_s *ensure_mail_thread(struct text_object *obj,
                                timed_thread_create(thread,
                                                (void *) info.mail, info.mail->interval * 1000000);
                        if (!info.mail->p_timed_thread) {
-                               ERR("Error creating %s timed thread", text);
+                               NORM_ERR("Error creating %s timed thread", text);
                        }
                        timed_thread_register(info.mail->p_timed_thread,
                                        &info.mail->p_timed_thread);
                        if (timed_thread_run(info.mail->p_timed_thread)) {
-                               ERR("Error running %s timed thread", text);
+                               NORM_ERR("Error running %s timed thread", text);
                        }
                }
                return info.mail;
@@ -3614,18 +3793,18 @@ static inline struct mail_s *ensure_mail_thread(struct text_object *obj,
                                                (void *) obj->data.mail,
                                                obj->data.mail->interval * 1000000);
                        if (!obj->data.mail->p_timed_thread) {
-                               ERR("Error creating %s timed thread", text);
+                               NORM_ERR("Error creating %s timed thread", text);
                        }
                        timed_thread_register(obj->data.mail->p_timed_thread,
                                        &obj->data.mail->p_timed_thread);
                        if (timed_thread_run(obj->data.mail->p_timed_thread)) {
-                               ERR("Error running %s timed thread", text);
+                               NORM_ERR("Error running %s timed thread", text);
                        }
                }
                return obj->data.mail;
        } else if (!obj->a) {
                // something is wrong, warn once then stop
-               ERR("There's a problem with your mail settings.  "
+               NORM_ERR("There's a problem with your mail settings.  "
                                "Check that the global mail settings are properly defined"
                                " (line %li).", obj->line);
                obj->a++;
@@ -3724,12 +3903,12 @@ static inline double get_barnum(char *buf)
        }
 
        if (sscanf(buf, "%lf", &barnum) == 0) {
-               ERR("reading exec value failed (perhaps it's not the "
+               NORM_ERR("reading exec value failed (perhaps it's not the "
                                "correct format?)");
                return -1;
        }
        if (barnum > 100.0 || barnum < 0.0) {
-               ERR("your exec value is not between 0 and 100, "
+               NORM_ERR("your exec value is not between 0 and 100, "
                                "therefore it will be ignored");
                return -1;
        }
@@ -3802,7 +3981,7 @@ static void generate_text_internal(char *p, int p_max_size,
 
                switch (obj->type) {
                        default:
-                               ERR("not implemented obj type %d", obj->type);
+                               NORM_ERR("not implemented obj type %d", obj->type);
                        OBJ(read_tcp) {
                                int sock, received;
                                struct sockaddr_in addr;
@@ -3827,13 +4006,13 @@ static void generate_text_internal(char *p, int p_max_size,
                                                        }
                                                        close(sock);
                                                } else {
-                                                       ERR("read_tcp: Couldn't create a connection");
+                                                       NORM_ERR("read_tcp: Couldn't create a connection");
                                                }
                                        }else{
-                                               ERR("read_tcp: Couldn't create a socket");
+                                               NORM_ERR("read_tcp: Couldn't create a socket");
                                        }
                                }else{
-                                       ERR("read_tcp: Problem with resolving the hostname");
+                                       NORM_ERR("read_tcp: Problem with resolving the hostname");
                                }
                        }
 #ifndef __OpenBSD__
@@ -3968,7 +4147,7 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
                        OBJ(cpu) {
                                if (obj->data.cpu_index > info.cpu_count) {
-                                       ERR("obj->data.cpu_index %i info.cpu_count %i",
+                                       NORM_ERR("obj->data.cpu_index %i info.cpu_count %i",
                                                        obj->data.cpu_index, info.cpu_count);
                                        CRIT_ERR(NULL, NULL, "attempting to use more CPUs than you have!");
                                }
@@ -4003,9 +4182,11 @@ static void generate_text_internal(char *p, int p_max_size,
                                new_graph(p, obj->a, obj->b, obj->c, obj->d, cur->loadavg[0],
                                                obj->e, 1, obj->char_a, obj->char_b);
                        }
+#endif /* X11 */
                        OBJ(color) {
                                new_fg(p, obj->data.l);
                        }
+#ifdef X11
                        OBJ(color0) {
                                new_fg(p, color0);
                        }
@@ -4249,7 +4430,6 @@ static void generate_text_internal(char *p, int p_max_size,
                        OBJ(endif) {
                                /* harmless object, just ignore */
                        }
-#ifdef HAVE_POPEN
                        OBJ(addr) {
                                if ((obj->data.net->addr.sa_data[2] & 255) == 0
                                                && (obj->data.net->addr.sa_data[3] & 255) == 0
@@ -4449,7 +4629,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        parse_conky_vars(&subroot, obj->data.execi.buffer, p, tmp_info);
                                } else {
                                        char *output = obj->data.execi.buffer;
-                                       FILE *fp = popen(obj->data.execi.cmd, "r");
+                                       FILE *fp = pid_popen(obj->data.execi.cmd, "r", &childpid);
                                        int length = fread(output, 1, text_buffer_size, fp);
 
                                        pclose(fp);
@@ -4471,14 +4651,14 @@ static void generate_text_internal(char *p, int p_max_size,
                                                timed_thread_create(&threaded_exec,
                                                (void *) obj, obj->data.texeci.interval * 1000000);
                                        if (!obj->data.texeci.p_timed_thread) {
-                                               ERR("Error creating texeci timed thread");
+                                               NORM_ERR("Error creating texeci timed thread");
                                        }
                                        /*
                                         * note that we don't register this thread with the
                                         * timed_thread list, because we destroy it manually
                                         */
                                        if (timed_thread_run(obj->data.texeci.p_timed_thread)) {
-                                               ERR("Error running texeci timed thread");
+                                               NORM_ERR("Error running texeci timed thread");
                                        }
                                } else {
                                        timed_thread_lock(obj->data.texeci.p_timed_thread);
@@ -4486,7 +4666,6 @@ static void generate_text_internal(char *p, int p_max_size,
                                        timed_thread_unlock(obj->data.texeci.p_timed_thread);
                                }
                        }
-#endif /* HAVE_POPEN */
                        OBJ(imap_unseen) {
                                struct mail_s *mail = ensure_mail_thread(obj, imap_thread, "imap");
 
@@ -4672,7 +4851,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                if (obj->data.curl.uri != NULL) {
                                        ccurl_process_info(p, p_max_size, obj->data.curl.uri, obj->data.curl.interval);
                                } else {
-                                       ERR("error processing Curl data");
+                                       NORM_ERR("error processing Curl data");
                                }
                        }
 #endif
@@ -4681,7 +4860,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                if (obj->data.rss.uri != NULL) {
                                        rss_process_info(p, p_max_size, obj->data.rss.uri, obj->data.rss.action, obj->data.rss.act_par, obj->data.rss.interval, obj->data.rss.nrspaces);
                                } else {
-                                       ERR("error processing RSS data");
+                                       NORM_ERR("error processing RSS data");
                                }
                        }
 #endif
@@ -4690,7 +4869,16 @@ static void generate_text_internal(char *p, int p_max_size,
                                if (obj->data.weather.uri != NULL) {
                                        weather_process_info(p, p_max_size, obj->data.weather.uri, obj->data.weather.data_type, obj->data.weather.interval);
                                } else {
-                                       ERR("error processing weather data, check that you have a valid XOAP key if using XOAP.");
+                                       NORM_ERR("error processing weather data, check that you have a valid XOAP key if using XOAP.");
+                               }
+                       }
+#endif
+#ifdef XOAP
+                       OBJ(weather_forecast) {
+                               if (obj->data.weather_forecast.uri != NULL) {
+                                       weather_forecast_process_info(p, p_max_size, obj->data.weather_forecast.uri, obj->data.weather_forecast.day, obj->data.weather_forecast.data_type, obj->data.weather_forecast.interval);
+                               } else {
+                                       NORM_ERR("error processing weather forecast data, check that you have a valid XOAP key if using XOAP.");
                                }
                        }
 #endif
@@ -4856,7 +5044,7 @@ static void generate_text_internal(char *p, int p_max_size,
 
                                val = compare(expression);
                                if (val == -2) {
-                                       ERR("compare failed for expression '%s'",
+                                       NORM_ERR("compare failed for expression '%s'",
                                                        expression);
                                } else if (!val) {
                                        DO_JUMP;
@@ -5591,10 +5779,12 @@ static void generate_text_internal(char *p, int p_max_size,
 #endif
                                        }
                                }
-                       OBJ(tail)
-                               print_tail_object(obj, p, p_max_size);
-                       OBJ(head)
-                               print_head_object(obj, p, p_max_size);
+                       OBJ(tail) {
+                               print_tailhead("tail", obj, p, p_max_size);
+                       }
+                       OBJ(head) {
+                               print_tailhead("head", obj, p, p_max_size);
+                       }
                        OBJ(lines) {
                                FILE *fp = open_file(obj->data.s, &obj->a);
 
@@ -5707,7 +5897,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                                DO_JUMP;
                                        }
                                } else
-                                       ERR("argument to if_smapi_bat_installed must be an integer");
+                                       NORM_ERR("argument to if_smapi_bat_installed must be an integer");
                        }
                        OBJ(smapi_bat_perc) {
                                int idx, val;
@@ -5716,7 +5906,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                                smapi_get_bat_int(idx, "remaining_percent") : 0;
                                        percent_print(p, p_max_size, val);
                                } else
-                                       ERR("argument to smapi_bat_perc must be an integer");
+                                       NORM_ERR("argument to smapi_bat_perc must be an integer");
                        }
                        OBJ(smapi_bat_temp) {
                                int idx, val;
@@ -5726,7 +5916,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        /* temperature is in milli degree celsius */
                                        temp_print(p, p_max_size, val / 1000, TEMP_CELSIUS);
                                } else
-                                       ERR("argument to smapi_bat_temp must be an integer");
+                                       NORM_ERR("argument to smapi_bat_temp must be an integer");
                        }
                        OBJ(smapi_bat_power) {
                                int idx, val;
@@ -5736,7 +5926,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        /* power_now is in mW, set to W with one digit precision */
                                        snprintf(p, p_max_size, "%.1f", ((double)val / 1000));
                                } else
-                                       ERR("argument to smapi_bat_power must be an integer");
+                                       NORM_ERR("argument to smapi_bat_power must be an integer");
                        }
 #ifdef X11
                        OBJ(smapi_bat_bar) {
@@ -5748,6 +5938,16 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
 #endif /* X11 */
 #endif /* IBM */
+                       OBJ(include) {
+                               if(obj->sub) {
+                                       char buf[max_user_text];
+
+                                       generate_text_internal(buf, max_user_text, *obj->sub, cur);
+                                       snprintf(p, p_max_size, "%s", buf);
+                               } else {
+                                       p[0] = 0;
+                               }
+                       }
                        OBJ(blink) {
                                //blinking like this can look a bit ugly if the chars in the font don't have the same width
                                char buf[max_user_text];
@@ -6033,7 +6233,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        bytes = iconv(*iconv_cd[iconv_selected - 1], &ptr, &dummy1,
                                                        &outptr, &dummy2);
                                        if (bytes == -1) {
-                                               ERR("Iconv codeset conversion failed");
+                                               NORM_ERR("Iconv codeset conversion failed");
                                                break;
                                        }
                                }
@@ -6043,7 +6243,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                a = outptr - p;
                        }
 #endif /* HAVE_ICONV */
-                       if (obj->type != OBJ_text) {
+                       if (obj->type != OBJ_text && obj->type != OBJ_execp && obj->type != OBJ_execpi) {
                                substitute_newlines(p, a - 2);
                        }
                        p += a;
@@ -6059,7 +6259,7 @@ static void generate_text_internal(char *p, int p_max_size,
 #endif /* X11 */
 }
 
-void evaluate(char *text, char *buffer)
+void evaluate(const char *text, char *buffer)
 {
        struct information *tmp_info;
        struct text_object subroot;
@@ -6116,6 +6316,12 @@ static void generate_text(void)
        total_updates++;
 }
 
+void set_update_interval(double interval)
+{
+       update_interval = interval;
+       update_interval_old = interval;
+}
+
 static inline int get_string_width(const char *s)
 {
 #ifdef X11
@@ -6363,42 +6569,64 @@ static int text_size_updater(char *s, int special_index)
        last_font_height = font_height();
        return special_index;
 }
+#endif /* X11 */
 
 static inline void set_foreground_color(long c)
 {
-       if ((output_methods & TO_X) == 0)
-               return;
-       current_color = c;
-       XSetForeground(display, window.gc, c);
-}
+#ifdef X11
+       if (output_methods & TO_X) {
+               current_color = c;
+               XSetForeground(display, window.gc, c);
+       }
 #endif /* X11 */
+#ifdef NCURSES
+       if (output_methods & TO_NCURSES) {
+               attron(COLOR_PAIR(c));
+       }
+#endif /* NCURSES */
+       UNUSED(c);
+       return;
+}
 
 static void draw_string(const char *s)
 {
        int i, i2, pos, width_of_s;
        int max = 0;
        int added;
+       char *s_with_newlines;
 
        if (s[0] == '\0') {
                return;
        }
 
        width_of_s = get_string_width(s);
+       s_with_newlines = strdup(s);
+       for(i = 0; i < (int) strlen(s_with_newlines); i++) {
+               if(s_with_newlines[i] == SECRIT_MULTILINE_CHAR) {
+                       s_with_newlines[i] = '\n';
+               }
+       }
        if ((output_methods & TO_STDOUT) && draw_mode == FG) {
-               printf("%s\n", s);
+               printf("%s\n", s_with_newlines);
                if (extra_newline) fputc('\n', stdout);
                fflush(stdout); /* output immediately, don't buffer */
        }
        if ((output_methods & TO_STDERR) && draw_mode == FG) {
-               fprintf(stderr, "%s\n", s);
+               fprintf(stderr, "%s\n", s_with_newlines);
                fflush(stderr); /* output immediately, don't buffer */
        }
        if ((output_methods & OVERWRITE_FILE) && draw_mode == FG && overwrite_fpointer) {
-               fprintf(overwrite_fpointer, "%s\n", s);
+               fprintf(overwrite_fpointer, "%s\n", s_with_newlines);
        }
        if ((output_methods & APPEND_FILE) && draw_mode == FG && append_fpointer) {
-               fprintf(append_fpointer, "%s\n", s);
+               fprintf(append_fpointer, "%s\n", s_with_newlines);
+       }
+#ifdef NCURSES
+       if ((output_methods & TO_NCURSES) && draw_mode == FG) {
+               printw("%s", s_with_newlines);
        }
+#endif
+       free(s_with_newlines);
        memset(tmpstring1, 0, text_buffer_size);
        memset(tmpstring2, 0, text_buffer_size);
        strncpy(tmpstring1, s, text_buffer_size - 1);
@@ -6475,18 +6703,21 @@ static void draw_string(const char *s)
        memcpy(tmpstring1, s, text_buffer_size);
 }
 
-#ifdef X11
 int draw_each_line_inner(char *s, int special_index, int last_special_applied)
 {
+#ifdef X11
        int font_h = font_height();
        int cur_y_add = 0;
+#endif /* X11 */
        char *recurse = 0;
        char *p = s;
        int last_special_needed = -1;
        int orig_special_index = special_index;
 
+#ifdef X11
        cur_x = text_start_x;
        cur_y += font_ascent();
+#endif /* X11 */
 
        while (*p) {
                if (*p == SECRIT_MULTILINE_CHAR) {
@@ -6496,7 +6727,9 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied)
                        break;
                }
                if (*p == SPECIAL_CHAR || last_special_applied > -1) {
+#ifdef X11
                        int w = 0;
+#endif /* X11 */
 
                        /* draw string before special, unless we're dealing multiline
                         * specials */
@@ -6510,6 +6743,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied)
                        }
                        /* draw special */
                        switch (specials[special_index].type) {
+#ifdef X11
                                case HORIZONTAL_LINE:
                                {
                                        int h = specials[special_index].height;
@@ -6804,12 +7038,14 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied)
                                        font_h = font_height();
                                        break;
                                }
+#endif /* X11 */
                                case FG:
                                        if (draw_mode == FG) {
                                                set_foreground_color(specials[special_index].arg);
                                        }
                                        break;
 
+#ifdef X11
                                case BG:
                                        if (draw_mode == BG) {
                                                set_foreground_color(specials[special_index].arg);
@@ -6891,9 +7127,12 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied)
                                        last_special_needed = special_index;
                                        break;
                                }
+#endif /* X11 */
                        }
 
+#ifdef X11
                        cur_x += w;
+#endif /* X11 */
 
                        if (special_index != last_special_applied) {
                                special_index++;
@@ -6905,31 +7144,40 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied)
                p++;
        }
 
+#ifdef X11
        cur_y += cur_y_add;
+#endif /* X11 */
        draw_string(s);
+#ifdef NCURSES
+       if (output_methods & TO_NCURSES) {
+               printw("\n");
+       }
+#endif /* NCURSES */
+#ifdef X11
        cur_y += font_descent();
+#endif /* X11 */
        if (recurse && *recurse) {
                special_index = draw_each_line_inner(recurse, special_index, last_special_needed);
                *(recurse - 1) = SECRIT_MULTILINE_CHAR;
        }
        return special_index;
 }
-#endif /* X11 */
 
 static int draw_line(char *s, int special_index)
 {
 #ifdef X11
-       if ((output_methods & TO_X) == 0) {
-#endif /* X11 */
-               draw_string(s);
-               //'special_index - special_index' instead of 0 otherwise gcc complains about not using special_index when build without X11
-               return special_index - special_index;
-#ifdef X11
+       if (output_methods & TO_X) {
+               return draw_each_line_inner(s, special_index, -1);
        }
-
-       /* find specials and draw stuff */
-       return draw_each_line_inner(s, special_index, -1);
 #endif /* X11 */
+#ifdef NCURSES
+       if (output_methods & TO_NCURSES) {
+               return draw_each_line_inner(s, special_index, -1);
+       }
+#endif /* NCURSES */
+       draw_string(s);
+       UNUSED(special_index);
+       return 0;
 }
 
 static void draw_text(void)
@@ -6964,6 +7212,10 @@ static void draw_text(void)
        }
        setup_fonts();
 #endif /* X11 */
+#ifdef NCURSES
+       init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
+       attron(COLOR_PAIR(COLOR_WHITE));
+#endif /* NCURSES */
        for_each_line(text_buffer, draw_line);
 #if defined(HAVE_LUA) && defined(X11)
        llua_draw_post_hook();
@@ -6975,12 +7227,12 @@ static void draw_stuff(void)
        if (overwrite_file) {
                overwrite_fpointer = fopen(overwrite_file, "w");
                if(!overwrite_fpointer)
-                       ERR("Can't overwrite '%s' anymore", overwrite_file);
+                       NORM_ERR("Can't overwrite '%s' anymore", overwrite_file);
        }
        if (append_file) {
                append_fpointer = fopen(append_file, "a");
                if(!append_fpointer)
-                       ERR("Can't append '%s' anymore", append_file);
+                       NORM_ERR("Can't append '%s' anymore", append_file);
        }
 #ifdef X11
        if (output_methods & TO_X) {
@@ -7076,6 +7328,9 @@ static void update_text(void)
                clear_text(1);
 #endif /* X11 */
        need_to_update = 1;
+#ifdef HAVE_LUA
+       llua_update_info(&info, update_interval);
+#endif /* HAVE_LUA */
 }
 
 #ifdef HAVE_SYS_INOTIFY_H
@@ -7108,6 +7363,16 @@ static void main_loop(void)
        next_update_time = get_time();
        info.looped = 0;
        while (terminate == 0 && (total_run_times == 0 || info.looped < total_run_times)) {
+               if(update_interval_bat != NOBATTERY && update_interval_bat != update_interval_old) {
+                       char buf[max_user_text];
+
+                       get_battery_short_status(buf, max_user_text, "BAT0");
+                       if(buf[0] == 'D') {
+                               update_interval = update_interval_bat;
+                       } else {
+                               update_interval = update_interval_old;
+                       }
+               }
                info.looped++;
 
 #ifdef SIGNAL_BLOCKING
@@ -7143,7 +7408,7 @@ static void main_loop(void)
                                s = select(ConnectionNumber(display) + 1, &fdsr, 0, 0, &tv);
                                if (s == -1) {
                                        if (errno != EINTR) {
-                                               ERR("can't select(): %s", strerror(errno));
+                                               NORM_ERR("can't select(): %s", strerror(errno));
                                        }
                                } else {
                                        /* timeout */
@@ -7167,15 +7432,19 @@ static void main_loop(void)
 
                                        /* resize window if it isn't right size */
                                        if (!fixed_size
-                                               && (text_width + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2 != window.width
-                                               || text_height + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2 != window.height)) {
-                                                       window.width = text_width + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2;
-                                                       window.height = text_height + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2;
-                                                       XResizeWindow(display, window.window, window.width,
+                                                       && (text_width + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2 != window.width
+                                                               || text_height + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2 != window.height)) {
+                                               window.width = text_width + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2;
+                                               window.height = text_height + window.border_inner_margin * 2 + window.border_outer_margin * 2 + window.border_width * 2;
+                                               XResizeWindow(display, window.window, window.width,
                                                                window.height);
-                                                       set_transparent_background(window.window);
+                                               set_transparent_background(window.window);
 
-                                                       changed++;
+                                               changed++;
+#ifdef HAVE_LUA
+                                               /* update lua window globals */
+                                               llua_update_window_table(text_start_x, text_start_y, text_width, text_height);
+#endif /* HAVE_LUA */
                                        }
 
                                        /* move window if it isn't in right position */
@@ -7184,42 +7453,42 @@ static void main_loop(void)
                                                changed++;
                                        }
 
-                                        /* update struts */
-                                        if (changed && window.type == TYPE_PANEL) {
+                                       /* update struts */
+                                       if (changed && window.type == TYPE_PANEL) {
                                                int sidenum = -1;
 
-                                                fprintf(stderr, PACKAGE_NAME": defining struts\n");
-                                                fflush(stderr);
+                                               fprintf(stderr, PACKAGE_NAME": defining struts\n");
+                                               fflush(stderr);
 
                                                switch (text_alignment) {
                                                        case TOP_LEFT:
                                                        case TOP_RIGHT:
                                                        case TOP_MIDDLE:
-                                                       {
-                                                               sidenum = 2;
-                                                               break;
-                                                       }
+                                                               {
+                                                                       sidenum = 2;
+                                                                       break;
+                                                               }
                                                        case BOTTOM_LEFT:
                                                        case BOTTOM_RIGHT:
                                                        case BOTTOM_MIDDLE:
-                                                       {
-                                                               sidenum = 3;
-                                                               break;
-                                                       }
+                                                               {
+                                                                       sidenum = 3;
+                                                                       break;
+                                                               }
                                                        case MIDDLE_LEFT:
-                                                       {
-                                                               sidenum = 0;
-                                                               break;
-                                                       }
+                                                               {
+                                                                       sidenum = 0;
+                                                                       break;
+                                                               }
                                                        case MIDDLE_RIGHT:
-                                                       {
-                                                               sidenum = 1;
-                                                               break;
-                                                       }
+                                                               {
+                                                                       sidenum = 1;
+                                                                       break;
+                                                               }
                                                }
 
                                                set_struts(sidenum);
-                                        }
+                                       }
                                }
 #endif
 
@@ -7318,9 +7587,10 @@ static void main_loop(void)
                                        case ButtonPress:
                                                if (own_window) {
                                                        /* if an ordinary window with decorations */
-                                                       if ((window.type == TYPE_NORMAL)
-                                                               && (!TEST_HINT(window.hints,
-                                                               HINT_UNDECORATED))) {
+                                                       if ((window.type == TYPE_NORMAL &&
+                                                                               (!TEST_HINT(window.hints,
+                                                                                                       HINT_UNDECORATED))) ||
+                                                                       window.type == TYPE_DESKTOP) {
                                                                /* allow conky to hold input focus. */
                                                                break;
                                                        } else {
@@ -7414,6 +7684,12 @@ static void main_loop(void)
                        if(t > 0) usleep((useconds_t)t);
                        update_text();
                        draw_stuff();
+#ifdef NCURSES
+                       if(output_methods & TO_NCURSES) {
+                               refresh();
+                               clear();
+                       }
+#endif
 #ifdef X11
                }
 #endif /* X11 */
@@ -7428,12 +7704,12 @@ static void main_loop(void)
                switch (g_signal_pending) {
                        case SIGHUP:
                        case SIGUSR1:
-                               ERR("received SIGHUP or SIGUSR1. reloading the config file.");
+                               NORM_ERR("received SIGHUP or SIGUSR1. reloading the config file.");
                                reload_config();
                                break;
                        case SIGINT:
                        case SIGTERM:
-                               ERR("received SIGINT or SIGTERM to terminate. bye!");
+                               NORM_ERR("received SIGINT or SIGTERM to terminate. bye!");
                                terminate = 1;
 #ifdef X11
                                if (output_methods & TO_X) {
@@ -7465,7 +7741,7 @@ static void main_loop(void)
                                 * If you don't want to handle a signal, don't set a handler on
                                 * it in the first place. */
                                if (g_signal_pending) {
-                                       ERR("ignoring signal (%d)", g_signal_pending);
+                                       NORM_ERR("ignoring signal (%d)", g_signal_pending);
                                }
                                break;
                }
@@ -7493,7 +7769,7 @@ static void main_loop(void)
                                        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 */
-                                               ERR("'%s' modified, reloading...", current_config);
+                                               NORM_ERR("'%s' modified, reloading...", current_config);
                                                reload_config();
                                                if (ev->mask & IN_IGNORED) {
                                                        /* for some reason we get IN_IGNORED here
@@ -7514,6 +7790,9 @@ static void main_loop(void)
                }
 #endif /* HAVE_SYS_INOTIFY_H */
 
+#ifdef HAVE_LUA
+       llua_update_info(&info, update_interval);
+#endif /* HAVE_LUA */
                g_signal_pending = 0;
        }
        clean_up(NULL, NULL);
@@ -7527,7 +7806,6 @@ static void main_loop(void)
 #endif /* HAVE_SYS_INOTIFY_H */
 }
 
-static void load_config_file(const char *);
 #ifdef X11
 static void load_config_file_x11(const char *);
 #endif /* X11 */
@@ -7545,6 +7823,14 @@ static void reload_config(void)
 void clean_up(void *memtofree1, void* memtofree2)
 {
        int i;
+
+#ifdef NCURSES
+       if(output_methods & TO_NCURSES) {
+               endwin();
+       }
+#endif
+       conftree_empty(currentconffile);
+       currentconffile = NULL;
        if(memtofree1) {
                free(memtofree1);
        }
@@ -7626,8 +7912,15 @@ void clean_up(void *memtofree1, void* memtofree2)
        weather_free_info();
 #endif
 #ifdef HAVE_LUA
+       llua_shutdown_hook();
        llua_close();
 #endif /* HAVE_LUA */
+#ifdef IMLIB2
+       cimlib_deinit();
+#endif /* IMLIB2 */
+#ifdef XOAP
+       xmlCleanupParser();
+#endif /* XOAP */
 
        if (specials) {
                for (i = 0; i < special_count; i++) {
@@ -7846,7 +8139,8 @@ static void set_default_configurations(void)
        }
 
        no_buffers = 1;
-       update_interval = 3.0;
+       set_update_interval(3);
+       update_interval_bat = NOBATTERY;
        info.music_player_interval = 1.0;
        stuff_in_uppercase = 0;
        info.users.number = 1;
@@ -7886,7 +8180,7 @@ int x11_error_handler(Display *d, XErrorEvent *err)
        __attribute__((noreturn));
 int x11_error_handler(Display *d, XErrorEvent *err)
 {
-       ERR("X Error: type %i Display %lx XID %li serial %lu error_code %i request_code %i minor_code %i other Display: %lx\n",
+       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,
@@ -7903,7 +8197,7 @@ int x11_ioerror_handler(Display *d)
        __attribute__((noreturn));
 int x11_ioerror_handler(Display *d)
 {
-       ERR("X Error: Display %lx\n",
+       NORM_ERR("X Error: Display %lx\n",
                        (long unsigned)d
                        );
        abort();
@@ -7961,7 +8255,7 @@ static void X11_create_window(void)
                x11_stuff.region = XCreateRegion();
 #ifdef HAVE_XDAMAGE
                if (!XDamageQueryExtension(display, &x11_stuff.event_base, &x11_stuff.error_base)) {
-                       ERR("Xdamage extension unavailable");
+                       NORM_ERR("Xdamage extension unavailable");
                }
                x11_stuff.damage = XDamageCreate(display, window.window, XDamageReportNonEmpty);
                x11_stuff.region2 = XFixesCreateRegionFromWindow(display, window.window, 0);
@@ -7978,8 +8272,8 @@ static void X11_create_window(void)
 }
 #endif /* X11 */
 
-#define CONF_ERR ERR("%s: %d: config file error", f, line)
-#define CONF_ERR2(a) ERR("%s: %d: config file error: %s", f, line, a)
+#define CONF_ERR NORM_ERR("%s: %d: config file error", f, line)
+#define CONF_ERR2(a) NORM_ERR("%s: %d: config file error: %s", f, line, a)
 #define CONF2(a) if (strcasecmp(name, a) == 0)
 #define CONF(a) else CONF2(a)
 #define CONF3(a, b) else if (strcasecmp(name, a) == 0 \
@@ -8048,15 +8342,14 @@ static int do_config_step(int *line, FILE *fp, char *buf, char **name, char **va
        return 0;
 }
 
-static void load_config_file(const char *f)
+char load_config_file(const char *f)
 {
        int line = 0;
        FILE *fp;
 
-       set_default_configurations();
        fp = open_config_file(f);
        if (!fp) {
-               return;
+               return FALSE;
        }
        DBGP("reading contents from config file '%s'", f);
 
@@ -8124,15 +8417,6 @@ static void load_config_file(const char *f)
                CONF("show_graph_range") {
                        show_graph_range = string_to_bool(value);
                }
-               CONF("border_margin") {
-                       ERR("border_margin is deprecated, please use window.border_inner_margin instead");
-                       if (value) {
-                               window.border_inner_margin = strtol(value, 0, 0);
-                               if (window.border_inner_margin < 0) window.border_inner_margin = 0;
-                       } else {
-                               CONF_ERR;
-                       }
-               }
                CONF("border_inner_margin") {
                        if (value) {
                                window.border_inner_margin = strtol(value, 0, 0);
@@ -8329,8 +8613,11 @@ static void load_config_file(const char *f)
                }
 #endif /* X11 */
                CONF("out_to_console") {
-                       if(string_to_bool(value))
+                       if(string_to_bool(value)) {
                                output_methods |= TO_STDOUT;
+                       } else {
+                               output_methods &= ~TO_STDOUT;
+                       }
                }
                CONF("extra_newline") {
                        extra_newline = string_to_bool(value);
@@ -8339,6 +8626,15 @@ static void load_config_file(const char *f)
                        if(string_to_bool(value))
                                output_methods |= TO_STDERR;
                }
+#ifdef NCURSES
+               CONF("out_to_ncurses") {
+                       if(string_to_bool(value)) {
+                               initscr();
+                               start_color();
+                               output_methods |= TO_NCURSES;
+                       }
+               }
+#endif
                CONF("overwrite_file") {
                        if(overwrite_file) {
                                free(overwrite_file);
@@ -8348,7 +8644,7 @@ static void load_config_file(const char *f)
                                overwrite_file = strdup(value);
                                output_methods |= OVERWRITE_FILE;
                        } else
-                               ERR("overwrite_file won't be able to create/overwrite '%s'", value);
+                               NORM_ERR("overwrite_file won't be able to create/overwrite '%s'", value);
                }
                CONF("append_file") {
                        if(append_file) {
@@ -8359,7 +8655,7 @@ static void load_config_file(const char *f)
                                append_file = strdup(value);
                                output_methods |= APPEND_FILE;
                        } else
-                               ERR("append_file won't be able to create/append '%s'", value);
+                               NORM_ERR("append_file won't be able to create/append '%s'", value);
                }
                CONF("use_spacer") {
                        if (value) {
@@ -8371,7 +8667,7 @@ static void load_config_file(const char *f)
                                        use_spacer = NO_SPACER;
                                } else {
                                        use_spacer = string_to_bool(value);
-                                       ERR("use_spacer should have an argument of left, right, or"
+                                       NORM_ERR("use_spacer should have an argument of left, right, or"
                                                " none.  '%s' seems to be some form of '%s', so"
                                                " defaulting to %s.", value,
                                                use_spacer ? "true" : "false",
@@ -8383,7 +8679,7 @@ static void load_config_file(const char *f)
                                        }
                                }
                        } else {
-                               ERR("use_spacer should have an argument. Defaulting to right.");
+                               NORM_ERR("use_spacer should have an argument. Defaulting to right.");
                                use_spacer = RIGHT_SPACER;
                        }
                }
@@ -8407,7 +8703,7 @@ static void load_config_file(const char *f)
 #else
                CONF("use_xft") {
                        if (string_to_bool(value)) {
-                               ERR("Xft not enabled at compile time");
+                               NORM_ERR("Xft not enabled at compile time");
                        }
                }
                CONF("xftfont") {
@@ -8604,9 +8900,16 @@ static void load_config_file(const char *f)
                }
 #endif /* IMLIB2 */
 #endif /* X11 */
+               CONF("update_interval_on_battery") {
+                       if (value) {
+                               update_interval_bat = strtod(value, 0);
+                       } else {
+                               CONF_ERR;
+                       }
+               }
                CONF("update_interval") {
                        if (value) {
-                               update_interval = strtod(value, 0);
+                               set_update_interval(strtod(value, 0));
                        } else {
                                CONF_ERR;
                        }
@@ -8643,7 +8946,7 @@ static void load_config_file(const char *f)
                        if (value) {
                                text_buffer_size = atoi(value);
                                if (text_buffer_size < DEFAULT_TEXT_BUFFER_SIZE) {
-                                       ERR("text_buffer_size must be >=%i bytes", DEFAULT_TEXT_BUFFER_SIZE);
+                                       NORM_ERR("text_buffer_size must be >=%i bytes", DEFAULT_TEXT_BUFFER_SIZE);
                                        text_buffer_size = DEFAULT_TEXT_BUFFER_SIZE;
                                }
                        } else {
@@ -8702,7 +9005,7 @@ static void load_config_file(const char *f)
                                CRIT_ERR(NULL, NULL, "no text supplied in configuration; exiting");
                        }
                        global_text_lines = line + 1;
-                       return;
+                       return TRUE;
                }
 #ifdef TCP_PORT_MONITOR
                CONF("max_port_monitor_connections") {
@@ -8719,7 +9022,7 @@ static void load_config_file(const char *f)
 #endif
                CONF("if_up_strictness") {
                        if (!value) {
-                               ERR("incorrect if_up_strictness value, defaulting to 'up'");
+                               NORM_ERR("incorrect if_up_strictness value, defaulting to 'up'");
                                ifup_strictness = IFUP_UP;
                        } else if (strcasecmp(value, "up") == EQUAL) {
                                ifup_strictness = IFUP_UP;
@@ -8728,40 +9031,19 @@ static void load_config_file(const char *f)
                        } else if (strcasecmp(value, "address") == EQUAL) {
                                ifup_strictness = IFUP_ADDR;
                        } else {
-                               ERR("incorrect if_up_strictness value, defaulting to 'up'");
+                               NORM_ERR("incorrect if_up_strictness value, defaulting to 'up'");
                                ifup_strictness = IFUP_UP;
                        }
                }
 
                CONF("temperature_unit") {
                        if (!value) {
-                               ERR("config option 'temperature_unit' needs an argument, either 'celsius' or 'fahrenheit'");
+                               NORM_ERR("config option 'temperature_unit' needs an argument, either 'celsius' or 'fahrenheit'");
                        } else if (set_temp_output_unit(value)) {
-                               ERR("temperature_unit: incorrect argument");
+                               NORM_ERR("temperature_unit: incorrect argument");
                        }
                }
 
-               CONF("alias") {
-                       if (value) {
-                               size_t maxlength = strlen(value);       //+1 for terminating 0 not needed, 'cause of the space in the middle of value
-                               char *skey = malloc(maxlength);
-                               char *svalue = malloc(maxlength);
-                               char *oldvalue;
-                               if (sscanf(value, "%[0-9a-zA-Z_] %[^\n]", skey, svalue) == 2) {
-                                       oldvalue = getenv(skey);
-                                       if (oldvalue == NULL) {
-                                               setenv(skey, svalue, 0);
-                                       }
-                                       //PS: Don't free oldvalue, it's the real envvar, not a copy
-                               } else {
-                                       CONF_ERR;
-                               }
-                               free(skey);
-                               free(svalue);
-                       } else {
-                               CONF_ERR;
-                       }
-               }
 #ifdef HAVE_LUA
                CONF("lua_load") {
                        if (value) {
@@ -8789,6 +9071,20 @@ static void load_config_file(const char *f)
                                CONF_ERR;
                        }
                }
+               CONF("lua_startup_hook") {
+                       if (value) {
+                               llua_set_startup_hook(value);
+                       } else {
+                               CONF_ERR;
+                       }
+               }
+               CONF("lua_shutdown_hook") {
+                       if (value) {
+                               llua_set_shutdown_hook(value);
+                       } else {
+                               CONF_ERR;
+                       }
+               }
 #endif /* X11 */
 #endif /* HAVE_LUA */
 
@@ -8808,7 +9104,7 @@ static void load_config_file(const char *f)
                CONF("own_window_colour") {}
 
                else {
-                       ERR("%s: %d: no such configuration: '%s'", f, line, name);
+                       NORM_ERR("%s: %d: no such configuration: '%s'", f, line, name);
                }
        }
 
@@ -8821,6 +9117,7 @@ static void load_config_file(const char *f)
        if (!global_text) { // didn't supply any text
                CRIT_ERR(NULL, NULL, "missing text block in configuration; exiting");
        }
+       return TRUE;
 }
 
 #ifdef X11
@@ -8981,7 +9278,7 @@ static void load_config_file_x11(const char *f)
                                if (value) {
                                        background_colour = get_x11_color(value);
                                } else {
-                                       ERR("Invalid colour for own_window_colour (try omitting the "
+                                       NORM_ERR("Invalid colour for own_window_colour (try omitting the "
                                                "'#' for hex colours");
                                }
                        }
@@ -9008,42 +9305,6 @@ static void load_config_file_x11(const char *f)
 }
 #endif /* X11 */
 
-#if defined(WEATHER) && defined(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
- */
-static void load_xoap_keys(void)
-{
-  FILE *fp;
-  char *par = (char *) malloc(11 * sizeof(char));
-  char *key = (char *) malloc(17 * sizeof(char));
-
-  xoap = (char *) malloc(64 * sizeof(char));
-  to_real_path(xoap, XOAP_FILE);
-  fp = fopen(xoap, "r");
-  if (fp != NULL) {
-    if( fscanf(fp, "%10s %16s", par, key) == 2 ) {
-      strcpy(xoap, "?cc=*&link=xoap&prod=xoap&par=");
-      strcat(xoap, par);
-      strcat(xoap, "&key=");
-      strcat(xoap, key);
-      strcat(xoap, "&unit=m");
-    } else {
-      free(xoap);
-      xoap = NULL;
-    }
-    fclose(fp);
-  } else {
-    free(xoap);
-    xoap = NULL;
-  }
-  free(par);
-  free(key);
-}
-#endif /* WEATHER && XOAP */
-
 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"
@@ -9125,11 +9386,13 @@ static const struct option longopts[] = {
 void initialisation(int argc, char **argv) {
        struct sigaction act, oact;
 
+       set_default_configurations();
        load_config_file(current_config);
+       currentconffile = conftree_add(currentconffile, current_config);
 
        /* init specials array */
        if ((specials = calloc(sizeof(struct special_t), max_specials)) == 0) {
-               ERR("failed to create specials array");
+               NORM_ERR("failed to create specials array");
        }
 
 #ifdef MAIL_FILE
@@ -9181,11 +9444,6 @@ void initialisation(int argc, char **argv) {
                        case 'a':
                                text_alignment = string_to_alignment(optarg);
                                break;
-                       case 'X':
-                               if (disp)
-                                       free(disp);
-                               disp = strdup(optarg);
-                               break;
 
 #ifdef OWN_WINDOW
                        case 'o':
@@ -9209,6 +9467,7 @@ void initialisation(int argc, char **argv) {
 
                        case 'u':
                                update_interval = strtod(optarg, 0);
+                               update_interval_old = update_interval;
                                if (info.music_player_interval == 0) {
                                        // default to update_interval
                                        info.music_player_interval = update_interval;
@@ -9253,7 +9512,7 @@ void initialisation(int argc, char **argv) {
 
                switch (pid) {
                        case -1:
-                               ERR(PACKAGE_NAME": couldn't fork() to background: %s",
+                               NORM_ERR(PACKAGE_NAME": couldn't fork() to background: %s",
                                        strerror(errno));
                                break;
 
@@ -9285,6 +9544,12 @@ void initialisation(int argc, char **argv) {
        xargv = argv;
        X11_create_window();
 #endif /* X11 */
+#ifdef HAVE_LUA
+       llua_setup_info(&info, update_interval);
+#endif /* HAVE_LUA */
+#ifdef XOAP
+       xmlInitParser();
+#endif /* XOAP */
 
        /* Set signal handlers */
        act.sa_handler = signal_handler;
@@ -9295,12 +9560,16 @@ void initialisation(int argc, char **argv) {
 #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) {
-               ERR("error setting signal handler: %s", strerror(errno));
+               NORM_ERR("error setting signal handler: %s", strerror(errno));
        }
 
+#ifdef HAVE_LUA
+       llua_startup_hook();
+#endif /* HAVE_LUA */
 }
 
 int main(int argc, char **argv)
@@ -9330,7 +9599,7 @@ int main(int argc, char **argv)
                        || ((s = getenv("LANG")) && *s)) {
                temp = (char *) malloc((strlen(s) + 1) * sizeof(char));
                if (temp == NULL) {
-                       ERR("malloc failed");
+                       NORM_ERR("malloc failed");
                }
                for (x = 0; x < strlen(s); x++) {
                        temp[x] = tolower(s[x]);
@@ -9343,7 +9612,7 @@ int main(int argc, char **argv)
                free(temp);
        }
        if (!setlocale(LC_CTYPE, "")) {
-               ERR("Can't set the specified locale!\nCheck LANG, LC_CTYPE, LC_ALL.");
+               NORM_ERR("Can't set the specified locale!\nCheck LANG, LC_CTYPE, LC_ALL.");
        }
 #endif /* X11 */
        while (1) {
@@ -9378,6 +9647,11 @@ int main(int argc, char **argv)
                        case 'w':
                                window.window = strtol(optarg, 0, 0);
                                break;
+                       case 'X':
+                               if (disp)
+                                       free(disp);
+                               disp = strdup(optarg);
+                               break;
 #endif /* X11 */
 
                        case '?':
@@ -9390,7 +9664,7 @@ int main(int argc, char **argv)
                struct stat sb;
                if (stat(current_config, &sb) ||
                                (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) {
-                       ERR("invalid configuration file '%s'\n", current_config);
+                       NORM_ERR("invalid configuration file '%s'\n", current_config);
                        free(current_config);
                        current_config = 0;
                }
@@ -9420,7 +9694,7 @@ int main(int argc, char **argv)
                if (!current_config) {
 #ifdef CONFIG_OUTPUT
                        current_config = strdup("==builtin==");
-                       ERR("no readable personal or system-wide config file found,"
+                       NORM_ERR("no readable personal or system-wide config file found,"
                                        " using builtin default");
 #else
                        CRIT_ERR(NULL, NULL, "no readable personal or system-wide config file found");
@@ -9428,10 +9702,10 @@ int main(int argc, char **argv)
                }
        }
 
-#if defined(WEATHER) && defined(XOAP)
+#ifdef XOAP
        /* Load xoap keys, if existing */
        load_xoap_keys();
-#endif /* WEATHER && XOAP */
+#endif /* XOAP */
 
 #ifdef HAVE_SYS_INOTIFY_H
        inotify_fd = inotify_init();
@@ -9446,13 +9720,24 @@ int main(int argc, char **argv)
 #endif
 
        return 0;
+
+}
+
+void alarm_handler(void) {
+       if(childpid > 0) {
+               kill(childpid, SIGTERM);
+       }
 }
 
 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;
+        * and do any signal processing there, NOT here (except 
+        * SIGALRM because this is caused when conky is hanging) */
+       if(sig == SIGALRM) {
+               alarm_handler();
+       } else {
+               g_signal_pending = sig;
+       }
 }
-