/*
* Copyright (c) 2002 Peter Memishian (meem) <meem@gnu.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* wmnetload - A dockapp to monitor network interface usage.
* Inspired by Seiichi SATO's nifty CPU usage monitor.
*
* Linux-specific interface statistics gathering routines.
*/
#pragma ident "@(#)ifstat_linux.c 1.3 02/10/27 meem"
#include <config.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ifstat.h"
#include "utils.h"
#define WN_PND_MAX 1024 /* see rant below */
struct ifstatstate {
int rbindex; /* receive byte count index */
int tbindex; /* transmit byte count index */
FILE *fp;
};
/*
* Do one-time setup stuff for accessing the interface statistics and store
* the gathered information in an interface statistics state structure.
* Return the state structure.
*/
ifstatstate_t *
if_statinit(void)
{
char line[WN_PND_MAX];
const char *seps = " :\t|";
char *token;
unsigned int i;
ifstatstate_t *statep;
statep = malloc(sizeof (ifstatstate_t));
if (statep == NULL) {
warn("cannot allocate interface statistics state");
return (NULL);
}
/*
* This has to be one of the most vile interfaces ever conceived.
* In a word: pathetic. The Linux community should be ashamed.
*/
statep->fp = fopen("/proc/net/dev", "r");
if (statep->fp == NULL)
goto openfail;
statep->rbindex = -1;
statep->tbindex = -1;
/*
* Find the line with the column headers.
*/
for (;;) {
if (fgets(line, sizeof (line), statep->fp) == NULL)
goto parsefail;
if (strstr(line, "bytes") != NULL)
break;
}
/*
* Figure out which columns are associated with which statistics;
* blithely assume that "receive" is before "transmit".
*/
token = strtok(line, seps);
for (i = 0; token != NULL; i++) {
if (strcmp(token, "bytes") == 0) {
if (statep->rbindex == -1)
statep->rbindex = i;
else
statep->tbindex = i;
}
token = strtok(NULL, seps);
}
if (statep->rbindex == -1 || statep->tbindex == -1)
goto parsefail;
return (statep);
openfail:
free(statep);
warn("cannot open /proc/net/dev; no stats will be available\n");
return (NULL);
parsefail:
(void) fclose(statep->fp);
free(statep);
warn("cannot parse /proc/net/dev; no stats will be available\n");
return (NULL);
}
/*
* Optionally using state stored in `statep', retrieve stats on interface
* `ifname', and store the statistics in `ifstatsp'.
*/
int
if_stats(const char *ifname, ifstatstate_t *statep, ifstats_t *ifstatsp)
{
char line[WN_PND_MAX];
const char *seps = " :\t|";
char *token;
unsigned int i;
statep->fp = freopen("/proc/net/dev", "r", statep->fp);
if (statep->fp == NULL)
return (0);
do {
if (fgets(line, sizeof (line), statep->fp) == NULL)
return (0);
token = strtok(line, seps);
if (token == NULL)
return (0);
} while (strcmp(token, ifname) != 0);
/*
* Found the right line; just read in the stats.
*/
for (i = 1; token != NULL; i++) {
token = strtok(NULL, seps);
if (i == statep->rbindex)
ifstatsp->rxbytes = strtoll(token, NULL, 0);
else if (i == statep->tbindex)
ifstatsp->txbytes = strtoll(token, NULL, 0);
if (i >= statep->rbindex && i >= statep->tbindex)
return (1);
}
return (0);
}
/*
* Clean up the interface state structure pointed to by `statep'.
*/
void
if_statfini(ifstatstate_t *statep)
{
(void) fclose(statep->fp);
free(statep);
}
syntax highlighted by Code2HTML, v. 0.9.1