SYSINFO utility for information on UNIX pc SLK lines (repost)

Lenny Tropiano lenny at icus.islp.ny.us
Mon Oct 16 22:39:38 AEST 1989


Since for some reason a lot of people have the older version, and don't
have this version, my release 2.1, I'm reposting it to unix-pc.sources.
It hasn't been posted here in a long time, so it isn't too bad.  This
version has the loadavgd (daemon) to report load avg results.  Now
if someone coulld EXPLAIN to me the significance of the three numbers,
other than the larger the number the more loaded the machine.  Note,
I didn't write loadavgd, I just incorporated the ipc-shared memory
segment.

-Lenny
--

#! /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.1 Makefile sysinfo.c loadavgd.c
# Wrapped by lenny at icus on Mon Oct 16 08:35:18 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1549 characters\)
sed "s/^X//" >README <<'END_OF_README'
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| Lenny Tropiano            ICUS Software Systems      [w] +1 (516) 589-7930 |
X| lenny at icus.islp.ny.us     Telex; 154232428 ICUS      [h] +1 (516) 968-8576 |
X| {ames,pacbell,decuac,hombre,sbcs,attctc}!icus!lenny     attmail!icus!lenny |
X+------- ICUS Software Systems -- PO Box 1;  Islip Terrace, NY  11752 -------+
END_OF_README
if test 1549 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README2.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README2.1\"
else
echo shar: Extracting \"README2.1\" \(2230 characters\)
sed "s/^X//" >README2.1 <<'END_OF_README2.1'
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
XUpdates:
X
XRelease 2.1:
X
XDavid H. Brierley
XHome: dave at galaxia.Newport.RI.US   {rayssd,xanth,lazlo,jclyde}!galaxia!dave
XWork: dhb at rayssd.ray.com           {sun,decuac,gatech,necntc,ukma}!rayssd!dhb
X
XThe following is a diff listing for a minor change that I made to the version
X2.0 release of sysinfo.  It is used in conjunction with the mode that makes
Xsysinfo follow the active window and what it does is look to see if the label
Xlines are blank before attempting to use them.  I like having sysinfo follow
Xthe active window because I do a lot of window type stuff using windy and
Xsome other software that I have developed, but every once in a while I will
Xbring up the UA or some other program that wants to write into the label lines.
XA few seconds later, the labels are overwritten by sysinfo.
X
XThe basic changes I made were to enclose the calls that rewrote the label
Xlines inside an if statement that calls a new routine to check if it is ok
Xto write on the labels and then, of course, I included the new routine.  The
Xroutine says it is ok to write if the label lines are completely blank or if
Xthey look like they were previously written by sysinfo.  The changes are simple
Xenough that you should have no problems incorporating them (assuming that you
Xwant to) into the source even if you have made massive changes since the last
Xtime you posted it.
X
XI was thinking of posting this patch to unix-pc.sources but I thought I would
Xlet you take a look at it first.  If you want me to go ahead and post it let
Xme know, otherwise I will wait for it to be incorporated into the next release.
X
END_OF_README2.1
if test 2230 -ne `wc -c <README2.1`; then
    echo shar: \"README2.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(961 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
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)sysinfo
X	chgrp bin  $(DEST)sysinfo
X	chmod 4755 $(DEST)sysinfo
X	cp loadavgd $(DAEMONS)
X	chown root $(DAEMONS)loadavgd
X	chgrp bin  $(DAEMONS)loadavgd
X	chmod 4750 $(DAEMONS)loadavgd
X	nohup $(DAEMONS)loadavgd> /dev/null 2>&1 &
END_OF_Makefile
if test 961 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sysinfo.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sysinfo.c\"
else
echo shar: Extracting \"sysinfo.c\" \(9977 characters\)
sed "s/^X//" >sysinfo.c <<'END_OF_sysinfo.c'
X/************************************************************************\
X**                                                                      **
X** Program name: sysinfo.c (System Info)                                **
X** Programmer:   Lenny Tropiano            UUCP: ...icus!lenny          **
X** Organization: ICUS Software Systems     (c)1988, 1989                **
X** Date:         January 23, 1988                                       **
X** Version 2.0:  June 27, 1988                                          **
X** Version 2.1:  Februrary 19, 1989 (Revision Level 4)                  **
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 by David H. Brierley to check the the    **
X**                     current status of the SLK lines for existing     **
X**                     information and not display the sysinfo lines    **
X**                     over those SLK's if in CHGWIND #define'd, good   **
X**                     for use with the UA and Telephone Manager F-key  **
X**                     SLK definitions]  -- dave at galaxia.Newport.RI.US  **
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
Xstatic  char *LINE_1 = "%-20.20s %-25.25s   up  %2d day%1.1s %2d hour%1.1s %2d minute%1.1s";
Xstatic	char *LINE_2 = "Filesystem: %6ld free  %6ld total %2d%% available %5d i-nodes  %4.2fMB memory";
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	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		if (slktest(wd) == 0) {
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		}
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
Xslktest (wd)
Xint wd;
X{
X	/*
X	 * check the SLK lines for the existence of anything currently there
X	 * if found two blank SLK lines or some remaining sysinfo information,
X	 * denoted by "Filesystem" in the second line, then return 0, else
X	 * return -1
X	 * Developed by David H. Brierley (dave at galaxia.Newport.RI.US)
X	 */
X
X	int rvalue;
X	int n;
X
X	rvalue = 0;
X	utd.ut_num = WTXTSLK1;
X	ioctl (wd, WIOCGETTEXT, &utd);
X	if (utd.ut_text[0] == '\0') 
X		++rvalue;
X	else 
X		for (n = 0; n < WTXTLEN; ++n) 
X			if ((utd.ut_text[n] != '\0') && 
X			    (utd.ut_text[n] != ' ')) 
X				break;
X
X	if (n == WTXTLEN) 
X	    ++rvalue;
X
X	utd.ut_num = WTXTSLK2;
X	ioctl (wd, WIOCGETTEXT, &utd);
X	if (utd.ut_text[0] == '\0') 
X		++rvalue;
X	else 
X		for (n = 0; n < WTXTLEN; ++n) 
X			if ((utd.ut_text[n] != '\0') && 
X			    (utd.ut_text[n] != ' ')) 
X				break;
X
X	if (n == WTXTLEN) 
X		++rvalue;
X
X	if (rvalue == 2) 	/* two blank lines */
X		return (0);
X
X				/* found the beginning of LINE_2 */
X
X    	if (strncmp (utd.ut_text, LINE_2, 12) == 0) 
X		return (0);
X
X	/* not blank, return -1 */
X	return (-1);
X
X}
END_OF_sysinfo.c
if test 9977 -ne `wc -c <sysinfo.c`; then
    echo shar: \"sysinfo.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f loadavgd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"loadavgd.c\"
else
echo shar: Extracting \"loadavgd.c\" \(10503 characters\)
sed "s/^X//" >loadavgd.c <<'END_OF_loadavgd.c'
X/*
X * renamed loadavgd.c by Lenny Tropiano (lenny at 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_loadavgd.c
if test 10503 -ne `wc -c <loadavgd.c`; then
    echo shar: \"loadavgd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
| Lenny Tropiano            ICUS Software Systems      [w] +1 (516) 589-7930 |
| lenny at icus.islp.ny.us     Telex; 154232428 ICUS      [h] +1 (516) 968-8576 |
| {ames,pacbell,decuac,hombre,sbcs,attctc}!icus!lenny     attmail!icus!lenny |
+------- ICUS Software Systems -- PO Box 1;  Islip Terrace, NY  11752 -------+



More information about the Comp.sys.att mailing list