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.
This commit is contained in:
parent
1d122f32e6
commit
f947d0a446
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
.*.swp
|
8
Makefile
8
Makefile
@ -4,6 +4,7 @@ CFLAGS+=-std=gnu99
|
|||||||
CFLAGS+=-pedantic
|
CFLAGS+=-pedantic
|
||||||
CFLAGS+=-DPREFIX=\"\"
|
CFLAGS+=-DPREFIX=\"\"
|
||||||
CFLAGS+=-I.
|
CFLAGS+=-I.
|
||||||
|
LDFLAGS+=-lconfuse
|
||||||
|
|
||||||
VERSION=$(shell git describe --tags --abbrev=0)
|
VERSION=$(shell git describe --tags --abbrev=0)
|
||||||
|
|
||||||
@ -18,9 +19,12 @@ CFLAGS+=-lbsd
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Define this if you want i3status to spit out dzen2-compatible output on stdout
|
# Define this if you want i3status to spit out dzen2-compatible output on stdout
|
||||||
#CFLAGS+=-DDZEN
|
CFLAGS+=-DDZEN
|
||||||
CFLAGS+=$(EXTRA_CFLAGS)
|
CFLAGS+=$(EXTRA_CFLAGS)
|
||||||
|
|
||||||
|
OBJS:=$(wildcard src/*.c *.c)
|
||||||
|
OBJS:=$(OBJS:.c=.o)
|
||||||
|
|
||||||
src/%.o: src/%.c
|
src/%.o: src/%.c
|
||||||
@$(CC) $(CFLAGS) -c -o $@ $<
|
@$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
@echo " CC $<"
|
@echo " CC $<"
|
||||||
@ -29,7 +33,7 @@ src/%.o: src/%.c
|
|||||||
@$(CC) $(CFLAGS) -c -o $@ $<
|
@$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
@echo " CC $<"
|
@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)
|
@$(CC) -o $@ src/*.o *.o $(LDFLAGS)
|
||||||
@echo " LD $@"
|
@echo " LD $@"
|
||||||
|
|
||||||
|
208
i3status.c
208
i3status.c
@ -1,80 +1,57 @@
|
|||||||
/*
|
/*
|
||||||
* vim:ts=8:expandtab
|
* 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 © 2008-2009 Michael Stapelberg and contributors
|
||||||
* Copyright © 2009 Thorsten Toepper <atsutane at freethoughts dot de>
|
* Copyright © 2009 Thorsten Toepper <atsutane at freethoughts dot de>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* * Redistributions of source code must retain the above copyright notice, this
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
* list of conditions and the following disclaimer.
|
* list of conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* list of conditions and the following disclaimer in the documentation and/or other
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* * Neither the name of Michael Stapelberg nor the names of contributors
|
* * Neither the name of Michael Stapelberg nor the names of contributors
|
||||||
* may be used to endorse or promote products derived from this software without
|
* may be used to endorse or promote products derived from this software
|
||||||
* specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
* DAMAGE.
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <confuse.h>
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
#include "i3status.h"
|
#include "i3status.h"
|
||||||
|
|
||||||
struct battery_head batteries;
|
|
||||||
|
|
||||||
/* socket file descriptor for general purposes */
|
/* socket file descriptor for general purposes */
|
||||||
int general_socket;
|
int general_socket;
|
||||||
|
|
||||||
const char *wlan_interface = NULL;
|
cfg_t *cfg, *cfg_general;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exit upon SIGPIPE because when we have nowhere to write to, gathering
|
* 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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char part[512],
|
unsigned int j;
|
||||||
pathbuf[512];
|
|
||||||
unsigned int i;
|
cfg_opt_t general_opts[] = {
|
||||||
int j;
|
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";
|
char *configfile = PREFIX "/etc/i3status.conf";
|
||||||
int o, option_index = 0;
|
int o, option_index = 0;
|
||||||
@ -105,66 +141,58 @@ int main(int argc, char *argv[]) {
|
|||||||
action.sa_handler = sigpipe;
|
action.sa_handler = sigpipe;
|
||||||
sigaction(SIGPIPE, &action, NULL);
|
sigaction(SIGPIPE, &action, NULL);
|
||||||
|
|
||||||
SIMPLEQ_INIT(&batteries);
|
|
||||||
|
|
||||||
while ((o = getopt_long(argc, argv, "c:h", long_options, &option_index)) != -1)
|
while ((o = getopt_long(argc, argv, "c:h", long_options, &option_index)) != -1)
|
||||||
if ((char)o == 'c')
|
if ((char)o == 'c')
|
||||||
configfile = optarg;
|
configfile = optarg;
|
||||||
else if ((char)o == 'h') {
|
else if ((char)o == 'h') {
|
||||||
printf("i3status (c) 2008-2009 Michael Stapelberg\n"
|
printf("i3status © 2008-2009 Michael Stapelberg\n"
|
||||||
"Syntax: %s [-c <configfile>]\n", argv[0]);
|
"Syntax: %s [-c <configfile>]\n", argv[0]);
|
||||||
return 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;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
setup();
|
cfg_general = cfg_getsec(cfg, "general");
|
||||||
|
|
||||||
if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||||
die("Could not create socket\n");
|
die("Could not create socket\n");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
for (j = 0; j < MAX_ORDER; j++) {
|
for (j = 0; j < cfg_size(cfg, "order"); j++) {
|
||||||
generate_order(wlan_interface, ORDER_WLAN, "wlan", get_wireless_info());
|
if (j > 0)
|
||||||
generate_order(eth_interface, ORDER_ETH, "eth", get_eth_info());
|
print_seperator();
|
||||||
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]) {
|
const char *current = cfg_getnstr(cfg, "order", j);
|
||||||
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]) {
|
CASE_SEC("ipv6")
|
||||||
struct battery *current;
|
print_ipv6_info(cfg_getstr(sec, "format"));
|
||||||
SIMPLEQ_FOREACH(current, &batteries, batteries)
|
|
||||||
generate(ORDER_BATTERY, "battery", get_battery_info(current));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == order[ORDER_TIME]) {
|
CASE_SEC_TITLE("wireless")
|
||||||
if (time_format != NULL) {
|
print_wireless_info(title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down"));
|
||||||
/* 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", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(interval);
|
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(cfg_getint(cfg_general, "interval"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
85
i3status.h
85
i3status.h
@ -2,8 +2,7 @@
|
|||||||
#define _I3STATUS_H
|
#define _I3STATUS_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <confuse.h>
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
#ifdef DZEN
|
#ifdef DZEN
|
||||||
#define BAR "^fg(#333333)^p(5;-2)^ro(2)^p()^fg()^p(5)"
|
#define BAR "^fg(#333333)^p(5;-2)^ro(2)^p()^fg()^p(5)"
|
||||||
@ -11,18 +10,7 @@
|
|||||||
#define BAR "<fc=#333333> | </fc>"
|
#define BAR "<fc=#333333> | </fc>"
|
||||||
#endif
|
#endif
|
||||||
#define BEGINS_WITH(haystack, needle) (strncmp(haystack, needle, strlen(needle)) == 0)
|
#define BEGINS_WITH(haystack, needle) (strncmp(haystack, needle, strlen(needle)) == 0)
|
||||||
#define max(a, b) (a > b ? a : b)
|
#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)
|
|
||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
|
|
||||||
@ -44,64 +32,49 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum { CS_DISCHARGING, CS_CHARGING, CS_FULL } charging_status_t;
|
/* Allows for the definition of a variable without opening a new scope, thus
|
||||||
enum { ORDER_RUN, ORDER_WLAN, ORDER_ETH, ORDER_BATTERY, ORDER_CPU_TEMPERATURE, ORDER_LOAD, ORDER_TIME, ORDER_IPV6, MAX_ORDER };
|
* 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 {
|
#define CASE_SEC(name) \
|
||||||
char *path;
|
if (BEGINS_WITH(current, name)) \
|
||||||
/* Use last full capacity instead of design capacity */
|
with(cfg_t *, sec, cfg_getsec(cfg, name)) \
|
||||||
bool use_last_full;
|
if (sec != NULL)
|
||||||
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 */
|
/* src/general.c */
|
||||||
char *skip_character(char *input, char character, int amount);
|
char *skip_character(char *input, char character, int amount);
|
||||||
void die(const char *fmt, ...);
|
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);
|
bool slurp(char *filename, char *destination, int size);
|
||||||
|
|
||||||
/* src/output.c */
|
/* src/output.c */
|
||||||
void write_error_to_statusbar(const char *message);
|
void print_seperator();
|
||||||
char *color(const char *colorstr);
|
char *color(const char *colorstr);
|
||||||
char *endcolor() __attribute__ ((pure));
|
char *endcolor() __attribute__ ((pure));
|
||||||
void cleanup_rbar_dir();
|
|
||||||
|
|
||||||
/* src/config.c */
|
void print_ipv6_info(const char *format);
|
||||||
int load_configuration(const char *configfile);
|
void print_battery_info(int number, const char *format);
|
||||||
|
void print_time(const char *format);
|
||||||
const char *get_ipv6_addr();
|
|
||||||
const char *get_battery_info(struct battery *bat);
|
|
||||||
const char *get_ip_addr();
|
const char *get_ip_addr();
|
||||||
const char *get_wireless_info();
|
void print_wireless_info(const char *interface, const char *format_up, const char *format_down);
|
||||||
const char *get_cpu_temperature_info();
|
void print_run_watch(const char *title, const char *pidfile, const char *format);
|
||||||
const char *get_eth_info();
|
void print_cpu_temperature_info(int zone, const char *format);
|
||||||
const char *get_load();
|
void print_eth_info(const char *interface, const char *format);
|
||||||
|
void print_load();
|
||||||
bool process_runs(const char *path);
|
bool process_runs(const char *path);
|
||||||
|
|
||||||
SIMPLEQ_HEAD(battery_head, battery);
|
|
||||||
extern struct battery_head batteries;
|
|
||||||
|
|
||||||
/* socket file descriptor for general purposes */
|
/* socket file descriptor for general purposes */
|
||||||
extern int general_socket;
|
extern int general_socket;
|
||||||
|
|
||||||
extern int highest_order;
|
extern cfg_t *cfg, *cfg_general;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
527
queue.h
527
queue.h
@ -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_ */
|
|
153
src/config.c
153
src/config.c
@ -1,153 +0,0 @@
|
|||||||
// vim:ts=8:expandtab
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <glob.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -53,21 +53,6 @@ void die(const char *fmt, ...) {
|
|||||||
(void)vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
(void)vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||||
va_end(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);
|
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;
|
|
||||||
}
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
// vim:ts=8:expandtab
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "i3status.h"
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
||||||
#include <err.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
// vim:ts=8:expandtab
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include "i3status.h"
|
|
||||||
|
|
||||||
#if defined(LINUX)
|
|
||||||
#include <linux/ethtool.h>
|
|
||||||
#include <linux/sockios.h>
|
|
||||||
#define PART_ETHSPEED "E: %s (%d Mbit/s)"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
||||||
#include <net/if_media.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
// vim:ts=8:expandtab
|
|
||||||
#include "i3status.h"
|
|
||||||
#include <err.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
// vim:ts=8:expandtab
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <iwlib.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
154
src/output.c
154
src/output.c
@ -11,22 +11,12 @@
|
|||||||
#include "i3status.h"
|
#include "i3status.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Writes an errormessage to statusbar
|
* Returns the correct color format for dzen (^fg(color)) or xmobar (<fc=color>)
|
||||||
*
|
|
||||||
*/
|
|
||||||
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 <normcolors>)
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *color(const char *colorstr) {
|
char *color(const char *colorstr) {
|
||||||
static char colorbuf[32];
|
static char colorbuf[32];
|
||||||
if (!use_colors) {
|
if (!cfg_getbool(cfg_general, "colors")) {
|
||||||
colorbuf[0] = '\0';
|
colorbuf[0] = '\0';
|
||||||
return colorbuf;
|
return colorbuf;
|
||||||
}
|
}
|
||||||
@ -34,8 +24,6 @@ char *color(const char *colorstr) {
|
|||||||
(void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", colorstr);
|
(void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", colorstr);
|
||||||
#elif XMOBAR
|
#elif XMOBAR
|
||||||
(void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", colorstr);
|
(void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", colorstr);
|
||||||
#else
|
|
||||||
(void)snprintf(colorbuf, sizeof(colorbuf), "%s %s ", colorstr, wmii_normcolors);
|
|
||||||
#endif
|
#endif
|
||||||
return colorbuf;
|
return colorbuf;
|
||||||
}
|
}
|
||||||
@ -52,142 +40,8 @@ char *endcolor() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void print_seperator() {
|
||||||
* Cleans wmii's /rbar directory by deleting all regular files
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void cleanup_rbar_dir() {
|
|
||||||
#if defined(DZEN) || defined(XMOBAR)
|
#if defined(DZEN) || defined(XMOBAR)
|
||||||
return;
|
printf("%s", BAR);
|
||||||
#endif
|
#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);
|
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
* worn off your battery is.
|
* 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];
|
char buf[1024];
|
||||||
static char part[512];
|
|
||||||
char *walk, *last;
|
char *walk, *last;
|
||||||
int full_design = -1,
|
int full_design = -1,
|
||||||
remaining = -1,
|
remaining = -1,
|
||||||
@ -26,8 +25,12 @@ const char *get_battery_info(struct battery *bat) {
|
|||||||
charging_status_t status = CS_DISCHARGING;
|
charging_status_t status = CS_DISCHARGING;
|
||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
if (!slurp(bat->path, buf, sizeof(buf)))
|
static char batpath[512];
|
||||||
return "No battery";
|
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++) {
|
for (walk = buf, last = buf; (walk-buf) < 1024; walk++) {
|
||||||
if (*walk == '\n') {
|
if (*walk == '\n') {
|
||||||
@ -49,22 +52,24 @@ const char *get_battery_info(struct battery *bat) {
|
|||||||
status = CS_FULL;
|
status = CS_FULL;
|
||||||
else {
|
else {
|
||||||
/* The only thing left is the full capacity */
|
/* The only thing left is the full capacity */
|
||||||
|
#if 0
|
||||||
if (bat->use_last_full) {
|
if (bat->use_last_full) {
|
||||||
if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
|
if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
|
||||||
!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
|
!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
#endif
|
||||||
if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
|
if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
|
||||||
!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
|
!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
|
||||||
continue;
|
continue;
|
||||||
}
|
//}
|
||||||
|
|
||||||
full_design = atoi(walk+1);
|
full_design = atoi(walk+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((full_design == 1) || (remaining == -1))
|
if ((full_design == 1) || (remaining == -1))
|
||||||
return part;
|
return;
|
||||||
|
|
||||||
if (present_rate > 0) {
|
if (present_rate > 0) {
|
||||||
float remaining_time;
|
float remaining_time;
|
||||||
@ -81,13 +86,13 @@ const char *get_battery_info(struct battery *bat) {
|
|||||||
minutes = seconds / 60;
|
minutes = seconds / 60;
|
||||||
seconds -= (minutes * 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_CHARGING ? "CHR" :
|
||||||
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
||||||
(((float)remaining / (float)full_design) * 100),
|
(((float)remaining / (float)full_design) * 100),
|
||||||
max(hours, 0), max(minutes, 0), max(seconds, 0));
|
max(hours, 0), max(minutes, 0), max(seconds, 0));
|
||||||
} else {
|
} else {
|
||||||
(void)snprintf(part, sizeof(part), "%s %.02f%%",
|
(void)printf("%s %.02f%%",
|
||||||
(status == CS_CHARGING ? "CHR" :
|
(status == CS_CHARGING ? "CHR" :
|
||||||
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
||||||
(((float)remaining / (float)full_design) * 100));
|
(((float)remaining / (float)full_design) * 100));
|
||||||
@ -97,16 +102,22 @@ const char *get_battery_info(struct battery *bat) {
|
|||||||
int sysctl_rslt;
|
int sysctl_rslt;
|
||||||
size_t sysctl_size = sizeof(sysctl_rslt);
|
size_t sysctl_size = sizeof(sysctl_rslt);
|
||||||
|
|
||||||
if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0)
|
if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) {
|
||||||
return "No battery";
|
printf("No battery");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
present_rate = sysctl_rslt;
|
present_rate = sysctl_rslt;
|
||||||
if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0)
|
if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) {
|
||||||
return "No battery";
|
printf("No battery");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
remaining = sysctl_rslt;
|
remaining = sysctl_rslt;
|
||||||
if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0)
|
if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) {
|
||||||
return "No battery";
|
printf("No battery");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
state = sysctl_rslt;
|
state = sysctl_rslt;
|
||||||
if (state == 0 && present_rate == 100)
|
if (state == 0 && present_rate == 100)
|
||||||
@ -123,17 +134,16 @@ const char *get_battery_info(struct battery *bat) {
|
|||||||
minutes = remaining;
|
minutes = remaining;
|
||||||
hours = minutes / 60;
|
hours = minutes / 60;
|
||||||
minutes -= (hours * 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_CHARGING ? "CHR" :
|
||||||
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
||||||
present_rate,
|
present_rate,
|
||||||
max(hours, 0), max(minutes, 0));
|
max(hours, 0), max(minutes, 0));
|
||||||
} else {
|
} else {
|
||||||
(void)snprintf(part, sizeof(part), "%s %02d%%",
|
(void)printf("%s %02d%%",
|
||||||
(status == CS_CHARGING ? "CHR" :
|
(status == CS_CHARGING ? "CHR" :
|
||||||
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
||||||
present_rate);
|
present_rate);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return part;
|
|
||||||
}
|
}
|
59
src/print_cpu_temperature.c
Normal file
59
src/print_cpu_temperature.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// vim:ts=8:expandtab
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "i3status.h"
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
#include <err.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
src/print_eth_info.c
Normal file
95
src/print_eth_info.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// vim:ts=8:expandtab
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "i3status.h"
|
||||||
|
|
||||||
|
#if defined(LINUX)
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
#define PART_ETHSPEED "E: %s (%d Mbit/s)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
#include <net/if_media.h>
|
||||||
|
#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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* Returns the IPv6 address with which you have connectivity at the moment.
|
* 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];
|
static char buf[INET6_ADDRSTRLEN+1];
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result, *resp;
|
struct addrinfo *result, *resp;
|
||||||
@ -28,7 +28,8 @@ const char *get_ipv6_addr() {
|
|||||||
/* We don’t display the error here because most
|
/* We don’t display the error here because most
|
||||||
* likely, there just is no connectivity.
|
* likely, there just is no connectivity.
|
||||||
* Thus, don’t spam the user’s console. */
|
* Thus, don’t spam the user’s console. */
|
||||||
return "no IPv6";
|
printf("no IPv6");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (resp = result; resp != NULL; resp = resp->ai_next) {
|
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) {
|
if (getsockname(fd, (struct sockaddr*)&local, &local_len) == -1) {
|
||||||
perror("getsockname()");
|
perror("getsockname()");
|
||||||
(void)close(fd);
|
(void)close(fd);
|
||||||
return "no IPv6";
|
printf("no IPv6");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)close(fd);
|
(void)close(fd);
|
||||||
@ -67,13 +69,31 @@ const char *get_ipv6_addr() {
|
|||||||
buf, sizeof(buf), NULL, 0,
|
buf, sizeof(buf), NULL, 0,
|
||||||
NI_NUMERICHOST)) != 0) {
|
NI_NUMERICHOST)) != 0) {
|
||||||
fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret));
|
fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(ret));
|
||||||
return "no IPv6";
|
printf("no IPv6");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(result);
|
free(result);
|
||||||
return buf;
|
printf("%s", buf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(result);
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
39
src/print_load.c
Normal file
39
src/print_load.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// vim:ts=8:expandtab
|
||||||
|
#include "i3status.h"
|
||||||
|
#include <err.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
10
src/print_run_watch.c
Normal file
10
src/print_run_watch.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#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());
|
||||||
|
}
|
13
src/print_time.c
Normal file
13
src/print_time.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// vim:ts=8:expandtab
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
92
src/print_wireless_info.c
Normal file
92
src/print_wireless_info.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// vim:ts=8:expandtab
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <iwlib.h>
|
||||||
|
|
||||||
|
#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());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user