chiark / gitweb /
[PATCH] klibc: version 1.0.3
[elogind.git] / klibc / klibc / execvpe.c
1 /*
2  * execvpe.c
3  *
4  * execvpe() function (from which we build execlp, execlpe, execvp).
5  *
6  * This version of execvpe() will *not* spawn /bin/sh if the command
7  * return ENOEXEC.  That's what #! is for, folks!
8  *
9  * Since execlpe() and execvpe() aren't in POSIX, nor in glibc,
10  * I have followed QNX precedent in the implementation of the PATH:
11  * the PATH that is used is the one in the current environment, not
12  * in the new environment.
13  */
14
15 #include <errno.h>
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <limits.h>
20
21 #define DEFAULT_PATH    "/bin:/usr/bin:."
22
23 int execvpe(const char *file, char * const *argv, char * const *envp)
24 {
25   char path[PATH_MAX];
26   const char *searchpath, *esp;
27   size_t prefixlen, filelen, totallen;
28
29   if ( strchr(file, '/') )      /* Specific path */
30     return execve(file, argv, envp);
31
32   filelen = strlen(file);
33
34   searchpath = getenv("PATH");
35   if ( !searchpath )
36     searchpath = DEFAULT_PATH;
37   
38   errno = ENOENT; /* Default errno, if execve() doesn't change it */
39
40   do {
41     esp = strchr(searchpath, ':');
42     if ( esp )
43       prefixlen = esp-searchpath;
44     else
45       prefixlen = strlen(searchpath);
46     
47     if ( prefixlen == 0 || searchpath[prefixlen-1] == '/' ) {
48       totallen = prefixlen+filelen;
49       if ( totallen >= PATH_MAX )
50         continue;
51       memcpy(path, searchpath, prefixlen);
52       memcpy(path+prefixlen, file, filelen);
53     } else {
54       totallen = prefixlen+filelen+1;
55       if ( totallen >= PATH_MAX )
56         continue;
57       memcpy(path, searchpath, prefixlen);
58       path[prefixlen] = '/';
59       memcpy(path+prefixlen+1, file, filelen);
60     }
61     path[totallen] = '\0';
62     
63     execve(path, argv, envp);
64     if ( errno == E2BIG || errno == ENOEXEC ||
65          errno == ENOMEM || errno == ETXTBSY )
66       break;                    /* Report this as an error, no more search */
67     
68     searchpath = esp+1;
69   } while ( esp );
70
71   return -1;
72 }
73