[unix-pc.sources] UNIXPC Source: sysinfo.c

lenny@icus.UUCP (Lenny Tropiano) (06/28/88)

Unshar and read the README files...

-- cut here -- -- cut here -- -- cut here -- -- cut here --
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README README2.0 Makefile loadavgd.c sysinfo.c
# Wrapped by lenny@icus on Mon Jun 27 19:52:08 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1843 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XI wrote this little ditty just to utilize the two lines on the bottom of
Xthe screen where the soft labels for the function keys are normally displayed.
XThis program will only work if you login on the console (obviously) and
Xyou aren't using the "user agent" or something that needs those two lines.
X
XI give thanks to Scott Hazen Mueller for his contribution of "newmgr.c"
Xthat initially gave me the idea for displaying the file system information.
X
XAfter unpacking the shar file, "su" and become root.  Then type:
X
X	# make install
X
XThis will copy the program into /usr/lbin (as defined by the Makefile) but
Xyou might just want to have this for your own "bin" directory, because
Xit is only useful if you run on a windowed device.
X
XThe mail file is only read for the number of messages if the modification
Xtime changes since the last read (saving on disk I/O).  This program also
Xruns with a nice value of 5, and sleeps for 15 seconds between passes.
X(#defined by NICE and SLEEP respectively)
X
XYou might want to place the following lines in your /etc/localprofile
Xor .profile to activate sysinfo apon login:
X
XTTY=`tty`
Xif [ "`expr $TTY : '/dev/w' `" != "0" ]
Xthen 
X	sysinfo
Xfi
X
XPlease report any bugs, suggestions and problems to me:
X
X============================ US MAIL:   Lenny Tropiano, ICUS Computer Group
X IIIII   CCC   U   U   SSSS             PO Box 1
X   I    C   C  U   U  S                 Islip Terrace, New York  11752
X   I    C      U   U   SSS   PHONE:     (516) 968-8576 [H] (516) 582-5525 [W] 
X   I    C   C  U   U      S  AT&T MAIL: ...attmail!icus!lenny  TELEX: 154232428
X IIIII   CCC    UUU   SSSS   UUCP:
X============================    ...{uunet!godfre, harvard!talcott}!\
X                   ...{ihnp4, boulder, mtune, bc-cis, ptsfa, sbcs}! >icus!lenny 
X"Usenet the final frontier"        ...{cmcl2!phri, hoptoad}!dasys1!/
X
END_OF_FILE
if test 1843 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'README2.0' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README2.0'\"
else
echo shar: Extracting \"'README2.0'\" \(637 characters\)
sed "s/^X//" >'README2.0' <<'END_OF_FILE'
XSomething changed from previous version of sysinfo.
X
X	1)  added memory computation so you can see you memory slowly
X	    fading away...
X
X	2)  Used a loadavgd routine that created BSD-type load average
X	    shared memory segment:
X
XIPC status from /dev/kmem as of Mon Jun 27 19:11:36 1988
XT     ID     KEY        MODE       OWNER    GROUP
XMessage Queues:
XShared Memory:
Xm      0 0x610205de --rw-r--r--     root     root
XSemaphores:
X
X	    That can be read by this program and updated so you can
X	    see how your machine is loaded down.
X
XBug fixes:
X
X	1)  Clearing out the mail message counter when you deleted ALL
X	    your incoming mail.
X
END_OF_FILE
if test 637 -ne `wc -c <'README2.0'`; then
    echo shar: \"'README2.0'\" unpacked with wrong size!
fi
# end of 'README2.0'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(915 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Makefile to compile sysinfo.c  (System Info)  Version 2.0
X# By Lenny Tropiano  
X# (c)1987,1988 ICUS Software Systems  UUCP:  ...icus!lenny
X#
XCFLAGS=-v -O
XLDFLAGS=-s
XLIBS=/lib/crt0s.o /lib/shlib.ifile
XDEST=/usr/lbin/
XDAEMONS=/etc/daemons/
X#
XWINDOW=-DCHGWIND # Change sysinfo to current window always
X#
Xsysinfo.o:
X	$(CC) $(CFLAGS) $(WINDOW) -c sysinfo.c
X#
Xall:	sysinfo loadavgd
X
Xsysinfo:  sysinfo.o
X	@echo "Loading ..."
X	$(LD) $(LDFLAGS) -o sysinfo sysinfo.o $(LIBS) 
X
Xloadavgd:  loadavgd.o 
X	@echo "Loading ..."
X	$(LD) $(LDFLAGS) -o loadavgd loadavgd.o -lm $(LIBS) 
X#
X# You need to be superuser to do this
X#
X$(DEST):
X	mkdir $(DEST)
X$(DAEMONS):
X	mkdir $(DAEMONS)
X
Xinstall: all $(DEST) $(DAEMONS)
X	cp sysinfo $(DEST)
X	chown root $(DEST)
X	chgrp bin  $(DEST)
X	chmod 4755 $(DEST)
X	cp loadavgd $(DAEMONS)
X	chown root $(DAEMONS)
X	chgrp bin  $(DAEMONS)
X	chmod 4750 $(DAEMONS)
X	nohup $(DAEMONS)loadavgd> /dev/null 2>&1 &
END_OF_FILE
if test 915 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'loadavgd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'loadavgd.c'\"
else
echo shar: Extracting \"'loadavgd.c'\" \(10503 characters\)
sed "s/^X//" >'loadavgd.c' <<'END_OF_FILE'
X/*
X * renamed loadavgd.c by Lenny Tropiano (lenny@icus.UUCP ICUS Software Systems)
X *
X *	ldavg.c -- compute load averages for System V
X *	Phil Budne @ Boston U / DSG
X *
X *	Forges BSD 4.2 rwhod packets containing system load averages
X *	(#ifdef RWHOD for this, else a shm segment is used, ftok("/unix", 'a'))
X */
X
X# include <sys/types.h>			/* system types */
X# include <sys/sysinfo.h>		/* sysinfo structure */
X# include <sys/utsname.h>		/* for uname(2) */
X# include <sys/stat.h>			/* for stat(2) */
X# include <sys/param.h>			/* for HZ */
X# include <stdio.h>
X# include <nlist.h>
X# include <time.h>
X# include <math.h>
X# include <utmp.h>
X# include <fcntl.h>
X#ifdef RWHOD
X# include "rwhod.h"			/* (from BSD) */
X#else  SHM
X# include <sys/ipc.h>
X# include <sys/shm.h>
X#endif RWHOD
X#ifdef UNIXPC
X/*
X * Open a window on the status line.  While SMGR owns columns 33-74, it doesn't
X * seem to use columns 56-74, which by some strange chance is just enough for
X * our window.
X * (Whoops!  Can you say "icon"?  We use the spot reserved for the Phone
X * Manager instead... your choice.  Compile with -DUNIXPC to get windows;
X * the generic-System V code will work on the UNIX PC if you don't want them.)
X */
X# include <sys/window.h>
X# include <status.h>
X#endif UNIXPC
X
X/* # define DEBUG /**/
X#ifdef RWHOD
X# define UDP 1
X# define DSK 1
X# define PMUL 100
X
X# if UDP
X# include "netdb.h"
Xunsigned short port = 513;
Xunsigned long ipaddr;
X# endif
X#endif RWHOD
X
Xextern struct utmp *getutent();
X
X# define UNIX "/unix"
X# define KMEM "/dev/kmem"
X
Xstruct nlist nlsym[] = {
X# define NL_SYSINFO 0
X        { "sysinfo" },			/* 0 */
X#ifdef RWHOD
X# define NL_LBOLT 1
X	{ "lbolt" },			/* 1 */
X#endif RWHOD
X        { 0 }
X};
X
X#ifdef RWHOD
Xstruct whod proto;
Xstruct utsname utsn;
Xchar whopacket[100];
X#else  SHM
Xkey_t aven_key;
Xint aven_shm;
Xdouble *aven_seg;
X#endif RWHOD
Xint fd, memfd;
X#ifdef UNIXPC
Xstruct uwdata avenwin = {
X	0,	0,	288,	12,	NBORDER,	0,	0,	0
X};
Xextern char *sys_errlist[];
Xextern int errno;
X#endif
X
Xchar *unixsys = UNIX;
Xchar *kmem = KMEM;
Xchar *argv0;
X
Xmain(argc, argv)
Xint  argc;
Xchar *argv[];
X{
X	switch (fork()) {
X	case -1:
X		perror("fork");
X		exit(1);
X	case 0:
X		break;
X	default:
X		exit(0);
X	}
X	argv0 = argv[0];
X#ifdef RWHOD
X	uname(&utsn);			/* get system names */
X#endif RWHOD
X	setpgrp();			/* create own pgrp */
X#ifdef UNIXPC
X	if (freopen("/dev/window", "r+", stdout) == (FILE *) 0) {
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Can't open load average window:\n%s", argv0, sys_errlist[errno]);
X		exit(1);
X	}
X	ioctl(1, WIOCSETD, &avenwin);
X	ioctl(0, WIOCSELECT);
X	fclose(stdin);
X	fclose(stderr);
X#endif UNIXPC
X	init_nlist();			/* get name values, open kmem */
X	init_packet();			/* initialize packet prototype */
X	doit();				/* never returns */
X} /* main */
X
Xinit_nlist() {
X	nlist(unixsys, nlsym);		/* get system values */
X
X        if(nlsym[NL_SYSINFO].n_value == 0) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Cannot locate `sysinfo' structure", argv0);
X#else
X                fprintf(stderr, "%s: can't find sysinf structure\n", argv0);
X#endif
X                exit(1);
X        } /* no value */
X
X	if ((memfd = open(kmem, O_RDONLY)) < 0) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Cannot open kernel memory image:\n%s", argv0, sys_errlist[errno]);
X#else
X		fprintf(stderr, "%s: no mem\n", argv0);
X#endif UNIXPC
X		exit(1);
X	} /* could not open kmem */
X
X} /* init_nlist */
X
X# define PERIOD 5			/* sample period (in seconds) */
X# define INTERVAL1 60			/* average interval 1 (in seconds) */
X# define INTERVAL2 (5*60)		/* average interval 2 (in seconds) */
X# define INTERVAL3 (15*60)		/* average interval 3 (in seconds) */
X# define PACKINTERVAL 30		/* interval for make_packet */
X
Xdoit() {
X	struct sysinfo sinf;
X	int packt = 0;
X	long occ, que, nocc, nque, n, c;
X	double avg1, avg2, avg3, new;
X	double exp1, exp2, exp3;
X
X	exp1 = exp( - ((double) PERIOD) / INTERVAL1 );
X	exp2 = exp( - ((double) PERIOD) / INTERVAL2 );
X	exp3 = exp( - ((double) PERIOD) / INTERVAL3 );
X
X	getsysinf(&sinf);		/* prime the pump */
X	occ = sinf.runocc;		/* number of samples */
X	que = sinf.runque;		/* run queue summation */
X
X	avg1 = avg2 = avg3 = ((double) que) / occ;
X
X	for( ; ; ) {
X		if( --packt < 0 ) {
X#ifdef RWHOD
X			make_packet((int) (avg1 * PMUL),
X				    (int) (avg2 * PMUL),
X				    (int) (avg3 * PMUL));
X#else  SHM
X			make_packet(avg1, avg2, avg3);
X#endif RWHOD
X			packt = PACKINTERVAL / PERIOD;
X		} /* packet time */
X
X/*		printf("runque: %ld  runocc: %ld\n", que, occ ); /**/
X
X		sleep(PERIOD);
X		getsysinf(&sinf);	/* get new info */
X		nocc = sinf.runocc;
X		nque = sinf.runque;
X
X		n = nocc - occ;		/* get number of times updated */
X		if( n <= 0 ) continue;
X		c = nque - que - n;	/* get number of runners w/o us */
X		if( c < 0 ) c = 0;	/* mumble! */
X
X		new = ((double) c ) / n; /* new instantaneous avg */
X
X		/************************************************/
X		/*   The following formula is used to achieve   */
X		/*   exponential decay of old measurements:	*/
X		/*	avgN = avgN * expN  +  new * (1 - expN)	*/
X		/*						*/
X		/*   However, the factorized forms below	*/
X		/*   require fewer floating point operations.	*/
X		/************************************************/
X
X		avg1 = ((avg1 - new) * exp1) + new;
X		avg2 = ((avg2 - new) * exp2) + new;
X		avg3 = ((avg3 - new) * exp3) + new;
X
X		occ = nocc;
X		que = nque;
X
X	} /* for ever */
X} /* doit */
X
Xgetsysinf(s)
Xstruct sysinfo *s;
X{
X	l_lseek(memfd, (long)nlsym[NL_SYSINFO].n_value, 0);
X	r_read(memfd, (char *)s, sizeof(struct sysinfo));
X}
X
X/* lseek with error checking */
Xl_lseek(fd, offset, whence)
Xint fd, whence;
Xlong	offset;
X{
X	if (lseek(fd, offset, whence) == -1) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Error during seek in kernel memory image:\n%s", argv0, sys_errlist[errno]);
X#else
X		fprintf(stderr, "%s: error on lseek\n", argv0);
X#endif UNIXPC
X		exit(1);
X	}
X}
X
X/* read with error checking */
Xr_read (fd, buf, nbytes)
Xint	fd, nbytes;
Xchar	*buf;
X{
X	if (read(fd, buf, nbytes) != nbytes) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Error during read from kernel memory image:\n%s", argv0, sys_errlist[errno]);
X#else
X		fprintf(stderr, "%s: error on read\n", argv0);
X#endif UNIXPC
X		exit(1);
X	}
X}
X
Xinit_packet() {
X#ifdef RWHOD
X	time_t boothz;
X# if UDP
X	struct hostent *he;
X
X	he = gethostbyname( "localnet" );
X	if( he == NULL || he->h_addr == 0 ) {
X		fprintf(stderr, "no address: localnet\n");
X		exit( 1 );
X	}
X	ipaddr = he->h_addr;
X# endif
X# if DSK
X	sprintf(whopacket, "/usr/spool/rwho/whod.%s", utsn.nodename);
X# endif
X	memset(&proto, '\0', sizeof proto);	/* clear proto packet */
X
X	strncat(proto.wd_hostname, utsn.nodename, 9); /* at most 9, add null */
X	proto.wd_vers = WHODVERSION;
X	proto.wd_type = WHODTYPE_STATUS;
X
X	l_lseek(memfd, (long)nlsym[NL_LBOLT].n_value, 0);
X	r_read(memfd, (char *)&boothz, sizeof( boothz ) );
X	proto.wd_boottime = time(0) - (boothz / HZ);
X#else  SHM
X	if ((aven_key = ftok(UNIX, 'a')) == (key_t) -1) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Can't find shared memory keyfile:\n%s: %s", argv0, UNIX, sys_errlist[errno]);
X#else
X		perror(UNIX);
X#endif UNIXPC
X		exit(1);
X	}
X	if ((aven_shm = shmget(aven_key, 3 * sizeof (double), IPC_CREAT|IPC_EXCL|0644)) < 0) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Can't create shared memory segment:\n%s", argv0, sys_errlist[errno]);
X#else
X		perror("shmget");
X#endif UNIXPC
X		exit(1);
X	}
X	if ((int) (aven_seg = (double *) shmat(aven_shm, (char *) 0, 0)) == -1) {
X#ifdef UNIXPC
X		eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Can't attach shared memory segment:\n%s", argv0, sys_errlist[errno]);
X#else
X		perror("shmat");
X#endif UNIXPC
X		if (shmctl(aven_shm, IPC_RMID, (struct shmid_ds *) 0) < 0)
X#ifdef UNIXPC
X			eprintf(ST_OTHER, ST_DISPLAY, (char *) 0, "%s: Can't remove shared memory segment:\n%s", argv0, sys_errlist[errno]);
X#else
X			perror("shmctl(IPC_RMID)");
X#endif UNIXPC
X		exit(1);
X	}
X#endif RWHOD
X	
X} /* init_packet */
X
Xmake_packet(iavg1, iavg2, iavg3)
X#ifdef RWHOD
Xlong iavg1, iavg2, iavg3;
X#else  SHM
Xdouble iavg1, iavg2, iavg3;
X#endif RWHOD
X{
X#ifdef RWHOD
X	static struct whod packet;	/* local packet copy */
X	register struct whoent *wep;	/* pointer to packet whoent */
X	register struct utmp *utp;	/* return from getutent */
X	int whof, cc;			/* output file, char count */
X
X	packet = proto;			/* copy proto packet */
X	time(&packet.wd_sendtime);
X	time(&packet.wd_recvtime);	/* forge this !! */
X	packet.wd_loadav[0] = iavg1;
X	packet.wd_loadav[1] = iavg2;
X	packet.wd_loadav[2] = iavg3;
X
X	setutent();			/* open utmp file */
X	wep = &packet.wd_we[0];		/* get pointer to first user in pkt */
X
X	while( (utp = getutent()) != NULL ) {
X	    if( (utp->ut_type == USER_PROCESS) && utp->ut_user[0]) {
X		strncpy(wep->we_utmp.out_line, utp->ut_id, 4);
X		wep->we_utmp.out_line[4] = '\0';
X
X		strncpy(wep->we_utmp.out_name, utp->ut_user, 8);
X
X		wep->we_utmp.out_time = utp->ut_time;
X
X		wep->we_idle = idletime(utp);
X		wep++;			/* bump packet pointer */
X	    } /* user process */
X	} /* while */
X	endutent();
X
X# if DSK
X	whof = creat(whopacket, 0644);	/* open packt file */
X	if( whof >= 0 ) {
X	    cc = (char *)wep - (char *)&packet;
X	    if( write(whof, (char *)&packet, cc) != cc )
X	    	perror("write failed");
X	    close(whof);
X	} /* file opened */
X	else perror(whopacket);
X# endif
X# if UDP
X	cc = (char *)wep - (char *)&packet;
X	udpsend( (char *)&packet, cc, ipaddr, port, port, 1);
X# endif
X# ifdef DEBUG
X	fprintf(stderr, "wrote packet (%d)\n", cc);
X	fflush(stderr);
X# endif
X#else  SHM
X	aven_seg[0] = iavg1;
X	aven_seg[1] = iavg2;
X	aven_seg[2] = iavg3;
X#ifdef UNIXPC
X	printf("\rLoad average: %4.2f %4.2f %4.2f", iavg1, iavg2, iavg3);
X	fflush(stdout);
X#endif UNIXPC
X#endif RWHOD
X} /* make_packet */
X
X#ifdef RWHOD
Xidletime(up)
Xstruct utmp *up;
X{
X    register int i;
X    register char *cp, *dp;
X    char ttyname[10];
X    struct stat buf;
X    time_t now;
X
X    cp = "/dev/";
X    dp = ttyname;
X    
X    while( *cp != '\0' )		/* copy "/dev/" */
X        *dp++ = *cp++;
X
X    cp = up->ut_line;			/* get line name */
X    if( *cp == 's' )			/* starts with an 's'? (sxtnnn) */
X        *dp++ = 'v';			/* insert a 'v' */
X
X    for( i = 0; i < 8; i++ )		/* copy line name */
X        if( (*dp++ = *cp++) == '\0' ) break;	/* or until null */
X
X    if( stat(ttyname, &buf) != 0 )	/* get file status */
X        return( 0 );
X
X    time(&now);				/* get current time */
X    i = now - buf.st_atime;		/* get differnce from last acces */
X    return( i );			/* return idle time */
X} /* idletime */
X#endif RWHOD
END_OF_FILE
if test 10503 -ne `wc -c <'loadavgd.c'`; then
    echo shar: \"'loadavgd.c'\" unpacked with wrong size!
fi
# end of 'loadavgd.c'
fi
if test -f 'sysinfo.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sysinfo.c'\"
else
echo shar: Extracting \"'sysinfo.c'\" \(8409 characters\)
sed "s/^X//" >'sysinfo.c' <<'END_OF_FILE'
X/************************************************************************\
X**                                                                      **
X** Program name: sysinfo.c (System Info)                                **
X** Programmer:   Lenny Tropiano            UUCP: ...icus!lenny          **
X** Organization: ICUS Software Systems     (c)1988                      **
X** Date:         January 23, 1988                                       **
X** Version 2.0:  June 27, 1988                                          **
X**                                                                      **
X** Revision Level: 1  [Updated to switch to current window]             **
X** Revision Level: 2  [Updated to show load average in the window]      **
X** Revision Level: 3  [Updated to available main memory in the window]  **
X** Revision Level: 4  [Updated to available main memory in the window]  **
X**                                                                      **
X**************************************************************************
X**                                                                      **
X** Credits:      The idea of displaying the file system information     **
X**               came from Scott Hazen Mueller's  newmgr, the replace-  **
X**               ment to the smgr.                                      **
X**                                                                      **
X**************************************************************************
X**                                                                      **
X** Program use:  Program is run as a info process from your .profile    **
X**               This program the file system and displays the          **
X**               pertinent information on the bottom of the screen      **
X**               where the software labels would normally be displayed. **
X**               The program also displays the uptime.                  **
X**                                                                      **
X**************************************************************************
X** Permission is granted to distribute this program by any means as     **
X** long as credit is given for my work.     I would also like to see    **
X** any modifications or enhancements to this program.                   **
X\************************************************************************/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/window.h>
X#include <sys/filsys.h>
X#include <sys/param.h>
X#include <sys/ipc.h>
X#include <sys/shm.h>
X#include <nlist.h>
X#include <utmp.h>
X#include <setjmp.h>
X
X#ifndef ctob			/* For System V */
X#include <sys/sysmacros.h>
X#endif
X
Xstruct nlist unixsym[] = {
X#define X_FREEMEM	0
X	{ "freemem" },
X	{ NULL }
X};
X
X#define UNIX	"/unix"
X#define KMEM	"/dev/kmem"
X#define	MINUTE	60L
X#define	HOUR	(60L * 60L)
X#define	DAY	(24L * 60L * 60L)
X#define	SLEEP	15			/* Sleep time (interval between)*/
X#define	NICE	5			/* Niceness value		*/
X#define MEGABYTE 1048576.0
X                             
X#define LINE_1    "%-20.20s %-25.25s   up  %2d day%1.1s %2d hour%1.1s %2d minute%1.1s"
X#define LINE_2    "Filesystem: %6ld free  %6ld total %2d%% available %5d i-nodes  %4.2fMB memory"
X#define	FILESYS	"/dev/rfp002"
X#ifndef TRUE
X#define TRUE	1
X#endif
X
Xint	wd;				/* window descriptor		*/
Xint 	kmem;				/* kmem file descriptor		*/
Xjmp_buf	jmpbuf;				/* save the current environ	*/
Xchar	*progname;			/* program name			*/
Xchar	mailfile[30];			/* mailbox file name            */
Xstruct  utdata utd;			/* Window data structure        */
Xstruct  filsys fs;			/* Filesystem superblock struct */
Xtime_t	boottime;			/* system boot time in sec      */
Xtime_t	mailtime = 0L;			/* mail modification time       */
Xint	msgs = 0;
Xint	shm;
Xunsigned long	days = 0L;
Xunsigned long	hrs  = 0L;
Xunsigned long	mins = 0L;
X
X/************************************************************************/
X
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	terminate();
X	char	*getenv();
X	struct	utmp	*utent, *getutent();
X
X	if (fork() != 0) 		/* detach process-info */
X		exit(0);
X		
X	nice(NICE);			/* Be a little nice	*/
X	signal (SIGINT, SIG_IGN);
X	signal (SIGQUIT, SIG_IGN);
X 	signal (SIGHUP, terminate);
X 	signal (SIGTERM, terminate);
X
X    	progname = *argv;
X	sprintf(mailfile,"%s",getenv("MAIL"));
X
X	setutent();
X	while ((utent = getutent()) != (struct utmp *)NULL) {
X		if (utent->ut_type == BOOT_TIME) {
X			boottime = utent->ut_time;
X			break;
X		}
X	}
X	endutent();
X
X	shm = shmget(ftok("/unix",'a'),12,0);
X	/*
X	 * Look up addresses of variables.
X	 */
X	if (nlist(UNIX, unixsym) < 0) {
X		fprintf(stderr, "%s: no namelist.\n", UNIX);
X		exit(1);
X	}
X	/*
X	 * Open kernel memory.
X	 */
X	if ((kmem = open(KMEM, 0)) < 0) {
X		perror(KMEM);
X		exit(1);
X	}
X
X	info_process();
X	terminate();
X
X}
X
Xinfo_process()
X{
X	int	refrsh();
X	long	memory();
X	float	freemem;
X	char	mailbuffer[30], loadbuf[30];
X
X#ifdef CHGWIND
X 	signal (SIGWIND, refrsh);  /* trap window change signal */
X#else
X	open_current_window();	   /* must initialize if not using -DCHGWIND */
X#endif 
X
X	while (TRUE) {
X
X#ifdef CHGWIND
X		setjmp(jmpbuf);
X		open_current_window();
X#endif
X
X		filestatus();
X		uptime();
X		mailcheck(mailbuffer);
X		loadaverage(loadbuf);
X
X		utd.ut_num = WTXTSLK1;
X		sprintf(utd.ut_text,LINE_1,
X			mailbuffer, loadbuf,
X			days,(days == 1) ? " " : "s",
X			hrs, (hrs  == 1) ? " " : "s",
X			mins,(mins == 1) ? " " : "s"
X		);
X        	ioctl(wd, WIOCSETTEXT, &utd);
X
X		utd.ut_num = WTXTSLK2;
X		freemem    = memory() / MEGABYTE;
X		sprintf(utd.ut_text,LINE_2,
X		   fs.s_tfree * 2, fs.s_fsize * 2, 
X		   (int)((((float)fs.s_tfree / (float)fs.s_fsize) + 0.005) 
X			   * 100.0), fs.s_tinode, freemem
X		);
X        	ioctl(wd, WIOCSETTEXT, &utd);
X#ifdef CHGWIND
X		close(wd);
X#endif
X		sleep(SLEEP);
X	}
X}
X
Xint refrsh()
X{
X	int	window, 
X		dummy, 
X		refrsh();
X	char	windev[9];
X
X	signal(SIGWIND,SIG_IGN);
X	window = ioctl(0, WIOCGPREV, dummy);
X	sprintf(windev,"/dev/w%d",window);
X	if ((wd = open(windev,O_RDWR|O_NDELAY)) == -1) 
X		wd = 0;
X	utd.ut_num = WTXTSLK1;		/* clear the label area     */
X	utd.ut_text[0] = '\0';
X        ioctl(wd, WIOCSETTEXT, &utd);
X	utd.ut_num = WTXTSLK2;
X        ioctl(wd, WIOCSETTEXT, &utd);
X	close(wd);			/* close previous window    */
X	longjmp(jmpbuf, 0);		/* return back to main loop */
X}
X
Xint open_current_window()
X{
X	int	window, 
X		dummy, 
X		refrsh();
X	char	windev[9];
X
X	window = ioctl(0, WIOCGCURR, dummy);
X	sprintf(windev,"/dev/w%d",window);
X	if ((wd = open(windev,O_RDWR|O_NDELAY)) == -1) 
X		wd = 0;
X}
X
Xint terminate()
X{
X	utd.ut_num = WTXTSLK1;		/* clear the label area */
X	utd.ut_text[0] = '\0';
X        ioctl(0, WIOCSETTEXT, &utd);
X	utd.ut_num = WTXTSLK2;
X        ioctl(0, WIOCSETTEXT, &utd);
X#ifndef CHGWIND
X	close(wd);
X#endif
X	close(kmem);
X
X	exit(0);
X}
X
Xfilestatus()
X{
X	int	fd;
X
X	if ((fd = open(FILESYS, O_RDONLY)) == -1) {
X		fprintf(stderr,"%s: cannot open %s for read\n",
X			progname, FILESYS);
X		terminate();
X	}
X	
X	if (lseek(fd, 512, 0) == -1) {
X		fprintf(stderr,"%s: cannot lseek to superblock\n", progname);
X		terminate();
X	}
X
X	if (read(fd, &fs, sizeof(struct filsys)) == -1) {
X		fprintf(stderr,"%s: cannot read the superblock\n", progname);
X		terminate();
X	}
X
X	close(fd);
X
X}
X
Xuptime()
X{
X	time_t   curtime, bootsec;
X
X	time(&curtime);
X	bootsec = curtime - boottime;
X
X	days = bootsec / DAY;
X	bootsec -= DAY * days;
X	hrs = bootsec / HOUR;
X	bootsec -= HOUR * hrs;
X	mins = bootsec / MINUTE;
X	bootsec -= MINUTE * mins;
X}
X
Xmailcheck(buf)
Xchar *buf;
X{
X	FILE	*fp;
X	char	buffer[BUFSIZ];
X	struct	stat	statbuf;
X
X	if (access(mailfile,4) == 0) {
X		if (stat(mailfile,&statbuf) != -1) {
X		    if (statbuf.st_ctime > mailtime) {
X			msgs = 0;
X			if ((fp = fopen(mailfile,"r")) != NULL) {
X			   while (fgets(buffer, BUFSIZ, fp) != NULL) 
X				if (strncmp(buffer,"From ",5) == 0)
X					msgs++;
X			}
X			fclose(fp);
X			mailtime = statbuf.st_ctime;
X		    }
X		}
X	} else
X		msgs = 0;
X	if (msgs > 0) 
X		sprintf(buf,"%d mail message%s",msgs,
X			(msgs == 1) ? "" : "s");
X	else
X		buf[0] = '\0';
X}
X
Xloadaverage(lbuf)
Xchar *lbuf;
X{
X	double	*shmseg;
X
X	shmseg = (double *)shmat(shm, (char *) 0, SHM_RDONLY);
X	sprintf(lbuf,"Load avg:  %4.2f %4.2f %4.2f", 
X		shmseg[0], shmseg[1], shmseg[2]);
X	shmdt(shmseg);
X}
X
Xlong memory()
X{
X	int mem;
X
X	/*
X	 * Read variables.
X	 */
X	lseek(kmem, (long) unixsym[X_FREEMEM].n_value, 0);
X	read(kmem, (char *) &mem, sizeof(int));
X
X	return(ctob(mem));
X}
X
END_OF_FILE
if test 8409 -ne `wc -c <'sysinfo.c'`; then
    echo shar: \"'sysinfo.c'\" unpacked with wrong size!
fi
# end of 'sysinfo.c'
fi
echo shar: End of shell archive.
exit 0
-- 
Paper-net: Lenny Tropiano          | @-net:         lenny@icus.UUCP
           ICUS Software Systems   | !-net:      ...att    \
           PO Box 1                |                boulder \
           Islip Terrace, NY 11752 |                talcott  !icus!lenny
Vocal-net: (516) 582-5525 [work]   |                pacbell /
           (516) 968-8576 [home]   |                sbcs   /
Telex-net: 154232428 ICUS          | Another-net:   attmail!icus!lenny