home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / 2014.11.minnie.tuhs.org.tar / minnie.tuhs.org / UnixArchive / PDP-11 / Trees / V6 / usr / source / s1 / find.c < prev    next >
C/C++ Source or Header  |  1975-05-14  |  9KB  |  450 lines

  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(¬,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. }
  450.