| /* |
| * execvpe.c |
| * |
| * execvpe() function (from which we build execlp, execlpe, execvp). |
| * |
| * This version of execvpe() will *not* spawn /bin/sh if the command |
| * return ENOEXEC. That's what #! is for, folks! |
| * |
| * Since execlpe() and execvpe() aren't in POSIX, nor in glibc, |
| * I have followed QNX precedent in the implementation of the PATH: |
| * the PATH that is used is the one in the current environment, not |
| * in the new environment. Otherwise it would be impossible to pass |
| * a different PATH to the new process than the one one would want to |
| * use to search. |
| */ |
| |
| #include <errno.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <limits.h> |
| |
| #define DEFAULT_PATH "/bin:/usr/bin:." |
| |
| int execvpe(const char *file, char * const *argv, char * const *envp) |
| { |
| char path[PATH_MAX]; |
| const char *searchpath, *esp; |
| size_t prefixlen, filelen, totallen; |
| |
| if ( strchr(file, '/') ) /* Specific path */ |
| return execve(file, argv, envp); |
| |
| filelen = strlen(file); |
| |
| searchpath = getenv("PATH"); |
| if ( !searchpath ) |
| searchpath = DEFAULT_PATH; |
| |
| errno = ENOENT; /* Default errno, if execve() doesn't change it */ |
| |
| do { |
| esp = strchr(searchpath, ':'); |
| if ( esp ) |
| prefixlen = esp-searchpath; |
| else |
| prefixlen = strlen(searchpath); |
| |
| if ( prefixlen == 0 || searchpath[prefixlen-1] == '/' ) { |
| totallen = prefixlen+filelen; |
| if ( totallen >= PATH_MAX ) |
| continue; |
| memcpy(path, searchpath, prefixlen); |
| memcpy(path+prefixlen, file, filelen); |
| } else { |
| totallen = prefixlen+filelen+1; |
| if ( totallen >= PATH_MAX ) |
| continue; |
| memcpy(path, searchpath, prefixlen); |
| path[prefixlen] = '/'; |
| memcpy(path+prefixlen+1, file, filelen); |
| } |
| path[totallen] = '\0'; |
| |
| execve(path, argv, envp); |
| if ( errno == E2BIG || errno == ENOEXEC || |
| errno == ENOMEM || errno == ETXTBSY ) |
| break; /* Report this as an error, no more search */ |
| |
| searchpath = esp+1; |
| } while ( esp ); |
| |
| return -1; |
| } |
| |