home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / ftp / glob.c,v < prev    next >
Encoding:
Text File  |  1994-05-23  |  11.4 KB  |  707 lines

  1. head    1.1;
  2. access;
  3. symbols;
  4. locks
  5.     rzsfl:1.1; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.1
  10. date    94.05.23.09.03.42;    author rzsfl;    state Exp;
  11. branches;
  12. next    ;
  13.  
  14.  
  15. desc
  16. @Original
  17. @
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*
  26.  * Copyright (c) 1980 Regents of the University of California.
  27.  * All rights reserved.
  28.  *
  29.  * Redistribution and use in source and binary forms, with or without
  30.  * modification, are permitted provided that the following conditions
  31.  * are met:
  32.  * 1. Redistributions of source code must retain the above copyright
  33.  *    notice, this list of conditions and the following disclaimer.
  34.  * 2. Redistributions in binary form must reproduce the above copyright
  35.  *    notice, this list of conditions and the following disclaimer in the
  36.  *    documentation and/or other materials provided with the distribution.
  37.  * 3. All advertising materials mentioning features or use of this software
  38.  *    must display the following acknowledgement:
  39.  *    This product includes software developed by the University of
  40.  *    California, Berkeley and its contributors.
  41.  * 4. Neither the name of the University nor the names of its contributors
  42.  *    may be used to endorse or promote products derived from this software
  43.  *    without specific prior written permission.
  44.  *
  45.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  46.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  47.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  48.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  49.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  50.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  51.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  52.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  53.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  54.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  55.  * SUCH DAMAGE.
  56.  */
  57.  
  58. #ifndef lint
  59. /*static char sccsid[] = "from: @@(#)glob.c    5.9 (Berkeley) 2/25/91";*/
  60. static char rcsid[] = "$Id: glob.c,v 1.2 1993/08/01 18:15:27 mycroft Exp $";
  61. #endif /* not lint */
  62.  
  63. /*
  64.  * C-shell glob for random programs.
  65.  */
  66.  
  67. #include <sys/param.h>
  68. #include <sys/stat.h>
  69. #include <dirent.h>
  70.  
  71. #include <pwd.h>
  72. #include <errno.h>
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <string.h>
  76.  
  77. #define    QUOTE 0200
  78. #define    TRIM 0177
  79. #define    eq(a,b)        (strcmp(a, b)==0)
  80. #define    GAVSIZ        (NCARGS/6)
  81. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  82.  
  83. static    char **gargv;        /* Pointer to the (stack) arglist */
  84. static    int gargc;        /* Number args in gargv */
  85. static    int gnleft;
  86. static    short gflag;
  87. static    int tglob();
  88. char    **ftpglob();
  89. char    *globerr;
  90. char    *home;
  91. extern    int errno;
  92. static    char *strspl(), *strend();
  93. char    **copyblk();
  94.  
  95. static void acollect(), addpath(), collect(), expand(), Gcat();
  96. static void ginit(), matchdir(), rscan(), sort();
  97. static int amatch(), execbrc(), match();
  98.  
  99. static    int globcnt;
  100.  
  101. char    *globchars = "`{[*?";
  102.  
  103. static    char *gpath, *gpathp, *lastgpathp;
  104. static    int globbed;
  105. static    char *entp;
  106. static    char **sortbas;
  107.  
  108. char **
  109. ftpglob(v)
  110.     register char *v;
  111. {
  112.     char agpath[BUFSIZ];
  113.     char *agargv[GAVSIZ];
  114.     char *vv[2];
  115.     vv[0] = v;
  116.     vv[1] = 0;
  117.     gflag = 0;
  118.     rscan(vv, tglob);
  119.     if (gflag == 0)
  120.         return (copyblk(vv));
  121.  
  122.     globerr = 0;
  123.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  124.     lastgpathp = &gpath[sizeof agpath - 2];
  125.     ginit(agargv); globcnt = 0;
  126.     collect(v);
  127.     if (globcnt == 0 && (gflag&1)) {
  128.         blkfree(gargv), gargv = 0;
  129.         return (0);
  130.     } else
  131.         return (gargv = copyblk(gargv));
  132. }
  133.  
  134. static void
  135. ginit(agargv)
  136.     char **agargv;
  137. {
  138.  
  139.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  140.     gnleft = NCARGS - 4;
  141. }
  142.  
  143. static void
  144. collect(as)
  145.     register char *as;
  146. {
  147.     if (eq(as, "{") || eq(as, "{}")) {
  148.         Gcat(as, "");
  149.         sort();
  150.     } else
  151.         acollect(as);
  152. }
  153.  
  154. static void
  155. acollect(as)
  156.     register char *as;
  157. {
  158.     register int ogargc = gargc;
  159.  
  160.     gpathp = gpath; *gpathp = 0; globbed = 0;
  161.     expand(as);
  162.     if (gargc != ogargc)
  163.         sort();
  164. }
  165.  
  166. static void
  167. sort()
  168. {
  169.     register char **p1, **p2, *c;
  170.     char **Gvp = &gargv[gargc];
  171.  
  172.     p1 = sortbas;
  173.     while (p1 < Gvp-1) {
  174.         p2 = p1;
  175.         while (++p2 < Gvp)
  176.             if (strcmp(*p1, *p2) > 0)
  177.                 c = *p1, *p1 = *p2, *p2 = c;
  178.         p1++;
  179.     }
  180.     sortbas = Gvp;
  181. }
  182.  
  183. static void
  184. expand(as)
  185.     char *as;
  186. {
  187.     register char *cs;
  188.     register char *sgpathp, *oldcs;
  189.     struct stat stb;
  190.  
  191.     sgpathp = gpathp;
  192.     cs = as;
  193.     if (*cs == '~' && gpathp == gpath) {
  194.         addpath('~');
  195.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  196.             addpath(*cs++);
  197.         if (!*cs || *cs == '/') {
  198.             if (gpathp != gpath + 1) {
  199.                 *gpathp = 0;
  200.                 if (gethdir(gpath + 1))
  201.                     globerr = "Unknown user name after ~";
  202.                 (void) strcpy(gpath, gpath + 1);
  203.             } else
  204.                 (void) strcpy(gpath, home);
  205.             gpathp = strend(gpath);
  206.         }
  207.     }
  208.     while (!any(*cs, globchars)) {
  209.         if (*cs == 0) {
  210.             if (!globbed)
  211.                 Gcat(gpath, "");
  212.             else if (stat(gpath, &stb) >= 0) {
  213.                 Gcat(gpath, "");
  214.                 globcnt++;
  215.             }
  216.             goto endit;
  217.         }
  218.         addpath(*cs++);
  219.     }
  220.     oldcs = cs;
  221.     while (cs > as && *cs != '/')
  222.         cs--, gpathp--;
  223.     if (*cs == '/')
  224.         cs++, gpathp++;
  225.     *gpathp = 0;
  226.     if (*oldcs == '{') {
  227.         (void) execbrc(cs, ((char *)0));
  228.         return;
  229.     }
  230.     matchdir(cs);
  231. endit:
  232.     gpathp = sgpathp;
  233.     *gpathp = 0;
  234. }
  235.  
  236. static void
  237. matchdir(pattern)
  238.     char *pattern;
  239. {
  240.     struct stat stb;
  241.     register struct dirent *dp;
  242.     DIR *dirp;
  243.  
  244.     dirp = opendir(gpath);
  245.     if (dirp == NULL) {
  246.         if (globbed)
  247.             return;
  248.         goto patherr2;
  249.     }
  250.     if (fstat(dirp->dd_fd, &stb) < 0)
  251.         goto patherr1;
  252.     if (!isdir(stb)) {
  253.         errno = ENOTDIR;
  254.         goto patherr1;
  255.     }
  256.     while ((dp = readdir(dirp)) != NULL) {
  257.         if (dp->d_ino == 0)
  258.             continue;
  259.         if (match(dp->d_name, pattern)) {
  260.             Gcat(gpath, dp->d_name);
  261.             globcnt++;
  262.         }
  263.     }
  264.     closedir(dirp);
  265.     return;
  266.  
  267. patherr1:
  268.     closedir(dirp);
  269. patherr2:
  270.     globerr = "Bad directory components";
  271. }
  272.  
  273. static int
  274. execbrc(p, s)
  275.     char *p, *s;
  276. {
  277.     char restbuf[BUFSIZ + 2];
  278.     register char *pe, *pm, *pl;
  279.     int brclev = 0;
  280.     char *lm, savec, *sgpathp;
  281.  
  282.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  283.         continue;
  284.     for (pe = ++p; *pe; pe++)
  285.     switch (*pe) {
  286.  
  287.     case '{':
  288.         brclev++;
  289.         continue;
  290.  
  291.     case '}':
  292.         if (brclev == 0)
  293.             goto pend;
  294.         brclev--;
  295.         continue;
  296.  
  297.     case '[':
  298.         for (pe++; *pe && *pe != ']'; pe++)
  299.             continue;
  300.         continue;
  301.     }
  302. pend:
  303.     brclev = 0;
  304.     for (pl = pm = p; pm <= pe; pm++)
  305.     switch (*pm & (QUOTE|TRIM)) {
  306.  
  307.     case '{':
  308.         brclev++;
  309.         continue;
  310.  
  311.     case '}':
  312.         if (brclev) {
  313.             brclev--;
  314.             continue;
  315.         }
  316.         goto doit;
  317.  
  318.     case ','|QUOTE:
  319.     case ',':
  320.         if (brclev)
  321.             continue;
  322. doit:
  323.         savec = *pm;
  324.         *pm = 0;
  325.         (void) strcpy(lm, pl);
  326.         (void) strcat(restbuf, pe + 1);
  327.         *pm = savec;
  328.         if (s == 0) {
  329.             sgpathp = gpathp;
  330.             expand(restbuf);
  331.             gpathp = sgpathp;
  332.             *gpathp = 0;
  333.         } else if (amatch(s, restbuf))
  334.             return (1);
  335.         sort();
  336.         pl = pm + 1;
  337.         if (brclev)
  338.             return (0);
  339.         continue;
  340.  
  341.     case '[':
  342.         for (pm++; *pm && *pm != ']'; pm++)
  343.             continue;
  344.         if (!*pm)
  345.             pm--;
  346.         continue;
  347.     }
  348.     if (brclev)
  349.         goto doit;
  350.     return (0);
  351. }
  352.  
  353. static int
  354. match(s, p)
  355.     char *s, *p;
  356. {
  357.     register int c;
  358.     register char *sentp;
  359.     char sglobbed = globbed;
  360.  
  361.     if (*s == '.' && *p != '.')
  362.         return (0);
  363.     sentp = entp;
  364.     entp = s;
  365.     c = amatch(s, p);
  366.     entp = sentp;
  367.     globbed = sglobbed;
  368.     return (c);
  369. }
  370.  
  371. static int
  372. amatch(s, p)
  373.     register char *s, *p;
  374. {
  375.     register int scc;
  376.     int ok, lc;
  377.     char *sgpathp;
  378.     struct stat stb;
  379.     int c, cc;
  380.  
  381.     globbed = 1;
  382.     for (;;) {
  383.         scc = *s++ & TRIM;
  384.         switch (c = *p++) {
  385.  
  386.         case '{':
  387.             return (execbrc(p - 1, s - 1));
  388.  
  389.         case '[':
  390.             ok = 0;
  391.             lc = 077777;
  392.             while (cc = *p++) {
  393.                 if (cc == ']') {
  394.                     if (ok)
  395.                         break;
  396.                     return (0);
  397.                 }
  398.                 if (cc == '-') {
  399.                     if (lc <= scc && scc <= *p++)
  400.                         ok++;
  401.                 } else
  402.                     if (scc == (lc = cc))
  403.                         ok++;
  404.             }
  405.             if (cc == 0)
  406.                 if (ok)
  407.                     p--;
  408.                 else
  409.                     return 0;
  410.             continue;
  411.  
  412.         case '*':
  413.             if (!*p)
  414.                 return (1);
  415.             if (*p == '/') {
  416.                 p++;
  417.                 goto slash;
  418.             }
  419.             s--;
  420.             do {
  421.                 if (amatch(s, p))
  422.                     return (1);
  423.             } while (*s++);
  424.             return (0);
  425.  
  426.         case 0:
  427.             return (scc == 0);
  428.  
  429.         default:
  430.             if (c != scc)
  431.                 return (0);
  432.             continue;
  433.  
  434.         case '?':
  435.             if (scc == 0)
  436.                 return (0);
  437.             continue;
  438.  
  439.         case '/':
  440.             if (scc)
  441.                 return (0);
  442. slash:
  443.             s = entp;
  444.             sgpathp = gpathp;
  445.             while (*s)
  446.                 addpath(*s++);
  447.             addpath('/');
  448.             if (stat(gpath, &stb) == 0 && isdir(stb))
  449.                 if (*p == 0) {
  450.                     Gcat(gpath, "");
  451.                     globcnt++;
  452.                 } else
  453.                     expand(p);
  454.             gpathp = sgpathp;
  455.             *gpathp = 0;
  456.             return (0);
  457.         }
  458.     }
  459. }
  460.  
  461. static
  462. Gmatch(s, p)
  463.     register char *s, *p;
  464. {
  465.     register int scc;
  466.     int ok, lc;
  467.     int c, cc;
  468.  
  469.     for (;;) {
  470.         scc = *s++ & TRIM;
  471.         switch (c = *p++) {
  472.  
  473.         case '[':
  474.             ok = 0;
  475.             lc = 077777;
  476.             while (cc = *p++) {
  477.                 if (cc == ']') {
  478.                     if (ok)
  479.                         break;
  480.                     return (0);
  481.                 }
  482.                 if (cc == '-') {
  483.                     if (lc <= scc && scc <= *p++)
  484.                         ok++;
  485.                 } else
  486.                     if (scc == (lc = cc))
  487.                         ok++;
  488.             }
  489.             if (cc == 0)
  490.                 if (ok)
  491.                     p--;
  492.                 else
  493.                     return 0;
  494.             continue;
  495.  
  496.         case '*':
  497.             if (!*p)
  498.                 return (1);
  499.             for (s--; *s; s++)
  500.                 if (Gmatch(s, p))
  501.                     return (1);
  502.             return (0);
  503.  
  504.         case 0:
  505.             return (scc == 0);
  506.  
  507.         default:
  508.             if ((c & TRIM) != scc)
  509.                 return (0);
  510.             continue;
  511.  
  512.         case '?':
  513.             if (scc == 0)
  514.                 return (0);
  515.             continue;
  516.  
  517.         }
  518.     }
  519. }
  520.  
  521. static void
  522. Gcat(s1, s2)
  523.     register char *s1, *s2;
  524. {
  525.     register int len = strlen(s1) + strlen(s2) + 1;
  526.  
  527.     if (len >= gnleft || gargc >= GAVSIZ - 1)
  528.         globerr = "Arguments too long";
  529.     else {
  530.         gargc++;
  531.         gnleft -= len;
  532.         gargv[gargc] = 0;
  533.         gargv[gargc - 1] = strspl(s1, s2);
  534.     }
  535. }
  536.  
  537. static void
  538. addpath(c)
  539.     char c;
  540. {
  541.  
  542.     if (gpathp >= lastgpathp)
  543.         globerr = "Pathname too long";
  544.     else {
  545.         *gpathp++ = c;
  546.         *gpathp = 0;
  547.     }
  548. }
  549.  
  550. static void
  551. rscan(t, f)
  552.     register char **t;
  553.     int (*f)();
  554. {
  555.     register char *p, c;
  556.  
  557.     while (p = *t++) {
  558.         if (f == tglob)
  559.             if (*p == '~')
  560.                 gflag |= 2;
  561.             else if (eq(p, "{") || eq(p, "{}"))
  562.                 continue;
  563.         while (c = *p++)
  564.             (*f)(c);
  565.     }
  566. }
  567. /*
  568. static
  569. scan(t, f)
  570.     register char **t;
  571.     int (*f)();
  572. {
  573.     register char *p, c;
  574.  
  575.     while (p = *t++)
  576.         while (c = *p)
  577.             *p++ = (*f)(c);
  578. } */
  579.  
  580. static
  581. tglob(c)
  582.     register char c;
  583. {
  584.  
  585.     if (any(c, globchars))
  586.         gflag |= c == '{' ? 2 : 1;
  587.     return (c);
  588. }
  589. /*
  590. static
  591. trim(c)
  592.     char c;
  593. {
  594.  
  595.     return (c & TRIM);
  596. } */
  597.  
  598.  
  599. letter(c)
  600.     register char c;
  601. {
  602.  
  603.     return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  604. }
  605.  
  606. digit(c)
  607.     register char c;
  608. {
  609.  
  610.     return (c >= '0' && c <= '9');
  611. }
  612.  
  613. any(c, s)
  614.     register int c;
  615.     register char *s;
  616. {
  617.  
  618.     while (*s)
  619.         if (*s++ == c)
  620.             return(1);
  621.     return(0);
  622. }
  623. blklen(av)
  624.     register char **av;
  625. {
  626.     register int i = 0;
  627.  
  628.     while (*av++)
  629.         i++;
  630.     return (i);
  631. }
  632.  
  633. char **
  634. blkcpy(oav, bv)
  635.     char **oav;
  636.     register char **bv;
  637. {
  638.     register char **av = oav;
  639.  
  640.     while (*av++ = *bv++)
  641.         continue;
  642.     return (oav);
  643. }
  644.  
  645. blkfree(av0)
  646.     char **av0;
  647. {
  648.     register char **av = av0;
  649.  
  650.     while (*av)
  651.         free(*av++);
  652. }
  653.  
  654. static
  655. char *
  656. strspl(cp, dp)
  657.     register char *cp, *dp;
  658. {
  659.     register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  660.  
  661.     if (ep == (char *)0)
  662.         fatal("Out of memory");
  663.     (void) strcpy(ep, cp);
  664.     (void) strcat(ep, dp);
  665.     return (ep);
  666. }
  667.  
  668. char **
  669. copyblk(v)
  670.     register char **v;
  671. {
  672.     register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  673.                         sizeof(char **)));
  674.     if (nv == (char **)0)
  675.         fatal("Out of memory");
  676.  
  677.     return (blkcpy(nv, v));
  678. }
  679.  
  680. static
  681. char *
  682. strend(cp)
  683.     register char *cp;
  684. {
  685.  
  686.     while (*cp)
  687.         cp++;
  688.     return (cp);
  689. }
  690. /*
  691.  * Extract a home directory from the password file
  692.  * The argument points to a buffer where the name of the
  693.  * user whose home directory is sought is currently.
  694.  * We write the home directory of the user back there.
  695.  */
  696. gethdir(home)
  697.     char *home;
  698. {
  699.     register struct passwd *pp = getpwnam(home);
  700.  
  701.     if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
  702.         return (1);
  703.     (void) strcpy(home, pp->pw_dir);
  704.     return (0);
  705. }
  706. @
  707.