commit a747b0c8d3871483ee64f865d57dc10ccd828ec0
Author: Daniel Barlow <dan@telent.net>
Date: Wed, 29 Apr 2026 19:04:02 +0100
initial commit
Diffstat:
6 files changed, 471 insertions(+), 0 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -0,0 +1,267 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "bitflags"
+version = "2.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
+
+[[package]]
+name = "bstr"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
+name = "fork"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bcc4b4161e53d499e41af904acb23950adf85682c772921ef3957cf1ecc98b3"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.186"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "luad"
+version = "0.1.0"
+dependencies = [
+ "fork",
+ "libc",
+ "mlua",
+]
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "mlua"
+version = "0.11.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccd36acfa49ce6ee56d1307a061dd302c564eee757e6e4cd67eb4f7204846fab"
+dependencies = [
+ "bstr",
+ "either",
+ "libc",
+ "mlua-sys",
+ "num-traits",
+ "parking_lot",
+ "rustc-hash",
+ "rustversion",
+]
+
+[[package]]
+name = "mlua-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1c3a7fc7580227ece249fd90aa2fa3b39eb2b49d3aec5e103b3e85f2c3dfc8"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
diff --git a/Cargo.toml b/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "luad"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+fork = "0.7.0"
+libc = "0.2.186"
+mlua = { version = "0.11.6", features = ["lua53"] }
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly"
diff --git a/rustup.nix b/rustup.nix
@@ -0,0 +1,52 @@
+{ pkgs ? import <nixpkgs> {} }:
+ let
+ overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml));
+ libPath = with pkgs; lib.makeLibraryPath [
+ # load external libraries that you need in your rust project here
+ ];
+ python = (pkgs.python3.withPackages (python-pkgs: [
+ python-pkgs.pynacl
+ python-pkgs.zeroconf
+ python-pkgs.bleak
+ ]));
+ in
+ pkgs.mkShell rec {
+ nativeBuildInputs= with pkgs; [
+ openssl
+ rustup
+ lua5_3
+ pkg-config
+# sops
+ ];
+ buildInputs = with pkgs; [
+ clang
+ # Replace llvmPackages with llvmPackages_X, where X is the latest LLVM version (at the time of writing, 16)
+ llvmPackages.bintools
+ rustup
+ ];
+ RUSTC_VERSION = overrides.toolchain.channel;
+ # https://github.com/rust-lang/rust-bindgen#environment-variables
+ LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
+ shellHook = ''
+ export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
+ export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/
+ '';
+ # Add precompiled library to rustc search path
+ RUSTFLAGS = (builtins.map (a: ''-L ${a}/lib'') [
+ # add libraries here (e.g. pkgs.libvmi)
+ ]);
+ LD_LIBRARY_PATH = libPath;
+ # Add glibc, clang, glib, and other headers to bindgen search path
+ BINDGEN_EXTRA_CLANG_ARGS =
+ # Includes normal include path
+ (builtins.map (a: ''-I"${a}/include"'') [
+ # add dev libraries here (e.g. pkgs.libvmi.dev)
+ pkgs.glibc.dev
+ ])
+ # Includes with special directory paths
+ ++ [
+ ''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"''
+ ''-I"${pkgs.glib.dev}/include/glib-2.0"''
+ ''-I${pkgs.glib.out}/lib/glib-2.0/include/''
+ ];
+ }
diff --git a/src/bin/luac.rs b/src/bin/luac.rs
@@ -0,0 +1,36 @@
+#![feature(unix_socket_ancillary_data)]
+
+use std::{
+ os::unix::net::{
+ UnixDatagram,
+ SocketAncillary,
+ AncillaryData
+ },
+ env,
+ io::IoSlice
+};
+
+fn main() {
+ let mut payload = "".to_string();
+ let mut argv = env::args();
+ let _ = argv.next();
+ for a in argv {
+ payload.push_str(&a);
+ payload.push_str("\0");
+ }
+ let payload = payload.into_bytes();
+ let Ok(sock_path) = env::var("LUAD_SOCKET_PATH") else {
+ panic!("need to set LUAD_SOCKET_PATH env var");
+ };
+ let sock = UnixDatagram::unbound().expect("socket");
+ sock.connect(sock_path).expect("connect");
+ let fds = [0, 1, 2];
+ let mut ancillary_buffer = [0; 128];
+ let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+ ancillary.add_fds(&fds[..]);
+ let buf = IoSlice::new(&payload);
+ sock.send_vectored_with_ancillary(&[buf], &mut ancillary).expect("send failed");
+
+
+ println!("heyt");
+}
diff --git a/src/main.rs b/src/main.rs
@@ -0,0 +1,105 @@
+#![feature(unix_socket_ancillary_data)]
+
+use mlua::Lua;
+use std::{
+ env,
+ io,
+ io::IoSliceMut,
+ path::Path,
+ process::exit,
+ collections::HashMap
+};
+
+use std::os::unix::net::{
+ UnixDatagram,
+ SocketAncillary,
+ AncillaryData
+};
+
+use libc::WEXITSTATUS;
+use fork::{Fork, fork, waitpid};
+
+// if we use SCM_RIGHTS to pass fds from client, we also need to
+// write the client as we can't do that with socat
+
+fn run_lua(lua : &Lua, path : &Path) {
+ let chunk = lua.load(path);
+ match chunk.exec() {
+ Ok(()) => { println!("lua returned ok"); },
+ Err(e) => {
+ println!("lua error {:?}", e);
+ exit(1);
+ },
+ };
+ exit(0);
+}
+
+fn main() -> std::io::Result<()> {
+ let Ok(sock_path) = env::var("LUAD_SOCKET_PATH") else {
+ panic!("need to set LUAD_SOCKET_PATH env var");
+ };
+
+ let lua = unsafe { Lua::unsafe_new() };
+
+ let sock = UnixDatagram::bind(sock_path)?;
+
+ // listen for datagrams. each time we get one, fork a child
+ // to run lua script with the datagram payload and its stdio
+ // connected to the passed fds. when the lua subprocess exits,
+ // write the exit status back to the peer
+ // this implies we need a map of child pid -> peer address
+
+ loop {
+ let mut buf = [0u8; 1024];
+ let mut bufs = [
+ IoSliceMut::new(&mut buf),
+ ];
+ let mut ancillary_buffer = [0; 128];
+ let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+ match sock.recv_vectored_with_ancillary(&mut bufs, &mut ancillary) {
+ Ok((size, truncated)) => {
+ let mut fds : Vec<i32> = Vec::new();
+ for ancillary_result in ancillary.messages() {
+ if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+ for fd in scm_rights {
+ println!("receive file descriptor: {fd}");
+ fds.push(fd);
+ }
+ }
+ }
+ println!("data {:?}, len {:?}", buf, size);
+ println!("fds {:?}", fds);
+
+ },
+ Err(e) => {
+ println!("error reading: {:?}", e);
+ }
+ }
+ }
+
+ // for pathname in io::stdin().lines() {
+ // let pathname = pathname.unwrap();
+ // let path = Path::new(&pathname);
+ // match fork() {
+ // Ok(Fork::Parent(pid)) => {
+ // // println!("parent {:?} {:?}", pid, result);
+ // match waitpid(pid) {
+ // Ok(status) => {
+ // println!("exited {:?}", WEXITSTATUS(status));
+ // },
+ // Err(e) => {
+ // println!("waitpid failed {:?}", e);
+ // }
+ // }
+ // },
+ // Ok(Fork::Child) => {
+ // run_lua(&lua, &path);
+ // }
+ // Err(e) => {
+ // println!("fork error {:?}", e);
+ // exit(1);
+ // }
+ // }
+ // };
+ // Ok(())
+}