* Copyright (c) 1983 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of California at Berkeley. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
static char sccsid
[] = "@(#)expand.c 5.3 (Berkeley) %G%";
#define GAVSIZ NCARGS / 6
static char shchars
[] = "${[*?";
int which
; /* bit mask of types to expand */
int eargc
; /* expanded arg count */
char **eargv
; /* expanded arg vectors */
char *tilde
; /* "~user" if not expanding tilde, else "" */
int expany
; /* any expansions done? */
#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \
sizeof(*sortbase), argcmp), sortbase = &eargv[eargc]
* 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.
* Major portions of this were snarfed from csh/sh.glob.c.
register struct namelist
*nl
, *prev
;
printf("expand(%x, %d)\nlist = ", list
, wh
);
for (nl
= list
; nl
!= NULL
; nl
= nl
->n_next
)
for (cp
= nl
->n_name
; *cp
; cp
++)
path
= tpathp
= pathp
= pathbuf
;
lastpathp
= &path
[sizeof pathbuf
- 2];
eargv
= sortbase
= argvbuf
;
* Walk the name list and expand names into eargv[];
for (nl
= list
; nl
!= NULL
; nl
= nl
->n_next
)
* Take expanded list of names from eargv[] and build a new list.
for (n
= 0; n
< eargc
; n
++) {
printf("expanded list = ");
register struct namelist
*tp
;
if (s
== NULL
|| *s
== '\0')
if ((which
& E_VARS
) && (cp
= index(s
, '$')) != NULL
) {
yyerror("no variable name after '$'");
if ((tail
= index(cp
, RC
)) == NULL
) {
yyerror("unmatched '{'");
yyerror("no variable name after '$'");
tp
= lookup(cp
, NULL
, 0);
for (; tp
!= NULL
; tp
= tp
->n_next
) {
sprintf(buf
, "%s%s%s", s
, tp
->n_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
) {
strcat(buf
, ": unknown user name");
for (cp
= path
; *cp
++ = *cp1
++; )
if (!(which
& E_SHELL
)) {
Cat(s
, ""); /* "nonomatch" is set */
return (strcmp(*a1
, *a2
));
* 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
);
strcat(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 || ++eargc
>= GAVSIZ
)
yyerror("Arguments too long");
eargv
[eargc
- 1] = s
= malloc(len
);
fatal("ran out of memory\n");
while (*s
++ = *s1
++ & TRIM
)
while (*s
++ = *s2
++ & TRIM
)
yyerror("Pathname too long");
* 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("%s: unknown user name\n", file
);
for (s1
= buf
; *s1
++ = *s2
++; )