[alt.sources] w

marc@CAM.ORG (Marc Boucher) (09/26/90)

#!/bin/sh
# This is a shell archive (shar 3.20)
# made 09/26/1990 08:57 UTC by root@altitude
# Source directory /usr/local/src/w
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1108 -rw------- w.README
#   5607 -rw-r--r-- w.c
#   2083 -rw-r--r-- lavd.c
#    336 -rw-r--r-- Makefile
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= w.README ==============
echo "x - extracting w.README (Text)"
sed 's/^X//' << 'SHAR_EOF' > w.README &&
XWed Sep 26 04:45:52 EDT 1990
X
XThe files w.c and lavd.c are quick and dirty adaptations to System V/386
X(at&t, esix, isc, etc..) of what is described below.
X
XThanks rayan!
X
XMarc Boucher 
XInternet: marc@CAM.ORG % BIX: mboucher % Telephone: (514) 466-8932 ou 489-8989 
X
X%From jarvis.csri.toronto.edu!neat.cs.toronto.edu!rayan Mon Sep  4 04:53:51 GMT 1989
XArticle 1183 of comp.sys.sgi:
XPath: jarvis.csri.toronto.edu!neat.cs.toronto.edu!rayan
XNewsgroups: comp.sys.sgi
X%From: rayan@cs.toronto.edu (Rayan Zachariassen)
XSubject: Re: 'w' for Iris 4D
XMessage-ID: <89Sep4.005321edt.2142@neat.cs.toronto.edu>
XReferences: <3263@watale.waterloo.edu>
XDate: 4 Sep 89 04:53:51 GMT
X
Xneat.cs.toronto.edu:~ftp/pub/sgi/w.tar.Z contains w.c and etc/lavd.c, the
Xlatter a daemon which puts the load average in shared mem segment for the
Xbenefit of w.c.  This is for 3.1, and should work under 3.2 although it seems
Xavenrun will be available in 3.2.  Hmm, perhaps the kernel should maintain the
Xshmem segment.  This stuff is PD as a subtle encouragement for SGI to provide
Xa 'w' with their releases. (hint, wink, nudge, ...)
X
Xrayan
X
SHAR_EOF
$TOUCH -am 0926045590 w.README &&
chmod 0600 w.README ||
echo "restore of w.README failed"
set `wc -c w.README`;Wc_c=$1
if test "$Wc_c" != "1108"; then
	echo original size 1108, current size $Wc_c
fi
# ============= w.c ==============
echo "x - extracting w.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > w.c &&
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/fs/s5dir.h>
X#include <sys/signal.h>
X#include <sys/user.h>
X#include <fcntl.h>
X
X#include <sys/immu.h>
X#include <sys/region.h>
X#include <sys/param.h>
X#include <sys/proc.h>
X
X#include <sys/sysi86.h>
X
X#include <utmp.h>
X#include <sys/stat.h>
X#include <time.h>
X
X#include <sys/ipc.h>
X#include <sys/shm.h>
X
Xstruct info {
X	struct info	*next;
X	struct utmp	ut;		/* need user, line, and time */
X	time_t		atime;		/* last mod time of line, for idle */
X	dev_t		device;		/* device id of the line */
X	char		*command;	/* user.u_psargs[] */
X	time_t		jcpu;		/* sum of all children and current */
X	time_t		pcpu;		/* cpu of current processes */
X};
X
Xchar *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X		  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
Xchar *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
X
Xmain(argc, argv)
X	int argc;
X	char *argv[];
X{
X	struct utmp *utp;
X	struct user uu;
X	struct proc pp, *pro;
X	struct stat stbuf;
X	struct info *ip, *head;
X	struct tm *tmp, nowtm;
X	int pid, fd, s, nusers;
X	int c, errflag, hflag, sflag;
X	short pgrp;
X	char *user = NULL;
X	time_t now, boot;
X	extern int optind;
X	extern char *calloc(), *malloc();
X
X	errflag = hflag = sflag = 0;
X	while ((c = getopt(argc, argv, "hls")) != EOF) {
X		switch (c) {
X		case 'h':	++hflag; break;
X		case 's':	++sflag; break;
X		case 'l':	sflag = 0; break;
X		default:	++errflag; break;
X		}
X	}
X	if (optind < argc)
X		user = argv[optind++];
X	if (errflag || optind < argc) {
X		fprintf(stderr, "Usage: %s [-hls] [user]\n", argv[0]);
X		exit(1);
X	}
X	(void) chdir("/dev");
X	now = time(0);
X	nowtm = *(localtime(&now));
X	ip = head = NULL;
X	nusers = 0;
X	/* find out all the tty devices used (from utmp) */
X	while ((utp = (struct utmp *)getutent()) != NULL) {
X		if (utp->ut_type == BOOT_TIME)
X			boot = utp->ut_time;
X		if (utp->ut_type != USER_PROCESS)
X			continue;
X		++nusers;
X		if (ip != NULL) {
X			ip->next = (struct info *)calloc(1, sizeof (struct info));
X			ip = ip->next;
X		} else
X			ip = (struct info *)calloc(1, sizeof (struct info));
X		ip->command = "-";
X		ip->jcpu = ip->pcpu = 0;
X		if (head == NULL)
X			head = ip;
X		ip->ut = *utp;
X		if (stat(utp->ut_line, &stbuf) < 0) {
X			ip->atime = now;
X			ip->device = 0;
X		} else {
X			ip->atime = stbuf.st_atime;
X			ip->device = stbuf.st_rdev;
X		}
X	}
X	boot = now - boot;
X	if (!strcmp(argv[0],"uptime")) {
X		uptime(&nowtm, boot, nusers);
X		exit(0);
X	}
X	if ((fd = open("/dev/kmem", O_RDONLY)) < 0) {
X		perror("/dev/kmem");
X		exit(1);
X	}
X
X	for (ip = head; ip != NULL; ip = ip->next) {
X		if (sysi86(RDUBLK, ip->ut.ut_pid, &uu, sizeof uu) < sizeof uu) {
X			perror("sysi86");
X			exit(1);
X		}
X		if (ip == NULL)
X			continue;
X
X		for(pro=uu.u_procp;pro;pro=pp.p_child) {
X			(void) lseek(fd, (ulong)pro, 0);
X			read(fd, &pp, sizeof pp);
X		}
X
X		if (sysi86(RDUBLK, pp.p_pid, &uu, sizeof uu) < sizeof uu) {
X			perror("sysi86");
X			exit(1);
X		}
X
X		(void) lseek(fd, (ulong)(uu.u_ttyp), 0);
X		read(fd, &pgrp, sizeof pgrp);
X
X		if (pgrp == pp.p_pgrp) {
X			ip->command = malloc(strlen(uu.u_psargs)+1);
X			strcpy(ip->command, uu.u_psargs);
X		}
X		ip->pcpu += uu.u_utime + uu.u_stime;
X		ip->jcpu += uu.u_utime + uu.u_stime + uu.u_cutime + uu.u_cstime;
X
X#if	0
Xprintf("pid=%d ttyp=%x ttyd=%x ttyip=%x procp=%x args=%s\n", pid,
X			uu.u_ttyp, uu.u_ttyd, uu.u_ttyip, uu.u_procp,
X			uu.u_psargs);
Xprintf("uid=%d pid=%d ppid=%d flag=%x pp.p_pgrp=%d pgrp=%d\n",
X			pp.p_uid, pp.p_pid, pp.p_ppid, pp.p_flag,
X			pp.p_pgrp, pgrp);
X#endif
X	}
X	close(fd);
X
X	if (!hflag) {
X		uptime(&nowtm, boot, nusers);
X		printf("User     tty       login@  idle   JCPU   PCPU  what\n");
X	}
X
X	for (ip = head; ip != NULL; ip = ip->next) {
X		if (user && strncmp(user, ip->ut.ut_user, 8) != 0)
X			continue;
X		printf("%-8.8s %-8.8s ", ip->ut.ut_user, ip->ut.ut_line);
X		tmp = localtime(&ip->ut.ut_time);
X		if (now - ip->ut.ut_time > 60*60*24*7)	/* > 1 week */
X			printf("%2d%3s%2d", tmp->tm_mday,
X				month[tmp->tm_mon], tmp->tm_year%100);
X		else if (now - ip->ut.ut_time > 60*60*24)	/* > 1 day */
X			printf("%3s%2d%2s", weekday[tmp->tm_wday],
X				(tmp->tm_hour % 12) +
X					((tmp->tm_hour % 12) == 0 ? 12 : 0),
X				(tmp->tm_hour < 12) ? "am" : "pm");
X		else
X			printtime(tmp);
X		s = now-(ip->atime);
X		if (s < 60)
X			printf("      ");
X		else if (s < 60*60)
X			printf("    %2d", s/60);
X		else
X			printf("%3d:%02d", s/(60*60), (s%(60*60))/60);
X		printcpu(ip->jcpu);
X		printcpu(ip->pcpu);
X		printf("  %s\n", ip->command);
X	}
X	exit(0);
X}
X
Xprinttime(tmp)
X	struct tm *tmp;
X{
X	printf("%2d:%02d%2s",
X		(tmp->tm_hour % 12) + ((tmp->tm_hour % 12) == 0 ? 12 : 0),
X		tmp->tm_min, (tmp->tm_hour < 12) ? "am" : "pm");
X}
X
Xprintcpu(s)
X	int s;
X{
X	if (s < 100)
X		printf("       ");
X	else if (s < 6000)
X		printf("%7d", s/100);
X	else
X		printf("%4d:%02d", (s/100/60), (s/100)%60);
X}
X
Xuptime(nowtmp, sinceboot, nusers)
X	struct tm *nowtmp;
X	time_t sinceboot;
X	int nusers;
X{
X	int id;
X	float *lav;
X
X	putchar(' ');
X	printtime(nowtmp);
X	printf("  up ");
X	if (sinceboot > 2*24*60*60)
X		printf("%d days, ", sinceboot/24/60/60);
X	else if (sinceboot > 24*60*60)
X		printf("%d day, ", sinceboot/24/60/60);
X	sinceboot %= 24*60*60;
X	if (sinceboot > 60*60)
X		printf("%2d:%02d", sinceboot/60/60, (sinceboot%(60*60))/60);
X	else
X		printf("%d mins", sinceboot/60);
X	printf(",  %d user%s", nusers, nusers == 1 ? "," : "s,");
X	printf("  load average: ");
X	id = shmget(ftok("/dev/kmem", 'lav'), 4 * sizeof (float), 0400);
X	if (id < 0
X	    || (lav = (float *)shmat(id, (char *)0, SHM_RDONLY)) == (float *)-1)
X		printf("hard to get\n");
X	else {
X		printf("%.2f, %.2f, %.2f\n", lav[0], lav[1], lav[2]);
X		(void) shmdt(lav);
X	}
X}
SHAR_EOF
$TOUCH -am 0615004990 w.c &&
chmod 0644 w.c ||
echo "restore of w.c failed"
set `wc -c w.c`;Wc_c=$1
if test "$Wc_c" != "5607"; then
	echo original size 5607, current size $Wc_c
fi
# ============= lavd.c ==============
echo "x - extracting lavd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > lavd.c &&
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/sysinfo.h>
X#include <sys/ipc.h>
X#include <sys/shm.h>
X#include <signal.h>
X#include <nlist.h>
X#include <fcntl.h>
X
X#define INTERVAL	5
X
X#define	NSAMPLES (15 /* minutes */ * 60 /* sec/min */ / INTERVAL)
X
Xint ringload[NSAMPLES];
Xint ringindex = 0;
X
Xint id;
Xfloat *lav;
X
Xvoid
Xdie()
X{
X	if (lav)
X		(void) shmdt(lav);
X	if (id)
X		(void) shmctl(id, IPC_RMID, (struct shmid_ds *)NULL);
X	exit(1);
X}
X
Xstruct nlist sym[] = {
X	{ "sysinfo" },
X	{ NULL }
X};
X
Xmain()
X{
X	struct sysinfo sinfo;
X	int flag = 0, now, last1, last5, last15;
X	extern int shmget();
X	extern char *shmat();
X	extern key_t ftok();
X	int kmem;
X
X	if(nlist("/unix", sym) < 0) {
X		fprintf(stderr, "/unix: no namelist.\n");
X		exit(1);
X	}
X	kmem=open("/dev/kmem", O_RDONLY);
X	if(kmem<0) {
X		perror("/dev/kmem");
X		exit(2);
X	}
X	if(!fork()) {
X		setpgrp();
X		if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X			(void) signal(SIGINT, die);
X		if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X			(void) signal(SIGHUP, die);
X		if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X			(void) signal(SIGTERM, die);
X		id = shmget(ftok("/dev/kmem", 'lav'), 4 * sizeof (float), 0644|IPC_CREAT);
X		lav = (float *)shmat(id, (char *)0, 0);
X
X		for (;;) {
X			now = ringindex;
X			lseek(kmem, (long) sym[0].n_value, 0);
X			read(kmem, (char *) &sinfo, sizeof sinfo);
X			/*sysmp(MP_SAGET, MPSA_SINFO, &sinfo, sizeof sinfo);*/
X			ringload[ringindex++] = sinfo.runque;
X			if (!flag) {
X				while (flag < NSAMPLES)
X					ringload[flag++] = sinfo.runque;
X				if (!flag)
X					break;	/* shut up the compiler */
X			}
X			ringindex %= NSAMPLES;
X			last1 = (NSAMPLES + now - 60 / INTERVAL)%NSAMPLES;
X			last5 = (NSAMPLES + now - 5*60 / INTERVAL)%NSAMPLES;
X			last15 = ringindex;
X			lav[0] = (ringload[now] - ringload[last1])/60.0;
X			lav[1] = (ringload[now] - ringload[last5])/(5*60.0),
X			lav[2] = (ringload[now] - ringload[last15])/(15*60.0);
X			lav[3] = (ringload[now] - ringload[(now-1+NSAMPLES)%NSAMPLES])/(float)INTERVAL;
X			/* printf("%6.2f %6.2f %6.2f\n", lav[0], lav[1], lav[2]); */
X			sleep(INTERVAL);
X		}
X		/* NOTREACHED */
X	}
X	exit(0);
X}
SHAR_EOF
$TOUCH -am 0615200190 lavd.c &&
chmod 0644 lavd.c ||
echo "restore of lavd.c failed"
set `wc -c lavd.c`;Wc_c=$1
if test "$Wc_c" != "2083"; then
	echo original size 2083, current size $Wc_c
fi
# ============= Makefile ==============
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X
XWDEST=/usr/local/bin/w
XUDEST=/usr/local/bin/uptime
XLDEST=/usr/local/etc/lavd
X
Xall: w lavd
X
Xw: w.c
X	cc -s -o w w.c
X	mcs -d w
X
Xlavd: lavd.c
X	cc -s -o lavd lavd.c
X	mcs -d lavd
X
Xclean:
X	rm -f *.o w lavd core
X
Xinstall: all
X	cp w $(WDEST)
X	chgrp sys $(WDEST)
X	chmod 2111 $(WDEST)
X	ln $(WDEST) $(UDEST)
X	cp lavd $(LDEST)
X	chmod 100 $(LDEST)
X
SHAR_EOF
$TOUCH -am 0615005390 Makefile &&
chmod 0644 Makefile ||
echo "restore of Makefile failed"
set `wc -c Makefile`;Wc_c=$1
if test "$Wc_c" != "336"; then
	echo original size 336, current size $Wc_c
fi
exit 0
-- 
Internet: marc@CAM.ORG % BIX: mboucher % Telephone: (514) 466-8932 ou 489-8989