dotfiles/.config/i3blocks/bandwidth2/bandwidth2.c
2019-05-02 02:54:34 +02:00

228 lines
5.5 KiB
C

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#define RED "#FF7373"
#define ORANGE "#FFA500"
typedef unsigned long long int ulli;
enum {
STATE_OK,
STATE_WARNING,
STATE_CRITICAL,
STATE_UNKNOWN,
};
void usage(char *argv[])
{
printf("Usage: %s [-b|B] [-t seconds] [-i interface] [-w Bytes:Bytes] [-c Bytes:Bytes] [-s] [-h]\n", argv[0]);
printf("\n");
printf("-b \t\tuse bits/s\n");
printf("-B \t\tuse Bytes/s (default)\n");
printf("-t seconds\trefresh time (default is 1)\n");
printf("-i interfaces\tnetwork interfaces to monitor (comma separated).\n");
printf(" \tIf not specified, check all interfaces.\n");
printf("-w Bytes:Bytes\tSet warning (color orange) for Rx:Tx bandwidth. (default: none)\n");
printf("-c Bytes:Bytes\tSet critical (color red) for Rx:Tx bandwidth. (default: none)\n");
printf("-s \t\tuse SI units\n");
printf("-h \t\tthis help\n");
printf("\n");
}
void get_values(char **const ifaces, int num_ifaces, time_t * const s, ulli * const received, ulli * const sent)
{
FILE *f;
f = fopen("/proc/net/dev", "r");
if (!f) {
fprintf(stderr, "Can't open /proc/net/dev\n");
exit(STATE_UNKNOWN);
}
ulli temp_r, temp_s;
char line[BUFSIZ] = {0};
char ifname[BUFSIZ];
*received = 0;
*sent = 0;
while (fgets(line, BUFSIZ - 1, f) != NULL) {
if (sscanf(line, "%[^:]: %llu %*u %*u %*u %*u %*u %*u %*u %llu", ifname, &temp_r, &temp_s) == 3) {
int i;
int iface_found = num_ifaces == 0;
for (i = 0; i < num_ifaces; i++) {
if (strcmp(ifaces[i], ifname) != 0) {
iface_found = 1;
break;
}
}
if (!iface_found || strcmp(ifname, "lo") == 0)
continue;
*received = *received + temp_r;
*sent = *sent + temp_s;
}
}
fclose(f);
*s = time(NULL);
if (!s) {
fprintf(stderr, "Can't get Epoch time\n");
exit(STATE_UNKNOWN);
}
}
void display(int const unit, int const divisor,
double b, int const warning, int const critical)
{
char fmtstr[7];
if (critical != 0 && b > critical) {
printf("<span fallback='true' color='%s'>", RED);
} else if (warning != 0 && b > warning) {
printf("<span fallback='true' color='%s'>", ORANGE);
} else {
printf("<span fallback='true'>");
}
if (unit == 'b')
b = b * 8;
snprintf(fmtstr, sizeof (fmtstr), "%%%d.1lf ", divisor > 1000 ? 6 : 5);
if (b < divisor) {
printf(fmtstr, b);
printf(" %c/s", unit);
} else if (b < divisor * divisor) {
printf(fmtstr, b / divisor);
printf("K%c/s", unit);
} else if (b < divisor * divisor * divisor) {
printf(fmtstr, b / (divisor * divisor));
printf("M%c/s", unit);
} else {
printf(fmtstr, b / (divisor * divisor * divisor));
printf("G%c/s", unit);
}
printf("</span>");
}
void parse_ifaces(char *str, char ***ifaces, int *num_ifaces)
{
int max_ifaces = strlen(str) / 2 + 1;
*ifaces = calloc(max_ifaces, sizeof (char *));
*num_ifaces = 0;
while (((*ifaces)[*num_ifaces] = strsep(&str, ","))) {
if ((*ifaces)[*num_ifaces] != NULL && (*ifaces)[*num_ifaces][0] != '\0') {
(*num_ifaces)++;
}
}
}
int main(int argc, char *argv[])
{
int c, unit = 'B', t = 1;
char str_ifaces[BUFSIZ] = {0};
char **ifaces;
int num_ifaces;
int warningrx = 0, warningtx = 0, criticalrx = 0, criticaltx = 0;
int divisor = 1024;
char *envvar = NULL;
char *label = "";
envvar = getenv("USE_BITS");
if (envvar && *envvar == '1')
unit = 'b';
envvar = getenv("USE_BYTES");
if (envvar && *envvar == '1')
unit = 'B';
envvar = getenv("REFRESH_TIME");
if (envvar)
t = atoi(envvar);
envvar = getenv("INTERFACE");
if (envvar)
snprintf(str_ifaces, BUFSIZ, "%s", envvar);
envvar = getenv("INTERFACES");
if (envvar)
snprintf(str_ifaces, BUFSIZ, "%s", envvar);
envvar = getenv("WARN_RX");
if (envvar)
warningrx = atoi(envvar);
envvar = getenv("WARN_TX");
if (envvar)
warningtx = atoi(envvar);
envvar = getenv("CRIT_RX");
if (envvar)
criticalrx = atoi(envvar);
envvar = getenv("CRIT_TX");
if (envvar)
criticaltx = atoi(envvar);
envvar = getenv("USE_SI");
if (envvar && *envvar == '1')
divisor = 1000;
envvar = getenv("LABEL");
if (envvar)
label = envvar;
while (c = getopt(argc, argv, "bBsht:i:w:c:"), c != -1) {
switch (c) {
case 'b':
case 'B':
unit = c;
break;
case 't':
t = atoi(optarg);
break;
case 'i':
snprintf(str_ifaces, BUFSIZ, "%s", optarg);
break;
case 'w':
sscanf(optarg, "%d:%d", &warningrx, &warningtx);
break;
case 'c':
sscanf(optarg, "%d:%d", &criticalrx, &criticaltx);
break;
case 's':
divisor = 1000;
break;
case 'h':
usage(argv);
return STATE_UNKNOWN;
}
}
parse_ifaces(str_ifaces, &ifaces, &num_ifaces);
time_t s, s_old;
ulli received, sent, received_old, sent_old;
double rx, tx;
get_values(ifaces, num_ifaces, &s_old, &received_old, &sent_old);
while (1) {
sleep(t);
get_values(ifaces, num_ifaces, &s, &received, &sent);
rx = (received - received_old) / (float)(s - s_old);
tx = (sent - sent_old) / (float)(s - s_old);
printf("%s", label);
display(unit, divisor, rx, warningrx, criticalrx);
printf(" ");
display(unit, divisor, tx, warningtx, criticaltx);
printf("\n");
fflush(stdout);
s_old = s;
received_old = received;
sent_old = sent;
}
free(ifaces);
return STATE_OK;
}