home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / wu-ftpd-2.4.2b13-MIHS / src / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  13.1 KB  |  818 lines

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