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
|
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(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),
_ => todo!(),
}?;
stdout().write(&res).map(|_| ()).map_err(|e| e.into())
}
|