summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 5598b3056739a3d0199bd65b9cfbf398c6b828d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::ffi::{CStr, CString};
use std::io::{stdin, stdout, Read, Write};

use clap::Parser as _;

mod arguments;
mod cmd;
mod error;
mod pb3;
mod rfc822;

use arguments::{Arguments, Mode};
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() -> Result<()> {
    simplelog::TermLogger::init(
        simplelog::LevelFilter::Info,
        simplelog::Config::default(),
        simplelog::TerminalMode::Stderr,
        simplelog::ColorChoice::Never,
    )
    .unwrap();

    let args = Arguments::parse();

    switch_to_user(&args.sys_user)?;

    let path = args.maildir_path.join(args.mail_user);

    stdout().write_all(b"OPEN\n")?;
    stdout().flush()?;
    let mut req = Vec::with_capacity(2048);
    stdin().read_to_end(&mut req)?;

    let res = match args.mode {
        Mode::Read => cmd::read(path, &req),
        Mode::Raw => cmd::raw(path, &req),
        Mode::List => cmd::list(path, &req),
        Mode::Folders => cmd::folders(path, &req),
        Mode::Count => cmd::count(path, &req),
        //Mode::Search => cmd::search(&path, &req),
        Mode::Move => cmd::move_mail(path, &req),
        Mode::Remove => cmd::remove(path, &req),
        Mode::AddFolder => cmd::add_folder(path, &req),
        _ => todo!(),
    }?;

    stdout().write_all(&res).map_err(|e| e.into())
}