|
|
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 <sys/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: double 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 *rindex();
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 = rindex(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 && strcmpn(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: strcatn(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: ino_t findtty();
439: struct pte *Usrptma, *usrpt, *pte, apte;
440: struct dblock db;
441:
442: Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
443: usrpt = (struct pte *) nl[X_USRPT].n_value;
444: if((mem = open("/dev/mem", 0)) < 0) {
445: fprintf(stderr, "No mem\n");
446: exit(1);
447: }
448: if ((swap = open("/dev/drum", 0)) < 0) {
449: fprintf(stderr, "No drum\n");
450: exit(1);
451: }
452: /*
453: * read mem to find swap dev.
454: */
455: lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0);
456: read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value));
457: /*
458: * Find base of swap
459: */
460: lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
461: read(kmem, &nswap, sizeof(nswap));
462: lseek(kmem, (long)nl[X_ECMX].n_value, 0);
463: if (read(kmem, &ecmx, sizeof (ecmx)) != sizeof (ecmx)) {
464: fprintf(stderr, "Can't read ecmx\n");
465: exit(1);
466: }
467: /*
468: * Locate proc table
469: */
470: lseek(kmem, (long)nl[X_NPROC].n_value, 0);
471: read(kmem, &nproc, sizeof(nproc));
472: pr = (struct pr *)calloc(nproc, sizeof (struct pr));
473: f = (struct find *)calloc(nproc, sizeof(struct find));
474: np = 0;
475: lseek(kmem, (long)nl[X_PROC].n_value, 0);
476: read(kmem, &aproc, sizeof(aproc));
477: for (pn=0; pn<nproc; pn++) {
478: lseek(kmem, (int)(aproc + pn), 0);
479: read(kmem, &mproc, sizeof mproc);
480: /* decide if it's an interesting process */
481: if (mproc.p_stat==0 || mproc.p_pgrp==0)
482: continue;
483: f[pn].f_parent = &f[((unsigned)mproc.p_pptr
484: - (unsigned)aproc) / sizeof(mproc)];
485: if (mproc.p_flag&SDETACH)
486: continue;
487: /* find & read in the user structure */
488: if ((mproc.p_flag & SLOAD) == 0) {
489: /* not in memory - get from swap device */
490: addr = mproc.p_swaddr<<9;
491: lseek(swap, (long)addr, 0);
492: if (read(swap, &up, sizeof(up)) != sizeof(up)) {
493: continue;
494: }
495: } else {
496: int p0br, cc;
497: #define INTPPG (NBPG / sizeof (int))
498: struct pte pagetbl[NBPG / sizeof (struct pte)];
499: /* loaded, get each page from memory separately */
500: szpt = mproc.p_szpt;
501: p0br = (int)mproc.p_p0br;
502: pte = &Usrptma[btokmx(mproc.p_p0br) + szpt-1];
503: lseek(kmem, (long)pte, 0);
504: if (read(kmem, &apte, sizeof(apte)) != sizeof(apte))
505: continue;
506: lseek(mem, ctob(apte.pg_pfnum), 0);
507: if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl))
508: cont:
509: continue;
510: for(cc=0; cc<UPAGES; cc++) { /* get u area */
511: int upage = pagetbl[NPTEPG-UPAGES+cc].pg_pfnum;
512: lseek(mem,ctob(upage),0);
513: if (read(mem,((int *)&up)+INTPPG*cc,NBPG) != NBPG)
514: goto cont;
515: }
516: szpt = up.u_pcb.pcb_szpt;
517: pr[np].w_seekaddr = ctob(apte.pg_pfnum);
518: }
519: vstodb(0, CLSIZE, &up.u_smap, &db, 1);
520: pr[np].w_lastpg = ctob(db.db_base);
521: if (up.u_ttyino == 0)
522: continue;
523:
524: /* save the interesting parts */
525: f[pn].f_pr = &pr[np];
526: pr[np].w_pid = mproc.p_pid;
527: pr[np].w_flag = mproc.p_flag;
528: if (mproc.p_stat != SIDL && mproc.p_stat != SZOMB)
529: pr[np].w_size = mproc.p_dsize + mproc.p_ssize;
530: pr[np].w_pctcpu = mproc.p_pctcpu;
531: pr[np].w_ptime = mproc.p_time;
532: if (mproc.p_stat != SIDL && mproc.p_stat != SZOMB)
533: pr[np].w_rss = mproc.p_rssize;
534: 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);
535: pr[np].w_time = up.u_vm.vm_utime + up.u_vm.vm_stime;
536: pr[np].w_ctime = up.u_cvm.vm_utime + up.u_cvm.vm_stime;
537: pr[np].w_tty = up.u_ttyino;
538: strncpy(pr[np].w_comm, up.u_comm, sizeof(up.u_comm));
539: /*
540: * Get args if there's a chance we'll print it.
541: * Cant just save pointer: getargs returns static place.
542: * Cant use strcpyn: that crock blank pads.
543: */
544: pr[np].w_args[0] = 0;
545: strcatn(pr[np].w_args,getargs(&pr[np]),ARGWIDTH);
546: if (pr[np].w_args[0]==0 || pr[np].w_args[0]=='-' && pr[np].w_args[1]<=' ' || pr[np].w_args[0] == '?') {
547: strcat(pr[np].w_args, " (");
548: strcat(pr[np].w_args, pr[np].w_comm);
549: strcat(pr[np].w_args, ")");
550: }
551: np++;
552: }
553: /* fix tty names for /dev/pt/pt?? */
554: for (pn = 0; pn < nproc; ++pn)
555: if (f[pn].f_pr)
556: f[pn].f_pr->w_tty = findtty(&f[pn]);
557: }
558:
559: /*
560: * getargs: given a pointer to a proc structure, this looks at the swap area
561: * and tries to reconstruct the arguments. This is straight out of ps.
562: */
563: char *
564: getargs(p)
565: struct pr *p;
566: {
567: int c, addr, nbad;
568: static int abuf[CLSIZE*NBPG/sizeof(int)];
569: struct pte pagetbl[NPTEPG];
570: register int *ip;
571: register char *cp, *cp1;
572:
573: if ((p->w_flag & SLOAD) == 0) {
574: lseek(swap, p->w_lastpg, 0);
575: if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
576: return(p->w_comm);
577: } else {
578: c = p->w_seekaddr;
579: lseek(mem,c,0);
580: if (read(mem,pagetbl,NBPG) != NBPG)
581: return(p->w_comm);
582: if (pagetbl[NPTEPG-CLSIZE-UPAGES].pg_fod==0 && pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum) {
583: lseek(mem,ctob(pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum),0);
584: if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf))
585: return(p->w_comm);
586: } else {
587: lseek(swap, p->w_lastpg, 0);
588: if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
589: return(p->w_comm);
590: }
591: }
592: abuf[sizeof(abuf)/sizeof(abuf[0])-1] = 0;
593: for (ip = &abuf[sizeof(abuf)/sizeof(abuf[0])-2]; ip > abuf;) {
594: /* Look from top for -1 or 0 as terminator flag. */
595: if (*--ip == -1 || *ip == 0) {
596: cp = (char *)(ip+1);
597: if (*cp==0)
598: cp++;
599: nbad = 0; /* up to 5 funny chars as ?'s */
600: for (cp1 = cp; cp1 < (char *)&abuf[sizeof(abuf)/sizeof(abuf[0])]; cp1++) {
601: c = *cp1&0177;
602: if (c==0) /* nulls between args => spaces */
603: *cp1 = ' ';
604: else if (c < ' ' || c > 0176) {
605: if (++nbad >= 5) {
606: *cp1++ = ' ';
607: break;
608: }
609: *cp1 = '?';
610: } else if (c=='=') { /* Oops - found an
611: * environment var, back
612: * over & erase it. */
613: *cp1 = 0;
614: while (cp1>cp && *--cp1!=' ')
615: *cp1 = 0;
616: break;
617: }
618: }
619: while (*--cp1==' ') /* strip trailing spaces */
620: *cp1 = 0;
621: return(cp);
622: }
623: }
624: return (p->w_comm);
625: }
626:
627: /*
628: * Given a base/size pair in virtual swap area,
629: * return a physical base/size pair which is the
630: * (largest) initial, physically contiguous block.
631: */
632: vstodb(vsbase, vssize, dmp, dbp, rev)
633: register int vsbase;
634: int vssize;
635: struct dmap *dmp;
636: register struct dblock *dbp;
637: {
638: register int blk = DMMIN;
639: register swblk_t *ip = dmp->dm_map;
640:
641: if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
642: panic("vstodb");
643: while (vsbase >= blk) {
644: vsbase -= blk;
645: if (blk < DMMAX)
646: blk *= 2;
647: ip++;
648: }
649: if (*ip <= 0 || *ip + blk > nswap)
650: panic("vstodb *ip");
651: dbp->db_size = min(vssize, blk - vsbase);
652: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
653: }
654:
655: panic(cp)
656: char *cp;
657: {
658:
659: /* printf("%s\n", cp); */
660: }
661:
662: min(a, b)
663: {
664:
665: return (a < b ? a : b);
666: }
667:
668: ino_t
669: findtty(fp)
670: struct find *fp;
671: {
672: if (fp->f_tty)
673: return(fp->f_tty);
674: if (isttyinode(fp->f_pr->w_tty))
675: return(fp->f_tty = fp->f_pr->w_tty);
676: return(fp->f_tty = findtty(fp->f_parent));
677: }
678:
679: static char *dirlist[] = {
680: "/dev/",
681: "/dev/dk/",
682: 0
683: };
684:
685: #define BITSPERBYTE 8
686: #define BITMAP 1024
687:
688: char inodes[BITMAP];
689:
690: isttyinode(i)
691: ino_t i;
692: {
693: register char **dpp, *dp;
694: int fd;
695: struct direct db;
696: static init = 0;
697:
698: if (init == 0) {
699: for (dpp = dirlist; dp = *dpp++;) {
700: if ((fd = open(dp, 0)) < 0)
701: continue;
702: while (read(fd, (char *) &db, sizeof(db)) == sizeof(db))
703: inodes[db.d_ino / BITSPERBYTE] |= (1 <<
704: (db.d_ino % BITSPERBYTE));
705: close(fd);
706: }
707: ++init;
708: }
709: return(inodes[i / BITSPERBYTE] & (1 << (i % BITSPERBYTE)));
710: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.