]> git.sur5r.net Git - i3/i3status/blobdiff - src/first_network_device.c
Unit testing in Travis (#170)
[i3/i3status] / src / first_network_device.c
index 16f23e07702f4f42ab031987adbacfccf38b035d..541aabb4d69daa2cf032b07d7445efb00a71aa3b 100644 (file)
@@ -1,15 +1,63 @@
 // vim:ts=4:sw=4:expandtab
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <ifaddrs.h>
 
 #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);
 
@@ -31,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;