version 1.33, 2014/01/17 18:42:30 |
version 1.34, 2014/12/16 18:31:06 |
|
|
#include <unistd.h> |
#include <unistd.h> |
#include <paths.h> |
#include <paths.h> |
#include <errno.h> |
#include <errno.h> |
|
#include <glob.h> |
#include "extern.h" |
#include "extern.h" |
|
|
/* |
/* |
|
|
char * |
char * |
expand(char *name) |
expand(char *name) |
{ |
{ |
|
const int flags = GLOB_BRACE|GLOB_TILDE|GLOB_NOSORT; |
char xname[PATHSIZE]; |
char xname[PATHSIZE]; |
char cmdbuf[PATHSIZE]; /* also used for file names */ |
char cmdbuf[PATHSIZE]; /* also used for file names */ |
pid_t pid; |
char *match = NULL; |
int l; |
glob_t names; |
char *cp, *shell; |
|
int pivec[2]; |
|
struct stat sbuf; |
|
extern int wait_status; |
|
|
|
/* |
/* |
* The order of evaluation is "%" and "#" expand into constants. |
* The order of evaluation is "%" and "#" expand into constants. |
|
|
(void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); |
(void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); |
name = savestr(xname); |
name = savestr(xname); |
} |
} |
if (strpbrk(name, "~{[*?$`'\"\\") == NULL) |
if (strpbrk(name, "~{[*?\\") == NULL) |
return(name); |
return(savestr(name)); |
/* XXX - just use glob(3) and env expansion instead? */ |
|
if (pipe(pivec) < 0) { |
/* XXX - does not expand enviroment variables. */ |
warn("pipe"); |
switch (glob(name, flags, NULL, &names)) { |
return(name); |
case 0: |
} |
if (names.gl_pathc == 1) |
(void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name); |
match = savestr(names.gl_pathv[0]); |
shell = value("SHELL"); |
else |
pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NULL); |
fprintf(stderr, "\"%s\": Ambiguous.\n", name); |
if (pid < 0) { |
break; |
(void)close(pivec[0]); |
case GLOB_NOSPACE: |
(void)close(pivec[1]); |
fprintf(stderr, "\"%s\": Out of memory.\n", name); |
return(NULL); |
break; |
} |
case GLOB_NOMATCH: |
(void)close(pivec[1]); |
fprintf(stderr, "\"%s\": No match.\n", name); |
l = myread(pivec[0], xname, PATHSIZE); |
break; |
if (l < 0) |
default: |
warn("read"); /* report error before errno changes */ |
|
(void)close(pivec[0]); |
|
if (wait_child(pid) < 0 && WIFSIGNALED(wait_status) && |
|
WTERMSIG(wait_status) != SIGPIPE) { |
|
fprintf(stderr, "\"%s\": Expansion failed.\n", name); |
fprintf(stderr, "\"%s\": Expansion failed.\n", name); |
return(NULL); |
break; |
} |
} |
if (l < 0) |
globfree(&names); |
return(NULL); |
return(match); |
if (l == 0) { |
|
fprintf(stderr, "\"%s\": No match.\n", name); |
|
return(NULL); |
|
} |
|
if (l == PATHSIZE) { |
|
fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name); |
|
return(NULL); |
|
} |
|
xname[l] = '\0'; |
|
for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) |
|
; |
|
cp[1] = '\0'; |
|
if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) { |
|
fprintf(stderr, "\"%s\": Ambiguous.\n", name); |
|
return(NULL); |
|
} |
|
return(savestr(xname)); |
|
} |
} |
|
|
/* |
/* |