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).
This commit is contained in:
Michael Stapelberg 2014-12-07 15:14:02 +01:00
parent 7bdfb5b72e
commit b219f47f39
5 changed files with 68 additions and 6 deletions

View File

@ -576,13 +576,23 @@ int main(int argc, char *argv[]) {
CASE_SEC_TITLE("wireless") { CASE_SEC_TITLE("wireless") {
SEC_OPEN_MAP("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; SEC_CLOSE_MAP;
} }
CASE_SEC_TITLE("ethernet") { CASE_SEC_TITLE("ethernet") {
SEC_OPEN_MAP("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; SEC_CLOSE_MAP;
} }

View File

@ -15,18 +15,18 @@ order += "ipv6"
order += "disk /" order += "disk /"
order += "run_watch DHCP" order += "run_watch DHCP"
order += "run_watch VPN" order += "run_watch VPN"
order += "wireless wlan0" order += "wireless _first_"
order += "ethernet eth0" order += "ethernet _first_"
order += "battery 0" order += "battery 0"
order += "load" order += "load"
order += "tztime local" order += "tztime local"
wireless wlan0 { wireless _first_ {
format_up = "W: (%quality at %essid) %ip" format_up = "W: (%quality at %essid) %ip"
format_down = "W: down" format_down = "W: down"
} }
ethernet eth0 { ethernet _first_ {
# if you use %speed, i3status requires root privileges # if you use %speed, i3status requires root privileges
format_up = "E: %ip (%speed)" format_up = "E: %ip (%speed)"
format_down = "E: down" format_down = "E: down"

View File

@ -170,6 +170,13 @@ char *auto_detect_format();
/* src/print_time.c */ /* src/print_time.c */
void set_timezone(const char *tz); 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_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_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); 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);

View File

@ -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 interface. You can specify different format strings for the network being
connected or not connected. 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 order*: +wireless wlan0+
*Example format*: +W: (%quality at %essid, %bitrate / %frequency) %ip+ *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 interface. Getting the link speed requires the cap_net_admin capability. Set
it using +setcap cap_net_admin=ep $(which i3status)+. 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 order*: +ethernet eth0+
*Example format*: +E: %ip (%speed)+ *Example format*: +E: %ip (%speed)+

View File

@ -0,0 +1,39 @@
// vim:ts=8:expandtab
#include <sys/stat.h>
#include <stdlib.h>
#include <ifaddrs.h>
#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;
}