diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 9f507221..2d092b0b 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -10,15 +10,35 @@ use libredox::Fd; use redox_scheme::Socket; use redox_scheme::scheme::{SchemeAsync, SchemeSync}; -unsafe fn get_fd(var: &str) -> RawFd { - let fd: RawFd = std::env::var(var).unwrap().parse().unwrap(); +unsafe fn get_fd(var: &str) -> Option { + let value = match std::env::var(var) { + Ok(value) => value, + Err(_) => { + let exe = std::env::args() + .next() + .unwrap_or_else(|| "daemon".to_string()); + eprintln!("daemon: {var} not set for {exe}; readiness notification disabled"); + return None; + } + }; + let fd: RawFd = match value.parse() { + Ok(fd) => fd, + Err(err) => { + let exe = std::env::args() + .next() + .unwrap_or_else(|| "daemon".to_string()); + eprintln!("daemon: invalid {var} value {value:?} for {exe}: {err}; readiness notification disabled"); + return None; + } + }; if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) } == -1 { - panic!( + eprintln!( "daemon: failed to set CLOEXEC flag for {var} fd: {}", io::Error::last_os_error() ); + return None; } - fd + Some(fd) } unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) { @@ -38,20 +58,22 @@ unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) { /// A long running background process that handles requests. #[must_use = "Daemon::ready must be called"] pub struct Daemon { - write_pipe: PipeWriter, + write_pipe: Option, } impl Daemon { /// Create a new daemon. pub fn new(f: impl FnOnce(Daemon) -> !) -> ! { - let write_pipe = unsafe { io::PipeWriter::from_raw_fd(get_fd("INIT_NOTIFY")) }; + let write_pipe = get_fd("INIT_NOTIFY").map(|fd| unsafe { io::PipeWriter::from_raw_fd(fd) }); f(Daemon { write_pipe }) } /// Notify the process that the daemon is ready to accept requests. pub fn ready(mut self) { - self.write_pipe.write_all(&[0]).unwrap(); + if let Some(write_pipe) = self.write_pipe.as_mut() { + write_pipe.write_all(&[0]).unwrap(); + } } /// Executes `Command` as a child process. @@ -83,21 +105,25 @@ impl Daemon { /// A long running background process that handles requests using schemes. #[must_use = "SchemeDaemon::ready must be called"] pub struct SchemeDaemon { - write_pipe: PipeWriter, + write_pipe: Option, } impl SchemeDaemon { /// Create a new daemon for use with schemes. pub fn new(f: impl FnOnce(SchemeDaemon) -> !) -> ! { - let write_pipe = unsafe { io::PipeWriter::from_raw_fd(get_fd("INIT_NOTIFY")) }; + let write_pipe = get_fd("INIT_NOTIFY").map(|fd| unsafe { io::PipeWriter::from_raw_fd(fd) }); f(SchemeDaemon { write_pipe }) } /// Notify the process that the scheme daemon is ready to accept requests. pub fn ready_with_fd(self, cap_fd: Fd) -> syscall::Result<()> { + let write_pipe = match self.write_pipe { + Some(pipe) => pipe, + None => return Ok(()), + }; syscall::call_wo( - self.write_pipe.as_raw_fd() as usize, + write_pipe.as_raw_fd() as usize, &cap_fd.into_raw().to_ne_bytes(), syscall::CallFlags::FD, &[],