1 /* $NetBSD: glob.c,v 1.27 2013/07/16 17:47:43 christos Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)glob.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: glob.c,v 1.27 2013/07/16 17:47:43 christos Exp $");
41 #include <sys/param.h>
55 static int gargsiz
, pargsiz
;
60 #define G_NONE 0 /* No globbing needed */
61 #define G_GLOB 1 /* string contains *?[] characters */
62 #define G_CSH 2 /* string contains ~`{ characters */
64 #define GLOBSPACE 100 /* Alloc increment */
78 * globbing is now done in two stages. In the first pass we expand
79 * csh globbing idioms ~`{ and then we proceed doing the normal
80 * globbing if needed ?*[
82 * Csh type globbing is handled in globexpand() and the rest is
83 * handled in glob() which is part of the 4.4BSD libc.
86 static Char
*globtilde(Char
**, Char
*);
87 static Char
*handleone(Char
*, Char
**, int);
88 static Char
**libglob(Char
**);
89 static Char
**globexpand(Char
**);
90 static int globbrace(Char
*, Char
*, Char
***);
91 static void expbrace(Char
***, Char
***, size_t);
92 static int pmatch(Char
*, Char
*);
93 static void pword(void);
94 static void psave(int);
95 static void backeval(Char
*, int);
98 globtilde(Char
**nv
, Char
*s
)
100 Char gbuf
[MAXPATHLEN
], *b
, *e
, *gstart
, *u
;
105 for (b
= gstart
, e
= &gbuf
[MAXPATHLEN
- 1];
106 *s
&& *s
!= '/' && *s
!= ':' && b
< e
;
110 if (gethdir(gstart
)) {
113 stderror(ERR_UNKUSER
, vis_str(gstart
));
115 stderror(ERR_NOHOME
);
117 b
= &gstart
[Strlen(gstart
)];
123 return (Strsave(gstart
));
127 globbrace(Char
*s
, Char
*p
, Char
***bl
)
129 Char gbuf
[MAXPATHLEN
];
130 Char
*lm
, *pe
, *pl
, *pm
, **nv
, **vl
;
134 nv
= vl
= xmalloc(sizeof(Char
*) * (size_t)size
);
137 /* copy part up to the brace */
138 for (lm
= gbuf
, p
= s
; *p
!= LBRC
; *lm
++ = *p
++)
141 /* check for balanced braces */
142 for (i
= 0, pe
= ++p
; *pe
; pe
++)
144 /* Ignore everything between [] */
145 for (++pe
; *pe
!= RBRK
&& *pe
!= EOS
; pe
++)
152 else if (*pe
== LBRC
)
154 else if (*pe
== RBRC
) {
160 if (i
!= 0 || *pe
== '\0') {
165 for (i
= 0, pl
= pm
= p
; pm
<= pe
; pm
++)
168 for (++pm
; *pm
!= RBRK
&& *pm
!= EOS
; pm
++)
192 (void)Strcpy(lm
, pl
);
193 (void)Strcat(gbuf
, pe
+ 1);
195 *vl
++ = Strsave(gbuf
);
198 if (vl
== &nv
[size
]) {
200 nv
= (Char
**)xrealloc((ptr_t
) nv
,
201 (size_t)size
* sizeof(Char
*));
202 vl
= &nv
[size
- GLOBSPACE
];
215 expbrace(Char
***nvp
, Char
***elp
, size_t size
)
217 Char
**ex
, **nv
, *s
, **vl
;
223 for (ex
= vl
; *ex
; ex
++)
226 for (s
= *vl
; s
; s
= *++vl
) {
229 /* leave {} untouched for find */
230 if (s
[0] == '{' && (s
[1] == '\0' || (s
[1] == '}' && s
[2] == '\0')))
232 if ((b
= Strchr(s
, '{')) != NULL
) {
236 if ((len
= globbrace(s
, b
, &bl
)) < 0) {
238 stderror(ERR_MISSING
, -len
);
247 if (&ex
[len
] >= &nv
[size
]) {
250 l
= &ex
[len
] - &nv
[size
];
251 size
+= (size_t)(GLOBSPACE
> l
? GLOBSPACE
: l
);
254 nv
= (Char
**)xrealloc((ptr_t
)nv
,
255 (size_t)size
* sizeof(Char
*));
262 for (bp
= ex
; bp
!= vp
; bp
--)
266 for (bp
= bl
+ 1; *bp
; *vp
++ = *bp
++)
280 Char
**ex
, **nv
, *s
, **vl
;
284 nv
= vl
= xmalloc(sizeof(Char
*) * size
);
288 * Step 1: expand backquotes.
290 while ((s
= *v
++) != NULL
) {
291 if (Strchr(s
, '`')) {
294 (void) dobackp(s
, 0);
295 for (i
= 0; i
< pargc
; i
++) {
297 if (vl
== &nv
[size
]) {
299 nv
= (Char
**)xrealloc((ptr_t
) nv
,
300 (size_t)size
* sizeof(Char
*));
301 vl
= &nv
[size
- GLOBSPACE
];
309 if (vl
== &nv
[size
]) {
311 nv
= (Char
**)xrealloc((ptr_t
)nv
,
312 size
* sizeof(Char
*));
313 vl
= &nv
[size
- GLOBSPACE
];
323 * Step 2: expand braces
326 expbrace(&nv
, &ex
, size
);
332 for (s
= *vl
; s
; s
= *++vl
)
334 *vl
= globtilde(nv
, s
);
340 handleone(Char
*str
, Char
**vl
, int action
)
347 setname(vis_str(str
));
349 stderror(ERR_NAME
| ERR_AMBIG
);
353 str
= Strsave(*vlp
++);
355 cp
= Strspl(str
, STRspace
);
357 str
= Strspl(cp
, *vlp
);
364 str
= Strsave(strip(*vlp
));
378 int gflgs
, magic
, match
, nonomatch
;
380 gflgs
= GLOB_NOMAGIC
;
383 nonomatch
= adrof(STRnonomatch
) != 0;
393 gflgs
|= GLOB_NOCHECK
;
396 ptr
= short2qstr(*vl
);
397 switch (glob(ptr
, gflgs
, 0, &globv
)) {
399 setname(vis_str(*vl
));
400 stderror(ERR_NAME
| ERR_GLOB
);
408 if (globv
.gl_flags
& GLOB_MAGCHAR
) {
409 match
|= (globv
.gl_matchc
!= 0);
412 gflgs
|= GLOB_APPEND
;
415 vl
= (globv
.gl_pathc
== 0 || (magic
&& !match
&& !nonomatch
)) ?
416 NULL
: blk2short(globv
.gl_pathv
);
422 globone(Char
*str
, int action
)
424 Char
*v
[2], **vl
, **vo
;
427 noglob
= adrof(STRnoglob
) != 0;
434 return (strip(Strsave(str
)));
438 * Expand back-quote, tilde and brace
441 if (noglob
|| (gflg
& G_GLOB
) == 0) {
444 return (Strsave(STRNULL
));
447 return (handleone(str
, vo
, action
));
455 else if (noglob
|| (gflg
& G_GLOB
) == 0)
456 return (strip(Strsave(str
)));
461 if ((gflg
& G_CSH
) && vl
!= vo
)
464 setname(vis_str(str
));
465 stderror(ERR_NAME
| ERR_NOMATCH
);
469 return (Strsave(STRNULL
));
472 return (handleone(str
, vl
, action
));
489 gargc
= blklen(gargv
);
493 noglob
= adrof(STRnoglob
) != 0;
497 * Expand back-quote, tilde and brace
499 vl
= vo
= globexpand(v
);
501 vl
= vo
= saveblk(v
);
503 if (!noglob
&& (gflg
& G_GLOB
)) {
505 if ((gflg
& G_CSH
) && vl
!= vo
)
511 gargc
= vl
? blklen(vl
) : 0;
519 gargv
= xmalloc(sizeof(Char
*) * (size_t)gargsiz
);
525 rscan(Char
**t
, void (*f
)(int))
529 while ((p
= *t
++) != NULL
)
539 while ((p
= *t
++) != NULL
)
549 while ((p
= *t
++) != NULL
) {
550 if (*p
== '~' || *p
== '=')
552 else if (*p
== '{' &&
553 (p
[1] == '\0' || (p
[1] == '}' && p
[2] == '\0')))
555 while ((c
= *p
++) != '\0') {
557 * eat everything inside the matching backquotes
561 while (*p
&& *p
!= '`')
563 if (*p
) /* Quoted chars */
568 if (*p
) /* The matching ` */
582 * Command substitute cp. If literal, then this is a substitution from a
583 * << redirection, and so we should not crunch blanks and tabs, separating
584 * words only at newlines.
587 dobackp(Char
*cp
, int literal
)
589 Char word
[MAXPATHLEN
], *ep
, *lp
, *rp
;
598 pargv
= xmalloc(sizeof(Char
*) * (size_t)pargsiz
);
600 pargcp
= pargs
= word
;
602 pnleft
= MAXPATHLEN
- 4;
604 for (lp
= cp
; *lp
!= '`'; lp
++) {
613 for (rp
= lp
; *rp
&& *rp
!= '`'; rp
++)
621 stderror(ERR_UNMATCHED
, '`');
625 backeval(ep
, literal
);
631 backeval(Char
*cp
, int literal
)
633 struct command faket
;
635 Char ibuf
[BUFSIZE
], *fakecom
[2], *ip
;
636 int pvec
[2], c
, quoted
;
642 quoted
= (literal
|| (cp
[0] & QUOTE
)) ? QUOTE
: 0;
643 faket
.t_dtyp
= NODE_COMMAND
;
648 faket
.t_dcom
= fakecom
;
649 fakecom
[0] = STRfakecom1
;
653 * We do the psave job to temporarily change the current job so that the
654 * following fork is considered a separate job. This is so that when
655 * backquotes are used in a builtin function that calls glob the "current
656 * job" is not corrupted. We only need one level of pushed jobs as long as
657 * we are sure to fork here.
662 * It would be nicer if we could integrate this redirection more with the
663 * routines in sh.sem.c by doing a fake execute on a builtin function that
667 if (pfork(&faket
, -1) == 0) {
668 struct wordent fparaml
;
671 (void)close(pvec
[0]);
672 (void)dmove(pvec
[1], 1);
673 (void)dmove(SHERR
, 2);
676 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
677 * posted to comp.bugs.4bsd 12 Sep. 1989.
679 if (pargv
) /* mg, 21.dec.88 */
680 blkfree(pargv
), pargv
= 0, pargsiz
= 0;
683 for (arginp
= cp
; *cp
; cp
++) {
685 if (*cp
== '\n' || *cp
== '\r')
690 * In the child ``forget'' everything about current aliases or
697 (void) lex(&fparaml
);
701 t
= syntax(fparaml
.next
, &fparaml
, 0);
705 t
->t_dflg
|= F_NOFORK
;
706 (void)signal(SIGTSTP
, SIG_IGN
);
707 (void)signal(SIGTTIN
, SIG_IGN
);
708 (void)signal(SIGTTOU
, SIG_IGN
);
709 execute(t
, -1, NULL
, NULL
);
713 (void)close(pvec
[1]);
727 icnt
= read(pvec
[0], tibuf
, BUFSIZE
);
728 while (icnt
== -1 && errno
== EINTR
);
733 for (i
= 0; i
< icnt
; i
++)
734 ip
[i
] = (unsigned char) tibuf
[i
];
744 * Continue around the loop one more time, so that we can eat
745 * the last newline without terminating this word.
750 if (!quoted
&& (c
== ' ' || c
== '\t'))
756 * Unless at end-of-file, we will form a new word here if there were
757 * characters in the word, or in any case when we take text literally.
758 * If we didn't make empty words here when literal was set then we
759 * would lose blank lines.
761 if (c
!= -1 && (cnt
|| literal
))
765 (void)close(pvec
[0]);
774 stderror(ERR_WTOOLONG
);
782 if (pargc
== pargsiz
- 1) {
783 pargsiz
+= GLOBSPACE
;
784 pargv
= (Char
**)xrealloc((ptr_t
)pargv
,
785 (size_t)pargsiz
* sizeof(Char
*));
787 pargv
[pargc
++] = Strsave(pargs
);
790 pnleft
= MAXPATHLEN
- 4;
794 Gmatch(Char
*string
, Char
*pattern
)
802 if (*pattern
== '^') {
807 blk
= xmalloc(GLOBSPACE
* sizeof(Char
*));
808 blk
[0] = Strsave(pattern
);
811 expbrace(&blk
, NULL
, GLOBSPACE
);
813 for (p
= blk
; *p
; p
++)
814 gres
|= pmatch(string
, *p
);
817 return(gres
== gpol
);
821 pmatch(Char
*string
, Char
*pattern
)
823 int match
, negate_range
;
824 Char patternc
, rangec
, stringc
;
827 stringc
= *string
& TRIM
;
828 patternc
= *pattern
++;
831 return (stringc
== 0);
840 if (Gmatch(string
++, pattern
))
845 if ((negate_range
= (*pattern
== '^')) != 0)
847 while ((rangec
= *pattern
++) != '\0') {
852 if (rangec
== '-' && *(pattern
-2) != '[' && *pattern
!= ']') {
853 match
= (stringc
<= (*pattern
& TRIM
) &&
854 (*(pattern
-2) & TRIM
) <= stringc
);
858 match
= (stringc
== (rangec
& TRIM
));
861 stderror(ERR_NAME
| ERR_MISSING
, ']');
862 if (match
== negate_range
)
866 if ((patternc
& TRIM
) != stringc
)
875 Gcat(Char
*s1
, Char
*s2
)
884 n
= (p
- s1
) + (q
- s2
) - 1;
885 if (++gargc
>= gargsiz
) {
886 gargsiz
+= GLOBSPACE
;
887 gargv
= (Char
**)xrealloc((ptr_t
)gargv
,
888 (size_t)gargsiz
* sizeof(Char
*));
891 p
= gargv
[gargc
- 1] = xmalloc((size_t)n
* sizeof(Char
));
892 for (q
= s1
; (*p
++ = *q
++) != '\0';)
894 for (p
--, q
= s2
; (*p
++ = *q
++) != '\0';)
900 sortscmp(const ptr_t a
, const ptr_t b
)
902 #if defined(NLS) && !defined(NOSTRCOLL)
906 if (!a
) /* check for NULL */
911 if (!*(Char
**)a
) /* check for NULL */
912 return (*(Char
**)b
? 1 : 0);
916 #if defined(NLS) && !defined(NOSTRCOLL)
917 (void)strcpy(buf
, short2str(*(Char
**)a
));
918 return ((int)strcoll(buf
, short2str(*(Char
**)b
)));
920 return ((int)Strcmp(*(Char
**)a
, *(Char
**)b
));