diff --git a/Cargo.lock b/Cargo.lock index a7227be..7980158 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -533,6 +533,7 @@ dependencies = [ "bytes", "fnv", "lazy_static", + "memchr", "mio", "num_cpus", "pin-project-lite", diff --git a/Cargo.toml b/Cargo.toml index 0968b90..4a87add 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ default = ["threaded"] threaded = ["tokio/rt-threaded"] [dependencies] -tokio = {version = "0.2", features=["time", "macros", "io-driver", "sync", "rt-core"]} +tokio = {version = "0.2", features=["time", "macros", "io-driver", "sync", "rt-core", "fs"]} notify = "4.0" futures= "0.3" sexp = "1.1" diff --git a/src/config/error.rs b/src/config/error.rs index e7f7f94..12e0140 100644 --- a/src/config/error.rs +++ b/src/config/error.rs @@ -2,13 +2,16 @@ use super::*; use std::{ io, + path::PathBuf, }; #[derive(Debug)] pub enum Error { IO(io::Error), Syntax(sexp::Error), - + NotFound(PathBuf), + InvalidUtf8, + InvalidSexp, Unknown, } @@ -30,7 +33,9 @@ impl std::fmt::Display for Error match self { Self::IO(io) => write!(f, "i/o error: {}", io), Self::Syntax(sy) => write!(f, "s-expression syntax error: {}", sy), - + Self::NotFound(path) => write!(f, "File not found: {:?}", path), + Self::InvalidUtf8 => write!(f, "Invalid UTF8 decoded string or some such"), + Self::InvalidSexp => write!(f, "Invalid s-expression"), _ => write!(f, "unknown error") } } @@ -40,7 +45,7 @@ impl From for Error { fn from(from: io::Error) -> Self { - Self::IO(from) + Self::IO(from) } } @@ -48,7 +53,7 @@ impl From for Error { fn from(from: sexp::Error) -> Self { - Self::Syntax(from) + Self::Syntax(from) } } @@ -56,6 +61,14 @@ impl From> for Error { fn from(from: Box) -> Self { - Self::Syntax(*from) + Self::Syntax(*from) + } +} + +impl From for Error +{ + fn from(from: std::str::Utf8Error) -> Self + { + Self::InvalidUtf8 } } diff --git a/src/config/global.rs b/src/config/global.rs index 1b53604..9a6eb23 100644 --- a/src/config/global.rs +++ b/src/config/global.rs @@ -33,6 +33,8 @@ pub struct Config pub job_dirs: Vec, /// The rules for users pub user_rules: Vec, + /// Enable debug + pub debug: bool, } impl Default for Config @@ -40,6 +42,6 @@ impl Default for Config #[inline] fn default() -> Self { - Self{job_dirs: Vec::new(), user_rules: Vec::new()} + Self{job_dirs: Vec::new(), user_rules: Vec::new(), debug: false} } } diff --git a/src/config/job.rs b/src/config/job.rs index c7bcc65..10e1f23 100644 --- a/src/config/job.rs +++ b/src/config/job.rs @@ -40,5 +40,4 @@ pub struct Job what: Command, } - const DEFAULT_JOB_DIR: &str = "/etc/rori.kron"; diff --git a/src/config/mod.rs b/src/config/mod.rs index 4891478..d191de3 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -3,8 +3,8 @@ use std::{ str, fmt, path::{ - PathBuf, - Path, + PathBuf, + Path, }, }; @@ -20,9 +20,9 @@ pub use global::*; /// Parse a single config file #[inline] -pub fn parse_global_single(path: impl AsRef) -> Result +pub async fn parse_global_single(path: impl AsRef) -> Result { let mut cfg = Config::default(); - parse::global(&mut cfg, path)?; + parse::global(&mut cfg, path).await?; Ok(cfg) } diff --git a/src/config/parse.rs b/src/config/parse.rs index 74b4de3..a5efb63 100644 --- a/src/config/parse.rs +++ b/src/config/parse.rs @@ -1,10 +1,74 @@ //! Parses the config files use super::*; +use tokio::fs::File; +use tokio::prelude::*; +use sexp::{ + parse, + Sexp, + Atom, +}; + +fn get_atom_string<'a, T>(maybe_atom: T) -> Result<&'a String, Error> +where T: AsRef + 'a +{ + match maybe_atom.as_ref() { + Sexp::Atom(Atom::S(string)) => Ok(string), + _ => Err(Error::InvalidSexp), + } +} + +fn new_job(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> { + to.job_dirs.push(PathBuf::from(get_atom_string(&cdr[0])?)); + + Ok(()) +} + /// Parse a single config file -pub fn global(to: &mut Config, path: impl AsRef) -> Result<(), error::Error> +pub async fn global(to: &mut Config, path: impl AsRef) -> Result<(), error::Error> { let path = path.as_ref(); - todo!(); + if path.exists() { + let mut file = File::open(path).await?; + let mut contents = vec![]; + file.read_to_end(&mut contents).await?; + + let parsed = sexp::parse(std::str::from_utf8(&contents[..])?)?; + + if let Sexp::List(sexp) = parsed { + for sexp in sexp.into_iter() { + if let Sexp::List(sexp) = sexp { + + let car = &sexp[0]; + let cdr = &sexp[1..]; + match car { + Sexp::List(_) => return Err(Error::InvalidSexp), + Sexp::Atom(car) => { + if let Atom::S(car) = car { + match car.to_lowercase().trim() { + "jobs-dir" => new_job(to, cdr), + "debug" => new_job(to, cdr), + "allow" => new_job(to, cdr), + "deny" => new_job(to, cdr), + _ => return Err(Error::Unknown), + }?; + } else { + return Err(Error::InvalidSexp); + } + } + } + } + else { + return Err(Error::InvalidSexp); + } + } + } else { + return Err(Error::InvalidSexp); + } + + Ok(()) + } else { + return Err(Error::NotFound(path.to_owned())); + } } diff --git a/src/context.rs b/src/context.rs index e1b0fd7..17a0980 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,8 +4,8 @@ use super::*; use std::sync::{Arc, Weak}; use tokio::{ sync::{ - RwLock, - mpsc, + RwLock, + mpsc, }, task, }; diff --git a/src/log.rs b/src/log.rs index bad53ae..bcb7dce 100644 --- a/src/log.rs +++ b/src/log.rs @@ -2,12 +2,12 @@ use std::{ fmt::{ - self, - Display, + self, + Display, }, io::{ - self, - Write, + self, + Write, }, }; use once_cell::sync::OnceCell; diff --git a/src/main.rs b/src/main.rs index 360edd5..9a53d13 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,7 @@ async fn do_thing_every() -> Result<(mpsc::Sender<()>, task::JoinHandle<()>), Bo let (tx, mut rx) = mpsc::channel(16); let handle = tokio::spawn(async move { - println!("starting?"); + println!("starting?"); loop { let mut tick = interval.tick(); @@ -59,15 +59,17 @@ async fn do_thing_every() -> Result<(mpsc::Sender<()>, task::JoinHandle<()>), Bo async fn main() -> Result<(), Box> { log::init(Default::default()); - + debug!("Initialised"); + + println!("{:?}", config::parse_global_single("/home/manx/flon.txt").await.expect("Waaaaaah")); - let (mut tx, h) = do_thing_every().await?; + //let (mut tx, h) = do_thing_every().await?; - loop { - time::delay_for(Duration::from_secs(6)).await; - tx.send(()).await?; - } - h.await?; + // loop { + // time::delay_for(Duration::from_secs(6)).await; + // tx.send(()).await?; + // } + // h.await?; Ok(()) }