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