]> git.sur5r.net Git - i3/i3status/blobdiff - i3status.c
Implement %essid and %signal for wireless on OpenBSD.
[i3/i3status] / i3status.c
index 523ba7ebd10d174e87edd6bd9bb3426890184820..915cbccdb33be9f72fd73754c4fae51033bb42ae 100644 (file)
@@ -3,7 +3,7 @@
  *
  * i3status – Generates a status line for dzen2 or xmobar
  *
- * Copyright © 2008-2011 Michael Stapelberg and contributors
+ * Copyright © 2008-2012 Michael Stapelberg and contributors
  * Copyright © 2009 Thorsten Toepper <atsutane at freethoughts dot de>
  * Copyright © 2010 Axel Wagner <mail at merovius dot de>
  * Copyright © 2010 Fernando Tarlá Cardoso Lemos <fernandotcl at gmail dot com>
@@ -28,6 +28,9 @@
 #include <sys/time.h>
 #include <locale.h>
 
+#include <yajl/yajl_gen.h>
+#include <yajl/yajl_version.h>
+
 #include "i3status.h"
 
 #define exit_if_null(pointer, ...) { if (pointer == NULL) die(__VA_ARGS__); }
@@ -110,14 +113,15 @@ static char *resolve_tilde(const char *path) {
                 head = globbuf.gl_pathv[0];
                 result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1);
                 strncpy(result, head, strlen(head));
-                strncat(result, tail, strlen(tail));
+                if (tail)
+                        strncat(result, tail, strlen(tail));
         }
         globfree(&globbuf);
 
         return result;
 }
 
-static char *get_config_path() {
+static char *get_config_path(void) {
         char *xdg_config_home, *xdg_config_dirs, *config_path;
 
         /* 1: check the traditional path under the home directory */
@@ -164,8 +168,8 @@ static char *get_config_path() {
         free(buf);
 
         die("Unable to find the configuration file (looked at "
-                "~/.i3status/config, $XDG_CONFIG_HOME/i3status/config, "
-                "/etc/i3status/config and $XDG_CONFIG_DIRS/i3status/config)");
+                "~/.i3status.conf, $XDG_CONFIG_HOME/i3status/config, "
+                "/etc/i3status.conf and $XDG_CONFIG_DIRS/i3status/config)");
         return NULL;
 }
 
@@ -209,6 +213,9 @@ int main(int argc, char *argv[]) {
 
         cfg_opt_t battery_opts[] = {
                 CFG_STR("format", "%status %percentage %remaining", CFGF_NONE),
+                CFG_STR("path", "/sys/class/power_supply/BAT%d/uevent", CFGF_NONE),
+                CFG_INT("low_threshold", 30, CFGF_NONE),
+                CFG_STR("threshold_type", "time", CFGF_NONE),
                 CFG_BOOL("last_full_capacity", false, CFGF_NONE),
                 CFG_END()
         };
@@ -291,11 +298,11 @@ int main(int argc, char *argv[]) {
                 if ((char)o == 'c')
                         configfile = optarg;
                 else if ((char)o == 'h') {
-                        printf("i3status " VERSION " © 2008-2011 Michael Stapelberg and contributors\n"
+                        printf("i3status " VERSION " © 2008-2012 Michael Stapelberg and contributors\n"
                                 "Syntax: %s [-c <configfile>] [-h] [-v]\n", argv[0]);
                         return 0;
                 } else if ((char)o == 'v') {
-                        printf("i3status " VERSION " © 2008-2011 Michael Stapelberg and contributors\n");
+                        printf("i3status " VERSION " © 2008-2012 Michael Stapelberg and contributors\n");
                         return 0;
                 }
 
@@ -330,6 +337,8 @@ int main(int argc, char *argv[]) {
                 output_format = O_DZEN2;
         else if (strcasecmp(output_str, "xmobar") == 0)
                 output_format = O_XMOBAR;
+        else if (strcasecmp(output_str, "i3bar") == 0)
+                output_format = O_I3BAR;
         else if (strcasecmp(output_str, "none") == 0)
                 output_format = O_NONE;
         else die("Unknown output format: \"%s\"\n", output_str);
@@ -340,11 +349,34 @@ int main(int argc, char *argv[]) {
                         || !valid_color(cfg_getstr(cfg_general, "color_separator")))
                die("Bad color format");
 
+#if YAJL_MAJOR >= 2
+        yajl_gen json_gen = yajl_gen_alloc(NULL);
+#else
+        yajl_gen json_gen = yajl_gen_alloc(NULL, NULL);
+#endif
+
+        if (output_format == O_I3BAR) {
+                /* Initialize the i3bar protocol. See i3/docs/i3bar-protocol
+                 * for details. */
+                printf("{\"version\":1}\n[\n");
+                fflush(stdout);
+                yajl_gen_array_open(json_gen);
+                yajl_gen_clear(json_gen);
+        }
+
         if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                 die("Could not create socket\n");
 
         int interval = cfg_getint(cfg_general, "interval");
 
+        /* One memory page which each plugin can use to buffer output.
+         * Even though it’s unclean, we just assume that the user will not
+         * specify a format string which expands to something longer than 4096
+         * bytes — given that the output of i3status is used to display
+         * information on screen, more than 1024 characters for the full line
+         * (!), not individual plugins, seem very unlikely. */
+        char buffer[4096];
+
         struct tm tm;
         while (1) {
                 struct timeval tv;
@@ -355,51 +387,102 @@ int main(int argc, char *argv[]) {
                         localtime_r(&current_time, &tm);
                         current_tm = &tm;
                 }
+                if (output_format == O_I3BAR)
+                        yajl_gen_array_open(json_gen);
                 for (j = 0; j < cfg_size(cfg, "order"); j++) {
                         if (j > 0)
                                 print_seperator();
 
                         const char *current = cfg_getnstr(cfg, "order", j);
 
-                        CASE_SEC("ipv6")
-                                print_ipv6_info(cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
-
-                        CASE_SEC_TITLE("wireless")
-                                print_wireless_info(title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
-
-                        CASE_SEC_TITLE("ethernet")
-                                print_eth_info(title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
-
-                        CASE_SEC_TITLE("battery")
-                                print_battery_info(atoi(title), cfg_getstr(sec, "format"), cfg_getbool(sec, "last_full_capacity"));
-
-                        CASE_SEC_TITLE("run_watch")
-                                print_run_watch(title, cfg_getstr(sec, "pidfile"), cfg_getstr(sec, "format"));
-
-                        CASE_SEC_TITLE("disk")
-                                print_disk_info(title, cfg_getstr(sec, "format"));
-
-                        CASE_SEC("load")
-                                print_load(cfg_getstr(sec, "format"));
-
-                        CASE_SEC("time")
-                                print_time(cfg_getstr(sec, "format"), current_tm);
-
-                        CASE_SEC("ddate")
-                                print_ddate(cfg_getstr(sec, "format"), current_tm);
-
-                        CASE_SEC_TITLE("volume")
-                                print_volume(cfg_getstr(sec, "format"),
+                        CASE_SEC("ipv6") {
+                                SEC_OPEN_MAP("ipv6");
+                                print_ipv6_info(json_gen, buffer, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("wireless") {
+                                SEC_OPEN_MAP("wireless");
+                                print_wireless_info(json_gen, buffer, title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("ethernet") {
+                                SEC_OPEN_MAP("ethernet");
+                                print_eth_info(json_gen, buffer, title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("battery") {
+                                SEC_OPEN_MAP("battery");
+                                print_battery_info(json_gen, buffer, atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format"), cfg_getint(sec, "low_threshold"), cfg_getstr(sec, "threshold_type"), cfg_getbool(sec, "last_full_capacity"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("run_watch") {
+                                SEC_OPEN_MAP("run_watch");
+                                print_run_watch(json_gen, buffer, title, cfg_getstr(sec, "pidfile"), cfg_getstr(sec, "format"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("disk") {
+                                SEC_OPEN_MAP("disk_info");
+                                print_disk_info(json_gen, buffer, title, cfg_getstr(sec, "format"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC("load") {
+                                SEC_OPEN_MAP("load");
+                                print_load(json_gen, buffer, cfg_getstr(sec, "format"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC("time") {
+                                SEC_OPEN_MAP("time");
+                                print_time(json_gen, buffer, cfg_getstr(sec, "format"), current_tm);
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC("ddate") {
+                                SEC_OPEN_MAP("ddate");
+                                print_ddate(json_gen, buffer, cfg_getstr(sec, "format"), current_tm);
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("volume") {
+                                SEC_OPEN_MAP("volume");
+                                print_volume(json_gen, buffer, cfg_getstr(sec, "format"),
                                              cfg_getstr(sec, "device"),
                                              cfg_getstr(sec, "mixer"),
                                              cfg_getint(sec, "mixer_idx"));
-
-                        CASE_SEC_TITLE("cpu_temperature")
-                                print_cpu_temperature_info(atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format"));
-
-                        CASE_SEC("cpu_usage")
-                                print_cpu_usage(cfg_getstr(sec, "format"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC_TITLE("cpu_temperature") {
+                                SEC_OPEN_MAP("cpu_temperature");
+                                print_cpu_temperature_info(json_gen, buffer, atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format"));
+                                SEC_CLOSE_MAP;
+                        }
+
+                        CASE_SEC("cpu_usage") {
+                                SEC_OPEN_MAP("cpu_usage");
+                                print_cpu_usage(json_gen, buffer, cfg_getstr(sec, "format"));
+                                SEC_CLOSE_MAP;
+                        }
                 }
+                if (output_format == O_I3BAR) {
+                        yajl_gen_array_close(json_gen);
+                        const unsigned char *buf;
+#if YAJL_MAJOR >= 2
+                        size_t len;
+#else
+                        unsigned int len;
+#endif
+                        yajl_gen_get_buf(json_gen, &buf, &len);
+                        write(STDOUT_FILENO, buf, len);
+                        yajl_gen_clear(json_gen);
+                }
+
                 printf("\n");
                 fflush(stdout);