diff options
Diffstat (limited to 'bin/sh/exec.c')
-rw-r--r-- | bin/sh/exec.c | 161 |
1 files changed, 40 insertions, 121 deletions
diff --git a/bin/sh/exec.c b/bin/sh/exec.c index e104b63..044fc30 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include <fcntl.h> #include <errno.h> +#include <paths.h> #include <stdlib.h> /* @@ -92,7 +93,6 @@ struct tblentry { static struct tblentry *cmdtable[CMDTABLESIZE]; -static int builtinloc = -1; /* index in path of %builtin, or -1 */ int exerrno = 0; /* Last exec error */ @@ -106,6 +106,8 @@ static void delete_cmd_entry(void); /* * Exec a program. Never returns. If you change this routine, you may * have to change the find_command routine as well. + * + * The argv array may be changed and element argv[-1] should be writable. */ void @@ -124,43 +126,47 @@ shellexec(char **argv, char **envp, const char *path, int idx) tryexec(cmdname, argv, envp); if (errno != ENOENT && errno != ENOTDIR) e = errno; + if (e == ENOEXEC) + break; } stunalloc(cmdname); } } /* Map to POSIX errors */ - switch (e) { - case EACCES: - exerrno = 126; - break; - case ENOENT: + if (e == ENOENT || e == ENOTDIR) { exerrno = 127; - break; - default: - exerrno = 2; - break; - } - if (e == ENOENT || e == ENOTDIR) exerror(EXEXEC, "%s: not found", argv[0]); - exerror(EXEXEC, "%s: %s", argv[0], strerror(e)); + } else { + exerrno = 126; + exerror(EXEXEC, "%s: %s", argv[0], strerror(e)); + } } static void tryexec(char *cmd, char **argv, char **envp) { - int e; + int e, in; + ssize_t n; + char buf[256]; execve(cmd, argv, envp); e = errno; if (e == ENOEXEC) { - initshellproc(); - setinputfile(cmd, 0); - commandname = arg0 = savestr(argv[0]); - setparam(argv + 1); - exraise(EXSHELLPROC); - /*NOTREACHED*/ + INTOFF; + in = open(cmd, O_RDONLY | O_NONBLOCK); + if (in != -1) { + n = pread(in, buf, sizeof buf, 0); + close(in); + if (n > 0 && memchr(buf, '\0', n) != NULL) { + errno = ENOEXEC; + return; + } + } + *argv = cmd; + *--argv = _PATH_BSHELL; + execve(_PATH_BSHELL, argv, envp); } errno = e; } @@ -190,9 +196,8 @@ padvance(const char **path, const char *name) for (p = start; *p && *p != ':' && *p != '%'; p++) ; /* nothing */ len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ - while (stackblocksize() < len) - growstackblock(); - q = stackblock(); + STARTSTACKSTR(q); + CHECKSTRSPACE(len, q); if (p != start) { memcpy(q, start, p - start); q += p - start; @@ -229,7 +234,7 @@ hashcmd(int argc __unused, char **argv __unused) verbose = 0; while ((c = nextopt("rv")) != '\0') { if (c == 'r') { - clearcmdentry(0); + clearcmdentry(); } else if (c == 'v') { verbose++; } @@ -245,8 +250,7 @@ hashcmd(int argc __unused, char **argv __unused) } while ((name = *argptr) != NULL) { if ((cmdp = cmdlookup(name, 0)) != NULL - && (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))) + && cmdp->cmdtype == CMDNORMAL) delete_cmd_entry(); find_command(name, &entry, DO_ERR, pathval()); if (verbose) { @@ -337,8 +341,8 @@ find_command(const char *name, struct cmdentry *entry, int act, goto success; } - /* If %builtin not in path, check for builtin next */ - if (builtinloc < 0 && (i = find_builtin(name, &spec)) >= 0) { + /* Check for builtin next */ + if ((i = find_builtin(name, &spec)) >= 0) { INTOFF; cmdp = cmdlookup(name, 1); if (cmdp->cmdtype == CMDFUNCTION) @@ -354,7 +358,7 @@ find_command(const char *name, struct cmdentry *entry, int act, prev = -1; /* where to start */ if (cmdp) { /* doing a rehash */ if (cmdp->cmdtype == CMDBUILTIN) - prev = builtinloc; + prev = -1; else prev = cmdp->param.index; } @@ -366,19 +370,7 @@ loop: stunalloc(fullname); idx++; if (pathopt) { - if (prefix("builtin", pathopt)) { - if ((i = find_builtin(name, &spec)) < 0) - goto loop; - INTOFF; - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype == CMDFUNCTION) - cmdp = &loc_cmd; - cmdp->cmdtype = CMDBUILTIN; - cmdp->param.index = i; - cmdp->special = spec; - INTON; - goto success; - } else if (prefix("func", pathopt)) { + if (prefix("func", pathopt)) { /* handled below */ } else { goto loop; /* ignore unimplemented options */ @@ -485,8 +477,7 @@ hashcd(void) for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)) + if (cmdp->cmdtype == CMDNORMAL) cmdp->rehash = 1; } } @@ -503,39 +494,7 @@ hashcd(void) void changepath(const char *newval) { - const char *old, *new; - int idx; - int firstchange; - int bltin; - - old = pathval(); - new = newval; - firstchange = 9999; /* assume no change */ - idx = 0; - bltin = -1; - for (;;) { - if (*old != *new) { - firstchange = idx; - if ((*old == '\0' && *new == ':') - || (*old == ':' && *new == '\0')) - firstchange++; - old = new; /* ignore subsequent differences */ - } - if (*new == '\0') - break; - if (*new == '%' && bltin < 0 && prefix("builtin", new + 1)) - bltin = idx; - if (*new == ':') { - idx++; - } - new++, old++; - } - if (builtinloc < 0 && bltin >= 0) - builtinloc = bltin; /* zap builtins */ - if (builtinloc >= 0 && bltin < 0) - firstchange = 0; - clearcmdentry(firstchange); - builtinloc = bltin; + clearcmdentry(); } @@ -545,45 +504,7 @@ changepath(const char *newval) */ void -clearcmdentry(int firstchange) -{ - struct tblentry **tblp; - struct tblentry **pp; - struct tblentry *cmdp; - - INTOFF; - for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { - pp = tblp; - while ((cmdp = *pp) != NULL) { - if ((cmdp->cmdtype == CMDNORMAL && - cmdp->param.index >= firstchange) - || (cmdp->cmdtype == CMDBUILTIN && - builtinloc >= firstchange)) { - *pp = cmdp->next; - ckfree(cmdp); - } else { - pp = &cmdp->next; - } - } - } - INTON; -} - - -/* - * Delete all functions. - */ - -#ifdef mkinit -MKINIT void deletefuncs(void); - -SHELLPROC { - deletefuncs(); -} -#endif - -void -deletefuncs(void) +clearcmdentry(void) { struct tblentry **tblp; struct tblentry **pp; @@ -593,9 +514,8 @@ deletefuncs(void) for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { pp = tblp; while ((cmdp = *pp) != NULL) { - if (cmdp->cmdtype == CMDFUNCTION) { + if (cmdp->cmdtype == CMDNORMAL) { *pp = cmdp->next; - unreffunc(cmdp->param.func); ckfree(cmdp); } else { pp = &cmdp->next; @@ -606,7 +526,6 @@ deletefuncs(void) } - /* * Locate a command in the command hash table. If "add" is nonzero, * add the command to the table if it is not already present. The @@ -740,7 +659,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path) int error1 = 0; if (path != pathval()) - clearcmdentry(0); + clearcmdentry(); for (i = 1; i < argc; i++) { /* First look at the keywords */ @@ -836,7 +755,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path) } if (path != pathval()) - clearcmdentry(0); + clearcmdentry(); return error1; } |