1: #define UCB         /* Controls output format for -F */
   2: 
   3: /*
   4:  * ls - list file or directory
   5:  *
   6:  * this version of ls is designed for graphic terminals and to
   7:  * list directories with lots of files in them compactly.
   8:  * It supports three variants for listings:
   9:  *
  10:  *	1) Columnar output.
  11:  *	2) Stream output.
  12:  *	3) Old one per line format.
  13:  *
  14:  * Columnar output is the default.
  15:  * If, however, the standard output is not a teletype, the default
  16:  * is one-per-line.
  17:  *
  18:  * With columnar output, the items are sorted down the columns.
  19:  * We use columns only for a directory we are interpreting.
  20:  * Thus, in particular, we do not use columns for
  21:  *
  22:  *	ls /usr/bin/p*
  23:  *
  24:  * This version of ls also prints non-printing characters as '?' if
  25:  * the standard output is a teletype.
  26:  *
  27:  * Flags relating to these and other new features are:
  28:  *
  29:  *	-m	force stream output.
  30:  *
  31:  *	-1	force one entry per line, e.g. to a teletype
  32:  *
  33:  *	-q	force non-printings to be '?'s, e.g. to a file
  34:  *
  35:  *	-C	force columnar output, e.g. into a file
  36:  *
  37:  *	-n	like -l, but user/group id's in decimal rather than
  38:  *		looking in /etc/passwd to save time
  39:  *
  40:  *	-F	turns on the "flagging" of executables and directories
  41:  *
  42:  *	-R	causes ls to recurse through the branches of the subtree
  43:  *		ala find
  44:  */
  45: 
  46: #include <sys/param.h>
  47: #include <sys/stat.h>
  48: #include <sys/dir.h>
  49: #include <stdio.h>
  50: #include <ctype.h>
  51: #include <pwd.h>
  52: #include <grp.h>
  53: #include <utmp.h>
  54: #include <sgtty.h>
  55: #include <varargs.h>
  56: #ifdef  UCB_QUOTAS
  57: #include <sys/inode.h>
  58: #include <sys/qstat.h>
  59: #endif
  60: 
  61: #ifndef NFILES
  62: #define NFILES  1024
  63: #endif
  64: #ifndef NUID
  65: #define NUID    512 /* must not be a multiple of 5 */
  66: #endif
  67: #ifndef NGID
  68: #define NGID    32  /* must not be a multiple of 5 */
  69: #endif
  70: 
  71: struct  utmp    utmp;
  72: #define NMAX    (sizeof (utmp.ut_name))
  73: 
  74: #define MAXFILEWIDTH 14
  75: FILE    *pwdf, *dirf;
  76: 
  77: struct lbuf {
  78:     union {
  79:         char    lname[15];
  80:         char    *namep;
  81:     } ln;
  82:     char    ltype;
  83:     ino_t   lnum;
  84:     short   lflags;
  85:     short   lnl;
  86:     short   luid;
  87:     short   lgid;
  88:     long    lsize;
  89:     long    lmtime;
  90: #ifdef  UCB_QUOTAS
  91:     long    lqused;
  92:     long    lqmax;
  93: #endif
  94: };
  95: 
  96: struct dchain {
  97:     char *dc_name;      /* the path name */
  98:     struct dchain *dc_next; /* the next directory on the chain */
  99: };
 100: 
 101: struct dchain *dfirst;      /* the start of the directory chain */
 102: struct dchain *cdfirst;     /* the start of the current directory chain */
 103: struct dchain *dtemp;       /* temporary used when linking */
 104: char *curdir;           /* the current directory */
 105: 
 106: int aflg, bflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
 107: int Aflg, nflg, qflg, Fflg, Rflg, across, Cflg;
 108: int nopad;
 109: int tabflg;
 110: int rflg    = 1;
 111: long    year;
 112: int flags;
 113: long    tblocks;
 114: int statreq;
 115: int xtraent;        /* for those switches which print out a total */
 116: struct  lbuf    *flist[NFILES];
 117: struct  lbuf    **lastp = flist;
 118: struct  lbuf    **firstp = flist;
 119: char    *dotp   = ".";
 120: 
 121: char    *makename();
 122: struct  lbuf *gstat();
 123: char    *ctime();
 124: long    nblock();
 125: char    *getname();
 126: char    *getgroup();
 127: 
 128: #define ISARG   0100000
 129: int colwidth;
 130: int filewidth;
 131: int fixedwidth;
 132: int outcol;
 133: 
 134: extern  char _sobuf[];
 135: 
 136: main(argc, argv)
 137: int argc;
 138: char *argv[];
 139: {
 140:     int i, width;
 141:     register struct lbuf *ep;
 142:     register struct lbuf **slastp;
 143:     struct lbuf **epp;
 144:     struct lbuf lb;
 145:     char *t;
 146:     char *cp;
 147:     int compar();
 148:     struct sgttyb sgbuf;
 149: 
 150:     Fflg = 0;
 151:     tabflg = 0;
 152:     Aflg = getuid() == 0;
 153:     setbuf(stdout, _sobuf);
 154:     time (&lb.lmtime);
 155:     year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
 156:     qflg = gtty(1, &sgbuf) == 0;
 157: 
 158:     /* guarantee at least on column width */
 159:     fixedwidth = 2;
 160: 
 161:     /*
 162: 	 * If the standard output is not a teletype,
 163: 	 * then we default to one-per-line format
 164: 	 * otherwise decide between stream and
 165: 	 * columnar based on our name.
 166: 	 */
 167:     if (qflg) {
 168:         Cflg = 1;
 169:         if ((sgbuf.sg_flags & XTABS) == 0)
 170:             tabflg++;
 171:         for (cp = argv[0]; cp[0] && cp[1]; cp++)
 172:             continue;
 173:         /*
 174: 		 * Certain kinds of links (l, ll, lr, lf, lx) cause some
 175: 		 * various options to be turned on.
 176: 		 */
 177:         switch (cp[0]) {
 178:         case 'l':
 179:             if (cp[-1] == 'l') {
 180:                 /* ll => -l */
 181:                 lflg = 1;
 182:                 statreq++;
 183:                 xtraent++;
 184:             } else {
 185:                 /* l => -m */
 186:                 nopad = 1;
 187:                 Cflg = 0;
 188:             }
 189:             break;
 190:         case 'x':   /* lx => -x */
 191:             across = 1;
 192:             break;
 193:         case 'f':   /* lf => -F */
 194:             Fflg = 1;
 195:             break;
 196:         case 'r':   /* lr => -R */
 197:             Rflg = 1;
 198:             break;
 199:         }
 200:     } else {
 201:         tabflg++;
 202:     }
 203: 
 204:     while (--argc > 0 && *argv[1] == '-') {
 205:         argv++;
 206:         while (*++*argv) switch (**argv) {
 207:         /*
 208: 		 * C - force columnar output
 209: 		 */
 210:         case 'C':
 211:             Cflg = 1;
 212:             nopad = 0;
 213:             continue;
 214:         /*
 215: 		 * m - force stream output
 216: 		 */
 217:         case 'm':
 218:             Cflg = 0;
 219:             nopad = 1;
 220:             continue;
 221:         /*
 222: 		 * x - force sort across
 223: 		 */
 224:         case 'x':
 225:             across = 1;
 226:             nopad = 0;
 227:             Cflg = 1;
 228:             continue;
 229:         /*
 230: 		 * q - force ?'s in output
 231: 		 */
 232:         case 'q':
 233:             qflg = 1;
 234:             bflg = 0;
 235:             continue;
 236:         /*
 237: 		 * b - force octal value in output
 238: 		 */
 239:         case 'b':
 240:             bflg = 1;
 241:             qflg = 0;
 242:             continue;
 243:         /*
 244: 		 * 1 - force 1/line in output
 245: 		 */
 246:         case '1':
 247:             Cflg = 0;
 248:             nopad = 0;
 249:             continue;
 250:         /* STANDARD FLAGS */
 251:         case 'a':
 252:             aflg++;
 253:             continue;
 254: 
 255:         case 'A':
 256:             Aflg = !Aflg;
 257:             continue;
 258: 
 259:         case 'c':
 260:             cflg++;
 261:             continue;
 262: 
 263:         case 's':
 264:             fixedwidth += 5;
 265:             sflg++;
 266:             statreq++;
 267:             xtraent++;
 268:             continue;
 269: 
 270:         case 'd':
 271:             dflg++;
 272:             continue;
 273: 
 274:         /*
 275: 		 * n - don't look in password file
 276: 		 */
 277:         case 'n':
 278:             nflg++;
 279:         case 'l':
 280:             lflg++;
 281:             statreq++;
 282:             xtraent++;
 283:             continue;
 284: 
 285:         case 'r':
 286:             rflg = -1;
 287:             continue;
 288: 
 289:         case 't':
 290:             tflg++;
 291:             statreq++;
 292:             continue;
 293: 
 294:         case 'u':
 295:             uflg++;
 296:             continue;
 297: 
 298:         case 'i':
 299:             fixedwidth += 6;
 300:             iflg++;
 301:             continue;
 302: 
 303:         case 'f':
 304:             fflg++;
 305:             continue;
 306: 
 307:         case 'g':
 308:             gflg++;
 309:             continue;
 310: 
 311:         case 'F':
 312:             Fflg++;
 313:             continue;
 314: 
 315:         case 'R':
 316:             Rflg++;
 317:             continue;
 318: 
 319:         default:
 320:             fprintf (stderr, "usage: ls [-1ACFRabcdfgilmnqrstux] [files]\n");
 321:             exit(1);
 322:         }
 323:     }
 324:     if (Fflg)
 325: #ifdef UCB
 326:         fixedwidth++;
 327: #else
 328:         fixedwidth += 2;
 329: #endif
 330:     if (fflg) {
 331:         aflg++;
 332:         lflg = 0;
 333:         sflg = 0;
 334:         tflg = 0;
 335:         statreq = 0;
 336:         xtraent = 0;
 337:     }
 338:     if(lflg) {
 339:         Cflg = 0;
 340:         t = "/etc/passwd";
 341:         if (gflg)
 342:             t = "/etc/group";
 343:         nopad = 0;
 344:         fixedwidth = 70;
 345:         pwdf = fopen(t, "r");
 346:     }
 347:     if (argc==0) {
 348:         argc++;
 349:         argv = &dotp - 1;
 350:     }
 351:     for (i=0; i < argc; i++) {
 352:         argv++;
 353:         if (Cflg) {
 354:             width = strlen (*argv);
 355:             if (width > filewidth)
 356:                 filewidth = width;
 357:         }
 358:         if ((ep = gstat(*argv, 1))==NULL)
 359:             continue;
 360:         ep->ln.namep = *argv;
 361:         ep->lflags |= ISARG;
 362:     }
 363:     if (!Cflg)
 364:         filewidth = MAXFILEWIDTH;
 365:     else
 366:     colwidth = fixedwidth + filewidth;
 367:     qsort(firstp, lastp - firstp, sizeof *lastp, compar);
 368:     slastp = lastp;
 369:     /* For each argument user typed */
 370:     for (epp=firstp; epp<slastp; epp++) {
 371:         ep = *epp;
 372:         if (ep->ltype=='d' && dflg==0 || fflg)
 373:             pdirectory(ep->ln.namep, (argc>1), slastp);
 374:         else
 375:             pentry(ep);
 376: 
 377:         /* -R: print subdirectories found */
 378:         while (dfirst || cdfirst) {
 379:             /* Place direct subdirs on front in right order */
 380:             while (cdfirst) {
 381:                 /* reverse cdfirst onto front of dfirst */
 382:                 dtemp = cdfirst;
 383:                 cdfirst = cdfirst -> dc_next;
 384:                 dtemp -> dc_next = dfirst;
 385:                 dfirst = dtemp;
 386:             }
 387:             /* take off first dir on dfirst & print it */
 388:             dtemp = dfirst;
 389:             dfirst = dfirst->dc_next;
 390:             pdirectory (dtemp->dc_name, 1, firstp);
 391:             cfree (dtemp->dc_name);
 392:             cfree (dtemp);
 393:         }
 394:     }
 395:     if (outcol)
 396:         putc('\n', stdout);
 397:     fflush(stdout);
 398: }
 399: 
 400: /*
 401:  * pdirectory: print the directory name, labelling it if title is
 402:  * nonzero, using lp as the place to start reading in the dir.
 403:  */
 404: pdirectory (name, title, lp)
 405: char *name;
 406: int title;
 407: struct lbuf **lp;
 408: {
 409:     register struct dchain *dp;
 410:     register struct lbuf *ap;
 411:     register char *pname;
 412:     struct lbuf **app;
 413: 
 414:     filewidth = 0;
 415:     curdir = name;
 416:     if (title)
 417:         printf("\n%s:\n", name);
 418:     lastp = lp;
 419:     readdir(name);
 420:     if (!Cflg)
 421:         filewidth = MAXFILEWIDTH;
 422:     colwidth = fixedwidth + filewidth;
 423: #ifdef notdef
 424:     /* Taken out because it appears this is done below in pem. */
 425:     if (tabflg) {
 426:         if (colwidth <= 8)
 427:             colwidth = 8;
 428:         else
 429:             if (colwidth <= 16)
 430:                 colwidth = 16;
 431:     }
 432: #endif
 433:     if (fflg==0)
 434:         qsort(lp,lastp - lp,sizeof *lastp,compar);
 435:     if (Rflg) for (app=lastp-1; app>=lp; app--) {
 436:         ap = *app;
 437:         if (ap->ltype == 'd' && strcmp(ap->ln.lname, ".") &&
 438:                 strcmp(ap->ln.lname, "..")) {
 439:             dp = (struct dchain *) calloc(1, sizeof(struct dchain));
 440:             pname = makename (curdir, ap->ln.lname);
 441:             dp->dc_name = (char *) calloc(1, strlen(pname)+1);
 442:             strcpy(dp->dc_name, pname);
 443:             dp -> dc_next = dfirst;
 444:             dfirst = dp;
 445:         }
 446:     }
 447:     if (lflg || sflg)
 448:         printf("total %D", tblocks);
 449:     pem(lp, lastp);
 450:     newline();
 451: }
 452: 
 453: /*
 454:  * pem: print 'em.  Print a list of files (e.g. a directory) bounded
 455:  * by slp and lp.
 456:  */
 457: pem(slp, lp)
 458:     register struct lbuf **slp, **lp;
 459: {
 460:     int ncols, nrows, row, col;
 461:     register struct lbuf **ep;
 462: 
 463:     if (tabflg) {
 464:         if (colwidth <= 9)
 465:             colwidth = 8;
 466:         else
 467:             if (colwidth <= 17)
 468:                 colwidth = 16;
 469:     }
 470:     ncols = 80 / colwidth;
 471:     if (ncols == 1 || Cflg == 0) {
 472:         for (ep = slp; ep < lp; ep++)
 473:             pentry(*ep);
 474:         return;
 475:     }
 476:     if (across) {
 477:         for (ep = slp; ep < lp; ep++)
 478:             pentry(*ep);
 479:         return;
 480:     }
 481:     if (xtraent)
 482:         slp--;
 483:     nrows = (lp - slp - 1) / ncols + 1;
 484:     for (row = 0; row < nrows; row++) {
 485:         col = row == 0 && xtraent;
 486:         for (; col < ncols; col++) {
 487:             ep = slp + (nrows * col) + row;
 488:             if (ep < lp)
 489:                 pentry(*ep);
 490:         }
 491:         if (outcol)
 492:             printf("\n");
 493:     }
 494: }
 495: 
 496: /*
 497:  * pputchar: like putchar but knows how to handle control chars.
 498:  * CAUTION: if you make ctrl chars print in ^x notation, or any
 499:  * other notation which is wider than one character, the column
 500:  * nature of things (such as files with 14 letter names) will be
 501:  * messed up.  Weigh this carefully!
 502:  */
 503: pputchar(c)
 504:     char c;
 505: {
 506:     char cc;
 507: 
 508:     switch (c) {
 509:         case '\t':
 510:             outcol = (outcol + 8) &~ 7;
 511:             break;
 512:         case '\n':
 513:             outcol = 0;
 514:             break;
 515:         default:
 516:             if (c < ' ' || c >= 0177) {
 517:                 if (qflg)
 518:                     c = '?';
 519:                 else if (bflg) {
 520:                     outcol += 3;
 521:                     putc ('\\', stdout);
 522:                     cc = '0' + (c>>6 & 07);
 523:                     putc (cc, stdout);
 524:                     cc = '0' + (c>>3 & 07);
 525:                     putc (cc, stdout);
 526:                     c = '0' + (c & 07);
 527:                 }
 528:             }
 529:             outcol++;
 530:             break;
 531:     }
 532:     putc(c, stdout);
 533: }
 534: 
 535: newline()
 536: {
 537:     if (outcol)
 538:         putc('\n', stdout);
 539:     outcol = 0;
 540: }
 541: 
 542: /*
 543:  * column: get to the beginning of the next column.
 544:  */
 545: column()
 546: {
 547: 
 548:     if (outcol == 0)
 549:         return;
 550:     if (nopad) {
 551:         putc(',', stdout);
 552:         outcol++;
 553:         if (outcol + colwidth + 2 > 80) {
 554:             putc('\n', stdout);
 555:             outcol = 0;
 556:             return;
 557:         }
 558:         putc(' ', stdout);
 559:         outcol++;
 560:         return;
 561:     }
 562:     if (Cflg == 0) {
 563:         putc('\n', stdout);
 564:         return;
 565:     }
 566:     if ((outcol / colwidth + 2) * colwidth > 80) {
 567:         putc('\n', stdout);
 568:         outcol = 0;
 569:         return;
 570:     }
 571:     if (tabflg && (colwidth <= 16)) {
 572:         if (colwidth > 8)
 573:             if ((outcol % 16) < 8) {
 574:                 outcol += 8 - (outcol % 8);
 575:                 putc ('\t', stdout);
 576:             }
 577:         outcol += 8 - (outcol % 8);
 578:         putc ('\t', stdout);
 579:         return;
 580:     }
 581:     do {
 582:         outcol++;
 583:         putc(' ', stdout);
 584:     } while (outcol % colwidth);
 585: }
 586: 
 587: 
 588: /*
 589:  * nblock: the number of 1024 byte blocks a size byte file takes up.
 590:  */
 591: long
 592: nblock(size)
 593: long size;
 594: {
 595:     return((size+1023)>>10);
 596: }
 597: 
 598: /*
 599:  * This code handles the rwx- business.
 600:  * You figure it out.
 601:  */
 602: int m1[] = { 1, S_IREAD>>0, 'r', '-' };
 603: int m2[] = { 1, S_IWRITE>>0, 'w', '-' };
 604: int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
 605: int m4[] = { 1, S_IREAD>>3, 'r', '-' };
 606: int m5[] = { 1, S_IWRITE>>3, 'w', '-' };
 607: int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
 608: int m7[] = { 1, S_IREAD>>6, 'r', '-' };
 609: int m8[] = { 1, S_IWRITE>>6, 'w', '-' };
 610: int m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
 611: 
 612: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
 613: 
 614: pmode(aflag)
 615: {
 616:     register int **mp;
 617: 
 618:     flags = aflag;
 619:     for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
 620:         select(*mp++);
 621: }
 622: 
 623: select(pairp)
 624: register int *pairp;
 625: {
 626:     register int n;
 627: 
 628:     n = *pairp++;
 629:     while (--n>=0 && (flags&*pairp++)==0)
 630:         pairp++;
 631:     pputchar(*pairp);
 632: }
 633: 
 634: /*
 635:  * returns cat(dir, "/", file), unless dir ends in /, when it doesn't //
 636:  */
 637: char *
 638: makename(dir, file)
 639: char *dir, *file;
 640: {
 641:     static char dfile[100];
 642:     register char *dp, *fp;
 643:     register int i;
 644: 
 645:     dp = dfile;
 646:     fp = dir;
 647:     while (*fp)
 648:         *dp++ = *fp++;
 649:     if (*(dp-1) != '/')
 650:     *dp++ = '/';
 651:     fp = file;
 652:     for (i=0; i<DIRSIZ; i++)
 653:         *dp++ = *fp++;
 654:     *dp = 0;
 655:     return(dfile);
 656: }
 657: 
 658: /*
 659:  * readdir: read in the directory whose name is dir,
 660:  * starting at lastp.
 661:  */
 662: readdir(dir)
 663: char *dir;
 664: {
 665:     static struct direct dentry;
 666:     register int j, width;
 667:     register struct lbuf *ep;
 668: 
 669:     if ((dirf = fopen(dir, "r")) == NULL) {
 670:         printf("%s unreadable\n", dir);
 671:         return;
 672:     }
 673:     tblocks = 0;
 674:     for(;;) {
 675:         if (fread(&dentry, sizeof(dentry), 1, dirf) != 1)
 676:             break;
 677:         if (dentry.d_ino==0 ||
 678:             aflg==0 && dentry.d_name[0]=='.' && (
 679:             !Aflg ||
 680:             dentry.d_name[1]=='\0'
 681:             || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
 682:             continue;
 683:         if (Cflg) {
 684:             width = strlen (dentry.d_name);
 685:             if (width > filewidth)
 686:                 filewidth = width;
 687:         }
 688:         ep = gstat(makename(dir, dentry.d_name), Fflg || Rflg);
 689:         if (ep==NULL)
 690:             continue;
 691:         if (ep->lnum != -1)
 692:             ep->lnum = dentry.d_ino;
 693:         for (j=0; j<DIRSIZ; j++)
 694:             ep->ln.lname[j] = dentry.d_name[j];
 695:     }
 696:     fclose(dirf);
 697: }
 698: 
 699: /*
 700:  * stat the given file and return an lbuf containing it.
 701:  * argfl is nonzero if a stat is required because the file is
 702:  * an argument, rather than having been found in a directory.
 703:  */
 704: struct lbuf *
 705: gstat(file, argfl)
 706: char *file;
 707: {
 708:     struct stat statb;
 709:     register struct lbuf *rep;
 710:     static int nomocore;
 711: #ifdef  UCB_QUOTAS
 712:     struct qstat qstatb;
 713: #endif
 714: 
 715:     if (nomocore)
 716:         return(NULL);
 717:     rep = (struct lbuf *)malloc(sizeof(struct lbuf));
 718:     if (rep==NULL) {
 719:         fprintf(stderr, "ls: out of memory\n");
 720:         nomocore = 1;
 721:         return(NULL);
 722:     }
 723:     if (lastp >= &flist[NFILES]) {
 724:         static int msg;
 725:         lastp--;
 726:         if (msg==0) {
 727:             fprintf(stderr, "ls: too many files\n");
 728:             msg++;
 729:         }
 730:     }
 731:     *lastp++ = rep;
 732:     rep->lflags = 0;
 733:     rep->lnum = 0;
 734:     rep->ltype = '-';
 735:     if (argfl || statreq) {
 736:         if (stat(file, &statb)<0) {
 737:             printf("%s not found\n", file);
 738:             statb.st_ino = -1;
 739:             statb.st_size = 0;
 740:             statb.st_mode = 0;
 741:             if (argfl) {
 742:                 lastp--;
 743:                 return(0);
 744:             }
 745:         }
 746:         rep->lnum = statb.st_ino;
 747:         rep->lsize = statb.st_size;
 748:         switch(statb.st_mode&S_IFMT) {
 749: 
 750:         case S_IFDIR:
 751:             rep->ltype = 'd';
 752:             break;
 753: 
 754:         case S_IFBLK:
 755:             rep->ltype = 'b';
 756:             rep->lsize = statb.st_rdev;
 757:             break;
 758: 
 759:         case S_IFCHR:
 760:             rep->ltype = 'c';
 761:             rep->lsize = statb.st_rdev;
 762:             break;
 763: 
 764: #ifdef  UCB_QUOTAS
 765:         case S_IFQUOT:
 766:             qstat(file, &qstatb);
 767:             rep->ltype = 'q';
 768:             rep->lqused = qstatb.qs_un.qs_qused;
 769:             rep->lqmax = qstatb.qs_un.qs_qmax;
 770:             break;
 771: #endif
 772: 
 773:         case S_IFMPB:
 774:             rep->ltype = 'M';
 775:             rep->lsize = statb.st_rdev;
 776:             break;
 777: 
 778:         case S_IFMPC:
 779:             rep->ltype = 'm';
 780:             rep->lsize = statb.st_rdev;
 781:             break;
 782:         }
 783:         rep->lflags = statb.st_mode & ~S_IFMT;
 784:         rep->luid = statb.st_uid;
 785:         rep->lgid = statb.st_gid;
 786:         rep->lnl = statb.st_nlink;
 787:         if(uflg)
 788:             rep->lmtime = statb.st_atime;
 789:         else if (cflg)
 790:             rep->lmtime = statb.st_ctime;
 791:         else
 792:             rep->lmtime = statb.st_mtime;
 793:         tblocks += nblock(statb.st_size);
 794:     }
 795:     return(rep);
 796: }
 797: 
 798: /*
 799:  * decide whether to print pp1 before or after pp2, based on their
 800:  * names, various times, and the r flag.
 801:  */
 802: compar(pp1, pp2)
 803: struct lbuf **pp1, **pp2;
 804: {
 805:     register struct lbuf *p1, *p2;
 806: 
 807:     p1 = *pp1;
 808:     p2 = *pp2;
 809:     if (dflg==0) {
 810:         if (p1->lflags&ISARG && p1->ltype=='d') {
 811:             if (!(p2->lflags&ISARG && p2->ltype=='d'))
 812:                 return(1);
 813:         } else {
 814:             if (p2->lflags&ISARG && p2->ltype=='d')
 815:                 return(-1);
 816:         }
 817:     }
 818:     if (tflg) {
 819:         if(p2->lmtime == p1->lmtime)
 820:             return(0);
 821:         if(p2->lmtime > p1->lmtime)
 822:             return(rflg);
 823:         return(-rflg);
 824:     }
 825:     return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
 826:                 p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
 827: }
 828: 
 829: /*
 830:  * print the entry pointed at by ap
 831:  */
 832: pentry(ap)
 833: struct lbuf *ap;
 834: {
 835:     struct { char dminor, dmajor;};
 836:     register struct lbuf *p;
 837:     register char *cp;
 838:     char fname[100];
 839:     char *pname, *name;
 840:     struct passwd *getpwuid();
 841:     struct passwd *pwptr;
 842:     struct group *getgrgid();
 843: 
 844:     fname[0] = 0;
 845:     p = ap;
 846:     if (p->lnum == -1)
 847:         return;
 848:     column();
 849:     if (iflg)
 850:         if (nopad && !lflg)
 851:             printf("%d ", p->lnum);
 852:         else
 853:             printf("%5d ", p->lnum);
 854:     if (sflg)
 855:         switch (p->ltype) {
 856: 
 857:         case 'b':
 858:         case 'c':
 859:         case 'm':
 860:         case 'M':
 861:             if (nopad && !lflg)
 862:                 printf("%D ", 0);
 863:             else
 864:                 printf("%4D ", 0);
 865:             break;
 866: 
 867:         default:
 868:             if (nopad && !lflg)
 869:                 printf("%D ", nblock(p->lsize));
 870:             else
 871:                 printf("%4D ", nblock(p->lsize));
 872:             break;
 873:         }
 874:     if (lflg) {
 875:         pputchar(p->ltype);
 876:         pmode(p->lflags);
 877:         printf("%2d ", p->lnl);
 878:         if(gflg) {
 879:             name = getgroup(p->lgid);
 880:             if (nflg == 0 && name != 0)
 881:                 printf("%-9.9s", name);
 882:             else
 883:                 printf("%-9d", p->lgid);
 884:         } else {
 885: #ifndef UCB_PWHASH
 886:             if (nflg == 0 && (name = getname(p->luid))) {
 887:                 printf("%-9.9s", name);
 888:             }
 889: #else
 890:             pwptr = getpwuid(p->luid);
 891:             if (nflg == 0 && pwptr != 0)
 892:                 printf("%-9.9s", pwptr->pw_name);
 893: #endif
 894:             else
 895:                 printf("%-9d", p->luid);
 896:             name = getgroup(p->lgid);
 897:             if (nflg == 0 && name != 0)
 898:                 printf("%-9.9s", name);
 899:             else
 900:                 printf("%-9d", p->lgid);
 901:         }
 902:         switch (p->ltype) {
 903: 
 904:         case 'b':
 905:         case 'c':
 906:         case 'm':
 907:         case 'M':
 908:             printf("%3d,%3d",
 909:                 major((int)p->lsize), minor((int)p->lsize));
 910:             break;
 911: #ifdef  UCB_QUOTAS
 912:         case 'q':
 913:             printf("%4ld/%4ld", p->lqused, p->lqmax);
 914:             break;
 915: #endif
 916:         default:
 917:             printf("%7ld", p->lsize);
 918:         }
 919:         cp = ctime(&p->lmtime);
 920:         if(p->lmtime < year)
 921:             printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
 922:             printf(" %-12.12s ", cp+4);
 923:     }
 924: #ifndef UCB
 925:     if (Fflg) {
 926:         if (p->ltype == 'd')
 927:         strcat (fname, "[");
 928:         else if (p->lflags & 0111)
 929:         strcat (fname, "*");
 930:         else if (!nopad)
 931:         strcat (fname, " ");
 932:     }
 933: #endif
 934:     if (p->lflags & ISARG)
 935:         strncat (fname, p->ln.namep, 98);
 936:     else
 937:         strncat (fname, p->ln.lname, 14);
 938: #ifndef UCB
 939:     if (Fflg) {
 940:         if (p->ltype == 'd')
 941:         strcat (fname, "]");
 942:         else if (!nopad)
 943:         strcat (fname, " ");
 944:     }
 945: #else
 946:     if (Fflg) {
 947:         if (p->ltype == 'd')
 948:         strcat (fname, "/");
 949:         else if (p->lflags & 0111)
 950:         strcat (fname, "*");
 951:         else if (!nopad)
 952:         strcat (fname, " ");
 953:     }
 954: #endif
 955:     printf ("%s", fname);
 956:     free(ap);
 957: }
 958: 
 959: /* char printf_id[] = "@(#) printf.c:2.2 6/5/79";*/
 960: 
 961: /*
 962:  * This version of printf is compatible with the Version 7 C
 963:  * printf. The differences are only minor except that this
 964:  * printf assumes it is to print through pputchar. Version 7
 965:  * printf is more general (and is much larger) and includes
 966:  * provisions for floating point.
 967:  */
 968: 
 969: #define MAXOCT  11      /* Maximum octal digits in a long */
 970: #define MAXINT  32767       /* largest normal length positive integer */
 971: #define BIG 1000000000  /* largest power of 10 less than an unsigned long */
 972: #define MAXDIGS 10      /* number of digits in BIG */
 973: 
 974: static int width, sign, fill;
 975: 
 976: char *b_dconv();
 977: 
 978: printf(va_alist)
 979:     va_dcl
 980: {
 981:     va_list ap;
 982:     register char *fmt;
 983:     char fcode;
 984:     int prec;
 985:     int length,mask1,nbits,n;
 986:     long int mask2, num;
 987:     register char *bptr;
 988:     char *ptr;
 989:     char buf[134];
 990: 
 991:     va_start(ap);
 992:     fmt = va_arg(ap,char *);
 993:     for (;;) {
 994:         /* process format string first */
 995:         while ((fcode = *fmt++)!='%') {
 996:             /* ordinary (non-%) character */
 997:             if (fcode=='\0')
 998:                 return;
 999:             pputchar(fcode);
1000:         }
1001:         /* length modifier: -1 for h, 1 for l, 0 for none */
1002:         length = 0;
1003:         /* check for a leading - sign */
1004:         sign = 0;
1005:         if (*fmt == '-') {
1006:             sign++;
1007:             fmt++;
1008:         }
1009:         /* a '0' may follow the - sign */
1010:         /* this is the requested fill character */
1011:         fill = 1;
1012:         if (*fmt == '0') {
1013:             fill--;
1014:             fmt++;
1015:         }
1016: 
1017:         /* Now comes a digit string which may be a '*' */
1018:         if (*fmt == '*') {
1019:             width = va_arg(ap, int);
1020:             if (width < 0) {
1021:                 width = -width;
1022:                 sign = !sign;
1023:             }
1024:             fmt++;
1025:         }
1026:         else {
1027:             width = 0;
1028:             while (*fmt>='0' && *fmt<='9')
1029:                 width = width * 10 + (*fmt++ - '0');
1030:         }
1031: 
1032:         /* maybe a decimal point followed by more digits (or '*') */
1033:         if (*fmt=='.') {
1034:             if (*++fmt == '*') {
1035:                 prec = va_arg(ap, int);
1036:                 fmt++;
1037:             }
1038:             else {
1039:                 prec = 0;
1040:                 while (*fmt>='0' && *fmt<='9')
1041:                     prec = prec * 10 + (*fmt++ - '0');
1042:             }
1043:         }
1044:         else
1045:             prec = -1;
1046: 
1047:         /*
1048: 		 * At this point, "sign" is nonzero if there was
1049: 		 * a sign, "fill" is 0 if there was a leading
1050: 		 * zero and 1 otherwise, "width" and "prec"
1051: 		 * contain numbers corresponding to the digit
1052: 		 * strings before and after the decimal point,
1053: 		 * respectively, and "fmt" addresses the next
1054: 		 * character after the whole mess. If there was
1055: 		 * no decimal point, "prec" will be -1.
1056: 		 */
1057:         switch (*fmt) {
1058:             case 'L':
1059:             case 'l':
1060:                 length = 2;
1061:                 /* no break!! */
1062:             case 'h':
1063:             case 'H':
1064:                 length--;
1065:                 fmt++;
1066:                 break;
1067:         }
1068: 
1069:         /*
1070: 		 * At exit from the following switch, we will
1071: 		 * emit the characters starting at "bptr" and
1072: 		 * ending at "ptr"-1, unless fcode is '\0'.
1073: 		 */
1074:         switch (fcode = *fmt++) {
1075:             /* process characters and strings first */
1076:             case 'c':
1077:                 buf[0] = va_arg(ap, int);
1078:                 ptr = bptr = &buf[0];
1079:                 if (buf[0] != '\0')
1080:                     ptr++;
1081:                 break;
1082:             case 's':
1083:                 bptr = va_arg(ap,char *);
1084:                 if (bptr==0)
1085:                     bptr = "(null pointer)";
1086:                 if (prec < 0)
1087:                     prec = MAXINT;
1088:                 for (n=0; *bptr++ && n < prec; n++) ;
1089:                 ptr = --bptr;
1090:                 bptr -= n;
1091:                 break;
1092:             case 'O':
1093:                 length = 1;
1094:                 fcode = 'o';
1095:                 /* no break */
1096:             case 'o':
1097:             case 'X':
1098:             case 'x':
1099:                 if (length > 0)
1100:                     num = va_arg(ap,long);
1101:                 else
1102:                     num = (unsigned)va_arg(ap,int);
1103:                 if (fcode=='o') {
1104:                     mask1 = 0x7;
1105:                     mask2 = 0x1fffffffL;
1106:                     nbits = 3;
1107:                 }
1108:                 else {
1109:                     mask1 = 0xf;
1110:                     mask2 = 0x0fffffffL;
1111:                     nbits = 4;
1112:                 }
1113:                 n = (num!=0);
1114:                 bptr = buf + MAXOCT + 3;
1115:                 /* shift and mask for speed */
1116:                 do
1117:                     if (((int) num & mask1) < 10)
1118:                     *--bptr = ((int) num & mask1) + 060;
1119:                     else
1120:                     *--bptr = ((int) num & mask1) + 0127;
1121:                 while (num = (num >> nbits) & mask2);
1122: 
1123:                 if (fcode=='o') {
1124:                     if (n)
1125:                         *--bptr = '0';
1126:                 }
1127:                 else
1128:                     if (!sign && fill <= 0) {
1129:                         pputchar('0');
1130:                         pputchar(fcode);
1131:                         width -= 2;
1132:                     }
1133:                     else {
1134:                         *--bptr = fcode;
1135:                         *--bptr = '0';
1136:                     }
1137:                 ptr = buf + MAXOCT + 3;
1138:                 break;
1139:             case 'D':
1140:             case 'U':
1141:             case 'I':
1142:                 length = 1;
1143: 
1144:               fcode = fcode + 'a' - 'A';
1145:                 /* no break */
1146:             case 'd':
1147:             case 'i':
1148:             case 'u':
1149:                 if (length > 0)
1150:                     num = va_arg(ap,long);
1151:                 else {
1152:                     n = va_arg(ap,int);
1153:                     if (fcode=='u')
1154:                         num = (unsigned) n;
1155:                     else
1156:                         num = (long) n;
1157:                 }
1158:                 if (n = (fcode != 'u' && num < 0))
1159:                     num = -num;
1160:                 /* now convert to digits */
1161:                 bptr = b_dconv(num, buf);
1162:                 if (n)
1163:                     *--bptr = '-';
1164:                 if (fill == 0)
1165:                     fill = -1;
1166:                 ptr = buf + MAXDIGS + 1;
1167:                 break;
1168:             default:
1169:                 /* not a control character,
1170: 				 * print it.
1171: 				 */
1172:                 ptr = bptr = &fcode;
1173:                 ptr++;
1174:                 break;
1175:             }
1176:             if (fcode != '\0')
1177:                 b_emit(bptr,ptr);
1178:     }
1179:     va_end(ap);
1180: }
1181: 
1182: /* b_dconv converts the unsigned long integer "value" to
1183:  * printable decimal and places it in "buffer", right-justified.
1184:  * The value returned is the address of the first non-zero character,
1185:  * or the address of the last character if all are zero.
1186:  * The result is NOT null terminated, and is MAXDIGS characters long,
1187:  * starting at buffer[1] (to allow for insertion of a sign).
1188:  *
1189:  * This program assumes it is running on 2's complement machine
1190:  * with reasonable overflow treatment.
1191:  */
1192: char *
1193: b_dconv(value, buffer)
1194:     long value;
1195:     char *buffer;
1196: {
1197:     register char *bp;
1198:     register int svalue;
1199:     int n;
1200:     long lval;
1201: 
1202:     bp = buffer;
1203: 
1204:     /* zero is a special case */
1205:     if (value == 0) {
1206:         bp += MAXDIGS;
1207:         *bp = '0';
1208:         return(bp);
1209:     }
1210: 
1211:     /* develop the leading digit of the value in "n" */
1212:     n = 0;
1213:     while (value < 0) {
1214:         value -= BIG;   /* will eventually underflow */
1215:         n++;
1216:     }
1217:     while ((lval = value - BIG) >= 0) {
1218:         value = lval;
1219:         n++;
1220:     }
1221: 
1222:     /* stash it in buffer[1] to allow for a sign */
1223:     bp[1] = n + '0';
1224:     /*
1225: 	 * Now develop the rest of the digits. Since speed counts here,
1226: 	 * we do it in two loops. The first gets "value" down until it
1227: 	 * is no larger than MAXINT. The second one uses integer divides
1228: 	 * rather than long divides to speed it up.
1229: 	 */
1230:     bp += MAXDIGS + 1;
1231:     while (value > MAXINT) {
1232:         *--bp = (int)(value % 10) + '0';
1233:         value /= 10;
1234:     }
1235: 
1236:     /* cannot lose precision */
1237:     svalue = value;
1238:     while (svalue > 0) {
1239:         *--bp = (svalue % 10) + '0';
1240:         svalue /= 10;
1241:     }
1242: 
1243:     /* fill in intermediate zeroes if needed */
1244:     if (buffer[1] != '0') {
1245:         while (bp > buffer + 2)
1246:             *--bp = '0';
1247:         --bp;
1248:     }
1249:     return(bp);
1250: }
1251: 
1252: /*
1253:  * This program sends string "s" to pputchar. The character after
1254:  * the end of "s" is given by "send". This allows the size of the
1255:  * field to be computed; it is stored in "alen". "width" contains the
1256:  * user specified length. If width<alen, the width will be taken to
1257:  * be alen. "sign" is zero if the string is to be right-justified
1258:  * in the field, nonzero if it is to be left-justified. "fill" is
1259:  * 0 if the string is to be padded with '0', positive if it is to be
1260:  * padded with ' ', and negative if an initial '-' should appear before
1261:  * any padding in right-justification (to avoid printing "-3" as
1262:  * "000-3" where "-0003" was intended).
1263:  */
1264: b_emit(s, send)
1265:     register char *s;
1266:     char *send;
1267: {
1268:     char cfill;
1269:     register int alen;
1270:     int npad;
1271: 
1272:     alen = send - s;
1273:     if (alen > width)
1274:         width = alen;
1275:     cfill = fill>0? ' ': '0';
1276: 
1277:     /* we may want to print a leading '-' before anything */
1278:     if (*s == '-' && fill < 0) {
1279:         pputchar(*s++);
1280:         alen--;
1281:         width--;
1282:     }
1283:     npad = width - alen;
1284: 
1285:     /* emit any leading pad characters */
1286:     if (!sign)
1287:         while (--npad >= 0)
1288:             pputchar(cfill);
1289: 
1290:     /* emit the string itself */
1291:     while (--alen >= 0)
1292:         pputchar(*s++);
1293: 
1294:     /* emit trailing pad characters */
1295:     if (sign)
1296:         while (--npad >= 0)
1297:             pputchar(cfill);
1298: }
1299: 
1300: #ifndef UCB_PWHASH
1301: 
1302: struct nametable {
1303:     char    nt_name[NMAX+1];
1304:     unsigned short  nt_id;
1305: };
1306: struct nametable    unames[NUID];
1307: struct nametable    gnames[NGID];
1308: 
1309: 
1310: struct nametable *
1311: findslot (id, tbl, len)
1312: unsigned short  id;
1313: struct nametable    *tbl;
1314: int     len;
1315: {
1316:     register struct nametable   *nt, *nt_start;
1317: 
1318:     /*
1319: 	 * find the id or an empty slot.
1320: 	 * return NULL if neither found.
1321: 	 */
1322: 
1323:     nt = nt_start = tbl + (id % (len - 20));
1324:     while (nt->nt_name[0] && nt->nt_id != id)
1325:     {
1326:         if ((nt += 5) >= &tbl[len])
1327:             nt -= len;
1328:         if (nt == nt_start)
1329:             return((struct nametable *)NULL);
1330:     }
1331:     return(nt);
1332: }
1333: 
1334: char *
1335: getname (uid)
1336: unsigned short  uid;
1337: {
1338:     register struct passwd      *pw;
1339:     static int          init = 0;
1340:     struct passwd           *getpwent();
1341:     register struct nametable   *n;
1342: 
1343:     /*
1344: 	 * find uid in hashed table; add it if not found.
1345: 	 * return pointer to name.
1346: 	 */
1347: 
1348:     if ((n = findslot(uid, unames, NUID)) == NULL)
1349:         return((char *)NULL);
1350: 
1351:     if (n->nt_name[0])  /* occupied? */
1352:         return(n->nt_name);
1353: 
1354:     switch (init) {
1355:         case 0:
1356:             setpwent();
1357:             init = 1;
1358:             /* intentional fall-thru */
1359:         case 1:
1360:             while (pw = getpwent()) {
1361:                 if (pw->pw_uid < 0)
1362:                     continue;
1363:                 n = findslot(pw->pw_uid, unames, NUID);
1364:                 if (n == NULL) {
1365:                     endpwent();
1366:                     init = 2;
1367:                     return((char *)NULL);
1368:                 }
1369:                 if (n->nt_name[0])
1370:                     continue;   /* duplicate, not uid */
1371:                 strncpy(n->nt_name, pw->pw_name, NMAX);
1372:                 n->nt_id = pw->pw_uid;
1373:                 if (pw->pw_uid == uid)
1374:                     return (n->nt_name);
1375:             }
1376:             endpwent();
1377:             init = 2;
1378:             /* intentional fall-thru */
1379:         case 2:
1380:             return ((char *)NULL);
1381:     }
1382: }
1383: 
1384: char *
1385: getgroup (gid)
1386: unsigned short  gid;
1387: {
1388:     register struct group   *gr;
1389:     static int  init = 0;
1390:     struct group    *getgrent();
1391:     register struct nametable   *n;
1392: 
1393:     /*
1394: 	 * find gid in hashed table; add it if not found.
1395: 	 * return pointer to name.
1396: 	 */
1397: 
1398:     if ((n = findslot(gid, gnames, NGID)) == NULL)
1399:         return((char *)NULL);
1400: 
1401:     if (n->nt_name[0])  /* occupied? */
1402:         return(n->nt_name);
1403: 
1404:     switch (init) {
1405:         case 0:
1406:             setgrent();
1407:             init = 1;
1408:             /* intentional fall-thru */
1409:         case 1:
1410:             while (gr = getgrent()) {
1411:                 if (gr->gr_gid < 0)
1412:                     continue;
1413:                 n = findslot(gr->gr_gid, gnames, NGID);
1414:                 if (n == NULL) {
1415:                     endgrent();
1416:                     init = 2;
1417:                     return((char *)NULL);
1418:                 }
1419:                 if (n->nt_name[0])
1420:                     continue;   /* duplicate, not gid */
1421:                 strncpy(n->nt_name, gr->gr_name, NMAX);
1422:                 n->nt_id = gr->gr_gid;
1423:                 if (gr->gr_gid == gid)
1424:                     return (n->nt_name);
1425:             }
1426:             endgrent();
1427:             init = 2;
1428:             /* intentional fall-thru */
1429:         case 2:
1430:             return ((char *)NULL);
1431:     }
1432: }
1433: #endif

Defined functions

b_dconv defined in line 1192; used 2 times
b_emit defined in line 1264; used 1 times
column defined in line 545; used 1 times
compar defined in line 802; used 3 times
findslot defined in line 1310; used 4 times
getgroup defined in line 1384; used 3 times
getname defined in line 1334; used 2 times
gstat defined in line 704; used 3 times
main defined in line 136; never used
makename defined in line 637; used 3 times
nblock defined in line 591; used 4 times
newline defined in line 535; used 1 times
pdirectory defined in line 404; used 2 times
pem defined in line 457; used 1 times
pentry defined in line 832; used 4 times
pmode defined in line 614; used 1 times
pputchar defined in line 503; used 9 times
printf defined in line 978; used 56 times
readdir defined in line 662; used 1 times
select defined in line 623; used 1 times

Defined variables

Aflg defined in line 107; used 4 times
Cflg defined in line 107; used 13 times
Fflg defined in line 107; used 8 times
Rflg defined in line 107; used 4 times
across defined in line 107; used 3 times
aflg defined in line 106; used 3 times
bflg defined in line 106; used 3 times
cdfirst defined in line 102; used 5 times
cflg defined in line 106; used 2 times
colwidth defined in line 129; used 17 times
curdir defined in line 104; used 2 times
dfirst defined in line 101; used 8 times
dflg defined in line 106; used 3 times
dotp defined in line 119; used 1 times
dtemp defined in line 103; used 7 times
fflg defined in line 106; used 4 times
filewidth defined in line 130; used 9 times
fill defined in line 974; used 7 times
firstp defined in line 118; used 4 times
fixedwidth defined in line 131; used 8 times
flags defined in line 112; used 2 times
flist defined in line 116; used 3 times
gflg defined in line 106; used 3 times
gnames defined in line 1307; used 2 times
iflg defined in line 106; used 2 times
lastp defined in line 117; used 12 times
lflg defined in line 106; used 9 times
m defined in line 612; used 4 times
  • in line 619(4)
m1 defined in line 602; used 1 times
m2 defined in line 603; used 1 times
m3 defined in line 604; used 1 times
m4 defined in line 605; used 1 times
m5 defined in line 606; used 1 times
m6 defined in line 607; used 1 times
m7 defined in line 608; used 1 times
m8 defined in line 609; used 1 times
m9 defined in line 610; used 1 times
nflg defined in line 107; used 5 times
nopad defined in line 108; used 13 times
outcol defined in line 132; used 23 times
qflg defined in line 107; used 5 times
rflg defined in line 110; used 4 times
sflg defined in line 106; used 4 times
sign defined in line 974; used 7 times
statreq defined in line 114; used 6 times
tabflg defined in line 109; used 6 times
tblocks defined in line 113; used 3 times
tflg defined in line 106; used 3 times
uflg defined in line 106; used 2 times
unames defined in line 1306; used 2 times
utmp defined in line 71; used 1 times
  • in line 72
width defined in line 974; used 20 times
xtraent defined in line 115; used 6 times
year defined in line 111; used 2 times

Defined struct's

dchain defined in line 96; used 14 times
lbuf defined in line 77; used 44 times
nametable defined in line 1302; used 16 times

Defined macros

BIG defined in line 971; used 2 times
ISARG defined in line 128; used 7 times
MAXDIGS defined in line 972; used 3 times
MAXFILEWIDTH defined in line 74; used 2 times
MAXINT defined in line 970; used 2 times
MAXOCT defined in line 969; used 2 times
NFILES defined in line 62; used 3 times
NGID defined in line 68; used 4 times
NMAX defined in line 72; used 3 times
NUID defined in line 65; used 4 times
UCB defined in line 1; used 3 times
Last modified: 1983-05-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4074
Valid CSS Valid XHTML 1.0 Strict