1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | #include <sys/types.h> |
34 | #include <glob.h> |
35 | #include <errno.h> |
36 | #include <stdlib.h> |
37 | #include <string.h> |
38 | #include <unistd.h> |
39 | #include <limits.h> |
40 | #include <stdarg.h> |
41 | |
42 | #include "csh.h" |
43 | #include "extern.h" |
44 | |
45 | static int noglob; |
46 | static int pargsiz, gargsiz; |
47 | |
48 | |
49 | |
50 | |
51 | #define G_NONE 0 /* No globbing needed */ |
52 | #define G_GLOB 1 /* string contains *?[] characters */ |
53 | #define G_CSH 2 /* string contains ~`{ characters */ |
54 | |
55 | #define GLOBSPACE 100 /* Alloc increment */ |
56 | |
57 | #define LBRC '{' |
58 | #define RBRC '}' |
59 | #define LBRK '[' |
60 | #define RBRK ']' |
61 | #define EOS '\0' |
62 | |
63 | Char **gargv = NULL; |
64 | long gargc = 0; |
65 | Char **pargv = NULL; |
66 | long pargc = 0; |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | static Char *globtilde(Char **, Char *); |
78 | static Char **libglob(Char **); |
79 | static Char **globexpand(Char **); |
80 | static int globbrace(Char *, Char *, Char ***); |
81 | static void expbrace(Char ***, Char ***, int); |
82 | static int pmatch(Char *, Char *); |
83 | static void pword(void); |
84 | static void psave(int); |
85 | static void backeval(Char *, bool); |
86 | |
87 | |
88 | static Char * |
89 | globtilde(Char **nv, Char *s) |
90 | { |
91 | Char gbuf[PATH_MAX], *gstart, *b, *u, *e; |
92 | |
93 | gstart = gbuf; |
94 | *gstart++ = *s++; |
95 | u = s; |
96 | for (b = gstart, e = &gbuf[PATH_MAX - 1]; |
97 | *s && *s != '/' && *s != ':' && b < e; |
98 | *b++ = *s++) |
99 | continue; |
100 | *b = EOS; |
101 | if (gethdir(gstart, &gbuf[sizeof(gbuf)/sizeof(Char)] - gstart)) { |
102 | blkfree(nv); |
103 | if (*gstart) |
104 | stderror(ERR_UNKUSER, vis_str(gstart)); |
105 | else |
106 | stderror(ERR_NOHOME); |
107 | } |
108 | b = &gstart[Strlen(gstart)]; |
109 | while (*s) |
110 | *b++ = *s++; |
111 | *b = EOS; |
112 | --u; |
113 | free(u); |
114 | return (Strsave(gstart)); |
115 | } |
116 | |
117 | static int |
118 | globbrace(Char *s, Char *p, Char ***bl) |
119 | { |
120 | int i, len; |
121 | Char *pm, *pe, *lm, *pl; |
122 | Char **nv, **vl; |
123 | Char gbuf[PATH_MAX]; |
124 | int size = GLOBSPACE; |
125 | |
126 | nv = vl = xreallocarray(NULL, size, sizeof(Char *)); |
127 | *vl = NULL; |
128 | |
129 | len = 0; |
130 | |
131 | for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) |
132 | continue; |
133 | |
134 | |
135 | for (i = 0, pe = ++p; *pe; pe++) |
136 | if (*pe == LBRK) { |
137 | |
138 | for (++pe; *pe != RBRK && *pe != EOS; pe++) |
139 | continue; |
140 | if (*pe == EOS) { |
141 | blkfree(nv); |
142 | return (-RBRK); |
143 | } |
144 | } |
145 | else if (*pe == LBRC) |
146 | i++; |
147 | else if (*pe == RBRC) { |
148 | if (i == 0) |
149 | break; |
150 | i--; |
151 | } |
152 | |
153 | if (i != 0 || *pe == '\0') { |
154 | blkfree(nv); |
155 | return (-RBRC); |
156 | } |
157 | |
158 | for (i = 0, pl = pm = p; pm <= pe; pm++) |
159 | switch (*pm) { |
160 | case LBRK: |
161 | for (++pm; *pm != RBRK && *pm != EOS; pm++) |
162 | continue; |
163 | if (*pm == EOS) { |
164 | *vl = NULL; |
165 | blkfree(nv); |
166 | return (-RBRK); |
167 | } |
168 | break; |
169 | case LBRC: |
170 | i++; |
171 | break; |
172 | case RBRC: |
173 | if (i) { |
174 | i--; |
175 | break; |
176 | } |
177 | |
178 | case ',': |
179 | if (i && *pm == ',') |
180 | break; |
181 | else { |
182 | Char savec = *pm; |
183 | |
184 | *pm = EOS; |
185 | (void) Strlcpy(lm, pl, &gbuf[sizeof(gbuf)/sizeof(Char)] - lm); |
186 | (void) Strlcat(gbuf, pe + 1, PATH_MAX); |
187 | *pm = savec; |
188 | *vl++ = Strsave(gbuf); |
189 | len++; |
190 | pl = pm + 1; |
191 | if (vl == &nv[size]) { |
192 | size += GLOBSPACE; |
193 | nv = xreallocarray(nv, size, sizeof(Char *)); |
194 | vl = &nv[size - GLOBSPACE]; |
195 | } |
196 | } |
197 | break; |
198 | default: |
199 | break; |
200 | } |
201 | *vl = NULL; |
202 | *bl = nv; |
203 | return (len); |
204 | } |
205 | |
206 | |
207 | static void |
208 | expbrace(Char ***nvp, Char ***elp, int size) |
209 | { |
210 | Char **vl, **el, **nv, *s; |
211 | |
212 | vl = nv = *nvp; |
213 | if (elp != NULL) |
| |
214 | el = *elp; |
215 | else |
216 | for (el = vl; *el; el++) |
| 5 | | Loop condition is true. Entering loop body | |
|
| 7 | | Loop condition is false. Execution continues on line 219 | |
|
217 | continue; |
| 6 | | Execution continues on line 216 | |
|
218 | |
219 | for (s = *vl; s; s = *++vl) { |
| 8 | | Loop condition is true. Entering loop body | |
|
220 | Char *b; |
221 | Char **vp, **bp; |
222 | |
223 | |
224 | if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0'))) |
| 9 | | Assuming the condition is false | |
|
225 | continue; |
226 | if ((b = Strchr(s, '{')) != NULL) { |
| 10 | | Assuming the condition is true | |
|
| |
227 | Char **bl; |
228 | int len; |
229 | |
230 | if ((len = globbrace(s, b, &bl)) < 0) { |
| 12 | | Assuming the condition is true | |
|
| |
231 | free(nv); |
| |
232 | stderror(ERR_MISSING, -len); |
233 | } |
234 | free(s); |
235 | if (len == 1) { |
| |
236 | *vl-- = *bl; |
237 | free(bl); |
238 | continue; |
239 | } |
240 | len = blklen(bl); |
241 | if (&el[len] >= &nv[size]) { |
| 16 | | Assuming the condition is true | |
|
| |
242 | int l, e; |
243 | |
244 | l = &el[len] - &nv[size]; |
245 | size += GLOBSPACE > l ? GLOBSPACE : l; |
| 18 | | Assuming 'l' is < GLOBSPACE | |
|
| |
246 | l = vl - nv; |
247 | e = el - nv; |
248 | nv = xreallocarray(nv, size, sizeof(Char *)); |
| 20 | | Use of memory after it is freed |
|
249 | vl = nv + l; |
250 | el = nv + e; |
251 | } |
252 | vp = vl--; |
253 | *vp = *bl; |
254 | len--; |
255 | for (bp = el; bp != vp; bp--) |
256 | bp[len] = *bp; |
257 | el += len; |
258 | vp++; |
259 | for (bp = bl + 1; *bp; *vp++ = *bp++) |
260 | continue; |
261 | free(bl); |
262 | } |
263 | |
264 | } |
265 | if (elp != NULL) |
266 | *elp = el; |
267 | *nvp = nv; |
268 | } |
269 | |
270 | static Char ** |
271 | globexpand(Char **v) |
272 | { |
273 | Char *s; |
274 | Char **nv, **vl, **el; |
275 | int size = GLOBSPACE; |
276 | |
277 | |
278 | nv = vl = xreallocarray(NULL, size, sizeof(Char *)); |
279 | *vl = NULL; |
280 | |
281 | |
282 | |
283 | |
284 | while ((s = *v++) != NULL) { |
285 | if (Strchr(s, '`')) { |
286 | int i; |
287 | |
288 | (void) dobackp(s, 0); |
289 | for (i = 0; i < pargc; i++) { |
290 | *vl++ = pargv[i]; |
291 | if (vl == &nv[size]) { |
292 | size += GLOBSPACE; |
293 | nv = xreallocarray(nv, size, sizeof(Char *)); |
294 | vl = &nv[size - GLOBSPACE]; |
295 | } |
296 | } |
297 | free(pargv); |
298 | pargv = NULL; |
299 | } |
300 | else { |
301 | *vl++ = Strsave(s); |
302 | if (vl == &nv[size]) { |
303 | size += GLOBSPACE; |
304 | nv = xreallocarray(nv, size, sizeof(Char *)); |
305 | vl = &nv[size - GLOBSPACE]; |
306 | } |
307 | } |
308 | } |
309 | *vl = NULL; |
310 | |
311 | if (noglob) |
312 | return (nv); |
313 | |
314 | |
315 | |
316 | |
317 | el = vl; |
318 | expbrace(&nv, &el, size); |
319 | |
320 | |
321 | |
322 | |
323 | vl = nv; |
324 | for (s = *vl; s; s = *++vl) |
325 | if (*s == '~') |
326 | *vl = globtilde(nv, s); |
327 | vl = nv; |
328 | return (vl); |
329 | } |
330 | |
331 | static Char * |
332 | handleone(Char *str, Char **vl, int action) |
333 | { |
334 | |
335 | Char *cp, **vlp = vl; |
336 | |
337 | switch (action) { |
338 | case G_ERROR: |
339 | setname(vis_str(str)); |
340 | blkfree(vl); |
341 | stderror(ERR_NAME | ERR_AMBIG); |
342 | break; |
343 | case G_APPEND: |
344 | trim(vlp); |
345 | str = Strsave(*vlp++); |
346 | do { |
347 | cp = Strspl(str, STRspace); |
348 | free(str); |
349 | str = Strspl(cp, *vlp); |
350 | free(cp); |
351 | } |
352 | while (*++vlp) |
353 | ; |
354 | blkfree(vl); |
355 | break; |
356 | case G_IGNORE: |
357 | str = Strsave(strip(*vlp)); |
358 | blkfree(vl); |
359 | break; |
360 | default: |
361 | break; |
362 | } |
363 | return (str); |
364 | } |
365 | |
366 | static Char ** |
367 | libglob(Char **vl) |
368 | { |
369 | int gflgs = GLOB_QUOTE | GLOB_NOMAGIC; |
370 | glob_t globv; |
371 | char *ptr; |
372 | int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; |
373 | |
374 | if (!vl || !vl[0]) |
375 | return (vl); |
376 | |
377 | globv.gl_offs = 0; |
378 | globv.gl_pathv = 0; |
379 | globv.gl_pathc = 0; |
380 | |
381 | if (nonomatch) |
382 | gflgs |= GLOB_NOCHECK; |
383 | |
384 | do { |
385 | ptr = short2qstr(*vl); |
386 | switch (glob(ptr, gflgs, 0, &globv)) { |
387 | case GLOB_ABORTED: |
388 | setname(vis_str(*vl)); |
389 | stderror(ERR_NAME | ERR_GLOB); |
390 | |
391 | case GLOB_NOSPACE: |
392 | stderror(ERR_NOMEM); |
393 | |
394 | default: |
395 | break; |
396 | } |
397 | if (globv.gl_flags & GLOB_MAGCHAR) { |
398 | match |= (globv.gl_matchc != 0); |
399 | magic = 1; |
400 | } |
401 | gflgs |= GLOB_APPEND; |
402 | } |
403 | while (*++vl) |
404 | ; |
405 | vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? |
406 | NULL : blk2short(globv.gl_pathv); |
407 | globfree(&globv); |
408 | return (vl); |
409 | } |
410 | |
411 | Char * |
412 | globone(Char *str, int action) |
413 | { |
414 | Char *v[2], **vl, **vo; |
415 | int gflg; |
416 | |
417 | noglob = adrof(STRnoglob) != 0; |
418 | gflag = 0; |
419 | v[0] = str; |
420 | v[1] = 0; |
421 | tglob(v); |
422 | gflg = gflag; |
423 | if (gflg == G_NONE) |
424 | return (strip(Strsave(str))); |
425 | |
426 | if (gflg & G_CSH) { |
427 | |
428 | |
429 | |
430 | vo = globexpand(v); |
431 | if (noglob || (gflg & G_GLOB) == 0) { |
432 | if (vo[0] == NULL) { |
433 | free(vo); |
434 | return (Strsave(STRNULL)); |
435 | } |
436 | if (vo[1] != NULL) |
437 | return (handleone(str, vo, action)); |
438 | else { |
439 | str = strip(vo[0]); |
440 | free(vo); |
441 | return (str); |
442 | } |
443 | } |
444 | } |
445 | else if (noglob || (gflg & G_GLOB) == 0) |
446 | return (strip(Strsave(str))); |
447 | else |
448 | vo = v; |
449 | |
450 | vl = libglob(vo); |
451 | if ((gflg & G_CSH) && vl != vo) |
452 | blkfree(vo); |
453 | if (vl == NULL) { |
454 | setname(vis_str(str)); |
455 | stderror(ERR_NAME | ERR_NOMATCH); |
456 | } |
457 | if (vl[0] == NULL) { |
458 | free(vl); |
459 | return (Strsave(STRNULL)); |
460 | } |
461 | if (vl[1] != NULL) |
462 | return (handleone(str, vl, action)); |
463 | else { |
464 | str = strip(*vl); |
465 | free(vl); |
466 | return (str); |
467 | } |
468 | } |
469 | |
470 | Char ** |
471 | globall(Char **v) |
472 | { |
473 | Char **vl, **vo; |
474 | int gflg = gflag; |
475 | |
476 | if (!v || !v[0]) { |
477 | gargv = saveblk(v); |
478 | gargc = blklen(gargv); |
479 | return (gargv); |
480 | } |
481 | |
482 | noglob = adrof(STRnoglob) != 0; |
483 | |
484 | if (gflg & G_CSH) |
485 | |
486 | |
487 | |
488 | vl = vo = globexpand(v); |
489 | else |
490 | vl = vo = saveblk(v); |
491 | |
492 | if (!noglob && (gflg & G_GLOB)) { |
493 | vl = libglob(vo); |
494 | if ((gflg & G_CSH) && vl != vo) |
495 | blkfree(vo); |
496 | } |
497 | else |
498 | trim(vl); |
499 | |
500 | gargc = vl ? blklen(vl) : 0; |
501 | return (gargv = vl); |
502 | } |
503 | |
504 | void |
505 | ginit(void) |
506 | { |
507 | gargsiz = GLOBSPACE; |
508 | gargv = xreallocarray(NULL, gargsiz, sizeof(Char *)); |
509 | gargv[0] = 0; |
510 | gargc = 0; |
511 | } |
512 | |
513 | void |
514 | rscan(Char **t, void (*f)(int)) |
515 | { |
516 | Char *p; |
517 | |
518 | while ((p = *t++) != NULL) |
519 | while (*p) |
520 | (*f) (*p++); |
521 | } |
522 | |
523 | void |
524 | trim(Char **t) |
525 | { |
526 | Char *p; |
527 | |
528 | while ((p = *t++) != NULL) |
529 | while (*p) |
530 | *p++ &= TRIM; |
531 | } |
532 | |
533 | void |
534 | tglob(Char **t) |
535 | { |
536 | Char *p, c; |
537 | |
538 | while ((p = *t++) != NULL) { |
539 | if (*p == '~' || *p == '=') |
540 | gflag |= G_CSH; |
541 | else if (*p == '{' && |
542 | (p[1] == '\0' || (p[1] == '}' && p[2] == '\0'))) |
543 | continue; |
544 | while ((c = *p++) != '\0') { |
545 | |
546 | |
547 | |
548 | if (c == '`') { |
549 | gflag |= G_CSH; |
550 | while (*p && *p != '`') |
551 | if (*p++ == '\\') { |
552 | if (*p) |
553 | p++; |
554 | else |
555 | break; |
556 | } |
557 | if (*p) |
558 | p++; |
559 | else |
560 | break; |
561 | } |
562 | else if (c == '{') |
563 | gflag |= G_CSH; |
564 | else if (isglob(c)) |
565 | gflag |= G_GLOB; |
566 | } |
567 | } |
568 | } |
569 | |
570 | |
571 | |
572 | |
573 | |
574 | |
575 | Char ** |
576 | dobackp(Char *cp, bool literal) |
577 | { |
578 | Char *lp, *rp; |
579 | Char *ep, word[PATH_MAX]; |
580 | |
581 | blkfree(pargv); |
582 | pargsiz = GLOBSPACE; |
583 | pargv = xreallocarray(NULL, pargsiz, sizeof(Char *)); |
584 | pargv[0] = NULL; |
585 | pargcp = pargs = word; |
586 | pargc = 0; |
587 | pnleft = PATH_MAX - 4; |
588 | for (;;) { |
589 | for (lp = cp; *lp != '`'; lp++) { |
590 | if (*lp == 0) { |
591 | if (pargcp != pargs) |
592 | pword(); |
593 | return (pargv); |
594 | } |
595 | psave(*lp); |
596 | } |
597 | lp++; |
598 | for (rp = lp; *rp && *rp != '`'; rp++) |
599 | if (*rp == '\\') { |
600 | rp++; |
601 | if (!*rp) |
602 | goto oops; |
603 | } |
604 | if (!*rp) |
605 | oops: stderror(ERR_UNMATCHED, '`'); |
606 | ep = Strsave(lp); |
607 | ep[rp - lp] = 0; |
608 | backeval(ep, literal); |
609 | cp = rp + 1; |
610 | } |
611 | } |
612 | |
613 | static void |
614 | backeval(Char *cp, bool literal) |
615 | { |
616 | int icnt, c; |
617 | Char *ip; |
618 | struct command faket; |
619 | bool hadnl; |
620 | int pvec[2], quoted; |
621 | Char *fakecom[2], ibuf[BUFSIZ]; |
622 | char tibuf[BUFSIZ]; |
623 | |
624 | hadnl = 0; |
625 | icnt = 0; |
626 | quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; |
627 | faket.t_dtyp = NODE_COMMAND; |
628 | faket.t_dflg = 0; |
629 | faket.t_dlef = 0; |
630 | faket.t_drit = 0; |
631 | faket.t_dspr = 0; |
632 | faket.t_dcom = fakecom; |
633 | fakecom[0] = STRfakecom1; |
634 | fakecom[1] = 0; |
635 | |
636 | |
637 | |
638 | |
639 | |
640 | |
641 | |
642 | |
643 | psavejob(); |
644 | |
645 | |
646 | |
647 | |
648 | |
649 | |
650 | mypipe(pvec); |
651 | if (pfork(&faket, -1) == 0) { |
652 | struct wordent paraml; |
653 | struct command *t; |
654 | |
655 | (void) close(pvec[0]); |
656 | (void) dmove(pvec[1], 1); |
657 | (void) dmove(SHERR, 2); |
658 | initdesc(); |
659 | |
660 | |
661 | |
662 | |
663 | if (pargv) |
664 | blkfree(pargv), pargv = 0, pargsiz = 0; |
665 | |
666 | arginp = cp; |
667 | while (*cp) |
668 | *cp++ &= TRIM; |
669 | |
670 | |
671 | |
672 | |
673 | |
674 | alvec = NULL; |
675 | evalvec = NULL; |
676 | alvecp = NULL; |
677 | evalp = NULL; |
678 | (void) lex(¶ml); |
679 | if (seterr) |
680 | stderror(ERR_OLD); |
681 | alias(¶ml); |
682 | t = syntax(paraml.next, ¶ml, 0); |
683 | if (seterr) |
684 | stderror(ERR_OLD); |
685 | if (t) |
686 | t->t_dflg |= F_NOFORK; |
687 | (void) signal(SIGTSTP, SIG_IGN); |
688 | (void) signal(SIGTTIN, SIG_IGN); |
689 | (void) signal(SIGTTOU, SIG_IGN); |
690 | execute(t, -1, NULL, NULL); |
691 | exitstat(); |
692 | } |
693 | free(cp); |
694 | (void) close(pvec[1]); |
695 | c = 0; |
696 | ip = NULL; |
697 | do { |
698 | int cnt = 0; |
699 | |
700 | for (;;) { |
701 | if (icnt == 0) { |
702 | int i; |
703 | |
704 | ip = ibuf; |
705 | do |
706 | icnt = read(pvec[0], tibuf, BUFSIZ); |
707 | while (icnt == -1 && errno == EINTR); |
708 | if (icnt <= 0) { |
709 | c = -1; |
710 | break; |
711 | } |
712 | for (i = 0; i < icnt; i++) |
713 | ip[i] = (unsigned char) tibuf[i]; |
714 | } |
715 | if (hadnl) |
716 | break; |
717 | --icnt; |
718 | c = (*ip++ & TRIM); |
719 | if (c == 0) |
720 | break; |
721 | if (c == '\n') { |
722 | |
723 | |
724 | |
725 | |
726 | hadnl = 1; |
727 | continue; |
728 | } |
729 | if (!quoted && (c == ' ' || c == '\t')) |
730 | break; |
731 | cnt++; |
732 | psave(c | quoted); |
733 | } |
734 | |
735 | |
736 | |
737 | |
738 | |
739 | |
740 | if (c != -1 && (cnt || literal)) |
741 | pword(); |
742 | hadnl = 0; |
743 | } while (c >= 0); |
744 | (void) close(pvec[0]); |
745 | pwait(); |
746 | prestjob(); |
747 | } |
748 | |
749 | static void |
750 | psave(int c) |
751 | { |
752 | if (--pnleft <= 0) |
753 | stderror(ERR_WTOOLONG); |
754 | *pargcp++ = c; |
755 | } |
756 | |
757 | static void |
758 | pword(void) |
759 | { |
760 | psave(0); |
761 | if (pargc == pargsiz - 1) { |
762 | pargsiz += GLOBSPACE; |
763 | pargv = xreallocarray(pargv, pargsiz, sizeof(Char *)); |
764 | } |
765 | pargv[pargc++] = Strsave(pargs); |
766 | pargv[pargc] = NULL; |
767 | pargcp = pargs; |
768 | pnleft = PATH_MAX - 4; |
769 | } |
770 | |
771 | int |
772 | Gmatch(Char *string, Char *pattern) |
773 | { |
774 | Char **blk, **p; |
775 | int gpol = 1, gres = 0; |
776 | |
777 | if (*pattern == '^') { |
| 1 | Assuming the condition is false | |
|
| |
778 | gpol = 0; |
779 | pattern++; |
780 | } |
781 | |
782 | blk = xreallocarray(NULL, GLOBSPACE, sizeof(Char *)); |
783 | blk[0] = Strsave(pattern); |
784 | blk[1] = NULL; |
785 | |
786 | expbrace(&blk, NULL, GLOBSPACE); |
| |
787 | |
788 | for (p = blk; *p; p++) |
789 | gres |= pmatch(string, *p); |
790 | |
791 | blkfree(blk); |
792 | return(gres == gpol); |
793 | } |
794 | |
795 | static int |
796 | pmatch(Char *string, Char *pattern) |
797 | { |
798 | Char stringc, patternc; |
799 | int match, negate_range; |
800 | Char rangec; |
801 | |
802 | for (;; ++string) { |
803 | stringc = *string & TRIM; |
804 | patternc = *pattern++; |
805 | switch (patternc) { |
806 | case 0: |
807 | return (stringc == 0); |
808 | case '?': |
809 | if (stringc == 0) |
810 | return (0); |
811 | break; |
812 | case '*': |
813 | if (!*pattern) |
814 | return (1); |
815 | while (*string) |
816 | if (Gmatch(string++, pattern)) |
817 | return (1); |
818 | return (0); |
819 | case '[': |
820 | match = 0; |
821 | if ((negate_range = (*pattern == '^')) != 0) |
822 | pattern++; |
823 | while ((rangec = *pattern++) != '\0') { |
824 | if (rangec == ']') |
825 | break; |
826 | if (match) |
827 | continue; |
828 | if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') { |
829 | match = (stringc <= (*pattern & TRIM) && |
830 | (*(pattern-2) & TRIM) <= stringc); |
831 | pattern++; |
832 | } |
833 | else |
834 | match = (stringc == (rangec & TRIM)); |
835 | } |
836 | if (rangec == 0) |
837 | stderror(ERR_NAME | ERR_MISSING, ']'); |
838 | if (match == negate_range) |
839 | return (0); |
840 | break; |
841 | default: |
842 | if ((patternc & TRIM) != stringc) |
843 | return (0); |
844 | break; |
845 | |
846 | } |
847 | } |
848 | } |
849 | |
850 | void |
851 | Gcat(Char *s1, Char *s2) |
852 | { |
853 | Char *p, *q; |
854 | int n; |
855 | |
856 | for (p = s1; *p++;) |
857 | continue; |
858 | for (q = s2; *q++;) |
859 | continue; |
860 | n = (p - s1) + (q - s2) - 1; |
861 | if (++gargc >= gargsiz) { |
862 | gargsiz += GLOBSPACE; |
863 | gargv = xreallocarray(gargv, gargsiz, sizeof(Char *)); |
864 | } |
865 | gargv[gargc] = 0; |
866 | p = gargv[gargc - 1] = xreallocarray(NULL, n, sizeof(Char)); |
867 | for (q = s1; (*p++ = *q++) != '\0';) |
868 | continue; |
869 | for (p--, q = s2; (*p++ = *q++) != '\0';) |
870 | continue; |
871 | } |
872 | |
873 | int |
874 | sortscmp(const void *a, const void *b) |
875 | { |
876 | char buf[2048]; |
877 | |
878 | if (!a) |
879 | return (b ? 1 : 0); |
880 | if (!b) |
881 | return (-1); |
882 | |
883 | if (!*(Char **)a) |
884 | return (*(Char **)b ? 1 : 0); |
885 | if (!*(Char **)b) |
886 | return (-1); |
887 | |
888 | (void) strlcpy(buf, short2str(*(Char **)a), sizeof buf); |
889 | return ((int) strcoll(buf, short2str(*(Char **)b))); |
890 | } |