diff options
| -rw-r--r-- | include/i3status.h | 3 | ||||
| -rw-r--r-- | src/first_network_device.c | 57 | 
2 files changed, 53 insertions, 7 deletions
| diff --git a/include/i3status.h b/include/i3status.h index b4cf83f..4d2d0f1 100644 --- a/include/i3status.h +++ b/include/i3status.h @@ -202,7 +202,8 @@ void set_timezone(const char *tz);  /* src/first_network_device.c */  typedef enum {      NET_TYPE_WIRELESS = 0, -    NET_TYPE_ETHERNET = 1 +    NET_TYPE_ETHERNET = 1, +    NET_TYPE_OTHER = 2  } net_type_t;  const char *first_eth_interface(const net_type_t type); diff --git a/src/first_network_device.c b/src/first_network_device.c index 06d8b4a..541aabb 100644 --- a/src/first_network_device.c +++ b/src/first_network_device.c @@ -6,11 +6,58 @@  #include "i3status.h" +static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) { +    FILE *fp; +    char buf[1024]; + +    snprintf(buf, sizeof(buf), "/sys/class/net/%s/uevent", ifnam); +    if ((fp = fopen(buf, "r")) == NULL) +        return false; + +    dest[0] = '\0'; + +    while (fgets(buf, sizeof(buf), fp)) { +        size_t slen; +        char *s; + +        slen = strlen(buf); +        /* Line is too long to fit in the buffer */ +        if (buf[slen - 1] != '\n' && !feof(fp)) +            break; +        if ((s = strchr(buf, '='))) { +            if (strncmp(buf, "DEVTYPE", s - buf)) +                continue; +            buf[slen - 1] = '\0'; +            strncpy(dest, ++s, n); +            break; +        } +    } +    fclose(fp); +    return true; +} + +static net_type_t iface_type(const char *ifname) { +    char devtype[32]; + +    if (!sysfs_devtype(devtype, sizeof(devtype), ifname)) +        return NET_TYPE_OTHER; + +    if (!devtype[0]) +        return NET_TYPE_ETHERNET; + +    if (strcmp(devtype, "wlan") == 0) +        return NET_TYPE_WIRELESS; + +    if (strcmp(devtype, "wwan") == 0) +        return NET_TYPE_OTHER; + +    return NET_TYPE_OTHER; +} +  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]; +    net_type_t iftype;      getifaddrs(&ifaddr); @@ -32,10 +79,8 @@ const char *first_eth_interface(const net_type_t type) {              addrp->ifa_addr->sa_family != AF_INET6)              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)) +        iftype = iface_type(addrp->ifa_name); +        if (iftype != type)              continue;          interface = strdup(addrp->ifa_name);          break; | 
