Computer Systems Research Group BSD Distribution
Annotation For usr.bin/w/w.c
Not logged in

Origin for each line in usr.bin/w/w.c from check-in 2685ec94a9:

2685ec94a9 1980-10-01    1: static char *sccsid = "@(#)w.c	4.1 (Berkeley) 10/01/80";
2685ec94a9 1980-10-01    2: /*
2685ec94a9 1980-10-01    3:  * w - print system status (who and what)
2685ec94a9 1980-10-01    4:  *
2685ec94a9 1980-10-01    5:  * This program is similar to the systat command on Tenex/Tops 10/20
2685ec94a9 1980-10-01    6:  * It needs read permission on /dev/mem, /dev/kmem, and /dev/drum.
2685ec94a9 1980-10-01    7:  */
2685ec94a9 1980-10-01    8: #include <sys/param.h>
2685ec94a9 1980-10-01    9: #include <nlist.h>
2685ec94a9 1980-10-01   10: #include <stdio.h>
2685ec94a9 1980-10-01   11: #include <ctype.h>
2685ec94a9 1980-10-01   12: #include <utmp.h>
2685ec94a9 1980-10-01   13: #include <time.h>
2685ec94a9 1980-10-01   14: #include <sys/stat.h>
2685ec94a9 1980-10-01   15: #include <sys/dir.h>
2685ec94a9 1980-10-01   16: #include <sys/user.h>
2685ec94a9 1980-10-01   17: #include <sys/proc.h>
2685ec94a9 1980-10-01   18: #include <sys/pte.h>
2685ec94a9 1980-10-01   19: #include <sys/vm.h>
2685ec94a9 1980-10-01   20: 
2685ec94a9 1980-10-01   21: #define NMAX sizeof(utmp.ut_name)
2685ec94a9 1980-10-01   22: #define LMAX sizeof(utmp.ut_line)
2685ec94a9 1980-10-01   23: 
2685ec94a9 1980-10-01   24: #define ARGWIDTH	33	/* # chars left on 80 col crt for args */
2685ec94a9 1980-10-01   25: 
2685ec94a9 1980-10-01   26: struct smproc {
2685ec94a9 1980-10-01   27: 	short	w_pid;			/* proc.p_pid */
2685ec94a9 1980-10-01   28: 	char	w_flag;			/* proc.p_flag */
2685ec94a9 1980-10-01   29: 	short	w_size;			/* proc.p_size */
2685ec94a9 1980-10-01   30: 	long	w_seekaddr;		/* where to find args */
2685ec94a9 1980-10-01   31: 	long	w_lastpg;		/* disk address of stack */
2685ec94a9 1980-10-01   32: 	int	w_igintr;		/* INTR+3*QUIT, 0=die, 1=ign, 2=catch */
2685ec94a9 1980-10-01   33: 	time_t	w_time;			/* CPU time used by this process */
2685ec94a9 1980-10-01   34: 	time_t	w_ctime;		/* CPU time used by children */
2685ec94a9 1980-10-01   35: 	dev_t	w_tty;			/* tty device of process */
2685ec94a9 1980-10-01   36: 	char	w_comm[15];		/* user.u_comm, null terminated */
2685ec94a9 1980-10-01   37: 	char	w_args[ARGWIDTH+1];	/* args if interesting process */
2685ec94a9 1980-10-01   38: } pr[NPROC];
2685ec94a9 1980-10-01   39: 
2685ec94a9 1980-10-01   40: struct	nlist nl[] = {
2685ec94a9 1980-10-01   41: 	{ "_proc" },
2685ec94a9 1980-10-01   42: #define	X_PROC		0
2685ec94a9 1980-10-01   43: 	{ "_swapdev" },
2685ec94a9 1980-10-01   44: #define	X_SWAPDEV	1
2685ec94a9 1980-10-01   45: 	{ "_Usrptmap" },
2685ec94a9 1980-10-01   46: #define	X_USRPTMA	2
2685ec94a9 1980-10-01   47: 	{ "_usrpt" },
2685ec94a9 1980-10-01   48: #define	X_USRPT		3
2685ec94a9 1980-10-01   49: 	{ "_nswap" },
2685ec94a9 1980-10-01   50: #define	X_NSWAP		4
2685ec94a9 1980-10-01   51: 	{ "_avenrun" },
2685ec94a9 1980-10-01   52: #define	X_AVENRUN	5
2685ec94a9 1980-10-01   53: 	{ "_bootime" },
2685ec94a9 1980-10-01   54: #define	X_BOOTIME	6
2685ec94a9 1980-10-01   55: 	{ 0 },
2685ec94a9 1980-10-01   56: };
2685ec94a9 1980-10-01   57: 
2685ec94a9 1980-10-01   58: FILE	*ps;
2685ec94a9 1980-10-01   59: FILE	*ut;
2685ec94a9 1980-10-01   60: FILE	*bootfd;
2685ec94a9 1980-10-01   61: int	kmem;
2685ec94a9 1980-10-01   62: int	mem;
2685ec94a9 1980-10-01   63: int	swap;			/* /dev/kmem, mem, and swap */
2685ec94a9 1980-10-01   64: int	nswap;
2685ec94a9 1980-10-01   65: dev_t	tty;
2685ec94a9 1980-10-01   66: char	doing[520];		/* process attached to terminal */
2685ec94a9 1980-10-01   67: time_t	proctime;		/* cpu time of process in doing */
2685ec94a9 1980-10-01   68: double	avenrun[3];
2685ec94a9 1980-10-01   69: 
2685ec94a9 1980-10-01   70: #define	DIV60(t)	((t+30)/60)    /* x/60 rounded */ 
2685ec94a9 1980-10-01   71: #define	TTYEQ		(tty == pr[i].w_tty)
2685ec94a9 1980-10-01   72: #define IGINT		(1+3*1)		/* ignoring both SIGINT & SIGQUIT */
2685ec94a9 1980-10-01   73: 
2685ec94a9 1980-10-01   74: char	*getargs();
2685ec94a9 1980-10-01   75: char	*fread();
2685ec94a9 1980-10-01   76: char	*ctime();
2685ec94a9 1980-10-01   77: char	*rindex();
2685ec94a9 1980-10-01   78: FILE	*popen();
2685ec94a9 1980-10-01   79: struct	tm *localtime();
2685ec94a9 1980-10-01   80: 
2685ec94a9 1980-10-01   81: int	debug;			/* true if -d flag: debugging output */
2685ec94a9 1980-10-01   82: int	header = 1;		/* true if -h flag: don't print heading */
2685ec94a9 1980-10-01   83: int	lflag = 1;		/* true if -l flag: long style output */
2685ec94a9 1980-10-01   84: int	login;			/* true if invoked as login shell */
2685ec94a9 1980-10-01   85: int	idle;			/* number of minutes user is idle */
2685ec94a9 1980-10-01   86: int	nusers;			/* number of users logged in now */
2685ec94a9 1980-10-01   87: char *	sel_user;		/* login of particular user selected */
2685ec94a9 1980-10-01   88: char firstchar;			/* first char of name of prog invoked as */
2685ec94a9 1980-10-01   89: time_t	jobtime;		/* total cpu time visible */
2685ec94a9 1980-10-01   90: time_t	now;			/* the current time of day */
2685ec94a9 1980-10-01   91: struct	tm *nowt;		/* current time as time struct */
2685ec94a9 1980-10-01   92: time_t	bootime, uptime;	/* time of last reboot & elapsed time since */
2685ec94a9 1980-10-01   93: int	np;			/* number of processes currently active */
2685ec94a9 1980-10-01   94: struct	utmp utmp;
2685ec94a9 1980-10-01   95: struct	proc mproc;
2685ec94a9 1980-10-01   96: struct	user up;
2685ec94a9 1980-10-01   97: char	fill[512];
2685ec94a9 1980-10-01   98: 
2685ec94a9 1980-10-01   99: main(argc, argv)
2685ec94a9 1980-10-01  100: 	char **argv;
2685ec94a9 1980-10-01  101: {
2685ec94a9 1980-10-01  102: 	int days, hrs, mins;
2685ec94a9 1980-10-01  103: 	register int i, j;
2685ec94a9 1980-10-01  104: 	char *cp;
2685ec94a9 1980-10-01  105: 	register int curpid, empty;
2685ec94a9 1980-10-01  106: 	char obuf[BUFSIZ];
2685ec94a9 1980-10-01  107: 
2685ec94a9 1980-10-01  108: 	setbuf(stdout, obuf);
2685ec94a9 1980-10-01  109: 	login = (argv[0][0] == '-');
2685ec94a9 1980-10-01  110: 	cp = rindex(argv[0], '/');
2685ec94a9 1980-10-01  111: 	firstchar = login ? argv[0][1] : (cp==0) ? argv[0][0] : cp[1];
2685ec94a9 1980-10-01  112: 	cp = argv[0];	/* for Usage */
2685ec94a9 1980-10-01  113: 
2685ec94a9 1980-10-01  114: 	while (argc > 1) {
2685ec94a9 1980-10-01  115: 		if (argv[1][0] == '-') {
2685ec94a9 1980-10-01  116: 			for (i=1; argv[1][i]; i++) {
2685ec94a9 1980-10-01  117: 				switch(argv[1][i]) {
2685ec94a9 1980-10-01  118: 
2685ec94a9 1980-10-01  119: 				case 'd':
2685ec94a9 1980-10-01  120: 					debug++;
2685ec94a9 1980-10-01  121: 					break;
2685ec94a9 1980-10-01  122: 
2685ec94a9 1980-10-01  123: 				case 'h':
2685ec94a9 1980-10-01  124: 					header = 0;
2685ec94a9 1980-10-01  125: 					break;
2685ec94a9 1980-10-01  126: 
2685ec94a9 1980-10-01  127: 				case 'l':
2685ec94a9 1980-10-01  128: 					lflag++;
2685ec94a9 1980-10-01  129: 					break;
2685ec94a9 1980-10-01  130: 
2685ec94a9 1980-10-01  131: 				case 's':
2685ec94a9 1980-10-01  132: 					lflag = 0;
2685ec94a9 1980-10-01  133: 					break;
2685ec94a9 1980-10-01  134: 
2685ec94a9 1980-10-01  135: 				case 'u':
2685ec94a9 1980-10-01  136: 				case 'w':
2685ec94a9 1980-10-01  137: 					firstchar = argv[1][1];
2685ec94a9 1980-10-01  138: 					break;
2685ec94a9 1980-10-01  139: 
2685ec94a9 1980-10-01  140: 				default:
2685ec94a9 1980-10-01  141: 					printf("Bad flag %s\n", argv[1]);
2685ec94a9 1980-10-01  142: 					exit(1);
2685ec94a9 1980-10-01  143: 				}
2685ec94a9 1980-10-01  144: 			}
2685ec94a9 1980-10-01  145: 		} else {
2685ec94a9 1980-10-01  146: 			if (!isalnum(argv[1][0]) || argc > 2) {
2685ec94a9 1980-10-01  147: 				printf("Usage: %s [ -hlsuw ] [ user ]\n", cp);
2685ec94a9 1980-10-01  148: 				exit(1);
2685ec94a9 1980-10-01  149: 			} else
2685ec94a9 1980-10-01  150: 				sel_user = argv[1];
2685ec94a9 1980-10-01  151: 		}
2685ec94a9 1980-10-01  152: 		argc--; argv++;
2685ec94a9 1980-10-01  153: 	}
2685ec94a9 1980-10-01  154: 
2685ec94a9 1980-10-01  155: 	if ((kmem = open("/dev/kmem", 0)) < 0) {
2685ec94a9 1980-10-01  156: 		fprintf(stderr, "No kmem\n");
2685ec94a9 1980-10-01  157: 		exit(1);
2685ec94a9 1980-10-01  158: 	}
2685ec94a9 1980-10-01  159: 	nlist("/vmunix", nl);
2685ec94a9 1980-10-01  160: 	if (nl[0].n_type==0) {
2685ec94a9 1980-10-01  161: 		fprintf(stderr, "No namelist\n");
2685ec94a9 1980-10-01  162: 		exit(1);
2685ec94a9 1980-10-01  163: 	}
2685ec94a9 1980-10-01  164: 
2685ec94a9 1980-10-01  165: 	if (firstchar != 'u')
2685ec94a9 1980-10-01  166: 		readpr();
2685ec94a9 1980-10-01  167: 
2685ec94a9 1980-10-01  168: 	ut = fopen("/etc/utmp","r");
2685ec94a9 1980-10-01  169: 	if (header) {
2685ec94a9 1980-10-01  170: 		/* Print time of day */
2685ec94a9 1980-10-01  171: 		time(&now);
2685ec94a9 1980-10-01  172: 		nowt = localtime(&now);
2685ec94a9 1980-10-01  173: 		prtat(nowt);
2685ec94a9 1980-10-01  174: 
2685ec94a9 1980-10-01  175: 		/*
2685ec94a9 1980-10-01  176: 		 * Print how long system has been up.
2685ec94a9 1980-10-01  177: 		 * (Found by looking for "bootime" in kernel)
2685ec94a9 1980-10-01  178: 		 */
2685ec94a9 1980-10-01  179: 		lseek(kmem, (long)nl[X_BOOTIME].n_value, 0);
2685ec94a9 1980-10-01  180: 		read(kmem, &bootime, sizeof (bootime));
2685ec94a9 1980-10-01  181: 
2685ec94a9 1980-10-01  182: 		uptime = now - bootime;
2685ec94a9 1980-10-01  183: 		days = uptime / (60*60*24);
2685ec94a9 1980-10-01  184: 		uptime %= (60*60*24);
2685ec94a9 1980-10-01  185: 		hrs = uptime / (60*60);
2685ec94a9 1980-10-01  186: 		uptime %= (60*60);
2685ec94a9 1980-10-01  187: 		mins = DIV60(uptime);
2685ec94a9 1980-10-01  188: 
2685ec94a9 1980-10-01  189: 		printf("  up");
2685ec94a9 1980-10-01  190: 		if (days > 0)
2685ec94a9 1980-10-01  191: 			printf(" %d day%s,", days, days>1?"s":"");
2685ec94a9 1980-10-01  192: 		if (hrs > 0 && mins > 0) {
2685ec94a9 1980-10-01  193: 			printf(" %2d:%02d,", hrs, mins);
2685ec94a9 1980-10-01  194: 		} else {
2685ec94a9 1980-10-01  195: 			if (hrs > 0)
2685ec94a9 1980-10-01  196: 				printf(" %d hr%s,", hrs, hrs>1?"s":"");
2685ec94a9 1980-10-01  197: 			if (mins > 0)
2685ec94a9 1980-10-01  198: 				printf(" %d min%s,", mins, mins>1?"s":"");
2685ec94a9 1980-10-01  199: 		}
2685ec94a9 1980-10-01  200: 
2685ec94a9 1980-10-01  201: 		/* Print number of users logged in to system */
2685ec94a9 1980-10-01  202: 		while (fread(&utmp, sizeof(utmp), 1, ut)) {
2685ec94a9 1980-10-01  203: 			if (utmp.ut_name[0] != '\0')
2685ec94a9 1980-10-01  204: 				nusers++;
2685ec94a9 1980-10-01  205: 		}
2685ec94a9 1980-10-01  206: 		rewind(ut);
2685ec94a9 1980-10-01  207: 		printf("  %d users", nusers);
2685ec94a9 1980-10-01  208: 
2685ec94a9 1980-10-01  209: 		/*
2685ec94a9 1980-10-01  210: 		 * Print 1, 5, and 15 minute load averages.
2685ec94a9 1980-10-01  211: 		 * (Found by looking in kernel for avenrun).
2685ec94a9 1980-10-01  212: 		 */
2685ec94a9 1980-10-01  213: 		printf(",  load average:");
2685ec94a9 1980-10-01  214: 		lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
2685ec94a9 1980-10-01  215: 		read(kmem, avenrun, sizeof(avenrun));
2685ec94a9 1980-10-01  216: 		for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) {
2685ec94a9 1980-10-01  217: 			if (i > 0)
2685ec94a9 1980-10-01  218: 				printf(",");
2685ec94a9 1980-10-01  219: 			printf(" %.2f", avenrun[i]);
2685ec94a9 1980-10-01  220: 		}
2685ec94a9 1980-10-01  221: 		printf("\n");
2685ec94a9 1980-10-01  222: 		if (firstchar == 'u')
2685ec94a9 1980-10-01  223: 			exit(0);
2685ec94a9 1980-10-01  224: 
2685ec94a9 1980-10-01  225: 		/* Headers for rest of output */
2685ec94a9 1980-10-01  226: 		if (lflag)
2685ec94a9 1980-10-01  227: 			printf("User     tty       login@  idle   JCPU   PCPU  what\n");
2685ec94a9 1980-10-01  228: 		else
2685ec94a9 1980-10-01  229: 			printf("User    tty  idle  what\n");
2685ec94a9 1980-10-01  230: 		fflush(stdout);
2685ec94a9 1980-10-01  231: 	}
2685ec94a9 1980-10-01  232: 
2685ec94a9 1980-10-01  233: 
2685ec94a9 1980-10-01  234: 	for (;;) {	/* for each entry in utmp */
2685ec94a9 1980-10-01  235: 		if (fread(&utmp, sizeof(utmp), 1, ut) == NULL) {
2685ec94a9 1980-10-01  236: 			fclose(ut);
2685ec94a9 1980-10-01  237: 			exit(0);
2685ec94a9 1980-10-01  238: 		}
2685ec94a9 1980-10-01  239: 		if (utmp.ut_name[0] == '\0')
2685ec94a9 1980-10-01  240: 			continue;	/* that tty is free */
2685ec94a9 1980-10-01  241: 		if (sel_user && strcmpn(utmp.ut_name, sel_user, NMAX) != 0)
2685ec94a9 1980-10-01  242: 			continue;	/* we wanted only somebody else */
2685ec94a9 1980-10-01  243: 
2685ec94a9 1980-10-01  244: 		gettty();
2685ec94a9 1980-10-01  245: 		jobtime = 0;
2685ec94a9 1980-10-01  246: 		proctime = 0;
2685ec94a9 1980-10-01  247: 		strcpy(doing, "-");	/* default act: normally never prints */
2685ec94a9 1980-10-01  248: 		empty = 1;
2685ec94a9 1980-10-01  249: 		curpid = -1;
2685ec94a9 1980-10-01  250: 		idle = findidle();
2685ec94a9 1980-10-01  251: 		for (i=0; i<np; i++) {	/* for each process on this tty */
2685ec94a9 1980-10-01  252: 			if (!(TTYEQ))
2685ec94a9 1980-10-01  253: 				continue;
2685ec94a9 1980-10-01  254: 			jobtime += pr[i].w_time + pr[i].w_ctime;
2685ec94a9 1980-10-01  255: 			proctime += pr[i].w_time;
2685ec94a9 1980-10-01  256: 			if (debug) {
2685ec94a9 1980-10-01  257: 				printf("\t\t%d\t%s", pr[i].w_pid, pr[i].w_args);
2685ec94a9 1980-10-01  258: 				if ((j=pr[i].w_igintr) > 0)
2685ec94a9 1980-10-01  259: 					if (j==IGINT)
2685ec94a9 1980-10-01  260: 						printf(" &");
2685ec94a9 1980-10-01  261: 					else
2685ec94a9 1980-10-01  262: 						printf(" & %d %d", j%3, j/3);
2685ec94a9 1980-10-01  263: 				printf("\n");
2685ec94a9 1980-10-01  264: 			}
2685ec94a9 1980-10-01  265: 			if (empty && pr[i].w_igintr!=IGINT) {
2685ec94a9 1980-10-01  266: 				empty = 0;
2685ec94a9 1980-10-01  267: 				curpid = -1;
2685ec94a9 1980-10-01  268: 			}
2685ec94a9 1980-10-01  269: 			if(pr[i].w_pid>curpid && (pr[i].w_igintr!=IGINT || empty)){
2685ec94a9 1980-10-01  270: 				curpid = pr[i].w_pid;
2685ec94a9 1980-10-01  271: 				strcpy(doing, lflag ? pr[i].w_args : pr[i].w_comm);
2685ec94a9 1980-10-01  272: #ifdef notdef
2685ec94a9 1980-10-01  273: 				if (doing[0]==0 || doing[0]=='-' && doing[1]<=' ' || doing[0] == '?') {
2685ec94a9 1980-10-01  274: 					strcat(doing, " (");
2685ec94a9 1980-10-01  275: 					strcat(doing, pr[i].w_comm);
2685ec94a9 1980-10-01  276: 					strcat(doing, ")");
2685ec94a9 1980-10-01  277: 				}
2685ec94a9 1980-10-01  278: #endif
2685ec94a9 1980-10-01  279: 			}
2685ec94a9 1980-10-01  280: 		}
2685ec94a9 1980-10-01  281: 		putline();
2685ec94a9 1980-10-01  282: 	}
2685ec94a9 1980-10-01  283: }
2685ec94a9 1980-10-01  284: 
2685ec94a9 1980-10-01  285: /* figure out the major/minor device # pair for this tty */
2685ec94a9 1980-10-01  286: gettty()
2685ec94a9 1980-10-01  287: {
2685ec94a9 1980-10-01  288: 	char ttybuf[20];
2685ec94a9 1980-10-01  289: 	struct stat statbuf;
2685ec94a9 1980-10-01  290: 
2685ec94a9 1980-10-01  291: 	ttybuf[0] = 0;
2685ec94a9 1980-10-01  292: 	strcpy(ttybuf, "/dev/");
2685ec94a9 1980-10-01  293: 	strcat(ttybuf, utmp.ut_line);
2685ec94a9 1980-10-01  294: 	stat(ttybuf, &statbuf);
2685ec94a9 1980-10-01  295: 	tty = statbuf.st_rdev;
2685ec94a9 1980-10-01  296: }
2685ec94a9 1980-10-01  297: 
2685ec94a9 1980-10-01  298: /*
2685ec94a9 1980-10-01  299:  * putline: print out the accumulated line of info about one user.
2685ec94a9 1980-10-01  300:  */
2685ec94a9 1980-10-01  301: putline()
2685ec94a9 1980-10-01  302: {
2685ec94a9 1980-10-01  303: 	register int tm;
2685ec94a9 1980-10-01  304: 
2685ec94a9 1980-10-01  305: 	/* print login name of the user */
2685ec94a9 1980-10-01  306: 	printf("%-*.*s ", NMAX, NMAX, utmp.ut_name);
2685ec94a9 1980-10-01  307: 
2685ec94a9 1980-10-01  308: 	/* print tty user is on */
2685ec94a9 1980-10-01  309: 	if (lflag)
2685ec94a9 1980-10-01  310: 		/* long form: all (up to) LMAX chars */
2685ec94a9 1980-10-01  311: 		printf("%-*.*s", LMAX, LMAX, utmp.ut_line);
2685ec94a9 1980-10-01  312: 	else {
2685ec94a9 1980-10-01  313: 		/* short form: 2 chars, skipping 'tty' if there */
2685ec94a9 1980-10-01  314: 		if (utmp.ut_line[0]=='t' && utmp.ut_line[1]=='t' && utmp.ut_line[2]=='y')
2685ec94a9 1980-10-01  315: 			printf("%-2.2s", &utmp.ut_line[3]);
2685ec94a9 1980-10-01  316: 		else
2685ec94a9 1980-10-01  317: 			printf("%-2.2s", utmp.ut_line);
2685ec94a9 1980-10-01  318: 	}
2685ec94a9 1980-10-01  319: 
2685ec94a9 1980-10-01  320: 	if (lflag)
2685ec94a9 1980-10-01  321: 		/* print when the user logged in */
2685ec94a9 1980-10-01  322: 		prtat(localtime(&utmp.ut_time));
2685ec94a9 1980-10-01  323: 
2685ec94a9 1980-10-01  324: 	/* print idle time */
2685ec94a9 1980-10-01  325: 	prttime(idle," ");
2685ec94a9 1980-10-01  326: 
2685ec94a9 1980-10-01  327: 	if (lflag) {
2685ec94a9 1980-10-01  328: 		/* print CPU time for all processes & children */
2685ec94a9 1980-10-01  329: 		prttime(DIV60(jobtime)," ");
2685ec94a9 1980-10-01  330: 		/* print cpu time for interesting process */
2685ec94a9 1980-10-01  331: 		prttime(DIV60(proctime)," ");
2685ec94a9 1980-10-01  332: 	}
2685ec94a9 1980-10-01  333: 
2685ec94a9 1980-10-01  334: 	/* what user is doing, either command tail or args */
2685ec94a9 1980-10-01  335: 	printf(" %-.32s\n",doing);
2685ec94a9 1980-10-01  336: 	fflush(stdout);
2685ec94a9 1980-10-01  337: }
2685ec94a9 1980-10-01  338: 
2685ec94a9 1980-10-01  339: /* find & return number of minutes current tty has been idle */
2685ec94a9 1980-10-01  340: findidle()
2685ec94a9 1980-10-01  341: {
2685ec94a9 1980-10-01  342: 	struct stat stbuf;
2685ec94a9 1980-10-01  343: 	long lastaction, diff;
2685ec94a9 1980-10-01  344: 	char ttyname[20];
2685ec94a9 1980-10-01  345: 
2685ec94a9 1980-10-01  346: 	strcpy(ttyname, "/dev/");
2685ec94a9 1980-10-01  347: 	strcatn(ttyname, utmp.ut_line, LMAX);
2685ec94a9 1980-10-01  348: 	stat(ttyname, &stbuf);
2685ec94a9 1980-10-01  349: 	time(&now);
2685ec94a9 1980-10-01  350: 	lastaction = stbuf.st_atime;
2685ec94a9 1980-10-01  351: 	diff = now - lastaction;
2685ec94a9 1980-10-01  352: 	diff = DIV60(diff);
2685ec94a9 1980-10-01  353: 	if (diff < 0) diff = 0;
2685ec94a9 1980-10-01  354: 	return(diff);
2685ec94a9 1980-10-01  355: }
2685ec94a9 1980-10-01  356: 
2685ec94a9 1980-10-01  357: /*
2685ec94a9 1980-10-01  358:  * prttime prints a time in hours and minutes.
2685ec94a9 1980-10-01  359:  * The character string tail is printed at the end, obvious
2685ec94a9 1980-10-01  360:  * strings to pass are "", " ", or "am".
2685ec94a9 1980-10-01  361:  */
2685ec94a9 1980-10-01  362: prttime(tim, tail)
2685ec94a9 1980-10-01  363: 	time_t tim;
2685ec94a9 1980-10-01  364: 	char *tail;
2685ec94a9 1980-10-01  365: {
2685ec94a9 1980-10-01  366: 	register int didhrs = 0;
2685ec94a9 1980-10-01  367: 
2685ec94a9 1980-10-01  368: 	if (tim >= 60) {
2685ec94a9 1980-10-01  369: 		printf("%3d:", tim/60);
2685ec94a9 1980-10-01  370: 		didhrs++;
2685ec94a9 1980-10-01  371: 	} else {
2685ec94a9 1980-10-01  372: 		printf("    ");
2685ec94a9 1980-10-01  373: 	}
2685ec94a9 1980-10-01  374: 	tim %= 60;
2685ec94a9 1980-10-01  375: 	if (tim > 0 || didhrs) {
2685ec94a9 1980-10-01  376: 		printf(didhrs&&tim<10 ? "%02d" : "%2d", tim);
2685ec94a9 1980-10-01  377: 	} else {
2685ec94a9 1980-10-01  378: 		printf("  ");
2685ec94a9 1980-10-01  379: 	}
2685ec94a9 1980-10-01  380: 	printf("%s", tail);
2685ec94a9 1980-10-01  381: }
2685ec94a9 1980-10-01  382: 
2685ec94a9 1980-10-01  383: /* prtat prints a 12 hour time given a pointer to a time of day */
2685ec94a9 1980-10-01  384: prtat(p)
2685ec94a9 1980-10-01  385: 	struct tm *p;
2685ec94a9 1980-10-01  386: {
2685ec94a9 1980-10-01  387: 	register int t, pm;
2685ec94a9 1980-10-01  388: 
2685ec94a9 1980-10-01  389: 	t = p -> tm_hour;
2685ec94a9 1980-10-01  390: 	pm = (t > 11);
2685ec94a9 1980-10-01  391: 	if (t > 11)
2685ec94a9 1980-10-01  392: 		t -= 12;
2685ec94a9 1980-10-01  393: 	if (t == 0)
2685ec94a9 1980-10-01  394: 		t = 12;
2685ec94a9 1980-10-01  395: 	prttime(t*60 + p->tm_min, pm ? "pm" : "am");
2685ec94a9 1980-10-01  396: }
2685ec94a9 1980-10-01  397: 
2685ec94a9 1980-10-01  398: /*
2685ec94a9 1980-10-01  399:  * readpr finds and reads in the array pr, containing the interesting
2685ec94a9 1980-10-01  400:  * parts of the proc and user tables for each live process.
2685ec94a9 1980-10-01  401:  */
2685ec94a9 1980-10-01  402: readpr()
2685ec94a9 1980-10-01  403: {
2685ec94a9 1980-10-01  404: 	int pn, mf, addr, c;
2685ec94a9 1980-10-01  405: 	int szpt, pfnum, i;
2685ec94a9 1980-10-01  406: 	struct pte *Usrptma, *usrpt, *pte, apte;
2685ec94a9 1980-10-01  407: 	struct dblock db;
2685ec94a9 1980-10-01  408: 
2685ec94a9 1980-10-01  409: 	Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
2685ec94a9 1980-10-01  410: 	usrpt = (struct pte *) nl[X_USRPT].n_value;
2685ec94a9 1980-10-01  411: 	if((mem = open("/dev/mem", 0)) < 0) {
2685ec94a9 1980-10-01  412: 		fprintf(stderr, "No mem\n");
2685ec94a9 1980-10-01  413: 		exit(1);
2685ec94a9 1980-10-01  414: 	}
2685ec94a9 1980-10-01  415: 	if ((swap = open("/dev/drum", 0)) < 0) {
2685ec94a9 1980-10-01  416: 		fprintf(stderr, "No drum\n");
2685ec94a9 1980-10-01  417: 		exit(1);
2685ec94a9 1980-10-01  418: 	}
2685ec94a9 1980-10-01  419: 	/*
2685ec94a9 1980-10-01  420: 	 * read mem to find swap dev.
2685ec94a9 1980-10-01  421: 	 */
2685ec94a9 1980-10-01  422: 	lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0);
2685ec94a9 1980-10-01  423: 	read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value));
2685ec94a9 1980-10-01  424: 	/*
2685ec94a9 1980-10-01  425: 	 * Find base of swap
2685ec94a9 1980-10-01  426: 	 */
2685ec94a9 1980-10-01  427: 	lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
2685ec94a9 1980-10-01  428: 	read(kmem, &nswap, sizeof(nswap));
2685ec94a9 1980-10-01  429: 	/*
2685ec94a9 1980-10-01  430: 	 * Locate proc table
2685ec94a9 1980-10-01  431: 	 */
2685ec94a9 1980-10-01  432: 	np = 0;
2685ec94a9 1980-10-01  433: 	for (pn=0; pn<NPROC; pn++) {
2685ec94a9 1980-10-01  434: 		lseek(kmem, (long)(nl[X_PROC].n_value + pn*(sizeof mproc)), 0);
2685ec94a9 1980-10-01  435: 		read(kmem, &mproc, sizeof mproc);
2685ec94a9 1980-10-01  436: 		/* decide if it's an interesting process */
2685ec94a9 1980-10-01  437: 		if (mproc.p_stat==0 || mproc.p_pgrp==0)
2685ec94a9 1980-10-01  438: 			continue;
2685ec94a9 1980-10-01  439: 		if (mproc.p_flag&SDETACH)
2685ec94a9 1980-10-01  440: 			continue;
2685ec94a9 1980-10-01  441: 		
2685ec94a9 1980-10-01  442: #ifdef notdef
2685ec94a9 1980-10-01  443: 		/*
2685ec94a9 1980-10-01  444: 		 * The following speeds up w on systems with lots of ttys
2685ec94a9 1980-10-01  445: 		 * by ignoring inits and gettys, but loses on root login shells.
2685ec94a9 1980-10-01  446: 		 * On Ernie it reduced user and system time by .3 seconds,
2685ec94a9 1980-10-01  447: 		 * an insignificant amount.  It is commented out since it
2685ec94a9 1980-10-01  448: 		 * will lose when root logs in.
2685ec94a9 1980-10-01  449: 		 */
2685ec94a9 1980-10-01  450: 		if (mproc.p_uid == 0 & mproc.p_ppid == 1)
2685ec94a9 1980-10-01  451: 			continue;
2685ec94a9 1980-10-01  452: #endif
2685ec94a9 1980-10-01  453: 
2685ec94a9 1980-10-01  454: 		/* find & read in the user structure */
2685ec94a9 1980-10-01  455: 		if ((mproc.p_flag & SLOAD) == 0) {
2685ec94a9 1980-10-01  456: 			/* not in memory - get from swap device */
2685ec94a9 1980-10-01  457: 			addr = mproc.p_swaddr<<9;
2685ec94a9 1980-10-01  458: 			lseek(swap, (long)addr, 0);
2685ec94a9 1980-10-01  459: 			if (read(swap, &up, sizeof(up)) != sizeof(up)) {
2685ec94a9 1980-10-01  460: 				continue;
2685ec94a9 1980-10-01  461: 			}
2685ec94a9 1980-10-01  462: 		} else {
2685ec94a9 1980-10-01  463: 			int p0br, cc;
2685ec94a9 1980-10-01  464: #define INTPPG (NBPG / sizeof (int))
2685ec94a9 1980-10-01  465: 			struct pte pagetbl[NBPG / sizeof (struct pte)];
2685ec94a9 1980-10-01  466: 			/* loaded, get each page from memory separately */
2685ec94a9 1980-10-01  467: 			szpt = mproc.p_szpt;
2685ec94a9 1980-10-01  468: 			p0br = (int)mproc.p_p0br;
2685ec94a9 1980-10-01  469: 			pte = &Usrptma[btokmx(mproc.p_p0br) + szpt-1];
2685ec94a9 1980-10-01  470: 			lseek(kmem, (long)pte, 0);
2685ec94a9 1980-10-01  471: 			if (read(kmem, &apte, sizeof(apte)) != sizeof(apte))
2685ec94a9 1980-10-01  472: 				continue;
2685ec94a9 1980-10-01  473: 			lseek(mem, ctob(apte.pg_pfnum), 0);
2685ec94a9 1980-10-01  474: 			if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl))   
2685ec94a9 1980-10-01  475: cont:
2685ec94a9 1980-10-01  476: 				continue;
2685ec94a9 1980-10-01  477: 			for(cc=0; cc<UPAGES; cc++) {	/* get u area */
2685ec94a9 1980-10-01  478: 				int upage = pagetbl[NPTEPG-UPAGES+cc].pg_pfnum;
2685ec94a9 1980-10-01  479: 				lseek(mem,ctob(upage),0);
2685ec94a9 1980-10-01  480: 				if (read(mem,((int *)&up)+INTPPG*cc,NBPG) != NBPG)
2685ec94a9 1980-10-01  481: 					goto cont;
2685ec94a9 1980-10-01  482: 			}
2685ec94a9 1980-10-01  483: 			szpt = up.u_pcb.pcb_szpt;
2685ec94a9 1980-10-01  484: 			pr[np].w_seekaddr = ctob(apte.pg_pfnum);
2685ec94a9 1980-10-01  485: 		}
2685ec94a9 1980-10-01  486: 		vstodb(0, 1, &up.u_smap, &db, 1);
2685ec94a9 1980-10-01  487: 		pr[np].w_lastpg = ctob(db.db_base);
2685ec94a9 1980-10-01  488: 		if (up.u_ttyp == NULL)
2685ec94a9 1980-10-01  489: 			continue;
2685ec94a9 1980-10-01  490: 
2685ec94a9 1980-10-01  491: 		/* save the interesting parts */
2685ec94a9 1980-10-01  492: 		pr[np].w_pid = mproc.p_pid;
2685ec94a9 1980-10-01  493: 		pr[np].w_flag = mproc.p_flag;
2685ec94a9 1980-10-01  494: 		pr[np].w_size = mproc.p_dsize + mproc.p_ssize;
2685ec94a9 1980-10-01  495: 		pr[np].w_igintr = (((int)up.u_signal[2]==1) + 2*((int)up.u_signal[2]>1) + 3*((int)up.u_signal[3]==1)) + 6*((int)up.u_signal[3]>1);
2685ec94a9 1980-10-01  496: 		pr[np].w_time = up.u_vm.vm_utime + up.u_vm.vm_stime;
2685ec94a9 1980-10-01  497: 		pr[np].w_ctime = up.u_cvm.vm_utime + up.u_cvm.vm_stime;
2685ec94a9 1980-10-01  498: 		pr[np].w_tty = up.u_ttyd;
2685ec94a9 1980-10-01  499: 		up.u_comm[14] = 0;	/* Bug: This bombs next field. */
2685ec94a9 1980-10-01  500: 		strcpy(pr[np].w_comm, up.u_comm);
2685ec94a9 1980-10-01  501: 		/*
2685ec94a9 1980-10-01  502: 		 * Get args if there's a chance we'll print it.
2685ec94a9 1980-10-01  503: 		 * Cant just save pointer: getargs returns static place.
2685ec94a9 1980-10-01  504: 		 * Cant use strcpyn: that crock blank pads.
2685ec94a9 1980-10-01  505: 		 */
2685ec94a9 1980-10-01  506: 		pr[np].w_args[0] = 0;
2685ec94a9 1980-10-01  507: 		strcatn(pr[np].w_args,getargs(&pr[np]),ARGWIDTH);
2685ec94a9 1980-10-01  508: 		if (pr[np].w_args[0]==0 || pr[np].w_args[0]=='-' && pr[np].w_args[1]<=' ' || pr[np].w_args[0] == '?') {
2685ec94a9 1980-10-01  509: 			strcat(pr[np].w_args, " (");
2685ec94a9 1980-10-01  510: 			strcat(pr[np].w_args, pr[np].w_comm);
2685ec94a9 1980-10-01  511: 			strcat(pr[np].w_args, ")");
2685ec94a9 1980-10-01  512: 		}
2685ec94a9 1980-10-01  513: 		np++;
2685ec94a9 1980-10-01  514: 	}
2685ec94a9 1980-10-01  515: }
2685ec94a9 1980-10-01  516: 
2685ec94a9 1980-10-01  517: /*
2685ec94a9 1980-10-01  518:  * getargs: given a pointer to a proc structure, this looks at the swap area
2685ec94a9 1980-10-01  519:  * and tries to reconstruct the arguments. This is straight out of ps.
2685ec94a9 1980-10-01  520:  */
2685ec94a9 1980-10-01  521: char *
2685ec94a9 1980-10-01  522: getargs(p)
2685ec94a9 1980-10-01  523: 	struct smproc *p;
2685ec94a9 1980-10-01  524: {
2685ec94a9 1980-10-01  525: 	int c, addr, nbad;
2685ec94a9 1980-10-01  526: 	static int abuf[512/sizeof(int)];
2685ec94a9 1980-10-01  527: 	struct pte pagetbl[NPTEPG];
2685ec94a9 1980-10-01  528: 	register int *ip;
2685ec94a9 1980-10-01  529: 	register char *cp, *cp1;
2685ec94a9 1980-10-01  530: 
2685ec94a9 1980-10-01  531: 	if ((p->w_flag & SLOAD) == 0) {
2685ec94a9 1980-10-01  532: 		lseek(swap, p->w_lastpg, 0);
2685ec94a9 1980-10-01  533: 		if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
2685ec94a9 1980-10-01  534: 			return(p->w_comm);
2685ec94a9 1980-10-01  535: 	} else {
2685ec94a9 1980-10-01  536: 		c = p->w_seekaddr;
2685ec94a9 1980-10-01  537: 		lseek(mem,c,0);
2685ec94a9 1980-10-01  538: 		if (read(mem,pagetbl,NBPG) != NBPG)
2685ec94a9 1980-10-01  539: 			return(p->w_comm);
2685ec94a9 1980-10-01  540: 		if (pagetbl[NPTEPG-1-UPAGES].pg_fod==0 && pagetbl[NPTEPG-1-UPAGES].pg_pfnum) {
2685ec94a9 1980-10-01  541: 			lseek(mem,ctob(pagetbl[NPTEPG-1-UPAGES].pg_pfnum),0);
2685ec94a9 1980-10-01  542: 			if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf))
2685ec94a9 1980-10-01  543: 				return(p->w_comm);
2685ec94a9 1980-10-01  544: 		} else {
2685ec94a9 1980-10-01  545: 			lseek(swap, p->w_lastpg, 0);
2685ec94a9 1980-10-01  546: 			if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
2685ec94a9 1980-10-01  547: 				return(p->w_comm);
2685ec94a9 1980-10-01  548: 		}
2685ec94a9 1980-10-01  549: 	}
2685ec94a9 1980-10-01  550: 	abuf[127] = 0;
2685ec94a9 1980-10-01  551: 	for (ip = &abuf[126]; ip > abuf;) {
2685ec94a9 1980-10-01  552: 		/* Look from top for -1 or 0 as terminator flag. */
2685ec94a9 1980-10-01  553: 		if (*--ip == -1 || *ip == 0) {
2685ec94a9 1980-10-01  554: 			cp = (char *)(ip+1);
2685ec94a9 1980-10-01  555: 			if (*cp==0)
2685ec94a9 1980-10-01  556: 				cp++;
2685ec94a9 1980-10-01  557: 			nbad = 0;	/* up to 5 funny chars as ?'s */
2685ec94a9 1980-10-01  558: 			for (cp1 = cp; cp1 < (char *)&abuf[128]; cp1++) {
2685ec94a9 1980-10-01  559: 				c = *cp1&0177;
2685ec94a9 1980-10-01  560: 				if (c==0)  /* nulls between args => spaces */
2685ec94a9 1980-10-01  561: 					*cp1 = ' ';
2685ec94a9 1980-10-01  562: 				else if (c < ' ' || c > 0176) {
2685ec94a9 1980-10-01  563: 					if (++nbad >= 5) {
2685ec94a9 1980-10-01  564: 						*cp1++ = ' ';
2685ec94a9 1980-10-01  565: 						break;
2685ec94a9 1980-10-01  566: 					}
2685ec94a9 1980-10-01  567: 					*cp1 = '?';
2685ec94a9 1980-10-01  568: 				} else if (c=='=') {	/* Oops - found an
2685ec94a9 1980-10-01  569: 							 * environment var, back
2685ec94a9 1980-10-01  570: 							 * over & erase it. */
2685ec94a9 1980-10-01  571: 					*cp1 = 0;
2685ec94a9 1980-10-01  572: 					while (cp1>cp && *--cp1!=' ')
2685ec94a9 1980-10-01  573: 						*cp1 = 0;
2685ec94a9 1980-10-01  574: 					break;
2685ec94a9 1980-10-01  575: 				}
2685ec94a9 1980-10-01  576: 			}
2685ec94a9 1980-10-01  577: 			while (*--cp1==' ')	/* strip trailing spaces */
2685ec94a9 1980-10-01  578: 				*cp1 = 0;
2685ec94a9 1980-10-01  579: 			return(cp);
2685ec94a9 1980-10-01  580: 		}
2685ec94a9 1980-10-01  581: 	}
2685ec94a9 1980-10-01  582: 	return (p->w_comm);
2685ec94a9 1980-10-01  583: }
2685ec94a9 1980-10-01  584: 
2685ec94a9 1980-10-01  585: /*
2685ec94a9 1980-10-01  586:  * Given a base/size pair in virtual swap area,
2685ec94a9 1980-10-01  587:  * return a physical base/size pair which is the
2685ec94a9 1980-10-01  588:  * (largest) initial, physically contiguous block.
2685ec94a9 1980-10-01  589:  */
2685ec94a9 1980-10-01  590: vstodb(vsbase, vssize, dmp, dbp, rev)
2685ec94a9 1980-10-01  591: 	register int vsbase;
2685ec94a9 1980-10-01  592: 	int vssize;
2685ec94a9 1980-10-01  593: 	struct dmap *dmp;
2685ec94a9 1980-10-01  594: 	register struct dblock *dbp;
2685ec94a9 1980-10-01  595: {
2685ec94a9 1980-10-01  596: 	register int blk = DMMIN;
2685ec94a9 1980-10-01  597: 	register swblk_t *ip = dmp->dm_map;
2685ec94a9 1980-10-01  598: 
2685ec94a9 1980-10-01  599: 	if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
2685ec94a9 1980-10-01  600: 		panic("vstodb");
2685ec94a9 1980-10-01  601: 	while (vsbase >= blk) {
2685ec94a9 1980-10-01  602: 		vsbase -= blk;
2685ec94a9 1980-10-01  603: 		if (blk < DMMAX)
2685ec94a9 1980-10-01  604: 			blk *= 2;
2685ec94a9 1980-10-01  605: 		ip++;
2685ec94a9 1980-10-01  606: 	}
2685ec94a9 1980-10-01  607: 	if (*ip <= 0 || *ip + blk > nswap)
2685ec94a9 1980-10-01  608: 		panic("vstodb *ip");
2685ec94a9 1980-10-01  609: 	dbp->db_size = min(vssize, blk - vsbase);
2685ec94a9 1980-10-01  610: 	dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
2685ec94a9 1980-10-01  611: }
2685ec94a9 1980-10-01  612: 
2685ec94a9 1980-10-01  613: panic(cp)
2685ec94a9 1980-10-01  614: 	char *cp;
2685ec94a9 1980-10-01  615: {
2685ec94a9 1980-10-01  616: 
2685ec94a9 1980-10-01  617: 	/* printf("%s\n", cp); */
2685ec94a9 1980-10-01  618: }
2685ec94a9 1980-10-01  619: 
2685ec94a9 1980-10-01  620: min(a, b)
2685ec94a9 1980-10-01  621: {
2685ec94a9 1980-10-01  622: 
2685ec94a9 1980-10-01  623: 	return (a < b ? a : b);
2685ec94a9 1980-10-01  624: }