tImplement network speed monitoring - spoon - dwm status utility (2f30 fork)
 (HTM) git clone git://src.adamsgaard.dk/spoon
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 54051f89a96e8bd68c71e56edffbdac50a62df8e
 (DIR) parent 4fea6b3b6c7b0effabba4f157548ef7c6d83676b
 (HTM) Author: Lucas Gabriel Vuotto <lvuotto92@gmail.com>
       Date:   Wed, 13 Sep 2017 10:24:43 -0300
       
       Implement network speed monitoring
       
       Signed-off-by: Lucas Gabriel Vuotto <lvuotto92@gmail.com>
       Signed-off-by: sin <sin@2f30.org>
       
       Diffstat:
         M Makefile                            |       4 ++--
         A netspeed.c                          |     126 +++++++++++++++++++++++++++++++
         M spoon.c                             |       1 +
         M stub.c                              |       7 +++++++
       
       4 files changed, 136 insertions(+), 2 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       t@@ -1,9 +1,9 @@
        VERSION = 0.4
        PREFIX = /usr/local
        SRC = spoon.c batt.c wifi.c cpu.c temp.c date.c load.c file.c key.c\
       -      strlcpy.c strlcat.c stub.c mix.c xkblayout.c mpd.c
       +      netspeed.c strlcpy.c strlcat.c stub.c mix.c xkblayout.c mpd.c
        OBJ = spoon.o batt.o wifi.o cpu.o temp.o date.o load.o file.o key.o\
       -      strlcpy.o strlcat.o stub.o
       +      netspeed.o strlcpy.o strlcat.o stub.o
        BIN = spoon
        DISTFILES = $(SRC) types.h util.h config.def.h Makefile LICENSE configure
        
 (DIR) diff --git a/netspeed.c b/netspeed.c
       t@@ -0,0 +1,126 @@
       +#include <ctype.h>
       +#include <err.h>
       +#include <inttypes.h>
       +#include <limits.h>
       +#include <stdint.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include "util.h"
       +
       +extern int delay;
       +
       +static const char *humansztbl[] = { " B", "kB", "MB", "GB", "TB", "PB", "EB",
       +    "ZB", "YB" };
       +
       +static int
       +humansz(size_t n)
       +{
       +        int i;
       +        for (i = 0; i < LEN(humansztbl) && n >= 1024; i++)
       +                n /= 1024;
       +        return i;
       +}
       +
       +static void
       +updatenetspeed(char *buf, size_t len, uint64_t rxbytes, uint64_t txbytes)
       +{
       +        static uint64_t oldrxbytes, oldtxbytes;
       +        uint64_t rx, tx;
       +        int irx, itx;
       +        rx = (rxbytes - oldrxbytes) / delay;
       +        tx = (txbytes - oldtxbytes) / delay;
       +        irx = humansz(rx);
       +        itx = humansz(tx);
       +        snprintf(buf, len, "v%6.1f%s/s ^%6.1f%s/s", rx
       +            / (double)(1 << (10 * irx)), humansztbl[irx], tx
       +            / (double)(1 << (10 * itx)), humansztbl[itx]);
       +        oldrxbytes = rxbytes;
       +        oldtxbytes = txbytes;
       +}
       +
       +#ifdef __OpenBSD__
       +#include <sys/socket.h>
       +#include <net/if.h>
       +#include <net/if_dl.h>
       +#include <net/route.h>
       +#include <sys/sysctl.h>
       +
       +int
       +netspeedread(void *arg, char *buf, size_t len)
       +{
       +        int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
       +        char *ifname = arg;
       +        struct rt_msghdr *rtm;
       +        struct if_msghdr *ifm;
       +        struct sockaddr_dl *sdl;
       +        void *lim, *next, *rtmraw;
       +        uint64_t rxbytes, txbytes;
       +        size_t sz;
       +
       +        if (sysctl(mib, 6, NULL, &sz, NULL, 0) < 0)
       +                return -1;
       +        if (!(rtmraw = malloc(sz)))
       +                return -1;
       +        if (sysctl(mib, 6, rtmraw, &sz, NULL, 0) < 0) {
       +                free(rtmraw);
       +                return -1;
       +        }
       +        lim = rtmraw + sz;
       +        rxbytes = txbytes = 0;
       +        for (next = rtmraw; next < lim; next += rtm->rtm_msglen) {
       +                rtm = (struct rt_msghdr *)next;
       +                if (rtm->rtm_version != RTM_VERSION || rtm->rtm_type
       +                    != RTM_IFINFO)
       +                        continue;
       +                ifm = (struct if_msghdr *)next;
       +                sdl = (struct sockaddr_dl *)(next + ifm->ifm_hdrlen);
       +                if (sdl->sdl_family != AF_LINK
       +                    || strncmp(ifname, sdl->sdl_data, sdl->sdl_nlen) != 0)
       +                        continue;
       +                rxbytes = ifm->ifm_data.ifi_ibytes;
       +                txbytes = ifm->ifm_data.ifi_obytes;
       +        }
       +        updatenetspeed(buf, len, rxbytes, txbytes);
       +        free(rtmraw);
       +
       +        return 0;
       +}
       +#elif __linux__
       +int
       +netspeedread(void *arg, char *buf, size_t len)
       +{
       +        char path[PATH_MAX];
       +        FILE *fp;
       +        char *ifname = arg;
       +        unsigned long long rxbytes, txbytes;
       +
       +        (void)snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/rx_bytes", ifname);
       +        if (!(fp = fopen(path, "r"))) {
       +                warn("fopen %s", path);
       +                goto closeandfree;
       +        }
       +        if (fscanf(fp, "%llu", &rxbytes) != 1) {
       +                warn("fscanf %s", path);
       +                goto closeandfree;
       +        }
       +        fclose(fp);
       +        (void)snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/tx_bytes", ifname);
       +        if (!(fp = fopen(path, "r"))) {
       +                warn("fopen %s", path);
       +                goto closeandfree;
       +        }
       +        if (fscanf(fp, "%llu", &txbytes) != 1) {
       +                warn("fscanf %s", path);
       +                goto closeandfree;
       +        }
       +        fclose(fp);
       +
       +        updatenetspeed(buf, len, rxbytes, txbytes);
       +        return 0;
       +
       +closeandfree:
       +        fclose(fp);
       +        return -1;
       +}
       +#endif
 (DIR) diff --git a/spoon.c b/spoon.c
       t@@ -20,6 +20,7 @@ int wifiread(void *, char *, size_t);
        int xkblayoutread(void *, char *, size_t);
        int fileread(void *, char *, size_t);
        int keyread(void *, char *, size_t);
       +int netspeedread(void *, char *, size_t);
        
        struct ent {
                char *fmt;
 (DIR) diff --git a/stub.c b/stub.c
       t@@ -62,3 +62,10 @@ keyread(void *arg, char *buf, size_t len)
        {
                return -1;
        }
       +
       +#pragma weak netspeedread
       +int
       +netspeedread(void *arg, char *buf, size_t len)
       +{
       +        return -1;
       +}