diff --git a/include/unistd.h b/include/unistd.h index 4c4b04cc7798..3753cd810e14 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -335,6 +335,7 @@ int execlp(const char *, const char *, ...); int execv(const char *, char * const *); int execve(const char *, char * const *, char * const *); int execvp(const char *, char * const *); +int execvP(const char *, const char *, char * const *); pid_t fork(void); long fpathconf(int, int); char *getcwd(char *, size_t); diff --git a/lib/libc/gen/exec.3 b/lib/libc/gen/exec.3 index 9387267c26b1..ea0f5b4b1df3 100644 --- a/lib/libc/gen/exec.3 +++ b/lib/libc/gen/exec.3 @@ -41,7 +41,8 @@ .Nm execle , .Nm exect , .Nm execv , -.Nm execvp +.Nm execvp , +.Nm execvP .Nd execute a file .Sh LIBRARY .Lb libc @@ -60,6 +61,8 @@ .Fn execv "const char *path" "char *const argv[]" .Ft int .Fn execvp "const char *file" "char *const argv[]" +.Ft int +.Fn execvP "const char *file" "const char *search_path" "char *const argv[]" .Sh DESCRIPTION The .Nm exec @@ -99,8 +102,9 @@ pointer. The .Fn exect , .Fn execv , +.Fn execvp , and -.Fn execvp +.Fn execvP functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the file name associated @@ -134,14 +138,19 @@ in the current process. Some of these functions have special semantics. .Pp The functions -.Fn execlp +.Fn execlp , +.Fn execvp , and -.Fn execvp +.Fn execvP will duplicate the actions of the shell in searching for an executable file if the specified file name does not contain a slash .Dq Li / character. -The search path is the path specified in the environment by +For +.Fn execlp +and +.Fn execvp , +search path is the path specified in the environment by .Dq Ev PATH variable. If this variable isn't specified, @@ -151,6 +160,9 @@ definition in .Aq paths.h , which is set to .Dq Ev /usr/bin:/bin . +For +.Fn execvP , +the search path is specified as an argument to the function. In addition, certain errors are treated specially. .Pp If an error is ambiguous (for simplicity, we shall consider all @@ -206,9 +218,10 @@ The shell. The .Fn execl , .Fn execle , -.Fn execlp -and +.Fn execlp , .Fn execvp +and +.Fn execvP functions may fail and set .Va errno @@ -300,3 +313,7 @@ and functions conform to .St -p1003.1-88 . +The +.Fn execvP +function first appeared in +.Fx 5.2 . diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c index 7f13e0a72134..3f81a3a5a4ab 100644 --- a/lib/libc/gen/exec.c +++ b/lib/libc/gen/exec.c @@ -142,15 +142,27 @@ execv(name, argv) } int -execvp(name, argv) +execvp(const char *name, char *const *argv) +{ + const char *path; + + /* Get the path we're searching. */ + if (!(path = getenv("PATH"))) + path = _PATH_DEFPATH; + return(execvP(name,path,argv)); +} + +int +execvP(name, path, argv) const char *name; + const char *path; char * const *argv; { char **memp; int cnt, lp, ln; char *p; int eacces, save_errno; - char *bp, *cur, *path, buf[MAXPATHLEN]; + char *bp, *cur, buf[MAXPATHLEN]; struct stat sb; eacces = 0; @@ -158,7 +170,7 @@ execvp(name, argv) /* If it's an absolute or relative path name, it's easy. */ if (index(name, '/')) { bp = (char *)name; - cur = path = NULL; + cur = NULL; goto retry; } bp = buf; @@ -169,16 +181,12 @@ execvp(name, argv) return (-1); } - /* Get the path we're searching. */ - if (!(path = getenv("PATH"))) - path = _PATH_DEFPATH; cur = alloca(strlen(path) + 1); if (cur == NULL) { errno = ENOMEM; return (-1); } strcpy(cur, path); - path = cur; while ( (p = strsep(&cur, ":")) ) { /* * It's a SHELL path -- double, leading and trailing colons @@ -197,7 +205,7 @@ execvp(name, argv) * the user may execute the wrong program. */ if (lp + ln + 2 > sizeof(buf)) { - (void)_write(STDERR_FILENO, "execvp: ", 8); + (void)_write(STDERR_FILENO, "execvP: ", 8); (void)_write(STDERR_FILENO, p, lp); (void)_write(STDERR_FILENO, ": path too long\n", 16);