rationalized handling of child processes, cleaned up mail1 some more
[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
abebe856 14static char sccsid[] = "@(#)w.c 5.9 (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 */
abebe856 412time_t
76238d88
BJ
413findidle()
414{
415 struct stat stbuf;
416 long lastaction, diff;
417 char ttyname[20];
418
419 strcpy(ttyname, "/dev/");
420 strcatn(ttyname, utmp.ut_line, LMAX);
421 stat(ttyname, &stbuf);
422 time(&now);
423 lastaction = stbuf.st_atime;
424 diff = now - lastaction;
425 diff = DIV60(diff);
426 if (diff < 0) diff = 0;
427 return(diff);
428}
429
80b96391
MK
430#define HR (60 * 60)
431#define DAY (24 * HR)
432#define MON (30 * DAY)
433
76238d88 434/*
80b96391 435 * prttime prints a time in hours and minutes or minutes and seconds.
76238d88
BJ
436 * The character string tail is printed at the end, obvious
437 * strings to pass are "", " ", or "am".
438 */
439prttime(tim, tail)
440 time_t tim;
441 char *tail;
442{
76238d88
BJ
443
444 if (tim >= 60) {
445 printf("%3d:", tim/60);
80b96391
MK
446 tim %= 60;
447 printf("%02d", tim);
448 } else if (tim > 0)
449 printf(" %2d", tim);
450 else
451 printf(" ");
76238d88
BJ
452 printf("%s", tail);
453}
454
80b96391
MK
455char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
456char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
457 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
458
76238d88 459/* prtat prints a 12 hour time given a pointer to a time of day */
80b96391
MK
460prtat(time)
461 long *time;
76238d88 462{
80b96391
MK
463 struct tm *p;
464 register int hr, pm;
465
466 p = localtime(time);
467 hr = p->tm_hour;
468 pm = (hr > 11);
469 if (hr > 11)
470 hr -= 12;
471 if (hr == 0)
472 hr = 12;
473 if (now - *time <= 18 * HR)
474 prttime(hr * 60 + p->tm_min, pm ? "pm" : "am");
475 else if (now - *time <= 7 * DAY)
476 printf(" %s%2d%s", weekday[p->tm_wday], hr, pm ? "pm" : "am");
477 else
478 printf(" %2d%s%2d", p->tm_mday, month[p->tm_mon], p->tm_year);
76238d88
BJ
479}
480
481/*
482 * readpr finds and reads in the array pr, containing the interesting
483 * parts of the proc and user tables for each live process.
af08d75a
MT
484 * We only accept procs whos controlling tty has a pgrp equal to the
485 * pgrp of the proc. This accurately defines the notion of the current
486 * process(s), but because of time skew, we always read in the tty struct
487 * after reading the proc, even though the same tty struct may have been
488 * read earlier on.
76238d88
BJ
489 */
490readpr()
491{
492 int pn, mf, addr, c;
493 int szpt, pfnum, i;
494 struct pte *Usrptma, *usrpt, *pte, apte;
495 struct dblock db;
496
497 Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
498 usrpt = (struct pte *) nl[X_USRPT].n_value;
499 if((mem = open("/dev/mem", 0)) < 0) {
500 fprintf(stderr, "No mem\n");
501 exit(1);
502 }
503 if ((swap = open("/dev/drum", 0)) < 0) {
504 fprintf(stderr, "No drum\n");
505 exit(1);
506 }
507 /*
508 * read mem to find swap dev.
509 */
510 lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0);
511 read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value));
512 /*
68d13ee3 513 * Find base of and parameters of swap
76238d88
BJ
514 */
515 lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
516 read(kmem, &nswap, sizeof(nswap));
68d13ee3
SL
517 lseek(kmem, (long)nl[X_DMMIN].n_value, 0);
518 read(kmem, &dmmin, sizeof(dmmin));
519 lseek(kmem, (long)nl[X_DMMAX].n_value, 0);
520 read(kmem, &dmmax, sizeof(dmmax));
76238d88
BJ
521 /*
522 * Locate proc table
523 */
bdb1f95f
BJ
524 lseek(kmem, (long)nl[X_NPROC].n_value, 0);
525 read(kmem, &nproc, sizeof(nproc));
526 pr = (struct pr *)calloc(nproc, sizeof (struct pr));
76238d88 527 np = 0;
bdb1f95f
BJ
528 lseek(kmem, (long)nl[X_PROC].n_value, 0);
529 read(kmem, &aproc, sizeof(aproc));
530 for (pn=0; pn<nproc; pn++) {
531 lseek(kmem, (int)(aproc + pn), 0);
76238d88
BJ
532 read(kmem, &mproc, sizeof mproc);
533 /* decide if it's an interesting process */
af08d75a
MT
534 if (mproc.p_stat==0 || mproc.p_stat==SZOMB
535 || mproc.p_stat==SSTOP || mproc.p_pgrp==0)
76238d88 536 continue;
76238d88
BJ
537 /* find & read in the user structure */
538 if ((mproc.p_flag & SLOAD) == 0) {
539 /* not in memory - get from swap device */
20932249 540 addr = dtob(mproc.p_swaddr);
76238d88
BJ
541 lseek(swap, (long)addr, 0);
542 if (read(swap, &up, sizeof(up)) != sizeof(up)) {
543 continue;
544 }
545 } else {
546 int p0br, cc;
547#define INTPPG (NBPG / sizeof (int))
548 struct pte pagetbl[NBPG / sizeof (struct pte)];
549 /* loaded, get each page from memory separately */
550 szpt = mproc.p_szpt;
551 p0br = (int)mproc.p_p0br;
552 pte = &Usrptma[btokmx(mproc.p_p0br) + szpt-1];
553 lseek(kmem, (long)pte, 0);
554 if (read(kmem, &apte, sizeof(apte)) != sizeof(apte))
555 continue;
556 lseek(mem, ctob(apte.pg_pfnum), 0);
557 if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl))
558cont:
559 continue;
560 for(cc=0; cc<UPAGES; cc++) { /* get u area */
561 int upage = pagetbl[NPTEPG-UPAGES+cc].pg_pfnum;
562 lseek(mem,ctob(upage),0);
563 if (read(mem,((int *)&up)+INTPPG*cc,NBPG) != NBPG)
564 goto cont;
565 }
566 szpt = up.u_pcb.pcb_szpt;
567 pr[np].w_seekaddr = ctob(apte.pg_pfnum);
568 }
e941b445 569 vstodb(0, CLSIZE, &up.u_smap, &db, 1);
20932249 570 pr[np].w_lastpg = dtob(db.db_base);
76238d88
BJ
571 if (up.u_ttyp == NULL)
572 continue;
573
af08d75a
MT
574 /* only include a process whose tty has a pgrp which matchs its own */
575 lseek(kmem, (long)up.u_ttyp, 0);
576 if (read(kmem, &ttyent, sizeof(ttyent)) != sizeof(ttyent))
577 continue;
578 if (ttyent.t_pgrp != mproc.p_pgrp)
579 continue;
580
76238d88
BJ
581 /* save the interesting parts */
582 pr[np].w_pid = mproc.p_pid;
583 pr[np].w_flag = mproc.p_flag;
584 pr[np].w_size = mproc.p_dsize + mproc.p_ssize;
20932249
SL
585 pr[np].w_igintr = (((int)up.u_signal[2]==1) +
586 2*((int)up.u_signal[2]>1) + 3*((int)up.u_signal[3]==1)) +
587 6*((int)up.u_signal[3]>1);
a43be079
SL
588 pr[np].w_time =
589 up.u_ru.ru_utime.tv_sec + up.u_ru.ru_stime.tv_sec;
590 pr[np].w_ctime =
591 up.u_cru.ru_utime.tv_sec + up.u_cru.ru_stime.tv_sec;
76238d88 592 pr[np].w_tty = up.u_ttyd;
af9a91c9 593 pr[np].w_uid = mproc.p_uid;
76238d88
BJ
594 up.u_comm[14] = 0; /* Bug: This bombs next field. */
595 strcpy(pr[np].w_comm, up.u_comm);
596 /*
597 * Get args if there's a chance we'll print it.
598 * Cant just save pointer: getargs returns static place.
599 * Cant use strcpyn: that crock blank pads.
600 */
601 pr[np].w_args[0] = 0;
602 strcatn(pr[np].w_args,getargs(&pr[np]),ARGWIDTH);
603 if (pr[np].w_args[0]==0 || pr[np].w_args[0]=='-' && pr[np].w_args[1]<=' ' || pr[np].w_args[0] == '?') {
604 strcat(pr[np].w_args, " (");
605 strcat(pr[np].w_args, pr[np].w_comm);
606 strcat(pr[np].w_args, ")");
607 }
608 np++;
609 }
610}
611
612/*
613 * getargs: given a pointer to a proc structure, this looks at the swap area
614 * and tries to reconstruct the arguments. This is straight out of ps.
615 */
616char *
617getargs(p)
bdb1f95f 618 struct pr *p;
76238d88
BJ
619{
620 int c, addr, nbad;
e941b445 621 static int abuf[CLSIZE*NBPG/sizeof(int)];
76238d88
BJ
622 struct pte pagetbl[NPTEPG];
623 register int *ip;
624 register char *cp, *cp1;
625
626 if ((p->w_flag & SLOAD) == 0) {
627 lseek(swap, p->w_lastpg, 0);
628 if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
629 return(p->w_comm);
630 } else {
631 c = p->w_seekaddr;
632 lseek(mem,c,0);
633 if (read(mem,pagetbl,NBPG) != NBPG)
634 return(p->w_comm);
e941b445
BJ
635 if (pagetbl[NPTEPG-CLSIZE-UPAGES].pg_fod==0 && pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum) {
636 lseek(mem,ctob(pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum),0);
76238d88
BJ
637 if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf))
638 return(p->w_comm);
639 } else {
640 lseek(swap, p->w_lastpg, 0);
641 if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
642 return(p->w_comm);
643 }
644 }
e941b445
BJ
645 abuf[sizeof(abuf)/sizeof(abuf[0])-1] = 0;
646 for (ip = &abuf[sizeof(abuf)/sizeof(abuf[0])-2]; ip > abuf;) {
76238d88
BJ
647 /* Look from top for -1 or 0 as terminator flag. */
648 if (*--ip == -1 || *ip == 0) {
649 cp = (char *)(ip+1);
650 if (*cp==0)
651 cp++;
652 nbad = 0; /* up to 5 funny chars as ?'s */
e941b445 653 for (cp1 = cp; cp1 < (char *)&abuf[sizeof(abuf)/sizeof(abuf[0])]; cp1++) {
76238d88
BJ
654 c = *cp1&0177;
655 if (c==0) /* nulls between args => spaces */
656 *cp1 = ' ';
657 else if (c < ' ' || c > 0176) {
658 if (++nbad >= 5) {
659 *cp1++ = ' ';
660 break;
661 }
662 *cp1 = '?';
663 } else if (c=='=') { /* Oops - found an
664 * environment var, back
665 * over & erase it. */
666 *cp1 = 0;
667 while (cp1>cp && *--cp1!=' ')
668 *cp1 = 0;
669 break;
670 }
671 }
672 while (*--cp1==' ') /* strip trailing spaces */
673 *cp1 = 0;
674 return(cp);
675 }
676 }
677 return (p->w_comm);
678}
679
680/*
681 * Given a base/size pair in virtual swap area,
682 * return a physical base/size pair which is the
683 * (largest) initial, physically contiguous block.
684 */
685vstodb(vsbase, vssize, dmp, dbp, rev)
686 register int vsbase;
687 int vssize;
688 struct dmap *dmp;
689 register struct dblock *dbp;
690{
68d13ee3 691 register int blk = dmmin;
76238d88
BJ
692 register swblk_t *ip = dmp->dm_map;
693
20932249
SL
694 vsbase = ctod(vsbase);
695 vssize = ctod(vssize);
76238d88
BJ
696 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
697 panic("vstodb");
698 while (vsbase >= blk) {
699 vsbase -= blk;
68d13ee3 700 if (blk < dmmax)
76238d88
BJ
701 blk *= 2;
702 ip++;
703 }
704 if (*ip <= 0 || *ip + blk > nswap)
705 panic("vstodb *ip");
706 dbp->db_size = min(vssize, blk - vsbase);
707 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
708}
709
710panic(cp)
711 char *cp;
712{
713
714 /* printf("%s\n", cp); */
715}
716
717min(a, b)
718{
719
720 return (a < b ? a : b);
721}