bunpen: bind execvpe
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
// vim: set shiftwidth=2 :
|
// vim: set shiftwidth=2 :
|
||||||
|
|
||||||
|
use log;
|
||||||
|
use os;
|
||||||
use path;
|
use path;
|
||||||
use rt;
|
use rt;
|
||||||
|
use strings;
|
||||||
use types::c;
|
use types::c;
|
||||||
|
|
||||||
export fn execve(path: str, argv: []str, envp: []str = []) (rt::errno | void) = {
|
export fn execve(path: str, argv: []str, envp: []str = []) rt::errno = {
|
||||||
let path_buf: [path::MAX]c::char = [0...];
|
let path_buf: [path::MAX]c::char = [0...];
|
||||||
|
|
||||||
syscall(
|
syscall(
|
||||||
@@ -14,6 +17,21 @@ export fn execve(path: str, argv: []str, envp: []str = []) (rt::errno | void) =
|
|||||||
to_cstr_array(argv): *[*]nullable *const c::char: uintptr: u64,
|
to_cstr_array(argv): *[*]nullable *const c::char: uintptr: u64,
|
||||||
to_cstr_array(envp): *[*]nullable *const c::char: uintptr: u64,
|
to_cstr_array(envp): *[*]nullable *const c::char: uintptr: u64,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
log::fatal("[exec] unexpectedly returned without error");
|
||||||
|
};
|
||||||
|
|
||||||
|
// if `name` contains a slash, proceed as per `execve`.
|
||||||
|
// otherwise, crawl $PATH and try executing until we succeed.
|
||||||
|
export fn execvpe(name: str, argv: []str, envp: []str = []) rt::errno = {
|
||||||
|
return if (strings::contains(name, "/")) {
|
||||||
|
yield execve(name, argv, envp);
|
||||||
|
} else {
|
||||||
|
yield match (os::getenv("PATH")) {
|
||||||
|
case let p: str => yield _execvpe(p, name, argv, envp);
|
||||||
|
case void => yield execve(name, argv, envp);
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// allocate and return a NULL-terminated array of pointers to c strings.
|
// allocate and return a NULL-terminated array of pointers to c strings.
|
||||||
@@ -26,3 +44,19 @@ fn to_cstr_array(strs: []str) []nullable *const c::char = {
|
|||||||
append(cstrs, null);
|
append(cstrs, null);
|
||||||
return cstrs;
|
return cstrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// split `path` on `:`, crawl it, and try executing until we succeed.
|
||||||
|
// note that 1:1 parity with libc's execvpe is probably not what we have here.
|
||||||
|
fn _execvpe(path: str, name: str, argv: []str, envp: []str = []) rt::errno = {
|
||||||
|
let status = rt::ENOENT;
|
||||||
|
let pieces = strings::split(path, ":");
|
||||||
|
defer free(pieces);
|
||||||
|
for (let p .. pieces) {
|
||||||
|
let this_path = strings::join("/", p, name);
|
||||||
|
defer free(this_path);
|
||||||
|
status = execve(this_path, argv, envp);
|
||||||
|
// try the next item, or return the status if this is the last one.
|
||||||
|
};
|
||||||
|
|
||||||
|
return status;
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user