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