1: /*	find	COMPILE:	cc -o find -s -O -i find.c -lS	*/
   2: #include <stdio.h>
   3: #include <sys/types.h>
   4: #include <sys/dir.h>
   5: #include <sys/stat.h>
   6: #define A_DAY   86400L /* a day full of seconds */
   7: #define EQ(x, y)    (strcmp(x, y)==0)
   8: 
   9: int Randlast;
  10: char    Pathname[200];
  11: 
  12: struct anode {
  13:     int (*F)();
  14:     struct anode *L, *R;
  15: } Node[100];
  16: int Nn;  /* number of nodes */
  17: char    *Fname;
  18: long    Now;
  19: int Argc,
  20:     Ai,
  21:     Pi;
  22: char    **Argv;
  23: /* cpio stuff */
  24: int Cpio;
  25: short   *Buf, *Dbuf, *Wp;
  26: int Bufsize = 5120;
  27: int Wct = 2560;
  28: 
  29: long    Newer;
  30: 
  31: struct stat Statb;
  32: 
  33: struct  anode   *exp(),
  34:         *e1(),
  35:         *e2(),
  36:         *e3(),
  37:         *mk();
  38: char    *nxtarg();
  39: char    Home[128];
  40: long    Blocks;
  41: char *rindex();
  42: char *sbrk();
  43: main(argc, argv) char *argv[];
  44: {
  45:     struct anode *exlist;
  46:     int paths;
  47:     register char *cp, *sp = 0;
  48:     FILE *pwd, *popen();
  49: 
  50:     time(&Now);
  51:     pwd = popen("pwd", "r");
  52:     fgets(Home, 128, pwd);
  53:     pclose(pwd);
  54:     Home[strlen(Home) - 1] = '\0';
  55:     Argc = argc; Argv = argv;
  56:     if(argc<3) {
  57: usage:      pr("Usage: find path-list predicate-list\n");
  58:         exit(1);
  59:     }
  60:     for(Ai = paths = 1; Ai < (argc-1); ++Ai, ++paths)
  61:         if(*Argv[Ai] == '-' || EQ(Argv[Ai], "(") || EQ(Argv[Ai], "!"))
  62:             break;
  63:     if(paths == 1) /* no path-list */
  64:         goto usage;
  65:     if(!(exlist = exp())) { /* parse and compile the arguments */
  66:         pr("find: parsing error\n");
  67:         exit(1);
  68:     }
  69:     if(Ai<argc) {
  70:         pr("find: missing conjunction\n");
  71:         exit(1);
  72:     }
  73:     for(Pi = 1; Pi < paths; ++Pi) {
  74:         sp = 0;
  75:         chdir(Home);
  76:         strcpy(Pathname, Argv[Pi]);
  77:         if(cp = rindex(Pathname, '/')) {
  78:             sp = cp + 1;
  79:             *cp = '\0';
  80:             if(chdir(*Pathname? Pathname: "/") == -1) {
  81:                 pr("find: bad starting directory\n");
  82:                 exit(2);
  83:             }
  84:             *cp = '/';
  85:         }
  86:         Fname = sp? sp: Pathname;
  87:         descend(Pathname, Fname, exlist); /* to find files that match  */
  88:     }
  89:     if(Cpio) {
  90:         strcpy(Pathname, "TRAILER!!!");
  91:         Statb.st_size = 0;
  92:         cpio();
  93:     }
  94:     exit(0);
  95: }
  96: 
  97: /* compile time functions:  priority is  exp()<e1()<e2()<e3()  */
  98: 
  99: struct anode *exp() { /* parse ALTERNATION (-o)  */
 100:     int or();
 101:     register struct anode * p1;
 102: 
 103:     p1 = e1() /* get left operand */ ;
 104:     if(EQ(nxtarg(), "-o")) {
 105:         Randlast--;
 106:         return(mk(or, p1, exp()));
 107:     }
 108:     else if(Ai <= Argc) --Ai;
 109:     return(p1);
 110: }
 111: struct anode *e1() { /* parse CONCATENATION (formerly -a) */
 112:     int and();
 113:     register struct anode * p1;
 114:     register char *a;
 115: 
 116:     p1 = e2();
 117:     a = nxtarg();
 118:     if(EQ(a, "-a")) {
 119: And:
 120:         Randlast--;
 121:         return(mk(and, p1, e1()));
 122:     } else if(EQ(a, "(") || EQ(a, "!") || (*a=='-' && !EQ(a, "-o"))) {
 123:         --Ai;
 124:         goto And;
 125:     } else if(Ai <= Argc) --Ai;
 126:     return(p1);
 127: }
 128: struct anode *e2() { /* parse NOT (!) */
 129:     int not();
 130: 
 131:     if(Randlast) {
 132:         pr("find: operand follows operand\n");
 133:         exit(1);
 134:     }
 135:     Randlast++;
 136:     if(EQ(nxtarg(), "!"))
 137:         return(mk(not, e3(), (struct anode *)0));
 138:     else if(Ai <= Argc) --Ai;
 139:     return(e3());
 140: }
 141: struct anode *e3() { /* parse parens and predicates */
 142:     int exeq(), ok(), glob(),  mtime(), atime(), ctime(), user(),
 143:         group(), size(), perm(), links(), print(),
 144:         type(), ino(), cpio(), newer();
 145:     struct anode *p1;
 146:     int i;
 147:     register char *a, *b, s;
 148: 
 149:     a = nxtarg();
 150:     if(EQ(a, "(")) {
 151:         Randlast--;
 152:         p1 = exp();
 153:         a = nxtarg();
 154:         if(!EQ(a, ")")) goto err;
 155:         return(p1);
 156:     }
 157:     else if(EQ(a, "-print")) {
 158:         return(mk(print, (struct anode *)0, (struct anode *)0));
 159:     }
 160:     b = nxtarg();
 161:     s = *b;
 162:     if(s=='+') b++;
 163:     if(EQ(a, "-name"))
 164:         return(mk(glob, (struct anode *)b, (struct anode *)0));
 165:     else if(EQ(a, "-mtime"))
 166:         return(mk(mtime, (struct anode *)atoi(b), (struct anode *)s));
 167:     else if(EQ(a, "-atime"))
 168:         return(mk(atime, (struct anode *)atoi(b), (struct anode *)s));
 169:     else if(EQ(a, "-ctime"))
 170:         return(mk(ctime, (struct anode *)atoi(b), (struct anode *)s));
 171:     else if(EQ(a, "-user")) {
 172:         if((i=getunum("/etc/passwd", b)) == -1) {
 173:             if(gmatch(b, "[0-9][0-9][0-9]*")
 174:             || gmatch(b, "[0-9][0-9]")
 175:             || gmatch(b, "[0-9]"))
 176:                 return mk(user, (struct anode *)atoi(b), (struct anode *)s);
 177:             pr("find: cannot find -user name\n");
 178:             exit(1);
 179:         }
 180:         return(mk(user, (struct anode *)i, (struct anode *)s));
 181:     }
 182:     else if(EQ(a, "-inum"))
 183:         return(mk(ino, (struct anode *)atoi(b), (struct anode *)s));
 184:     else if(EQ(a, "-group")) {
 185:         if((i=getunum("/etc/group", b)) == -1) {
 186:             if(gmatch(b, "[0-9][0-9][0-9]*")
 187:             || gmatch(b, "[0-9][0-9]")
 188:             || gmatch(b, "[0-9]"))
 189:                 return mk(group, (struct anode *)atoi(b), (struct anode *)s);
 190:             pr("find: cannot find -group name\n");
 191:             exit(1);
 192:         }
 193:         return(mk(group, (struct anode *)i, (struct anode *)s));
 194:     } else if(EQ(a, "-size"))
 195:         return(mk(size, (struct anode *)atoi(b), (struct anode *)s));
 196:     else if(EQ(a, "-links"))
 197:         return(mk(links, (struct anode *)atoi(b), (struct anode *)s));
 198:     else if(EQ(a, "-perm")) {
 199:         for(i=0; *b ; ++b) {
 200:             if(*b=='-') continue;
 201:             i <<= 3;
 202:             i = i + (*b - '0');
 203:         }
 204:         return(mk(perm, (struct anode *)i, (struct anode *)s));
 205:     }
 206:     else if(EQ(a, "-type")) {
 207:         i = s=='d' ? S_IFDIR :
 208:             s=='b' ? S_IFBLK :
 209:             s=='c' ? S_IFCHR :
 210:             s=='f' ? 0100000 :
 211:             0;
 212:         return(mk(type, (struct anode *)i, (struct anode *)0));
 213:     }
 214:     else if (EQ(a, "-exec")) {
 215:         i = Ai - 1;
 216:         while(!EQ(nxtarg(), ";"));
 217:         return(mk(exeq, (struct anode *)i, (struct anode *)0));
 218:     }
 219:     else if (EQ(a, "-ok")) {
 220:         i = Ai - 1;
 221:         while(!EQ(nxtarg(), ";"));
 222:         return(mk(ok, (struct anode *)i, (struct anode *)0));
 223:     }
 224:     else if(EQ(a, "-cpio")) {
 225:         if((Cpio = creat(b, 0666)) < 0) {
 226:             pr("find: cannot create "), pr(s), pr("\n");
 227:             exit(1);
 228:         }
 229:         Buf = (short *)sbrk(512);
 230:         Wp = Dbuf = (short *)sbrk(5120);
 231:         return(mk(cpio, (struct anode *)0, (struct anode *)0));
 232:     }
 233:     else if(EQ(a, "-newer")) {
 234:         if(stat(b, &Statb) < 0) {
 235:             pr("find: cannot access "), pr(b), pr("\n");
 236:             exit(1);
 237:         }
 238:         Newer = Statb.st_mtime;
 239:         return mk(newer, (struct anode *)0, (struct anode *)0);
 240:     }
 241: err:    pr("find: bad option "), pr(a), pr("\n");
 242:     exit(1);
 243: }
 244: struct anode *mk(f, l, r)
 245: int (*f)();
 246: struct anode *l, *r;
 247: {
 248:     Node[Nn].F = f;
 249:     Node[Nn].L = l;
 250:     Node[Nn].R = r;
 251:     return(&(Node[Nn++]));
 252: }
 253: 
 254: char *nxtarg() { /* get next arg from command line */
 255:     static strikes = 0;
 256: 
 257:     if(strikes==3) {
 258:         pr("find: incomplete statement\n");
 259:         exit(1);
 260:     }
 261:     if(Ai>=Argc) {
 262:         strikes++;
 263:         Ai = Argc + 1;
 264:         return("");
 265:     }
 266:     return(Argv[Ai++]);
 267: }
 268: 
 269: /* execution time functions */
 270: and(p)
 271: register struct anode *p;
 272: {
 273:     return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0);
 274: }
 275: or(p)
 276: register struct anode *p;
 277: {
 278:      return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0);
 279: }
 280: not(p)
 281: register struct anode *p;
 282: {
 283:     return( !((*p->L->F)(p->L)));
 284: }
 285: glob(p)
 286: register struct { int f; char *pat; } *p;
 287: {
 288:     return(gmatch(Fname, p->pat));
 289: }
 290: print()
 291: {
 292:     puts(Pathname);
 293:     return(1);
 294: }
 295: mtime(p)
 296: register struct { int f, t, s; } *p;
 297: {
 298:     return(scomp((int)((Now - Statb.st_mtime) / A_DAY), p->t, p->s));
 299: }
 300: atime(p)
 301: register struct { int f, t, s; } *p;
 302: {
 303:     return(scomp((int)((Now - Statb.st_atime) / A_DAY), p->t, p->s));
 304: }
 305: ctime(p)
 306: register struct { int f, t, s; } *p;
 307: {
 308:     return(scomp((int)((Now - Statb.st_ctime) / A_DAY), p->t, p->s));
 309: }
 310: user(p)
 311: register struct { int f, u, s; } *p;
 312: {
 313:     return(scomp(Statb.st_uid, p->u, p->s));
 314: }
 315: ino(p)
 316: register struct { int f, u, s; } *p;
 317: {
 318:     return(scomp((int)Statb.st_ino, p->u, p->s));
 319: }
 320: group(p)
 321: register struct { int f, u; } *p;
 322: {
 323:     return(p->u == Statb.st_gid);
 324: }
 325: links(p)
 326: register struct { int f, link, s; } *p;
 327: {
 328:     return(scomp(Statb.st_nlink, p->link, p->s));
 329: }
 330: size(p)
 331: register struct { int f, sz, s; } *p;
 332: {
 333:     return(scomp((int)((Statb.st_size+511)>>9), p->sz, p->s));
 334: }
 335: perm(p)
 336: register struct { int f, per, s; } *p;
 337: {
 338:     register i;
 339:     i = (p->s=='-') ? p->per : 07777; /* '-' means only arg bits */
 340:     return((Statb.st_mode & i & 07777) == p->per);
 341: }
 342: type(p)
 343: register struct { int f, per, s; } *p;
 344: {
 345:     return((Statb.st_mode&S_IFMT)==p->per);
 346: }
 347: exeq(p)
 348: register struct { int f, com; } *p;
 349: {
 350:     fflush(stdout); /* to flush possible `-print' */
 351:     return(doex(p->com));
 352: }
 353: ok(p)
 354: struct { int f, com; } *p;
 355: {
 356:     int c;  int yes;
 357:     yes = 0;
 358:     fflush(stdout); /* to flush possible `-print' */
 359:     pr("< "), pr(Argv[p->com]), pr(" ... "), pr(Pathname), pr(" >?   ");
 360:     fflush(stderr);
 361:     if((c=getchar())=='y') yes = 1;
 362:     while(c!='\n')
 363:         if(c==EOF)
 364:             exit(2);
 365:         else
 366:             c = getchar();
 367:     if(yes) return(doex(p->com));
 368:     return(0);
 369: }
 370: 
 371: #define MKSHORT(v, lv) {U.l=1L;if(U.c[0]) U.l=lv, v[0]=U.s[1], v[1]=U.s[0]; else U.l=lv, v[0]=U.s[0], v[1]=U.s[1];}
 372: union { long l; short s[2]; char c[4]; } U;
 373: long mklong(v)
 374: short v[];
 375: {
 376:     U.l = 1;
 377:     if(U.c[0] /* VAX */)
 378:         U.s[0] = v[1], U.s[1] = v[0];
 379:     else
 380:         U.s[0] = v[0], U.s[1] = v[1];
 381:     return U.l;
 382: }
 383: cpio()
 384: {
 385: #define MAGIC 070707
 386:     struct header {
 387:         short   h_magic,
 388:             h_dev,
 389:             h_ino,
 390:             h_mode,
 391:             h_uid,
 392:             h_gid,
 393:             h_nlink,
 394:             h_rdev;
 395:         short   h_mtime[2];
 396:         short   h_namesize;
 397:         short   h_filesize[2];
 398:         char    h_name[256];
 399:     } hdr;
 400:     register ifile, ct;
 401:     static long fsz;
 402:     register i;
 403: 
 404:     hdr.h_magic = MAGIC;
 405:     strcpy(hdr.h_name, !strncmp(Pathname, "./", 2)? Pathname+2: Pathname);
 406:     hdr.h_namesize = strlen(hdr.h_name) + 1;
 407:     hdr.h_uid = Statb.st_uid;
 408:     hdr.h_gid = Statb.st_gid;
 409:     hdr.h_dev = Statb.st_dev;
 410:     hdr.h_ino = Statb.st_ino;
 411:     hdr.h_mode = Statb.st_mode;
 412:     MKSHORT(hdr.h_mtime, Statb.st_mtime);
 413:     hdr.h_nlink = Statb.st_nlink;
 414:     fsz = hdr.h_mode & S_IFREG? Statb.st_size: 0L;
 415:     MKSHORT(hdr.h_filesize, fsz);
 416:     hdr.h_rdev = Statb.st_rdev;
 417:     if(EQ(hdr.h_name, "TRAILER!!!")) {
 418:         bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
 419:         for(i = 0; i < 10; ++i)
 420:             bwrite(Buf, 512);
 421:         return;
 422:     }
 423:     if(!mklong(hdr.h_filesize)) {
 424:         bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
 425:         return;
 426:     }
 427:     if((ifile = open(Fname, 0)) < 0) {
 428: cerror:
 429:         pr("find: cannot copy "), pr(hdr.h_name), pr("\n");
 430:         return;
 431:     }
 432:     bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
 433:     for(fsz = mklong(hdr.h_filesize); fsz > 0; fsz -= 512) {
 434:         ct = fsz>512? 512: fsz;
 435:         if(read(ifile, (char *)Buf, ct) < 0)
 436:             goto cerror;
 437:         bwrite(Buf, ct);
 438:     }
 439:     close(ifile);
 440:     return;
 441: }
 442: newer()
 443: {
 444:     return Statb.st_mtime > Newer;
 445: }
 446: 
 447: /* support functions */
 448: scomp(a, b, s) /* funny signed compare */
 449: register a, b;
 450: register char s;
 451: {
 452:     if(s == '+')
 453:         return(a > b);
 454:     if(s == '-')
 455:         return(a < (b * -1));
 456:     return(a == b);
 457: }
 458: 
 459: doex(com)
 460: {
 461:     register np;
 462:     register char *na;
 463:     static char *nargv[50];
 464:     static ccode;
 465: 
 466:     ccode = np = 0;
 467:     while (na=Argv[com++]) {
 468:         if(strcmp(na, ";")==0) break;
 469:         if(strcmp(na, "{}")==0) nargv[np++] = Pathname;
 470:         else nargv[np++] = na;
 471:     }
 472:     nargv[np] = 0;
 473:     if (np==0) return(9);
 474:     if(fork()) /*parent*/ wait(&ccode);
 475:     else { /*child*/
 476:         chdir(Home);
 477:         execvp(nargv[0], nargv, np);
 478:         exit(1);
 479:     }
 480:     return(ccode ? 0:1);
 481: }
 482: 
 483: getunum(f, s) char *f, *s; { /* find user/group name and return number */
 484:     register i;
 485:     register char *sp;
 486:     register c;
 487:     char str[20];
 488:     FILE *pin;
 489: 
 490:     i = -1;
 491:     pin = fopen(f, "r");
 492:     c = '\n'; /* prime with a CR */
 493:     do {
 494:         if(c=='\n') {
 495:             sp = str;
 496:             while((c = *sp++ = getc(pin)) != ':')
 497:                 if(c == EOF) goto RET;
 498:             *--sp = '\0';
 499:             if(EQ(str, s)) {
 500:                 while((c=getc(pin)) != ':')
 501:                     if(c == EOF) goto RET;
 502:                 sp = str;
 503:                 while((*sp = getc(pin)) != ':') sp++;
 504:                 *sp = '\0';
 505:                 i = atoi(str);
 506:                 goto RET;
 507:             }
 508:         }
 509:     } while((c = getc(pin)) != EOF);
 510:  RET:
 511:     fclose(pin);
 512:     return(i);
 513: }
 514: 
 515: descend(name, fname, exlist)
 516: struct anode *exlist;
 517: char *name, *fname;
 518: {
 519:     int dir = 0, /* open directory */
 520:         offset,
 521:         dsize,
 522:         entries,
 523:         dirsize;
 524:     struct direct dentry[32];
 525:     register struct direct  *dp;
 526:     register char *c1, *c2;
 527:     int i;
 528:     int rv = 0;
 529:     char *endofname;
 530: 
 531:     if(stat(fname, &Statb)<0) {
 532:         pr("find: bad status-- "), pr(name), pr("\n");
 533:         return(0);
 534:     }
 535:     (*exlist->F)(exlist);
 536:     if((Statb.st_mode&S_IFMT)!=S_IFDIR)
 537:         return(1);
 538: 
 539:     for(c1 = name; *c1; ++c1);
 540:     if(*(c1-1) == '/')
 541:         --c1;
 542:     endofname = c1;
 543:     dirsize = Statb.st_size;
 544: 
 545:     if(chdir(fname) == -1)
 546:         return(0);
 547:     for(offset=0 ; offset < dirsize ; offset += 512) { /* each block */
 548:         dsize = 512<(dirsize-offset)? 512: (dirsize-offset);
 549:         if(!dir) {
 550:             if((dir=open(".", 0))<0) {
 551:                 pr("find: cannot open "), pr(name), pr("\n");
 552:                 rv = 0;
 553:                 goto ret;
 554:             }
 555:             if(offset) lseek(dir, (long)offset, 0);
 556:             if(read(dir, (char *)dentry, dsize)<0) {
 557:                 pr("find: cannot read "), pr(name), pr("\n");
 558:                 rv = 0;
 559:                 goto ret;
 560:             }
 561:             if(dir > 10) {
 562:                 close(dir);
 563:                 dir = 0;
 564:             }
 565:         } else
 566:             if(read(dir, (char *)dentry, dsize)<0) {
 567:                 pr("find: cannot read "), pr(name), pr("\n");
 568:                 rv = 0;
 569:                 goto ret;
 570:             }
 571:         for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) { /* each directory entry */
 572:             if(dp->d_ino==0
 573:             || (dp->d_name[0]=='.' && dp->d_name[1]=='\0')
 574:             || (dp->d_name[0]=='.' && dp->d_name[1]=='.' && dp->d_name[2]=='\0'))
 575:                 continue;
 576:             c1 = endofname;
 577:             *c1++ = '/';
 578:             c2 = dp->d_name;
 579:             for(i=0; i<14; ++i)
 580:                 if(*c2)
 581:                     *c1++ = *c2++;
 582:                 else
 583:                     break;
 584:             *c1 = '\0';
 585:             if(c1 == endofname) { /* ?? */
 586:                 rv = 0;
 587:                 goto ret;
 588:             }
 589:             Fname = endofname+1;
 590:             if(!descend(name, Fname, exlist)) {
 591:                 *endofname = '\0';
 592:                 chdir(Home);
 593:                 if(chdir(Pathname) == -1) {
 594:                     pr("find: bad directory tree\n");
 595:                     exit(1);
 596:                 }
 597:             }
 598:         }
 599:     }
 600:     rv = 1;
 601: ret:
 602:     if(dir)
 603:         close(dir);
 604:     if(chdir("..") == -1) {
 605:         *endofname = '\0';
 606:         pr("find: bad directory "), pr(name), pr("\n");
 607:         rv = 1;
 608:     }
 609:     return(rv);
 610: }
 611: 
 612: gmatch(s, p) /* string match as in glob */
 613: register char *s, *p;
 614: {
 615:     if (*s=='.' && *p!='.') return(0);
 616:     return amatch(s, p);
 617: }
 618: 
 619: amatch(s, p)
 620: register char *s, *p;
 621: {
 622:     register cc;
 623:     int scc, k;
 624:     int c, lc;
 625: 
 626:     scc = *s;
 627:     lc = 077777;
 628:     switch (c = *p) {
 629: 
 630:     case '[':
 631:         k = 0;
 632:         while (cc = *++p) {
 633:             switch (cc) {
 634: 
 635:             case ']':
 636:                 if (k)
 637:                     return(amatch(++s, ++p));
 638:                 else
 639:                     return(0);
 640: 
 641:             case '-':
 642:                 k |= lc <= scc & scc <= (cc=p[1]);
 643:             }
 644:             if (scc==(lc=cc)) k++;
 645:         }
 646:         return(0);
 647: 
 648:     case '?':
 649:     caseq:
 650:         if(scc) return(amatch(++s, ++p));
 651:         return(0);
 652:     case '*':
 653:         return(umatch(s, ++p));
 654:     case 0:
 655:         return(!scc);
 656:     }
 657:     if (c==scc) goto caseq;
 658:     return(0);
 659: }
 660: 
 661: umatch(s, p)
 662: register char *s, *p;
 663: {
 664:     if(*p==0) return(1);
 665:     while(*s)
 666:         if (amatch(s++, p)) return(1);
 667:     return(0);
 668: }
 669: 
 670: bwrite(rp, c)
 671: register short *rp;
 672: register c;
 673: {
 674:     register short *wp = Wp;
 675: 
 676:     c = (c+1) >> 1;
 677:     while(c--) {
 678:         if(!Wct) {
 679: again:
 680:             if(write(Cpio, (char *)Dbuf, Bufsize)<0) {
 681:                 Cpio = chgreel(1, Cpio);
 682:                 goto again;
 683:             }
 684:             Wct = Bufsize >> 1;
 685:             wp = Dbuf;
 686:             ++Blocks;
 687:         }
 688:         *wp++ = *rp++;
 689:         --Wct;
 690:     }
 691:     Wp = wp;
 692: }
 693: chgreel(x, fl)
 694: {
 695:     register f;
 696:     char str[22];
 697:     FILE *devtty;
 698:     struct stat statb;
 699: 
 700:     pr("find: can't "), pr(x? "write output": "read input"), pr("\n");
 701:     fstat(fl, &statb);
 702:     if((statb.st_mode&S_IFMT) != S_IFCHR)
 703:         exit(1);
 704: again:
 705:     pr("If you want to go on, type device/file name when ready\n");
 706:     devtty = fopen("/dev/tty", "r");
 707:     fgets(str, 20, devtty);
 708:     str[strlen(str) - 1] = '\0';
 709:     if(!*str)
 710:         exit(1);
 711:     close(fl);
 712:     if((f = open(str, x? 1: 0)) < 0) {
 713:         pr("That didn't work");
 714:         fclose(devtty);
 715:         goto again;
 716:     }
 717:     return f;
 718: }
 719: pr(s)
 720: char *s;
 721: {
 722:     fputs(s, stderr);
 723: }

Defined functions

amatch defined in line 619; used 4 times
and defined in line 270; used 2 times
atime defined in line 300; used 2 times
bwrite defined in line 670; used 5 times
chgreel defined in line 693; used 1 times
cpio defined in line 383; used 3 times
ctime defined in line 305; used 2 times
descend defined in line 515; used 2 times
doex defined in line 459; used 2 times
e1 defined in line 111; used 3 times
e2 defined in line 128; used 2 times
e3 defined in line 141; used 3 times
exeq defined in line 347; used 2 times
exp defined in line 99; used 4 times
getunum defined in line 483; used 2 times
glob defined in line 285; used 2 times
gmatch defined in line 612; used 7 times
group defined in line 320; used 3 times
ino defined in line 315; used 2 times
links defined in line 325; used 2 times
main defined in line 43; never used
mk defined in line 244; used 22 times
mklong defined in line 373; used 2 times
mtime defined in line 295; used 2 times
newer defined in line 442; used 2 times
not defined in line 280; used 2 times
nxtarg defined in line 254; used 9 times
ok defined in line 353; used 2 times
or defined in line 275; used 2 times
perm defined in line 335; used 2 times
pr defined in line 719; used 46 times
print defined in line 290; used 2 times
scomp defined in line 448; used 7 times
size defined in line 330; used 2 times
type defined in line 342; used 2 times
umatch defined in line 661; used 1 times
user defined in line 310; used 3 times

Defined variables

Ai defined in line 20; used 19 times
Argc defined in line 19; used 6 times
Argv defined in line 22; used 8 times
Blocks defined in line 40; used 1 times
Buf defined in line 25; used 4 times
Bufsize defined in line 26; used 2 times
Cpio defined in line 24; used 5 times
Dbuf defined in line 25; used 3 times
Fname defined in line 17; used 6 times
Home defined in line 39; used 6 times
Newer defined in line 29; used 2 times
Nn defined in line 16; used 4 times
Node defined in line 15; used 4 times
Now defined in line 18; used 4 times
Pathname defined in line 10; used 14 times
Pi defined in line 21; used 4 times
Randlast defined in line 9; used 5 times
Statb defined in line 31; used 26 times
Wct defined in line 27; used 3 times
Wp defined in line 25; used 3 times

Defined struct's

anode defined in line 12; used 106 times
header defined in line 386; never used

Defined macros

A_DAY defined in line 6; used 3 times
EQ defined in line 7; used 30 times
MAGIC defined in line 385; used 1 times
MKSHORT defined in line 371; used 2 times
Last modified: 1979-05-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2379
Valid CSS Valid XHTML 1.0 Strict