diff options
author | Profpatsch <mail@profpatsch.de> | 2021-02-05 10:24:20 +0100 |
---|---|---|
committer | Profpatsch <mail@profpatsch.de> | 2021-02-05 10:24:20 +0100 |
commit | 035f7e860957e8c5637bdd1c033c1953dce980b3 (patch) | |
tree | 71b076b536d6a6a8839a54c57debd6c3401cdb14 | |
parent | 8faf9338c363df8cebae4089b8c4b1832b6cb251 (diff) |
pkgs/profpatsch: adjust exec stuff to new skalibs
skarnet thought it would be wise to completely change the skalibs exec function interface without any backwards compat, so here we are. Have to reverse the code a bit, because `xmexec0` is a recursive `#define` pointing to `xmexec0_af`. `record-get` gets a rust treatment, it doesn’t really need the C interface just to exec into prog.
-rw-r--r-- | pkgs/profpatsch/execline/el_exec.rs | 21 | ||||
-rw-r--r-- | pkgs/profpatsch/netencode/default.nix | 3 | ||||
-rw-r--r-- | pkgs/profpatsch/netencode/record-get.rs | 42 | ||||
-rw-r--r-- | pkgs/profpatsch/profpatsch.de/default.nix | 2 |
4 files changed, 54 insertions, 14 deletions
diff --git a/pkgs/profpatsch/execline/el_exec.rs b/pkgs/profpatsch/execline/el_exec.rs index 25fad36f..0e4e11b7 100644 --- a/pkgs/profpatsch/execline/el_exec.rs +++ b/pkgs/profpatsch/execline/el_exec.rs @@ -12,12 +12,16 @@ fn to_c_argv<S: AsRef<CStr>>(s: &[S]) -> (&[S], Vec<*const libc::c_char>) { /// Exec into argv, or exit 0 if it’s empty. /// Will throw 127 if the executable is not found (ENOENT) /// and 126 for any other exec error. -pub fn xpathexec0<'a, S: AsRef<CStr>>(argv: &'a [S]) { +pub fn xmexec0<'a, S: AsRef<CStr>>(argv: &'a [S]) { let (c_strings, c_argv) = to_c_argv(argv); unsafe { - C::xpathexec0( - c_argv.as_ptr() as *const *const libc::c_char + let env = C::environ; + C::xmexec0_af( + c_argv[0] as *const libc::c_char, + c_argv.as_ptr() as *const *const libc::c_char, + env, + C::env_len(env) ) } } @@ -25,8 +29,15 @@ pub fn xpathexec0<'a, S: AsRef<CStr>>(argv: &'a [S]) { mod C { #[link(name = "skarnet")] extern "C" { - pub fn xpathexec0( - argv: *const *const libc::c_char + pub fn xmexec0_af( + file: *const libc::c_char, + argv: *const *const libc::c_char, + envp: *const *const libc::c_char, + envlen: libc::size_t ); + pub static environ: *const *const libc::c_char; + pub fn env_len( + e: *const *const libc::c_char + ) -> libc::size_t; } } diff --git a/pkgs/profpatsch/netencode/default.nix b/pkgs/profpatsch/netencode/default.nix index 8457e1f5..bafedc13 100644 --- a/pkgs/profpatsch/netencode/default.nix +++ b/pkgs/profpatsch/netencode/default.nix @@ -35,10 +35,9 @@ let netencode-rs = netencode-rs-common false; record-get = writeRustSimple "record-get" { - dependencies = [ netencode-rs el-semicolon el-exec ]; + dependencies = [ netencode-rs el-semicolon ]; # TODO: for some reason the skarnet linker flag # is propagated by the link target is not? - buildInputs = [ pkgs.skalibs ]; } ./record-get.rs; diff --git a/pkgs/profpatsch/netencode/record-get.rs b/pkgs/profpatsch/netencode/record-get.rs index c823249d..60d2b52d 100644 --- a/pkgs/profpatsch/netencode/record-get.rs +++ b/pkgs/profpatsch/netencode/record-get.rs @@ -1,10 +1,10 @@ extern crate netencode; extern crate el_semicolon; -extern crate el_exec; use std::io::Read; use std::ffi::{CString, OsStr}; use std::os::unix::ffi::{OsStringExt, OsStrExt}; +use std::os::unix::process::{CommandExt}; use el_semicolon::{el_semicolon, Arg}; use netencode::{U, encode}; use netencode::parse::{u_u}; @@ -43,11 +43,8 @@ fn main() { } } } - let mut p : Vec<CString> = vec![]; - for arg in prog { - p.push(CString::new(*arg).unwrap()); - } - el_exec::xpathexec0(&p); + let env: Vec<(&[u8], &[u8])> = vec![]; + exec_into_args("record-get", prog, env) }, Ok(_) => { eprintln!("not a record!"); @@ -61,3 +58,36 @@ fn main() { } } } + +pub fn exec_into_args<'a, 'b, Args, Arg, Env, Key, Val>(current_prog_name: &str, args: Args, env_additions: Env) -> ! +where + Args: IntoIterator<Item = Arg>, + Arg: AsRef<[u8]>, + Env: IntoIterator<Item = (Key, Val)>, + Key: AsRef<[u8]>, + Val: AsRef<[u8]>, +{ + // TODO: is this possible without collecting into a Vec first, just leaving it an IntoIterator? + let args = args.into_iter().collect::<Vec<Arg>>(); + let mut args = args.iter().map(|v| OsStr::from_bytes(v.as_ref())); + let prog = args.nth(0).expect(&format!("{}: first argument must be an executable", current_prog_name)); + // TODO: same here + let env = env_additions.into_iter().collect::<Vec<(Key, Val)>>(); + let env = env.iter().map(|(k,v)| (OsStr::from_bytes(k.as_ref()), OsStr::from_bytes(v.as_ref()))); + let err = std::process::Command::new(prog).args(args).envs(env).exec(); + die_missing_executable(current_prog_name, format!("exec failed: {:?}, while trying to execing into {:?}", err, prog)); +} + +/// Exit 127 to signify a missing executable. +pub fn die_missing_executable<S>(current_prog_name: &str, msg: S) -> ! +where S: AsRef<str> +{ + die_with(127, current_prog_name, msg) +} + +fn die_with<S>(status: i32, current_prog_name: &str, msg: S) -> ! +where S: AsRef<str> +{ + eprintln!("{}: {}", current_prog_name, msg.as_ref()); + std::process::exit(status) +} diff --git a/pkgs/profpatsch/profpatsch.de/default.nix b/pkgs/profpatsch/profpatsch.de/default.nix index 338599ae..9f15cd2a 100644 --- a/pkgs/profpatsch/profpatsch.de/default.nix +++ b/pkgs/profpatsch/profpatsch.de/default.nix @@ -120,7 +120,7 @@ let None => std::process::exit(1), // If it does, continue Some(val) => - el_exec::xpathexec0( + el_exec::xmexec0( &el_substitute::simple_substitute_argv( &vec![el_substitute::Subst { var: &as_var, |