diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e79b4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +.*.swp diff --git a/Makefile b/Makefile index bcbb73d..2e9f93a 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ CFLAGS+=-std=gnu99 CFLAGS+=-pedantic CFLAGS+=-DPREFIX=\"\" CFLAGS+=-I. +LDFLAGS+=-lconfuse VERSION=$(shell git describe --tags --abbrev=0) @@ -18,9 +19,12 @@ CFLAGS+=-lbsd endif # Define this if you want i3status to spit out dzen2-compatible output on stdout -#CFLAGS+=-DDZEN +CFLAGS+=-DDZEN CFLAGS+=$(EXTRA_CFLAGS) +OBJS:=$(wildcard src/*.c *.c) +OBJS:=$(OBJS:.c=.o) + src/%.o: src/%.c @$(CC) $(CFLAGS) -c -o $@ $< @echo " CC $<" @@ -29,7 +33,7 @@ src/%.o: src/%.c @$(CC) $(CFLAGS) -c -o $@ $< @echo " CC $<" -i3status: src/general.o src/config.o src/get_load.o src/output.o src/get_cpu_temperature.o src/process_runs.o src/get_eth_info.o src/get_ip_addr.o src/get_wireless_info.o src/get_battery_info.o src/get_ipv6_addr.o i3status.o +i3status: ${OBJS} @$(CC) -o $@ src/*.o *.o $(LDFLAGS) @echo " LD $@" diff --git a/i3status.c b/i3status.c index 8b6ca72..141a984 100644 --- a/i3status.c +++ b/i3status.c @@ -1,80 +1,57 @@ /* * vim:ts=8:expandtab * - * i3status – Generates a status line for dzen2 or wmii + * i3status – Generates a status line for dzen2 or xmobar * * * Copyright © 2008-2009 Michael Stapelberg and contributors * Copyright © 2009 Thorsten Toepper * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * * * Neither the name of Michael Stapelberg nor the names of contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * */ -#include -#include -#include #include #include -#include #include -#include #include #include -#include -#include -#include #include #include #include #include - -#include "queue.h" +#include #include "i3status.h" -struct battery_head batteries; - /* socket file descriptor for general purposes */ int general_socket; -const char *wlan_interface = NULL; -const char *eth_interface = NULL; -char *wmii_path = NULL; -const char *time_format = NULL; -bool use_colors = false; -bool get_ethspeed = false; -bool get_ipv6 = false; -bool get_cpu_temperature = false; -char *thermal_zone = NULL; -const char *wmii_normcolors = "#222222 #333333"; -int order[MAX_ORDER]; -const char **run_watches = NULL; -unsigned int num_run_watches; -unsigned int interval = 1; +cfg_t *cfg, *cfg_general; /* * Exit upon SIGPIPE because when we have nowhere to write to, gathering @@ -87,10 +64,69 @@ void sigpipe(int signum) { } int main(int argc, char *argv[]) { - char part[512], - pathbuf[512]; - unsigned int i; - int j; + unsigned int j; + + cfg_opt_t general_opts[] = { + CFG_BOOL("colors", 1, CFGF_NONE), + CFG_INT("interval", 1, CFGF_NONE), + CFG_END() + }; + + cfg_opt_t run_watch_opts[] = { + CFG_STR("pidfile", NULL, CFGF_NONE), + CFG_STR("format", "%title: %status", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t wireless_opts[] = { + CFG_STR("format_up", "W: (%quality at %essid) %ip", CFGF_NONE), + CFG_STR("format_down", "W: down", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t ethernet_opts[] = { + CFG_STR("format", "E: %ip (%speed)", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t ipv6_opts[] = { + CFG_STR("format", "%ip", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t battery_opts[] = { + CFG_STR("format", "%status %remaining", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t time_opts[] = { + CFG_STR("format", "%d.%m.%Y %H:%M:%S", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t load_opts[] = { + CFG_STR("format", "%5min %10min %15min", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t temp_opts[] = { + CFG_STR("format", "%degrees C", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t opts[] = { + CFG_STR_LIST("order", "{ipv6,\"run_watch DHCP\",\"wireless wlan0\",\"ethernet eth0\",\"battery 0\",\"cpu_temperature 0\",load,time}", CFGF_NONE), + CFG_SEC("general", general_opts, CFGF_NONE), + CFG_SEC("run_watch", run_watch_opts, CFGF_TITLE | CFGF_MULTI), + CFG_SEC("wireless", wireless_opts, CFGF_TITLE | CFGF_MULTI), + CFG_SEC("ethernet", ethernet_opts, CFGF_TITLE | CFGF_MULTI), + CFG_SEC("battery", battery_opts, CFGF_TITLE | CFGF_MULTI), + CFG_SEC("cpu_temperature", temp_opts, CFGF_TITLE | CFGF_MULTI), + CFG_SEC("ipv6", ipv6_opts, CFGF_TITLE), + CFG_SEC("time", time_opts, CFGF_NONE), + CFG_SEC("load", load_opts, CFGF_NONE), + CFG_END() + }; char *configfile = PREFIX "/etc/i3status.conf"; int o, option_index = 0; @@ -105,66 +141,58 @@ int main(int argc, char *argv[]) { action.sa_handler = sigpipe; sigaction(SIGPIPE, &action, NULL); - SIMPLEQ_INIT(&batteries); - while ((o = getopt_long(argc, argv, "c:h", long_options, &option_index)) != -1) if ((char)o == 'c') configfile = optarg; else if ((char)o == 'h') { - printf("i3status (c) 2008-2009 Michael Stapelberg\n" + printf("i3status © 2008-2009 Michael Stapelberg\n" "Syntax: %s [-c ]\n", argv[0]); return 0; } - if (load_configuration(configfile) < 0) + cfg = cfg_init(opts, CFGF_NONE); + if (cfg_parse(cfg, configfile) == CFG_PARSE_ERROR) return EXIT_FAILURE; - setup(); + cfg_general = cfg_getsec(cfg, "general"); if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) die("Could not create socket\n"); while (1) { - for (j = 0; j < MAX_ORDER; j++) { - generate_order(wlan_interface, ORDER_WLAN, "wlan", get_wireless_info()); - generate_order(eth_interface, ORDER_ETH, "eth", get_eth_info()); - generate_order(get_ipv6, ORDER_IPV6, "ipv6", get_ipv6_addr()); - generate_order(get_cpu_temperature, ORDER_CPU_TEMPERATURE, "cpu_temperature", get_cpu_temperature_info()); - generate_order(true, ORDER_LOAD, "load", get_load()); + for (j = 0; j < cfg_size(cfg, "order"); j++) { + if (j > 0) + print_seperator(); - if (j == order[ORDER_RUN]) { - for (i = 0; i < num_run_watches; i += 2) { - bool running = process_runs(run_watches[i+1]); - if (use_colors) - snprintf(part, sizeof(part), "%s%s: %s%s", - (running ? color("#00FF00") : color("#FF0000")), - run_watches[i], - (running ? "yes" : "no"), endcolor()); - else snprintf(part, sizeof(part), "%s: %s", run_watches[i], (running ? "yes" : "no")); - snprintf(pathbuf, sizeof(pathbuf), "%d%s", order[ORDER_RUN], run_watches[i]); - write_to_statusbar(pathbuf, part, false); - } - } + const char *current = cfg_getnstr(cfg, "order", j); - if (j == order[ORDER_BATTERY]) { - struct battery *current; - SIMPLEQ_FOREACH(current, &batteries, batteries) - generate(ORDER_BATTERY, "battery", get_battery_info(current)); - } + CASE_SEC("ipv6") + print_ipv6_info(cfg_getstr(sec, "format")); - if (j == order[ORDER_TIME]) { - if (time_format != NULL) { - /* Get date & time */ - time_t current_time = time(NULL); - struct tm *current_tm = localtime(¤t_time); - (void)strftime(part, sizeof(part), time_format, current_tm); - generate(ORDER_TIME, "time", part); - } else { - generate(ORDER_TIME, "time", ""); - } - } + 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")); + + CASE_SEC_TITLE("battery") + print_battery_info(atoi(title), cfg_getstr(sec, "format")); + + CASE_SEC_TITLE("run_watch") + print_run_watch(title, cfg_getstr(sec, "pidfile"), cfg_getstr(sec, "format")); + + CASE_SEC("load") + print_load(cfg_getstr(sec, "format")); + + CASE_SEC("time") + print_time(cfg_getstr(sec, "format")); + + CASE_SEC_TITLE("cpu_temperature") + print_cpu_temperature_info(atoi(title), cfg_getstr(sec, "format")); } + printf("\n"); + fflush(stdout); - sleep(interval); + sleep(cfg_getint(cfg_general, "interval")); } } diff --git a/i3status.h b/i3status.h index aa7f20e..d00d318 100644 --- a/i3status.h +++ b/i3status.h @@ -2,8 +2,7 @@ #define _I3STATUS_H #include - -#include "queue.h" +#include #ifdef DZEN #define BAR "^fg(#333333)^p(5;-2)^ro(2)^p()^fg()^p(5)" @@ -11,18 +10,7 @@ #define BAR " | " #endif #define BEGINS_WITH(haystack, needle) (strncmp(haystack, needle, strlen(needle)) == 0) -#define max(a, b) (a > b ? a : b) - -#define generate(orderidx, name, function) \ - do { \ - write_to_statusbar(order_to_str(order[orderidx], name), function, (j == (highest_order-1))); \ - } while (0) - -#define generate_order(condition, orderidx, name, function) \ - do { \ - if (j == order[orderidx] && condition) \ - generate(orderidx, name, function); \ - } while (0) +#define max(a, b) ((a) > (b) ? (a) : (b)) #if defined(LINUX) @@ -44,64 +32,49 @@ #endif -typedef enum { CS_DISCHARGING, CS_CHARGING, CS_FULL } charging_status_t; -enum { ORDER_RUN, ORDER_WLAN, ORDER_ETH, ORDER_BATTERY, ORDER_CPU_TEMPERATURE, ORDER_LOAD, ORDER_TIME, ORDER_IPV6, MAX_ORDER }; +/* Allows for the definition of a variable without opening a new scope, thus + * suited for usage in a macro. Idea from wmii. */ +#define with(type, var, init) \ + for (type var = (type)-1; (var == (type)-1) && ((var=(init)) || 1); ) -struct battery { - char *path; - /* Use last full capacity instead of design capacity */ - bool use_last_full; - SIMPLEQ_ENTRY(battery) batteries; -}; +#define CASE_SEC(name) \ + if (BEGINS_WITH(current, name)) \ + with(cfg_t *, sec, cfg_getsec(cfg, name)) \ + if (sec != NULL) + +#define CASE_SEC_TITLE(name) \ + if (BEGINS_WITH(current, name)) \ + with(const char *, title, current + strlen(name) + 1) \ + with(cfg_t *, sec, cfg_gettsec(cfg, name, title)) \ + if (sec != NULL) + + +typedef enum { CS_DISCHARGING, CS_CHARGING, CS_FULL } charging_status_t; /* src/general.c */ char *skip_character(char *input, char character, int amount); void die(const char *fmt, ...); -void create_file(const char *name); -char *order_to_str(int number, char *name); -void setup(void); -void write_to_statusbar(const char *name, const char *message, bool final_entry); bool slurp(char *filename, char *destination, int size); /* src/output.c */ -void write_error_to_statusbar(const char *message); +void print_seperator(); char *color(const char *colorstr); char *endcolor() __attribute__ ((pure)); -void cleanup_rbar_dir(); -/* src/config.c */ -int load_configuration(const char *configfile); - -const char *get_ipv6_addr(); -const char *get_battery_info(struct battery *bat); +void print_ipv6_info(const char *format); +void print_battery_info(int number, const char *format); +void print_time(const char *format); const char *get_ip_addr(); -const char *get_wireless_info(); -const char *get_cpu_temperature_info(); -const char *get_eth_info(); -const char *get_load(); +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 *format); +void print_eth_info(const char *interface, const char *format); +void print_load(); bool process_runs(const char *path); -SIMPLEQ_HEAD(battery_head, battery); -extern struct battery_head batteries; - /* socket file descriptor for general purposes */ extern int general_socket; -extern int highest_order; - -extern const char *wlan_interface; -extern const char *eth_interface; -extern char *wmii_path; -extern const char *time_format; -extern bool use_colors; -extern bool get_ethspeed; -extern bool get_ipv6; -extern bool get_cpu_temperature; -extern char *thermal_zone; -extern const char *wmii_normcolors; -extern int order[MAX_ORDER]; -extern const char **run_watches; -extern unsigned int num_run_watches; -extern unsigned int interval; +extern cfg_t *cfg, *cfg_general; #endif diff --git a/queue.h b/queue.h deleted file mode 100644 index 75bb957..0000000 --- a/queue.h +++ /dev/null @@ -1,527 +0,0 @@ -/* $OpenBSD: queue.h,v 1.1 2007/10/26 03:14:08 niallo Exp $ */ -/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) -#define _Q_INVALIDATE(a) (a) = ((void *)-1) -#else -#define _Q_INVALIDATE(a) -#endif - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != SLIST_END(head); \ - (varp) = &SLIST_NEXT((var), field)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_NEXT(head, elm, field) do { \ - (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->slh_first; \ - \ - while (curelm->field.sle_next != (elm)) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - _Q_INVALIDATE((elm)->field.sle_next); \ - } \ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List access methods - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * tail queue access methods - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue access methods - */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/src/config.c b/src/config.c deleted file mode 100644 index e39c19b..0000000 --- a/src/config.c +++ /dev/null @@ -1,153 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include -#include -#include -#include - -#include "i3status.h" - -int highest_order = 0; - -/* - * Reads the configuration from the given file - * - */ -int load_configuration(const char *configfile) { - #define OPT(x) else if (strcasecmp(dest_name, x) == 0) - - /* check if the file exists */ - struct stat buf; - if (stat(configfile, &buf) < 0) - return -1; - - int result = 0; - FILE *handle = fopen(configfile, "r"); - if (handle == NULL) - die("Could not open configfile\n"); - char dest_name[512], dest_value[512], whole_buffer[1026]; - - while (!feof(handle)) { - char *ret; - if ((ret = fgets(whole_buffer, 1024, handle)) == whole_buffer) { - /* sscanf implicitly strips whitespace */ - if (sscanf(whole_buffer, "%s %[^\n]", dest_name, dest_value) < 1) - continue; - } else if (ret != NULL) - die("Could not read line in configuration file\n"); - - /* skip comments and empty lines */ - if (dest_name[0] == '#' || strlen(dest_name) < 3) - continue; - - OPT("wlan") - wlan_interface = strdup(dest_value); - OPT("eth") - eth_interface = strdup(dest_value); - OPT("time_format") - time_format = strdup(dest_value); - OPT("battery") { - struct battery *new = calloc(1, sizeof(struct battery)); - if (new == NULL) - die("Could not allocate memory\n"); - if (asprintf(&(new->path), "/sys/class/power_supply/BAT%d/uevent", atoi(dest_value)) == -1) - die("Could not build battery path\n"); - - /* check if flags were specified for this battery */ - if (strstr(dest_value, ",") != NULL) { - char *flags = strstr(dest_value, ","); - flags++; - if (*flags == 'f') - new->use_last_full = true; - } - SIMPLEQ_INSERT_TAIL(&batteries, new, batteries); - } OPT("color") - use_colors = true; - OPT("get_ipv6") - get_ipv6 = true; - OPT("get_ethspeed") - get_ethspeed = true; - OPT("get_cpu_temperature") { - get_cpu_temperature = true; - int zone = 0; - if (strlen(dest_value) > 0) - zone = atoi(dest_value); - if (asprintf(&thermal_zone, THERMAL_ZONE, zone) == -1) - die("Could not build thermal_zone path\n"); - } OPT("normcolors") - wmii_normcolors = strdup(dest_value); - OPT("interval") - interval = atoi(dest_value); - OPT("wmii_path") - { -#if !defined(DZEN) && !defined(XMOBAR) - static glob_t globbuf; - struct stat stbuf; - if (glob(dest_value, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf) < 0) - die("glob() failed\n"); - wmii_path = strdup(globbuf.gl_pathc > 0 ? globbuf.gl_pathv[0] : dest_value); - globfree(&globbuf); - - if ((stat(wmii_path, &stbuf)) == -1) { - fprintf(stderr, "Warning: wmii_path contains an invalid path\n"); - free(wmii_path); - wmii_path = strdup(dest_value); - } - if (wmii_path[strlen(wmii_path)-1] != '/') - die("wmii_path is not terminated by /\n"); -#endif - } - OPT("run_watch") - { - char *name = strdup(dest_value); - char *path = name; - while (*path != ' ') - path++; - *(path++) = '\0'; - num_run_watches += 2; - run_watches = realloc(run_watches, sizeof(char*) * num_run_watches); - run_watches[num_run_watches-2] = name; - run_watches[num_run_watches-1] = path; - } - OPT("order") - { - - for (int c = 0; c < MAX_ORDER; c++) - order[c] = -1; - - #define SET_ORDER(opt, idx) { if (strcasecmp(token, opt) == 0) order[idx] = highest_order++; } - char *walk, *token; - walk = token = dest_value; - while (*walk != '\0') { - while ((*walk != ',') && (*walk != '\0')) - walk++; - *(walk++) = '\0'; - SET_ORDER("run", ORDER_RUN); - SET_ORDER("ipv6", ORDER_IPV6); - SET_ORDER("wlan", ORDER_WLAN); - SET_ORDER("eth", ORDER_ETH); - SET_ORDER("battery", ORDER_BATTERY); - SET_ORDER("cpu_temperature", ORDER_CPU_TEMPERATURE); - SET_ORDER("load", ORDER_LOAD); - SET_ORDER("time", ORDER_TIME); - token = walk; - while (isspace((int)(*token))) - token++; - } - } - else - { - result = -2; - die("Unknown configfile option: %s\n", dest_name); - } - } - fclose(handle); - -#if !defined(DZEN) && !defined(XMOBAR) - if (wmii_path == NULL) - exit(EXIT_FAILURE); -#endif - - return result; -} diff --git a/src/general.c b/src/general.c index 8d48f74..a093c16 100644 --- a/src/general.c +++ b/src/general.c @@ -53,21 +53,6 @@ void die(const char *fmt, ...) { (void)vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); - if (wmii_path != NULL) - write_error_to_statusbar(buffer); - else - fprintf(stderr, "%s", buffer); + fprintf(stderr, "%s", buffer); exit(EXIT_FAILURE); } - -/* - * This function just concats two strings in place, it should only be used - * for concatting order to the name of a file or concatting color codes. - * Otherwise, the buffer size would have to be increased. - * - */ -char *order_to_str(int number, char *name) { - static char buf[32]; - (void)snprintf(buf, sizeof(buf), "%d%s", number, name); - return buf; -} diff --git a/src/get_cpu_temperature.c b/src/get_cpu_temperature.c deleted file mode 100644 index 9eb55bb..0000000 --- a/src/get_cpu_temperature.c +++ /dev/null @@ -1,44 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include - -#include "i3status.h" - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#include -#include -#define TZ_ZEROC 2732 -#define TZ_KELVTOC(x) (((x) - TZ_ZEROC) / 10), abs(((x) - TZ_ZEROC) % 10) -#endif - - -/* - * Reads the CPU temperature from /sys/class/thermal/thermal_zone0/temp and - * returns the temperature in degree celcius. - * - */ -const char *get_cpu_temperature_info() { - static char buf[16]; - -#if defined(LINUX) - long int temp; - if (!slurp(thermal_zone, buf, sizeof(buf))) - die("Could not open \"%s\"\n", thermal_zone); - temp = strtol(buf, NULL, 10); - if (temp == LONG_MIN || temp == LONG_MAX || temp <= 0) - (void)snprintf(buf, sizeof(buf), "T: ? C"); - else - (void)snprintf(buf, sizeof(buf), "T: %ld C", (temp/1000)); -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - int sysctl_rslt; - size_t sysctl_size = sizeof (sysctl_rslt); - if (sysctlbyname(thermal_zone,&sysctl_rslt,&sysctl_size,NULL,0)) - return "No Thermal"; - - snprintf(buf,sizeof(buf),"T: %d.%d C",TZ_KELVTOC(sysctl_rslt)); -#endif - - return buf; -} diff --git a/src/get_eth_info.c b/src/get_eth_info.c deleted file mode 100644 index 80cc829..0000000 --- a/src/get_eth_info.c +++ /dev/null @@ -1,88 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "i3status.h" - -#if defined(LINUX) -#include -#include -#define PART_ETHSPEED "E: %s (%d Mbit/s)" -#endif - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#define IFM_TYPE_MATCH(dt, t) \ - (IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t))) - -#define PART_ETHSPEED "E: %s (%s)" - -#endif - -/* - * Combines ethernet IP addresses and speed (if requested) for displaying - * - */ -const char *get_eth_info() { - static char part[512]; -#if defined(LINUX) - int ethspeed=0; -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - char *ethspeed; -#endif - const char *ip_address = get_ip_addr(eth_interface); - - if (ip_address == NULL) { - (void)snprintf(part, sizeof(part), "E: down"); - return part; - } - - if (get_ethspeed) { -#if defined(LINUX) - /* This code path requires root privileges */ - struct ifreq ifr; - struct ethtool_cmd ecmd; - - ecmd.cmd = ETHTOOL_GSET; - (void)memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_data = (caddr_t)&ecmd; - (void)strcpy(ifr.ifr_name, eth_interface); - if (ioctl(general_socket, SIOCETHTOOL, &ifr) == 0) - ethspeed = (ecmd.speed == USHRT_MAX ? 0 : ecmd.speed); - else get_ethspeed = false; -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - struct ifmediareq ifm; - (void)memset(&ifm, 0, sizeof(ifm)); - (void)strncpy(ifm.ifm_name, eth_interface, sizeof(ifm.ifm_name)); - int ret = ioctl(general_socket, SIOCGIFMEDIA, (caddr_t)&ifm); - - /* Get the description of the media type, partially taken from - * FreeBSD's ifconfig */ - const struct ifmedia_description *desc; - struct ifmedia_description ifm_subtype_descriptions[] = - IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; - - for (desc = ifm_subtype_descriptions; - desc->ifmt_string != NULL; - desc++) { - if (IFM_TYPE_MATCH(desc->ifmt_word, ifm.ifm_active) && - IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(ifm.ifm_active)) - break; - } - ethspeed = (desc->ifmt_string != NULL ? desc->ifmt_string : "?"); -#endif - } - - if (get_ethspeed) - (void)snprintf(part, sizeof(part), PART_ETHSPEED, ip_address, ethspeed); - else (void)snprintf(part, sizeof(part), "E: %s", ip_address); - - return part; -} diff --git a/src/get_load.c b/src/get_load.c deleted file mode 100644 index 2f58d9b..0000000 --- a/src/get_load.c +++ /dev/null @@ -1,22 +0,0 @@ -// vim:ts=8:expandtab -#include "i3status.h" -#include -#include -#include -#include - -const char *get_load() { - static char part[512]; - -/* Get load */ -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(sun) - double loadavg[3]; - if (getloadavg(loadavg, 3) == -1) - errx(-1, "getloadavg() failed\n"); - (void)snprintf(part, sizeof(part), "%1.2f %1.2f %1.2f", loadavg[0], loadavg[1], loadavg[2]); -#else - part[0] = '\0'; -#endif - - return part; -} diff --git a/src/get_wireless_info.c b/src/get_wireless_info.c deleted file mode 100644 index 1f13764..0000000 --- a/src/get_wireless_info.c +++ /dev/null @@ -1,64 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include -#include -#include -#include - -#include "i3status.h" - -const char *get_wireless_essid() { - static char part[512]; -#ifdef LINUX - int skfd; - if ((skfd = iw_sockets_open()) < 0) { - perror("socket"); - exit(-1); - } - struct wireless_config cfg; - if (iw_get_basic_config(skfd, wlan_interface, &cfg) >= 0) - snprintf(part, sizeof(part), "%s", cfg.essid); - else part[0] = '\0'; - (void)close(skfd); -#else - part[0] = '\0'; -#endif - return part; -} - -/* - * Just parses /proc/net/wireless looking for lines beginning with - * wlan_interface, extracting the quality of the link and adding the - * current IP address of wlan_interface. - * - */ -const char *get_wireless_info() { - char buf[1024]; - static char part[512]; - char *interfaces; - memset(buf, 0, sizeof(buf)); - memset(part, 0, sizeof(part)); - - if (!slurp("/proc/net/wireless", buf, sizeof(buf))) - die("Could not open \"/proc/net/wireless\"\n"); - - interfaces = skip_character(buf, '\n', 1) + 1; - while ((interfaces = skip_character(interfaces, '\n', 1)+1) < buf+strlen(buf)) { - while (isspace((int)*interfaces)) - interfaces++; - if (!BEGINS_WITH(interfaces, wlan_interface)) - continue; - int quality; - if (sscanf(interfaces, "%*[^:]: 0000 %d", &quality) != 1) - continue; - if ((quality == UCHAR_MAX) || (quality == 0)) { - (void)snprintf(part, sizeof(part), "%sW: down%s", color("#FF0000"), endcolor()); - } else (void)snprintf(part, sizeof(part), "%sW: (%03d%% at %s) %s%s", - color("#00FF00"), quality, get_wireless_essid(), get_ip_addr(wlan_interface), endcolor()); - return part; - } - - return part; -} - diff --git a/src/output.c b/src/output.c index eee458b..d4d8c2f 100644 --- a/src/output.c +++ b/src/output.c @@ -11,22 +11,12 @@ #include "i3status.h" /* - * Writes an errormessage to statusbar - * - */ -void write_error_to_statusbar(const char *message) { - cleanup_rbar_dir(); - create_file("error"); - write_to_statusbar("error", message, true); -} - -/* - * Returns the correct color format for dzen (^fg(color)) or wmii (color ) + * Returns the correct color format for dzen (^fg(color)) or xmobar () * */ char *color(const char *colorstr) { static char colorbuf[32]; - if (!use_colors) { + if (!cfg_getbool(cfg_general, "colors")) { colorbuf[0] = '\0'; return colorbuf; } @@ -34,8 +24,6 @@ char *color(const char *colorstr) { (void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", colorstr); #elif XMOBAR (void)snprintf(colorbuf, sizeof(colorbuf), "", colorstr); -#else - (void)snprintf(colorbuf, sizeof(colorbuf), "%s %s ", colorstr, wmii_normcolors); #endif return colorbuf; } @@ -52,142 +40,8 @@ char *endcolor() { #endif } -/* - * Cleans wmii's /rbar directory by deleting all regular files - * - */ -void cleanup_rbar_dir() { +void print_seperator() { #if defined(DZEN) || defined(XMOBAR) - return; + printf("%s", BAR); #endif - struct dirent *ent; - DIR *dir; - char pathbuf[strlen(wmii_path)+256+1]; - - if ((dir = opendir(wmii_path)) == NULL) - exit(EXIT_FAILURE); - - while ((ent = readdir(dir)) != NULL) { - if (ent->d_type == DT_REG) { - (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s", wmii_path, ent->d_name); - if (unlink(pathbuf) == -1) - exit(EXIT_FAILURE); - } - } - - (void)closedir(dir); -} - -/* - * Creates the specified file in wmii's /rbar directory with - * correct modes and initializes colors if colormode is enabled - * - */ -void create_file(const char *name) { -#if defined(DZEN) || defined(XMOBAR) - return; -#endif - char pathbuf[strlen(wmii_path)+256+1]; - int fd; - int flags = O_CREAT | O_WRONLY; - struct stat statbuf; - - (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s", wmii_path, name); - - /* Overwrite file's contents if it exists */ - if (stat(pathbuf, &statbuf) >= 0) - flags |= O_TRUNC; - - if ((fd = open(pathbuf, flags, S_IRUSR | S_IWUSR)) < 0) - exit(EXIT_FAILURE); - if (use_colors) { - char *tmp = color("#888888"); - if (write(fd, tmp, strlen(tmp)) != (ssize_t)strlen(tmp)) - exit(EXIT_FAILURE); - } - (void)close(fd); -} - -/* - * Waits until wmii_path/rbar exists (= the filesystem gets mounted), - * cleans up all files and creates the needed files - * - */ -void setup(void) { - unsigned int i; - char pathbuf[512]; - -#if !defined(DZEN) && !defined(XMOBAR) - struct stat statbuf; - /* Wait until wmii_path/rbar exists */ - for (; stat(wmii_path, &statbuf) < 0; sleep(interval)); -#endif -#define cf(orderidx, name) create_file(order_to_str(order[orderidx], name)); - - cleanup_rbar_dir(); - if (wlan_interface) - cf(ORDER_WLAN, "wlan"); - if (eth_interface) - cf(ORDER_ETH, "eth"); - if (get_cpu_temperature) - cf(ORDER_CPU_TEMPERATURE, "cpu_temperature"); - cf(ORDER_LOAD, "load"); - if (time_format) - cf(ORDER_TIME, "time"); - for (i = 0; i < num_run_watches; i += 2) { - snprintf(pathbuf, sizeof(pathbuf), "%d%s", order[ORDER_RUN], run_watches[i]); - create_file(pathbuf); - } -} - -/* - * Writes the given message in the corresponding file in wmii's /rbar directory - * - */ -void write_to_statusbar(const char *name, const char *message, bool final_entry) { -#ifdef DZEN - if (final_entry) { - if (printf("%s^p(6)\n", message) < 0) { - perror("printf"); - exit(1); - } - - fflush(stdout); - return; - } - if (printf("%s" BAR, message) < 0) { - perror("printf"); - exit(1); - } - return; -#elif XMOBAR - if (final_entry) { - if (printf("%s\n", message) < 0) { - perror("printf"); - exit(1); - } - - fflush(stdout); - return; - } - if (printf("%s" BAR, message) < 0) { - perror("printf"); - exit(1); - } - return; - -#endif - - char pathbuf[strlen(wmii_path)+256+1]; - int fd; - - (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s", wmii_path, name); - if ((fd = open(pathbuf, O_RDWR)) == -1) { - /* Try to re-setup stuff and just continue */ - setup(); - return; - } - if (write(fd, message, strlen(message)) != (ssize_t)strlen(message)) - exit(EXIT_FAILURE); - (void)close(fd); } diff --git a/src/get_battery_info.c b/src/print_battery_info.c similarity index 85% rename from src/get_battery_info.c rename to src/print_battery_info.c index ee78706..eb1f6bb 100644 --- a/src/get_battery_info.c +++ b/src/print_battery_info.c @@ -16,9 +16,8 @@ * worn off your battery is. * */ -const char *get_battery_info(struct battery *bat) { +void print_battery_info(int number, const char *format) { char buf[1024]; - static char part[512]; char *walk, *last; int full_design = -1, remaining = -1, @@ -26,8 +25,12 @@ const char *get_battery_info(struct battery *bat) { charging_status_t status = CS_DISCHARGING; #if defined(LINUX) - if (!slurp(bat->path, buf, sizeof(buf))) - return "No battery"; + static char batpath[512]; + sprintf(batpath, "/sys/class/power_supply/BAT%d/uevent", number); + if (!slurp(batpath, buf, sizeof(buf))) { + printf("No battery"); + return; + } for (walk = buf, last = buf; (walk-buf) < 1024; walk++) { if (*walk == '\n') { @@ -49,22 +52,24 @@ const char *get_battery_info(struct battery *bat) { status = CS_FULL; else { /* The only thing left is the full capacity */ +#if 0 if (bat->use_last_full) { if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") && !BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL")) continue; } else { +#endif if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") && !BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN")) continue; - } + //} full_design = atoi(walk+1); } } if ((full_design == 1) || (remaining == -1)) - return part; + return; if (present_rate > 0) { float remaining_time; @@ -81,13 +86,13 @@ const char *get_battery_info(struct battery *bat) { minutes = seconds / 60; seconds -= (minutes * 60); - (void)snprintf(part, sizeof(part), "%s %.02f%% %02d:%02d:%02d", + (void)printf("%s %.02f%% %02d:%02d:%02d", (status == CS_CHARGING ? "CHR" : (status == CS_DISCHARGING ? "BAT" : "FULL")), (((float)remaining / (float)full_design) * 100), max(hours, 0), max(minutes, 0), max(seconds, 0)); } else { - (void)snprintf(part, sizeof(part), "%s %.02f%%", + (void)printf("%s %.02f%%", (status == CS_CHARGING ? "CHR" : (status == CS_DISCHARGING ? "BAT" : "FULL")), (((float)remaining / (float)full_design) * 100)); @@ -97,16 +102,22 @@ const char *get_battery_info(struct battery *bat) { int sysctl_rslt; size_t sysctl_size = sizeof(sysctl_rslt); - if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) - return "No battery"; + if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) { + printf("No battery"); + return; + } present_rate = sysctl_rslt; - if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) - return "No battery"; + if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) { + printf("No battery"); + return; + } remaining = sysctl_rslt; - if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) - return "No battery"; + if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) { + printf("No battery"); + return; + } state = sysctl_rslt; if (state == 0 && present_rate == 100) @@ -123,17 +134,16 @@ const char *get_battery_info(struct battery *bat) { minutes = remaining; hours = minutes / 60; minutes -= (hours * 60); - (void)snprintf(part, sizeof(part), "%s %02d%% %02dh%02d", + (void)printf("%s %02d%% %02dh%02d", (status == CS_CHARGING ? "CHR" : (status == CS_DISCHARGING ? "BAT" : "FULL")), present_rate, max(hours, 0), max(minutes, 0)); } else { - (void)snprintf(part, sizeof(part), "%s %02d%%", + (void)printf("%s %02d%%", (status == CS_CHARGING ? "CHR" : (status == CS_DISCHARGING ? "BAT" : "FULL")), present_rate); } #endif - return part; } diff --git a/src/print_cpu_temperature.c b/src/print_cpu_temperature.c new file mode 100644 index 0000000..d524f0b --- /dev/null +++ b/src/print_cpu_temperature.c @@ -0,0 +1,59 @@ +// vim:ts=8:expandtab +#include +#include +#include +#include + +#include "i3status.h" + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include +#include +#include +#define TZ_ZEROC 2732 +#define TZ_KELVTOC(x) (((x) - TZ_ZEROC) / 10), abs(((x) - TZ_ZEROC) % 10) +#endif + +static char *thermal_zone; + +/* + * Reads the CPU temperature from /sys/class/thermal/thermal_zone0/temp and + * returns the temperature in degree celcius. + * + */ +void print_cpu_temperature_info(int zone, const char *format) { + const char *walk; + static char buf[16]; + + asprintf(&thermal_zone, THERMAL_ZONE, zone); + + for (walk = format; *walk != '\0'; walk++) { + if (*walk != '%') { + putchar(*walk); + continue; + } + + if (BEGINS_WITH(walk+1, "degrees")) { +#if defined(LINUX) + long int temp; + if (!slurp(thermal_zone, buf, sizeof(buf))) + die("Could not open \"%s\"\n", thermal_zone); + temp = strtol(buf, NULL, 10); + if (temp == LONG_MIN || temp == LONG_MAX || temp <= 0) + (void)printf("?"); + else + (void)printf("%ld", (temp/1000)); +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + int sysctl_rslt; + size_t sysctl_size = sizeof(sysctl_rslt); + if (sysctlbyname(thermal_zone, &sysctl_rslt, &sysctl_size, NULL, 0)) { + (void)printf("No thermal zone found"); + return; + } + + (void)printf("%d.%d", TZ_KELVTOC(sysctl_rslt)); +#endif + walk += strlen("degrees"); + } + } +} diff --git a/src/print_eth_info.c b/src/print_eth_info.c new file mode 100644 index 0000000..7624383 --- /dev/null +++ b/src/print_eth_info.c @@ -0,0 +1,95 @@ +// vim:ts=8:expandtab +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i3status.h" + +#if defined(LINUX) +#include +#include +#define PART_ETHSPEED "E: %s (%d Mbit/s)" +#endif + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include +#define IFM_TYPE_MATCH(dt, t) \ + (IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t))) + +#define PART_ETHSPEED "E: %s (%s)" + +#endif + +static void print_eth_speed(const char *interface) { +#if defined(LINUX) + int ethspeed = 0; +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + char *ethspeed; +#endif + +#if defined(LINUX) + /* This code path requires root privileges */ + struct ifreq ifr; + struct ethtool_cmd ecmd; + + ecmd.cmd = ETHTOOL_GSET; + (void)memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_data = (caddr_t)&ecmd; + (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("?"); +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + struct ifmediareq ifm; + (void)memset(&ifm, 0, sizeof(ifm)); + (void)strncpy(ifm.ifm_name, interface, sizeof(ifm.ifm_name)); + int ret = ioctl(general_socket, SIOCGIFMEDIA, (caddr_t)&ifm); + + /* Get the description of the media type, partially taken from + * FreeBSD's ifconfig */ + const struct ifmedia_description *desc; + struct ifmedia_description ifm_subtype_descriptions[] = + IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; + + for (desc = ifm_subtype_descriptions; + desc->ifmt_string != NULL; + desc++) { + if (IFM_TYPE_MATCH(desc->ifmt_word, ifm.ifm_active) && + IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(ifm.ifm_active)) + break; + } + ethspeed = (desc->ifmt_string != NULL ? desc->ifmt_string : "?"); + printf("%s", ethspeed); +#endif +} + +/* + * Combines ethernet IP addresses and speed (if requested) for displaying + * + */ +void print_eth_info(const char *interface, const char *format) { + const char *walk; + const char *ip_address = get_ip_addr(interface); + + for (walk = format; *walk != '\0'; walk++) { + if (*walk != '%') { + putchar(*walk); + continue; + } + + if (strncmp(walk+1, "ip", strlen("ip")) == 0) { + printf("%s", ip_address); + walk += strlen("ip"); + } else if (strncmp(walk+1, "speed", strlen("speed")) == 0) { + print_eth_speed(interface); + walk += strlen("speed"); + } + } +} diff --git a/src/get_ip_addr.c b/src/print_ip_addr.c similarity index 100% rename from src/get_ip_addr.c rename to src/print_ip_addr.c diff --git a/src/get_ipv6_addr.c b/src/print_ipv6_addr.c similarity index 78% rename from src/get_ipv6_addr.c rename to src/print_ipv6_addr.c index 341b5ba..fcb2df8 100644 --- a/src/get_ipv6_addr.c +++ b/src/print_ipv6_addr.c @@ -12,7 +12,7 @@ * Returns the IPv6 address with which you have connectivity at the moment. * */ -const char *get_ipv6_addr() { +static void print_ipv6_addr() { static char buf[INET6_ADDRSTRLEN+1]; struct addrinfo hints; struct addrinfo *result, *resp; @@ -28,7 +28,8 @@ const char *get_ipv6_addr() { /* We don’t display the error here because most * likely, there just is no connectivity. * Thus, don’t spam the user’s console. */ - return "no IPv6"; + printf("no IPv6"); + return; } for (resp = result; resp != NULL; resp = resp->ai_next) { @@ -56,7 +57,8 @@ const char *get_ipv6_addr() { if (getsockname(fd, (struct sockaddr*)&local, &local_len) == -1) { perror("getsockname()"); (void)close(fd); - return "no IPv6"; + printf("no IPv6"); + return; } (void)close(fd); @@ -67,13 +69,31 @@ const char *get_ipv6_addr() { buf, sizeof(buf), NULL, 0, NI_NUMERICHOST)) != 0) { fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret)); - return "no IPv6"; + printf("no IPv6"); + return; } free(result); - return buf; + printf("%s", buf); + return; } free(result); - return "no IPv6"; + printf("no IPv6"); +} + +void print_ipv6_info(const char *format) { + const char *walk; + + for (walk = format; *walk != '\0'; walk++) { + if (*walk != '%') { + putchar(*walk); + continue; + } + + if (strncmp(walk+1, "ip", strlen("ip")) == 0) { + print_ipv6_addr(); + walk += strlen("ip"); + } + } } diff --git a/src/print_load.c b/src/print_load.c new file mode 100644 index 0000000..c0d9494 --- /dev/null +++ b/src/print_load.c @@ -0,0 +1,39 @@ +// vim:ts=8:expandtab +#include "i3status.h" +#include +#include +#include +#include + +void print_load(const char *format) { +/* Get load */ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(sun) + double loadavg[3]; + const char *walk; + + if (getloadavg(loadavg, 3) == -1) + errx(-1, "getloadavg() failed\n"); + + for (walk = format; *walk != '\0'; walk++) { + if (*walk != '%') { + putchar(*walk); + continue; + } + + if (BEGINS_WITH(walk+1, "5min")) { + (void)printf("%1.2f", loadavg[0]); + walk += strlen("5min"); + } + + if (BEGINS_WITH(walk+1, "10min")) { + (void)printf("%1.2f", loadavg[1]); + walk += strlen("10min"); + } + + if (BEGINS_WITH(walk+1, "15min")) { + (void)printf("%1.2f", loadavg[2]); + walk += strlen("15min"); + } + } +#endif +} diff --git a/src/print_run_watch.c b/src/print_run_watch.c new file mode 100644 index 0000000..391467e --- /dev/null +++ b/src/print_run_watch.c @@ -0,0 +1,10 @@ +#include +#include "i3status.h" + +void print_run_watch(const char *title, const char *pidfile, const char *format) { + bool running = process_runs(pidfile); + printf("%s%s: %s%s", + (running ? color("#00FF00") : color("#FF0000")), + title, + (running ? "yes" : "no"), endcolor()); +} diff --git a/src/print_time.c b/src/print_time.c new file mode 100644 index 0000000..6871437 --- /dev/null +++ b/src/print_time.c @@ -0,0 +1,13 @@ +// vim:ts=8:expandtab +#include +#include +#include + +void print_time(const char *format) { + static char part[512]; + /* Get date & time */ + time_t current_time = time(NULL); + struct tm *current_tm = localtime(¤t_time); + (void)strftime(part, sizeof(part), format, current_tm); + printf("%s", part); +} diff --git a/src/print_wireless_info.c b/src/print_wireless_info.c new file mode 100644 index 0000000..f7776c8 --- /dev/null +++ b/src/print_wireless_info.c @@ -0,0 +1,92 @@ +// vim:ts=8:expandtab +#include +#include +#include +#include +#include +#include + +#include "i3status.h" + +static const char *get_wireless_essid(const char *interface) { + static char part[512]; +#ifdef LINUX + int skfd; + if ((skfd = iw_sockets_open()) < 0) { + perror("socket"); + exit(-1); + } + struct wireless_config wcfg; + if (iw_get_basic_config(skfd, interface, &wcfg) >= 0) + snprintf(part, sizeof(part), "%s", wcfg.essid); + else part[0] = '\0'; + (void)close(skfd); +#else + part[0] = '\0'; +#endif + return part; +} + +/* + * Just parses /proc/net/wireless looking for lines beginning with + * wlan_interface, extracting the quality of the link and adding the + * current IP address of wlan_interface. + * + */ +void print_wireless_info(const char *interface, const char *format_up, const char *format_down) { + char buf[1024]; + int quality = -1; + char *interfaces; + const char *walk; + memset(buf, 0, sizeof(buf)); + + if (!slurp("/proc/net/wireless", buf, sizeof(buf))) + die("Could not open \"/proc/net/wireless\"\n"); + + interfaces = skip_character(buf, '\n', 1) + 1; + while ((interfaces = skip_character(interfaces, '\n', 1)+1) < buf+strlen(buf)) { + while (isspace((int)*interfaces)) + interfaces++; + if (!BEGINS_WITH(interfaces, interface)) + continue; + if (sscanf(interfaces, "%*[^:]: 0000 %d", &quality) != 1) + continue; + break; + } + + /* Interface could not be found */ + if (quality == -1) + return; + + if ((quality == UCHAR_MAX) || (quality == 0)) { + walk = format_down; + printf("%s", color("#FF0000")); + } else { + printf("%s", color("#00FF00")); + walk = format_up; + } + + for (; *walk != '\0'; walk++) { + if (*walk != '%') { + putchar(*walk); + continue; + } + + if (BEGINS_WITH(walk+1, "quality")) { + (void)printf("%03d%%", quality); + walk += strlen("quality"); + } + + if (BEGINS_WITH(walk+1, "essid")) { + (void)printf("%s", get_wireless_essid(interface)); + walk += strlen("essid"); + } + + if (BEGINS_WITH(walk+1, "ip")) { + (void)printf("%s", get_ip_addr(interface)); + walk += strlen("ip"); + } + } + + (void)printf("%s", endcolor()); +}