Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libc/gen/exec.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include <paths.h> | #include <paths.h> | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include "un-namespace.h" | #include "un-namespace.h" | ||||
#include "libc_private.h" | #include "libc_private.h" | ||||
extern char **environ; | extern char **environ; | ||||
static const char execvPe_err_preamble[] = "execvP: "; | |||||
static const char execvPe_err_trailer[] = ": path too long\n"; | |||||
int | int | ||||
execl(const char *name, const char *arg, ...) | execl(const char *name, const char *arg, ...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
const char **argv; | const char **argv; | ||||
int n; | int n; | ||||
va_start(ap, arg); | va_start(ap, arg); | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
execvPe(const char *name, const char *path, char * const *argv, | execvPe(const char *name, const char *path, char * const *argv, | ||||
char * const *envp) | char * const *envp) | ||||
{ | { | ||||
const char **memp; | const char **memp; | ||||
size_t cnt, lp, ln; | size_t cnt, lp, ln; | ||||
int eacces, save_errno; | int eacces, save_errno; | ||||
char *cur, buf[MAXPATHLEN]; | char buf[MAXPATHLEN]; | ||||
const char *p, *bp; | const char *bp, *np, *op, *p; | ||||
struct stat sb; | struct stat sb; | ||||
eacces = 0; | eacces = 0; | ||||
/* If it's an absolute or relative path name, it's easy. */ | /* If it's an absolute or relative path name, it's easy. */ | ||||
if (strchr(name, '/')) { | if (strchr(name, '/')) { | ||||
bp = name; | bp = name; | ||||
cur = NULL; | op = NULL; | ||||
goto retry; | goto retry; | ||||
} | } | ||||
bp = buf; | bp = buf; | ||||
/* If it's an empty path name, fail in the usual POSIX way. */ | /* If it's an empty path name, fail in the usual POSIX way. */ | ||||
if (*name == '\0') { | if (*name == '\0') { | ||||
errno = ENOENT; | errno = ENOENT; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
cur = alloca(strlen(path) + 1); | op = path; | ||||
if (cur == NULL) { | ln = strlen(name); | ||||
errno = ENOMEM; | while (op != NULL) { | ||||
return (-1); | np = strchrnul(op, ':'); | ||||
} | |||||
strcpy(cur, path); | |||||
while ((p = strsep(&cur, ":")) != NULL) { | |||||
/* | /* | ||||
* It's a SHELL path -- double, leading and trailing colons | * It's a SHELL path -- double, leading and trailing colons | ||||
* mean the current directory. | * mean the current directory. | ||||
*/ | */ | ||||
if (*p == '\0') { | if (np == op) { | ||||
/* Empty component. */ | |||||
p = "."; | p = "."; | ||||
lp = 1; | lp = 1; | ||||
} else | } else { | ||||
lp = strlen(p); | /* Non-empty component. */ | ||||
ln = strlen(name); | p = op; | ||||
lp = np - op; | |||||
} | |||||
/* Advance to the next component or terminate after this. */ | |||||
if (*np == '\0') | |||||
op = NULL; | |||||
else | |||||
op = np + 1; | |||||
/* | /* | ||||
* If the path is too long complain. This is a possible | * If the path is too long complain. This is a possible | ||||
* security issue; given a way to make the path too long | * security issue; given a way to make the path too long | ||||
* the user may execute the wrong program. | * the user may execute the wrong program. | ||||
*/ | */ | ||||
if (lp + ln + 2 > sizeof(buf)) { | if (lp + ln + 2 > sizeof(buf)) { | ||||
(void)_write(STDERR_FILENO, "execvP: ", 8); | (void)_write(STDERR_FILENO, execvPe_err_preamble, | ||||
sizeof(execvPe_err_preamble) - 1); | |||||
(void)_write(STDERR_FILENO, p, lp); | (void)_write(STDERR_FILENO, p, lp); | ||||
(void)_write(STDERR_FILENO, ": path too long\n", | (void)_write(STDERR_FILENO, execvPe_err_trailer, | ||||
16); | sizeof(execvPe_err_trailer) - 1); | ||||
continue; | continue; | ||||
} | } | ||||
bcopy(p, buf, lp); | bcopy(p, buf, lp); | ||||
buf[lp] = '/'; | buf[lp] = '/'; | ||||
bcopy(name, buf + lp + 1, ln); | bcopy(name, buf + lp + 1, ln); | ||||
buf[lp + ln + 1] = '\0'; | buf[lp + ln + 1] = '\0'; | ||||
retry: (void)_execve(bp, argv, envp); | retry: (void)_execve(bp, argv, envp); | ||||
▲ Show 20 Lines • Show All 88 Lines • Show Last 20 Lines |