From: Michael Stapelberg Date: Sun, 11 Oct 2009 20:11:09 +0000 (+0200) Subject: Breaks configfiles! Major refactoring of i3status, see below X-Git-Tag: 2.0~26 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f947d0a;p=i3%2Fi3status Breaks configfiles! Major refactoring of i3status, see below We finally switched to libconfuse for a configuration file format which does not require much work for the programmer nor for the user. Plus, it avoids the Not-Invented-Here syndrome of yet another config file format. Furthermore, as a consequence of providing format strings for every "module" (ipv6, wireless, …), we directly print the output and thus we needed to drop support for wmii. This allowed us to get rid of quite some complexity. Documentation about the new configuration file and options will follow. This commit is the beginning of what will be i3status v2.0. --- 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()); - - 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); - } - } - - if (j == order[ORDER_BATTERY]) { - struct battery *current; - SIMPLEQ_FOREACH(current, &batteries, batteries) - generate(ORDER_BATTERY, "battery", get_battery_info(current)); - } - - 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", ""); - } - } + 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")); + + 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); ) + +#define CASE_SEC(name) \ + if (BEGINS_WITH(current, name)) \ + with(cfg_t *, sec, cfg_getsec(cfg, name)) \ + if (sec != NULL) -struct battery { - char *path; - /* Use last full capacity instead of design capacity */ - bool use_last_full; - SIMPLEQ_ENTRY(battery) batteries; -}; +#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_battery_info.c b/src/get_battery_info.c deleted file mode 100644 index ee78706..0000000 --- a/src/get_battery_info.c +++ /dev/null @@ -1,139 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include - -#include "i3status.h" - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#include -#endif - -/* - * Get battery information from /sys. Note that it uses the design capacity to - * calculate the percentage, not the last full capacity, so you can see how - * worn off your battery is. - * - */ -const char *get_battery_info(struct battery *bat) { - char buf[1024]; - static char part[512]; - char *walk, *last; - int full_design = -1, - remaining = -1, - present_rate = -1; - charging_status_t status = CS_DISCHARGING; - -#if defined(LINUX) - if (!slurp(bat->path, buf, sizeof(buf))) - return "No battery"; - - for (walk = buf, last = buf; (walk-buf) < 1024; walk++) { - if (*walk == '\n') { - last = walk+1; - continue; - } - - if (*walk != '=') - continue; - - if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") || - BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW")) - remaining = atoi(walk+1); - else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW")) - present_rate = atoi(walk+1); - else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging")) - status = CS_CHARGING; - else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full")) - status = CS_FULL; - else { - /* The only thing left is the full capacity */ - if (bat->use_last_full) { - if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") && - !BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL")) - continue; - } else { - 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; - - if (present_rate > 0) { - float remaining_time; - int seconds, hours, minutes; - if (status == CS_CHARGING) - remaining_time = ((float)full_design - (float)remaining) / (float)present_rate; - else if (status == CS_DISCHARGING) - remaining_time = ((float)remaining / (float)present_rate); - else remaining_time = 0; - - seconds = (int)(remaining_time * 3600.0); - hours = seconds / 3600; - seconds -= (hours * 3600); - minutes = seconds / 60; - seconds -= (minutes * 60); - - (void)snprintf(part, sizeof(part), "%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%%", - (status == CS_CHARGING ? "CHR" : - (status == CS_DISCHARGING ? "BAT" : "FULL")), - (((float)remaining / (float)full_design) * 100)); - } -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - int state; - int sysctl_rslt; - size_t sysctl_size = sizeof(sysctl_rslt); - - if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) - return "No battery"; - - present_rate = sysctl_rslt; - if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) - return "No battery"; - - remaining = sysctl_rslt; - if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) - return "No battery"; - - state = sysctl_rslt; - if (state == 0 && present_rate == 100) - status = CS_FULL; - else if (state == 0 && present_rate < 100) - status = CS_CHARGING; - else - status = CS_DISCHARGING; - - full_design = sysctl_rslt; - - if (state == 1) { - int hours, minutes; - minutes = remaining; - hours = minutes / 60; - minutes -= (hours * 60); - (void)snprintf(part, sizeof(part), "%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%%", - (status == CS_CHARGING ? "CHR" : - (status == CS_DISCHARGING ? "BAT" : "FULL")), - present_rate); - } -#endif - return part; -} 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_ip_addr.c b/src/get_ip_addr.c deleted file mode 100644 index 6ddd35a..0000000 --- a/src/get_ip_addr.c +++ /dev/null @@ -1,67 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "i3status.h" - -/* - * Return the IP address for the given interface or "no IP" if the - * interface is up and running but hasn't got an IP address yet - * - */ -const char *get_ip_addr(const char *interface) { - static char part[512]; - socklen_t len = sizeof(struct sockaddr_in); - memset(part, 0, sizeof(part)); - - struct ifaddrs *ifaddr, *addrp; - - getifaddrs(&ifaddr); - - if (ifaddr == NULL) { - (void)snprintf(part, sizeof(part), "E: down"); - return part; - } - - addrp = ifaddr; - - /* Skip until we are at the AF_INET address of interface */ - for (addrp = ifaddr; - - (addrp != NULL && - (strcmp(addrp->ifa_name, interface) != 0 || - addrp->ifa_addr == NULL || - addrp->ifa_addr->sa_family != AF_INET)); - - addrp = addrp->ifa_next) { - /* Check if the interface is down */ - if (strcmp(addrp->ifa_name, interface) == 0 && - (addrp->ifa_flags & IFF_RUNNING) == 0) { - freeifaddrs(ifaddr); - return NULL; - } - } - - if (addrp == NULL) { - freeifaddrs(ifaddr); - return "no IP"; - } - - int ret; - if ((ret = getnameinfo(addrp->ifa_addr, len, part, sizeof(part), NULL, 0, NI_NUMERICHOST)) != 0) { - fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret)); - freeifaddrs(ifaddr); - return "no IP"; - } - - freeifaddrs(ifaddr); - return part; -} - diff --git a/src/get_ipv6_addr.c b/src/get_ipv6_addr.c deleted file mode 100644 index 341b5ba..0000000 --- a/src/get_ipv6_addr.c +++ /dev/null @@ -1,79 +0,0 @@ -// vim:ts=8:expandtab -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Returns the IPv6 address with which you have connectivity at the moment. - * - */ -const char *get_ipv6_addr() { - static char buf[INET6_ADDRSTRLEN+1]; - struct addrinfo hints; - struct addrinfo *result, *resp; - int fd; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET6; - - /* We resolve the K root server to get a public IPv6 address. You can - * replace this with any other host which has an AAAA record, but the - * K root server is a pretty safe bet. */ - if (getaddrinfo("k.root-servers.net", "domain", &hints, &result) != 0) { - /* 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"; - } - - for (resp = result; resp != NULL; resp = resp->ai_next) { - if ((fd = socket(resp->ai_family, SOCK_DGRAM, 0)) == -1) { - perror("socket()"); - continue; - } - - /* Since the socket was created with SOCK_DGRAM, this is - * actually not establishing a connection or generating - * any other network traffic. Instead, as a side-effect, - * it saves the local address with which packets would - * be sent to the destination. */ - if (connect(fd, resp->ai_addr, resp->ai_addrlen) == -1) { - /* We don’t display the error here because most - * likely, there just is no IPv6 connectivity. - * Thus, don’t spam the user’s console but just - * try the next address. */ - (void)close(fd); - continue; - } - - struct sockaddr_storage local; - socklen_t local_len = sizeof(struct sockaddr_storage); - if (getsockname(fd, (struct sockaddr*)&local, &local_len) == -1) { - perror("getsockname()"); - (void)close(fd); - return "no IPv6"; - } - - (void)close(fd); - - memset(buf, 0, INET6_ADDRSTRLEN + 1); - int ret; - if ((ret = getnameinfo((struct sockaddr*)&local, local_len, - buf, sizeof(buf), NULL, 0, - NI_NUMERICHOST)) != 0) { - fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret)); - return "no IPv6"; - } - - free(result); - return buf; - } - - free(result); - return "no IPv6"; -} 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() { -#if defined(DZEN) || defined(XMOBAR) - return; -#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) { +void print_seperator() { #if defined(DZEN) || defined(XMOBAR) - return; + printf("%s", BAR); #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/print_battery_info.c b/src/print_battery_info.c new file mode 100644 index 0000000..eb1f6bb --- /dev/null +++ b/src/print_battery_info.c @@ -0,0 +1,149 @@ +// vim:ts=8:expandtab +#include +#include +#include + +#include "i3status.h" + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include +#include +#endif + +/* + * Get battery information from /sys. Note that it uses the design capacity to + * calculate the percentage, not the last full capacity, so you can see how + * worn off your battery is. + * + */ +void print_battery_info(int number, const char *format) { + char buf[1024]; + char *walk, *last; + int full_design = -1, + remaining = -1, + present_rate = -1; + charging_status_t status = CS_DISCHARGING; + +#if defined(LINUX) + 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') { + last = walk+1; + continue; + } + + if (*walk != '=') + continue; + + if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") || + BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW")) + remaining = atoi(walk+1); + else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW")) + present_rate = atoi(walk+1); + else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging")) + status = CS_CHARGING; + else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full")) + 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; + + if (present_rate > 0) { + float remaining_time; + int seconds, hours, minutes; + if (status == CS_CHARGING) + remaining_time = ((float)full_design - (float)remaining) / (float)present_rate; + else if (status == CS_DISCHARGING) + remaining_time = ((float)remaining / (float)present_rate); + else remaining_time = 0; + + seconds = (int)(remaining_time * 3600.0); + hours = seconds / 3600; + seconds -= (hours * 3600); + minutes = seconds / 60; + seconds -= (minutes * 60); + + (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)printf("%s %.02f%%", + (status == CS_CHARGING ? "CHR" : + (status == CS_DISCHARGING ? "BAT" : "FULL")), + (((float)remaining / (float)full_design) * 100)); + } +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + int state; + int sysctl_rslt; + size_t sysctl_size = sizeof(sysctl_rslt); + + 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) { + printf("No battery"); + return; + } + + remaining = sysctl_rslt; + if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) { + printf("No battery"); + return; + } + + state = sysctl_rslt; + if (state == 0 && present_rate == 100) + status = CS_FULL; + else if (state == 0 && present_rate < 100) + status = CS_CHARGING; + else + status = CS_DISCHARGING; + + full_design = sysctl_rslt; + + if (state == 1) { + int hours, minutes; + minutes = remaining; + hours = minutes / 60; + minutes -= (hours * 60); + (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)printf("%s %02d%%", + (status == CS_CHARGING ? "CHR" : + (status == CS_DISCHARGING ? "BAT" : "FULL")), + present_rate); + } +#endif +} 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/print_ip_addr.c b/src/print_ip_addr.c new file mode 100644 index 0000000..6ddd35a --- /dev/null +++ b/src/print_ip_addr.c @@ -0,0 +1,67 @@ +// vim:ts=8:expandtab +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i3status.h" + +/* + * Return the IP address for the given interface or "no IP" if the + * interface is up and running but hasn't got an IP address yet + * + */ +const char *get_ip_addr(const char *interface) { + static char part[512]; + socklen_t len = sizeof(struct sockaddr_in); + memset(part, 0, sizeof(part)); + + struct ifaddrs *ifaddr, *addrp; + + getifaddrs(&ifaddr); + + if (ifaddr == NULL) { + (void)snprintf(part, sizeof(part), "E: down"); + return part; + } + + addrp = ifaddr; + + /* Skip until we are at the AF_INET address of interface */ + for (addrp = ifaddr; + + (addrp != NULL && + (strcmp(addrp->ifa_name, interface) != 0 || + addrp->ifa_addr == NULL || + addrp->ifa_addr->sa_family != AF_INET)); + + addrp = addrp->ifa_next) { + /* Check if the interface is down */ + if (strcmp(addrp->ifa_name, interface) == 0 && + (addrp->ifa_flags & IFF_RUNNING) == 0) { + freeifaddrs(ifaddr); + return NULL; + } + } + + if (addrp == NULL) { + freeifaddrs(ifaddr); + return "no IP"; + } + + int ret; + if ((ret = getnameinfo(addrp->ifa_addr, len, part, sizeof(part), NULL, 0, NI_NUMERICHOST)) != 0) { + fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret)); + freeifaddrs(ifaddr); + return "no IP"; + } + + freeifaddrs(ifaddr); + return part; +} + diff --git a/src/print_ipv6_addr.c b/src/print_ipv6_addr.c new file mode 100644 index 0000000..fcb2df8 --- /dev/null +++ b/src/print_ipv6_addr.c @@ -0,0 +1,99 @@ +// vim:ts=8:expandtab +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Returns the IPv6 address with which you have connectivity at the moment. + * + */ +static void print_ipv6_addr() { + static char buf[INET6_ADDRSTRLEN+1]; + struct addrinfo hints; + struct addrinfo *result, *resp; + int fd; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + + /* We resolve the K root server to get a public IPv6 address. You can + * replace this with any other host which has an AAAA record, but the + * K root server is a pretty safe bet. */ + if (getaddrinfo("k.root-servers.net", "domain", &hints, &result) != 0) { + /* We don’t display the error here because most + * likely, there just is no connectivity. + * Thus, don’t spam the user’s console. */ + printf("no IPv6"); + return; + } + + for (resp = result; resp != NULL; resp = resp->ai_next) { + if ((fd = socket(resp->ai_family, SOCK_DGRAM, 0)) == -1) { + perror("socket()"); + continue; + } + + /* Since the socket was created with SOCK_DGRAM, this is + * actually not establishing a connection or generating + * any other network traffic. Instead, as a side-effect, + * it saves the local address with which packets would + * be sent to the destination. */ + if (connect(fd, resp->ai_addr, resp->ai_addrlen) == -1) { + /* We don’t display the error here because most + * likely, there just is no IPv6 connectivity. + * Thus, don’t spam the user’s console but just + * try the next address. */ + (void)close(fd); + continue; + } + + struct sockaddr_storage local; + socklen_t local_len = sizeof(struct sockaddr_storage); + if (getsockname(fd, (struct sockaddr*)&local, &local_len) == -1) { + perror("getsockname()"); + (void)close(fd); + printf("no IPv6"); + return; + } + + (void)close(fd); + + memset(buf, 0, INET6_ADDRSTRLEN + 1); + int ret; + if ((ret = getnameinfo((struct sockaddr*)&local, local_len, + buf, sizeof(buf), NULL, 0, + NI_NUMERICHOST)) != 0) { + fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret)); + printf("no IPv6"); + return; + } + + free(result); + printf("%s", buf); + return; + } + + free(result); + 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()); +}