drm/linux: Improve put_user()
[dragonfly.git] / contrib / tcsh-6 / sh.glob.c
1 /*
2  * sh.glob.c: Regular expression expansion
3  */
4 /*-
5  * Copyright (c) 1980, 1991 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 #include "sh.h"
33 #include "tc.h"
34 #include "tw.h"
35
36 #include "glob.h"
37
38 /*
39  * Values for gflag
40  */
41 #define G_NONE  0               /* No globbing needed                   */
42 #define G_GLOB  1               /* string contains *?[] characters      */
43 #define G_CSH   2               /* string contains ~`{ characters       */
44
45 #define GLOBSPACE       100     /* Alloc increment                      */
46
47
48 #define LBRC '{'
49 #define RBRC '}'
50 #define LBRK '['
51 #define RBRK ']'
52 #define EOS '\0'
53
54 /*
55  * globbing is now done in two stages. In the first pass we expand
56  * csh globbing idioms ~`{ and then we proceed doing the normal
57  * globbing if needed ?*[
58  *
59  * Csh type globbing is handled in globexpand() and the rest is
60  * handled in glob() which is part of the 4.4BSD libc.
61  *
62  */
63 static  Char     *globtilde     (Char *);
64 static  Char     *handleone     (Char *, Char **, int);
65 static  Char    **libglob       (Char **);
66 static  Char    **globexpand    (Char **, int);
67 static  int       globbrace     (const Char *, Char ***);
68 static  void      expbrace      (Char ***, Char ***, int);
69 static  void      pword         (struct blk_buf *, struct Strbuf *);
70 static  void      backeval      (struct blk_buf *, struct Strbuf *, Char *,
71                                  int);
72 static Char *
73 globtilde(Char *s)
74 {
75     Char *name, *u, *home, *res;
76
77     u = s;
78     for (s++; *s && *s != '/' && *s != ':'; s++)
79         continue;
80     name = Strnsave(u + 1, s - (u + 1));
81     cleanup_push(name, xfree);
82     home = gethdir(name);
83     if (home == NULL) {
84         if (adrof(STRnonomatch)) {
85             cleanup_until(name);
86             return u;
87         }
88         if (*name)
89             stderror(ERR_UNKUSER, short2str(name));
90         else
91             stderror(ERR_NOHOME);
92     }
93     cleanup_until(name);
94     if (home[0] == '/' && home[1] == '\0' && s[0] == '/')
95         res = Strsave(s);
96     else
97         res = Strspl(home, s);
98     xfree(home);
99     xfree(u);
100     return res;
101 }
102
103 /* Returns a newly allocated string, old or NULL */
104 Char *
105 globequal(Char *old)
106 {
107     int     dig;
108     const Char *dir;
109     Char    *b;
110
111     /*
112      * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
113      * in stack. PWP: let =foobar pass through (for X windows)
114      */
115     if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) {
116         /* =- */
117         const Char *olddir = varval (STRowd);
118
119         if (olddir && *olddir &&
120             !dcwd->di_next->di_name && !dcwd->di_prev->di_name)
121             return Strspl(olddir, &old[2]);
122         dig = -1;
123         b = &old[2];
124     }
125     else if (Isdigit(old[1])) {
126         /* =<number> */
127         dig = old[1] - '0';
128         for (b = &old[2]; Isdigit(*b); b++)
129             dig = dig * 10 + (*b - '0');
130         if (*b != '\0' && *b != '/')
131             /* =<number>foobar */
132             return old;
133     }
134     else
135         /* =foobar */
136         return old;
137
138     dir = getstakd(dig);
139     if (dir == NULL)
140         return NULL;
141     return Strspl(dir, b);
142 }
143
144 static int
145 globbrace(const Char *s, Char ***bl)
146 {
147     struct Strbuf gbuf = Strbuf_INIT;
148     struct blk_buf bb = BLK_BUF_INIT;
149     int     i;
150     const Char *p, *pm, *pe, *pl;
151     size_t prefix_len;
152
153     /* copy part up to the brace */
154     for (p = s; *p != LBRC; p++)
155         ;
156     prefix_len = p - s;
157
158     /* check for balanced braces */
159     for (i = 0, pe = ++p; *pe; pe++)
160         if (*pe == LBRK) {
161             /* Ignore everything between [] */
162             for (++pe; *pe != RBRK && *pe != EOS; pe++)
163                 continue;
164             if (*pe == EOS)
165                 return (-RBRK);
166         }
167         else if (*pe == LBRC)
168             i++;
169         else if (*pe == RBRC) {
170             if (i == 0)
171                 break;
172             i--;
173         }
174
175     if (i != 0 || *pe == '\0')
176         return (-RBRC);
177
178     Strbuf_appendn(&gbuf, s, prefix_len);
179
180     for (i = 0, pl = pm = p; pm <= pe; pm++)
181         switch (*pm) {
182         case LBRK:
183             for (++pm; *pm != RBRK && *pm != EOS; pm++)
184                 continue;
185             if (*pm == EOS) {
186                 bb_cleanup(&bb);
187                 xfree(gbuf.s);
188                 return (-RBRK);
189             }
190             break;
191         case LBRC:
192             i++;
193             break;
194         case RBRC:
195             if (i) {
196                 i--;
197                 break;
198             }
199             /* FALLTHROUGH */
200         case ',':
201             if (i && *pm == ',')
202                 break;
203             else {
204                 gbuf.len = prefix_len;
205                 Strbuf_appendn(&gbuf, pl, pm - pl);
206                 Strbuf_append(&gbuf, pe + 1);
207                 Strbuf_terminate(&gbuf);
208                 bb_append(&bb, Strsave(gbuf.s));
209                 pl = pm + 1;
210             }
211             break;
212         default:
213             break;
214         }
215     *bl = bb_finish(&bb);
216     xfree(gbuf.s);
217     return bb.len;
218 }
219
220
221 static void
222 expbrace(Char ***nvp, Char ***elp, int size)
223 {
224     Char **vl, **el, **nv, *s;
225
226     vl = nv = *nvp;
227     if (elp != NULL)
228         el = *elp;
229     else
230         el = vl + blklen(vl);
231
232     for (s = *vl; s; s = *++vl) {
233         Char  **vp, **bp;
234
235         /* leave {} untouched for find */
236         if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
237             continue;
238         if (Strchr(s, '{') != NULL) {
239             Char  **bl = NULL;
240             int     len;
241
242             if ((len = globbrace(s, &bl)) < 0)
243                 stderror(ERR_MISSING, -len);
244             xfree(s);
245             if (len == 1) {
246                 *vl-- = *bl;
247                 xfree(bl);
248                 continue;
249             }
250             if (&el[len] >= &nv[size]) {
251                 size_t l, e;
252                 l = &el[len] - &nv[size];
253                 size += GLOBSPACE > l ? GLOBSPACE : l;
254                 l = vl - nv;
255                 e = el - nv;
256                 nv = xrealloc(nv, size * sizeof(Char *));
257                 *nvp = nv; /* To keep cleanups working */
258                 vl = nv + l;
259                 el = nv + e;
260             }
261             /* nv vl   el     bl
262              * |  |    |      |
263              * -.--..--       x--
264              *   |            len
265              *   vp
266              */
267             vp = vl--;
268             *vp = *bl;
269             len--;
270             for (bp = el; bp != vp; bp--)
271                 bp[len] = *bp;
272             el += len;
273             /* nv vl    el bl
274              * |  |     |  |
275              * -.-x  ---    --
276              *   |len
277              *   vp
278              */
279             vp++;
280             for (bp = bl + 1; *bp; *vp++ = *bp++)
281                 continue;
282             xfree(bl);
283         }
284
285     }
286     if (elp != NULL)
287         *elp = el;
288 }
289
290 static Char **
291 globexpand(Char **v, int noglob)
292 {
293     Char   *s;
294     Char  ***fnv, **vl, **el;
295     int     size = GLOBSPACE;
296
297
298     fnv = xmalloc(sizeof(Char ***));
299     *fnv = vl = xmalloc(sizeof(Char *) * size);
300     *vl = NULL;
301     cleanup_push(fnv, blk_indirect_cleanup);
302
303     /*
304      * Step 1: expand backquotes.
305      */
306     while ((s = *v++) != NULL) {
307         if (Strchr(s, '`')) {
308             int     i;
309             Char **expanded;
310
311             expanded = dobackp(s, 0);
312             for (i = 0; expanded[i] != NULL; i++) {
313                 *vl++ = expanded[i];
314                 if (vl == &(*fnv)[size]) {
315                     size += GLOBSPACE;
316                     *fnv = xrealloc(*fnv, size * sizeof(Char *));
317                     vl = &(*fnv)[size - GLOBSPACE];
318                 }
319             }
320             xfree(expanded);
321         }
322         else {
323             *vl++ = Strsave(s);
324             if (vl == &(*fnv)[size]) {
325                 size += GLOBSPACE;
326                 *fnv = xrealloc(*fnv, size * sizeof(Char *));
327                 vl = &(*fnv)[size - GLOBSPACE];
328             }
329         }
330         *vl = NULL;
331     }
332
333     if (noglob)
334         goto done;
335
336     /*
337      * Step 2: expand braces
338      */
339     el = vl;
340     expbrace(fnv, &el, size);
341
342
343     /*
344      * Step 3: expand ~ =
345      */
346     vl = *fnv;
347     for (s = *vl; s; s = *++vl)
348         switch (*s) {
349             Char *ns;
350         case '~':
351             *vl = globtilde(s);
352             break;
353         case '=':
354             if ((ns = globequal(s)) == NULL) {
355                 if (!adrof(STRnonomatch))
356                     stderror(ERR_DEEP); /* Error */
357             }
358             if (ns && ns != s) {
359                 /* Expansion succeeded */
360                 xfree(s);
361                 *vl = ns;
362             }
363             break;
364         default:
365             break;
366         }
367     vl = *fnv;
368
369     /*
370      * Step 4: expand .. if the variable symlinks==expand is set
371      */
372     if (symlinks == SYM_EXPAND) {
373         for (s = *vl; s; s = *++vl) {
374             *vl = dnormalize(s, 1);
375             xfree(s);
376         }
377     }
378
379  done:
380     cleanup_ignore(fnv);
381     cleanup_until(fnv);
382     vl = *fnv;
383     xfree(fnv);
384     return vl;
385 }
386
387 static Char *
388 handleone(Char *str, Char **vl, int action)
389 {
390     size_t chars;
391     Char **t, *p, *strp;
392
393     switch (action) {
394     case G_ERROR:
395         setname(short2str(str));
396         blkfree(vl);
397         stderror(ERR_NAME | ERR_AMBIG);
398         break;
399     case G_APPEND:
400         chars = 0;
401         for (t = vl; (p = *t++) != NULL; chars++)
402             chars += Strlen(p);
403         str = xmalloc(chars * sizeof(Char));
404         for (t = vl, strp = str; (p = *t++) != NULL; chars++) {
405             while (*p)
406                  *strp++ = *p++ & TRIM;
407             *strp++ = ' ';
408         }
409         *--strp = '\0';
410         blkfree(vl);
411         break;
412     case G_IGNORE:
413         str = Strsave(strip(*vl));
414         blkfree(vl);
415         break;
416     default:
417         break;
418     }
419     return (str);
420 }
421
422 static Char **
423 libglob(Char **vl)
424 {
425     int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
426     glob_t  globv;
427     char   *ptr;
428     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
429
430     if (adrof(STRglobdot))
431        gflgs |= GLOB_DOT;
432
433     if (adrof(STRglobstar))
434        gflgs |= GLOB_STAR;
435
436     if (!vl || !vl[0])
437         return(vl);
438
439     globv.gl_offs = 0;
440     globv.gl_pathv = 0;
441     globv.gl_pathc = 0;
442
443     if (nonomatch)
444         gflgs |= GLOB_NOCHECK;
445
446     do {
447         ptr = short2qstr(*vl);
448         switch (glob(ptr, gflgs, 0, &globv)) {
449         case GLOB_ABEND:
450             globfree(&globv);
451             setname(ptr);
452             stderror(ERR_NAME | ERR_GLOB);
453             /* NOTREACHED */
454         case GLOB_NOSPACE:
455             globfree(&globv);
456             stderror(ERR_NOMEM);
457             /* NOTREACHED */
458         default:
459             break;
460         }
461         if (globv.gl_flags & GLOB_MAGCHAR) {
462             match |= (globv.gl_matchc != 0);
463             magic = 1;
464         }
465         gflgs |= GLOB_APPEND;
466     }
467     while (*++vl);
468     vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? 
469         NULL : blk2short(globv.gl_pathv);
470     globfree(&globv);
471     return (vl);
472 }
473
474 Char   *
475 globone(Char *str, int action)
476 {
477     Char   *v[2], **vl, **vo;
478     int gflg, noglob;
479
480     noglob = adrof(STRnoglob) != 0;
481     v[0] = str;
482     v[1] = 0;
483     gflg = tglob(v);
484     if (gflg == G_NONE)
485         return (strip(Strsave(str)));
486
487     if (gflg & G_CSH) {
488         /*
489          * Expand back-quote, tilde and brace
490          */
491         vo = globexpand(v, noglob);
492         if (noglob || (gflg & G_GLOB) == 0) {
493             vl = vo;
494             goto result;
495         }
496         cleanup_push(vo, blk_cleanup);
497     }
498     else if (noglob || (gflg & G_GLOB) == 0)
499         return (strip(Strsave(str)));
500     else
501         vo = v;
502
503     vl = libglob(vo);
504     if (gflg & G_CSH) {
505         if (vl != vo)
506             cleanup_until(vo);
507         else
508             cleanup_ignore(vo);
509     }
510     if (vl == NULL) {
511         setname(short2str(str));
512         stderror(ERR_NAME | ERR_NOMATCH);
513     }
514  result:
515     if (vl && vl[0] == NULL) {
516         xfree(vl);
517         return (Strsave(STRNULL));
518     }
519     if (vl && vl[1]) 
520         return (handleone(str, vl, action));
521     else {
522         str = strip(*vl);
523         xfree(vl);
524         return (str);
525     }
526 }
527
528 Char  **
529 globall(Char **v, int gflg)
530 {
531     Char  **vl, **vo;
532     int noglob;
533
534     if (!v || !v[0])
535         return saveblk(v);
536
537     noglob = adrof(STRnoglob) != 0;
538
539     if (gflg & G_CSH)
540         /*
541          * Expand back-quote, tilde and brace
542          */
543         vl = vo = globexpand(v, noglob);
544     else
545         vl = vo = saveblk(v);
546
547     if (!noglob && (gflg & G_GLOB)) {
548         cleanup_push(vo, blk_cleanup);
549         vl = libglob(vo);
550         if (vl == vo)
551             cleanup_ignore(vo);
552         cleanup_until(vo);
553     }
554     else
555         trim(vl);
556
557     return vl;
558 }
559
560 Char **
561 glob_all_or_error(Char **v)
562 {
563     int gflag;
564
565     gflag = tglob(v);
566     if (gflag) {
567         v = globall(v, gflag);
568         if (v == NULL)
569             stderror(ERR_NAME | ERR_NOMATCH);
570     } else {
571         v = saveblk(v);
572         trim(v);
573     }
574     return v;
575 }
576
577 void
578 rscan(Char **t, void (*f) (Char))
579 {
580     Char *p;
581
582     while ((p = *t++) != NULL)
583         while (*p)
584             (*f) (*p++);
585 }
586
587 void
588 trim(Char **t)
589 {
590     Char *p;
591
592     while ((p = *t++) != NULL)
593         while (*p) {
594 #if INVALID_BYTE != 0
595             if ((*p & INVALID_BYTE) != INVALID_BYTE)    /* *p < INVALID_BYTE */
596 #endif
597                 *p &= TRIM;
598             p++;
599         }
600 }
601
602 int
603 tglob(Char **t)
604 {
605     int gflag;
606     const Char *p;
607
608     gflag = 0;
609     while ((p = *t++) != NULL) {
610         if (*p == '~' || *p == '=')
611             gflag |= G_CSH;
612         else if (*p == '{' &&
613                  (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
614             continue;
615         while (*p != '\0') {
616             if (*p == '`') {
617                 gflag |= G_CSH;
618 #ifdef notdef
619                 /*
620                  * We do want to expand echo `echo '*'`, so we don't\
621                  * use this piece of code anymore.
622                  */
623                 p++;
624                 while (*p && *p != '`') 
625                     if (*p++ == '\\') {
626                         if (*p)         /* Quoted chars */
627                             p++;
628                         else
629                             break;
630                     }
631                 if (!*p)                /* The matching ` */
632                     break;
633 #endif
634             }
635             else if (*p == '{')
636                 gflag |= G_CSH;
637             else if (isglob(*p))
638                 gflag |= G_GLOB;
639             else if (symlinks == SYM_EXPAND && 
640                 p[1] && ISDOTDOT(p) && (p == *(t-1) || *(p-1) == '/') )
641                 gflag |= G_CSH;
642             p++;
643         }
644     }
645     return gflag;
646 }
647
648 /*
649  * Command substitute cp.  If literal, then this is a substitution from a
650  * << redirection, and so we should not crunch blanks and tabs, separating
651  * words only at newlines.
652  */
653 Char  **
654 dobackp(Char *cp, int literal)
655 {
656     struct Strbuf word = Strbuf_INIT;
657     struct blk_buf bb = BLK_BUF_INIT;
658     Char *lp, *rp, *ep;
659
660     cleanup_push(&bb, bb_cleanup);
661     cleanup_push(&word, Strbuf_cleanup);
662     for (;;) {
663         for (lp = cp; *lp != '\0' && *lp != '`'; lp++)
664             ;
665         Strbuf_appendn(&word, cp, lp - cp);
666         if (*lp == 0)
667             break;
668         lp++;
669         for (rp = lp; *rp && *rp != '`'; rp++)
670             if (*rp == '\\') {
671                 rp++;
672                 if (!*rp)
673                     goto oops;
674             }
675         if (!*rp) {
676         oops:
677             cleanup_until(&bb);
678             stderror(ERR_UNMATCHED, '`');
679         }
680         ep = Strnsave(lp, rp - lp);
681         cleanup_push(ep, xfree);
682         backeval(&bb, &word, ep, literal);
683         cleanup_until(ep);
684         cp = rp + 1;
685     }
686     if (word.len != 0)
687         pword(&bb, &word);
688     cleanup_ignore(&bb);
689     cleanup_until(&bb);
690     return bb_finish(&bb);
691 }
692
693
694 static void
695 backeval(struct blk_buf *bb, struct Strbuf *word, Char *cp, int literal)
696 {
697     ssize_t icnt;
698     Char c, *ip;
699     struct command faket;
700     int    hadnl;
701     int     pvec[2], quoted;
702     Char   *fakecom[2], ibuf[BUFSIZE];
703
704     hadnl = 0;
705     icnt = 0;
706     if (!literal) {
707         for (ip = cp; (*ip & QUOTE) != 0; ip++)
708                 continue;
709         quoted = *ip == '\0';
710     } else
711         quoted = literal;
712     faket.t_dtyp = NODE_COMMAND;
713     faket.t_dflg = F_BACKQ;
714     faket.t_dlef = 0;
715     faket.t_drit = 0;
716     faket.t_dspr = 0;
717     faket.t_dcom = fakecom;
718     fakecom[0] = STRfakecom1;
719     fakecom[1] = 0;
720
721     /*
722      * We do the psave job to temporarily change the current job so that the
723      * following fork is considered a separate job.  This is so that when
724      * backquotes are used in a builtin function that calls glob the "current
725      * job" is not corrupted.  We only need one level of pushed jobs as long as
726      * we are sure to fork here.
727      */
728     psavejob();
729     cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */
730
731     /*
732      * It would be nicer if we could integrate this redirection more with the
733      * routines in sh.sem.c by doing a fake execute on a builtin function that
734      * was piped out.
735      */
736     mypipe(pvec);
737     cleanup_push(&pvec[0], open_cleanup);
738     cleanup_push(&pvec[1], open_cleanup);
739     if (pfork(&faket, -1) == 0) {
740         jmp_buf_t osetexit;
741         struct command *t;
742         size_t omark;
743
744         xclose(pvec[0]);
745         (void) dmove(pvec[1], 1);
746         (void) dmove(SHDIAG,  2);
747         initdesc();
748         closem();
749         arginp = cp;
750         for (arginp = cp; *cp; cp++) {
751             *cp &= TRIM;
752             if (is_set(STRcsubstnonl) && (*cp == '\n' || *cp == '\r'))
753                 *cp = ' ';
754         }
755
756         /*
757          * In the child ``forget'' everything about current aliases or
758          * eval vectors.
759          */
760         alvec = NULL;
761         evalvec = NULL;
762         alvecp = NULL;
763         evalp = NULL;
764
765         omark = cleanup_push_mark();
766         getexit(osetexit);
767         for (;;) {
768             struct wordent paraml1;
769             initlex(&paraml1);
770
771             (void) setexit();
772             justpr = 0;
773             
774             if (haderr) {
775                 /* unwind */
776                 doneinp = 0;
777                 cleanup_pop_mark(omark);
778                 resexit(osetexit);
779                 reset();
780             }
781             if (seterr) {
782                 xfree(seterr);
783                 seterr = NULL;
784             }
785
786             freelex(&paraml1);
787             (void) lex(&paraml1);
788             cleanup_push(&paraml1, lex_cleanup);
789             if (seterr)
790                 stderror(ERR_OLD);
791             alias(&paraml1);
792             t = syntax(paraml1.next, &paraml1, 0);
793             cleanup_push(t, syntax_cleanup);
794             /* The F_BACKQ flag must set so the job output is correct if
795              * printexitvalue is set.  If it's not set, the job output
796              * will have "Exit N" appended where N is the exit status. */
797             if (t)
798                     t->t_dflg = F_BACKQ|F_NOFORK;
799             if (seterr)
800                 stderror(ERR_OLD);
801 #ifdef SIGTSTP
802             signal(SIGTSTP, SIG_IGN);
803 #endif
804 #ifdef SIGTTIN
805             signal(SIGTTIN, SIG_IGN);
806 #endif
807 #ifdef SIGTTOU
808             signal(SIGTTOU, SIG_IGN);
809 #endif
810             execute(t, -1, NULL, NULL, TRUE);
811
812             cleanup_until(&paraml1);
813         }
814     }
815     cleanup_until(&pvec[1]);
816     c = 0;
817     ip = NULL;
818     do {
819         ssize_t     cnt = 0;
820
821         for (;;) {
822             if (icnt == 0) {
823                 ip = ibuf;
824                 icnt = wide_read(pvec[0], ibuf, BUFSIZE, 0);
825                 if (icnt <= 0)
826                     goto eof;
827             }
828             if (hadnl)
829                 break;
830             --icnt;
831             c = (*ip++ & TRIM);
832             if (c == 0)
833                 break;
834 #if defined(WINNT_NATIVE) || defined(__CYGWIN__)
835             if (c == '\r')
836                 c = ' ';
837 #endif /* WINNT_NATIVE || __CYGWIN__ */
838             if (c == '\n') {
839                 /*
840                  * Continue around the loop one more time, so that we can eat
841                  * the last newline without terminating this word.
842                  */
843                 hadnl = 1;
844                 continue;
845             }
846             if (!quoted && (c == ' ' || c == '\t'))
847                 break;
848             cnt++;
849             if (c == '\\' || quoted)
850                 c |= QUOTE;
851             Strbuf_append1(word, c);
852         }
853         /*
854          * Unless at end-of-file, we will form a new word here if there were
855          * characters in the word, or in any case when we take text literally.
856          * If we didn't make empty words here when literal was set then we
857          * would lose blank lines.
858          */
859         if (c != 0 && (cnt || literal))
860             pword(bb, word);
861         hadnl = 0;
862     } while (c > 0);
863  eof:
864     cleanup_until(&pvec[0]);
865     pwait();
866     cleanup_until(&faket); /* psavejob_cleanup(); */
867 }
868
869 static void
870 pword(struct blk_buf *bb, struct Strbuf *word)
871 {
872     Char *s;
873
874     s = Strbuf_finish(word);
875     bb_append(bb, s);
876     *word = Strbuf_init;
877 }
878
879 int
880 Gmatch(const Char *string, const Char *pattern)
881 {
882     return Gnmatch(string, pattern, NULL);
883 }
884
885 int
886 Gnmatch(const Char *string, const Char *pattern, const Char **endstr)
887 {
888     Char ***fblk, **p;
889     const Char *tstring = string;
890     int    gpol = 1, gres = 0;
891
892     if (*pattern == '^') {
893         gpol = 0;
894         pattern++;
895     }
896
897     fblk = xmalloc(sizeof(Char ***));
898     *fblk = xmalloc(GLOBSPACE * sizeof(Char *));
899     (*fblk)[0] = Strsave(pattern);
900     (*fblk)[1] = NULL;
901
902     cleanup_push(fblk, blk_indirect_cleanup);
903     expbrace(fblk, NULL, GLOBSPACE);
904
905     if (endstr == NULL)
906         /* Exact matches only */
907         for (p = *fblk; *p; p++) 
908             gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0;
909     else {
910         const Char *end;
911
912         /* partial matches */
913         end = Strend(string);
914         for (p = *fblk; *p; p++)
915             if (t_pmatch(string, *p, &tstring, 1) != 0) {
916                 gres |= 1;
917                 if (end > tstring)
918                     end = tstring;
919             }
920         *endstr = end;
921     }
922
923     cleanup_until(fblk);
924     return(gres == gpol);
925
926
927 /* t_pmatch():
928  *      Return 2 on exact match,        
929  *      Return 1 on substring match.
930  *      Return 0 on no match.
931  *      *estr will point to the end of the longest exact or substring match.
932  */
933 int
934 t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs)
935 {
936     Char stringc, patternc, rangec;
937     int     match, negate_range;
938     const Char *pestr, *nstring;
939
940     for (nstring = string;; string = nstring) {
941         stringc = *nstring++ & TRIM;
942         patternc = *pattern++ & TRIM;
943         switch (patternc) {
944         case '\0':
945             *estr = string;
946             return (stringc == '\0' ? 2 : 1);
947         case '?':
948             if (stringc == 0)
949                 return (0);
950             break;
951         case '*':
952             if (!*pattern) {
953                 *estr = Strend(string);
954                 return (2);
955             }
956             pestr = NULL;
957
958             for (;;) {
959                 switch(t_pmatch(string, pattern, estr, cs)) {
960                 case 0:
961                     break;
962                 case 1:
963                     pestr = *estr;/*FIXME: does not guarantee longest match */
964                     break;
965                 case 2:
966                     return 2;
967                 default:
968                     abort();    /* Cannot happen */
969                 }
970                 stringc = *string++ & TRIM;
971                 if (!stringc)
972                     break;
973             }
974
975             if (pestr) {
976                 *estr = pestr;
977                 return 1;
978             }
979             else
980                 return 0;
981
982         case '[':
983             match = 0;
984             if ((negate_range = (*pattern == '^')) != 0)
985                 pattern++;
986             while ((rangec = *pattern++ & TRIM) != '\0') {
987                 if (rangec == ']')
988                     break;
989                 if (match)
990                     continue;
991                 if (*pattern == '-' && pattern[1] != ']') {
992                     Char rangec2;
993                     pattern++;
994                     rangec2 = *pattern++ & TRIM;
995                     match = (globcharcoll(stringc, rangec2, 0) <= 0 &&
996                         globcharcoll(rangec, stringc, 0) <= 0);
997                 }
998                 else 
999                     match = (stringc == rangec);
1000             }
1001             if (rangec == '\0')
1002                 stderror(ERR_NAME | ERR_MISSING, ']');
1003             if ((!match) && (stringc == '\0'))
1004                 return (0);
1005             if (match == negate_range)
1006                 return (0);
1007             break;
1008         default:
1009             if (cs ? patternc  != stringc
1010                 : Tolower(patternc) != Tolower(stringc))
1011                 return (0);
1012             break;
1013         }
1014     }
1015 }