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