about summary refs log tree commit diff
diff options
context:
space:
mode:
-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,