From 161b052713f5cee08f20ce6ade0881e274c47fdd Mon Sep 17 00:00:00 2001 From: "Jannis M. Hoffmann" Date: Tue, 15 Aug 2023 15:13:16 +0200 Subject: initial commit --- src/main.rs | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main.rs (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8a8b84e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,89 @@ +use std::ffi::{CStr, CString}; +use std::io::stdout; + +use clap::Parser as _; +use maildir::Maildir; + +mod arguments; +mod cmd; +mod error; +mod rfc822; + +use arguments::{Arguments, Mode}; +use cmd::{ + count, folders, list, move_mail, open_submaildir, raw, read, search, serialize_to, Return, +}; +use error::{Error, Result}; + +fn switch_to_user(sys_user: &str) -> Result<()> { + unsafe { + *libc::__errno_location() = 0; + } + let c_sys_user = + CString::new(sys_user).map_err(|e| Error::Setuid(format!("nul char in user, {}", e)))?; + let user_info: *const libc::passwd = unsafe { libc::getpwnam(c_sys_user.as_ptr()) }; + let err = unsafe { *libc::__errno_location() }; + if err != 0 { + return Err(Error::Setuid(format!( + "error calling getpwnam {:?}", + unsafe { libc::strerror(err) } + ))); + }; + if user_info.is_null() { + return Err(Error::Setuid(format!("user {:?} does not exist", sys_user))); + }; + let rc = unsafe { libc::setuid((*user_info).pw_uid) }; + if rc != 0 { + let err = unsafe { *libc::__errno_location() }; + return Err(Error::Setuid(format!( + "error calling setuid {:?}", + unsafe { CStr::from_ptr(libc::strerror(err)) } + ))); + } + Ok(()) +} + +fn main() -> std::io::Result<()> { + simplelog::TermLogger::init( + simplelog::LevelFilter::Info, + simplelog::Config::default(), + simplelog::TerminalMode::Stderr, + simplelog::ColorChoice::Never, + ) + .unwrap(); + + let args = Arguments::parse(); + + std::env::remove_var("PATH"); + if let Err(e) = switch_to_user(&args.sys_user) { + serialize_to(Err(e), &stdout())? + } + + let path = args.maildir_path.join(args.mail_user); + + let res = match args.mode { + Mode::Read { subfolder, mid } => { + read(&open_submaildir(path, &subfolder), &mid).map(Return::Read) + } + Mode::Raw { + subfolder, + mid, + mime_path, + } => raw(&open_submaildir(path, &subfolder), &mid, &mime_path) + .map(|(h, t)| Return::Raw(h, t)), + Mode::List { + subfolder, + start, + end, + ref sortby, + } => list(&open_submaildir(path, &subfolder), start, end, sortby).map(Return::List), + Mode::Folders => folders(&Maildir::from(path)).map(Return::Folders), + Mode::Count { subfolder } => count(&open_submaildir(path, &subfolder)).map(Return::Count), + Mode::Search { pattern, subfolder } => { + search(&open_submaildir(path, &subfolder), &pattern).map(Return::Search) + } + Mode::Move { mid, from, to } => move_mail(path, &mid, &from, &to).map(|()| Return::Move), + }; + + serialize_to(res, &stdout()) +} -- cgit v1.2.3