From b4f02adc32b38361c7fa57884a49bf1433d88980 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 30 Dec 2020 17:57:01 +0200 Subject: [PATCH] os: add os.execve/3 (extracted from unix_spawn_process); use os.execvp/2 in v.util.launch_tool/3 --- vlib/os/os_c.v | 30 ++++++++++++++++++++++++++++-- vlib/os/process_nix.c.v | 18 +++--------------- vlib/v/util/util.v | 2 +- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/vlib/os/os_c.v b/vlib/os/os_c.v index 016fb64dec..d006096f21 100644 --- a/vlib/os/os_c.v +++ b/vlib/os/os_c.v @@ -869,7 +869,7 @@ pub fn create(path string) ?File { } } -// execvp - loads and executes a new child process, in place of the current process. +// execvp - loads and executes a new child process, *in place* of the current process. // The child process executable is located in `cmdpath`. // The arguments, that will be passed to it are in `args`. // NB: this function will NOT return when successfull, since @@ -883,6 +883,32 @@ pub fn execvp(cmdpath string, args []string) ? { cargs << charptr(0) res := C.execvp(charptr(cmdpath.str), cargs.data) if res == -1 { - return error(posix_get_error_msg(C.errno)) + return error_with_code(posix_get_error_msg(C.errno), C.errno) + } +} + +// execve - loads and executes a new child process, *in place* of the current process. +// The child process executable is located in `cmdpath`. +// The arguments, that will be passed to it are in `args`. +// You can pass environment variables to through `envs`. +// NB: this function will NOT return when successfull, since +// the child process will take control over execution. +pub fn execve(cmdpath string, args []string, envs []string) ? { + mut cargv := []charptr{} + mut cenvs := []charptr{} + cargv << charptr(cmdpath.str) + for i in 0 .. args.len { + cargv << charptr(args[i].str) + } + for i in 0 .. envs.len { + cenvs << charptr(envs[i].str) + } + cargv << charptr(0) + cenvs << charptr(0) + res := C.execve(charptr(cmdpath.str), cargv.data, cenvs.data) + // NB: normally execve does not return at all. + // If it returns, then something went wrong... + if res == -1 { + return error_with_code(posix_get_error_msg(C.errno), C.errno) } } diff --git a/vlib/os/process_nix.c.v b/vlib/os/process_nix.c.v index 9710f4dff6..f54e24e0e7 100644 --- a/vlib/os/process_nix.c.v +++ b/vlib/os/process_nix.c.v @@ -43,22 +43,10 @@ fn (mut p Process) unix_spawn_process() int { fd_close(pipeset[3]) fd_close(pipeset[5]) } - mut cargv := []charptr{} - mut cenvs := []charptr{} - cargv << charptr(p.filename.str) - for i in 0 .. p.args.len { - cargv << charptr(p.args[i].str) + execve(p.filename, p.args, p.env) or { + eprintln(err) + exit(1) } - for i in 0 .. p.env.len { - cenvs << charptr(p.env[i].str) - } - cargv << charptr(0) - cenvs << charptr(0) - C.execve(charptr(p.filename.str), cargv.data, cenvs.data) - // NB: normally execve does not return at all. - // If it returns, then something went wrong... - eprintln(posix_get_error_msg(C.errno)) - exit(1) return 0 } diff --git a/vlib/v/util/util.v b/vlib/v/util/util.v index b034af484b..811b71585b 100644 --- a/vlib/v/util/util.v +++ b/vlib/v/util/util.v @@ -164,7 +164,7 @@ pub fn launch_tool(is_verbose bool, tool_name string, args []string) { if is_verbose { println('launch_tool running tool command: $tool_command ...') } - exit(os.system(tool_command)) + os.execvp(tool_exe, args) } // NB: should_recompile_tool/2 compares unix timestamps that have 1 second resolution