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