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