home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / ncftp-1.5.6 / src / rcs / glob.c,v < prev    next >
Encoding:
Text File  |  1994-06-29  |  10.8 KB  |  727 lines

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