ftp.nice.ch/peanuts/GeneralData/Documents/user-groups/rmNUG/dialupip.tar.gz#/dialupip/src/dialmon/dialmond.c

This is dialmond.c in view mode; [Download] [Up]

/*
**  Copyright (c) 1991 Bolt Beranek and Newman, Inc.
**  All rights reserved.
**
**  Redistribution and use in source and binary forms are permitted
**  provided that: (1) source distributions retain this entire copyright
**  notice and comment, and (2) distributions including binaries display
**  the following acknowledgement:  ``This product includes software
**  developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
**  documentation or other materials provided with the distribution and in
**  all advertising materials mentioning features or use of this software.
**  Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
**  to endorse or promote products derived from this software without
**  specific prior written permission.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
**  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
#include <nlist.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#ifdef	sun
#include <sys/param.h>
#endif	/* sun */
#include <sys/dk.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <net/if_du.h>
#include "dialupip.h"
#include "dialmon.h"


#define INTERVAL	5	/* Seconds between samples	*/
#define VMUNIX		"/vmunix"
#define KMEM		"/dev/kmem"

/* wish list for kernel symbols */
static struct nlist	nlst[] = {
    { "_du_softc" },
#define X_DU_SOFTC	0
    { "_globdialstats" },
#define X_GLOBDIALSTATS	1
    { "_cp_time" },
#define X_CP_TIME	2
    { "_avenrun" },
#define X_AVENRUN	3
    { NULL },
};

static int	fpkmem;		/* descriptor for /dev/kmem */
static FILE	*log;

extern char	*progname;

extern int		errno;
extern int		optind;
extern long		lseek();
extern unsigned int	sleep();
extern void		exit();
extern char		*strerror();



/*
**  Print error message and exit.
*/
static void
fatal(p)
    char	*p;
{
    if (log)
	(void)fprintf(log, "%s: %s, %s\n", progname, p, strerror(errno));
    exit(1);
}


/*
**  Read something from /dev/kmem.
*/
static void
readkernel(i, buff, size)
    int		i;
    char	*buff;
    int		size;
{
    char	log[80];

    if (lseek(fpkmem, (long)nlst[i].n_value, 0) == -1) {
	(void)sprintf(log, "Can't lseek to %ld (symbol #%d)",
	    (long)nlst[i].n_value, i);
	fatal(log);
    }
    if (read(fpkmem, buff, size) < 0)
	fatal("Can't read kmem");
}


/*
**  Copy some fields from the CYLN structure into the LINESTATUS part.
**  Returns the size of the structure.
*/
static void
CopyLineStats(sp, dup)
    DIALSTATS		*sp;
    struct du_softc	*dup;
{
    int			i;
    LINESTATS		*lsp;

    /* Size of Stats structure without the line variables. */
    for (lsp = sp->ln, i = 0; i < sp->ndu; lsp++, i++, dup++)
	if (dup->ds_if.if_flags & IFF_UP) {
            lsp->ln = (char)i;
	    lsp->cchr = dup->ds_cchr;
	    lsp->cchs = dup->ds_cchs;
	    lsp->cpsip = dup->ds_cpsip;
	    lsp->cprip = dup->ds_cprip;
	    lsp->flags = dup->ds_flags;
            lsp->ctpbusy = dup->ds_ctpbusy;
            lsp->ctpidle = dup->ds_ctpidle;
	    lsp->sesc = dup->ds_sesc;
	    lsp->resc = dup->ds_resc;
	    lsp->ierror = dup->ds_if.if_ierrors;
	    lsp->oerror = dup->ds_if.if_oerrors;
	}
	else
	    lsp->ln = (unsigned long)-1;
}


/*
**  Convert fields in struct to network order.
*/
static void
ToNetworkOrder(sp)
    DIALSTATS		*sp;
{
    int			i;
    unsigned long	ul;
    LINESTATS		*lsp;

    ul = sp->when;
    sp->when = htonl(ul);
    for (i = 0; i < 3; i++)
	sp->avenrun[i] = htonl(sp->avenrun[i]);
    for (i = 0; i < CPUSTATES; i++)
	sp->cputime[i] = htonl(sp->cputime[i]);
    sp->ipup = htonl(sp->ipup);
    sp->ipln = htonl(sp->ipln);
    sp->opln = htonl(sp->opln);
    sp->opup = htonl(sp->opup);
    sp->ndu = htonl(sp->ndu);
    for (lsp = sp->ln; lsp < &sp->ln[sp->ndu]; lsp++) {
	lsp->cchr = htonl(lsp->cchr);
	lsp->cchs = htonl(lsp->cchs);
	lsp->cpsip = htonl(lsp->cpsip);
	lsp->cprip = htonl(lsp->cprip);
	lsp->flags = htonl(lsp->flags);
	lsp->ctpbusy = htonl(lsp->ctpbusy);
	lsp->ctpidle = htonl(lsp->ctpidle);
	lsp->sesc = htonl(lsp->sesc);
	lsp->resc = htonl(lsp->resc);
	lsp->dest.s_addr = htonl(lsp->dest.s_addr);
	lsp->ierror = htonl(lsp->ierror);
	lsp->oerror = htonl(lsp->oerror);
	lsp->ln = htonl(lsp->ln);
    }
}



/*
**  Main client routine to print statistics.
*/
static void
sendstats(f)
    int			f;
{
    struct globdialstats gstats;
    struct du_softc	du_softc[MAX_NDU];
    struct timeval	tv;
    DIALSTATS		Stats;
    int			i;
    unsigned long	size;
    long		cpuold[CPUSTATES];
    long		cpucur[CPUSTATES];
#ifdef	sun
    int			avenrun[3];
#else
    double		avenrun[3];
#endif	/* sun */

    if ((fpkmem = open(KMEM, 0)) < 0)
        fatal("Can't open kmem");
    nlist(VMUNIX, nlst);
    if (nlst[0].n_type == 0)
        fatal("Can't nlist /vmunix");

    for (i = 0; i < CPUSTATES; i++)
	cpuold[i] = cpucur[i] = 0;

    for ( ; ; ) {
	/* Get global status values, copy into the local area. */
 	readkernel(X_GLOBDIALSTATS, (char *)&gstats, sizeof gstats);
	Stats.ipup = gstats.gds_ipup;
	Stats.ipln = gstats.gds_ipln;
	Stats.opln = gstats.gds_opln;
	Stats.opup = gstats.gds_opup;
	Stats.ndu = gstats.gds_ndu;

        /* get line stat values */
 	readkernel(X_DU_SOFTC, (char *)du_softc, sizeof du_softc);
        CopyLineStats(&Stats, du_softc);

	/* Get the load average. */
 	readkernel(X_AVENRUN, (char *)avenrun, sizeof avenrun);
#ifdef	sun
	for (i = 0; i < 3; i++)
	    Stats.avenrun[i] = (unsigned long)(avenrun[i] / (FSCALE / 100));
#else
	for (i = 0; i < 3; i++)
	    Stats.avenrun[i] = (unsigned long)(avenrun[i] * 100);
#endif	/* sun */

	/* Get amount of CPU time in USER/NICE/SYS/IDLE state. */
 	readkernel(X_CP_TIME, (char *)cpucur, sizeof cpucur);
	for (i = 0; i < CPUSTATES; i++) {
	    if (cpucur[i] < cpuold[i])
                /* Counter wrapped around */
		Stats.cputime[i] =
		    (unsigned long)cpucur[i] - (unsigned long)cpuold[i];
	    else
		Stats.cputime[i] = cpucur[i] - cpuold[i];
            cpuold[i] = cpucur[i];
	}

        /* Get time this structure was made */
	if (gettimeofday(&tv, (struct timezone *)NULL) < 0)
            fatal("Can't do gettimeofday");
	Stats.when = tv.tv_sec;

	/* Convert to network order.  Write the length, in net order,
	 * then the buffer. */
	ToNetworkOrder(&Stats);
	size = sizeof Stats;
	size = htonl(size);
	(void)write(f, (char *)&size, sizeof size);
	size = htonl(size);
	i = write(f, (char *)&Stats, (int)size);
	if (i < size)
	    fatal("write");

	(void)sleep(INTERVAL);
    }
}


static void
usage()
{
    (void)fprintf(stderr, "usage: %s\n", progname);
    exit(1);
}

main(argc, argv)
    int			argc;
    char		*argv[];
{
    int			i;

    /* Set defaults. */
    log = NULL;
    setprogname(argv[0]);

    /* Parse arguments. */
    while ((i = getopt(argc, argv, "")) != EOF)
	switch (i) {
	default:
	    usage();
	    /* NOTREACHED */
	}
    argc -= optind;
    argv += optind;
    if (argc)
	usage();

    /* Set the log file. */
    if ((log = fopen(DIALMOND_LOG, "a")) == NULL)
	 log = fopen("/dev/console", "w");

    /* All inetd's put the incoming socket on stdin, so... */
    sendstats(0);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.