Bug Summary

File:src/bin/csh/glob.c
Warning:line 253, column 10
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name glob.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/bin/csh/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/bin/csh -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/csh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/bin/csh/glob.c
1/* $OpenBSD: glob.c,v 1.23 2018/09/08 01:28:39 miko Exp $ */
2/* $NetBSD: glob.c,v 1.10 1995/03/21 09:03:01 cgd Exp $ */
3
4/*-
5 * Copyright (c) 1980, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34#include <glob.h>
35#include <errno(*__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
45static int noglob;
46static int pargsiz, gargsiz;
47
48/*
49 * Values for gflag
50 */
51#define G_NONE0 0 /* No globbing needed */
52#define G_GLOB1 1 /* string contains *?[] characters */
53#define G_CSH2 2 /* string contains ~`{ characters */
54
55#define GLOBSPACE100 100 /* Alloc increment */
56
57#define LBRC'{' '{'
58#define RBRC'}' '}'
59#define LBRK'[' '['
60#define RBRK']' ']'
61#define EOS'\0' '\0'
62
63Char **gargv = NULL((void *)0);
64long gargc = 0;
65Char **pargv = NULL((void *)0);
66long pargc = 0;
67
68/*
69 * globbing is now done in two stages. In the first pass we expand
70 * csh globbing idioms ~`{ and then we proceed doing the normal
71 * globbing if needed ?*[
72 *
73 * Csh type globbing is handled in globexpand() and the rest is
74 * handled in glob() which is part of the 4.4BSD libc.
75 *
76 */
77static Char *globtilde(Char **, Char *);
78static Char **libglob(Char **);
79static Char **globexpand(Char **);
80static int globbrace(Char *, Char *, Char ***);
81static void expbrace(Char ***, Char ***, int);
82static int pmatch(Char *, Char *);
83static void pword(void);
84static void psave(int);
85static void backeval(Char *, bool);
86
87
88static Char *
89globtilde(Char **nv, Char *s)
90{
91 Char gbuf[PATH_MAX1024], *gstart, *b, *u, *e;
92
93 gstart = gbuf;
94 *gstart++ = *s++;
95 u = s;
96 for (b = gstart, e = &gbuf[PATH_MAX1024 - 1];
97 *s && *s != '/' && *s != ':' && b < e;
98 *b++ = *s++)
99 continue;
100 *b = EOS'\0';
101 if (gethdir(gstart, &gbuf[sizeof(gbuf)/sizeof(Char)] - gstart)) {
102 blkfree(nv);
103 if (*gstart)
104 stderror(ERR_UNKUSER76, vis_str(gstart));
105 else
106 stderror(ERR_NOHOME77);
107 }
108 b = &gstart[Strlen(gstart)];
109 while (*s)
110 *b++ = *s++;
111 *b = EOS'\0';
112 --u;
113 free(u);
114 return (Strsave(gstart));
115}
116
117static int
118globbrace(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_MAX1024];
124 int size = GLOBSPACE100;
125
126 nv = vl = xreallocarray(NULL((void *)0), size, sizeof(Char *));
127 *vl = NULL((void *)0);
128
129 len = 0;
130 /* copy part up to the brace */
131 for (lm = gbuf, p = s; *p != LBRC'{'; *lm++ = *p++)
132 continue;
133
134 /* check for balanced braces */
135 for (i = 0, pe = ++p; *pe; pe++)
136 if (*pe == LBRK'[') {
137 /* Ignore everything between [] */
138 for (++pe; *pe != RBRK']' && *pe != EOS'\0'; pe++)
139 continue;
140 if (*pe == EOS'\0') {
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'\0'; pm++)
162 continue;
163 if (*pm == EOS'\0') {
164 *vl = NULL((void *)0);
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 /* FALLTHROUGH */
178 case ',':
179 if (i && *pm == ',')
180 break;
181 else {
182 Char savec = *pm;
183
184 *pm = EOS'\0';
185 (void) Strlcpy(lm, pl, &gbuf[sizeof(gbuf)/sizeof(Char)] - lm);
186 (void) Strlcat(gbuf, pe + 1, PATH_MAX1024);
187 *pm = savec;
188 *vl++ = Strsave(gbuf);
189 len++;
190 pl = pm + 1;
191 if (vl == &nv[size]) {
192 size += GLOBSPACE100;
193 nv = xreallocarray(nv, size, sizeof(Char *));
194 vl = &nv[size - GLOBSPACE100];
195 }
196 }
197 break;
198 default:
199 break;
200 }
201 *vl = NULL((void *)0);
202 *bl = nv;
203 return (len);
204}
205
206
207static void
208expbrace(Char ***nvp, Char ***elp, int size)
209{
210 Char **vl, **el, **nv, *s;
211
212 vl = nv = *nvp;
213 if (elp
3.1
'elp' is equal to NULL
!= NULL((void *)0))
4
Taking false branch
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 /* leave {} untouched for find */
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((void *)0)) {
10
Assuming the condition is true
11
Taking true branch
227 Char **bl;
228 int len;
229
230 if ((len = globbrace(s, b, &bl)) < 0) {
12
Assuming the condition is true
13
Taking true branch
231 free(nv);
14
Memory is released
232 stderror(ERR_MISSING51, -len);
233 }
234 free(s);
235 if (len
14.1
'len' is not equal to 1
== 1) {
15
Taking false branch
236 *vl-- = *bl;
237 free(bl);
238 continue;
239 }
240 len = blklen(bl);
241 if (&el[len] >= &nv[size]) {
16
Assuming the condition is false
17
Taking false branch
242 int l, e;
243
244 l = &el[len] - &nv[size];
245 size += GLOBSPACE100 > l ? GLOBSPACE100 : l;
246 l = vl - nv;
247 e = el - nv;
248 nv = xreallocarray(nv, size, sizeof(Char *));
249 vl = nv + l;
250 el = nv + e;
251 }
252 vp = vl--;
253 *vp = *bl;
18
Use of memory after it is freed
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((void *)0))
266 *elp = el;
267 *nvp = nv;
268}
269
270static Char **
271globexpand(Char **v)
272{
273 Char *s;
274 Char **nv, **vl, **el;
275 int size = GLOBSPACE100;
276
277
278 nv = vl = xreallocarray(NULL((void *)0), size, sizeof(Char *));
279 *vl = NULL((void *)0);
280
281 /*
282 * Step 1: expand backquotes.
283 */
284 while ((s = *v++) != NULL((void *)0)) {
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 += GLOBSPACE100;
293 nv = xreallocarray(nv, size, sizeof(Char *));
294 vl = &nv[size - GLOBSPACE100];
295 }
296 }
297 free(pargv);
298 pargv = NULL((void *)0);
299 }
300 else {
301 *vl++ = Strsave(s);
302 if (vl == &nv[size]) {
303 size += GLOBSPACE100;
304 nv = xreallocarray(nv, size, sizeof(Char *));
305 vl = &nv[size - GLOBSPACE100];
306 }
307 }
308 }
309 *vl = NULL((void *)0);
310
311 if (noglob)
312 return (nv);
313
314 /*
315 * Step 2: expand braces
316 */
317 el = vl;
318 expbrace(&nv, &el, size);
319
320 /*
321 * Step 3: expand ~
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
331static Char *
332handleone(Char *str, Char **vl, int action)
333{
334
335 Char *cp, **vlp = vl;
336
337 switch (action) {
338 case G_ERROR0:
339 setname(vis_str(str))(bname = (vis_str(str)));
340 blkfree(vl);
341 stderror(ERR_NAME0x10000000 | ERR_AMBIG40);
342 break;
343 case G_APPEND2:
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_IGNORE1:
357 str = Strsave(strip(*vlp));
358 blkfree(vl);
359 break;
360 default:
361 break;
362 }
363 return (str);
364}
365
366static Char **
367libglob(Char **vl)
368{
369 int gflgs = GLOB_QUOTE0x0400 | GLOB_NOMAGIC0x0200;
370 glob_t globv;
371 char *ptr;
372 int nonomatch = adrof(STRnonomatch)adrof1(STRnonomatch, &shvhed) != 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_NOCHECK0x0010;
383
384 do {
385 ptr = short2qstr(*vl);
386 switch (glob(ptr, gflgs, 0, &globv)) {
387 case GLOB_ABORTED(-2):
388 setname(vis_str(*vl))(bname = (vis_str(*vl)));
389 stderror(ERR_NAME0x10000000 | ERR_GLOB13);
390 /* NOTREACHED */
391 case GLOB_NOSPACE(-1):
392 stderror(ERR_NOMEM53);
393 /* NOTREACHED */
394 default:
395 break;
396 }
397 if (globv.gl_flags & GLOB_MAGCHAR0x0100) {
398 match |= (globv.gl_matchc != 0);
399 magic = 1;
400 }
401 gflgs |= GLOB_APPEND0x0001;
402 }
403 while (*++vl)
404 ;
405 vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
406 NULL((void *)0) : blk2short(globv.gl_pathv);
407 globfree(&globv);
408 return (vl);
409}
410
411Char *
412globone(Char *str, int action)
413{
414 Char *v[2], **vl, **vo;
415 int gflg;
416
417 noglob = adrof(STRnoglob)adrof1(STRnoglob, &shvhed) != 0;
418 gflag = 0;
419 v[0] = str;
420 v[1] = 0;
421 tglob(v);
422 gflg = gflag;
423 if (gflg == G_NONE0)
424 return (strip(Strsave(str)));
425
426 if (gflg & G_CSH2) {
427 /*
428 * Expand back-quote, tilde and brace
429 */
430 vo = globexpand(v);
431 if (noglob || (gflg & G_GLOB1) == 0) {
432 if (vo[0] == NULL((void *)0)) {
433 free(vo);
434 return (Strsave(STRNULL));
435 }
436 if (vo[1] != NULL((void *)0))
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_GLOB1) == 0)
446 return (strip(Strsave(str)));
447 else
448 vo = v;
449
450 vl = libglob(vo);
451 if ((gflg & G_CSH2) && vl != vo)
452 blkfree(vo);
453 if (vl == NULL((void *)0)) {
454 setname(vis_str(str))(bname = (vis_str(str)));
455 stderror(ERR_NAME0x10000000 | ERR_NOMATCH50);
456 }
457 if (vl[0] == NULL((void *)0)) {
458 free(vl);
459 return (Strsave(STRNULL));
460 }
461 if (vl[1] != NULL((void *)0))
462 return (handleone(str, vl, action));
463 else {
464 str = strip(*vl);
465 free(vl);
466 return (str);
467 }
468}
469
470Char **
471globall(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)adrof1(STRnoglob, &shvhed) != 0;
483
484 if (gflg & G_CSH2)
485 /*
486 * Expand back-quote, tilde and brace
487 */
488 vl = vo = globexpand(v);
489 else
490 vl = vo = saveblk(v);
491
492 if (!noglob && (gflg & G_GLOB1)) {
493 vl = libglob(vo);
494 if ((gflg & G_CSH2) && vl != vo)
495 blkfree(vo);
496 }
497 else
498 trim(vl);
499
500 gargc = vl ? blklen(vl) : 0;
501 return (gargv = vl);
502}
503
504void
505ginit(void)
506{
507 gargsiz = GLOBSPACE100;
508 gargv = xreallocarray(NULL((void *)0), gargsiz, sizeof(Char *));
509 gargv[0] = 0;
510 gargc = 0;
511}
512
513void
514rscan(Char **t, void (*f)(int))
515{
516 Char *p;
517
518 while ((p = *t++) != NULL((void *)0))
519 while (*p)
520 (*f) (*p++);
521}
522
523void
524trim(Char **t)
525{
526 Char *p;
527
528 while ((p = *t++) != NULL((void *)0))
529 while (*p)
530 *p++ &= TRIM0077777;
531}
532
533void
534tglob(Char **t)
535{
536 Char *p, c;
537
538 while ((p = *t++) != NULL((void *)0)) {
539 if (*p == '~' || *p == '=')
540 gflag |= G_CSH2;
541 else if (*p == '{' &&
542 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
543 continue;
544 while ((c = *p++) != '\0') {
545 /*
546 * eat everything inside the matching backquotes
547 */
548 if (c == '`') {
549 gflag |= G_CSH2;
550 while (*p && *p != '`')
551 if (*p++ == '\\') {
552 if (*p) /* Quoted chars */
553 p++;
554 else
555 break;
556 }
557 if (*p) /* The matching ` */
558 p++;
559 else
560 break;
561 }
562 else if (c == '{')
563 gflag |= G_CSH2;
564 else if (isglob(c)(((c) & 0100000U) ? 0 : (_cmap[(unsigned char)(c)] & (
0x0020)))
)
565 gflag |= G_GLOB1;
566 }
567 }
568}
569
570/*
571 * Command substitute cp. If literal, then this is a substitution from a
572 * << redirection, and so we should not crunch blanks and tabs, separating
573 * words only at newlines.
574 */
575Char **
576dobackp(Char *cp, bool literal)
577{
578 Char *lp, *rp;
579 Char *ep, word[PATH_MAX1024];
580
581 blkfree(pargv);
582 pargsiz = GLOBSPACE100;
583 pargv = xreallocarray(NULL((void *)0), pargsiz, sizeof(Char *));
584 pargv[0] = NULL((void *)0);
585 pargcp = pargs = word;
586 pargc = 0;
587 pnleft = PATH_MAX1024 - 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_UNMATCHED52, '`');
606 ep = Strsave(lp);
607 ep[rp - lp] = 0;
608 backeval(ep, literal);
609 cp = rp + 1;
610 }
611}
612
613static void
614backeval(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[BUFSIZ1024];
622 char tibuf[BUFSIZ1024];
623
624 hadnl = 0;
625 icnt = 0;
626 quoted = (literal || (cp[0] & QUOTE0100000U)) ? QUOTE0100000U : 0;
627 faket.t_dtyp = NODE_COMMAND1;
628 faket.t_dflg = 0;
629 faket.t_dlefL.T_dlef = 0;
630 faket.t_dritR.T_drit = 0;
631 faket.t_dspr = 0;
632 faket.t_dcom = fakecom;
633 fakecom[0] = STRfakecom1;
634 fakecom[1] = 0;
635
636 /*
637 * We do the psave job to temporarily change the current job so that the
638 * following fork is considered a separate job. This is so that when
639 * backquotes are used in a builtin function that calls glob the "current
640 * job" is not corrupted. We only need one level of pushed jobs as long as
641 * we are sure to fork here.
642 */
643 psavejob();
644
645 /*
646 * It would be nicer if we could integrate this redirection more with the
647 * routines in sh.sem.c by doing a fake execute on a builtin function that
648 * was piped out.
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 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
661 * posted to comp.bugs.4bsd 12 Sep. 1989.
662 */
663 if (pargv) /* mg, 21.dec.88 */
664 blkfree(pargv), pargv = 0, pargsiz = 0;
665 /* mg, 21.dec.88 */
666 arginp = cp;
667 while (*cp)
668 *cp++ &= TRIM0077777;
669
670 /*
671 * In the child ``forget'' everything about current aliases or
672 * eval vectors.
673 */
674 alvec = NULL((void *)0);
675 evalvec = NULL((void *)0);
676 alvecp = NULL((void *)0);
677 evalp = NULL((void *)0);
678 (void) lex(&paraml);
679 if (seterr)
680 stderror(ERR_OLD0x40000000);
681 alias(&paraml);
682 t = syntax(paraml.next, &paraml, 0);
683 if (seterr)
684 stderror(ERR_OLD0x40000000);
685 if (t)
686 t->t_dflg |= F_NOFORK(1<<4);
687 (void) signal(SIGTSTP18, SIG_IGN(void (*)(int))1);
688 (void) signal(SIGTTIN21, SIG_IGN(void (*)(int))1);
689 (void) signal(SIGTTOU22, SIG_IGN(void (*)(int))1);
690 execute(t, -1, NULL((void *)0), NULL((void *)0));
691 exitstat();
692 }
693 free(cp);
694 (void) close(pvec[1]);
695 c = 0;
696 ip = NULL((void *)0);
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, BUFSIZ1024);
707 while (icnt == -1 && errno(*__errno()) == EINTR4);
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++ & TRIM0077777);
719 if (c == 0)
720 break;
721 if (c == '\n') {
722 /*
723 * Continue around the loop one more time, so that we can eat
724 * the last newline without terminating this word.
725 */
726 hadnl = 1;
727 continue;
728 }
729 if (!quoted && (c == ' ' || c == '\t'))
730 break;
731 cnt++;
732 psave(c | quoted);
733 }
734 /*
735 * Unless at end-of-file, we will form a new word here if there were
736 * characters in the word, or in any case when we take text literally.
737 * If we didn't make empty words here when literal was set then we
738 * would lose blank lines.
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
749static void
750psave(int c)
751{
752 if (--pnleft <= 0)
753 stderror(ERR_WTOOLONG2);
754 *pargcp++ = c;
755}
756
757static void
758pword(void)
759{
760 psave(0);
761 if (pargc == pargsiz - 1) {
762 pargsiz += GLOBSPACE100;
763 pargv = xreallocarray(pargv, pargsiz, sizeof(Char *));
764 }
765 pargv[pargc++] = Strsave(pargs);
766 pargv[pargc] = NULL((void *)0);
767 pargcp = pargs;
768 pnleft = PATH_MAX1024 - 4;
769}
770
771int
772Gmatch(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
2
Taking false branch
778 gpol = 0;
779 pattern++;
780 }
781
782 blk = xreallocarray(NULL((void *)0), GLOBSPACE100, sizeof(Char *));
783 blk[0] = Strsave(pattern);
784 blk[1] = NULL((void *)0);
785
786 expbrace(&blk, NULL((void *)0), GLOBSPACE100);
3
Calling 'expbrace'
787
788 for (p = blk; *p; p++)
789 gres |= pmatch(string, *p);
790
791 blkfree(blk);
792 return(gres == gpol);
793}
794
795static int
796pmatch(Char *string, Char *pattern)
797{
798 Char stringc, patternc;
799 int match, negate_range;
800 Char rangec;
801
802 for (;; ++string) {
803 stringc = *string & TRIM0077777;
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 & TRIM0077777) &&
830 (*(pattern-2) & TRIM0077777) <= stringc);
831 pattern++;
832 }
833 else
834 match = (stringc == (rangec & TRIM0077777));
835 }
836 if (rangec == 0)
837 stderror(ERR_NAME0x10000000 | ERR_MISSING51, ']');
838 if (match == negate_range)
839 return (0);
840 break;
841 default:
842 if ((patternc & TRIM0077777) != stringc)
843 return (0);
844 break;
845
846 }
847 }
848}
849
850void
851Gcat(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 += GLOBSPACE100;
863 gargv = xreallocarray(gargv, gargsiz, sizeof(Char *));
864 }
865 gargv[gargc] = 0;
866 p = gargv[gargc - 1] = xreallocarray(NULL((void *)0), n, sizeof(Char));
867 for (q = s1; (*p++ = *q++) != '\0';)
868 continue;
869 for (p--, q = s2; (*p++ = *q++) != '\0';)
870 continue;
871}
872
873int
874sortscmp(const void *a, const void *b)
875{
876 char buf[2048];
877
878 if (!a) /* check for NULL */
879 return (b ? 1 : 0);
880 if (!b)
881 return (-1);
882
883 if (!*(Char **)a) /* check for NULL */
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}