about summary refs log tree commit diff
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-02-05 10:24:20 +0100
committerProfpatsch <mail@profpatsch.de>2021-02-05 10:24:20 +0100
commit035f7e860957e8c5637bdd1c033c1953dce980b3 (patch)
tree71b076b536d6a6a8839a54c57debd6c3401cdb14
parent8faf9338c363df8cebae4089b8c4b1832b6cb251 (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.rs21
-rw-r--r--pkgs/profpatsch/netencode/default.nix3
-rw-r--r--pkgs/profpatsch/netencode/record-get.rs42
-rw-r--r--pkgs/profpatsch/profpatsch.de/default.nix2
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,