- if(Ai>=Argc) {
- strikes++;
- Ai = Argc + 1;
- return("");
- }
- return(Argv[Ai++]);
-}
-
-/* execution time functions */
-and(p)
-register struct anode *p;
-{
- return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0);
-}
-or(p)
-register struct anode *p;
-{
- return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0);
-}
-not(p)
-register struct anode *p;
-{
- return( !((*p->L->F)(p->L)));
-}
-glob(p)
-register struct { int f; char *pat; } *p;
-{
- return(gmatch(Fname, p->pat));
-}
-print()
-{
- puts(Pathname);
- return(1);
-}
-mtime(p)
-register struct { int f, t, s; } *p;
-{
- return(scomp((int)((Now - Statb.st_mtime) / A_DAY), p->t, p->s));
-}
-atime(p)
-register struct { int f, t, s; } *p;
-{
- return(scomp((int)((Now - Statb.st_atime) / A_DAY), p->t, p->s));
-}
-user(p)
-register struct { int f, u, s; } *p;
-{
- return(scomp(Statb.st_uid, p->u, p->s));
-}
-ino(p)
-register struct { int f, u, s; } *p;
-{
- return(scomp((int)Statb.st_ino, p->u, p->s));
-}
-group(p)
-register struct { int f, u; } *p;
-{
- return(p->u == Statb.st_gid);
-}
-links(p)
-register struct { int f, link, s; } *p;
-{
- return(scomp(Statb.st_nlink, p->link, p->s));
-}
-size(p)
-register struct { int f, sz, s; } *p;
-{
- return(scomp((int)((Statb.st_size+511)>>9), p->sz, p->s));
-}
-perm(p)
-register struct { int f, per, s; } *p;
-{
- register i;
- i = (p->s=='-') ? p->per : 07777; /* '-' means only arg bits */
- return((Statb.st_mode & i & 07777) == p->per);
-}
-type(p)
-register struct { int f, per, s; } *p;
-{
- return((Statb.st_mode&S_IFMT)==p->per);
-}
-exeq(p)
-register struct { int f, com; } *p;
-{
- fflush(stdout); /* to flush possible `-print' */
- return(doex(p->com));
-}
-ok(p)
-struct { int f, com; } *p;
-{
- char c; int yes;
- yes = 0;
- fflush(stdout); /* to flush possible `-print' */
- fprintf(stderr, "< %s ... %s > ? ", Argv[p->com], Pathname);
- fflush(stderr);
- if((c=getchar())=='y') yes = 1;
- while(c!='\n') c = getchar();
- if(yes) return(doex(p->com));
- return(0);
-}
-
-#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];}
-union { long l; short s[2]; char c[4]; } U;
-long mklong(v)
-short v[];
-{
- U.l = 1;
- if(U.c[0] /* VAX */)
- U.s[0] = v[1], U.s[1] = v[0];
- else
- U.s[0] = v[0], U.s[1] = v[1];
- return U.l;
-}
-cpio()
-{
-#define MAGIC 070707
- struct header {
- short h_magic,
- h_dev,
- h_ino,
- h_mode,
- h_uid,
- h_gid,
- h_nlink,
- h_rdev;
- short h_mtime[2];
- short h_namesize;
- short h_filesize[2];
- char h_name[256];
- } hdr;
- register ifile, ct;
- static long fsz;
- register i;
-
- hdr.h_magic = MAGIC;
- strcpy(hdr.h_name, !strncmp(Pathname, "./", 2)? Pathname+2: Pathname);
- hdr.h_namesize = strlen(hdr.h_name) + 1;
- hdr.h_uid = Statb.st_uid;
- hdr.h_gid = Statb.st_gid;
- hdr.h_dev = Statb.st_dev;
- hdr.h_ino = Statb.st_ino;
- hdr.h_mode = Statb.st_mode;
- MKSHORT(hdr.h_mtime, Statb.st_mtime);
- hdr.h_nlink = Statb.st_nlink;
- fsz = hdr.h_mode & S_IFREG? Statb.st_size: 0L;
- MKSHORT(hdr.h_filesize, fsz);
- hdr.h_rdev = Statb.st_rdev;
- if(EQ(hdr.h_name, "TRAILER!!!")) {
- bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
- for(i = 0; i < 10; ++i)
- bwrite(Buf, 512);
- return;
- }
- if(!mklong(hdr.h_filesize))
- return;
- if((ifile = open(Fname, 0)) < 0) {
-cerror:
- fprintf(stderr, "find: cannot copy < %s >\n", hdr.h_name);
- return;
- }
- bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
- for(fsz = mklong(hdr.h_filesize); fsz > 0; fsz -= 512) {
- ct = fsz>512? 512: fsz;
- if(read(ifile, (char *)Buf, ct) < 0)
- goto cerror;
- bwrite(Buf, ct);
- }
- close(ifile);
- return;
-}
-newer()
-{
- return Statb.st_mtime > Newer;
-}
-
-/* support functions */
-scomp(a, b, s) /* funny signed compare */
-register a, b;
-register char s;
-{
- if(s == '+')
- return(a > b);
- if(s == '-')
- return(a < (b * -1));
- return(a == b);
-}
-
-doex(com)
-{
- register np;
- register char *na;
- static char *nargv[50];
- static ccode;
-
- ccode = np = 0;
- while (na=Argv[com++]) {
- if(strcmp(na, ";")==0) break;
- if(strcmp(na, "{}")==0) nargv[np++] = Pathname;
- else nargv[np++] = na;
- }
- nargv[np] = 0;
- if (np==0) return(9);
- if(fork()) /*parent*/ wait(&ccode);
- else { /*child*/
- chdir(Home);
- execvp(nargv[0], nargv, np);
- exit(1);
- }
- return(ccode ? 0:1);
-}
-
-getunum(f, s) char *f, *s; { /* find user/group name and return number */
- register i;
- register char *sp;
- register c;
- char str[20];
- FILE *pin;
-
- i = -1;
- pin = fopen(f, "r");
- c = '\n'; /* prime with a CR */
- do {
- if(c=='\n') {
- sp = str;
- while((c = *sp++ = getc(pin)) != ':')
- if(c == EOF) goto RET;
- *--sp = '\0';
- if(EQ(str, s)) {
- while((c=getc(pin)) != ':')
- if(c == EOF) goto RET;
- sp = str;
- while((*sp = getc(pin)) != ':') sp++;
- *sp = '\0';
- i = atoi(str);
- goto RET;
- }
- }
- } while((c = getc(pin)) != EOF);
- RET:
- fclose(pin);
- return(i);
-}
-
-descend(name, fname, exlist)
-struct anode *exlist;
-char *name, *fname;
-{
- int dir = 0, /* open directory */
- offset,
- dsize,
- entries,
- dirsize;
- struct direct dentry[BUFSIZ / sizeof (struct direct)];
- register struct direct *dp;
- register char *c1, *c2;
- int i;
- int rv = 0;
- char *endofname;
-
- if(stat(fname, &Statb)<0) {
- fprintf(stderr, "find: bad status < %s >\n", name);
- return(0);
- }
- (*exlist->F)(exlist);
- if((Statb.st_mode&S_IFMT)!=S_IFDIR)
- return(1);
-
- for(c1 = name; *c1; ++c1);
- if(*(c1-1) == '/')
- --c1;
- endofname = c1;
- dirsize = Statb.st_size;
-
- if(chdir(fname) == -1)
- return(0);
- for(offset=0 ; offset < dirsize ; offset += BUFSIZ) { /* each block */
- dsize = BUFSIZ<(dirsize-offset)? BUFSIZ: (dirsize-offset);
- if(!dir) {
- if((dir=open(".", 0))<0) {
- fprintf(stderr, "find: cannot open < %s >\n",
- name);
- rv = 0;
- goto ret;
- }
- if(offset) lseek(dir, (long)offset, 0);
- if(read(dir, (char *)dentry, dsize)<0) {
- fprintf(stderr, "find: cannot read < %s >\n",
- name);
- rv = 0;
- goto ret;
- }
- if(dir > 10) {
- close(dir);
- dir = 0;
- }
- } else
- if(read(dir, (char *)dentry, dsize)<0) {
- fprintf(stderr, "find: cannot read < %s >\n",
- name);
- rv = 0;
- goto ret;
- }
- for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) { /* each directory entry */
- if(dp->d_ino==0
- || (dp->d_name[0]=='.' && dp->d_name[1]=='\0')
- || (dp->d_name[0]=='.' && dp->d_name[1]=='.' && dp->d_name[2]=='\0'))
+
+ /*
+ * the command line has been completely processed into a search plan
+ * except for the (, ), !, and -o operators. Rearrange the plan so
+ * that the portions of the plan which are affected by the operators
+ * are moved into operator nodes themselves. For example:
+ *
+ * [!]--> [-name foo]--> [-print]
+ *
+ * becomes
+ *
+ * [! [-name foo] ]--> [-print]
+ *
+ * and
+ *
+ * [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
+ *
+ * becomes
+ *
+ * [expr [-depth]-->[-name foo] ]--> [-print]
+ *
+ * operators are handled in order of precedence.
+ */
+
+ plan = paren_squish(plan); /* ()'s */
+ plan = not_squish(plan); /* !'s */
+ plan = or_squish(plan); /* -o's */
+ return (plan);
+}
+
+FTS *tree; /* pointer to top of FTS hierarchy */
+
+/*
+ * find_execute --
+ * take a search plan and an array of search paths and executes the plan
+ * over all FTSENT's returned for the given search paths.
+ */
+int
+find_execute(plan, paths)
+ PLAN *plan; /* search plan */
+ char **paths; /* array of pathnames to traverse */
+{
+ register FTSENT *entry;
+ PLAN *p;
+ int rval;
+
+ if ((tree = fts_open(paths, ftsoptions, (int (*)())NULL)) == NULL)
+ err(1, "ftsopen");
+
+ for (rval = 0; (entry = fts_read(tree)) != NULL;) {
+ switch (entry->fts_info) {
+ case FTS_D:
+ if (isdepth)