* Copyright (c) 1980, 1991 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)glob.c 5.21 (Berkeley) 6/25/91";
static int noglob
, nonomatch
;
static int pargsiz
, gargsiz
;
#define G_NONE 0 /* No globbing needed */
#define G_GLOB 1 /* string contains *?[] characters */
#define G_CSH 2 /* string contains ~`{ characters */
#define GLOBSPACE 100 /* Alloc increment */
* globbing is now done in two stages. In the first pass we expand
* csh globbing idioms ~`{ and then we proceed doing the normal
* Csh type globbing is handled in globexpand() and the rest is
* handled in glob() which is part of the 4.4BSD libc.
static Char
*globtilde
__P((Char
**, Char
*));
static Char
**libglob
__P((Char
**));
static Char
**globexpand
__P((Char
**));
static int globbrace
__P((Char
*, Char
*, Char
***));
static void pword
__P((void));
static void psave
__P((int));
static void backeval
__P((Char
*, bool));
Char gbuf
[MAXPATHLEN
], *gstart
, *b
, *u
, *e
;
for (b
= gstart
, e
= &gbuf
[MAXPATHLEN
- 1]; *s
&& *s
!= '/' && b
< e
;
stderror(ERR_UNKUSER
, short2str(gstart
));
b
= &gstart
[Strlen(gstart
)];
return (Strsave(gstart
));
nv
= vl
= (Char
**) xmalloc((size_t) sizeof(Char
*) * size
);
/* copy part up to the brace */
for (lm
= gbuf
, p
= s
; *p
!= LBRC
; *lm
++ = *p
++)
/* check for balanced braces */
for (i
= 0, pe
= ++p
; *pe
; pe
++)
/* Ignore everything between [] */
for (++pe
; *pe
!= RBRK
&& *pe
!= EOS
; pe
++)
for (i
= 0, pl
= pm
= p
; pm
<= pe
; pm
++)
for (++pm
; *pm
!= RBRK
&& *pm
!= EOS
; pm
++)
(void) Strcat(gbuf
, pe
+ 1);
nv
= (Char
**) xrealloc((ptr_t
) nv
, (size_t)
vl
= &nv
[size
- GLOBSPACE
];
nv
= vl
= (Char
**) xmalloc((size_t) sizeof(Char
*) * size
);
* Step 1: expand backquotes.
for (i
= 0; i
< pargc
; i
++) {
nv
= (Char
**) xrealloc((ptr_t
) nv
,
(size_t) size
* sizeof(Char
*));
vl
= &nv
[size
- GLOBSPACE
];
nv
= (Char
**) xrealloc((ptr_t
) nv
, (size_t)
vl
= &nv
[size
- GLOBSPACE
];
for (s
= *vl
; s
; s
= *++vl
) {
if (b
= Strchr(s
, LBRC
)) {
if ((len
= globbrace(s
, b
, &bl
)) < 0) {
stderror(ERR_MISSING
, -len
);
if (&el
[len
] >= &nv
[size
]) {
l
= &el
[len
] - &nv
[size
];
size
+= GLOBSPACE
> l
? GLOBSPACE
: l
;
nv
= (Char
**) xrealloc((ptr_t
) nv
, (size_t)
for (bp
= el
; bp
!= vp
; bp
--)
for (bp
= bl
+ 1; *bp
; *vp
++ = *bp
++)
for (s
= *vl
; s
; s
= *++vl
)
handleone(str
, vl
, action
)
stderror(ERR_NAME
| ERR_AMBIG
);
cp
= Strspl(str
, STRspace
);
str
= Strsave(strip(*vlp
));
int gflgs
= GLOB_QUOTE
| GLOB_NOCHECK
;
nonomatch
= adrof(STRnonomatch
) != 0;
switch (glob(ptr
, gflgs
, 0, &globv
)) {
stderror(ERR_NAME
| ERR_GLOB
);
if (!nonomatch
&& (globv
.gl_matchc
== 0) &&
(globv
.gl_flags
& GLOB_MAGCHAR
)) {
vl
= blk2short(globv
.gl_pathv
);
noglob
= adrof(STRnoglob
) != 0;
return (strip(Strsave(str
)));
* Expand back-quote, tilde and brace
if (noglob
|| (gflag
& G_GLOB
) == 0) {
return (Strsave(STRNULL
));
return (handleone(str
, vo
, action
));
else if (noglob
|| (gflag
& G_GLOB
) == 0)
return (strip(Strsave(str
)));
stderror(ERR_NAME
| ERR_NOMATCH
);
return (Strsave(STRNULL
));
return (handleone(str
, vl
, action
));
noglob
= adrof(STRnoglob
) != 0;
* Expand back-quote, tilde and brace
if (!noglob
&& (gflag
& G_GLOB
)) {
gargc
= vl
? blklen(vl
) : 0;
gargv
= (Char
**) xmalloc((size_t) sizeof(Char
*) * gargsiz
);
if (*p
== '~' || *p
== '=')
(p
[1] == '\0' || p
[1] == '}' && p
[2] == '\0'))
gflag
|= (c
== '{' || c
== '`') ? G_CSH
: G_GLOB
;
* Command substitute cp. If literal, then this is a substitution from a
* << redirection, and so we should not crunch blanks and tabs, separating
* words only at newlines.
Char
*ep
, word
[MAXPATHLEN
];
pargv
= (Char
**) xmalloc((size_t) sizeof(Char
*) * pargsiz
);
for (lp
= cp
; *lp
!= '`'; lp
++) {
for (rp
= lp
; *rp
&& *rp
!= '`'; rp
++)
oops
: stderror(ERR_UNMATCHED
, '`');
Char
*fakecom
[2], ibuf
[BUFSIZ
];
quoted
= (literal
|| (cp
[0] & QUOTE
)) ? QUOTE
: 0;
faket
.t_dtyp
= NODE_COMMAND
;
fakecom
[0] = STRfakecom1
;
* We do the psave job to temporarily change the current job so that the
* following fork is considered a separate job. This is so that when
* backquotes are used in a builtin function that calls glob the "current
* job" is not corrupted. We only need one level of pushed jobs as long as
* we are sure to fork here.
* It would be nicer if we could integrate this redirection more with the
* routines in sh.sem.c by doing a fake execute on a builtin function that
if (pfork(&faket
, -1) == 0) {
(void) dmove(pvec
[1], 1);
* Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
* posted to comp.bugs.4bsd 12 Sep. 1989.
if (pargv
) /* mg, 21.dec.88 */
blkfree(pargv
), pargv
= 0, pargsiz
= 0;
t
= syntax(paraml
.next
, ¶ml
, 0);
(void) signal(SIGTSTP
, SIG_IGN
);
(void) signal(SIGTTIN
, SIG_IGN
);
(void) signal(SIGTTOU
, SIG_IGN
);
execute(t
, -1, NULL
, NULL
);
icnt
= read(pvec
[0], tibuf
, BUFSIZ
);
while (icnt
== -1 && errno
== EINTR
);
for (i
= 0; i
< icnt
; i
++)
ip
[i
] = (unsigned char) tibuf
[i
];
* Continue around the loop one more time, so that we can eat
* the last newline without terminating this word.
if (!quoted
&& (c
== ' ' || c
== '\t'))
* Unless at end-of-file, we will form a new word here if there were
* characters in the word, or in any case when we take text literally.
* If we didn't make empty words here when literal was set then we
* would lose blank lines.
if (c
!= -1 && (cnt
|| literal
))
if (pargc
== pargsiz
- 1) {
pargv
= (Char
**) xrealloc((ptr_t
) pargv
,
(size_t) pargsiz
* sizeof(Char
*));
pargv
[pargc
++] = Strsave(pargs
);
register Char
*string
, *pattern
;
register Char stringc
, patternc
;
stringc
= *string
& TRIM
;
if (Gmatch(string
++, pattern
))
while (rangec
= *pattern
++) {
if (rangec
== '-' && *(pattern
- 2) != '[' && *pattern
!= ']') {
match
= (stringc
<= (*pattern
& TRIM
) &&
(*(pattern
- 2) & TRIM
) <= stringc
);
match
= (stringc
== rangec
);
stderror(ERR_NAME
| ERR_MISSING
, ']');
if ((patternc
& TRIM
) != stringc
)
n
= (p
- s1
) + (q
- s2
) - 1;
if (++gargc
>= gargsiz
) {
gargv
= (Char
**) xrealloc((ptr_t
) gargv
,
(size_t) gargsiz
* sizeof(Char
*));
p
= gargv
[gargc
- 1] = (Char
*) xmalloc((size_t) n
* sizeof(Char
));
for (q
= s1
; *p
++ = *q
++;);
for (p
--, q
= s2
; *p
++ = *q
++;);
#if defined(NLS) && !defined(NOSTRCOLL)
if (!a
) /* check for NULL */
if (!*a
) /* check for NULL */
#if defined(NLS) && !defined(NOSTRCOLL)
(void) strcpy(buf
, short2str(*a
));
return ((int) strcoll(buf
, short2str(*b
)));
return ((int) Strcmp(*a
, *b
));