]>
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 | ||
86ee36e8 | 35 | fn usage(status: i32, program: &OsStr, out: &mut dyn Write) -> ! { |
d54e9e5a WB |
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", | |
86ee36e8 WB |
45 | ) |
46 | .as_bytes(), | |
d54e9e5a WB |
47 | ); |
48 | std::process::exit(status); | |
49 | } | |
50 | ||
9aa2a15a | 51 | fn main() { |
d54e9e5a WB |
52 | let mut args = std::env::args_os(); |
53 | let program = args.next().unwrap(); // program name always exists | |
54 | ||
55 | let mut use_sd_notify = false; | |
56 | let mut path = None; | |
57 | ||
750b5cb3 WB |
58 | let mut nonopt_arg = |arg: OsString| { |
59 | if path.is_some() { | |
60 | let _ = stderr().write_all(b"unexpected extra parameter: "); | |
61 | let _ = stderr().write_all(arg.as_bytes()); | |
62 | let _ = stderr().write_all(b"\n"); | |
63 | usage(1, &program, &mut stderr()); | |
64 | } | |
65 | ||
66 | path = Some(arg); | |
67 | }; | |
68 | ||
d54e9e5a WB |
69 | for arg in &mut args { |
70 | if arg == "-h" || arg == "--help" { | |
71 | usage(0, &program, &mut stdout()); | |
72 | } | |
73 | ||
74 | if arg == "--" { | |
75 | break; | |
76 | } else if arg == "--system" { | |
77 | use_sd_notify = true; | |
78 | } else { | |
750b5cb3 | 79 | if arg.as_bytes().starts_with(b"-") { |
d54e9e5a WB |
80 | let _ = stderr().write_all(b"unexpected option: "); |
81 | let _ = stderr().write_all(arg.as_bytes()); | |
750b5cb3 | 82 | let _ = stderr().write_all(b"\n"); |
d54e9e5a WB |
83 | usage(1, &program, &mut stderr()); |
84 | } | |
85 | ||
750b5cb3 | 86 | nonopt_arg(arg); |
d54e9e5a WB |
87 | } |
88 | } | |
89 | ||
750b5cb3 WB |
90 | for arg in &mut args { |
91 | nonopt_arg(arg); | |
92 | } | |
93 | drop(nonopt_arg); | |
94 | ||
d54e9e5a WB |
95 | let path = match path { |
96 | Some(path) => path, | |
97 | None => { | |
98 | eprintln!("missing path"); | |
99 | usage(1, &program, &mut stderr()); | |
100 | } | |
101 | }; | |
102 | ||
5bd0c562 | 103 | let mut rt = tokio::runtime::Runtime::new().expect("failed to spawn tokio runtime"); |
e420f6f9 | 104 | |
d54e9e5a | 105 | if let Err(err) = rt.block_on(do_main(use_sd_notify, path)) { |
9cffeac4 WB |
106 | eprintln!("error: {}", err); |
107 | std::process::exit(1); | |
108 | } | |
109 | } | |
110 | ||
d54e9e5a | 111 | async fn do_main(use_sd_notify: bool, socket_path: OsString) -> Result<(), Error> { |
571dbe03 | 112 | match std::fs::remove_file(&socket_path) { |
9cffeac4 | 113 | Ok(_) => (), |
8dd26985 | 114 | Err(ref e) if e.kind() == StdIo::ErrorKind::NotFound => (), // Ok |
9cffeac4 WB |
115 | Err(e) => bail!("failed to remove previous socket: {}", e), |
116 | } | |
117 | ||
571dbe03 WB |
118 | let address = |
119 | SockAddr::new_unix(socket_path.as_os_str()).expect("cannot create struct sockaddr_un?"); | |
9cffeac4 | 120 | |
8dd26985 | 121 | let mut listener = SeqPacketListener::bind(&address) |
9cffeac4 | 122 | .map_err(|e| format_err!("failed to create listening socket: {}", e))?; |
d54e9e5a WB |
123 | |
124 | if use_sd_notify { | |
125 | notify_systemd()?; | |
126 | } | |
127 | ||
9cffeac4 WB |
128 | loop { |
129 | let client = listener.accept().await?; | |
e420f6f9 | 130 | let client = client::Client::new(client); |
9aa2a15a | 131 | spawn(client.main()); |
9cffeac4 WB |
132 | } |
133 | } | |
d54e9e5a WB |
134 | |
135 | #[link(name = "systemd")] | |
136 | extern "C" { | |
137 | fn sd_notify(unset_environment: libc::c_int, state: *const libc::c_char) -> libc::c_int; | |
138 | } | |
139 | ||
140 | fn notify_systemd() -> StdIo::Result<()> { | |
141 | let err = unsafe { sd_notify(0, c_str!("READY=1\n").as_ptr()) }; | |
7bb69bd3 | 142 | if err >= 0 { |
d54e9e5a WB |
143 | Ok(()) |
144 | } else { | |
145 | Err(StdIo::Error::from_raw_os_error(-err)) | |
146 | } | |
147 | } |