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
78
79
80
81
82
83
84
85
86
87
88
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())
}
|