Add original unix v6
This commit is contained in:
@@ -0,0 +1,449 @@
|
||||
/* find -- find files in a pathname.
|
||||
Use of find is documented in /usr/man/man1/find.1 .
|
||||
|
||||
In addition, find has a secret first arg "+" which
|
||||
causes each file name to be printed along with a period
|
||||
if the predicates succeed.
|
||||
*/
|
||||
int randlast;
|
||||
char *pathname;
|
||||
int verbose;
|
||||
struct anode {
|
||||
int (*F)();
|
||||
struct anode *L, *R;
|
||||
} node[100];
|
||||
int nn; /* number of nodes */
|
||||
char *fname, *path;
|
||||
int now[2];
|
||||
int ap, ac;
|
||||
char **av;
|
||||
|
||||
struct ibuf {
|
||||
int idev;
|
||||
int inum;
|
||||
int iflags;
|
||||
char inl;
|
||||
char iuid;
|
||||
char igid;
|
||||
char isize0;
|
||||
char *isize;
|
||||
int iaddr[8];
|
||||
int iatime[2];
|
||||
int imtime[2];
|
||||
} statb;
|
||||
|
||||
main(argc,argv) char *argv[]; {
|
||||
|
||||
struct anode *exlist;
|
||||
int find();
|
||||
|
||||
time(&now);
|
||||
ac = argc; av = argv; ap = 2;
|
||||
pathname = argv[1];
|
||||
if(compstr(argv[1],"+")==0) {
|
||||
verbose++;
|
||||
ap++;
|
||||
pathname = argv[2];
|
||||
} else verbose = 0;
|
||||
argv[argc] = 0;
|
||||
if(argc<3) {
|
||||
printf("Insufficient args\n");
|
||||
exit(9);
|
||||
}
|
||||
if(!(exlist = exp())) { /* parse and compile the arguments */
|
||||
printf("Odd usage\n");
|
||||
exit(9);
|
||||
}
|
||||
if(ap<argc) {
|
||||
printf("Missing conjunction\n");
|
||||
exit(9);
|
||||
}
|
||||
descend(pathname,'f',find,exlist); /* to find files that match */
|
||||
}
|
||||
|
||||
/* compile time functions: priority is exp()<e1()<e2()<e3() */
|
||||
|
||||
struct anode *exp() { /* parse -o ... */
|
||||
int or();
|
||||
int p1;
|
||||
char *na;
|
||||
p1 = e1() /* get left operand */ ;
|
||||
if(compstr(na=nxtarg(),"-o")==0) {
|
||||
randlast--;
|
||||
return(mk(&or,p1,exp()));
|
||||
}
|
||||
else if(*na!=0) --ap;
|
||||
return(p1);
|
||||
}
|
||||
struct anode *e1() { /* parse -a */
|
||||
int and();
|
||||
int p1;
|
||||
char *na;
|
||||
p1 = e2();
|
||||
if(compstr(na=nxtarg(),"-a")==0) {
|
||||
randlast--;
|
||||
return(mk(&and,p1,e1()));
|
||||
}
|
||||
else if(*na!=0) --ap;
|
||||
return(p1);
|
||||
}
|
||||
struct anode *e2() { /* parse not (!) */
|
||||
int not();
|
||||
char *na;
|
||||
if(randlast) {
|
||||
printf("operand follows operand.\n");
|
||||
exit(9);
|
||||
}
|
||||
randlast++;
|
||||
if(compstr(na=nxtarg(),"!")==0)
|
||||
return(mk(¬,e3(),0));
|
||||
else if(*na!=0) --ap;
|
||||
return(e3());
|
||||
}
|
||||
struct anode *e3() { /* parse parens and predicates */
|
||||
int exeq(), ok(), glob(), mtime(), atime(), user(),
|
||||
group(), size(), perm(), links(), print(),
|
||||
type();
|
||||
int p1, i;
|
||||
char *a, *b, s;
|
||||
a = nxtarg();
|
||||
if(compstr(a,"(")==0) {
|
||||
randlast--;
|
||||
p1 = exp();
|
||||
a = nxtarg();
|
||||
if(compstr(a,")")!=0) goto err;
|
||||
return(p1);
|
||||
}
|
||||
else if(compstr(a,"-print")==0) {
|
||||
return(mk(&print,0,0));
|
||||
}
|
||||
b = nxtarg();
|
||||
s = *b;
|
||||
if(s=='+') b++;
|
||||
if(compstr(a,"-name")==0)
|
||||
return(mk(&glob,b,0));
|
||||
else if(compstr(a,"-mtime")==0)
|
||||
return(mk(&mtime,atoi(b),s));
|
||||
else if(compstr(a,"-atime")==0)
|
||||
return(mk(&atime,atoi(b),s));
|
||||
else if(compstr(a,"-user")==0) {
|
||||
if((i=getunum(b)) == -1) {
|
||||
printf("Cannot find user \"%s\"\n",b);
|
||||
exit(9);
|
||||
}
|
||||
return(mk(&user,i,s));
|
||||
}
|
||||
else if(compstr(a,"-group")==0)
|
||||
return(mk(&group,atoi(b),s));
|
||||
else if(compstr(a,"-size")==0)
|
||||
return(mk(&size,atoi(b),s));
|
||||
else if(compstr(a,"-links")==0)
|
||||
return(mk(&links,atoi(b),s));
|
||||
else if(compstr(a,"-perm")==0) {
|
||||
for(i=0; *b ; ++b) {
|
||||
if(*b=='-') continue;
|
||||
i =<< 3;
|
||||
i = i + (*b - '0');
|
||||
}
|
||||
return(mk(&perm,i,s));
|
||||
}
|
||||
else if(compstr(a,"-type")==0) {
|
||||
i = s=='d' ? 040000 :
|
||||
s=='b' ? 060000 :
|
||||
s=='c' ? 020000 :
|
||||
000000;
|
||||
return(mk(&type,i,0));
|
||||
}
|
||||
else if (compstr(a,"-exec")==0) {
|
||||
i = ap - 1;
|
||||
while(compstr(nxtarg(),";")!=0);
|
||||
return(mk(&exeq,i,0));
|
||||
}
|
||||
else if (compstr(a,"-ok")==0) {
|
||||
i = ap - 1;
|
||||
while(compstr(nxtarg(),";")!=0);
|
||||
return(mk(&ok,i,0));
|
||||
}
|
||||
err: printf("Bad option: \"%s\" \"%s\"\n",a,b);
|
||||
exit(9);
|
||||
}
|
||||
struct anode *mk(f,l,r) struct anode *l,*r; { /*make an expression node*/
|
||||
node[nn].F = f;
|
||||
node[nn].L = l;
|
||||
node[nn].R = r;
|
||||
return(&(node[nn++]));
|
||||
}
|
||||
|
||||
nxtarg() { /* get next arg from command line */
|
||||
if(ap>=ac) return("");
|
||||
return(av[ap++]);
|
||||
}
|
||||
|
||||
find(exlist,fullname) /* execute predicat list with current file */
|
||||
struct anode *exlist;
|
||||
char *fullname;
|
||||
{
|
||||
register int i;
|
||||
path = fullname;
|
||||
if(verbose) printf("%s",path);
|
||||
for(i=0;fullname[i];++i)
|
||||
if(fullname[i]=='/') fname = &fullname[i+1];
|
||||
i = (*exlist->F)(exlist);
|
||||
if(verbose)
|
||||
if(i) printf(".\n");
|
||||
else printf("\n");
|
||||
}
|
||||
|
||||
/* execution time functions */
|
||||
and(p) struct anode *p; {
|
||||
return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0);
|
||||
}
|
||||
or(p) struct anode *p; {
|
||||
return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0);
|
||||
}
|
||||
not(p) struct anode *p; {
|
||||
return( !((*p->L->F)(p->L)));
|
||||
}
|
||||
glob(p) struct { int f; char *pat; } *p; {
|
||||
return(gmatch(fname,p->pat));
|
||||
}
|
||||
print() {
|
||||
printf("%s\n",path);
|
||||
return(1);
|
||||
}
|
||||
mtime(p) struct { int f, t, s; } *p; {
|
||||
return(scomp((now[0]-statb.imtime[0])*3/4,p->t,p->s));
|
||||
}
|
||||
atime(p) struct { int f, t, s; } *p; {
|
||||
return(scomp((now[0]-statb.iatime[0])*3/4,p->t,p->s));
|
||||
}
|
||||
user(p) struct { int f, u, s; } *p; {
|
||||
return(scomp(statb.iuid,p->u,p->s));
|
||||
}
|
||||
group(p) struct { int f, u; } *p; {
|
||||
return(p->u == statb.igid);
|
||||
}
|
||||
links(p) struct { int f, link, s; } *p; {
|
||||
return(scomp(statb.inl,p->link,p->s));
|
||||
}
|
||||
size(p) struct { int f, sz, s; } *p; {
|
||||
register int i;
|
||||
i = statb.isize0 << 7;
|
||||
i = i | ((statb.isize>>9) & 0177);
|
||||
return(scomp(i,p->sz,p->s));
|
||||
}
|
||||
perm(p) struct { int f, per, s; } *p; {
|
||||
int i;
|
||||
i = (p->s=='-') ? p->per : 03777; /* '-' means only arg bits */
|
||||
return((statb.iflags & i & 017777) == p->per);
|
||||
}
|
||||
type(p) struct { int f, per, s; } *p; {
|
||||
return((statb.iflags&060000)==p->per);
|
||||
}
|
||||
exeq(p) struct { int f, com; } *p; {
|
||||
return(doex(p->com));
|
||||
}
|
||||
ok(p) struct { int f, com; } *p; {
|
||||
char c; int yes;
|
||||
yes = 0;
|
||||
printf("%s ... %s ...? ",av[p->com],path);
|
||||
if((c=getchar())=='y') yes = 1;
|
||||
while(c!='\n') c = getchar();
|
||||
if(yes) return(doex(p->com));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* support functions */
|
||||
scomp(a,b,s) char s; { /* funny signed compare */
|
||||
if(s == '+')
|
||||
return(a > b);
|
||||
if(s == '-')
|
||||
return(a < (b * -1));
|
||||
return(a == b);
|
||||
}
|
||||
doex(com) {
|
||||
int ccode;
|
||||
int np, i, c;
|
||||
char *nargv[50], *ncom, *na;
|
||||
|
||||
ccode = np = 0;
|
||||
while (na=av[com++]) {
|
||||
if(compstr(na,";")==0) break;
|
||||
if(compstr(na,"{}")==0) nargv[np++] = path;
|
||||
else nargv[np++] = na;
|
||||
}
|
||||
nargv[np] = 0;
|
||||
if (np==0) return(9);
|
||||
if(fork()) /*parent*/ wait(&ccode);
|
||||
else { /*child*/
|
||||
execv(nargv[0], nargv, np);
|
||||
i = 0;
|
||||
ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
while(c=nargv[0][i]) {
|
||||
ncom[9+i++] = c;
|
||||
}
|
||||
ncom[9+i] = '\0';
|
||||
execv(ncom+4, nargv, np);
|
||||
execv(ncom, nargv, np);
|
||||
exit(9);
|
||||
}
|
||||
return(ccode ? 0:1);
|
||||
}
|
||||
|
||||
char fin[518];
|
||||
getunum(s) char *s; { /* find username in /etc/passwd & return num. */
|
||||
int i;
|
||||
char str[20], *sp, c;
|
||||
i = -1;
|
||||
fin[0] = open("/etc/passwd",0);
|
||||
while(c = getchar()) {
|
||||
if(c=='\n') {
|
||||
sp = str;
|
||||
while((*sp = getchar()) != ':')
|
||||
if(! *sp++) goto RET;
|
||||
*sp = '\0';
|
||||
if(compstr(str,s)==0) {
|
||||
while((c=getchar()) != ':')
|
||||
if(! c) goto RET;
|
||||
sp = str;
|
||||
while((*sp = getchar()) != ':') sp++;
|
||||
*sp = '\0';
|
||||
i = atoi(str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
RET:
|
||||
close(fin);
|
||||
fin[0] = 0;
|
||||
return(i);
|
||||
}
|
||||
|
||||
compstr(s1,s2) char s1[], s2[]; { /* compare strings: */
|
||||
register char *c1, *c2;
|
||||
c1 = s1; c2 = s2;
|
||||
while(*c1 == *c2)
|
||||
if(*c1++ == '\0')
|
||||
return(0); /* s1 == s2 */
|
||||
else c2++;
|
||||
return(*c1 > *c2 ? 1 : -1);
|
||||
}
|
||||
|
||||
int descend(name,goal,func,arg)
|
||||
int (*func)();
|
||||
char *name, goal;
|
||||
{
|
||||
int dir /* open directory */, offset /* in directory */;
|
||||
int dsize, top;
|
||||
struct {
|
||||
int dinode;
|
||||
char dname[14];
|
||||
} dentry[32];
|
||||
register int i, j, k;
|
||||
char aname[128];
|
||||
|
||||
if(stat(name,&statb)<0) {
|
||||
printf("--bad status %s\n",name);
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
if((statb.iflags&060000)!=040000){ /*not a directory*/
|
||||
/*
|
||||
if(goal=='f'||goal=='b') /* search goal for files */
|
||||
/*
|
||||
(*func)(arg,name);
|
||||
return(1);
|
||||
} else if(goal=='d' || goal=='b') /* search goal is directories */
|
||||
/*
|
||||
(*func)(arg,name);
|
||||
*/
|
||||
(*func)(arg,name);
|
||||
if((statb.iflags&060000)!=040000)
|
||||
return(1);
|
||||
|
||||
top = statb.isize;
|
||||
for(offset=0 ; offset < top ; offset =+ 512) { /* each block */
|
||||
dsize = 512<(top-offset) ? 512 : (top-offset);
|
||||
if((dir=open(name,0))<0) {
|
||||
printf("--cannot open %s\n",name);
|
||||
return(0);
|
||||
}
|
||||
if(offset) seek(dir,offset,0);
|
||||
if(read(dir,&dentry,dsize)<0) {
|
||||
printf("--cannot read %s\n",name);
|
||||
return(0);
|
||||
}
|
||||
close(dir);
|
||||
for(i = 0; i < (dsize>>4); ++i) { /* each dir. entry */
|
||||
if(dentry[i].dinode==0 ||
|
||||
compstr(dentry[i].dname,".")==0 ||
|
||||
compstr(dentry[i].dname,"..")==0)
|
||||
continue;
|
||||
if (dentry[i].dinode == -1) break;
|
||||
for(j=0;aname[j]=name[j];++j);
|
||||
if(aname[j-1]!='/') aname[j++] = '/';
|
||||
for(k=0; (aname[j++]=dentry[i].dname[k]) &&
|
||||
k<13; ++k);
|
||||
aname[j] = '\0';
|
||||
if(descend(aname,goal,func,arg)==0)
|
||||
printf("--%s\n",name);
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
gmatch(s, p) /* string match as in glob */
|
||||
char *s, *p; {
|
||||
if (*s=='.' && *p!='.') return(0);
|
||||
return(amatch(s, p));
|
||||
}
|
||||
|
||||
amatch(s, p)
|
||||
char *s, *p;
|
||||
{
|
||||
register int cc, 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)
|
||||
char *s, *p;
|
||||
{
|
||||
if(*p==0) return(1);
|
||||
while(*s)
|
||||
if (amatch(s++,p)) return(1);
|
||||
return(0);
|
||||
}
|
||||
Reference in New Issue
Block a user