diff options
Diffstat (limited to 'src/first_network_device.c')
-rw-r--r-- | src/first_network_device.c | 57 |
1 files changed, 51 insertions, 6 deletions
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; |