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.