[pe.cust.sources] Neat little program for XELOS

earlw@pesnta.UUCP (Earl Wallace) (06/28/85)

This program compiles and runs under XELOS R01 and should run on R00. It
is another in the unfinished-project series of programs.  

	To compile:
		cc -O -n -o dstats dstats.c -lcurses

	To run:
		dstats		(updates screen every 5 seconds)
		dstats n 	(updates screen every 'n' seconds)

	The program:
		
/*
 * dstats - cute little sysinfo display map with interval updates
 *
 *	 June 1985 earlw@pesnta
 */

#include <stdio.h>
#include <curses.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/times.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <time.h>

#define	INTERVAL	5

extern	int	errno;
extern	char	*ctime(), *buildline();
extern	long 	lseek(), time(), times();
extern	unsigned sleep();
extern	void	update(), display(), diff(), strap();

struct	sysinfo	Sysinfo[3];			/* sysinfo stuff */
struct	utsname	Uts;				/* naming struct */
struct	tms	Tms;				/* process times */
struct	tm 	Tm;				/* local time */
int 	sysinfo_fd;
char	crtbuf[2000];

main(argc, argv)
int  argc;
char *argv[];
{
	register struct	sysinfo	*b0 = &Sysinfo[0];
	register struct	sysinfo	*b1 = &Sysinfo[1];
	register struct	sysinfo	*br = &Sysinfo[2];
	register long 	elasped, base, stop;
	register int	cnt;
	int 	 interval = INTERVAL, curmode;
	long	 curtime;
	char	 *tp;

	if (argc > 1)
		interval = atoi(argv[1]);

	for (cnt=0; cnt < 20; cnt++)		/* catch all signals */
		signal(cnt, strap);

	if ((sysinfo_fd=open("/dev/sysinfo", O_RDONLY)) < 0) {
		fprintf(stderr, "can't open /dev/sysinfo - ");
		perror("");
		exit(1);
	}

	/* 
	 * get system name
	 */
	if (uname(&Uts) < 0) {
		fprintf(stderr, "can't get system name\n");
		exit(9);
	}

	/*
	 * since we are starting, we get our base time and do the initial
	 * load of the sysinfo structure, after this we alternate buffers.
	 */
	initscr();				/* init screen */
	base = times(&Tms);			/* this is our base time */
	update(b1);				/* update structures set b1 */

	/*
	 * display time each second and update stats every interval seconds,
	 * do this forever.
	 */
	for (;;) {

		/* 
		 * print date/time each second
		 */
		for (cnt=0; cnt < interval; cnt++) {
			time(&curtime);		/* get current time */
			tp = ctime(&curtime);	/* convert time to string */
			tp[24] = '\0';		/* null out the newline */
			move(0,0);		/* row 1, col 1 */
			printw("%s %s %s %s %s %s", 
				tp, Uts.sysname, Uts.nodename,
				Uts.release, Uts.version, Uts.machine);	
			move(23,79);		/* row 24, col 80 */
			refresh();		/* refresh screen */
			sleep(1);		/* sleep one second */
		}
	
		/*
		 * do stats update
		 */
		if (curmode == 0) {
			update(b0);		/* update structures set b0 */
			stop = times(&Tms);	/* get stop time */
			elasped = stop - base;	/* get elasped time */
			base += elasped;	/* new base value */
			diff(b0, b1, br); 	/* b0 - b1 = br */
			curmode = 1;		/* switch mode */
		} else {
			update(b1);		/* update structures set b1 */
			stop = times(&Tms);	/* get stop time */
			elasped = stop - base;	/* get elasped time */
			base += elasped;	/* new base value */
			diff(b1, b0, br); 	/* b1 - b0 = br */
			curmode = 0;		/* switch mode */
		}
		display(br, elasped);		/* display results */
	}
}

/*
 * update sysinfo structure
 */

void
update(bx)
register struct	sysinfo	*bx;
{
	register long cnt;

	lseek(sysinfo_fd, 0L, 0);			/* rewind ? */
	if ((cnt=read(sysinfo_fd, bx, sizeof sysinfo)) < 0 || 
	     cnt != sizeof sysinfo) {
		endwin();			/* shutdown curses */
		fprintf(stderr, "Sysinfo read failed, want %d, got %d - ", 
			sizeof sysinfo, cnt);
		perror("");
		exit(10);
	}
}

/*
 * catch those signals if we can, we may miss one sometimes....
 */

void
strap(sno)
register int sno;
{
	clear();
	endwin();	
	exit(sno);
}

/* 
 * determine differences via brute force method
 *	diff(bx, by, br);	bx - by = br
 */

void
diff(bx, by, br)
register struct	sysinfo	*bx, *by, *br;
{
	br->cpu[CPU_IDLE]   = bx->cpu[CPU_IDLE]   - by->cpu[CPU_IDLE];
	br->cpu[CPU_USER]   = bx->cpu[CPU_USER]   - by->cpu[CPU_USER];
	br->cpu[CPU_KERNAL] = bx->cpu[CPU_KERNAL] - by->cpu[CPU_KERNAL];
	br->cpu[CPU_WAIT]   = bx->cpu[CPU_WAIT]   - by->cpu[CPU_WAIT];
	br->wait[W_IO]      = bx->wait[W_IO]      - by->wait[W_IO];
	br->wait[W_SWAP]    = bx->wait[W_SWAP]    - by->wait[W_SWAP];
	br->wait[W_PIO]     = bx->wait[W_PIO]     - by->wait[W_PIO];
	br->bread           = bx->bread           - by->bread;
	br->bwrite          = bx->bwrite          - by->bwrite;
	br->lread           = bx->lread           - by->lread;  
	br->lwrite          = bx->lwrite          - by->lwrite; 
	br->phread          = bx->phread          - by->phread;
	br->phwrite         = bx->phwrite         - by->phwrite;
	br->swapin          = bx->swapin          - by->swapin;
	br->swapout         = bx->swapout         - by->swapout;
	br->bswapin         = bx->bswapin         - by->bswapin;
	br->bswapout        = bx->bswapout        - by->bswapout;
	br->pswitch         = bx->pswitch         - by->pswitch;
	br->syscall         = bx->syscall         - by->syscall;
	br->sysread         = bx->sysread         - by->sysread;
	br->syswrite        = bx->syswrite        - by->syswrite;
	br->sysfork         = bx->sysfork         - by->sysfork;
	br->sysexec         = bx->sysexec         - by->sysexec;
	br->runque          = bx->runque          - by->runque;
	br->runocc          = bx->runocc          - by->runocc;
	br->swpque          = bx->swpque          - by->swpque;
	br->swpocc          = bx->swpocc          - by->swpocc;
	br->iget            = bx->iget            - by->iget;
	br->namei           = bx->namei           - by->namei;
	br->dirblk          = bx->dirblk          - by->dirblk;
	br->readch          = bx->readch          - by->readch;
	br->writech         = bx->writech         - by->writech;
	br->rcvint          = bx->rcvint          - by->rcvint;
	br->xmtint          = bx->xmtint          - by->xmtint;
	br->mdmint          = bx->mdmint          - by->mdmint;
	br->rawch           = bx->rawch           - by->rawch;
	br->canch           = bx->canch           - by->canch;
	br->outch           = bx->outch           - by->outch;
	br->msg             = bx->msg             - by->msg;
	br->sema            = bx->sema            - by->sema;
}

/*
 * display results
 */

void
display(br, et)
register struct	sysinfo	*br;
register long	et;
{
	register float	scale, sec, fl;

	scale = 100.0/(float)et;		/* scale for percentages */
	sec = (float)et/(float)Tms.tms_cfreq;	/* convert to seconds */

	move(2,0);	
	fl = scale * (float)br->cpu[CPU_USER];
	printw("cpu/user   %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(3,0);		
	fl = scale * (float)br->cpu[CPU_KERNAL];
	printw("cpu/kernel %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(4,0);			
	fl = scale * (float)br->cpu[CPU_IDLE];
	printw("cpu/idle   %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(5,0);				
	fl = scale * (float)br->cpu[CPU_WAIT];
	printw("cpu/wait   %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(6,0);				
	fl = scale * (float)br->wait[W_IO];
	printw("wait/io    %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(7,0);				
	fl = scale * (float)br->wait[W_SWAP];
	printw("wait/swap  %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(8,0);				
	fl = scale * (float)br->wait[W_PIO];
	printw("wait/pio   %5.1f%%: %s", fl, buildline(fl, 60)); 

	move(10,0);				
	printw("%7.1f bread/s     %7.1f bwrite/s    ",
		(float)br->bread / sec,
		(float)br->bwrite / sec);
	printw("%7.1f lread/s     %7.1f lwrite/s    ",
		(float)br->lread / sec,
		(float)br->lwrite / sec);
	move(11,0);				
	printw("%7.1f phread/s    %7.1f phwrite/s   ",
		(float)br->phread / sec,
		(float)br->phwrite / sec);
	printw("%7.1f swapin/s    %7.1f swapout/s   ",
		(float)br->swapin / sec,
		(float)br->swapout / sec);
	move(12,0);				
	printw("%7.1f bswapin/s   %7.1f bswapout/s  ",
		(float)br->bswapin / sec,
		(float)br->bswapout / sec);
	printw("%7.1f pswitch/s   %7.1f syscall/s   ",
		(float)br->pswitch / sec,
		(float)br->syscall / sec);
	move(13,0);				
	printw("%7.1f sysread/s   %7.1f syswrite/s  ",
		(float)br->sysread / sec,
		(float)br->syswrite / sec);
	printw("%7.1f sysfork/s   %7.1f sysexec/s   ",
		(float)br->sysfork / sec,
		(float)br->sysexec / sec);
	move(14,0);				
	printw("%7.1f runque/s    %7.1f runocc/s    ",
		(float)br->runque / sec,
		(float)br->runocc / sec);
	printw("%7.1f swpque/s    %7.1f swpocc/s    ",
		(float)br->swpque / sec,
		(float)br->swpocc / sec);
	move(15,0);				
	printw("%7.1f iget/s      %7.1f namei/s     ",
		(float)br->iget / sec,
		(float)br->namei / sec);
	printw("%7.1f dirblk/s    %7.1f readch/s    ",
		(float)br->dirblk / sec,
		(float)br->readch / sec);
	move(16,0);				
	printw("%7.1f writech/s   %7.1f rcvint/s    ",
		(float)br->writech / sec,
		(float)br->rcvint / sec);
	printw("%7.1f xmtint/s    %7.1f mdmint/s    ",
		(float)br->xmtint / sec,
		(float)br->mdmint / sec);
	move(17,0);				
	printw("%7.1f rawch/s     %7.1f canch/s     ",
		(float)br->rawch / sec,
		(float)br->canch / sec);
	printw("%7.1f outch/s     %7.1f msg/s       ",
		(float)br->outch / sec,
		(float)br->msg / sec);
	move(18,0);				
	printw("%7.1f sema/s",
		(float)br->sema / sec);
}

/*
 * build '**' line (scale for %100 being 'len' characters)
 */

char *
buildline(val, len)
register  float val;
register  int len;
{
	register char	*p, *pe, *cp;
	static	 char	 linebuf[81];

	p  = linebuf;
	pe = linebuf+len;
	cp = (int)(val/(100.0/(float)len)) + linebuf;
	for (; p < cp; p++)
		*p = '*';
	for (; p < pe; p++)
		*p = ' ';
	*p = '\0';
	return (linebuf);
}