On Sun, Jul 28, 2013 at 06:11:39PM +0200, Markus Teich wrote:
> Am 2013-07-27 18:27, schrieb Martti Kühne:
> >On Mon, Jul 22, 2013 at 3:17 PM, Markus Teich
> ><markus.te...@stusta.mhn.de> wrote:
> >>
> >>rx_now=0
> >>tx_now=0
> >>for i in /sys/class/net/*; do
> >>        if [[ -d "$i" && ${i##*/} != "lo" ]]; then
> >>                if [[ -f "$i/statistics/rx_bytes" ]]; then
> >>                        rx_now=($rx_now+`cat $i/statistics/rx_bytes`)
> >>                fi
> >>                if [[ -f "$i/statistics/tx_bytes" ]]; then
> >>                        tx_now=($tx_now+`cat $i/statistics/tx_bytes`)
> >>                fi
> >>        fi
> >>done
> >>let rx_rate=($rx_now-$rx_old)
> >>let tx_rate=($tx_now-$tx_old)
> >>
> >Might I ask what shell dialect is that written in? O_o
> 
> Bash patched together with some stackoverflow answers.
> It probably is not beautiful, but it works for me until I finally have
> the time to write it in C. :/

I included some changes suggested by Markus in a rewrite of the netusage
functions for dwmstatus (attached; including an adapted dwmstatus-Makefile
for convenience).

Comments and criticism is welcome.

I will try to push a change request to the suckless sites git repo if
nobody threats to neuter my hamster over the code I wrote...


Cheers,

Silvan

#define _BSD_SOURCE
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <X11/Xlib.h>

char *tzargentina = "America/Buenos_Aires";
char *tzutc = "UTC";
char *tzberlin = "Europe/Berlin";

static Display *dpy;

char *
smprintf(char *fmt, ...)
{
	va_list fmtargs;
	char *ret;
	int len;

	va_start(fmtargs, fmt);
	len = vsnprintf(NULL, 0, fmt, fmtargs);
	va_end(fmtargs);

	ret = malloc(++len);
	if (ret == NULL) {
		perror("malloc");
		exit(1);
	}

	va_start(fmtargs, fmt);
	vsnprintf(ret, len, fmt, fmtargs);
	va_end(fmtargs);

	return ret;
}

void
settz(char *tzname)
{
	setenv("TZ", tzname, 1);
}

int
parse_netdev(unsigned long long int *receivedabs, unsigned long long int *sentabs)
{
	char buf[255];
	char *datastart;
	static int bufsize;
	int rval;
	FILE *devfd;
	unsigned long long int receivedacc, sentacc;

	bufsize = 255;
	devfd = fopen("/proc/net/dev", "r");
	rval = 1;

	// Ignore the first two lines of the file
	fgets(buf, bufsize, devfd);
	fgets(buf, bufsize, devfd);

	while (fgets(buf, bufsize, devfd)) {
	    if ((datastart = strstr(buf, "lo:")) == NULL) {
		datastart = strstr(buf, ":");

		// With thanks to the conky project at http://conky.sourceforge.net/
		sscanf(datastart + 1, "%llu  %*d     %*d  %*d  %*d  %*d   %*d        %*d       %llu",\
		       &receivedacc, &sentacc);
		*receivedabs += receivedacc;
		*sentabs += sentacc;
		rval = 0;
	    }
	}

	fclose(devfd);
	return rval;
}

void
calculate_speed(char *speedstr, unsigned long long int newval, unsigned long long int oldval)
{
	double speed;
	speed = (newval - oldval) / 1024.0;
	if (speed > 1024.0) {
	    speed /= 1024.0;
	    sprintf(speedstr, "%.3f MB/s", speed);
	} else {
	    sprintf(speedstr, "%.2f KB/s", speed);
	}
}

char *
get_netusage(unsigned long long int *rec, unsigned long long int *sent)
{
	unsigned long long int newrec, newsent;
	newrec = newsent = 0;
	char downspeedstr[15], upspeedstr[15];
	static char retstr[42];
	int retval;

	retval = parse_netdev(&newrec, &newsent);
	if (retval) {
	    fprintf(stdout, "Error when parsing /proc/net/dev file.\n");
	    exit(1);
	}

	calculate_speed(downspeedstr, newrec, *rec);
	calculate_speed(upspeedstr, newsent, *sent);

	sprintf(retstr, "down: %s up: %s", downspeedstr, upspeedstr);

	*rec = newrec;
	*sent = newsent;
	return retstr;
}

char *
mktimes(char *fmt, char *tzname)
{
	char buf[129];
	time_t tim;
	struct tm *timtm;

	bzero(buf, sizeof(buf));
	settz(tzname);
	tim = time(NULL);
	timtm = localtime(&tim);
	if (timtm == NULL) {
		perror("localtime");
		exit(1);
	}

	if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) {
		fprintf(stderr, "strftime == 0\n");
		exit(1);
	}

	return smprintf("%s", buf);
}

void
setstatus(char *str)
{
	XStoreName(dpy, DefaultRootWindow(dpy), str);
	XSync(dpy, False);
}

char *
loadavg(void)
{
	double avgs[3];

	if (getloadavg(avgs, 3) < 0) {
		perror("getloadavg");
		exit(1);
	}

	return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
}

int
main(void)
{
	char *status;
	char *avgs;
	char *tmar;
	char *tmutc;
	char *tmbln;
	char *netstats;
	static unsigned long long int rec, sent;

	if (!(dpy = XOpenDisplay(NULL))) {
		fprintf(stderr, "dwmstatus: cannot open display.\n");
		return 1;
	}

	parse_netdev(&rec, &sent);
	for (;;sleep(1)) {
		avgs = loadavg();
		tmar = mktimes("%H:%M", tzargentina);
		tmutc = mktimes("%H:%M", tzutc);
		tmbln = mktimes("KW %W %a %d %b %H:%M %Z %Y", tzberlin);
		netstats = get_netusage(&rec, &sent);

		status = smprintf("[L: %s|N: %s|A: %s|U: %s|%s]",
				avgs, netstats, tmar, tmutc, tmbln);
		setstatus(status);
		free(avgs);
		free(tmar);
		free(tmutc);
		free(tmbln);
		free(status);
	}

	XCloseDisplay(dpy);

	return 0;
}

# See LICENSE file for copyright and license details.

include config.mk

SRC = ${NAME}.c
OBJ = ${SRC:.c=.o}

all: options ${NAME}

options:
        @echo ${NAME} build options:
        @echo "CFLAGS   = ${CFLAGS}"
        @echo "LDFLAGS  = ${LDFLAGS}"
        @echo "CC       = ${CC}"

.c.o:
        @echo CC $<
        @${CC} -c ${CFLAGS} $<

${OBJ}: config.mk

${NAME}: ${OBJ}
        @echo CC -o $@
        @${CC} -o $@ ${OBJ} ${LDFLAGS}

clean:
        @echo cleaning
        @rm -f ${NAME} ${OBJ} ${NAME}-${VERSION}.tar.gz

dist: clean
        @echo creating dist tarball
        @mkdir -p ${NAME}-${VERSION}
        @cp -R Makefile config.mk LICENSE \
                ${SRC} ${NAME}-${VERSION}
        @tar -cf ${NAME}-${VERSION}.tar ${NAME}-${VERSION}
        @gzip ${NAME}-${VERSION}.tar
        @rm -rf ${NAME}-${VERSION}

install: all
        @echo installing executable file to ${DESTDIR}${PREFIX}/bin
        @mkdir -p ${DESTDIR}${PREFIX}/bin
        @cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
        @chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}

uninstall:
        @echo removing executable file from ${DESTDIR}${PREFIX}/bin
        @rm -f ${DESTDIR}${PREFIX}/bin/${NAME}

.PHONY: all options clean dist install uninstall
NAME = dwmstatus-netusage
VERSION = 1.2

# Customize below to fit your system

# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man

X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib

# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11

# flags
CPPFLAGS = -DVERSION=\"${VERSION}\"
CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -g ${LIBS}
#LDFLAGS = -s ${LIBS}

# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}

# compiler and linker
CC = cc

Attachment: pgp0n5W3dEW9R.pgp
Description: PGP signature

Reply via email to