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