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