MACHINE defined by make(1), now
[unix-history] / usr / src / usr.bin / w / w.c
CommitLineData
f42904bc
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
68d13ee3 13#ifndef lint
be7adcb6 14static char sccsid[] = "@(#)w.c 5.8 (Berkeley) %G%";
f42904bc
DF
15#endif not lint
16
76238d88
BJ
17/*
18 * w - print system status (who and what)
19 *
20 * This program is similar to the systat command on Tenex/Tops 10/20
21 * It needs read permission on /dev/mem, /dev/kmem, and /dev/drum.
22 */
23#include <sys/param.h>
24#include <nlist.h>
25#include <stdio.h>
26#include <ctype.h>
27#include <utmp.h>
76238d88
BJ
28#include <sys/stat.h>
29#include <sys/dir.h>
30#include <sys/user.h>
31#include <sys/proc.h>
3b8dff21 32#include <sys/ioctl.h>
57ee57ff 33#include <machine/pte.h>
76238d88 34#include <sys/vm.h>
af08d75a 35#include <sys/tty.h>
76238d88
BJ
36
37#define NMAX sizeof(utmp.ut_name)
38#define LMAX sizeof(utmp.ut_line)
3b8dff21 39#define HMAX sizeof(utmp.ut_host)
76238d88
BJ
40
41#define ARGWIDTH 33 /* # chars left on 80 col crt for args */
42
bdb1f95f 43struct pr {
76238d88
BJ
44 short w_pid; /* proc.p_pid */
45 char w_flag; /* proc.p_flag */
46 short w_size; /* proc.p_size */
47 long w_seekaddr; /* where to find args */
48 long w_lastpg; /* disk address of stack */
49 int w_igintr; /* INTR+3*QUIT, 0=die, 1=ign, 2=catch */
50 time_t w_time; /* CPU time used by this process */
51 time_t w_ctime; /* CPU time used by children */
52 dev_t w_tty; /* tty device of process */
af9a91c9 53 int w_uid; /* uid of process */
76238d88
BJ
54 char w_comm[15]; /* user.u_comm, null terminated */
55 char w_args[ARGWIDTH+1]; /* args if interesting process */
bdb1f95f
BJ
56} *pr;
57int nproc;
76238d88
BJ
58
59struct nlist nl[] = {
be7adcb6
KB
60 { "_avenrun" },
61#define X_AVENRUN 0
62 { "_boottime" },
63#define X_BOOTTIME 1
76238d88 64 { "_proc" },
be7adcb6 65#define X_PROC 2
76238d88 66 { "_swapdev" },
be7adcb6 67#define X_SWAPDEV 3
76238d88 68 { "_Usrptmap" },
be7adcb6 69#define X_USRPTMA 4
76238d88 70 { "_usrpt" },
be7adcb6 71#define X_USRPT 5
76238d88 72 { "_nswap" },
be7adcb6 73#define X_NSWAP 6
bdb1f95f
BJ
74 { "_nproc" },
75#define X_NPROC 7
68d13ee3
SL
76 { "_dmmin" },
77#define X_DMMIN 8
78 { "_dmmax" },
79#define X_DMMAX 9
20932249 80 { "" },
76238d88
BJ
81};
82
83FILE *ps;
84FILE *ut;
85FILE *bootfd;
86int kmem;
87int mem;
88int swap; /* /dev/kmem, mem, and swap */
89int nswap;
68d13ee3 90int dmmin, dmmax;
76238d88 91dev_t tty;
af9a91c9 92int uid;
76238d88
BJ
93char doing[520]; /* process attached to terminal */
94time_t proctime; /* cpu time of process in doing */
95double avenrun[3];
bdb1f95f 96struct proc *aproc;
af08d75a 97struct tty ttyent;
76238d88 98
68d13ee3 99#define DIV60(t) ((t+30)/60) /* x/60 rounded */
af08d75a 100#define TTYEQ (tty == pr[i].w_tty)
76238d88
BJ
101#define IGINT (1+3*1) /* ignoring both SIGINT & SIGQUIT */
102
103char *getargs();
76238d88
BJ
104char *ctime();
105char *rindex();
106FILE *popen();
107struct tm *localtime();
80b96391 108time_t findidle();
76238d88
BJ
109
110int debug; /* true if -d flag: debugging output */
3b8dff21 111int ttywidth = 80; /* width of tty */
76238d88
BJ
112int header = 1; /* true if -h flag: don't print heading */
113int lflag = 1; /* true if -l flag: long style output */
3b8dff21 114int prfrom = 1; /* true if not -f flag: print host from */
76238d88 115int login; /* true if invoked as login shell */
80b96391 116time_t idle; /* number of minutes user is idle */
76238d88
BJ
117int nusers; /* number of users logged in now */
118char * sel_user; /* login of particular user selected */
119char firstchar; /* first char of name of prog invoked as */
120time_t jobtime; /* total cpu time visible */
121time_t now; /* the current time of day */
a43be079
SL
122struct timeval boottime;
123time_t uptime; /* time of last reboot & elapsed time since */
76238d88
BJ
124int np; /* number of processes currently active */
125struct utmp utmp;
126struct proc mproc;
20932249
SL
127union {
128 struct user U_up;
129 char pad[NBPG][UPAGES];
130} Up;
131#define up Up.U_up
76238d88
BJ
132
133main(argc, argv)
134 char **argv;
135{
136 int days, hrs, mins;
137 register int i, j;
138 char *cp;
139 register int curpid, empty;
3b8dff21 140 struct winsize win;
76238d88 141
76238d88
BJ
142 login = (argv[0][0] == '-');
143 cp = rindex(argv[0], '/');
144 firstchar = login ? argv[0][1] : (cp==0) ? argv[0][0] : cp[1];
145 cp = argv[0]; /* for Usage */
146
147 while (argc > 1) {
148 if (argv[1][0] == '-') {
149 for (i=1; argv[1][i]; i++) {
150 switch(argv[1][i]) {
151
152 case 'd':
153 debug++;
154 break;
155
3b8dff21
MK
156 case 'f':
157 prfrom = !prfrom;
158 break;
159
76238d88
BJ
160 case 'h':
161 header = 0;
162 break;
163
164 case 'l':
165 lflag++;
166 break;
167
168 case 's':
169 lflag = 0;
170 break;
171
172 case 'u':
173 case 'w':
635aa49f 174 firstchar = argv[1][i];
76238d88
BJ
175 break;
176
177 default:
178 printf("Bad flag %s\n", argv[1]);
179 exit(1);
180 }
181 }
182 } else {
183 if (!isalnum(argv[1][0]) || argc > 2) {
3b8dff21 184 printf("Usage: %s [ -hlsfuw ] [ user ]\n", cp);
76238d88
BJ
185 exit(1);
186 } else
187 sel_user = argv[1];
188 }
189 argc--; argv++;
190 }
191
192 if ((kmem = open("/dev/kmem", 0)) < 0) {
193 fprintf(stderr, "No kmem\n");
194 exit(1);
195 }
196 nlist("/vmunix", nl);
197 if (nl[0].n_type==0) {
198 fprintf(stderr, "No namelist\n");
199 exit(1);
200 }
201
be7adcb6
KB
202 if (firstchar == 'u') /* uptime(1) */
203 nl[X_BOOTTIME+1].n_name = "";
204 else { /* then read in procs, get window size */
205 readpr();
206 if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 70)
207 ttywidth = win.ws_col;
208 }
76238d88
BJ
209
210 ut = fopen("/etc/utmp","r");
80b96391 211 time(&now);
76238d88
BJ
212 if (header) {
213 /* Print time of day */
80b96391 214 prtat(&now);
76238d88
BJ
215
216 /*
217 * Print how long system has been up.
a43be079 218 * (Found by looking for "boottime" in kernel)
76238d88 219 */
a43be079
SL
220 lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0);
221 read(kmem, &boottime, sizeof (boottime));
76238d88 222
a43be079 223 uptime = now - boottime.tv_sec;
baaa0078 224 uptime += 30;
76238d88
BJ
225 days = uptime / (60*60*24);
226 uptime %= (60*60*24);
227 hrs = uptime / (60*60);
228 uptime %= (60*60);
baaa0078 229 mins = uptime / 60;
76238d88
BJ
230
231 printf(" up");
232 if (days > 0)
233 printf(" %d day%s,", days, days>1?"s":"");
234 if (hrs > 0 && mins > 0) {
235 printf(" %2d:%02d,", hrs, mins);
236 } else {
237 if (hrs > 0)
238 printf(" %d hr%s,", hrs, hrs>1?"s":"");
239 if (mins > 0)
240 printf(" %d min%s,", mins, mins>1?"s":"");
241 }
242
243 /* Print number of users logged in to system */
244 while (fread(&utmp, sizeof(utmp), 1, ut)) {
245 if (utmp.ut_name[0] != '\0')
246 nusers++;
247 }
248 rewind(ut);
fddf7972 249 printf(" %d user%s", nusers, nusers>1?"s":"");
76238d88
BJ
250
251 /*
252 * Print 1, 5, and 15 minute load averages.
253 * (Found by looking in kernel for avenrun).
254 */
255 printf(", load average:");
256 lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
257 read(kmem, avenrun, sizeof(avenrun));
258 for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) {
259 if (i > 0)
260 printf(",");
261 printf(" %.2f", avenrun[i]);
262 }
263 printf("\n");
af08d75a 264 if (firstchar == 'u') /* if this was uptime(1), finished */
76238d88
BJ
265 exit(0);
266
267 /* Headers for rest of output */
3b8dff21
MK
268 if (lflag && prfrom)
269 printf("User tty from login@ idle JCPU PCPU what\n");
270 else if (lflag)
76238d88 271 printf("User tty login@ idle JCPU PCPU what\n");
3b8dff21
MK
272 else if (prfrom)
273 printf("User tty from idle what\n");
76238d88
BJ
274 else
275 printf("User tty idle what\n");
276 fflush(stdout);
277 }
278
279
280 for (;;) { /* for each entry in utmp */
281 if (fread(&utmp, sizeof(utmp), 1, ut) == NULL) {
282 fclose(ut);
283 exit(0);
284 }
285 if (utmp.ut_name[0] == '\0')
286 continue; /* that tty is free */
287 if (sel_user && strcmpn(utmp.ut_name, sel_user, NMAX) != 0)
288 continue; /* we wanted only somebody else */
289
290 gettty();
291 jobtime = 0;
292 proctime = 0;
293 strcpy(doing, "-"); /* default act: normally never prints */
294 empty = 1;
295 curpid = -1;
296 idle = findidle();
297 for (i=0; i<np; i++) { /* for each process on this tty */
298 if (!(TTYEQ))
299 continue;
300 jobtime += pr[i].w_time + pr[i].w_ctime;
301 proctime += pr[i].w_time;
f8217b43
JL
302 /*
303 * Meaning of debug fields following proc name is:
304 * & by itself: ignoring both SIGINT and QUIT.
305 * (==> this proc is not a candidate.)
306 * & <i> <q>: i is SIGINT status, q is quit.
307 * 0 == DFL, 1 == IGN, 2 == caught.
308 * *: proc pgrp == tty pgrp.
309 */
310 if (debug) {
76238d88
BJ
311 printf("\t\t%d\t%s", pr[i].w_pid, pr[i].w_args);
312 if ((j=pr[i].w_igintr) > 0)
313 if (j==IGINT)
314 printf(" &");
315 else
316 printf(" & %d %d", j%3, j/3);
317 printf("\n");
318 }
319 if (empty && pr[i].w_igintr!=IGINT) {
320 empty = 0;
321 curpid = -1;
322 }
323 if(pr[i].w_pid>curpid && (pr[i].w_igintr!=IGINT || empty)){
324 curpid = pr[i].w_pid;
325 strcpy(doing, lflag ? pr[i].w_args : pr[i].w_comm);
326#ifdef notdef
327 if (doing[0]==0 || doing[0]=='-' && doing[1]<=' ' || doing[0] == '?') {
328 strcat(doing, " (");
329 strcat(doing, pr[i].w_comm);
330 strcat(doing, ")");
331 }
332#endif
333 }
334 }
335 putline();
336 }
337}
338
339/* figure out the major/minor device # pair for this tty */
340gettty()
341{
342 char ttybuf[20];
343 struct stat statbuf;
344
345 ttybuf[0] = 0;
346 strcpy(ttybuf, "/dev/");
347 strcat(ttybuf, utmp.ut_line);
348 stat(ttybuf, &statbuf);
349 tty = statbuf.st_rdev;
af9a91c9 350 uid = statbuf.st_uid;
76238d88
BJ
351}
352
353/*
354 * putline: print out the accumulated line of info about one user.
355 */
356putline()
357{
358 register int tm;
3b8dff21 359 int width = ttywidth - 1;
76238d88
BJ
360
361 /* print login name of the user */
362 printf("%-*.*s ", NMAX, NMAX, utmp.ut_name);
3b8dff21 363 width -= NMAX + 1;
76238d88
BJ
364
365 /* print tty user is on */
3b8dff21 366 if (lflag && !prfrom) {
76238d88
BJ
367 /* long form: all (up to) LMAX chars */
368 printf("%-*.*s", LMAX, LMAX, utmp.ut_line);
3b8dff21
MK
369 width -= LMAX;
370 } else {
76238d88
BJ
371 /* short form: 2 chars, skipping 'tty' if there */
372 if (utmp.ut_line[0]=='t' && utmp.ut_line[1]=='t' && utmp.ut_line[2]=='y')
373 printf("%-2.2s", &utmp.ut_line[3]);
374 else
375 printf("%-2.2s", utmp.ut_line);
3b8dff21
MK
376 width -= 2;
377 }
378
379 if (prfrom) {
380 printf(" %-14.14s", utmp.ut_host);
381 width -= 15;
76238d88
BJ
382 }
383
3b8dff21 384 if (lflag) {
76238d88 385 /* print when the user logged in */
80b96391 386 prtat(&utmp.ut_time);
3b8dff21
MK
387 width -= 8;
388 }
76238d88
BJ
389
390 /* print idle time */
80b96391
MK
391 if (idle >= 36 * 60)
392 printf("%2ddays ", (idle + 12 * 60) / (24 * 60));
393 else
394 prttime(idle," ");
3b8dff21 395 width -= 7;
76238d88
BJ
396
397 if (lflag) {
398 /* print CPU time for all processes & children */
a591da4b 399 prttime(jobtime," ");
3b8dff21 400 width -= 7;
76238d88 401 /* print cpu time for interesting process */
a591da4b 402 prttime(proctime," ");
3b8dff21 403 width -= 7;
76238d88
BJ
404 }
405
406 /* what user is doing, either command tail or args */
3b8dff21 407 printf(" %-.*s\n", width-1, doing);
76238d88
BJ
408 fflush(stdout);
409}
410
411/* find & return number of minutes current tty has been idle */
412findidle()
413{
414 struct stat stbuf;
415 long lastaction, diff;
416 char ttyname[20];
417
418 strcpy(ttyname, "/dev/");
419 strcatn(ttyname, utmp.ut_line, LMAX);
420 stat(ttyname, &stbuf);
421 time(&now);
422 lastaction = stbuf.st_atime;
423 diff = now - lastaction;
424 diff = DIV60(diff);
425 if (diff < 0) diff = 0;
426 return(diff);
427}
428
80b96391
MK
429#define HR (60 * 60)
430#define DAY (24 * HR)
431#define MON (30 * DAY)
432
76238d88 433/*
80b96391 434 * prttime prints a time in hours and minutes or minutes and seconds.
76238d88
BJ
435 * The character string tail is printed at the end, obvious
436 * strings to pass are "", " ", or "am".
437 */
438prttime(tim, tail)
439 time_t tim;
440 char *tail;
441{
76238d88
BJ
442
443 if (tim >= 60) {
444 printf("%3d:", tim/60);
80b96391
MK
445 tim %= 60;
446 printf("%02d", tim);
447 } else if (tim > 0)
448 printf(" %2d", tim);
449 else
450 printf(" ");
76238d88
BJ
451 printf("%s", tail);
452}
453
80b96391
MK
454char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
455char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
456 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
457
76238d88 458/* prtat prints a 12 hour time given a pointer to a time of day */
80b96391
MK
459prtat(time)
460 long *time;
76238d88 461{
80b96391
MK
462 struct tm *p;
463 register int hr, pm;
464
465 p = localtime(time);
466 hr = p->tm_hour;
467 pm = (hr > 11);
468 if (hr > 11)
469 hr -= 12;
470 if (hr == 0)
471 hr = 12;
472 if (now - *time <= 18 * HR)
473 prttime(hr * 60 + p->tm_min, pm ? "pm" : "am");
474 else if (now - *time <= 7 * DAY)
475 printf(" %s%2d%s", weekday[p->tm_wday], hr, pm ? "pm" : "am");
476 else
477 printf(" %2d%s%2d", p->tm_mday, month[p->tm_mon], p->tm_year);
76238d88
BJ
478}
479
480/*
481 * readpr finds and reads in the array pr, containing the interesting
482 * parts of the proc and user tables for each live process.
af08d75a
MT
483 * We only accept procs whos controlling tty has a pgrp equal to the
484 * pgrp of the proc. This accurately defines the notion of the current
485 * process(s), but because of time skew, we always read in the tty struct
486 * after reading the proc, even though the same tty struct may have been
487 * read earlier on.
76238d88
BJ
488 */
489readpr()
490{
491 int pn, mf, addr, c;
492 int szpt, pfnum, i;
493 struct pte *Usrptma, *usrpt, *pte, apte;
494 struct dblock db;
495
496 Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
497 usrpt = (struct pte *) nl[X_USRPT].n_value;
498 if((mem = open("/dev/mem", 0)) < 0) {
499 fprintf(stderr, "No mem\n");
500 exit(1);
501 }
502 if ((swap = open("/dev/drum", 0)) < 0) {
503 fprintf(stderr, "No drum\n");
504 exit(1);
505 }
506 /*
507 * read mem to find swap dev.
508 */
509 lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0);
510 read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value));
511 /*
68d13ee3 512 * Find base of and parameters of swap
76238d88
BJ
513 */
514 lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
515 read(kmem, &nswap, sizeof(nswap));
68d13ee3
SL
516 lseek(kmem, (long)nl[X_DMMIN].n_value, 0);
517 read(kmem, &dmmin, sizeof(dmmin));
518 lseek(kmem, (long)nl[X_DMMAX].n_value, 0);
519 read(kmem, &dmmax, sizeof(dmmax));
76238d88
BJ
520 /*
521 * Locate proc table
522 */
bdb1f95f
BJ
523 lseek(kmem, (long)nl[X_NPROC].n_value, 0);
524 read(kmem, &nproc, sizeof(nproc));
525 pr = (struct pr *)calloc(nproc, sizeof (struct pr));
76238d88 526 np = 0;
bdb1f95f
BJ
527 lseek(kmem, (long)nl[X_PROC].n_value, 0);
528 read(kmem, &aproc, sizeof(aproc));
529 for (pn=0; pn<nproc; pn++) {
530 lseek(kmem, (int)(aproc + pn), 0);
76238d88
BJ
531 read(kmem, &mproc, sizeof mproc);
532 /* decide if it's an interesting process */
af08d75a
MT
533 if (mproc.p_stat==0 || mproc.p_stat==SZOMB
534 || mproc.p_stat==SSTOP || mproc.p_pgrp==0)
76238d88 535 continue;
76238d88
BJ
536 /* find & read in the user structure */
537 if ((mproc.p_flag & SLOAD) == 0) {
538 /* not in memory - get from swap device */
20932249 539 addr = dtob(mproc.p_swaddr);
76238d88
BJ
540 lseek(swap, (long)addr, 0);
541 if (read(swap, &up, sizeof(up)) != sizeof(up)) {
542 continue;
543 }
544 } else {
545 int p0br, cc;
546#define INTPPG (NBPG / sizeof (int))
547 struct pte pagetbl[NBPG / sizeof (struct pte)];
548 /* loaded, get each page from memory separately */
549 szpt = mproc.p_szpt;
550 p0br = (int)mproc.p_p0br;
551 pte = &Usrptma[btokmx(mproc.p_p0br) + szpt-1];
552 lseek(kmem, (long)pte, 0);
553 if (read(kmem, &apte, sizeof(apte)) != sizeof(apte))
554 continue;
555 lseek(mem, ctob(apte.pg_pfnum), 0);
556 if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl))
557cont:
558 continue;
559 for(cc=0; cc<UPAGES; cc++) { /* get u area */
560 int upage = pagetbl[NPTEPG-UPAGES+cc].pg_pfnum;
561 lseek(mem,ctob(upage),0);
562 if (read(mem,((int *)&up)+INTPPG*cc,NBPG) != NBPG)
563 goto cont;
564 }
565 szpt = up.u_pcb.pcb_szpt;
566 pr[np].w_seekaddr = ctob(apte.pg_pfnum);
567 }
e941b445 568 vstodb(0, CLSIZE, &up.u_smap, &db, 1);
20932249 569 pr[np].w_lastpg = dtob(db.db_base);
76238d88
BJ
570 if (up.u_ttyp == NULL)
571 continue;
572
af08d75a
MT
573 /* only include a process whose tty has a pgrp which matchs its own */
574 lseek(kmem, (long)up.u_ttyp, 0);
575 if (read(kmem, &ttyent, sizeof(ttyent)) != sizeof(ttyent))
576 continue;
577 if (ttyent.t_pgrp != mproc.p_pgrp)
578 continue;
579
76238d88
BJ
580 /* save the interesting parts */
581 pr[np].w_pid = mproc.p_pid;
582 pr[np].w_flag = mproc.p_flag;
583 pr[np].w_size = mproc.p_dsize + mproc.p_ssize;
20932249
SL
584 pr[np].w_igintr = (((int)up.u_signal[2]==1) +
585 2*((int)up.u_signal[2]>1) + 3*((int)up.u_signal[3]==1)) +
586 6*((int)up.u_signal[3]>1);
a43be079
SL
587 pr[np].w_time =
588 up.u_ru.ru_utime.tv_sec + up.u_ru.ru_stime.tv_sec;
589 pr[np].w_ctime =
590 up.u_cru.ru_utime.tv_sec + up.u_cru.ru_stime.tv_sec;
76238d88 591 pr[np].w_tty = up.u_ttyd;
af9a91c9 592 pr[np].w_uid = mproc.p_uid;
76238d88
BJ
593 up.u_comm[14] = 0; /* Bug: This bombs next field. */
594 strcpy(pr[np].w_comm, up.u_comm);
595 /*
596 * Get args if there's a chance we'll print it.
597 * Cant just save pointer: getargs returns static place.
598 * Cant use strcpyn: that crock blank pads.
599 */
600 pr[np].w_args[0] = 0;
601 strcatn(pr[np].w_args,getargs(&pr[np]),ARGWIDTH);
602 if (pr[np].w_args[0]==0 || pr[np].w_args[0]=='-' && pr[np].w_args[1]<=' ' || pr[np].w_args[0] == '?') {
603 strcat(pr[np].w_args, " (");
604 strcat(pr[np].w_args, pr[np].w_comm);
605 strcat(pr[np].w_args, ")");
606 }
607 np++;
608 }
609}
610
611/*
612 * getargs: given a pointer to a proc structure, this looks at the swap area
613 * and tries to reconstruct the arguments. This is straight out of ps.
614 */
615char *
616getargs(p)
bdb1f95f 617 struct pr *p;
76238d88
BJ
618{
619 int c, addr, nbad;
e941b445 620 static int abuf[CLSIZE*NBPG/sizeof(int)];
76238d88
BJ
621 struct pte pagetbl[NPTEPG];
622 register int *ip;
623 register char *cp, *cp1;
624
625 if ((p->w_flag & SLOAD) == 0) {
626 lseek(swap, p->w_lastpg, 0);
627 if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
628 return(p->w_comm);
629 } else {
630 c = p->w_seekaddr;
631 lseek(mem,c,0);
632 if (read(mem,pagetbl,NBPG) != NBPG)
633 return(p->w_comm);
e941b445
BJ
634 if (pagetbl[NPTEPG-CLSIZE-UPAGES].pg_fod==0 && pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum) {
635 lseek(mem,ctob(pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum),0);
76238d88
BJ
636 if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf))
637 return(p->w_comm);
638 } else {
639 lseek(swap, p->w_lastpg, 0);
640 if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
641 return(p->w_comm);
642 }
643 }
e941b445
BJ
644 abuf[sizeof(abuf)/sizeof(abuf[0])-1] = 0;
645 for (ip = &abuf[sizeof(abuf)/sizeof(abuf[0])-2]; ip > abuf;) {
76238d88
BJ
646 /* Look from top for -1 or 0 as terminator flag. */
647 if (*--ip == -1 || *ip == 0) {
648 cp = (char *)(ip+1);
649 if (*cp==0)
650 cp++;
651 nbad = 0; /* up to 5 funny chars as ?'s */
e941b445 652 for (cp1 = cp; cp1 < (char *)&abuf[sizeof(abuf)/sizeof(abuf[0])]; cp1++) {
76238d88
BJ
653 c = *cp1&0177;
654 if (c==0) /* nulls between args => spaces */
655 *cp1 = ' ';
656 else if (c < ' ' || c > 0176) {
657 if (++nbad >= 5) {
658 *cp1++ = ' ';
659 break;
660 }
661 *cp1 = '?';
662 } else if (c=='=') { /* Oops - found an
663 * environment var, back
664 * over & erase it. */
665 *cp1 = 0;
666 while (cp1>cp && *--cp1!=' ')
667 *cp1 = 0;
668 break;
669 }
670 }
671 while (*--cp1==' ') /* strip trailing spaces */
672 *cp1 = 0;
673 return(cp);
674 }
675 }
676 return (p->w_comm);
677}
678
679/*
680 * Given a base/size pair in virtual swap area,
681 * return a physical base/size pair which is the
682 * (largest) initial, physically contiguous block.
683 */
684vstodb(vsbase, vssize, dmp, dbp, rev)
685 register int vsbase;
686 int vssize;
687 struct dmap *dmp;
688 register struct dblock *dbp;
689{
68d13ee3 690 register int blk = dmmin;
76238d88
BJ
691 register swblk_t *ip = dmp->dm_map;
692
20932249
SL
693 vsbase = ctod(vsbase);
694 vssize = ctod(vssize);
76238d88
BJ
695 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
696 panic("vstodb");
697 while (vsbase >= blk) {
698 vsbase -= blk;
68d13ee3 699 if (blk < dmmax)
76238d88
BJ
700 blk *= 2;
701 ip++;
702 }
703 if (*ip <= 0 || *ip + blk > nswap)
704 panic("vstodb *ip");
705 dbp->db_size = min(vssize, blk - vsbase);
706 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
707}
708
709panic(cp)
710 char *cp;
711{
712
713 /* printf("%s\n", cp); */
714}
715
716min(a, b)
717{
718
719 return (a < b ? a : b);
720}