diff --git a/logd/src/main.rs b/logd/src/main.rs index 42604cda11..5b6e23243c 100644 --- a/logd/src/main.rs +++ b/logd/src/main.rs @@ -19,8 +19,6 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let socket = Socket::create("log").expect("logd: failed to create log scheme"); - libredox::call::setrens(0, 0).expect("logd: failed to enter null namespace"); - eprintln!("logd: ready for logging on log:"); daemon.ready().expect("logd: failed to notify parent"); diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs index 802f02ec94..e10e77c1ad 100644 --- a/logd/src/scheme.rs +++ b/logd/src/scheme.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; -use std::fs::File; +use std::fs::{File, OpenOptions}; use std::io::Write; use std::mem; +use std::path::PathBuf; use std::sync::mpsc::{self, Sender}; use redox_scheme::scheme::SchemeSync; @@ -9,26 +10,46 @@ use redox_scheme::{CallerCtx, OpenResult}; use syscall::error::*; use syscall::schemev2::NewFdFlags; -pub struct LogHandle { - context: Box, - bufs: BTreeMap>, +pub enum LogHandle { + Log { + context: Box, + bufs: BTreeMap>, + }, + AddSink, } pub struct LogScheme { next_id: usize, - output_tx: Sender>, + output_tx: Sender, handles: BTreeMap, } +enum OutputCmd { + Log(Vec), + AddSink(PathBuf), +} + impl LogScheme { pub fn new(mut files: Vec) -> Self { - let (output_tx, output_rx) = mpsc::channel::>(); + let (output_tx, output_rx) = mpsc::channel::(); std::thread::spawn(move || { - for line in output_rx { - for file in &mut files { - let _ = file.write(&line); - let _ = file.flush(); + for cmd in output_rx { + match cmd { + OutputCmd::Log(line) => { + for file in &mut files { + let _ = file.write(&line); + let _ = file.flush(); + } + } + OutputCmd::AddSink(sink_path) => { + match OpenOptions::new().write(true).open(&sink_path) { + Ok(file) => files.push(file), + Err(err) => { + eprintln!("logd: failed to open {:?}: {:?}", sink_path, err) + } + } + } } } }); @@ -46,13 +67,17 @@ impl SchemeSync for LogScheme { let id = self.next_id; self.next_id += 1; - self.handles.insert( - id, - LogHandle { - context: path.to_string().into_boxed_str(), - bufs: BTreeMap::new(), - }, - ); + if path == "add_sink" { + self.handles.insert(id, LogHandle::AddSink); + } else { + self.handles.insert( + id, + LogHandle::Log { + context: path.to_string().into_boxed_str(), + bufs: BTreeMap::new(), + }, + ); + } Ok(OpenResult::ThisScheme { number: id, @@ -83,23 +108,38 @@ impl SchemeSync for LogScheme { _flags: u32, ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let (context, bufs) = match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + LogHandle::Log { context, bufs } => (context, bufs), + LogHandle::AddSink => { + // FIXME maybe check if root - let handle_buf = handle.bufs.entry(ctx.pid).or_insert_with(|| Vec::new()); + let sink_path = PathBuf::from( + String::from_utf8(buf.to_owned()).map_err(|_| Error::new(EINVAL))?, + ); + + self.output_tx.send(OutputCmd::AddSink(sink_path)).unwrap(); + + return Ok(buf.len()); + } + }; + + let handle_buf = bufs.entry(ctx.pid).or_insert_with(|| Vec::new()); let mut i = 0; while i < buf.len() { let b = buf[i]; - if handle_buf.is_empty() && !handle.context.is_empty() { - handle_buf.extend_from_slice(handle.context.as_bytes()); + if handle_buf.is_empty() && !context.is_empty() { + handle_buf.extend_from_slice(context.as_bytes()); handle_buf.extend_from_slice(b": "); } handle_buf.push(b); if b == b'\n' { - self.output_tx.send(mem::take(handle_buf)).unwrap(); + self.output_tx + .send(OutputCmd::Log(mem::take(handle_buf))) + .unwrap(); } i += 1; @@ -117,7 +157,7 @@ impl SchemeSync for LogScheme { fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - let scheme_path = b"log:"; + let scheme_path = b"/scheme/log/"; let mut i = 0; while i < buf.len() && i < scheme_path.len() { @@ -125,10 +165,13 @@ impl SchemeSync for LogScheme { i += 1; } + let path_bytes = match handle { + LogHandle::Log { context, .. } => context.as_bytes(), + LogHandle::AddSink => b"add_sink", + }; let mut j = 0; - let context_bytes = handle.context.as_bytes(); - while i < buf.len() && j < context_bytes.len() { - buf[i] = context_bytes[j]; + while i < buf.len() && j < path_bytes.len() { + buf[i] = path_bytes[j]; i += 1; j += 1; }