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:
| M | src/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(())
}