about summary refs log tree commit diff
path: root/pkgs/profpatsch/netencode
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2020-07-03 09:38:32 +0200
committerProfpatsch <mail@profpatsch.de>2020-07-06 20:13:42 +0200
commit60f23099bac85492e0587d643416215ed0b071a3 (patch)
treea9611725e28c8f90cbe9b2db9a67bf0eadf3fc6d /pkgs/profpatsch/netencode
parentb29bae9974ac0608d9873d6092dce785d427cffe (diff)
pkgs/profpatsch: move record-get to netencode
Diffstat (limited to 'pkgs/profpatsch/netencode')
-rw-r--r--pkgs/profpatsch/netencode/default.nix11
-rw-r--r--pkgs/profpatsch/netencode/record-get.rs56
2 files changed, 66 insertions, 1 deletions
diff --git a/pkgs/profpatsch/netencode/default.nix b/pkgs/profpatsch/netencode/default.nix
index 2297db51..8457e1f5 100644
--- a/pkgs/profpatsch/netencode/default.nix
+++ b/pkgs/profpatsch/netencode/default.nix
@@ -1,4 +1,4 @@
-{ pkgs, writeRustSimpleLib }:
+{ pkgs, writeRustSimpleLib, writeRustSimple, el-semicolon, el-exec }:
 
 let
   version-check = pkgs.buildRustCrate {
@@ -34,9 +34,18 @@ let
 
   netencode-rs = netencode-rs-common false;
 
+  record-get = writeRustSimple "record-get" {
+    dependencies = [ netencode-rs el-semicolon el-exec ];
+    # TODO: for some reason the skarnet linker flag
+    # is propagated by the link target is not?
+    buildInputs = [ pkgs.skalibs ];
+  } ./record-get.rs;
+
+
 in {
   inherit
    netencode-rs
    netencode-rs-tests
+   record-get
    ;
 }
diff --git a/pkgs/profpatsch/netencode/record-get.rs b/pkgs/profpatsch/netencode/record-get.rs
new file mode 100644
index 00000000..bf4db3dd
--- /dev/null
+++ b/pkgs/profpatsch/netencode/record-get.rs
@@ -0,0 +1,56 @@
+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 el_semicolon::{el_semicolon, Arg};
+use netencode::{U};
+use netencode::parse::{u_u};
+
+fn main() {
+    let args = std::env::args_os().by_ref()
+        .map(|s| s.into_vec())
+        .skip(1)
+        .collect::<Vec<_>>();
+    let args_ref : Vec<&[u8]> = args.iter().map(|v| v.as_slice()).collect();
+    let (arg, prog) = el_semicolon::el_semicolon(&args_ref).unwrap();
+    assert!(prog.len() > 0, "record get neets a block of vars and prog, no prog provided");
+    match arg {
+        Arg::EndOfArgv | Arg::Arg(_) => {
+            panic!("first argument must be a block of vars");
+        },
+        Arg::Block(vars) => {
+            let mut stdin = vec![];
+            std::io::stdin().read_to_end(&mut stdin);
+            match u_u(&stdin) {
+                Ok((_, U::Record(m))) => {
+                    for (key, val) in m.into_iter() {
+                        // only set if it appears in the block of values.
+                        // If the block is empty, don’t filter.
+                        if vars.is_empty() || vars.contains(&key.as_bytes()) {
+                            match *val {
+                                U::Binary(b) => std::env::set_var(key, OsStr::from_bytes(b)),
+                                _ => panic!("the value of {:?} was not a binary value!", key)
+                            }
+                        }
+                    }
+                    let mut p : Vec<CString> = vec![];
+                    for arg in prog {
+                        p.push(CString::new(*arg).unwrap());
+                    }
+                    el_exec::xpathexec0(&p);
+                },
+                Ok(_) => {
+                    eprintln!("not a record!");
+                    std::process::exit(100);
+                }
+                Err(e) => {
+                    eprintln!("could not parse netencode: {:?}", e);
+                    std::process::exit(100);
+                },
+            }
+        }
+    }
+}