home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / csh / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-05  |  18.8 KB  |  942 lines

  1. /*-
  2.  * Copyright (c) 1980, 1991 The 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[] = "@(#)glob.c    5.35 (Berkeley) 2/5/92";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <glob.h>
  40. #include <errno.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #if __STDC__
  45. # include <stdarg.h>
  46. #else
  47. # include <varargs.h>
  48. #endif
  49.  
  50. #include "csh.h"
  51. #include "extern.h"
  52.  
  53. static int noglob;
  54. static int pargsiz, gargsiz;
  55.  
  56. /*
  57.  * Values for gflag
  58.  */
  59. #define    G_NONE    0        /* No globbing needed            */
  60. #define    G_GLOB    1        /* string contains *?[] characters    */
  61. #define    G_CSH    2        /* string contains ~`{ characters    */
  62.  
  63. #define    GLOBSPACE    100    /* Alloc increment            */
  64.  
  65. #define LBRC '{'
  66. #define RBRC '}'
  67. #define LBRK '['
  68. #define RBRK ']'
  69. #define EOS '\0'
  70.  
  71. Char  **gargv = NULL;
  72. long    gargc = 0;
  73. Char  **pargv = NULL;
  74. long    pargc = 0;
  75.  
  76. /*
  77.  * globbing is now done in two stages. In the first pass we expand
  78.  * csh globbing idioms ~`{ and then we proceed doing the normal
  79.  * globbing if needed ?*[
  80.  *
  81.  * Csh type globbing is handled in globexpand() and the rest is
  82.  * handled in glob() which is part of the 4.4BSD libc.
  83.  *
  84.  */
  85. static Char    *globtilde __P((Char **, Char *));
  86. static Char    **libglob __P((Char **));
  87. static Char    **globexpand __P((Char **));
  88. static int    globbrace __P((Char *, Char *, Char ***));
  89. static void    expbrace __P((Char ***, Char ***, int));
  90. static int    pmatch __P((Char *, Char *));
  91. static void    pword __P((void));
  92. static void    psave __P((int));
  93. static void    backeval __P((Char *, bool));
  94.  
  95.  
  96. static Char *
  97. globtilde(nv, s)
  98.     Char  **nv, *s;
  99. {
  100.     Char    gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
  101.  
  102.     gstart = gbuf;
  103.     *gstart++ = *s++;
  104.     u = s;
  105.     for (b = gstart, e = &gbuf[MAXPATHLEN - 1];
  106.      *s && *s != '/' && *s != ':' && b < e;
  107.      *b++ = *s++)
  108.      continue;
  109.     *b = EOS;
  110.     if (gethdir(gstart)) {
  111.     blkfree(nv);
  112.     if (*gstart)
  113.         stderror(ERR_UNKUSER, vis_str(gstart));
  114.     else
  115.         stderror(ERR_NOHOME);
  116.     }
  117.     b = &gstart[Strlen(gstart)];
  118.     while (*s)
  119.     *b++ = *s++;
  120.     *b = EOS;
  121.     --u;
  122.     xfree((ptr_t) u);
  123.     return (Strsave(gstart));
  124. }
  125.  
  126. static int
  127. globbrace(s, p, bl)
  128.     Char   *s, *p, ***bl;
  129. {
  130.     int     i, len;
  131.     Char   *pm, *pe, *lm, *pl;
  132.     Char  **nv, **vl;
  133.     Char    gbuf[MAXPATHLEN];
  134.     int     size = GLOBSPACE;
  135.  
  136.     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
  137.     *vl = NULL;
  138.  
  139.     len = 0;
  140.     /* copy part up to the brace */
  141.     for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
  142.     continue;
  143.  
  144.     /* check for balanced braces */
  145.     for (i = 0, pe = ++p; *pe; pe++)
  146.     if (*pe == LBRK) {
  147.         /* Ignore everything between [] */
  148.         for (++pe; *pe != RBRK && *pe != EOS; pe++)
  149.         continue;
  150.         if (*pe == EOS) {
  151.         blkfree(nv);
  152.         return (-RBRK);
  153.         }
  154.     }
  155.     else if (*pe == LBRC)
  156.         i++;
  157.     else if (*pe == RBRC) {
  158.         if (i == 0)
  159.         break;
  160.         i--;
  161.     }
  162.  
  163.     if (i != 0 || *pe == '\0') {
  164.     blkfree(nv);
  165.     return (-RBRC);
  166.     }
  167.  
  168.     for (i = 0, pl = pm = p; pm <= pe; pm++)
  169.     switch (*pm) {
  170.     case LBRK:
  171.         for (++pm; *pm != RBRK && *pm != EOS; pm++)
  172.         continue;
  173.         if (*pm == EOS) {
  174.         *vl = NULL;
  175.         blkfree(nv);
  176.         return (-RBRK);
  177.         }
  178.         break;
  179.     case LBRC:
  180.         i++;
  181.         break;
  182.     case RBRC:
  183.         if (i) {
  184.         i--;
  185.         break;
  186.         }
  187.         /* FALLTHROUGH */
  188.     case ',':
  189.         if (i && *pm == ',')
  190.         break;
  191.         else {
  192.         Char    savec = *pm;
  193.  
  194.         *pm = EOS;
  195.         (void) Strcpy(lm, pl);
  196.         (void) Strcat(gbuf, pe + 1);
  197.         *pm = savec;
  198.         *vl++ = Strsave(gbuf);
  199.         len++;
  200.         pl = pm + 1;
  201.         if (vl == &nv[size]) {
  202.             size += GLOBSPACE;
  203.             nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  204.                         size * sizeof(Char *));
  205.             vl = &nv[size - GLOBSPACE];
  206.         }
  207.         }
  208.         break;
  209.     default:
  210.         break;
  211.     }
  212.     *vl = NULL;
  213.     *bl = nv;
  214.     return (len);
  215. }
  216.  
  217.  
  218. static void
  219. expbrace(nvp, elp, size)
  220.     Char ***nvp, ***elp;
  221.     int size;
  222. {
  223.     Char **vl, **el, **nv, *s;
  224.  
  225.     vl = nv = *nvp;
  226.     if (elp != NULL)
  227.     el = *elp;
  228.     else
  229.     for (el = vl; *el; el++)
  230.         continue;
  231.  
  232.     for (s = *vl; s; s = *++vl) {
  233.     Char   *b;
  234.     Char  **vp, **bp;
  235.  
  236.     /* leave {} untouched for find */
  237.     if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
  238.         continue;
  239.     if (b = Strchr(s, '{')) {
  240.         Char  **bl;
  241.         int     len;
  242.  
  243.         if ((len = globbrace(s, b, &bl)) < 0) {
  244.         xfree((ptr_t) nv);
  245.         stderror(ERR_MISSING, -len);
  246.         }
  247.         xfree((ptr_t) s);
  248.         if (len == 1) {
  249.         *vl-- = *bl;
  250.         xfree((ptr_t) bl);
  251.         continue;
  252.         }
  253.         len = blklen(bl);
  254.         if (&el[len] >= &nv[size]) {
  255.         int     l, e;
  256.  
  257.         l = &el[len] - &nv[size];
  258.         size += GLOBSPACE > l ? GLOBSPACE : l;
  259.         l = vl - nv;
  260.         e = el - nv;
  261.         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  262.                     size * sizeof(Char *));
  263.         vl = nv + l;
  264.         el = nv + e;
  265.         }
  266.         vp = vl--;
  267.         *vp = *bl;
  268.         len--;
  269.         for (bp = el; bp != vp; bp--)
  270.         bp[len] = *bp;
  271.         el += len;
  272.         vp++;
  273.         for (bp = bl + 1; *bp; *vp++ = *bp++)
  274.         continue;
  275.         xfree((ptr_t) bl);
  276.     }
  277.  
  278.     }
  279.     if (elp != NULL)
  280.     *elp = el;
  281.     *nvp = nv;
  282. }
  283.  
  284. static Char **
  285. globexpand(v)
  286.     Char  **v;
  287. {
  288.     Char   *s;
  289.     Char  **nv, **vl, **el;
  290.     int     size = GLOBSPACE;
  291.  
  292.  
  293.     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
  294.     *vl = NULL;
  295.  
  296.     /*
  297.      * Step 1: expand backquotes.
  298.      */
  299.     while (s = *v++) {
  300.     if (Strchr(s, '`')) {
  301.         int     i;
  302.  
  303.         (void) dobackp(s, 0);
  304.         for (i = 0; i < pargc; i++) {
  305.         *vl++ = pargv[i];
  306.         if (vl == &nv[size]) {
  307.             size += GLOBSPACE;
  308.             nv = (Char **) xrealloc((ptr_t) nv,
  309.                         (size_t) size * sizeof(Char *));
  310.             vl = &nv[size - GLOBSPACE];
  311.         }
  312.         }
  313.         xfree((ptr_t) pargv);
  314.         pargv = NULL;
  315.     }
  316.     else {
  317.         *vl++ = Strsave(s);
  318.         if (vl == &nv[size]) {
  319.         size += GLOBSPACE;
  320.         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  321.                     size * sizeof(Char *));
  322.         vl = &nv[size - GLOBSPACE];
  323.         }
  324.     }
  325.     }
  326.     *vl = NULL;
  327.  
  328.     if (noglob)
  329.     return (nv);
  330.  
  331.     /*
  332.      * Step 2: expand braces
  333.      */
  334.     el = vl;
  335.     vl = nv;
  336.     expbrace(&vl, &el, size);
  337.  
  338.  
  339.     /*
  340.      * Step 3: expand ~
  341.      */
  342.     vl = nv;
  343.     for (s = *vl; s; s = *++vl)
  344.     if (*s == '~')
  345.         *vl = globtilde(nv, s);
  346.     vl = nv;
  347.     return (vl);
  348. }
  349.  
  350. static Char *
  351. handleone(str, vl, action)
  352.     Char   *str, **vl;
  353.     int     action;
  354. {
  355.  
  356.     Char   *cp, **vlp = vl;
  357.  
  358.     switch (action) {
  359.     case G_ERROR:
  360.     setname(vis_str(str));
  361.     blkfree(vl);
  362.     stderror(ERR_NAME | ERR_AMBIG);
  363.     break;
  364.     case G_APPEND:
  365.     trim(vlp);
  366.     str = Strsave(*vlp++);
  367.     do {
  368.         cp = Strspl(str, STRspace);
  369.         xfree((ptr_t) str);
  370.         str = Strspl(cp, *vlp);
  371.         xfree((ptr_t) cp);
  372.     }
  373.     while (*++vlp);
  374.     blkfree(vl);
  375.     break;
  376.     case G_IGNORE:
  377.     str = Strsave(strip(*vlp));
  378.     blkfree(vl);
  379.     break;
  380.     default:
  381.     break;
  382.     }
  383.     return (str);
  384. }
  385.  
  386. static Char **
  387. libglob(vl)
  388.     Char  **vl;
  389. {
  390.     int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
  391.     glob_t  globv;
  392.     char   *ptr;
  393.     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
  394.  
  395.     if (!vl || !vl[0])
  396.     return (vl);
  397.  
  398.     globv.gl_offs = 0;
  399.     globv.gl_pathv = 0;
  400.     globv.gl_pathc = 0;
  401.  
  402.     if (nonomatch)
  403.     gflgs |= GLOB_NOCHECK;
  404.  
  405.     do {
  406.     ptr = short2qstr(*vl);
  407.     switch (glob(ptr, gflgs, 0, &globv)) {
  408.     case GLOB_ABEND:
  409.         setname(vis_str(*vl));
  410.         stderror(ERR_NAME | ERR_GLOB);
  411.         /* NOTREACHED */
  412.     case GLOB_NOSPACE:
  413.         stderror(ERR_NOMEM);
  414.         /* NOTREACHED */
  415.     default:
  416.         break;
  417.     }
  418.     if (globv.gl_flags & GLOB_MAGCHAR) {
  419.         match |= (globv.gl_matchc != 0);
  420.         magic = 1;
  421.     }
  422.     gflgs |= GLOB_APPEND;
  423.     }
  424.     while (*++vl);
  425.     vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
  426.     NULL : blk2short(globv.gl_pathv);
  427.     globfree(&globv);
  428.     return (vl);
  429. }
  430.  
  431. Char   *
  432. globone(str, action)
  433.     Char   *str;
  434.     int     action;
  435. {
  436.     Char   *v[2], **vl, **vo;
  437.     int    gflg;
  438.  
  439.     noglob = adrof(STRnoglob) != 0;
  440.     gflag = 0;
  441.     v[0] = str;
  442.     v[1] = 0;
  443.     tglob(v);
  444.     gflg = gflag;
  445.     if (gflg == G_NONE)
  446.     return (strip(Strsave(str)));
  447.  
  448.     if (gflg & G_CSH) {
  449.     /*
  450.      * Expand back-quote, tilde and brace
  451.      */
  452.     vo = globexpand(v);
  453.     if (noglob || (gflg & G_GLOB) == 0) {
  454.         if (vo[0] == NULL) {
  455.         xfree((ptr_t) vo);
  456.         return (Strsave(STRNULL));
  457.         }
  458.         if (vo[1] != NULL)
  459.         return (handleone(str, vo, action));
  460.         else {
  461.         str = strip(vo[0]);
  462.         xfree((ptr_t) vo);
  463.         return (str);
  464.         }
  465.     }
  466.     }
  467.     else if (noglob || (gflg & G_GLOB) == 0)
  468.     return (strip(Strsave(str)));
  469.     else
  470.     vo = v;
  471.  
  472.     vl = libglob(vo);
  473.     if ((gflg & G_CSH) && vl != vo)
  474.     blkfree(vo);
  475.     if (vl == NULL) {
  476.     setname(vis_str(str));
  477.     stderror(ERR_NAME | ERR_NOMATCH);
  478.     }
  479.     if (vl[0] == NULL) {
  480.     xfree((ptr_t) vl);
  481.     return (Strsave(STRNULL));
  482.     }
  483.     if (vl[1] != NULL)
  484.     return (handleone(str, vl, action));
  485.     else {
  486.     str = strip(*vl);
  487.     xfree((ptr_t) vl);
  488.     return (str);
  489.     }
  490. }
  491.  
  492. Char  **
  493. globall(v)
  494.     Char  **v;
  495. {
  496.     Char  **vl, **vo;
  497.     int   gflg = gflag;
  498.  
  499.     if (!v || !v[0]) {
  500.     gargv = saveblk(v);
  501.     gargc = blklen(gargv);
  502.     return (gargv);
  503.     }
  504.  
  505.     noglob = adrof(STRnoglob) != 0;
  506.  
  507.     if (gflg & G_CSH)
  508.     /*
  509.      * Expand back-quote, tilde and brace
  510.      */
  511.     vl = vo = globexpand(v);
  512.     else
  513.     vl = vo = saveblk(v);
  514.  
  515.     if (!noglob && (gflg & G_GLOB)) {
  516.     vl = libglob(vo);
  517.     if ((gflg & G_CSH) && vl != vo)
  518.         blkfree(vo);
  519.     }
  520.     else
  521.     trim(vl);
  522.  
  523.     gargc = vl ? blklen(vl) : 0;
  524.     return (gargv = vl);
  525. }
  526.  
  527. void
  528. ginit()
  529. {
  530.     gargsiz = GLOBSPACE;
  531.     gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
  532.     gargv[0] = 0;
  533.     gargc = 0;
  534. }
  535.  
  536. void
  537. rscan(t, f)
  538.     register Char **t;
  539.     void    (*f) ();
  540. {
  541.     register Char *p;
  542.  
  543.     while (p = *t++)
  544.     while (*p)
  545.         (*f) (*p++);
  546. }
  547.  
  548. void
  549. trim(t)
  550.     register Char **t;
  551. {
  552.     register Char *p;
  553.  
  554.     while (p = *t++)
  555.     while (*p)
  556.         *p++ &= TRIM;
  557. }
  558.  
  559. void
  560. tglob(t)
  561.     register Char **t;
  562. {
  563.     register Char *p, c;
  564.  
  565.     while (p = *t++) {
  566.     if (*p == '~' || *p == '=')
  567.         gflag |= G_CSH;
  568.     else if (*p == '{' &&
  569.          (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
  570.         continue;
  571.     while (c = *p++) {
  572.         /*
  573.          * eat everything inside the matching backquotes
  574.          */
  575.         if (c == '`') {
  576.         gflag |= G_CSH;
  577.         while (*p && *p != '`') 
  578.             if (*p++ == '\\') {
  579.             if (*p)        /* Quoted chars */
  580.                 p++;
  581.             else
  582.                 break;
  583.             }
  584.         if (*p)            /* The matching ` */
  585.             p++;
  586.         else
  587.             break;
  588.         }
  589.         else if (c == '{')
  590.         gflag |= G_CSH;
  591.         else if (isglob(c))
  592.         gflag |= G_GLOB;
  593.     }
  594.     }
  595. }
  596.  
  597. /*
  598.  * Command substitute cp.  If literal, then this is a substitution from a
  599.  * << redirection, and so we should not crunch blanks and tabs, separating
  600.  * words only at newlines.
  601.  */
  602. Char  **
  603. dobackp(cp, literal)
  604.     Char   *cp;
  605.     bool    literal;
  606. {
  607.     register Char *lp, *rp;
  608.     Char   *ep, word[MAXPATHLEN];
  609.  
  610.     if (pargv) {
  611. #ifdef notdef
  612.     abort();
  613. #endif
  614.     blkfree(pargv);
  615.     }
  616.     pargsiz = GLOBSPACE;
  617.     pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
  618.     pargv[0] = NULL;
  619.     pargcp = pargs = word;
  620.     pargc = 0;
  621.     pnleft = MAXPATHLEN - 4;
  622.     for (;;) {
  623.     for (lp = cp; *lp != '`'; lp++) {
  624.         if (*lp == 0) {
  625.         if (pargcp != pargs)
  626.             pword();
  627.         return (pargv);
  628.         }
  629.         psave(*lp);
  630.     }
  631.     lp++;
  632.     for (rp = lp; *rp && *rp != '`'; rp++)
  633.         if (*rp == '\\') {
  634.         rp++;
  635.         if (!*rp)
  636.             goto oops;
  637.         }
  638.     if (!*rp)
  639.     oops:  stderror(ERR_UNMATCHED, '`');
  640.     ep = Strsave(lp);
  641.     ep[rp - lp] = 0;
  642.     backeval(ep, literal);
  643.     cp = rp + 1;
  644.     }
  645. }
  646.  
  647. static void
  648. backeval(cp, literal)
  649.     Char   *cp;
  650.     bool    literal;
  651. {
  652.     register int icnt, c;
  653.     register Char *ip;
  654.     struct command faket;
  655.     bool    hadnl;
  656.     int     pvec[2], quoted;
  657.     Char   *fakecom[2], ibuf[BUFSIZ];
  658.     char    tibuf[BUFSIZ];
  659.  
  660.     hadnl = 0;
  661.     icnt = 0;
  662.     quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
  663.     faket.t_dtyp = NODE_COMMAND;
  664.     faket.t_dflg = 0;
  665.     faket.t_dlef = 0;
  666.     faket.t_drit = 0;
  667.     faket.t_dspr = 0;
  668.     faket.t_dcom = fakecom;
  669.     fakecom[0] = STRfakecom1;
  670.     fakecom[1] = 0;
  671.  
  672.     /*
  673.      * We do the psave job to temporarily change the current job so that the
  674.      * following fork is considered a separate job.  This is so that when
  675.      * backquotes are used in a builtin function that calls glob the "current
  676.      * job" is not corrupted.  We only need one level of pushed jobs as long as
  677.      * we are sure to fork here.
  678.      */
  679.     psavejob();
  680.  
  681.     /*
  682.      * It would be nicer if we could integrate this redirection more with the
  683.      * routines in sh.sem.c by doing a fake execute on a builtin function that
  684.      * was piped out.
  685.      */
  686.     mypipe(pvec);
  687.     if (pfork(&faket, -1) == 0) {
  688.     struct wordent paraml;
  689.     struct command *t;
  690.  
  691.     (void) close(pvec[0]);
  692.     (void) dmove(pvec[1], 1);
  693.     (void) dmove(SHERR, 2);
  694.     initdesc();
  695.     /*
  696.      * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
  697.      * posted to comp.bugs.4bsd 12 Sep. 1989.
  698.      */
  699.     if (pargv)        /* mg, 21.dec.88 */
  700.         blkfree(pargv), pargv = 0, pargsiz = 0;
  701.     /* mg, 21.dec.88 */
  702.     arginp = cp;
  703.     while (*cp)
  704.         *cp++ &= TRIM;
  705.  
  706.         /*
  707.      * In the child ``forget'' everything about current aliases or
  708.      * eval vectors.
  709.      */
  710.     alvec = NULL;
  711.     evalvec = NULL;
  712.     alvecp = NULL;
  713.     evalp = NULL;
  714.     (void) lex(¶ml);
  715.     if (seterr)
  716.         stderror(ERR_OLD);
  717.     alias(¶ml);
  718.     t = syntax(paraml.next, ¶ml, 0);
  719.     if (seterr)
  720.         stderror(ERR_OLD);
  721.     if (t)
  722.         t->t_dflg |= F_NOFORK;
  723.     (void) signal(SIGTSTP, SIG_IGN);
  724.     (void) signal(SIGTTIN, SIG_IGN);
  725.     (void) signal(SIGTTOU, SIG_IGN);
  726.     execute(t, -1, NULL, NULL);
  727.     exitstat();
  728.     }
  729.     xfree((ptr_t) cp);
  730.     (void) close(pvec[1]);
  731.     c = 0;
  732.     ip = NULL;
  733.     do {
  734.     int     cnt = 0;
  735.  
  736.     for (;;) {
  737.         if (icnt == 0) {
  738.         int     i;
  739.  
  740.         ip = ibuf;
  741.         do
  742.             icnt = read(pvec[0], tibuf, BUFSIZ);
  743.         while (icnt == -1 && errno == EINTR);
  744.         if (icnt <= 0) {
  745.             c = -1;
  746.             break;
  747.         }
  748.         for (i = 0; i < icnt; i++)
  749.             ip[i] = (unsigned char) tibuf[i];
  750.         }
  751.         if (hadnl)
  752.         break;
  753.         --icnt;
  754.         c = (*ip++ & TRIM);
  755.         if (c == 0)
  756.         break;
  757.         if (c == '\n') {
  758.         /*
  759.          * Continue around the loop one more time, so that we can eat
  760.          * the last newline without terminating this word.
  761.          */
  762.         hadnl = 1;
  763.         continue;
  764.         }
  765.         if (!quoted && (c == ' ' || c == '\t'))
  766.         break;
  767.         cnt++;
  768.         psave(c | quoted);
  769.     }
  770.     /*
  771.      * Unless at end-of-file, we will form a new word here if there were
  772.      * characters in the word, or in any case when we take text literally.
  773.      * If we didn't make empty words here when literal was set then we
  774.      * would lose blank lines.
  775.      */
  776.     if (c != -1 && (cnt || literal))
  777.         pword();
  778.     hadnl = 0;
  779.     } while (c >= 0);
  780.     (void) close(pvec[0]);
  781.     pwait();
  782.     prestjob();
  783. }
  784.  
  785. static void
  786. psave(c)
  787.     int    c;
  788. {
  789.     if (--pnleft <= 0)
  790.     stderror(ERR_WTOOLONG);
  791.     *pargcp++ = c;
  792. }
  793.  
  794. static void
  795. pword()
  796. {
  797.     psave(0);
  798.     if (pargc == pargsiz - 1) {
  799.     pargsiz += GLOBSPACE;
  800.     pargv = (Char **) xrealloc((ptr_t) pargv,
  801.                    (size_t) pargsiz * sizeof(Char *));
  802.     }
  803.     pargv[pargc++] = Strsave(pargs);
  804.     pargv[pargc] = NULL;
  805.     pargcp = pargs;
  806.     pnleft = MAXPATHLEN - 4;
  807. }
  808.  
  809. int 
  810. Gmatch(string, pattern)
  811.     Char *string, *pattern;
  812. {
  813.     Char **blk, **p;
  814.     int       gpol = 1, gres = 0;
  815.  
  816.     if (*pattern == '^') {
  817.     gpol = 0;
  818.     pattern++;
  819.     }
  820.  
  821.     blk = (Char **) xmalloc(GLOBSPACE * sizeof(Char *));
  822.     blk[0] = Strsave(pattern);
  823.     blk[1] = NULL;
  824.  
  825.     expbrace(&blk, NULL, GLOBSPACE);
  826.  
  827.     for (p = blk; *p; p++)
  828.     gres |= pmatch(string, *p);
  829.  
  830.     blkfree(blk);
  831.     return(gres == gpol);
  832.  
  833. static int
  834. pmatch(string, pattern)
  835.     register Char *string, *pattern;
  836. {
  837.     register Char stringc, patternc;
  838.     int     match, negate_range;
  839.     Char    rangec;
  840.  
  841.     for (;; ++string) {
  842.     stringc = *string & TRIM;
  843.     patternc = *pattern++;
  844.     switch (patternc) {
  845.     case 0:
  846.         return (stringc == 0);
  847.     case '?':
  848.         if (stringc == 0)
  849.         return (0);
  850.         break;
  851.     case '*':
  852.         if (!*pattern)
  853.         return (1);
  854.         while (*string)
  855.         if (Gmatch(string++, pattern))
  856.             return (1);
  857.         return (0);
  858.     case '[':
  859.         match = 0;
  860.         if (negate_range = (*pattern == '^'))
  861.         pattern++;
  862.         while (rangec = *pattern++) {
  863.         if (rangec == ']')
  864.             break;
  865.         if (match)
  866.             continue;
  867.         if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
  868.             match = (stringc <= (*pattern & TRIM) &&
  869.                   (*(pattern-2) & TRIM) <= stringc);
  870.             pattern++;
  871.         }
  872.         else 
  873.             match = (stringc == (rangec & TRIM));
  874.         }
  875.         if (rangec == 0)
  876.         stderror(ERR_NAME | ERR_MISSING, ']');
  877.         if (match == negate_range)
  878.         return (0);
  879.         break;
  880.     default:
  881.         if ((patternc & TRIM) != stringc)
  882.         return (0);
  883.         break;
  884.  
  885.     }
  886.     }
  887. }
  888.  
  889. void
  890. Gcat(s1, s2)
  891.     Char   *s1, *s2;
  892. {
  893.     register Char *p, *q;
  894.     int     n;
  895.  
  896.     for (p = s1; *p++;)
  897.     continue;
  898.     for (q = s2; *q++;)
  899.     continue;
  900.     n = (p - s1) + (q - s2) - 1;
  901.     if (++gargc >= gargsiz) {
  902.     gargsiz += GLOBSPACE;
  903.     gargv = (Char **) xrealloc((ptr_t) gargv,
  904.                    (size_t) gargsiz * sizeof(Char *));
  905.     }
  906.     gargv[gargc] = 0;
  907.     p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
  908.     for (q = s1; *p++ = *q++;)
  909.     continue;
  910.     for (p--, q = s2; *p++ = *q++;)
  911.     continue;
  912. }
  913.  
  914. #ifdef FILEC
  915. int
  916. sortscmp(a, b)
  917.     register const ptr_t a, b;
  918. {
  919. #if defined(NLS) && !defined(NOSTRCOLL)
  920.     char    buf[2048];
  921. #endif
  922.  
  923.     if (a)            /* check for NULL */
  924.     return (b ? 1 : 0);
  925.     if (!b)
  926.     return (-1);
  927.  
  928.     if (!*(Char **)a)            /* check for NULL */
  929.     return (*(Char **)b ? 1 : 0);
  930.     if (!*(Char **)b)
  931.     return (-1);
  932.  
  933. #if defined(NLS) && !defined(NOSTRCOLL)
  934.     (void) strcpy(buf, short2str(*(Char **)a));
  935.     return ((int) strcoll(buf, short2str(*(Char **)b)));
  936. #else
  937.     return ((int) Strcmp(*(Char **)a, *(Char **)b));
  938. #endif
  939. }
  940. #endif /* FILEC */
  941.