static char *sccsid
= "@(#)expand.c 4.8 (Berkeley) 83/11/30";
static char shchars
[] = "${[*?";
static int which
; /* bit mask of types to expand */
static int argc
; /* expanded arg count */
static char **argv
; /* expanded arg vectors */
static char *tilde
; /* "~user" if not expanding tilde, else "" */
static int expany
; /* any expansions done? */
* Take a list of names and expand any macros, etc.
* wh = E_VARS if expanding variables.
* wh = E_SHELL if expanding shell characters.
* wh = E_TILDE if expanding `~'.
* or any of these or'ed together.
register struct block
*bp
, *prev
;
printf("expand(%x, %d)\nlist = ", list
, wh
);
path
= tpathp
= pathp
= pathbuf
;
lastpathp
= &path
[sizeof pathbuf
- 2];
argv
= sortbase
= argvbuf
;
* Walk the block list and expand names into argv[];
for (bp
= list
; bp
!= NULL
; bp
= bp
->b_next
) {
* Take expanded list of names from argv[] and build a block list.
for (n
= 0; n
< argc
; n
++) {
fatal("ran out of memory\n");
bp
->b_next
= bp
->b_args
= NULL
;
printf("expanded list = ");
register struct block
*tp
;
if (s
== NULL
|| *s
== '\0')
if ((which
& E_VARS
) && (cp
= index(s
, '$')) != NULL
) {
error("no variable name after '$'\n");
if ((tail
= index(cp
, RC
)) == NULL
) {
error("unmatched %c\n", *cp
);
error("no variable name after '$'\n");
tp
= lookup(cp
, NULL
, 0);
if ((tp
= tp
->b_args
) != NULL
) {
for (; tp
!= NULL
; tp
= tp
->b_next
) {
sprintf(buf
, "%s%s%s", s
, tp
->b_name
, tail
);
sprintf(buf
, "%s%s", s
, tail
);
if ((which
& ~E_VARS
) == 0 || !strcmp(s
, "{") || !strcmp(s
, "{}")) {
if (*cp
== '\0' || *cp
== '/') {
while (*cp
&& *cp
!= '/');
if (pw
== NULL
|| strcmp(pw
->pw_name
, buf
+1) != 0) {
if ((pw
= getpwnam(buf
+1)) == NULL
) {
error("unknown user %s\n", buf
+1);
for (cp
= path
; *cp
++ = *cp1
++; )
if (!(which
& E_SHELL
)) {
* Bubble sort any new entries
register char **p1
, **p2
, *c
;
if (strcmp(*p1
, *p2
) > 0)
c
= *p1
, *p1
= *p2
, *p2
= c
;
* If there are any Shell meta characters in the name,
* expand into a list, after searching directory
register char *spathp
, *oldcp
;
while (!any(*cp
, shchars
)) {
if (!expany
|| stat(path
, &stb
) >= 0) {
while (cp
> s
&& *cp
!= '/')
register struct direct
*dp
;
if (fstat(dirp
->dd_fd
, &stb
) < 0)
if (!ISDIR(stb
.st_mode
)) {
while ((dp
= readdir(dirp
)) != NULL
)
if (match(dp
->d_name
, pattern
)) {
strcpy(pathp
, dp
->d_name
);
error("%s: %s\n", path
, sys_errlist
[errno
]);
char restbuf
[BUFSIZ
+ 2];
register char *pe
, *pm
, *pl
;
char *lm
, savec
, *spathp
;
for (lm
= restbuf
; *p
!= '{'; *lm
++ = *p
++)
for (pe
= ++p
; *pe
; pe
++)
for (pe
++; *pe
&& *pe
!= ']'; pe
++)
for (pl
= pm
= p
; pm
<= pe
; pm
++)
switch (*pm
& (QUOTE
|TRIM
)) {
} else if (amatch(s
, restbuf
))
for (pm
++; *pm
&& *pm
!= ']'; pm
++)
if (*s
== '.' && *p
!= '.')
return (execbrc(p
- 1, s
- 1));
if (lc
<= scc
&& scc
<= *p
++)
if (stat(path
, &stb
) == 0 && ISDIR(stb
.st_mode
))
if (lc
<= scc
&& scc
<= *p
++)
int len
= strlen(s1
) + strlen(s2
) + 1;
if (nleft
<= 0 || ++argc
>= GAVSIZ
)
error("Arguments too long\n");
argv
[argc
- 1] = s
= malloc(len
);
fatal("ran out of memory\n");
while (*s
++ = *s1
++ & TRIM
)
while (*s
++ = *s2
++ & TRIM
)
fatal("Pathname too long\n");
* Expand file names beginning with `~' into the
* user's home directory path name. Return a pointer in buf to the
* part corresponding to `file'.
register char *s1
, *s2
, *s3
;
} else if (*file
== '/') {
while (*s3
&& *s3
!= '/')
if (pw
== NULL
|| strcmp(pw
->pw_name
, file
) != 0) {
if ((pw
= getpwnam(file
)) == NULL
) {
error("unknown user %s\n", file
);
for (s1
= buf
; *s1
++ = *s2
++; )