luad

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 8dbe90e0ad291d83c56e6a1a7081701dfcba22f8
parent a747b0c8d3871483ee64f865d57dc10ccd828ec0
Author: Daniel Barlow <dan@telent.net>
Date:   Wed, 29 Apr 2026 21:25:34 +0100

parse the datagram payload and fork lua on the file

Diffstat:
Msrc/main.rs | 123+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 74 insertions(+), 49 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -13,27 +13,66 @@ use std::{ use std::os::unix::net::{ UnixDatagram, SocketAncillary, - AncillaryData + AncillaryData, + SocketAddr + }; 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 fork_lua(lua : &Lua, args: Vec<String>, fds: Vec<i32>) -> Option<i32> { + let pathname = &args[0]; -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); + let path = Path::new(pathname); + match fork() { + Ok(Fork::Parent(pid)) => Some(pid), + Ok(Fork::Child) => { + for (i, fd) in fds.iter().enumerate() { + unsafe { libc::dup2(*fd, i.try_into().unwrap()); } + }; + let chunk = lua.load(path); + match chunk.exec() { + Ok(()) => { println!("lua returned ok"); }, + Err(e) => { + println!("lua error {:?}", e); + exit(1); + }, + }; + exit(0); }, - }; - exit(0); + Err(e) => { + println!("fork error {:?}", e); + None + } + } +} + +fn read_ancillary_data(ancillary : SocketAncillary<'_>) -> Vec<i32> { + 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!("fds {:?}", fds); + fds +} + +fn split_command(buf : &[u8]) -> Vec<String> { + let mut words : Vec<String> = Vec::new(); + for w in buf.split(|e| *e == 0) { + if let Ok(s) = str::from_utf8(w) { + words.push(s.to_string()); + } + } + words } + fn main() -> std::io::Result<()> { let Ok(sock_path) = env::var("LUAD_SOCKET_PATH") else { panic!("need to set LUAD_SOCKET_PATH env var"); @@ -43,6 +82,7 @@ fn main() -> std::io::Result<()> { let sock = UnixDatagram::bind(sock_path)?; + let mut peers : HashMap<i32, SocketAddr> = HashMap::new(); // 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, @@ -56,50 +96,35 @@ fn main() -> std::io::Result<()> { ]; 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); - } - } + match sock.recv_vectored_with_ancillary_from(&mut bufs, &mut ancillary) { + Ok((size, truncated, peer)) => { + let fds = read_ancillary_data(ancillary); + let args = split_command(&buf[..size-1]); + println!("args {:?} from {:?}", args, peer); + if let Some(child) = fork_lua(&lua, args, fds) { + println!("forked {child}"); + peers.insert(child, peer); } - println!("data {:?}, len {:?}", buf, size); - println!("fds {:?}", fds); }, Err(e) => { println!("error reading: {:?}", e); } } + + + // // println!("parent {:?} {:?}", pid, result); + // match waitpid(pid) { + // Ok(status) => { + // println!("exited {:?}", WEXITSTATUS(status)); + // }, + // Err(e) => { + // println!("waitpid failed {:?}", 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(()) }