From f947d0a446b1b99020722cbc71127fc0c06086b2 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 11 Oct 2009 22:11:09 +0200 Subject: Breaks configfiles! Major refactoring of i3status, see below MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/config.c | 153 ------------------------------------------- src/general.c | 17 +---- src/get_battery_info.c | 139 --------------------------------------- src/get_cpu_temperature.c | 44 ------------- src/get_eth_info.c | 88 ------------------------- src/get_ip_addr.c | 67 ------------------- src/get_ipv6_addr.c | 79 ----------------------- src/get_load.c | 22 ------- src/get_wireless_info.c | 64 ------------------ src/output.c | 154 ++------------------------------------------ src/print_battery_info.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/print_cpu_temperature.c | 59 +++++++++++++++++ src/print_eth_info.c | 95 +++++++++++++++++++++++++++ src/print_ip_addr.c | 67 +++++++++++++++++++ src/print_ipv6_addr.c | 99 ++++++++++++++++++++++++++++ src/print_load.c | 39 +++++++++++ src/print_run_watch.c | 10 +++ src/print_time.c | 13 ++++ src/print_wireless_info.c | 92 ++++++++++++++++++++++++++ 19 files changed, 628 insertions(+), 822 deletions(-) delete mode 100644 src/config.c delete mode 100644 src/get_battery_info.c delete mode 100644 src/get_cpu_temperature.c delete mode 100644 src/get_eth_info.c delete mode 100644 src/get_ip_addr.c delete mode 100644 src/get_ipv6_addr.c delete mode 100644 src/get_load.c delete mode 100644 src/get_wireless_info.c create mode 100644 src/print_battery_info.c create mode 100644 src/print_cpu_temperature.c create mode 100644 src/print_eth_info.c create mode 100644 src/print_ip_addr.c create mode 100644 src/print_ipv6_addr.c create mode 100644 src/print_load.c create mode 100644 src/print_run_watch.c create mode 100644 src/print_time.c create mode 100644 src/print_wireless_info.c (limited to 'src') 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()); +} -- cgit v1.2.3