|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)find.c 4.20 (Berkeley) 9/28/87"; ! 3: #endif ! 4: ! 5: #include <stdio.h> ! 6: #include <sys/param.h> ! 7: #include <sys/dir.h> ! 8: #include <sys/stat.h> ! 9: ! 10: #define A_DAY 86400L /* a day full of seconds */ ! 11: #define EQ(x, y) (strcmp(x, y)==0) ! 12: ! 13: int Randlast; ! 14: char Pathname[MAXPATHLEN+1]; ! 15: ! 16: #define MAXNODES 100 ! 17: ! 18: struct anode { ! 19: int (*F)(); ! 20: struct anode *L, *R; ! 21: } Node[MAXNODES]; ! 22: int Nn; /* number of nodes */ ! 23: char *Fname; ! 24: long Now; ! 25: int Argc, ! 26: Ai, ! 27: Pi; ! 28: char **Argv; ! 29: /* cpio stuff */ ! 30: int Cpio; ! 31: short *Buf, *Dbuf, *Wp; ! 32: int Bufsize = 5120; ! 33: int Wct = 2560; ! 34: ! 35: long Newer; ! 36: ! 37: int Xdev = 1; /* true if SHOULD cross devices (file systems) */ ! 38: int follow; /* true if SHOULD descend symlinked directories */ ! 39: struct stat Devstat; /* stats of each argument path's file system */ ! 40: ! 41: struct stat Statb; ! 42: ! 43: struct anode *exp(), ! 44: *e1(), ! 45: *e2(), ! 46: *e3(), ! 47: *mk(); ! 48: char *nxtarg(); ! 49: char Home[MAXPATHLEN + 1]; ! 50: long Blocks; ! 51: char *rindex(); ! 52: char *sbrk(); ! 53: ! 54: /* ! 55: * SEE ALSO: updatedb, bigram.c, code.c ! 56: * Usenix ;login:, February/March, 1983, p. 8. ! 57: * ! 58: * REVISIONS: James A. Woods, Informatics General Corporation, ! 59: * NASA Ames Research Center, 6/81. ! 60: * ! 61: * The second form searches a pre-computed filelist ! 62: * (constructed nightly by /usr/lib/crontab) which is ! 63: * compressed by updatedb (v.i.z.) The effect of ! 64: * find <name> ! 65: * is similar to ! 66: * find / +0 -name "*<name>*" -print ! 67: * but much faster. ! 68: * ! 69: * 8/82 faster yet + incorporation of bigram coding -- jaw ! 70: * ! 71: * 1/83 incorporate glob-style matching -- jaw ! 72: */ ! 73: #define AMES 1 ! 74: ! 75: main(argc, argv) ! 76: int argc; ! 77: char *argv[]; ! 78: { ! 79: struct anode *exlist; ! 80: int paths; ! 81: register char *cp, *sp = 0; ! 82: #ifdef SUID_PWD ! 83: FILE *pwd, *popen(); ! 84: #endif ! 85: ! 86: #ifdef AMES ! 87: if (argc < 2) { ! 88: fprintf(stderr, ! 89: "Usage: find name, or find path-list predicate-list\n"); ! 90: exit(1); ! 91: } ! 92: if (argc == 2) { ! 93: fastfind(argv[1]); ! 94: exit(0); ! 95: } ! 96: #endif ! 97: time(&Now); ! 98: #ifdef SUID_PWD ! 99: pwd = popen("pwd", "r"); ! 100: fgets(Home, sizeof Home, pwd); ! 101: pclose(pwd); ! 102: Home[strlen(Home) - 1] = '\0'; ! 103: #else ! 104: if (getwd(Home) == NULL) { ! 105: fprintf(stderr, "find: Can't get current working directory\n"); ! 106: exit(1); ! 107: } ! 108: #endif ! 109: Argc = argc; Argv = argv; ! 110: if(argc<3) { ! 111: usage: fprintf(stderr, "Usage: find path-list predicate-list\n"); ! 112: exit(1); ! 113: } ! 114: for(Ai = paths = 1; Ai < (argc-1); ++Ai, ++paths) ! 115: if(*Argv[Ai] == '-' || EQ(Argv[Ai], "(") || EQ(Argv[Ai], "!")) ! 116: break; ! 117: if(paths == 1) /* no path-list */ ! 118: goto usage; ! 119: if(!(exlist = exp())) { /* parse and compile the arguments */ ! 120: fprintf(stderr, "find: parsing error\n"); ! 121: exit(1); ! 122: } ! 123: if(Ai<argc) { ! 124: fprintf(stderr, "find: missing conjunction\n"); ! 125: exit(1); ! 126: } ! 127: for(Pi = 1; Pi < paths; ++Pi) { ! 128: sp = 0; ! 129: chdir(Home); ! 130: strcpy(Pathname, Argv[Pi]); ! 131: if(cp = rindex(Pathname, '/')) { ! 132: sp = cp + 1; ! 133: *cp = '\0'; ! 134: if(chdir(*Pathname? Pathname: "/") == -1) { ! 135: fprintf(stderr, "find: bad starting directory\n"); ! 136: exit(2); ! 137: } ! 138: *cp = '/'; ! 139: } ! 140: Fname = sp? sp: Pathname; ! 141: if (!Xdev) ! 142: stat(Pathname, &Devstat); ! 143: descend(Pathname, Fname, exlist); /* to find files that match */ ! 144: } ! 145: if(Cpio) { ! 146: strcpy(Pathname, "TRAILER!!!"); ! 147: Statb.st_size = 0; ! 148: cpio(); ! 149: printf("%D blocks\n", Blocks*10); ! 150: } ! 151: exit(0); ! 152: } ! 153: ! 154: /* compile time functions: priority is exp()<e1()<e2()<e3() */ ! 155: ! 156: struct anode *exp() { /* parse ALTERNATION (-o) */ ! 157: int or(); ! 158: register struct anode * p1; ! 159: ! 160: p1 = e1() /* get left operand */ ; ! 161: if(EQ(nxtarg(), "-o")) { ! 162: Randlast--; ! 163: return(mk(or, p1, exp())); ! 164: } ! 165: else if(Ai <= Argc) --Ai; ! 166: return(p1); ! 167: } ! 168: struct anode *e1() { /* parse CONCATENATION (formerly -a) */ ! 169: int and(); ! 170: register struct anode * p1; ! 171: register char *a; ! 172: ! 173: p1 = e2(); ! 174: a = nxtarg(); ! 175: if(EQ(a, "-a")) { ! 176: And: ! 177: Randlast--; ! 178: return(mk(and, p1, e1())); ! 179: } else if(EQ(a, "(") || EQ(a, "!") || (*a=='-' && !EQ(a, "-o"))) { ! 180: --Ai; ! 181: goto And; ! 182: } else if(Ai <= Argc) --Ai; ! 183: return(p1); ! 184: } ! 185: struct anode *e2() { /* parse NOT (!) */ ! 186: int not(); ! 187: ! 188: if(Randlast) { ! 189: fprintf(stderr, "find: operand follows operand\n"); ! 190: exit(1); ! 191: } ! 192: Randlast++; ! 193: if(EQ(nxtarg(), "!")) ! 194: return(mk(not, e3(), (struct anode *)0)); ! 195: else if(Ai <= Argc) --Ai; ! 196: return(e3()); ! 197: } ! 198: struct anode *e3() { /* parse parens and predicates */ ! 199: int exeq(), ok(), glob(), mtime(), atime(), user(), ! 200: group(), size(), perm(), links(), print(), ! 201: type(), ino(), cpio(), newer(), ! 202: nouser(), nogroup(), ls(), dummy(); ! 203: struct anode *p1; ! 204: int i; ! 205: register char *a, *b; ! 206: register int s; ! 207: ! 208: a = nxtarg(); ! 209: if(EQ(a, "(")) { ! 210: Randlast--; ! 211: p1 = exp(); ! 212: a = nxtarg(); ! 213: if(!EQ(a, ")")) goto err; ! 214: return(p1); ! 215: } ! 216: else if(EQ(a, "-print")) { ! 217: return(mk(print, (struct anode *)0, (struct anode *)0)); ! 218: } ! 219: else if (EQ(a, "-nouser")) { ! 220: return (mk(nouser, (struct anode *)0, (struct anode *)0)); ! 221: } ! 222: else if (EQ(a, "-nogroup")) { ! 223: return (mk(nogroup, (struct anode *)0, (struct anode *)0)); ! 224: } ! 225: else if (EQ(a, "-ls")) { ! 226: return (mk(ls, (struct anode *)0, (struct anode *)0)); ! 227: } ! 228: else if (EQ(a, "-xdev")) { ! 229: Xdev = 0; ! 230: return (mk(dummy, (struct anode *)0, (struct anode *)0)); ! 231: } ! 232: else if (EQ(a, "-follow")) { ! 233: follow=1; ! 234: return mk(dummy, (struct anode *)0, (struct anode *)0); ! 235: } ! 236: b = nxtarg(); ! 237: s = *b; ! 238: if(s=='+') b++; ! 239: if(EQ(a, "-name")) ! 240: return(mk(glob, (struct anode *)b, (struct anode *)0)); ! 241: else if(EQ(a, "-mtime")) ! 242: return(mk(mtime, (struct anode *)atoi(b), (struct anode *)s)); ! 243: else if(EQ(a, "-atime")) ! 244: return(mk(atime, (struct anode *)atoi(b), (struct anode *)s)); ! 245: else if(EQ(a, "-user")) { ! 246: if((i=getuid(b)) == -1) { ! 247: if(gmatch(b, "[0-9]*")) ! 248: return mk(user, (struct anode *)atoi(b), (struct anode *)s); ! 249: fprintf(stderr, "find: cannot find -user name\n"); ! 250: exit(1); ! 251: } ! 252: return(mk(user, (struct anode *)i, (struct anode *)s)); ! 253: } ! 254: else if(EQ(a, "-inum")) ! 255: return(mk(ino, (struct anode *)atoi(b), (struct anode *)s)); ! 256: else if(EQ(a, "-group")) { ! 257: if((i=getgid(b)) == -1) { ! 258: if(gmatch(b, "[0-9]*")) ! 259: return mk(group, (struct anode *)atoi(b), (struct anode *)s); ! 260: fprintf(stderr, "find: cannot find -group name\n"); ! 261: exit(1); ! 262: } ! 263: return(mk(group, (struct anode *)i, (struct anode *)s)); ! 264: } else if(EQ(a, "-size")) ! 265: return(mk(size, (struct anode *)atoi(b), (struct anode *)s)); ! 266: else if(EQ(a, "-links")) ! 267: return(mk(links, (struct anode *)atoi(b), (struct anode *)s)); ! 268: else if(EQ(a, "-perm")) { ! 269: for(i=0; *b ; ++b) { ! 270: if(*b=='-') continue; ! 271: i <<= 3; ! 272: i = i + (*b - '0'); ! 273: } ! 274: return(mk(perm, (struct anode *)i, (struct anode *)s)); ! 275: } ! 276: else if(EQ(a, "-type")) { ! 277: i = s=='d' ? S_IFDIR : ! 278: s=='b' ? S_IFBLK : ! 279: s=='c' ? S_IFCHR : ! 280: s=='f' ? S_IFREG : ! 281: s=='l' ? S_IFLNK : ! 282: s=='s' ? S_IFSOCK : ! 283: 0; ! 284: return(mk(type, (struct anode *)i, (struct anode *)0)); ! 285: } ! 286: else if (EQ(a, "-exec")) { ! 287: i = Ai - 1; ! 288: while(!EQ(nxtarg(), ";")); ! 289: return(mk(exeq, (struct anode *)i, (struct anode *)0)); ! 290: } ! 291: else if (EQ(a, "-ok")) { ! 292: i = Ai - 1; ! 293: while(!EQ(nxtarg(), ";")); ! 294: return(mk(ok, (struct anode *)i, (struct anode *)0)); ! 295: } ! 296: else if(EQ(a, "-cpio")) { ! 297: if((Cpio = creat(b, 0666)) < 0) { ! 298: fprintf(stderr, "find: cannot create < %s >\n", s); ! 299: exit(1); ! 300: } ! 301: Buf = (short *)sbrk(512); ! 302: Wp = Dbuf = (short *)sbrk(5120); ! 303: return(mk(cpio, (struct anode *)0, (struct anode *)0)); ! 304: } ! 305: else if(EQ(a, "-newer")) { ! 306: if(stat(b, &Statb) < 0) { ! 307: fprintf(stderr, "find: cannot access < %s >\n", b); ! 308: exit(1); ! 309: } ! 310: Newer = Statb.st_mtime; ! 311: return mk(newer, (struct anode *)0, (struct anode *)0); ! 312: } ! 313: err: fprintf(stderr, "find: bad option < %s >\n", a); ! 314: exit(1); ! 315: } ! 316: struct anode *mk(f, l, r) ! 317: int (*f)(); ! 318: struct anode *l, *r; ! 319: { ! 320: if (Nn >= MAXNODES) { ! 321: fprintf(stderr, "find: Too many options\n"); ! 322: exit(1); ! 323: } ! 324: ! 325: Node[Nn].F = f; ! 326: Node[Nn].L = l; ! 327: Node[Nn].R = r; ! 328: return(&(Node[Nn++])); ! 329: } ! 330: ! 331: char *nxtarg() { /* get next arg from command line */ ! 332: static strikes = 0; ! 333: ! 334: if(strikes==3) { ! 335: fprintf(stderr, "find: incomplete statement\n"); ! 336: exit(1); ! 337: } ! 338: if(Ai>=Argc) { ! 339: strikes++; ! 340: Ai = Argc + 1; ! 341: return(""); ! 342: } ! 343: return(Argv[Ai++]); ! 344: } ! 345: ! 346: /* execution time functions */ ! 347: and(p) ! 348: register struct anode *p; ! 349: { ! 350: return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0); ! 351: } ! 352: or(p) ! 353: register struct anode *p; ! 354: { ! 355: return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0); ! 356: } ! 357: not(p) ! 358: register struct anode *p; ! 359: { ! 360: return( !((*p->L->F)(p->L))); ! 361: } ! 362: glob(p) ! 363: register struct { int f; char *pat; } *p; ! 364: { ! 365: return(gmatch(Fname, p->pat)); ! 366: } ! 367: print(p) ! 368: struct anode *p; ! 369: { ! 370: puts(Pathname); ! 371: return(1); ! 372: } ! 373: mtime(p) ! 374: register struct { int f, t, s; } *p; ! 375: { ! 376: return(scomp((int)((Now - Statb.st_mtime) / A_DAY), p->t, p->s)); ! 377: } ! 378: atime(p) ! 379: register struct { int f, t, s; } *p; ! 380: { ! 381: return(scomp((int)((Now - Statb.st_atime) / A_DAY), p->t, p->s)); ! 382: } ! 383: user(p) ! 384: register struct { int f, u, s; } *p; ! 385: { ! 386: return(scomp(Statb.st_uid, p->u, p->s)); ! 387: } ! 388: nouser(p) ! 389: struct anode *p; ! 390: { ! 391: char *getname(); ! 392: ! 393: return (getname(Statb.st_uid) == NULL); ! 394: } ! 395: ino(p) ! 396: register struct { int f, u, s; } *p; ! 397: { ! 398: return(scomp((int)Statb.st_ino, p->u, p->s)); ! 399: } ! 400: group(p) ! 401: register struct { int f, u; } *p; ! 402: { ! 403: return(p->u == Statb.st_gid); ! 404: } ! 405: nogroup(p) ! 406: struct anode *p; ! 407: { ! 408: char *getgroup(); ! 409: ! 410: return (getgroup(Statb.st_gid) == NULL); ! 411: } ! 412: links(p) ! 413: register struct { int f, link, s; } *p; ! 414: { ! 415: return(scomp(Statb.st_nlink, p->link, p->s)); ! 416: } ! 417: size(p) ! 418: register struct { int f, sz, s; } *p; ! 419: { ! 420: return(scomp((int)((Statb.st_size+511)>>9), p->sz, p->s)); ! 421: } ! 422: perm(p) ! 423: register struct { int f, per, s; } *p; ! 424: { ! 425: register i; ! 426: i = (p->s=='-') ? p->per : 07777; /* '-' means only arg bits */ ! 427: return((Statb.st_mode & i & 07777) == p->per); ! 428: } ! 429: type(p) ! 430: register struct { int f, per, s; } *p; ! 431: { ! 432: return((Statb.st_mode&S_IFMT)==p->per); ! 433: } ! 434: exeq(p) ! 435: register struct { int f, com; } *p; ! 436: { ! 437: fflush(stdout); /* to flush possible `-print' */ ! 438: return(doex(p->com)); ! 439: } ! 440: ok(p) ! 441: struct { int f, com; } *p; ! 442: { ! 443: char c; int yes; ! 444: yes = 0; ! 445: fflush(stdout); /* to flush possible `-print' */ ! 446: fprintf(stderr, "< %s ... %s > ? ", Argv[p->com], Pathname); ! 447: fflush(stderr); ! 448: if((c=getchar())=='y') yes = 1; ! 449: while(c!='\n') c = getchar(); ! 450: if(yes) return(doex(p->com)); ! 451: return(0); ! 452: } ! 453: ! 454: #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];} ! 455: union { long l; short s[2]; char c[4]; } U; ! 456: long mklong(v) ! 457: short v[]; ! 458: { ! 459: U.l = 1; ! 460: if(U.c[0] /* VAX */) ! 461: U.s[0] = v[1], U.s[1] = v[0]; ! 462: else ! 463: U.s[0] = v[0], U.s[1] = v[1]; ! 464: return U.l; ! 465: } ! 466: cpio(p) ! 467: struct anode *p; ! 468: { ! 469: #define MAGIC 070707 ! 470: struct header { ! 471: short h_magic, ! 472: h_dev, ! 473: h_ino, ! 474: h_mode, ! 475: h_uid, ! 476: h_gid, ! 477: h_nlink, ! 478: h_rdev; ! 479: short h_mtime[2]; ! 480: short h_namesize; ! 481: short h_filesize[2]; ! 482: char h_name[256]; ! 483: } hdr; ! 484: register ifile, ct; ! 485: static long fsz; ! 486: register i; ! 487: ! 488: hdr.h_magic = MAGIC; ! 489: strcpy(hdr.h_name, !strncmp(Pathname, "./", 2)? Pathname+2: Pathname); ! 490: hdr.h_namesize = strlen(hdr.h_name) + 1; ! 491: hdr.h_uid = Statb.st_uid; ! 492: hdr.h_gid = Statb.st_gid; ! 493: hdr.h_dev = Statb.st_dev; ! 494: hdr.h_ino = Statb.st_ino; ! 495: hdr.h_mode = Statb.st_mode; ! 496: MKSHORT(hdr.h_mtime, Statb.st_mtime); ! 497: hdr.h_nlink = Statb.st_nlink; ! 498: fsz = hdr.h_mode & S_IFREG? Statb.st_size: 0L; ! 499: MKSHORT(hdr.h_filesize, fsz); ! 500: hdr.h_rdev = Statb.st_rdev; ! 501: if(EQ(hdr.h_name, "TRAILER!!!")) { ! 502: bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize); ! 503: for(i = 0; i < 10; ++i) ! 504: bwrite(Buf, 512); ! 505: return; ! 506: } ! 507: if(!mklong(hdr.h_filesize)) ! 508: return; ! 509: if((ifile = open(Fname, 0)) < 0) { ! 510: cerror: ! 511: fprintf(stderr, "find: cannot copy < %s >\n", hdr.h_name); ! 512: return; ! 513: } ! 514: bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize); ! 515: for(fsz = mklong(hdr.h_filesize); fsz > 0; fsz -= 512) { ! 516: ct = fsz>512? 512: fsz; ! 517: if(read(ifile, (char *)Buf, ct) < 0) ! 518: goto cerror; ! 519: bwrite(Buf, ct); ! 520: } ! 521: close(ifile); ! 522: return; ! 523: } ! 524: newer(p) ! 525: struct anode *p; ! 526: { ! 527: return Statb.st_mtime > Newer; ! 528: } ! 529: ls(p) ! 530: struct anode *p; ! 531: { ! 532: list(Pathname, &Statb); ! 533: return (1); ! 534: } ! 535: dummy(p) ! 536: struct anode *p; ! 537: { ! 538: /* dummy */ ! 539: return (1); ! 540: } ! 541: ! 542: /* support functions */ ! 543: scomp(a, b, s) /* funny signed compare */ ! 544: register a, b; ! 545: register char s; ! 546: { ! 547: if(s == '+') ! 548: return(a > b); ! 549: if(s == '-') ! 550: return(a < (b * -1)); ! 551: return(a == b); ! 552: } ! 553: ! 554: doex(com) ! 555: { ! 556: register np; ! 557: register char *na; ! 558: static char *nargv[50]; ! 559: static ccode; ! 560: register int w, pid, omask; ! 561: ! 562: ccode = np = 0; ! 563: while (na=Argv[com++]) { ! 564: if(np >= sizeof nargv / sizeof *nargv - 1) break; ! 565: if(strcmp(na, ";")==0) break; ! 566: if(strcmp(na, "{}")==0) nargv[np++] = Pathname; ! 567: else nargv[np++] = na; ! 568: } ! 569: nargv[np] = 0; ! 570: if (np==0) return(9); ! 571: switch (pid = vfork()) { ! 572: case -1: ! 573: perror("find: Can't fork"); ! 574: exit(1); ! 575: break; ! 576: ! 577: case 0: ! 578: chdir(Home); ! 579: execvp(nargv[0], nargv, np); ! 580: write(2, "find: Can't execute ", 20); ! 581: perror(nargv[0]); ! 582: /* ! 583: * Kill ourselves; our exit status will be a suicide ! 584: * note indicating we couldn't do the "exec". ! 585: */ ! 586: kill(getpid(), SIGUSR1); ! 587: break; ! 588: ! 589: default: ! 590: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)); ! 591: while ((w = wait(&ccode)) != pid && w != -1) ! 592: ; ! 593: (void) sigsetmask(omask); ! 594: if ((ccode & 0177) == SIGUSR1) ! 595: exit(1); ! 596: return (ccode != 0 ? 0 : 1); ! 597: } ! 598: } ! 599: ! 600: getunum(f, s) char *f, *s; { /* find user/group name and return number */ ! 601: register i; ! 602: register char *sp; ! 603: register c; ! 604: char str[20]; ! 605: FILE *pin; ! 606: ! 607: i = -1; ! 608: pin = fopen(f, "r"); ! 609: c = '\n'; /* prime with a CR */ ! 610: do { ! 611: if(c=='\n') { ! 612: sp = str; ! 613: while((c = *sp++ = getc(pin)) != ':') ! 614: if(c == EOF) goto RET; ! 615: *--sp = '\0'; ! 616: if(EQ(str, s)) { ! 617: while((c=getc(pin)) != ':') ! 618: if(c == EOF) goto RET; ! 619: sp = str; ! 620: while((*sp = getc(pin)) != ':') sp++; ! 621: *sp = '\0'; ! 622: i = atoi(str); ! 623: goto RET; ! 624: } ! 625: } ! 626: } while((c = getc(pin)) != EOF); ! 627: RET: ! 628: fclose(pin); ! 629: return(i); ! 630: } ! 631: ! 632: descend(name, fname, exlist) ! 633: struct anode *exlist; ! 634: char *name, *fname; ! 635: { ! 636: DIR *dir = NULL; ! 637: register struct direct *dp; ! 638: register char *c1; ! 639: int rv = 0; ! 640: char *endofname; ! 641: ! 642: if ((follow?stat(fname, &Statb):lstat(fname, &Statb))<0) { ! 643: fprintf(stderr, "find: bad status < %s >\n", name); ! 644: return(0); ! 645: } ! 646: (*exlist->F)(exlist); ! 647: if((Statb.st_mode&S_IFMT)!=S_IFDIR || ! 648: !Xdev && Devstat.st_dev != Statb.st_dev) ! 649: return(1); ! 650: ! 651: if (Statb.st_nlink == 2 && exlist->F == and && ! 652: exlist->L->F == type && ((int) (exlist->L->L)) == S_IFDIR) ! 653: return(1); ! 654: ! 655: for (c1 = name; *c1; ++c1); ! 656: if (*(c1-1) == '/') ! 657: --c1; ! 658: endofname = c1; ! 659: ! 660: if (chdir(fname) == -1) ! 661: return(0); ! 662: if ((dir = opendir(".")) == NULL) { ! 663: fprintf(stderr, "find: cannot open < %s >\n", name); ! 664: rv = 0; ! 665: goto ret; ! 666: } ! 667: for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) { ! 668: if ((dp->d_name[0]=='.' && dp->d_name[1]=='\0') || ! 669: (dp->d_name[0]=='.' && dp->d_name[1]=='.' && dp->d_name[2]=='\0')) ! 670: continue; ! 671: c1 = endofname; ! 672: *c1++ = '/'; ! 673: strcpy(c1, dp->d_name); ! 674: Fname = endofname+1; ! 675: if(!descend(name, Fname, exlist)) { ! 676: *endofname = '\0'; ! 677: chdir(Home); ! 678: if(chdir(Pathname) == -1) { ! 679: fprintf(stderr, "find: bad directory tree\n"); ! 680: exit(1); ! 681: } ! 682: } ! 683: } ! 684: rv = 1; ! 685: ret: ! 686: if(dir) ! 687: closedir(dir); ! 688: if(chdir("..") == -1) { ! 689: *endofname = '\0'; ! 690: fprintf(stderr, "find: bad directory <%s>\n", name); ! 691: rv = 1; ! 692: } ! 693: return(rv); ! 694: } ! 695: ! 696: gmatch(s, p) /* string match as in glob */ ! 697: register char *s, *p; ! 698: { ! 699: if (*s=='.' && *p!='.') return(0); ! 700: return amatch(s, p); ! 701: } ! 702: ! 703: amatch(s, p) ! 704: register char *s, *p; ! 705: { ! 706: register cc; ! 707: int scc, k; ! 708: int c, lc; ! 709: ! 710: scc = *s; ! 711: lc = 077777; ! 712: switch (c = *p) { ! 713: ! 714: case '[': ! 715: k = 0; ! 716: while (cc = *++p) { ! 717: switch (cc) { ! 718: ! 719: case ']': ! 720: if (k) ! 721: return(amatch(++s, ++p)); ! 722: else ! 723: return(0); ! 724: ! 725: case '-': ! 726: cc = p[1]; ! 727: k |= lc <= scc && scc <= cc; ! 728: } ! 729: if (scc==(lc=cc)) k++; ! 730: } ! 731: return(0); ! 732: ! 733: case '?': ! 734: caseq: ! 735: if(scc) return(amatch(++s, ++p)); ! 736: return(0); ! 737: case '*': ! 738: return(umatch(s, ++p)); ! 739: case 0: ! 740: return(!scc); ! 741: } ! 742: if (c==scc) goto caseq; ! 743: return(0); ! 744: } ! 745: ! 746: umatch(s, p) ! 747: register char *s, *p; ! 748: { ! 749: if(*p==0) return(1); ! 750: while(*s) ! 751: if (amatch(s++, p)) return(1); ! 752: return(0); ! 753: } ! 754: ! 755: bwrite(rp, c) ! 756: register short *rp; ! 757: register c; ! 758: { ! 759: register short *wp = Wp; ! 760: ! 761: c = (c+1) >> 1; ! 762: while(c--) { ! 763: if(!Wct) { ! 764: again: ! 765: if(write(Cpio, (char *)Dbuf, Bufsize)<0) { ! 766: Cpio = chgreel(1, Cpio); ! 767: goto again; ! 768: } ! 769: Wct = Bufsize >> 1; ! 770: wp = Dbuf; ! 771: ++Blocks; ! 772: } ! 773: *wp++ = *rp++; ! 774: --Wct; ! 775: } ! 776: Wp = wp; ! 777: } ! 778: chgreel(x, fl) ! 779: { ! 780: register f; ! 781: char str[22]; ! 782: FILE *devtty; ! 783: struct stat statb; ! 784: extern errno; ! 785: ! 786: fprintf(stderr, "find: errno: %d, ", errno); ! 787: fprintf(stderr, "find: can't %s\n", x? "write output": "read input"); ! 788: fstat(fl, &statb); ! 789: if((statb.st_mode&S_IFMT) != S_IFCHR) ! 790: exit(1); ! 791: again: ! 792: fprintf(stderr, "If you want to go on, type device/file name %s\n", ! 793: "when ready"); ! 794: devtty = fopen("/dev/tty", "r"); ! 795: fgets(str, 20, devtty); ! 796: str[strlen(str) - 1] = '\0'; ! 797: if(!*str) ! 798: exit(1); ! 799: close(fl); ! 800: if((f = open(str, x? 1: 0)) < 0) { ! 801: fprintf(stderr, "That didn't work"); ! 802: fclose(devtty); ! 803: goto again; ! 804: } ! 805: return f; ! 806: } ! 807: ! 808: #ifdef AMES ! 809: /* ! 810: * 'fastfind' scans a file list for the full pathname of a file ! 811: * given only a piece of the name. The list has been processed with ! 812: * with "front-compression" and bigram coding. Front compression reduces ! 813: * space by a factor of 4-5, bigram coding by a further 20-25%. ! 814: * The codes are: ! 815: * ! 816: * 0-28 likeliest differential counts + offset to make nonnegative ! 817: * 30 escape code for out-of-range count to follow in next word ! 818: * 128-255 bigram codes, (128 most common, as determined by 'updatedb') ! 819: * 32-127 single character (printable) ascii residue ! 820: * ! 821: * A novel two-tiered string search technique is employed: ! 822: * ! 823: * First, a metacharacter-free subpattern and partial pathname is ! 824: * matched BACKWARDS to avoid full expansion of the pathname list. ! 825: * The time savings is 40-50% over forward matching, which cannot efficiently ! 826: * handle overlapped search patterns and compressed path residue. ! 827: * ! 828: * Then, the actual shell glob-style regular expression (if in this form) ! 829: * is matched against the candidate pathnames using the slower routines ! 830: * provided in the standard 'find'. ! 831: */ ! 832: ! 833: #define FCODES "/usr/lib/find/find.codes" ! 834: #define YES 1 ! 835: #define NO 0 ! 836: #define OFFSET 14 ! 837: #define ESCCODE 30 ! 838: ! 839: fastfind ( pathpart ) ! 840: char pathpart[]; ! 841: { ! 842: register char *p, *s; ! 843: register int c; ! 844: char *q, *index(), *patprep(); ! 845: int i, count = 0, globflag; ! 846: FILE *fp, *fopen(); ! 847: char *patend, *cutoff; ! 848: char path[1024]; ! 849: char bigram1[128], bigram2[128]; ! 850: int found = NO; ! 851: ! 852: if ( (fp = fopen ( FCODES, "r" )) == NULL ) { ! 853: fprintf ( stderr, "find: can't open %s\n", FCODES ); ! 854: exit ( 1 ); ! 855: } ! 856: for ( i = 0; i < 128; i++ ) ! 857: bigram1[i] = getc ( fp ), bigram2[i] = getc ( fp ); ! 858: ! 859: globflag = index ( pathpart, '*' ) || index ( pathpart, '?' ) || ! 860: index ( pathpart, '[' ); ! 861: patend = patprep ( pathpart ); ! 862: ! 863: c = getc ( fp ); ! 864: for ( ; ; ) { ! 865: ! 866: count += ( (c == ESCCODE) ? getw ( fp ) : c ) - OFFSET; ! 867: ! 868: for ( p = path + count; (c = getc ( fp )) > ESCCODE; ) /* overlay old path */ ! 869: if ( c < 0200 ) ! 870: *p++ = c; ! 871: else /* bigrams are parity-marked */ ! 872: *p++ = bigram1[c & 0177], *p++ = bigram2[c & 0177]; ! 873: if ( c == EOF ) ! 874: break; ! 875: *p-- = NULL; ! 876: cutoff = ( found ? path : path + count); ! 877: ! 878: for ( found = NO, s = p; s >= cutoff; s-- ) ! 879: if ( *s == *patend ) { /* fast first char check */ ! 880: for ( p = patend - 1, q = s - 1; *p != NULL; p--, q-- ) ! 881: if ( *q != *p ) ! 882: break; ! 883: if ( *p == NULL ) { /* success on fast match */ ! 884: found = YES; ! 885: if ( globflag == NO || amatch ( path, pathpart ) ) ! 886: puts ( path ); ! 887: break; ! 888: } ! 889: } ! 890: } ! 891: } ! 892: ! 893: /* ! 894: extract last glob-free subpattern in name for fast pre-match; ! 895: prepend '\0' for backwards match; return end of new pattern ! 896: */ ! 897: static char globfree[100]; ! 898: ! 899: char * ! 900: patprep ( name ) ! 901: char *name; ! 902: { ! 903: register char *p, *endmark; ! 904: register char *subp = globfree; ! 905: ! 906: *subp++ = '\0'; ! 907: p = name + strlen ( name ) - 1; ! 908: /* ! 909: skip trailing metacharacters (and [] ranges) ! 910: */ ! 911: for ( ; p >= name; p-- ) ! 912: if ( index ( "*?", *p ) == 0 ) ! 913: break; ! 914: if ( p < name ) ! 915: p = name; ! 916: if ( *p == ']' ) ! 917: for ( p--; p >= name; p-- ) ! 918: if ( *p == '[' ) { ! 919: p--; ! 920: break; ! 921: } ! 922: if ( p < name ) ! 923: p = name; ! 924: /* ! 925: if pattern has only metacharacters, ! 926: check every path (force '/' search) ! 927: */ ! 928: if ( (p == name) && index ( "?*[]", *p ) != 0 ) ! 929: *subp++ = '/'; ! 930: else { ! 931: for ( endmark = p; p >= name; p-- ) ! 932: if ( index ( "]*?", *p ) != 0 ) ! 933: break; ! 934: for ( ++p; (p <= endmark) && subp < (globfree + sizeof ( globfree )); ) ! 935: *subp++ = *p++; ! 936: } ! 937: *subp = '\0'; ! 938: return ( --subp ); ! 939: } ! 940: #endif ! 941: ! 942: /* rest should be done with nameserver or database */ ! 943: ! 944: #include <pwd.h> ! 945: #include <grp.h> ! 946: #include <utmp.h> ! 947: ! 948: struct utmp utmp; ! 949: #define NMAX (sizeof (utmp.ut_name)) ! 950: #define SCPYN(a, b) strncpy(a, b, NMAX) ! 951: ! 952: #define NUID 64 ! 953: #define NGID 300 ! 954: ! 955: struct ncache { ! 956: int uid; ! 957: char name[NMAX+1]; ! 958: } nc[NUID]; ! 959: char outrangename[NMAX+1]; ! 960: int outrangeuid = -1; ! 961: char groups[NGID][NMAX+1]; ! 962: char outrangegroup[NMAX+1]; ! 963: int outrangegid = -1; ! 964: ! 965: /* ! 966: * This function assumes that the password file is hashed ! 967: * (or some such) to allow fast access based on a name key. ! 968: * If this isn't true, duplicate the code for getgroup(). ! 969: */ ! 970: char * ! 971: getname(uid) ! 972: { ! 973: register struct passwd *pw; ! 974: struct passwd *getpwent(); ! 975: register int cp; ! 976: extern int _pw_stayopen; ! 977: ! 978: _pw_stayopen = 1; ! 979: ! 980: #if (((NUID) & ((NUID) - 1)) != 0) ! 981: cp = uid % (NUID); ! 982: #else ! 983: cp = uid & ((NUID) - 1); ! 984: #endif ! 985: if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0]) ! 986: return (nc[cp].name); ! 987: pw = getpwuid(uid); ! 988: if (!pw) ! 989: return (0); ! 990: nc[cp].uid = uid; ! 991: SCPYN(nc[cp].name, pw->pw_name); ! 992: return (nc[cp].name); ! 993: } ! 994: ! 995: char * ! 996: getgroup(gid) ! 997: { ! 998: register struct group *gr; ! 999: static init; ! 1000: struct group *getgrent(); ! 1001: ! 1002: if (gid >= 0 && gid < NGID && groups[gid][0]) ! 1003: return (&groups[gid][0]); ! 1004: if (gid >= 0 && gid == outrangegid) ! 1005: return (outrangegroup); ! 1006: rescan: ! 1007: if (init == 2) { ! 1008: if (gid < NGID) ! 1009: return (0); ! 1010: setgrent(); ! 1011: while (gr = getgrent()) { ! 1012: if (gr->gr_gid != gid) ! 1013: continue; ! 1014: outrangegid = gr->gr_gid; ! 1015: SCPYN(outrangegroup, gr->gr_name); ! 1016: endgrent(); ! 1017: return (outrangegroup); ! 1018: } ! 1019: endgrent(); ! 1020: return (0); ! 1021: } ! 1022: if (init == 0) ! 1023: setgrent(), init = 1; ! 1024: while (gr = getgrent()) { ! 1025: if (gr->gr_gid < 0 || gr->gr_gid >= NGID) { ! 1026: if (gr->gr_gid == gid) { ! 1027: outrangegid = gr->gr_gid; ! 1028: SCPYN(outrangegroup, gr->gr_name); ! 1029: return (outrangegroup); ! 1030: } ! 1031: continue; ! 1032: } ! 1033: if (groups[gr->gr_gid][0]) ! 1034: continue; ! 1035: SCPYN(groups[gr->gr_gid], gr->gr_name); ! 1036: if (gr->gr_gid == gid) ! 1037: return (&groups[gid][0]); ! 1038: } ! 1039: init = 2; ! 1040: goto rescan; ! 1041: } ! 1042: ! 1043: int ! 1044: getuid(username) ! 1045: char *username; ! 1046: { ! 1047: register struct passwd *pw; ! 1048: struct passwd *getpwnam(); ! 1049: #ifndef NO_PW_STAYOPEN ! 1050: extern int _pw_stayopen; ! 1051: ! 1052: _pw_stayopen = 1; ! 1053: #endif ! 1054: ! 1055: pw = getpwnam(username); ! 1056: if (pw != NULL) ! 1057: return (pw->pw_uid); ! 1058: else ! 1059: return (-1); ! 1060: } ! 1061: ! 1062: int ! 1063: getgid(groupname) ! 1064: char *groupname; ! 1065: { ! 1066: register struct group *gr; ! 1067: struct group *getgrnam(); ! 1068: ! 1069: gr = getgrnam(groupname); ! 1070: if (gr != NULL) ! 1071: return (gr->gr_gid); ! 1072: else ! 1073: return (-1); ! 1074: } ! 1075: ! 1076: #define permoffset(who) ((who) * 3) ! 1077: #define permission(who, type) ((type) >> permoffset(who)) ! 1078: #define kbytes(bytes) (((bytes) + 1023) / 1024) ! 1079: ! 1080: list(file, stp) ! 1081: char *file; ! 1082: register struct stat *stp; ! 1083: { ! 1084: char pmode[32], uname[32], gname[32], fsize[32], ftime[32]; ! 1085: char *getname(), *getgroup(), *ctime(); ! 1086: static long special[] = { S_ISUID, 's', S_ISGID, 's', S_ISVTX, 't' }; ! 1087: static time_t sixmonthsago = -1; ! 1088: #ifdef S_IFLNK ! 1089: char flink[MAXPATHLEN + 1]; ! 1090: #endif ! 1091: register int who; ! 1092: register char *cp; ! 1093: time_t now; ! 1094: ! 1095: if (file == NULL || stp == NULL) ! 1096: return (-1); ! 1097: ! 1098: time(&now); ! 1099: if (sixmonthsago == -1) ! 1100: sixmonthsago = now - 6L*30L*24L*60L*60L; ! 1101: ! 1102: switch (stp->st_mode & S_IFMT) { ! 1103: #ifdef S_IFDIR ! 1104: case S_IFDIR: /* directory */ ! 1105: pmode[0] = 'd'; ! 1106: break; ! 1107: #endif ! 1108: #ifdef S_IFCHR ! 1109: case S_IFCHR: /* character special */ ! 1110: pmode[0] = 'c'; ! 1111: break; ! 1112: #endif ! 1113: #ifdef S_IFBLK ! 1114: case S_IFBLK: /* block special */ ! 1115: pmode[0] = 'b'; ! 1116: break; ! 1117: #endif ! 1118: #ifdef S_IFLNK ! 1119: case S_IFLNK: /* symbolic link */ ! 1120: pmode[0] = 'l'; ! 1121: break; ! 1122: #endif ! 1123: #ifdef S_IFSOCK ! 1124: case S_IFSOCK: /* socket */ ! 1125: pmode[0] = 's'; ! 1126: break; ! 1127: #endif ! 1128: #ifdef S_IFREG ! 1129: case S_IFREG: /* regular */ ! 1130: #endif ! 1131: default: ! 1132: pmode[0] = '-'; ! 1133: break; ! 1134: } ! 1135: ! 1136: for (who = 0; who < 3; who++) { ! 1137: if (stp->st_mode & permission(who, S_IREAD)) ! 1138: pmode[permoffset(who) + 1] = 'r'; ! 1139: else ! 1140: pmode[permoffset(who) + 1] = '-'; ! 1141: ! 1142: if (stp->st_mode & permission(who, S_IWRITE)) ! 1143: pmode[permoffset(who) + 2] = 'w'; ! 1144: else ! 1145: pmode[permoffset(who) + 2] = '-'; ! 1146: ! 1147: if (stp->st_mode & special[who * 2]) ! 1148: pmode[permoffset(who) + 3] = special[who * 2 + 1]; ! 1149: else if (stp->st_mode & permission(who, S_IEXEC)) ! 1150: pmode[permoffset(who) + 3] = 'x'; ! 1151: else ! 1152: pmode[permoffset(who) + 3] = '-'; ! 1153: } ! 1154: pmode[permoffset(who) + 1] = '\0'; ! 1155: ! 1156: cp = getname(stp->st_uid); ! 1157: if (cp != NULL) ! 1158: sprintf(uname, "%-9.9s", cp); ! 1159: else ! 1160: sprintf(uname, "%-9d", stp->st_uid); ! 1161: ! 1162: cp = getgroup(stp->st_gid); ! 1163: if (cp != NULL) ! 1164: sprintf(gname, "%-9.9s", cp); ! 1165: else ! 1166: sprintf(gname, "%-9d", stp->st_gid); ! 1167: ! 1168: if (pmode[0] == 'b' || pmode[0] == 'c') ! 1169: sprintf(fsize, "%3d,%4d", ! 1170: major(stp->st_rdev), minor(stp->st_rdev)); ! 1171: else { ! 1172: sprintf(fsize, "%8ld", stp->st_size); ! 1173: #ifdef S_IFLNK ! 1174: if (pmode[0] == 'l') { ! 1175: /* ! 1176: * Need to get the tail of the file name, since we have ! 1177: * already chdir()ed into the directory of the file ! 1178: */ ! 1179: cp = rindex(file, '/'); ! 1180: if (cp == NULL) ! 1181: cp = file; ! 1182: else ! 1183: cp++; ! 1184: who = readlink(cp, flink, sizeof flink - 1); ! 1185: if (who >= 0) ! 1186: flink[who] = '\0'; ! 1187: else ! 1188: flink[0] = '\0'; ! 1189: } ! 1190: #endif ! 1191: } ! 1192: ! 1193: cp = ctime(&stp->st_mtime); ! 1194: if (stp->st_mtime < sixmonthsago || stp->st_mtime > now) ! 1195: sprintf(ftime, "%-7.7s %-4.4s", cp + 4, cp + 20); ! 1196: else ! 1197: sprintf(ftime, "%-12.12s", cp + 4); ! 1198: ! 1199: printf("%5lu %4ld %s %2d %s%s%s %s %s%s%s\n", ! 1200: stp->st_ino, /* inode # */ ! 1201: #ifdef S_IFSOCK ! 1202: (long) kbytes(dbtob(stp->st_blocks)), /* kbytes */ ! 1203: #else ! 1204: (long) kbytes(stp->st_size), /* kbytes */ ! 1205: #endif ! 1206: pmode, /* protection */ ! 1207: stp->st_nlink, /* # of links */ ! 1208: uname, /* owner */ ! 1209: gname, /* group */ ! 1210: fsize, /* # of bytes */ ! 1211: ftime, /* modify time */ ! 1212: file, /* name */ ! 1213: #ifdef S_IFLNK ! 1214: (pmode[0] == 'l') ? " -> " : "", ! 1215: (pmode[0] == 'l') ? flink : "" /* symlink */ ! 1216: #else ! 1217: "", ! 1218: "" ! 1219: #endif ! 1220: ); ! 1221: ! 1222: return (0); ! 1223: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.