1use std::error::Error;
2use std::path::PathBuf;
3
4use clap::Parser;
5
6#[derive(Parser, Debug)]
9pub struct Exec {
10 #[clap(long)]
12 pub console_socket: Option<PathBuf>,
13 #[clap(long)]
14 pub cwd: Option<PathBuf>,
16 #[clap(short, long, value_parser = parse_env::<String, String>, number_of_values = 1)]
18 pub env: Vec<(String, String)>,
19 #[clap(short, long)]
20 pub tty: bool,
21 #[clap(short, long, value_parser = parse_user::<u32, u32>)]
23 pub user: Option<(u32, Option<u32>)>,
24 #[clap(long, short = 'g', number_of_values = 1)]
26 pub additional_gids: Vec<u32>,
27 #[clap(short, long)]
29 pub process: Option<PathBuf>,
30 #[clap(short, long)]
32 pub detach: bool,
33 #[clap(long)]
34 pub pid_file: Option<PathBuf>,
36 #[clap(long)]
38 pub process_label: Option<String>,
39 #[clap(long)]
41 pub apparmor: Option<String>,
42 #[clap(long)]
44 pub no_new_privs: bool,
45 #[clap(long, number_of_values = 1)]
47 pub cap: Vec<String>,
48 #[clap(long, default_value = "0")]
50 pub preserve_fds: i32,
51 #[clap(long)]
53 pub ignore_paused: bool,
54 #[clap(long)]
56 pub cgroup: Option<String>,
57
58 #[clap(value_parser = clap::builder::NonEmptyStringValueParser::new(), required = true)]
60 pub container_id: String,
61
62 #[clap(required = false, trailing_var_arg = true)]
64 pub command: Vec<String>,
65}
66
67fn parse_env<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
68where
69 T: std::str::FromStr,
70 T::Err: Error + Send + Sync + 'static,
71 U: std::str::FromStr,
72 U::Err: Error + Send + Sync + 'static,
73{
74 let pos = s
75 .find('=')
76 .ok_or_else(|| format!("invalid VAR=value: no `=` found in `{s}`"))?;
77 Ok((s[..pos].parse()?, s[pos + 1..].parse()?))
78}
79
80fn parse_user<T, U>(s: &str) -> Result<(T, Option<U>), Box<dyn Error + Send + Sync + 'static>>
81where
82 T: std::str::FromStr,
83 T::Err: Error + Send + Sync + 'static,
84 U: std::str::FromStr,
85 U::Err: Error + Send + Sync + 'static,
86{
87 if let Some(pos) = s.find(':') {
88 Ok((s[..pos].parse()?, Some(s[pos + 1..].parse()?)))
89 } else {
90 Ok((s.parse()?, None))
91 }
92}