2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2004-2015, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
8 #include <libroot_private.h>
20 #include <errno_private.h>
24 count_arguments(va_list list
, const char* arg
, char*** _env
)
30 arg
= va_arg(list
, const char*);
34 *_env
= va_arg(list
, char**);
41 copy_arguments(va_list list
, const char** args
, const char* arg
)
47 arg
= va_arg(list
, const char*);
56 do_exec(const char* path
, char* const args
[], char* const environment
[],
57 bool useDefaultInterpreter
)
59 if (path
== NULL
|| args
== NULL
) {
60 __set_errno(B_BAD_VALUE
);
64 // Count argument/environment list entries here, we don't want
65 // to do this in the kernel
67 while (args
[argCount
] != NULL
) {
72 if (environment
!= NULL
) {
73 while (environment
[envCount
] != NULL
) {
79 // we need some more info on what to do...
80 __set_errno(B_BAD_VALUE
);
84 // Test validity of executable + support for scripts
85 char invoker
[B_FILE_NAME_LENGTH
];
86 status_t status
= __test_executable(path
, invoker
);
88 if (status
== B_NOT_AN_EXECUTABLE
&& useDefaultInterpreter
) {
89 strcpy(invoker
, "/bin/sh");
97 char** newArgs
= NULL
;
98 if (invoker
[0] != '\0') {
99 status
= __parse_invoke_line(invoker
, &newArgs
, &args
, &argCount
, path
);
108 char** flatArgs
= NULL
;
110 status
= __flatten_process_args(newArgs
? newArgs
: args
, argCount
,
111 environment
, &envCount
, path
, &flatArgs
, &flatArgsSize
);
113 if (status
== B_OK
) {
114 __set_errno(_kern_exec(path
, flatArgs
, flatArgsSize
, argCount
, envCount
,
116 // if this call returns, something definitely went wrong
131 execve(const char* path
, char* const args
[], char* const environment
[])
133 return do_exec(path
, args
, environment
, false);
138 execv(const char* path
, char* const argv
[])
140 return do_exec(path
, argv
, environ
, false);
145 execvp(const char* file
, char* const argv
[])
147 return execvpe(file
, argv
, environ
);
152 execvpe(const char* file
, char* const argv
[], char* const environment
[])
154 // let do_exec() handle cases where file is a path (or invalid)
155 if (file
== NULL
|| strchr(file
, '/') != NULL
)
156 return do_exec(file
, argv
, environment
, true);
158 // file is just a leaf name, so we have to look it up in the path
161 const char* paths
= getenv("PATH");
163 __set_errno(B_ENTRY_NOT_FOUND
);
167 int fileNameLen
= strlen(file
);
169 // iterate through the paths
170 const char* pathEnd
= paths
- 1;
171 while (pathEnd
!= NULL
) {
173 pathEnd
= strchr(paths
, ':');
174 int pathLen
= (pathEnd
? pathEnd
- paths
: strlen(paths
));
176 // We skip empty paths and those that would become too long.
177 // The latter is not really correct, but practically irrelevant.
179 || pathLen
+ 1 + fileNameLen
>= B_PATH_NAME_LENGTH
) {
183 // concatinate the program path
184 char path
[B_PATH_NAME_LENGTH
];
185 memcpy(path
, paths
, pathLen
);
186 path
[pathLen
] = '\0';
188 if (path
[pathLen
- 1] != '/')
192 // check whether it is a file
194 if (stat(path
, &st
) != 0 || !S_ISREG(st
.st_mode
))
197 // if executable, execute it
198 if (access(path
, X_OK
) == 0)
199 return do_exec(path
, argv
, environment
, true);
202 __set_errno(B_ENTRY_NOT_FOUND
);
208 execl(const char* path
, const char* arg
, ...)
217 count
= count_arguments(list
, arg
, NULL
);
222 args
= (const char**)alloca((count
+ 1) * sizeof(char*));
224 copy_arguments(list
, args
, arg
);
227 return do_exec(path
, (char* const*)args
, environ
, false);
232 execlp(const char* file
, const char* arg
, ...)
241 count
= count_arguments(list
, arg
, NULL
);
246 args
= (const char**)alloca((count
+ 1) * sizeof(char*));
248 copy_arguments(list
, args
, arg
);
251 return execvp(file
, (char* const*)args
);
256 execle(const char* path
, const char* arg
, ... /*, char** env */)
266 count
= count_arguments(list
, arg
, &env
);
271 args
= (const char**)alloca((count
+ 1) * sizeof(char*));
273 copy_arguments(list
, args
, arg
);
276 return do_exec(path
, (char* const*)args
, env
, false);
279 // TODO: remove this again if possible
280 extern int exect(const char *path
, char *const *argv
);
283 exect(const char* path
, char* const* argv
)
285 return execv(path
, argv
);