From b219f47f394e536198997578e4cce3c539b84b6d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 7 Dec 2014 15:14:02 +0100 Subject: [PATCH] support the special interface name _first_ for ethernet/wireless Since we have deterministic device names in Linux, these strings are a much better default in the i3status config than "eth0" and "wlan0" (what we used before). --- i3status.c | 14 ++++++++++++-- i3status.conf | 8 ++++---- include/i3status.h | 7 +++++++ man/i3status.man | 6 ++++++ src/first_network_device.c | 39 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 src/first_network_device.c diff --git a/i3status.c b/i3status.c index fc16c49..daa2d00 100644 --- a/i3status.c +++ b/i3status.c @@ -576,13 +576,23 @@ int main(int argc, char *argv[]) { CASE_SEC_TITLE("wireless") { SEC_OPEN_MAP("wireless"); - print_wireless_info(json_gen, buffer, title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); + const char *interface = NULL; + if (strcasecmp(title, "_first_") == 0) + interface = first_eth_interface(NET_TYPE_WIRELESS); + if (interface == NULL) + interface = title; + print_wireless_info(json_gen, buffer, interface, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); SEC_CLOSE_MAP; } CASE_SEC_TITLE("ethernet") { SEC_OPEN_MAP("ethernet"); - print_eth_info(json_gen, buffer, title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); + const char *interface = NULL; + if (strcasecmp(title, "_first_") == 0) + interface = first_eth_interface(NET_TYPE_ETHERNET); + if (interface == NULL) + interface = title; + print_eth_info(json_gen, buffer, interface, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); SEC_CLOSE_MAP; } diff --git a/i3status.conf b/i3status.conf index 01c182c..7052e23 100644 --- a/i3status.conf +++ b/i3status.conf @@ -15,18 +15,18 @@ order += "ipv6" order += "disk /" order += "run_watch DHCP" order += "run_watch VPN" -order += "wireless wlan0" -order += "ethernet eth0" +order += "wireless _first_" +order += "ethernet _first_" order += "battery 0" order += "load" order += "tztime local" -wireless wlan0 { +wireless _first_ { format_up = "W: (%quality at %essid) %ip" format_down = "W: down" } -ethernet eth0 { +ethernet _first_ { # if you use %speed, i3status requires root privileges format_up = "E: %ip (%speed)" format_down = "E: down" diff --git a/include/i3status.h b/include/i3status.h index d816f0a..f8f0784 100644 --- a/include/i3status.h +++ b/include/i3status.h @@ -170,6 +170,13 @@ char *auto_detect_format(); /* src/print_time.c */ void set_timezone(const char *tz); +/* src/first_network_device.c */ +typedef enum { + NET_TYPE_WIRELESS = 0, + NET_TYPE_ETHERNET = 1 +} net_type_t; +const char *first_eth_interface(const net_type_t type); + void print_ipv6_info(yajl_gen json_gen, char *buffer, const char *format_up, const char *format_down); void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format, const char *prefix_type, const char *threshold_type, const double low_threshold); void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, const char *format_down, const char *status_chr, const char *status_bat, const char *status_full, int low_threshold, char *threshold_type, bool last_full_capacity, bool integer_battery_capacity, bool hide_seconds); diff --git a/man/i3status.man b/man/i3status.man index 06dc4a6..e11aff5 100644 --- a/man/i3status.man +++ b/man/i3status.man @@ -274,6 +274,9 @@ Gets the link quality, frequency and ESSID of the given wireless network interface. You can specify different format strings for the network being connected or not connected. +The special interface name `_first_` will be replaced by the first wireless +network interface found on the system (excluding devices starting with "lo"). + *Example order*: +wireless wlan0+ *Example format*: +W: (%quality at %essid, %bitrate / %frequency) %ip+ @@ -284,6 +287,9 @@ Gets the IP address and (if possible) the link speed of the given ethernet interface. Getting the link speed requires the cap_net_admin capability. Set it using +setcap cap_net_admin=ep $(which i3status)+. +The special interface name `_first_` will be replaced by the first non-wireless +network interface found on the system (excluding devices starting with "lo"). + *Example order*: +ethernet eth0+ *Example format*: +E: %ip (%speed)+ diff --git a/src/first_network_device.c b/src/first_network_device.c new file mode 100644 index 0000000..c160027 --- /dev/null +++ b/src/first_network_device.c @@ -0,0 +1,39 @@ +// vim:ts=8:expandtab +#include +#include +#include + +#include "i3status.h" + +const char *first_eth_interface(const net_type_t type) { + static char *interface = NULL; + struct ifaddrs *ifaddr, *addrp; + struct stat stbuf; + static char path[1024]; + + getifaddrs(&ifaddr); + + if (ifaddr == NULL) + return NULL; + + free(interface); + interface = NULL; + for (addrp = ifaddr; + addrp != NULL; + addrp = addrp->ifa_next) { + if (strncasecmp("lo", addrp->ifa_name, strlen("lo")) == 0) + continue; + // Skip this interface if it is a wireless interface. + snprintf(path, sizeof(path), "/sys/class/net/%s/wireless", addrp->ifa_name); + const bool is_wireless = (stat(path, &stbuf) == 0); + if (( is_wireless && type == NET_TYPE_ETHERNET) || + (!is_wireless && type == NET_TYPE_WIRELESS)) + continue; + interface = strdup(addrp->ifa_name); + break; + } + + freeifaddrs(ifaddr); + return interface; +} +