From c08d5d47bda590b06390b919331159d6584b5e07 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Thu, 2 Oct 1980 01:26:36 -0800 Subject: [PATCH] date and time created 80/10/01 17:26:36 by bill SCCS-vsn: usr.bin/find/find.c 4.1 --- usr/src/usr.bin/find/find.c | 709 ++++++++++++++++++++++++++++++++++++ 1 file changed, 709 insertions(+) create mode 100644 usr/src/usr.bin/find/find.c diff --git a/usr/src/usr.bin/find/find.c b/usr/src/usr.bin/find/find.c new file mode 100644 index 0000000000..a44075e48c --- /dev/null +++ b/usr/src/usr.bin/find/find.c @@ -0,0 +1,709 @@ +static char *sccsid = "@(#)find.c 4.1 (Berkeley) %G%"; +/* find COMPILE: cc -o find -s -O -i find.c -lS */ +#include +#include +#include +#include +#define A_DAY 86400L /* a day full of seconds */ +#define EQ(x, y) (strcmp(x, y)==0) + +int Randlast; +char Pathname[200]; + +struct anode { + int (*F)(); + struct anode *L, *R; +} Node[100]; +int Nn; /* number of nodes */ +char *Fname; +long Now; +int Argc, + Ai, + Pi; +char **Argv; +/* cpio stuff */ +int Cpio; +short *Buf, *Dbuf, *Wp; +int Bufsize = 5120; +int Wct = 2560; + +long Newer; + +struct stat Statb; + +struct anode *exp(), + *e1(), + *e2(), + *e3(), + *mk(); +char *nxtarg(); +char Home[128]; +long Blocks; +char *rindex(); +char *sbrk(); +main(argc, argv) char *argv[]; +{ + struct anode *exlist; + int paths; + register char *cp, *sp = 0; + FILE *pwd, *popen(); + + time(&Now); + pwd = popen("pwd", "r"); + fgets(Home, 128, pwd); + pclose(pwd); + Home[strlen(Home) - 1] = '\0'; + Argc = argc; Argv = argv; + if(argc<3) { +usage: fprintf(stderr, "Usage: find path-list predicate-list\n"); + exit(1); + } + for(Ai = paths = 1; Ai < (argc-1); ++Ai, ++paths) + if(*Argv[Ai] == '-' || EQ(Argv[Ai], "(") || EQ(Argv[Ai], "!")) + break; + if(paths == 1) /* no path-list */ + goto usage; + if(!(exlist = exp())) { /* parse and compile the arguments */ + fprintf(stderr, "find: parsing error\n"); + exit(1); + } + if(Ai\n", s); + exit(1); + } + Buf = (short *)sbrk(512); + Wp = Dbuf = (short *)sbrk(5120); + return(mk(cpio, (struct anode *)0, (struct anode *)0)); + } + else if(EQ(a, "-newer")) { + if(stat(b, &Statb) < 0) { + fprintf(stderr, "find: cannot access < %s >\n", b); + exit(1); + } + Newer = Statb.st_mtime; + return mk(newer, (struct anode *)0, (struct anode *)0); + } +err: fprintf(stderr, "find: bad option < %s >\n", a); + exit(1); +} +struct anode *mk(f, l, r) +int (*f)(); +struct anode *l, *r; +{ + Node[Nn].F = f; + Node[Nn].L = l; + Node[Nn].R = r; + return(&(Node[Nn++])); +} + +char *nxtarg() { /* get next arg from command line */ + static strikes = 0; + + if(strikes==3) { + fprintf(stderr, "find: incomplete statement\n"); + exit(1); + } + 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')) + continue; + c1 = endofname; + *c1++ = '/'; + c2 = dp->d_name; + for(i=0; i<14; ++i) + if(*c2) + *c1++ = *c2++; + else + break; + *c1 = '\0'; + if(c1 == endofname) { /* ?? */ + rv = 0; + goto ret; + } + Fname = endofname+1; + if(!descend(name, Fname, exlist)) { + *endofname = '\0'; + chdir(Home); + if(chdir(Pathname) == -1) { + fprintf(stderr, "find: bad directory tree\n"); + exit(1); + } + } + } + } + rv = 1; +ret: + if(dir) + close(dir); + if(chdir("..") == -1) { + *endofname = '\0'; + fprintf(stderr, "find: bad directory <%s>\n", name); + rv = 1; + } + return(rv); +} + +gmatch(s, p) /* string match as in glob */ +register char *s, *p; +{ + if (*s=='.' && *p!='.') return(0); + return amatch(s, p); +} + +amatch(s, p) +register char *s, *p; +{ + register cc; + int scc, k; + int c, lc; + + scc = *s; + lc = 077777; + switch (c = *p) { + + case '[': + k = 0; + while (cc = *++p) { + switch (cc) { + + case ']': + if (k) + return(amatch(++s, ++p)); + else + return(0); + + case '-': + k |= lc <= scc & scc <= (cc=p[1]); + } + if (scc==(lc=cc)) k++; + } + return(0); + + case '?': + caseq: + if(scc) return(amatch(++s, ++p)); + return(0); + case '*': + return(umatch(s, ++p)); + case 0: + return(!scc); + } + if (c==scc) goto caseq; + return(0); +} + +umatch(s, p) +register char *s, *p; +{ + if(*p==0) return(1); + while(*s) + if (amatch(s++, p)) return(1); + return(0); +} + +bwrite(rp, c) +register short *rp; +register c; +{ + register short *wp = Wp; + + c = (c+1) >> 1; + while(c--) { + if(!Wct) { +again: + if(write(Cpio, (char *)Dbuf, Bufsize)<0) { + Cpio = chgreel(1, Cpio); + goto again; + } + Wct = Bufsize >> 1; + wp = Dbuf; + ++Blocks; + } + *wp++ = *rp++; + --Wct; + } + Wp = wp; +} +chgreel(x, fl) +{ + register f; + char str[22]; + FILE *devtty; + struct stat statb; + extern errno; + + fprintf(stderr, "find: errno: %d, ", errno); + fprintf(stderr, "find: can't %s\n", x? "write output": "read input"); + fstat(fl, &statb); + if((statb.st_mode&S_IFMT) != S_IFCHR) + exit(1); +again: + fprintf(stderr, "If you want to go on, type device/file name %s\n", + "when ready"); + devtty = fopen("/dev/tty", "r"); + fgets(str, 20, devtty); + str[strlen(str) - 1] = '\0'; + if(!*str) + exit(1); + close(fl); + if((f = open(str, x? 1: 0)) < 0) { + fprintf(stderr, "That didn't work"); + fclose(devtty); + goto again; + } + return f; +} -- 2.20.1