1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.glob.c,v 3.82 2011/02/27 00:15:17 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.82 2011/02/27 00:15:17 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 *
globtilde(Char * s)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 *
globequal(Char * old)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
globbrace(const Char * s,Char *** bl)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
expbrace(Char *** nvp,Char *** elp,int size)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 **
globexpand(Char ** v,int noglob)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 *
handleone(Char * str,Char ** vl,int action)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 **
libglob(Char ** vl)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 *
globone(Char * str,int action)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 **
globall(Char ** v,int gflg)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 **
glob_all_or_error(Char ** v)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
rscan(Char ** t,void (* f)(Char))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
trim(Char ** t)592 trim(Char **t)
593 {
594 Char *p;
595
596 while ((p = *t++) != '\0')
597 while (*p)
598 *p++ &= TRIM;
599 }
600
601 int
tglob(Char ** t)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 **
dobackp(Char * cp,int literal)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
backeval(struct blk_buf * bb,struct Strbuf * word,Char * cp,int literal)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(¶ml);
779 cleanup_push(¶ml, lex_cleanup);
780 if (seterr)
781 stderror(ERR_OLD);
782 alias(¶ml);
783 t = syntax(paraml.next, ¶ml, 0);
784 if (t == NULL)
785 return;
786 cleanup_push(t, syntax_cleanup);
787 /* The F_BACKQ flag must set so the job output is correct if
788 * printexitvalue is set. If it's not set, the job output
789 * will have "Exit N" appended where N is the exit status. */
790 t->t_dflg = F_BACKQ|F_NOFORK;
791 if (seterr)
792 stderror(ERR_OLD);
793 #ifdef SIGTSTP
794 signal(SIGTSTP, SIG_IGN);
795 #endif
796 #ifdef SIGTTIN
797 signal(SIGTTIN, SIG_IGN);
798 #endif
799 #ifdef SIGTTOU
800 signal(SIGTTOU, SIG_IGN);
801 #endif
802 execute(t, -1, NULL, NULL, TRUE);
803
804 cleanup_until(¶ml);
805 }
806 }
807 cleanup_until(&pvec[1]);
808 c = 0;
809 ip = NULL;
810 do {
811 ssize_t cnt = 0;
812 char *tmp;
813
814 tmp = tibuf;
815 for (;;) {
816 while (icnt == 0) {
817 int i, eof;
818
819 ip = ibuf;
820 icnt = xread(pvec[0], tmp, tibuf + BUFSIZE - tmp);
821 eof = 0;
822 if (icnt <= 0) {
823 if (tmp == tibuf)
824 goto eof;
825 icnt = 0;
826 eof = 1;
827 }
828 icnt += tmp - tibuf;
829 i = 0;
830 tmp = tibuf;
831 while (tmp < tibuf + icnt) {
832 int len;
833
834 len = normal_mbtowc(&ip[i], tmp, tibuf + icnt - tmp);
835 if (len == -1) {
836 reset_mbtowc();
837 if (!eof && (size_t)(tibuf + icnt - tmp) < MB_CUR_MAX) {
838 break; /* Maybe a partial character */
839 }
840 ip[i] = (unsigned char) *tmp | INVALID_BYTE; /* Error */
841 }
842 if (len <= 0)
843 len = 1;
844 i++;
845 tmp += len;
846 }
847 if (tmp != tibuf)
848 memmove (tibuf, tmp, tibuf + icnt - tmp);
849 tmp = tibuf + (tibuf + icnt - tmp);
850 icnt = i;
851 }
852 if (hadnl)
853 break;
854 --icnt;
855 c = (*ip++ & TRIM);
856 if (c == 0)
857 break;
858 #if defined(WINNT_NATIVE) || defined(__CYGWIN__)
859 if (c == '\r')
860 c = ' ';
861 #endif /* WINNT_NATIVE || __CYGWIN__ */
862 if (c == '\n') {
863 /*
864 * Continue around the loop one more time, so that we can eat
865 * the last newline without terminating this word.
866 */
867 hadnl = 1;
868 continue;
869 }
870 if (!quoted && (c == ' ' || c == '\t'))
871 break;
872 cnt++;
873 Strbuf_append1(word, c | quoted);
874 }
875 /*
876 * Unless at end-of-file, we will form a new word here if there were
877 * characters in the word, or in any case when we take text literally.
878 * If we didn't make empty words here when literal was set then we
879 * would lose blank lines.
880 */
881 if (c != 0 && (cnt || literal))
882 pword(bb, word);
883 hadnl = 0;
884 } while (c > 0);
885 eof:
886 cleanup_until(&pvec[0]);
887 pwait();
888 cleanup_until(&faket); /* psavejob_cleanup(); */
889 }
890
891 static void
pword(struct blk_buf * bb,struct Strbuf * word)892 pword(struct blk_buf *bb, struct Strbuf *word)
893 {
894 Char *s;
895
896 s = Strbuf_finish(word);
897 bb_append(bb, s);
898 *word = Strbuf_init;
899 }
900
901 int
Gmatch(const Char * string,const Char * pattern)902 Gmatch(const Char *string, const Char *pattern)
903 {
904 return Gnmatch(string, pattern, NULL);
905 }
906
907 int
Gnmatch(const Char * string,const Char * pattern,const Char ** endstr)908 Gnmatch(const Char *string, const Char *pattern, const Char **endstr)
909 {
910 Char ***fblk, **p;
911 const Char *tstring = string;
912 int gpol = 1, gres = 0;
913
914 if (*pattern == '^') {
915 gpol = 0;
916 pattern++;
917 }
918
919 fblk = xmalloc(sizeof(Char ***));
920 *fblk = xmalloc(GLOBSPACE * sizeof(Char *));
921 (*fblk)[0] = Strsave(pattern);
922 (*fblk)[1] = NULL;
923
924 cleanup_push(fblk, blk_indirect_cleanup);
925 expbrace(fblk, NULL, GLOBSPACE);
926
927 if (endstr == NULL)
928 /* Exact matches only */
929 for (p = *fblk; *p; p++)
930 gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0;
931 else {
932 const Char *end;
933
934 /* partial matches */
935 end = Strend(string);
936 for (p = *fblk; *p; p++)
937 if (t_pmatch(string, *p, &tstring, 1) != 0) {
938 gres |= 1;
939 if (end > tstring)
940 end = tstring;
941 }
942 *endstr = end;
943 }
944
945 cleanup_until(fblk);
946 return(gres == gpol);
947 }
948
949 /* t_pmatch():
950 * Return 2 on exact match,
951 * Return 1 on substring match.
952 * Return 0 on no match.
953 * *estr will point to the end of the longest exact or substring match.
954 */
955 int
t_pmatch(const Char * string,const Char * pattern,const Char ** estr,int cs)956 t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs)
957 {
958 Char stringc, patternc, rangec;
959 int match, negate_range;
960 const Char *pestr, *nstring;
961
962 for (nstring = string;; string = nstring) {
963 stringc = *nstring++ & TRIM;
964 patternc = *pattern++ & TRIM;
965 switch (patternc) {
966 case '\0':
967 *estr = string;
968 return (stringc == '\0' ? 2 : 1);
969 case '?':
970 if (stringc == 0)
971 return (0);
972 break;
973 case '*':
974 if (!*pattern) {
975 *estr = Strend(string);
976 return (2);
977 }
978 pestr = NULL;
979
980 for (;;) {
981 switch(t_pmatch(string, pattern, estr, cs)) {
982 case 0:
983 break;
984 case 1:
985 pestr = *estr;/*FIXME: does not guarantee longest match */
986 break;
987 case 2:
988 return 2;
989 default:
990 abort(); /* Cannot happen */
991 }
992 stringc = *string++ & TRIM;
993 if (!stringc)
994 break;
995 }
996
997 if (pestr) {
998 *estr = pestr;
999 return 1;
1000 }
1001 else
1002 return 0;
1003
1004 case '[':
1005 match = 0;
1006 if ((negate_range = (*pattern == '^')) != 0)
1007 pattern++;
1008 while ((rangec = *pattern++ & TRIM) != '\0') {
1009 if (rangec == ']')
1010 break;
1011 if (match)
1012 continue;
1013 if (*pattern == '-' && pattern[1] != ']') {
1014 Char rangec2;
1015 pattern++;
1016 rangec2 = *pattern++ & TRIM;
1017 match = (globcharcoll(stringc, rangec2, 0) <= 0 &&
1018 globcharcoll(rangec, stringc, 0) <= 0);
1019 }
1020 else
1021 match = (stringc == rangec);
1022 }
1023 if (rangec == '\0')
1024 stderror(ERR_NAME | ERR_MISSING, ']');
1025 if ((!match) && (stringc == '\0'))
1026 return (0);
1027 if (match == negate_range)
1028 return (0);
1029 break;
1030 default:
1031 if (cs ? patternc != stringc
1032 : Tolower(patternc) != Tolower(stringc))
1033 return (0);
1034 break;
1035 }
1036 }
1037 }
1038