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