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