* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley Software License Agreement
* specifies the terms and conditions for redistribution.
static char *sccsid
= "@(#)glob.c 5.6 (Berkeley) %G%";
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 */
char **gargv
= (char **) 0;
* 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. To do the
* 'No match' checking, we try to glob everything without checking
* and then we look if the string still contains globbing characters.
* If it does, then globbing failed for at least one component of the
char gbuf
[MAXPATHLEN
], *gstart
, *b
, *u
;
for (u
= s
, b
= gstart
; alnum(*s
) || *s
== '-'; *b
++ = *s
++)
if (*s
== EOS
|| *s
== '/') {
gstart
= strcpy(gbuf
, value("home"));
else if (gethdir(gstart
))
error("Unknown user: %s", gstart
);
b
= &gstart
[strlen(gstart
)];
nv
= vl
= (char **) xalloc(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(nv
,
nv
= vl
= (char **) xalloc(sizeof(char *) * size
);
* Step 1: expand backquotes.
for (i
= 0; i
< pargc
; i
++) {
nv
= (char **) xrealloc(nv
,
nv
= (char **) xrealloc(nv
,
* Step 2: expand tilde and braces
for (s
= *vl
; s
; s
= *++vl
) {
if (b
= index(s
, LBRC
)) {
if ((len
= globbrace(s
, b
, &bl
)) < 0) {
error("Missing %c", -len
);
if (&el
[len
] >= &nv
[size
]) {
l
= &el
[len
] - &nv
[size
];
size
+= GAVSIZ
> l
? GAVSIZ
: l
;
nv
= (char **) xrealloc(nv
,
for (bp
= el
; bp
!= vp
; bp
--)
for (bp
= bl
+ 1; *bp
; *vp
++ = *bp
++)
noglob
= adrof("noglob") != 0;
return (strip(savestr(str
)));
* Expand back-quote, tilde and brace
if (vl
[1] != (char *) 0) {
if (!noglob
&& (gflag
& G_GLOB
)) {
glob(nstr
, GLOB_NOCHECK
, 0, &globv
);
if (globv
.gl_pathc
!= 1) {
if (adrof("nonomatch") == 0) {
str
= strip(savestr(globv
.gl_pathv
[0]));
noglob
= adrof("noglob") != 0;
* Expand back-quote, tilde and brace
if (!noglob
&& (gflag
& G_GLOB
)) {
* Glob the strings in vl using the glob routine
glob(vl
[0], GLOB_NOCHECK
, 0, &globv
);
glob(*vl
, GLOB_NOCHECK
| GLOB_APPEND
, 0, &globv
);
if (adrof("nonomatch") == 0) {
return(gargv
= (char **) 0);
vl
= saveblk(globv
.gl_pathv
);
gargc
= vl
? blklen(vl
) : 0;
gargv
= (char **) xalloc(sizeof(char *) * gargsiz
);
(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 **) xalloc(sizeof(char *) * pargsiz
);
for (lp
= cp
; *lp
!= '`'; lp
++) {
for (rp
= lp
; *rp
&& *rp
!= '`'; rp
++)
oops
: error("Unmatched `");
char *fakecom
[2], ibuf
[BUFSIZ
];
quoted
= (literal
|| (cp
[0] & QUOTE
)) ? QUOTE
: 0;
* 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 was piped out.
if (pfork(&faket
, -1) == 0) {
(void) dmove(pvec
[1], 1);
t
= syntax(paraml
.next
, ¶ml
, 0);
(void) signal(SIGTSTP
, SIG_IGN
);
(void) signal(SIGTTIN
, SIG_IGN
);
(void) signal(SIGTTOU
, SIG_IGN
);
icnt
= read(pvec
[0], ip
, BUFSIZ
);
* Continue around the loop one more time, so
* that we can eat the last newline without
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(pargv
, pargsiz
* sizeof(char *));
pargv
[pargc
++] = savestr(pargs
);
register char *string
, *pattern
;
register char stringc
, patternc
;
stringc
= *string
& TRIM
;
switch (patternc
= *pattern
++) {
if (Gmatch(string
++, pattern
))
while (rangec
= *pattern
++) {
match
= (stringc
<= *pattern
++ &&
*(pattern
-2) <= stringc
);
match
= (stringc
== rangec
);
if ((patternc
& TRIM
) != stringc
)
n
= (p
- s1
) + (q
- s2
) - 1;
if (++gargc
>= gargsiz
) {
gargv
= (char **) xrealloc(gargv
, gargsiz
* sizeof(char *));
p
= gargv
[gargc
- 1] = xalloc((unsigned)n
);
for (q
= s1
; *p
++ = *q
++;);
for (p
--, q
= s2
; *p
++ = *q
++;);
return(strcmp(*a1
, *a2
));