CPPFLAGS+=-DVERSION=\"${GIT_VERSION}\"
CFLAGS+=-Iinclude
LIBS+=-lconfuse
+LIBS+=-lyajl
VERSION:=$(shell git describe --tags --abbrev=0)
GIT_VERSION:="$(shell git describe --tags --always) ($(shell git log --pretty=format:%cd --date=short -n1))"
Priority: extra
Maintainer: Michael Stapelberg <michael@stapelberg.de>
DM-Upload-Allowed: yes
-Build-Depends: debhelper (>= 5), libiw-dev [linux-any], libconfuse-dev, asciidoc, xmlto, libcap2-bin [linux-any], libasound2-dev [linux-any], libbsd-dev [kfreebsd-any]
+Build-Depends: debhelper (>= 5), libiw-dev [linux-any], libconfuse-dev, asciidoc, xmlto, libcap2-bin [linux-any], libasound2-dev [linux-any], libbsd-dev [kfreebsd-any], libyajl-dev
Standards-Version: 3.9.2
Homepage: http://i3wm.org/i3status
#include <sys/time.h>
#include <locale.h>
+#include <yajl/yajl_gen.h>
+
#include "i3status.h"
#define exit_if_null(pointer, ...) { if (pointer == NULL) die(__VA_ARGS__); }
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);
|| !valid_color(cfg_getstr(cfg_general, "color_separator")))
die("Bad color format");
+ yajl_gen json_gen = yajl_gen_alloc(NULL);
+
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)
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;
current_tm = &tm;
}
if (output_format == O_I3BAR)
- printf("[");
+ 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, "path"), 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_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)
- printf("],");
+ if (output_format == O_I3BAR) {
+ yajl_gen_array_close(json_gen);
+ const unsigned char *buf;
+ size_t len;
+ yajl_gen_get_buf(json_gen, &buf, &len);
+ write(STDOUT_FILENO, buf, len);
+ yajl_gen_clear(json_gen);
+ }
+
printf("\n");
fflush(stdout);
#include <stdbool.h>
#include <confuse.h>
#include <time.h>
+#include <yajl/yajl_gen.h>
+#include <unistd.h>
+#include <string.h>
#define BEGINS_WITH(haystack, needle) (strncmp(haystack, needle, strlen(needle)) == 0)
#define max(a, b) ((a) > (b) ? (a) : (b))
with(cfg_t *, sec, cfg_gettsec(cfg, name, title)) \
if (sec != NULL)
+/* Macro which any plugin can use to output the full_text part (when the output
+ * format is JSON) or just output to stdout (any other output format). */
+#define OUTPUT_FULL_TEXT(text) \
+ do { \
+ /* Terminate the output buffer here in any case, so that it’s \
+ * not forgotten in the module */ \
+ *outwalk = '\0'; \
+ if (output_format == O_I3BAR) { \
+ yajl_gen_string(json_gen, (const unsigned char *)"full_text", strlen("full_text")); \
+ yajl_gen_string(json_gen, (const unsigned char *)text, strlen(text)); \
+ } else { \
+ write(STDOUT_FILENO, text, strlen(text)); \
+ } \
+ } while (0)
+
+#define SEC_OPEN_MAP(name) \
+ do { \
+ if (output_format == O_I3BAR) { \
+ yajl_gen_map_open(json_gen); \
+ yajl_gen_string(json_gen, (const unsigned char *)"name", strlen("name")); \
+ yajl_gen_string(json_gen, (const unsigned char *)name, strlen(name)); \
+ } \
+ } while (0)
+
+#define SEC_CLOSE_MAP \
+ do { \
+ if (output_format == O_I3BAR) { \
+ yajl_gen_map_close(json_gen); \
+ } \
+ } while (0)
+
+#define START_COLOR(colorstr) \
+ do { \
+ if (cfg_getbool(cfg_general, "colors")) { \
+ const char *val = cfg_getstr(cfg_general, colorstr); \
+ if (output_format == O_I3BAR) { \
+ yajl_gen_string(json_gen, (const unsigned char *)"color", strlen("color")); \
+ yajl_gen_string(json_gen, (const unsigned char *)val, strlen(val)); \
+ } else { \
+ outwalk += sprintf(outwalk, "%s", color("color_bad")); \
+ } \
+ } \
+ } while (0)
+
+#define END_COLOR \
+ do { \
+ if (cfg_getbool(cfg_general, "colors") && output_format != O_I3BAR) { \
+ outwalk += sprintf(outwalk, "%s", endcolor()); \
+ } \
+ } while (0)
+
+#define INSTANCE(instance) \
+ do { \
+ if (output_format == O_I3BAR) { \
+ yajl_gen_string(json_gen, (const unsigned char *)"instance", strlen("instance")); \
+ yajl_gen_string(json_gen, (const unsigned char *)instance, strlen(instance)); \
+ } \
+ } while (0)
+
typedef enum { CS_DISCHARGING, CS_CHARGING, CS_FULL } charging_status_t;
/* src/auto_detect_format.c */
char *auto_detect_format();
-void print_ipv6_info(const char *format_up, const char *format_down);
-void print_disk_info(const char *path, const char *format);
-void print_battery_info(int number, const char *path, const char *format, bool last_full_capacity);
-void print_time(const char *format, struct tm *current_tm);
-void print_ddate(const char *format, struct tm *current_tm);
+void print_ipv6_info(yajl_gen json_gen, char *buffer, const char *format_up, const char *format_down);
+void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format);
+void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, bool last_full_capacity);
+void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
const char *get_ip_addr();
-void print_wireless_info(const char *interface, const char *format_up, const char *format_down);
-void print_run_watch(const char *title, const char *pidfile, const char *format);
-void print_cpu_temperature_info(int zone, const char *path, const char *format);
-void print_cpu_usage(const char *format);
-void print_eth_info(const char *interface, const char *format_up, const char *format_down);
-void print_load();
-void print_volume(const char *fmt, const char *device, const char *mixer, int mixer_idx);
+void print_wireless_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
+void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const char *pidfile, const char *format);
+void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const char *path, const char *format);
+void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format);
+void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
+void print_load(yajl_gen json_gen, char *buffer, const char *format);
+void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *device, const char *mixer, int mixer_idx);
bool process_runs(const char *path);
/* socket file descriptor for general purposes */
(void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", cfg_getstr(cfg_general, colorstr));
else if (output_format == O_XMOBAR)
(void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", cfg_getstr(cfg_general, colorstr));
- else if (output_format == O_I3BAR)
- (void)snprintf(colorbuf, sizeof(colorbuf), "\"color\":\"%s\", ", cfg_getstr(cfg_general, colorstr));
return colorbuf;
}
printf("^fg(%s)^p(5;-2)^ro(2)^p()^fg()^p(5)", cfg_getstr(cfg_general, "color_separator"));
else if (output_format == O_XMOBAR)
printf("<fc=%s> | </fc>", cfg_getstr(cfg_general, "color_separator"));
- else if (output_format == O_I3BAR)
- printf(", ");
else if (output_format == O_NONE)
printf(" | ");
}
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <yajl/yajl_gen.h>
#include "i3status.h"
* worn off your battery is.
*
*/
-void print_battery_info(int number, const char *path, const char *format, bool last_full_capacity) {
+void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, bool last_full_capacity) {
time_t empty_time;
struct tm *empty_tm;
char buf[1024];
char remainingbuf[256];
char emptytimebuf[256];
const char *walk, *last;
+ char *outwalk = buffer;
int full_design = -1,
remaining = -1,
present_rate = -1;
memset(remainingbuf, '\0', sizeof(remainingbuf));
memset(emptytimebuf, '\0', sizeof(emptytimebuf));
- if (output_format == O_I3BAR)
- printf("{\"name\":\"battery\", \"instance\": \"%s\", \"full_text\":\"", path);
+ INSTANCE(path);
#if defined(LINUX)
static char batpath[512];
sprintf(batpath, path, number);
if (!slurp(batpath, buf, sizeof(buf))) {
- printf("No battery");
+ OUTPUT_FULL_TEXT("No battery");
return;
}
for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (strncmp(walk+1, "status", strlen("status")) == 0) {
- printf("%s", statusbuf);
+ outwalk += sprintf(outwalk, "%s", statusbuf);
walk += strlen("status");
} else if (strncmp(walk+1, "percentage", strlen("percentage")) == 0) {
- printf("%s", percentagebuf);
+ outwalk += sprintf(outwalk, "%s", percentagebuf);
walk += strlen("percentage");
} else if (strncmp(walk+1, "remaining", strlen("remaining")) == 0) {
- printf("%s", remainingbuf);
+ outwalk += sprintf(outwalk, "%s", remainingbuf);
walk += strlen("remaining");
} else if (strncmp(walk+1, "emptytime", strlen("emptytime")) == 0) {
- printf("%s", emptytimebuf);
+ outwalk += sprintf(outwalk, "%s", emptytimebuf);
walk += strlen("emptytime");
}
}
- if (output_format == O_I3BAR)
- printf("\"}");
+ OUTPUT_FULL_TEXT(buffer);
}
#include <limits.h>
#include <stdio.h>
#include <string.h>
+#include <yajl/yajl_gen.h>
#include "i3status.h"
* returns the temperature in degree celcius.
*
*/
-void print_cpu_temperature_info(int zone, const char *path, const char *format) {
+void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const char *path, const char *format) {
#ifdef THERMAL_ZONE
const char *walk;
+ char *outwalk = buffer;
static char buf[16];
if (path == NULL) {
path = thermal_zone;
}
- if (output_format == O_I3BAR)
- printf("{\"name\":\"cpu_temperature\", \"instance\": \"%s\", \"full_text\":\"", path);
+ INSTANCE(path);
for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
goto error;
temp = strtol(buf, NULL, 10);
if (temp == LONG_MIN || temp == LONG_MAX || temp <= 0)
- (void)printf("?");
+ *(outwalk++) = '?';
else
- (void)printf("%ld", (temp/1000));
+ outwalk += sprintf(outwalk, "%ld", (temp/1000));
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
int sysctl_rslt;
size_t sysctl_size = sizeof(sysctl_rslt);
if (sysctlbyname(path, &sysctl_rslt, &sysctl_size, NULL, 0))
goto error;
- (void)printf("%d.%d", TZ_KELVTOC(sysctl_rslt));
+ outwalk += sprintf(outwalk, "%d.%d", TZ_KELVTOC(sysctl_rslt));
#endif
walk += strlen("degrees");
}
}
- if (output_format == O_I3BAR)
- printf("\"}");
-
+ OUTPUT_FULL_TEXT(buffer);
return;
error:
#endif
#include <limits.h>
#include <stdio.h>
#include <string.h>
+#include <yajl/yajl_gen.h>
#ifdef __FreeBSD__
#include <sys/types.h>
* percentage.
*
*/
-void print_cpu_usage(const char *format) {
+void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format) {
const char *walk;
+ char *outwalk = buffer;
char buf[1024];
int curr_user = 0, curr_nice = 0, curr_system = 0, curr_idle = 0, curr_total;
int diff_idle, diff_total, diff_usage;
- if (output_format == O_I3BAR)
- printf("{\"name\":\"cpu_usage\", \"full_text\":\"");
-
#if defined(LINUX)
static char statpath[512];
strcpy(statpath, "/proc/stat");
#endif
for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (strncmp(walk+1, "usage", strlen("usage")) == 0) {
- printf("%02d%%", diff_usage);
+ outwalk += sprintf(outwalk, "%02d%%", diff_usage);
walk += strlen("usage");
}
}
- if (output_format == O_I3BAR)
- printf("\"}");
-
+ OUTPUT_FULL_TEXT(buffer);
return;
error:
(void)fputs("Cannot read usage\n", stderr);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <yajl/yajl_gen.h>
#include "i3status.h"
};
/* Print the date *dt in format *format */
-int format_output(char *format, struct disc_time *dt) {
+static int format_output(char *outwalk, char *format, struct disc_time *dt) {
+ char *orig_outwalk = outwalk;
char *i;
char *tibs_end = 0;
for (i = format; *i != '\0'; i++) {
if (*i != '%') {
- putchar(*i);
+ *(outwalk++) = *i;
continue;
}
switch (*(i+1)) {
/* Weekday in long and abbreviation */
case 'A':
- printf("%s", day_long[dt->week_day]);
+ outwalk += sprintf(outwalk, "%s", day_long[dt->week_day]);
break;
case 'a':
- printf("%s", day_short[dt->week_day]);
+ outwalk += sprintf(outwalk, "%s", day_short[dt->week_day]);
break;
/* Season in long and abbreviation */
case 'B':
- printf("%s", season_long[dt->season]);
+ outwalk += sprintf(outwalk, "%s", season_long[dt->season]);
break;
case 'b':
- printf("%s", season_short[dt->season]);
+ outwalk += sprintf(outwalk, "%s", season_short[dt->season]);
break;
/* Day of the season (ordinal and cardinal) */
case 'd':
- printf("%d", dt->season_day + 1);
+ outwalk += sprintf(outwalk, "%d", dt->season_day + 1);
break;
case 'e':
- printf("%d", dt->season_day + 1);
+ outwalk += sprintf(outwalk, "%d", dt->season_day + 1);
switch (dt->season_day) {
case 0:
- printf("st");
+ outwalk += sprintf(outwalk, "st");
break;
case 1:
- printf("nd");
+ outwalk += sprintf(outwalk, "nd");
break;
case 2:
- printf("rd");
+ outwalk += sprintf(outwalk, "rd");
break;
default:
- printf("th");
+ outwalk += sprintf(outwalk, "th");
break;
}
break;
/* YOLD */
case 'Y':
- printf("%d", dt->year);
+ outwalk += sprintf(outwalk, "%d", dt->year);
break;
/* Holidays */
case 'H':
if (dt->season_day == 4) {
- printf(holidays[dt->season]);
+ outwalk += sprintf(outwalk, holidays[dt->season]);
}
if (dt->season_day == 49) {
- printf(holidays[dt->season + 5]);
+ outwalk += sprintf(outwalk, holidays[dt->season + 5]);
}
break;
/* Stop parsing the format string, except on Holidays */
case 'N':
if (dt->season_day != 4 && dt->season_day != 49) {
- return 0;
+ return (outwalk - orig_outwalk);
}
break;
/* Newline- and Tabbing-characters */
case 'n':
- printf("\n");
+ outwalk += sprintf(outwalk, "\n");
break;
case 't':
- printf("\t");
+ outwalk += sprintf(outwalk, "\t");
break;
/* The St. Tib's Day replacement */
case '{':
}
if (dt->st_tibs_day) {
/* We outpt "St. Tib's Day... */
- printf("St. Tib's Day");
+ outwalk += sprintf(outwalk, "St. Tib's Day");
} else {
/* ...or parse the substring between %{ and %} ... */
*tibs_end = '\0';
- if (!format_output(i + 2, dt)) return 0;
+ outwalk += format_output(outwalk, i + 2, dt);
*tibs_end = '%';
}
/* ...and continue with the rest */
break;
default:
/* No escape-sequence, so we just skip */
- printf("%%%c",*(i+1));
+ outwalk += sprintf(outwalk, "%%%c", *(i+1));
break;
}
i++;
}
- return 1;
+ return (outwalk - orig_outwalk);
}
/* Get the current date and convert it to discordian */
return &dt;
}
-void print_ddate(const char *format, struct tm *current_tm) {
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
+ char *outwalk = buffer;
static char *form = NULL;
struct disc_time *dt;
if ((dt = get_ddate(current_tm)) == NULL)
if (form == NULL)
if ((form = malloc(strlen(format) + 1)) == NULL)
return;
- if (output_format == O_I3BAR)
- printf("{\"name\":\"ddate\", \"full_text\":\"");
strcpy(form, format);
- format_output(form, dt);
- if (output_format == O_I3BAR)
- printf("\"}");
+ outwalk += format_output(outwalk, form, dt);
+ OUTPUT_FULL_TEXT(buffer);
}
#include <sys/param.h>
#include <sys/mount.h>
#endif
-
+#include <yajl/yajl_gen.h>
#include "i3status.h"
* Prints the given amount of bytes in a human readable manner.
*
*/
-static void print_bytes_human(uint64_t bytes) {
+static int print_bytes_human(char *outwalk, uint64_t bytes) {
if (bytes > TERABYTE)
- printf("%.02f TB", (double)bytes / TERABYTE);
+ return sprintf(outwalk, "%.02f TB", (double)bytes / TERABYTE);
else if (bytes > GIGABYTE)
- printf("%.01f GB", (double)bytes / GIGABYTE);
+ return sprintf(outwalk, "%.01f GB", (double)bytes / GIGABYTE);
else if (bytes > MEGABYTE)
- printf("%.01f MB", (double)bytes / MEGABYTE);
+ return sprintf(outwalk, "%.01f MB", (double)bytes / MEGABYTE);
else if (bytes > KILOBYTE)
- printf("%.01f KB", (double)bytes / KILOBYTE);
+ return sprintf(outwalk, "%.01f KB", (double)bytes / KILOBYTE);
else {
- printf("%.01f B", (double)bytes);
+ return sprintf(outwalk, "%.01f B", (double)bytes);
}
}
* human readable manner.
*
*/
-void print_disk_info(const char *path, const char *format) {
+void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format) {
const char *walk;
+ char *outwalk = buffer;
- if (output_format == O_I3BAR)
- printf("{\"name\":\"disk_info\", \"instance\": \"%s\", \"full_text\":\"", path);
+ INSTANCE(path);
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
struct statfs buf;
for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (BEGINS_WITH(walk+1, "free")) {
- print_bytes_human((uint64_t)buf.f_bsize * (uint64_t)buf.f_bfree);
+ outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * (uint64_t)buf.f_bfree);
walk += strlen("free");
}
if (BEGINS_WITH(walk+1, "used")) {
- print_bytes_human((uint64_t)buf.f_bsize * ((uint64_t)buf.f_blocks - (uint64_t)buf.f_bfree));
+ outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * ((uint64_t)buf.f_blocks - (uint64_t)buf.f_bfree));
walk += strlen("used");
}
if (BEGINS_WITH(walk+1, "total")) {
- print_bytes_human((uint64_t)buf.f_bsize * (uint64_t)buf.f_blocks);
+ outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * (uint64_t)buf.f_blocks);
walk += strlen("total");
}
if (BEGINS_WITH(walk+1, "avail")) {
- print_bytes_human((uint64_t)buf.f_bsize * (uint64_t)buf.f_bavail);
+ outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * (uint64_t)buf.f_bavail);
walk += strlen("avail");
}
}
- if (output_format == O_I3BAR)
- printf("\"}");
+ *outwalk = '\0';
+ OUTPUT_FULL_TEXT(buffer);
}
#endif
-static void print_eth_speed(const char *interface) {
+static int print_eth_speed(char *outwalk, const char *interface) {
#if defined(LINUX)
int ethspeed = 0;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
(void)strcpy(ifr.ifr_name, interface);
if (ioctl(general_socket, SIOCETHTOOL, &ifr) == 0) {
ethspeed = (ecmd.speed == USHRT_MAX ? 0 : ecmd.speed);
- printf("%d Mbit/s", ethspeed);
- } else printf("?");
+ return sprintf(outwalk, "%d Mbit/s", ethspeed);
+ } else return sprintf(outwalk, "?");
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
struct ifmediareq ifm;
(void)memset(&ifm, 0, sizeof(ifm));
break;
}
ethspeed = (desc->ifmt_string != NULL ? desc->ifmt_string : "?");
- printf("%s", ethspeed);
+ return sprintf(outwalk, "%s", ethspeed);
#endif
}
* Combines ethernet IP addresses and speed (if requested) for displaying
*
*/
-void print_eth_info(const char *interface, const char *format_up, const char *format_down) {
+void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down) {
const char *walk;
const char *ip_address = get_ip_addr(interface);
+ char *outwalk = buffer;
- if (output_format == O_I3BAR)
- printf("{\"name\":\"ethernet\", \"instance\": \"%s\", ", interface);
+ INSTANCE(interface);
if (ip_address == NULL) {
- printf("%s", color("color_bad"));
- printf("%s", format_down);
- (void)printf("%s", endcolor());
- return;
- } else {
- printf("%s", color("color_good"));
+ START_COLOR("color_bad");
+ outwalk += sprintf(outwalk, "%s", format_down);
+ goto out;
}
- if (output_format == O_I3BAR)
- printf("\"full_text\":\"");
+ START_COLOR("color_good");
for (walk = format_up; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (strncmp(walk+1, "ip", strlen("ip")) == 0) {
- printf("%s", ip_address);
+ outwalk += sprintf(outwalk, "%s", ip_address);
walk += strlen("ip");
} else if (strncmp(walk+1, "speed", strlen("speed")) == 0) {
- print_eth_speed(interface);
+ outwalk += print_eth_speed(outwalk, interface);
walk += strlen("speed");
}
}
- (void)printf("%s", endcolor());
-
- if (output_format == O_I3BAR)
- printf("\"}");
+out:
+ END_COLOR;
+ OUTPUT_FULL_TEXT(buffer);
}
if (ifaddr == NULL)
return NULL;
- addrp = ifaddr;
-
/* Skip until we are at the AF_INET address of interface */
for (addrp = ifaddr;
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
+#include <yajl/yajl_gen.h>
#include "i3status.h"
return NULL;
}
-void print_ipv6_info(const char *format_up, const char *format_down) {
+void print_ipv6_info(yajl_gen json_gen, char *buffer, const char *format_up, const char *format_down) {
const char *walk;
char *addr_string = get_ipv6_addr();
-
- if (output_format == O_I3BAR)
- printf("{\"name\":\"ipv6\", \"full_text\":\"");
+ char *outwalk = buffer;
if (addr_string == NULL) {
- printf("%s", format_down);
+ OUTPUT_FULL_TEXT(format_down);
return;
}
for (walk = format_up; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (strncmp(walk+1, "ip", strlen("ip")) == 0) {
- printf("%s", addr_string);
+ outwalk += sprintf(outwalk, "%s", addr_string);
walk += strlen("ip");
}
}
- if (output_format == O_I3BAR)
- printf("\"}");
+ OUTPUT_FULL_TEXT(buffer);
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <yajl/yajl_gen.h>
-void print_load(const char *format) {
-/* Get load */
- if (output_format == O_I3BAR)
- printf("{\"name\":\"load\", \"full_text\":\"");
+void print_load(yajl_gen json_gen, char *buffer, const char *format) {
+ char *outwalk = buffer;
+ /* Get load */
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(sun)
double loadavg[3];
for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (BEGINS_WITH(walk+1, "1min")) {
- (void)printf("%1.2f", loadavg[0]);
+ outwalk += sprintf(outwalk, "%1.2f", loadavg[0]);
walk += strlen("1min");
}
if (BEGINS_WITH(walk+1, "5min")) {
- (void)printf("%1.2f", loadavg[1]);
+ outwalk += sprintf(outwalk, "%1.2f", loadavg[1]);
walk += strlen("5min");
}
if (BEGINS_WITH(walk+1, "15min")) {
- (void)printf("%1.2f", loadavg[2]);
+ outwalk += sprintf(outwalk, "%1.2f", loadavg[2]);
walk += strlen("15min");
}
}
- if (output_format == O_I3BAR)
- printf("\"}");
+ *outwalk = '\0';
+ OUTPUT_FULL_TEXT(buffer);
return;
error:
#include <stdio.h>
#include <string.h>
+#include <yajl/yajl_gen.h>
#include "i3status.h"
-void print_run_watch(const char *title, const char *pidfile, const char *format) {
+void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const char *pidfile, const char *format) {
bool running = process_runs(pidfile);
const char *walk;
+ char *outwalk = buffer;
- if (output_format == O_I3BAR)
- printf("{\"name\":\"run_watch\", \"instance\": \"%s\", ", pidfile);
+ INSTANCE(pidfile);
- printf("%s", (running ? color("color_good") : color("color_bad")));
-
- if (output_format == O_I3BAR)
- printf("\"full_text\":\"");
+ START_COLOR((running ? "color_good" : "color_bad"));
for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (strncmp(walk+1, "title", strlen("title")) == 0) {
- printf("%s", title);
+ outwalk += sprintf(outwalk, "%s", title);
walk += strlen("title");
} else if (strncmp(walk+1, "status", strlen("status")) == 0) {
- printf("%s", (running ? "yes" : "no"));
+ outwalk += sprintf(outwalk, "%s", (running ? "yes" : "no"));
walk += strlen("status");
}
}
- printf("%s", endcolor());
-
- if (output_format == O_I3BAR)
- printf("\"}");
+ END_COLOR;
+ OUTPUT_FULL_TEXT(buffer);
}
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
+#include <yajl/yajl_gen.h>
#include "i3status.h"
-void print_time(const char *format, struct tm *current_tm) {
- static char part[512];
- /* Get date & time */
- if (current_tm == NULL) {
+void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
+ char *outwalk = buffer;
+ if (current_tm == NULL)
return;
- }
- if (output_format == O_I3BAR)
- printf("{\"name\":\"time\", \"full_text\":\"");
- (void)strftime(part, sizeof(part), format, current_tm);
- printf("%s", part);
- if (output_format == O_I3BAR)
- printf("\"}");
+ /* Get date & time */
+ outwalk += strftime(outwalk, 4095, format, current_tm);
+ *outwalk = '\0';
+ OUTPUT_FULL_TEXT(buffer);
}
}
#endif
-void print_volume(const char *fmt, const char *device, const char *mixer, int mixer_idx) {
-/* Printing volume only works with ALSA at the moment */
- if (output_format == O_I3BAR)
- printf("{\"name\":\"volume\", \"instance\": \"%s.%s.%d\", \"full_text\":\"", device, mixer, mixer_idx);
+void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *device, const char *mixer, int mixer_idx) {
+ char *outwalk = buffer;
+
+ /* Printing volume only works with ALSA at the moment */
+ if (output_format == O_I3BAR) {
+ char *instance;
+ asprintf(&instance, "%s.%s.%d", device, mixer, mixer_idx);
+ INSTANCE(instance);
+ free(instance);
+ }
#ifdef LINUX
/* Check if we already opened the mixer and get the handle
* from cache if so */
const char *walk = fmt;
for (; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (BEGINS_WITH(walk+1, "volume")) {
- printf("%d%%", avg);
+ outwalk += sprintf(outwalk, "%d%%", avg);
walk += strlen("volume");
}
}
const char *walk = fmt;
for (; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (BEGINS_WITH(walk+1, "volume")) {
- printf("%d%%", vol & 0x7f);
+ outwalk += sprintf(outwalk, "%d%%", vol & 0x7f);
walk += strlen("volume");
}
}
close(mixfd);
#endif
- if (output_format == O_I3BAR)
- printf("\"}");
+
+ *outwalk = '\0';
+ OUTPUT_FULL_TEXT(buffer);
}
return 0;
}
-void print_wireless_info(const char *interface, const char *format_up, const char *format_down) {
+void print_wireless_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down) {
const char *walk;
+ char *outwalk = buffer;
wireless_info_t info;
- if (output_format == O_I3BAR)
- printf("{\"name\":\"wireless\", \"instance\": \"%s\", ", interface);
+
+ INSTANCE(interface);
if (get_wireless_info(interface, &info)) {
walk = format_up;
if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY)
- printf("%s", info.quality < info.quality_average ? color("color_degraded") : color("color_good"));
+ START_COLOR((info.quality < info.quality_average ? "color_degraded" : "color_good"));
}
else {
walk = format_down;
- printf("%s", color("color_bad"));
+ START_COLOR("color_bad");
}
- if (output_format == O_I3BAR)
- printf("\"full_text\":\"");
-
for (; *walk != '\0'; walk++) {
if (*walk != '%') {
- putchar(*walk);
+ *(outwalk++) = *walk;
continue;
}
if (BEGINS_WITH(walk+1, "quality")) {
if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY) {
if (info.quality_max)
- printf("%03d%%", PERCENT_VALUE(info.quality, info.quality_max));
+ outwalk += sprintf(outwalk, "%03d%%", PERCENT_VALUE(info.quality, info.quality_max));
else
- printf("%d", info.quality);
- }
- else {
- printf("no value");
+ outwalk += sprintf(outwalk, "%d", info.quality);
+ } else {
+ *(outwalk++) = '?';
}
walk += strlen("quality");
}
if (BEGINS_WITH(walk+1, "signal")) {
if (info.flags & WIRELESS_INFO_FLAG_HAS_SIGNAL) {
if (info.signal_level_max)
- printf("%03d%%", PERCENT_VALUE(info.signal_level, info.signal_level_max));
+ outwalk += sprintf(outwalk, "%03d%%", PERCENT_VALUE(info.signal_level, info.signal_level_max));
else
- printf("%d dBm", info.signal_level);
- }
- else {
- printf("no value");
+ outwalk += sprintf(outwalk, "%d dBm", info.signal_level);
+ } else {
+ *(outwalk++) = '?';
}
walk += strlen("signal");
}
if (BEGINS_WITH(walk+1, "noise")) {
if (info.flags & WIRELESS_INFO_FLAG_HAS_NOISE) {
if (info.noise_level_max)
- printf("%03d%%", PERCENT_VALUE(info.noise_level, info.noise_level_max));
+ outwalk += sprintf(outwalk, "%03d%%", PERCENT_VALUE(info.noise_level, info.noise_level_max));
else
- printf("%d dBm", info.noise_level);
- }
- else {
- printf("no value");
+ outwalk += sprintf(outwalk, "%d dBm", info.noise_level);
+ } else {
+ *(outwalk++) = '?';
}
walk += strlen("noise");
}
if (BEGINS_WITH(walk+1, "essid")) {
if (info.flags & WIRELESS_INFO_FLAG_HAS_ESSID)
- printf("%s", info.essid);
+ outwalk += sprintf(outwalk, "%s", info.essid);
else
- printf("no value");
+ *(outwalk++) = '?';
walk += strlen("essid");
}
if (BEGINS_WITH(walk+1, "ip")) {
const char *ip_address = get_ip_addr(interface);
- if (ip_address != NULL)
- (void)printf("%s", get_ip_addr(interface));
- else (void)printf("no IP");
+ outwalk += sprintf(outwalk, "%s", (ip_address ? ip_address : "no IP"));
walk += strlen("ip");
}
#ifdef LINUX
if (BEGINS_WITH(walk+1, "bitrate")) {
- char buffer[128];
+ char br_buffer[128];
- iw_print_bitrate(buffer, sizeof(buffer), info.bitrate);
+ iw_print_bitrate(br_buffer, sizeof(br_buffer), info.bitrate);
- printf("%s", buffer);
+ outwalk += sprintf(outwalk, "%s", br_buffer);
walk += strlen("bitrate");
}
#endif
}
- (void)printf("%s", endcolor());
-
- if (output_format == O_I3BAR)
- printf("\"}");
+ END_COLOR;
+ OUTPUT_FULL_TEXT(buffer);
}