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