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") {
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;
}

View File

@ -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"

View File

@ -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);

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
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)+

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;
}