1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
3 * Conky, a system monitor, based on torsmo
5 * Any original torsmo code is licensed under the BSD license
7 * All code written since the fork of torsmo is licensed under the GPL
9 * Please see COPYING for details
11 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
12 * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
14 * All rights reserved.
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 * vim: ts=4 sw=4 noet ai cindent syntax=c
33 #include "text_object.h"
48 #include <sys/param.h>
49 #ifdef HAVE_SYS_INOTIFY_H
50 #include <sys/inotify.h>
51 #endif /* HAVE_SYS_INOTIFY_H */
54 #include <X11/Xutil.h>
56 #include <X11/extensions/Xdamage.h>
57 #endif /* HAVE_XDAMAGE */
59 #include <sys/types.h>
61 #include <netinet/in.h>
66 #include <libxml/parser.h>
70 #include "obj_create.h"
71 #include "obj_display.h"
72 #include "obj_destroy.h"
85 #include "temphelper.h"
89 /* check for OS and include appropriate headers */
90 #if defined(__linux__)
92 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
94 #elif defined(__OpenBSD__)
98 #if defined(__FreeBSD_kernel__)
102 /* FIXME: apm_getinfo is unused here. maybe it's meant for common.c */
103 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
104 || defined(__OpenBSD__)) && (defined(i386) || defined(__i386__))
105 int apm_getinfo(int fd, apm_info_t aip);
106 char *get_apm_adapter(void);
107 char *get_apm_battery_life(void);
108 char *get_apm_battery_time(void);
112 #include "defconfig.h"
113 #include "conf_cookie.h"
117 #define S_ISSOCK(x) ((x & S_IFMT) == S_IFSOCK)
120 #define MAX_IF_BLOCK_DEPTH 5
122 //#define SIGNAL_BLOCKING
123 #undef SIGNAL_BLOCKING
125 /* debugging level, used by logging.h */
126 int global_debug_level = 0;
128 static volatile int g_signal_pending;
133 /* prototypes for internally used functions */
134 static void signal_handler(int);
135 static void print_version(void) __attribute__((noreturn));
137 static void print_version(void)
139 printf(PACKAGE_NAME" "VERSION" compiled "BUILD_DATE" for "BUILD_ARCH"\n");
141 printf("\nCompiled in features:\n\n"
142 "System config file: "SYSTEM_CONFIG_FILE"\n"
143 "Package library path: "PACKAGE_LIBDIR"\n\n"
147 " * Xdamage extension\n"
148 # endif /* HAVE_XDAMAGE */
150 " * XDBE (double buffer extension)\n"
151 # endif /* HAVE_XDBE */
156 "\n Music detection:\n"
159 #endif /* AUDACIOUS */
175 #endif /* HAVE_OPENMP */
182 #ifdef TCP_PORT_MONITOR
184 #endif /* TCP_PORT_MONITOR */
187 #endif /* HAVE_CURL */
192 " * Weather (METAR)\n"
194 " * Weather (XOAP)\n"
199 #endif /* HAVE_IWLIB */
201 " * support for IBM/Lenovo notebooks\n"
211 #endif /* CONFIG_OUTPUT */
216 " * ALSA mixer support\n"
217 #endif /* MIXER_IS_ALSA */
227 #ifdef HAVE_LUA_CAIRO
229 #endif /* HAVE_LUA_CAIRO */
230 #ifdef HAVE_LUA_IMLIB2
233 #endif /* HAVE_LUA */
239 #ifdef HAVE_SYS_INOTIFY_H
243 static void main_loop(conky_context *ctx)
246 #ifdef SIGNAL_BLOCKING
247 sigset_t newmask, oldmask;
250 #ifdef HAVE_SYS_INOTIFY_H
251 int inotify_config_wd = -1;
252 #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
253 #define INOTIFY_BUF_LEN (20 * (INOTIFY_EVENT_SIZE + 16))
254 char inotify_buff[INOTIFY_BUF_LEN];
255 #endif /* HAVE_SYS_INOTIFY_H */
258 #ifdef SIGNAL_BLOCKING
259 sigemptyset(&newmask);
260 sigaddset(&newmask, SIGINT);
261 sigaddset(&newmask, SIGTERM);
262 sigaddset(&newmask, SIGUSR1);
265 ctx->next_update_time = get_time();
266 while (terminate == 0 && (ctx->total_run_times == 0 || ctx->info.looped < ctx->total_run_times)) {
267 if (ctx->update_interval_bat != NOBATTERY && ctx->update_interval_bat != ctx->update_interval_old) {
268 char buf[ctx->max_user_text];
270 get_battery_short_status(buf, ctx->max_user_text, "BAT0");
272 ctx->update_interval = ctx->update_interval_bat;
274 ctx->update_interval = ctx->update_interval_old;
279 #ifdef SIGNAL_BLOCKING
280 /* block signals. we will inspect for pending signals later */
281 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
282 CRIT_ERR(NULL, NULL, "unable to sigprocmask()");
287 if (ctx->output_methods & TO_X) {
290 /* wait for X event or timeout */
292 if (!XPending(display)) {
296 t = ctx->next_update_time - get_time();
300 } else if (t > ctx->update_interval) {
301 t = ctx->update_interval;
304 tv.tv_sec = (long) t;
305 tv.tv_usec = (long) (t * 1000000) % 1000000;
307 FD_SET(ConnectionNumber(display), &fdsr);
309 s = select(ConnectionNumber(display) + 1, &fdsr, 0, 0, &tv);
311 if (errno != EINTR) {
312 NORM_ERR("can't select(): %s", strerror(errno));
322 if (ctx->need_to_update) {
324 int wx = ctx->window.x, wy = ctx->window.y;
327 ctx->need_to_update = 0;
328 ctx->selected_font = 0;
329 update_text_area(ctx);
331 if (ctx->own_window) {
334 /* resize ctx->window if it isn't right size */
336 && (ctx->text_width + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2 != ctx->window.width
337 || ctx->text_height + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2 != ctx->window.height)) {
338 ctx->window.width = ctx->text_width + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2;
339 ctx->window.height = ctx->text_height + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2;
340 draw_stuff(ctx); /* redraw everything in our newly sized ctx->window */
341 XResizeWindow(display, ctx->window.window, ctx->window.width,
342 ctx->window.height); /* resize ctx->window */
343 set_transparent_background(ctx->window.window);
351 /* update lua ctx->window globals */
352 llua_update_window_table(ctx->text_start_x, ctx->text_start_y, ctx->text_width, ctx->text_height);
353 #endif /* HAVE_LUA */
356 /* move ctx->window if it isn't in right position */
357 if (!ctx->fixed_pos && (ctx->window.x != wx || ctx->window.y != wy)) {
358 XMoveWindow(display, ctx->window.window, ctx->window.x, ctx->window.y);
363 if (changed && ctx->window.type == TYPE_PANEL) {
366 fprintf(stderr, PACKAGE_NAME": defining struts\n");
369 switch (ctx->text_alignment) {
407 r.x = ctx->text_start_x - ctx->window.border_inner_margin - ctx->window.border_outer_margin - ctx->window.border_width;
408 r.y = ctx->text_start_y - ctx->window.border_inner_margin - ctx->window.border_outer_margin - ctx->window.border_width;
409 r.width = ctx->text_width + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2;
410 r.height = ctx->text_height + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2;
411 XUnionRectWithRegion(&r, ctx->window.region, ctx->window.region);
416 /* handle X events */
417 while (XPending(display)) {
420 XNextEvent(display, &ev);
427 r.width = ev.xexpose.width;
428 r.height = ev.xexpose.height;
429 XUnionRectWithRegion(&r, ctx->window.region, ctx->window.region);
435 if ( ev.xproperty.state == PropertyNewValue ) {
436 get_x11_desktop_info( ev.xproperty.display, ev.xproperty.atom );
443 /* set background to ParentRelative for all parents */
444 if (ctx->own_window) {
445 set_transparent_background(ctx->window.window);
449 case ConfigureNotify:
450 if (ctx->own_window) {
451 /* if ctx->window size isn't what expected, set fixed size */
452 if (ev.xconfigure.width != ctx->window.width
453 || ev.xconfigure.height != ctx->window.height) {
454 if (ctx->window.width != 0 && ctx->window.height != 0) {
458 /* clear old stuff before screwing up
463 XWindowAttributes attrs;
464 if (XGetWindowAttributes(display,
465 ctx->window.window, &attrs)) {
466 ctx->window.width = attrs.width;
467 ctx->window.height = attrs.height;
471 ctx->text_width = ctx->window.width - ctx->window.border_inner_margin * 2 - ctx->window.border_outer_margin * 2 - ctx->window.border_width * 2;
472 ctx->text_height = ctx->window.height - ctx->window.border_inner_margin * 2 - ctx->window.border_outer_margin * 2 - ctx->window.border_width * 2;
473 if (ctx->text_width > ctx->maximum_width
474 && ctx->maximum_width > 0) {
475 ctx->text_width = ctx->maximum_width;
479 /* if position isn't what expected, set fixed pos
480 * total_updates avoids setting ctx->fixed_pos when ctx->window
481 * is set to weird locations when started */
483 if (total_updates >= 2 && !ctx->fixed_pos
484 && (ctx->window.x != ev.xconfigure.x
485 || ctx->window.y != ev.xconfigure.y)
486 && (ev.xconfigure.x != 0
487 || ev.xconfigure.y != 0)) {
494 if (ctx->own_window) {
495 /* if an ordinary ctx->window with decorations */
496 if ((ctx->window.type == TYPE_NORMAL &&
497 (!TEST_HINT(ctx->window.hints,
498 HINT_UNDECORATED))) ||
499 ctx->window.type == TYPE_DESKTOP) {
500 /* allow conky to hold input focus. */
503 /* forward the click to the desktop ctx->window */
504 XUngrabPointer(display, ev.xbutton.time);
505 ev.xbutton.window = ctx->window.desktop;
506 ev.xbutton.x = ev.xbutton.x_root;
507 ev.xbutton.y = ev.xbutton.y_root;
508 XSendEvent(display, ev.xbutton.window, False,
509 ButtonPressMask, &ev);
510 XSetInputFocus(display, ev.xbutton.window,
511 RevertToParent, ev.xbutton.time);
517 if (ctx->own_window) {
518 /* if an ordinary ctx->window with decorations */
519 if ((ctx->window.type == TYPE_NORMAL)
520 && (!TEST_HINT(ctx->window.hints,
521 HINT_UNDECORATED))) {
522 /* allow conky to hold input focus. */
525 /* forward the release to the desktop ctx->window */
526 ev.xbutton.window = ctx->window.desktop;
527 ev.xbutton.x = ev.xbutton.x_root;
528 ev.xbutton.y = ev.xbutton.y_root;
529 XSendEvent(display, ev.xbutton.window, False,
530 ButtonReleaseMask, &ev);
539 if (ev.type == ctx->window.event_base + XDamageNotify) {
540 XDamageNotifyEvent *dev = (XDamageNotifyEvent *) &ev;
542 XFixesSetRegion(display, ctx->window.part, &dev->area, 1);
543 XFixesUnionRegion(display, ctx->window.region2, ctx->window.region2, ctx->window.part);
545 #endif /* HAVE_XDAMAGE */
551 XDamageSubtract(display, ctx->window.damage, ctx->window.region2, None);
552 XFixesSetRegion(display, ctx->window.region2, 0, 0);
553 #endif /* HAVE_XDAMAGE */
555 /* XDBE doesn't seem to provide a way to clear the back buffer
556 * without interfering with the front buffer, other than passing
557 * XdbeBackground to XdbeSwapBuffers. That means that if we're
558 * using XDBE, we need to redraw the text even if it wasn't part of
559 * the exposed area. OTOH, if we're not going to call draw_stuff at
560 * all, then no swap happens and we can safely do nothing. */
562 if (!XEmptyRegion(ctx->window.region)) {
567 r.x = ctx->text_start_x - ctx->window.border_inner_margin - ctx->window.border_outer_margin - ctx->window.border_width;
568 r.y = ctx->text_start_y - ctx->window.border_inner_margin - ctx->window.border_outer_margin - ctx->window.border_width;
569 r.width = ctx->text_width + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2;
570 r.height = ctx->text_height + ctx->window.border_inner_margin * 2 + ctx->window.border_outer_margin * 2 + ctx->window.border_width * 2;
571 XUnionRectWithRegion(&r, ctx->window.region, ctx->window.region);
574 XSetRegion(display, ctx->window.gc, ctx->window.region);
577 XftDrawSetClip(ctx->window.xftdraw, ctx->window.region);
581 XDestroyRegion(ctx->window.region);
582 ctx->window.region = XCreateRegion();
586 t = (ctx->next_update_time - get_time()) * 1000000;
587 if(t > 0) usleep((useconds_t)t);
591 if(ctx->output_methods & TO_NCURSES) {
600 #ifdef SIGNAL_BLOCKING
601 /* unblock signals of interest and let handler fly */
602 if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
603 CRIT_ERR(NULL, NULL, "unable to sigprocmask()");
607 switch (g_signal_pending) {
610 NORM_ERR("received SIGHUP or SIGUSR1. reloading the config file.");
615 NORM_ERR("received SIGINT or SIGTERM to terminate. bye!");
618 if (ctx->output_methods & TO_X) {
619 XDestroyRegion(ctx->window.region);
620 ctx->window.region = NULL;
622 XDamageDestroy(display, ctx->window.damage);
623 XFixesDestroyRegion(display, ctx->window.region2);
624 XFixesDestroyRegion(display, ctx->window.part);
625 #endif /* HAVE_XDAMAGE */
631 if(ctx->overwrite_file) {
632 free(ctx->overwrite_file);
633 ctx->overwrite_file = 0;
635 if(ctx->append_file) {
636 free(ctx->append_file);
637 ctx->append_file = 0;
641 /* Reaching here means someone set a signal
642 * (SIGXXXX, signal_handler), but didn't write any code
644 * If you don't want to handle a signal, don't set a handler on
645 * it in the first place. */
646 if (g_signal_pending) {
647 NORM_ERR("ignoring signal (%d)", g_signal_pending);
651 #ifdef HAVE_SYS_INOTIFY_H
652 if (inotify_fd != -1 && inotify_config_wd == -1 && ctx->current_config != 0) {
653 inotify_config_wd = inotify_add_watch(inotify_fd,
657 if (inotify_fd != -1 && inotify_config_wd != -1 && ctx->current_config != 0) {
658 int len = 0, idx = 0;
660 struct timeval time_to_wait;
662 FD_ZERO(&descriptors);
663 FD_SET(inotify_fd, &descriptors);
665 time_to_wait.tv_sec = time_to_wait.tv_usec = 0;
667 select(inotify_fd + 1, &descriptors, NULL, NULL, &time_to_wait);
668 if (FD_ISSET(inotify_fd, &descriptors)) {
669 /* process inotify events */
670 len = read(inotify_fd, inotify_buff, INOTIFY_BUF_LEN);
671 while (len > 0 && idx < len) {
672 struct inotify_event *ev = (struct inotify_event *) &inotify_buff[idx];
673 if (ev->wd == inotify_config_wd && (ev->mask & IN_MODIFY || ev->mask & IN_IGNORED)) {
674 /* ctx->current_config should be reloaded */
675 NORM_ERR("'%s' modified, reloading...", ctx->current_config);
677 if (ev->mask & IN_IGNORED) {
678 /* for some reason we get IN_IGNORED here
679 * sometimes, so we need to re-add the watch */
680 inotify_config_wd = inotify_add_watch(inotify_fd,
687 llua_inotify_query(ev->wd, ev->mask);
689 #endif /* HAVE_LUA */
690 idx += INOTIFY_EVENT_SIZE + ev->len;
694 #endif /* HAVE_SYS_INOTIFY_H */
697 llua_update_info(ctx, ctx->update_interval);
698 #endif /* HAVE_LUA */
699 g_signal_pending = 0;
701 clean_up(ctx, NULL, NULL);
703 #ifdef HAVE_SYS_INOTIFY_H
704 if (inotify_fd != -1) {
705 inotify_rm_watch(inotify_fd, inotify_config_wd);
707 inotify_fd = inotify_config_wd = 0;
709 #endif /* HAVE_SYS_INOTIFY_H */
712 static void print_help(const char *prog_name) {
713 printf("Usage: %s [OPTION]...\n"
714 PACKAGE_NAME" is a system monitor that renders text on desktop or to own transparent\n"
715 "ctx->window. Command line options will override configurations defined in config\n"
717 " -v, --version version\n"
718 " -q, --quiet quiet mode\n"
719 " -D, --debug increase debugging output, ie. -DD for more debugging\n"
720 " -c, --config=FILE config file to load\n"
722 " -C, --print-config print the builtin default config to stdout\n"
723 " e.g. 'conky -C > ~/.conkyrc' will create a new default config\n"
725 " -d, --daemonize daemonize, fork to background\n"
728 " -a, --alignment=ALIGNMENT text alignment on screen, {top,bottom,middle}_{left,right,middle}\n"
729 " -f, --font=FONT font to use\n"
730 " -X, --display=DISPLAY X11 display to use\n"
732 " -o, --own-ctx->window create own ctx->window to draw\n"
735 " -b, --double-buffer double buffer (prevents flickering)\n"
737 " -w, --ctx->window-id=WIN_ID ctx->window id to draw\n"
741 " -t, --text=TEXT text to render, remember single quotes, like -t '$uptime'\n"
742 " -u, --interval=SECS update interval\n"
743 " -i COUNT number of times to update "PACKAGE_NAME" (and quit)\n",
748 /* : means that character before that takes an argument */
749 static const char *getopt_string = "vVqdDt:u:i:hc:"
764 static const struct option longopts[] = {
765 { "help", 0, NULL, 'h' },
766 { "version", 0, NULL, 'V' },
767 { "debug", 0, NULL, 'D' },
768 { "config", 1, NULL, 'c' },
770 { "print-config", 0, NULL, 'C' },
772 { "daemonize", 0, NULL, 'd' },
774 { "alignment", 1, NULL, 'a' },
775 { "font", 1, NULL, 'f' },
776 { "display", 1, NULL, 'X' },
778 { "own-ctx->window", 0, NULL, 'o' },
781 { "double-buffer", 0, NULL, 'b' },
783 { "ctx->window-id", 1, NULL, 'w' },
785 { "text", 1, NULL, 't' },
786 { "interval", 0, NULL, 'u' },
790 void initialisation(conky_context *ctx, int argc, char **argv)
792 struct sigaction act, oact;
794 set_default_configurations(ctx);
795 load_config_file(ctx, ctx->current_config);
796 currentconffile = conftree_add(currentconffile, ctx->current_config);
798 /* init specials array */
799 if ((specials = calloc(sizeof(struct special_t), max_specials)) == 0) {
800 NORM_ERR("failed to create specials array");
804 if (current_mail_spool == NULL) {
807 variable_substitute(MAIL_FILE, buf, 256);
809 if (buf[0] != '\0') {
810 current_mail_spool = strndup(buf, text_buffer_size);
815 /* handle other command line arguments */
817 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) \
818 || defined(__NetBSD__)
819 optind = optreset = 1;
824 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
825 if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY,
826 "kvm_open")) == NULL) {
827 CRIT_ERR(NULL, NULL, "cannot read kvm");
832 int c = getopt_long(argc, argv, getopt_string, longopts, NULL);
840 ctx->fork_to_background = 1;
843 global_debug_level++;
847 set_first_font(ctx, optarg);
850 ctx->text_alignment = string_to_alignment(optarg);
865 if (ctx->global_text) {
866 free(ctx->global_text);
867 ctx->global_text = 0;
869 ctx->global_text = strndup(optarg, ctx->max_user_text);
870 convert_escapes(ctx->global_text);
874 ctx->update_interval = strtod(optarg, 0);
875 ctx->update_interval_old = ctx->update_interval;
876 if (ctx->info.music_player_interval == 0) {
877 // default to ctx->update_interval
878 ctx->info.music_player_interval = ctx->update_interval;
883 ctx->total_run_times = strtod(optarg, 0);
887 ctx->gap_x = atoi(optarg);
891 ctx->gap_y = atoi(optarg);
902 if (ctx->output_methods & TO_X) {
903 load_config_file_x11(ctx, ctx->current_config);
907 /* generate text and get initial size */
908 extract_variable_text(ctx, ctx->global_text);
909 if (ctx->global_text) {
910 free(ctx->global_text);
911 ctx->global_text = 0;
913 ctx->global_text = NULL;
915 if (ctx->fork_to_background) {
920 NORM_ERR(PACKAGE_NAME": couldn't fork() to background: %s",
927 fprintf(stderr, "\n");
933 fprintf(stderr, PACKAGE_NAME": forked to background, pid is %d\n",
940 ctx->text_buffer = malloc(ctx->max_user_text);
941 memset(ctx->text_buffer, 0, ctx->max_user_text);
942 ctx->tmpstring1 = malloc(text_buffer_size);
943 memset(ctx->tmpstring1, 0, text_buffer_size);
944 ctx->tmpstring2 = malloc(text_buffer_size);
945 memset(ctx->tmpstring2, 0, text_buffer_size);
950 X11_create_window(ctx);
953 llua_setup_info(ctx, ctx->update_interval);
954 #endif /* HAVE_LUA */
959 /* Set signal handlers */
960 act.sa_handler = signal_handler;
961 sigemptyset(&act.sa_mask);
964 act.sa_flags |= SA_RESTART;
967 if ( sigaction(SIGINT, &act, &oact) < 0
968 || sigaction(SIGALRM, &act, &oact) < 0
969 || sigaction(SIGUSR1, &act, &oact) < 0
970 || sigaction(SIGHUP, &act, &oact) < 0
971 || sigaction(SIGTERM, &act, &oact) < 0) {
972 NORM_ERR("error setting signal handler: %s", strerror(errno));
977 #endif /* HAVE_LUA */
980 int main(int argc, char **argv)
982 /* Conky's main context struct */
984 conky_context *ctx = &mctx;
993 g_signal_pending = 0;
994 memset(ctx, 0, sizeof(conky_context));
995 ctx->max_user_text = MAX_USER_TEXT_DEFAULT;
998 #ifdef TCP_PORT_MONITOR
999 /* set default connection limit */
1000 tcp_portmon_set_max_connections(0);
1003 /* handle command line parameters that don't change configs */
1005 if (((s = getenv("LC_ALL")) && *s) || ((s = getenv("LC_CTYPE")) && *s)
1006 || ((s = getenv("LANG")) && *s)) {
1007 temp = (char *) malloc((strlen(s) + 1) * sizeof(char));
1009 NORM_ERR("malloc failed");
1011 for (x = 0; x < strlen(s); x++) {
1012 temp[x] = tolower(s[x]);
1015 if (strstr(temp, "utf-8") || strstr(temp, "utf8")) {
1021 if (!setlocale(LC_CTYPE, "")) {
1022 NORM_ERR("Can't set the specified locale!\nCheck LANG, LC_CTYPE, LC_ALL.");
1026 int c = getopt_long(argc, argv, getopt_string, longopts, NULL);
1037 if (ctx->current_config) {
1038 free(ctx->current_config);
1040 ctx->current_config = strndup(optarg, ctx->max_user_text);
1043 freopen("/dev/null", "w", stderr);
1046 print_help(argv[0]);
1048 #ifdef CONFIG_OUTPUT
1055 ctx->window.window = strtol(optarg, 0, 0);
1060 ctx->disp = strdup(optarg);
1069 /* check if specified config file is valid */
1070 if (ctx->current_config) {
1072 if (stat(ctx->current_config, &sb) ||
1073 (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) {
1074 NORM_ERR("invalid configuration file '%s'\n", ctx->current_config);
1075 free(ctx->current_config);
1076 ctx->current_config = 0;
1080 /* load ctx->current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */
1082 if (!ctx->current_config) {
1083 /* load default config file */
1084 char buf[DEFAULT_TEXT_BUFFER_SIZE];
1087 /* Try to use personal config file first */
1088 to_real_path(buf, CONFIG_FILE);
1089 if (buf[0] && (fp = fopen(buf, "r"))) {
1090 ctx->current_config = strndup(buf, ctx->max_user_text);
1094 /* Try to use system config file if personal config not readable */
1095 if (!ctx->current_config && (fp = fopen(SYSTEM_CONFIG_FILE, "r"))) {
1096 ctx->current_config = strndup(SYSTEM_CONFIG_FILE, ctx->max_user_text);
1100 /* No readable config found */
1101 if (!ctx->current_config) {
1102 #ifdef CONFIG_OUTPUT
1103 ctx->current_config = strdup("==builtin==");
1104 NORM_ERR("no readable personal or system-wide config file found,"
1105 " using builtin default");
1107 CRIT_ERR(NULL, NULL, "no readable personal or system-wide config file found");
1108 #endif /* ! CONF_OUTPUT */
1113 /* Load xoap keys, if existing */
1117 #ifdef HAVE_SYS_INOTIFY_H
1118 inotify_fd = inotify_init();
1119 #endif /* HAVE_SYS_INOTIFY_H */
1121 initialisation(&mctx, argc, argv);
1125 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1133 static void signal_handler(int sig)
1135 /* signal handler is light as a feather, as it should be. we will poll
1136 * g_signal_pending with each loop of conky and do any signal processing
1137 * there, NOT here */
1138 g_signal_pending = sig;