]> git.proxmox.com Git - pve-lxc-syscalld.git/blame - src/main.rs
drop io_err_other in favor of std::io::Error::other
[pve-lxc-syscalld.git] / src / main.rs
CommitLineData
4032c669
WB
1#![deny(unsafe_op_in_unsafe_fn)]
2
d54e9e5a 3use std::ffi::{OsStr, OsString};
9aa2a15a 4use std::future::Future;
8dd26985 5use std::io as StdIo;
d54e9e5a
WB
6use std::io::{stderr, stdout, Write};
7use std::os::unix::ffi::OsStrExt;
9cffeac4 8
8150a439 9use anyhow::{bail, format_err, Error};
b8cb8723 10use nix::sys::socket::UnixAddr;
9cffeac4 11
9aa2a15a
WB
12#[macro_use]
13mod macros;
14
42f25756 15pub mod apparmor;
738dbfbe 16pub mod capability;
e420f6f9
WB
17pub mod client;
18pub mod fork;
8dd26985 19pub mod io;
9cffeac4 20pub mod lxcseccomp;
e420f6f9 21pub mod nsfd;
a22aece0 22pub mod poll_fn;
3bbd1db0 23pub mod process;
9cffeac4 24pub mod seccomp;
e420f6f9 25pub mod sys_mknod;
3e69a521 26pub mod sys_quotactl;
c95be5f6 27pub mod syscall;
9cffeac4
WB
28pub mod tools;
29
8dd26985 30use crate::io::seq_packet::SeqPacketListener;
9aa2a15a 31
7d20b692 32#[track_caller]
9aa2a15a 33pub fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
5bd0c562 34 tokio::spawn(fut);
9aa2a15a
WB
35}
36
86ee36e8 37fn usage(status: i32, program: &OsStr, out: &mut dyn Write) -> ! {
d54e9e5a
WB
38 let _ = out.write_all("usage: ".as_bytes());
39 let _ = out.write_all(program.as_bytes());
40 let _ = out.write_all(
41 concat!(
42 "[options] SOCKET_PATH\n",
43 "options:\n",
44 " -h, --help show this help message\n",
45 " --system \
46 run as systemd daemon (use sd_notify() when ready to accept connections)\n",
86ee36e8
WB
47 )
48 .as_bytes(),
d54e9e5a
WB
49 );
50 std::process::exit(status);
51}
52
9aa2a15a 53fn main() {
d54e9e5a
WB
54 let mut args = std::env::args_os();
55 let program = args.next().unwrap(); // program name always exists
56
57 let mut use_sd_notify = false;
58 let mut path = None;
59
750b5cb3
WB
60 let mut nonopt_arg = |arg: OsString| {
61 if path.is_some() {
62 let _ = stderr().write_all(b"unexpected extra parameter: ");
63 let _ = stderr().write_all(arg.as_bytes());
64 let _ = stderr().write_all(b"\n");
65 usage(1, &program, &mut stderr());
66 }
67
68 path = Some(arg);
69 };
70
d54e9e5a
WB
71 for arg in &mut args {
72 if arg == "-h" || arg == "--help" {
73 usage(0, &program, &mut stdout());
74 }
75
76 if arg == "--" {
77 break;
78 } else if arg == "--system" {
79 use_sd_notify = true;
80 } else {
750b5cb3 81 if arg.as_bytes().starts_with(b"-") {
d54e9e5a
WB
82 let _ = stderr().write_all(b"unexpected option: ");
83 let _ = stderr().write_all(arg.as_bytes());
750b5cb3 84 let _ = stderr().write_all(b"\n");
d54e9e5a
WB
85 usage(1, &program, &mut stderr());
86 }
87
750b5cb3 88 nonopt_arg(arg);
d54e9e5a
WB
89 }
90 }
91
750b5cb3
WB
92 for arg in &mut args {
93 nonopt_arg(arg);
94 }
750b5cb3 95
d54e9e5a
WB
96 let path = match path {
97 Some(path) => path,
98 None => {
99 eprintln!("missing path");
100 usage(1, &program, &mut stderr());
101 }
102 };
103
53d40cee
WB
104 let cpus = num_cpus::get();
105
106 let rt = tokio::runtime::Builder::new_multi_thread()
107 .enable_all()
d463e3b4 108 .worker_threads(cpus.clamp(2, 4))
53d40cee
WB
109 .build()
110 .expect("failed to spawn tokio runtime");
e420f6f9 111
d54e9e5a 112 if let Err(err) = rt.block_on(do_main(use_sd_notify, path)) {
d463e3b4 113 eprintln!("error: {err}");
9cffeac4
WB
114 std::process::exit(1);
115 }
116}
117
d54e9e5a 118async fn do_main(use_sd_notify: bool, socket_path: OsString) -> Result<(), Error> {
571dbe03 119 match std::fs::remove_file(&socket_path) {
9cffeac4 120 Ok(_) => (),
8dd26985 121 Err(ref e) if e.kind() == StdIo::ErrorKind::NotFound => (), // Ok
9cffeac4
WB
122 Err(e) => bail!("failed to remove previous socket: {}", e),
123 }
124
571dbe03 125 let address =
b8cb8723 126 UnixAddr::new(socket_path.as_os_str()).expect("cannot create struct sockaddr_un?");
9cffeac4 127
8dd26985 128 let mut listener = SeqPacketListener::bind(&address)
9cffeac4 129 .map_err(|e| format_err!("failed to create listening socket: {}", e))?;
d54e9e5a
WB
130
131 if use_sd_notify {
132 notify_systemd()?;
133 }
134
9cffeac4
WB
135 loop {
136 let client = listener.accept().await?;
e420f6f9 137 let client = client::Client::new(client);
9aa2a15a 138 spawn(client.main());
9cffeac4
WB
139 }
140}
d54e9e5a
WB
141
142#[link(name = "systemd")]
143extern "C" {
144 fn sd_notify(unset_environment: libc::c_int, state: *const libc::c_char) -> libc::c_int;
145}
146
147fn notify_systemd() -> StdIo::Result<()> {
148 let err = unsafe { sd_notify(0, c_str!("READY=1\n").as_ptr()) };
7bb69bd3 149 if err >= 0 {
d54e9e5a
WB
150 Ok(())
151 } else {
152 Err(StdIo::Error::from_raw_os_error(-err))
153 }
154}