1: /* find -- find files in a pathname.
   2: 	Use of find is documented in /usr/man/man1/find.1 .
   3: 
   4: 	In addition, find has a secret first arg "+" which
   5: 	causes each file name to be printed along with a period
   6: 	if the predicates succeed.
   7:  */
   8: int randlast;
   9: char *pathname;
  10: int verbose;
  11: struct anode {
  12:     int (*F)();
  13:     struct anode *L, *R;
  14: } node[100];
  15: int nn;  /* number of nodes */
  16: char *fname, *path;
  17: int now[2];
  18: int ap, ac;
  19: char **av;
  20: 
  21: struct ibuf {
  22:     int idev;
  23:     int inum;
  24:     int iflags;
  25:     char    inl;
  26:     char    iuid;
  27:     char    igid;
  28:     char    isize0;
  29:     char    *isize;
  30:     int iaddr[8];
  31:     int iatime[2];
  32:     int imtime[2];
  33: } statb;
  34: 
  35: main(argc,argv) char *argv[]; {
  36: 
  37: struct anode *exlist;
  38: int find();
  39: 
  40:     time(&now);
  41:     ac = argc; av = argv; ap = 2;
  42:     pathname = argv[1];
  43:     if(compstr(argv[1],"+")==0) {
  44:         verbose++;
  45:         ap++;
  46:         pathname = argv[2];
  47:     } else verbose = 0;
  48:     argv[argc] = 0;
  49:     if(argc<3) {
  50:         printf("Insufficient args\n");
  51:         exit(9);
  52:     }
  53:     if(!(exlist = exp())) { /* parse and compile the arguments */
  54:         printf("Odd usage\n");
  55:         exit(9);
  56:     }
  57:     if(ap<argc) {
  58:         printf("Missing conjunction\n");
  59:         exit(9);
  60:     }
  61:     descend(pathname,'f',find,exlist); /* to find files that match  */
  62: }
  63: 
  64: /* compile time functions:  priority is  exp()<e1()<e2()<e3()  */
  65: 
  66: struct anode *exp() { /* parse -o ... */
  67:     int or();
  68:     int p1;
  69:     char *na;
  70:     p1 = e1() /* get left operand */ ;
  71:     if(compstr(na=nxtarg(),"-o")==0) {
  72:         randlast--;
  73:         return(mk(&or,p1,exp()));
  74:     }
  75:     else if(*na!=0) --ap;
  76:     return(p1);
  77: }
  78: struct anode *e1() { /* parse -a */
  79:     int and();
  80:     int p1;
  81:     char *na;
  82:     p1 = e2();
  83:     if(compstr(na=nxtarg(),"-a")==0) {
  84:         randlast--;
  85:         return(mk(&and,p1,e1()));
  86:     }
  87:     else if(*na!=0) --ap;
  88:     return(p1);
  89: }
  90: struct anode *e2() { /* parse not (!) */
  91:     int not();
  92:     char *na;
  93:     if(randlast) {
  94:         printf("operand follows operand.\n");
  95:         exit(9);
  96:     }
  97:     randlast++;
  98:     if(compstr(na=nxtarg(),"!")==0)
  99:         return(mk(&not,e3(),0));
 100:     else if(*na!=0) --ap;
 101:     return(e3());
 102: }
 103: struct anode *e3() { /* parse parens and predicates */
 104:     int exeq(), ok(), glob(),  mtime(), atime(), user(),
 105:         group(), size(), perm(), links(), print(),
 106:         type();
 107:     int p1, i;
 108:     char *a, *b, s;
 109:     a = nxtarg();
 110:     if(compstr(a,"(")==0) {
 111:         randlast--;
 112:         p1 = exp();
 113:         a = nxtarg();
 114:         if(compstr(a,")")!=0) goto err;
 115:         return(p1);
 116:     }
 117:     else if(compstr(a,"-print")==0) {
 118:         return(mk(&print,0,0));
 119:     }
 120:     b = nxtarg();
 121:     s = *b;
 122:     if(s=='+') b++;
 123:     if(compstr(a,"-name")==0)
 124:         return(mk(&glob,b,0));
 125:     else if(compstr(a,"-mtime")==0)
 126:         return(mk(&mtime,atoi(b),s));
 127:     else if(compstr(a,"-atime")==0)
 128:         return(mk(&atime,atoi(b),s));
 129:     else if(compstr(a,"-user")==0) {
 130:         if((i=getunum(b)) == -1) {
 131:             printf("Cannot find user \"%s\"\n",b);
 132:             exit(9);
 133:         }
 134:         return(mk(&user,i,s));
 135:     }
 136:     else if(compstr(a,"-group")==0)
 137:         return(mk(&group,atoi(b),s));
 138:     else if(compstr(a,"-size")==0)
 139:         return(mk(&size,atoi(b),s));
 140:     else if(compstr(a,"-links")==0)
 141:         return(mk(&links,atoi(b),s));
 142:     else if(compstr(a,"-perm")==0) {
 143:         for(i=0; *b ; ++b) {
 144:             if(*b=='-') continue;
 145:             i =<< 3;
 146:             i = i + (*b - '0');
 147:         }
 148:         return(mk(&perm,i,s));
 149:     }
 150:     else if(compstr(a,"-type")==0) {
 151:         i = s=='d' ? 040000 :
 152:             s=='b' ? 060000 :
 153:             s=='c' ? 020000 :
 154:             000000;
 155:         return(mk(&type,i,0));
 156:     }
 157:     else if (compstr(a,"-exec")==0) {
 158:         i = ap - 1;
 159:         while(compstr(nxtarg(),";")!=0);
 160:         return(mk(&exeq,i,0));
 161:     }
 162:     else if (compstr(a,"-ok")==0) {
 163:         i = ap - 1;
 164:         while(compstr(nxtarg(),";")!=0);
 165:         return(mk(&ok,i,0));
 166:     }
 167:     err: printf("Bad option: \"%s\" \"%s\"\n",a,b);
 168:     exit(9);
 169: }
 170: struct anode *mk(f,l,r) struct anode *l,*r; { /*make an expression node*/
 171:     node[nn].F = f;
 172:     node[nn].L = l;
 173:     node[nn].R = r;
 174:     return(&(node[nn++]));
 175: }
 176: 
 177: nxtarg() { /* get next arg from command line */
 178:     if(ap>=ac) return("");
 179:     return(av[ap++]);
 180: }
 181: 
 182: find(exlist,fullname) /* execute predicat list with current file */
 183: struct anode *exlist;
 184: char *fullname;
 185: {
 186: register int i;
 187:     path = fullname;
 188:     if(verbose) printf("%s",path);
 189:     for(i=0;fullname[i];++i)
 190:         if(fullname[i]=='/') fname = &fullname[i+1];
 191:     i = (*exlist->F)(exlist);
 192:     if(verbose)
 193:         if(i) printf(".\n");
 194:         else printf("\n");
 195: }
 196: 
 197: /* execution time functions */
 198: and(p) struct anode *p; {
 199:     return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0);
 200: }
 201: or(p) struct anode *p; {
 202:      return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0);
 203: }
 204: not(p) struct anode *p; {
 205:     return( !((*p->L->F)(p->L)));
 206: }
 207: glob(p) struct { int f; char *pat; } *p;  {
 208:     return(gmatch(fname,p->pat));
 209: }
 210: print() {
 211:     printf("%s\n",path);
 212:     return(1);
 213: }
 214: mtime(p) struct { int f, t, s; } *p;  {
 215:     return(scomp((now[0]-statb.imtime[0])*3/4,p->t,p->s));
 216: }
 217: atime(p) struct { int f, t, s; } *p;  {
 218:     return(scomp((now[0]-statb.iatime[0])*3/4,p->t,p->s));
 219: }
 220: user(p) struct { int f, u, s; } *p;  {
 221:     return(scomp(statb.iuid,p->u,p->s));
 222: }
 223: group(p) struct { int f, u; } *p;  {
 224:     return(p->u == statb.igid);
 225: }
 226: links(p) struct { int f, link, s; } *p;  {
 227:     return(scomp(statb.inl,p->link,p->s));
 228: }
 229: size(p) struct { int f, sz, s; } *p;  {
 230:     register int i;
 231:     i = statb.isize0 << 7;
 232:     i = i | ((statb.isize>>9) & 0177);
 233:     return(scomp(i,p->sz,p->s));
 234: }
 235: perm(p) struct { int f, per, s; } *p;  {
 236: int i;
 237:     i = (p->s=='-') ? p->per : 03777; /* '-' means only arg bits */
 238:     return((statb.iflags & i & 017777) == p->per);
 239: }
 240: type(p) struct { int f, per, s; } *p; {
 241:     return((statb.iflags&060000)==p->per);
 242: }
 243: exeq(p) struct { int f, com; } *p; {
 244:     return(doex(p->com));
 245: }
 246: ok(p) struct { int f, com; } *p; {
 247:     char c;  int yes;
 248:     yes = 0;
 249:     printf("%s ... %s ...? ",av[p->com],path);
 250:     if((c=getchar())=='y') yes = 1;
 251:     while(c!='\n') c = getchar();
 252:     if(yes) return(doex(p->com));
 253:     return(0);
 254: }
 255: 
 256: /* support functions */
 257: scomp(a,b,s) char s; { /* funny signed compare */
 258:     if(s == '+')
 259:         return(a > b);
 260:     if(s == '-')
 261:         return(a < (b * -1));
 262:     return(a == b);
 263: }
 264: doex(com) {
 265:     int ccode;
 266:     int np, i, c;
 267:     char *nargv[50], *ncom, *na;
 268: 
 269:     ccode = np = 0;
 270:     while (na=av[com++]) {
 271:         if(compstr(na,";")==0) break;
 272:         if(compstr(na,"{}")==0) nargv[np++] = path;
 273:         else nargv[np++] = na;
 274:     }
 275:     nargv[np] = 0;
 276:     if (np==0) return(9);
 277:     if(fork()) /*parent*/ wait(&ccode);
 278:     else { /*child*/
 279:         execv(nargv[0], nargv, np);
 280:         i = 0;
 281:         ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
 282:         while(c=nargv[0][i])  {
 283:             ncom[9+i++] = c;
 284:         }
 285:         ncom[9+i] = '\0';
 286:         execv(ncom+4, nargv, np);
 287:         execv(ncom, nargv, np);
 288:         exit(9);
 289:     }
 290:     return(ccode ? 0:1);
 291: }
 292: 
 293: char fin[518];
 294: getunum(s) char *s; { /* find username in /etc/passwd & return num. */
 295: int i;
 296: char str[20], *sp, c;
 297:     i = -1;
 298:     fin[0] = open("/etc/passwd",0);
 299:     while(c = getchar()) {
 300:         if(c=='\n') {
 301:             sp = str;
 302:             while((*sp = getchar()) != ':')
 303:                 if(! *sp++) goto RET;
 304:             *sp = '\0';
 305:             if(compstr(str,s)==0) {
 306:                 while((c=getchar()) != ':')
 307:                     if(! c) goto RET;
 308:                 sp = str;
 309:                 while((*sp = getchar()) != ':') sp++;
 310:                 *sp = '\0';
 311:                 i = atoi(str);
 312:                 break;
 313:             }
 314:         }
 315:     }
 316:     RET:
 317:     close(fin);
 318:     fin[0] = 0;
 319:     return(i);
 320: }
 321: 
 322: compstr(s1,s2) char s1[], s2[]; {   /* compare strings: */
 323: register char *c1, *c2;
 324:     c1 = s1;  c2 = s2;
 325:     while(*c1 == *c2)
 326:         if(*c1++ == '\0')
 327:             return(0); /* s1 == s2 */
 328:         else c2++;
 329:     return(*c1 > *c2 ? 1 : -1);
 330: }
 331: 
 332: int descend(name,goal,func,arg)
 333: int (*func)();
 334: char *name, goal;
 335: {
 336:     int dir /* open directory */, offset /* in directory */;
 337:     int dsize, top;
 338:     struct {
 339:         int dinode;
 340:         char    dname[14];
 341:     } dentry[32];
 342:     register int i, j, k;
 343:     char aname[128];
 344: 
 345:     if(stat(name,&statb)<0) {
 346:         printf("--bad status %s\n",name);
 347:         return(0);
 348:     }
 349: /*
 350: 	if((statb.iflags&060000)!=040000){ /*not a directory*/
 351: /*
 352: 		if(goal=='f'||goal=='b') /* search goal for files */
 353: /*
 354: 			(*func)(arg,name);
 355: 		return(1);
 356: 	} else  if(goal=='d' || goal=='b') /* search goal is directories */
 357: /*
 358: 			(*func)(arg,name);
 359: */
 360:     (*func)(arg,name);
 361:     if((statb.iflags&060000)!=040000)
 362:         return(1);
 363: 
 364:     top = statb.isize;
 365:     for(offset=0 ; offset < top ; offset =+ 512) { /* each block */
 366:         dsize = 512<(top-offset) ? 512 : (top-offset);
 367:         if((dir=open(name,0))<0) {
 368:             printf("--cannot open %s\n",name);
 369:             return(0);
 370:         }
 371:         if(offset) seek(dir,offset,0);
 372:         if(read(dir,&dentry,dsize)<0) {
 373:             printf("--cannot read %s\n",name);
 374:             return(0);
 375:         }
 376:         close(dir);
 377:         for(i = 0; i < (dsize>>4); ++i) { /* each dir. entry */
 378:             if(dentry[i].dinode==0 ||
 379:                 compstr(dentry[i].dname,".")==0 ||
 380:                 compstr(dentry[i].dname,"..")==0)
 381:                 continue;
 382:             if (dentry[i].dinode == -1) break;
 383:             for(j=0;aname[j]=name[j];++j);
 384:             if(aname[j-1]!='/') aname[j++] = '/';
 385:             for(k=0; (aname[j++]=dentry[i].dname[k]) &&
 386:                 k<13; ++k);
 387:             aname[j] = '\0';
 388:             if(descend(aname,goal,func,arg)==0)
 389:                 printf("--%s\n",name);
 390:         }
 391:     }
 392:     return(1);
 393: }
 394: 
 395: gmatch(s, p) /* string match as in glob */
 396: char *s, *p; {
 397:     if (*s=='.' && *p!='.') return(0);
 398:     return(amatch(s, p));
 399: }
 400: 
 401: amatch(s, p)
 402: char *s, *p;
 403: {
 404:     register int cc, scc, k;
 405:     int c, lc;
 406: 
 407:     scc = *s;
 408:     lc = 077777;
 409:     switch (c = *p) {
 410: 
 411:     case '[':
 412:         k = 0;
 413:         while (cc = *++p) {
 414:             switch (cc) {
 415: 
 416:             case ']':
 417:                 if (k)
 418:                     return(amatch(++s, ++p));
 419:                 else
 420:                     return(0);
 421: 
 422:             case '-':
 423:                 k =| lc <= scc & scc <= (cc=p[1]);
 424:             }
 425:             if (scc==(lc=cc)) k++;
 426:         }
 427:         return(0);
 428: 
 429:     case '?':
 430:     caseq:
 431:         if(scc) return(amatch(++s, ++p));
 432:         return(0);
 433:     case '*':
 434:         return(umatch(s, ++p));
 435:     case 0:
 436:         return(!scc);
 437:     }
 438:     if (c==scc) goto caseq;
 439:     return(0);
 440: }
 441: 
 442: umatch(s, p)
 443: char *s, *p;
 444: {
 445:     if(*p==0) return(1);
 446:     while(*s)
 447:         if (amatch(s++,p)) return(1);
 448:     return(0);
 449: }

Defined functions

amatch defined in line 401; used 4 times
and defined in line 198; used 2 times
atime defined in line 217; used 2 times
compstr defined in line 322; used 25 times
descend defined in line 332; used 2 times
doex defined in line 264; used 2 times
e1 defined in line 78; used 2 times
e2 defined in line 90; used 1 times
  • in line 82
e3 defined in line 103; used 2 times
exeq defined in line 243; used 2 times
exp defined in line 66; used 3 times
find defined in line 182; used 2 times
getunum defined in line 294; used 1 times
glob defined in line 207; used 2 times
gmatch defined in line 395; used 1 times
group defined in line 223; used 2 times
links defined in line 226; used 2 times
main defined in line 35; never used
mk defined in line 170; used 15 times
mtime defined in line 214; used 2 times
not defined in line 204; used 2 times
nxtarg defined in line 177; used 8 times
ok defined in line 246; used 2 times
or defined in line 201; used 2 times
perm defined in line 235; used 2 times
print defined in line 210; used 2 times
scomp defined in line 257; used 5 times
size defined in line 229; used 2 times
type defined in line 240; used 2 times
umatch defined in line 442; used 1 times
user defined in line 220; used 2 times

Defined variables

ac defined in line 18; used 2 times
ap defined in line 18; used 10 times
av defined in line 19; used 4 times
fin defined in line 293; used 8 times
fname defined in line 16; used 2 times
nn defined in line 15; used 4 times
node defined in line 14; used 4 times
now defined in line 17; used 3 times
path defined in line 16; used 5 times
pathname defined in line 9; used 3 times
randlast defined in line 8; used 5 times
statb defined in line 33; used 12 times
verbose defined in line 10; used 4 times

Defined struct's

anode defined in line 11; used 24 times
ibuf defined in line 21; never used
Last modified: 1975-05-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1752
Valid CSS Valid XHTML 1.0 Strict