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