1use std::{ffi::OsString, path::PathBuf};
2
3use clap::{ArgAction, Args, Parser, Subcommand};
4
5const TARGET_HELP: &str = "Target in the form user@ENDPOINT_ID";
6
7#[derive(Parser, Debug)]
8#[command(name = "iroh-ssh", about = "ssh without ip")]
9pub struct Cli {
10 #[command(subcommand)]
11 pub cmd: Option<Cmd>,
12
13 #[arg(help = TARGET_HELP)]
14 pub target: Option<String>,
15
16 #[command(flatten)]
17 pub ssh: SshOpts,
18
19 #[arg(trailing_var_arg = true)]
20 pub remote_cmd: Option<Vec<OsString>>,
21}
22
23#[derive(Subcommand,Debug)]
24pub enum Cmd {
25 Connect(ConnectArgs),
26 #[command(hide = true)]
27 Exec(ExecArgs),
28 Server(ServerArgs),
29 Service {
30 #[command(subcommand)]
31 op: ServiceCmd,
32 },
33 Info,
34 #[command(hide = true)]
35 Proxy(ProxyArgs),
36 #[command(hide = true)]
37 RunService(ServiceArgs),
38 Version,
39}
40
41#[derive(Args, Clone, Debug)]
42pub struct ProxyArgs {
43 #[arg(help = "Proxy Endpoint ID")]
44 pub endpoint_id: String,
45}
46
47#[derive(Args, Clone, Debug)]
48pub struct ConnectArgs {
49 #[arg(help = TARGET_HELP)]
50 pub target: String,
51
52 #[command(flatten)]
53 pub ssh: SshOpts,
54
55 #[arg(trailing_var_arg = true)]
56 pub remote_cmd: Vec<OsString>,
57}
58
59#[derive(Args, Clone, Debug)]
60pub struct ExecArgs {
61 #[arg(help = TARGET_HELP)]
62 pub target: String,
63
64 #[command(flatten)]
65 pub ssh: SshOpts,
66
67 #[arg(trailing_var_arg = true, required = true)]
68 pub remote_cmd: Vec<OsString>,
69}
70
71#[derive(Args, Clone, Default, Debug)]
72pub struct SshOpts {
73 #[arg(
74 short = 'i',
75 long,
76 value_name = "PATH",
77 help = "Identity file for publickey auth"
78 )]
79 pub identity_file: Option<PathBuf>,
80
81 #[arg(short = 'L', value_name = "LPORT:HOST:RPORT",
82 help = "Local forward [bind_addr:]lport:host:rport (host can't be endpoint_id yet)", action = ArgAction::Append)]
83 pub local_forward: Vec<String>,
84
85 #[arg(short = 'R', value_name = "RPORT:HOST:LPORT",
86 help = "Remote forward [bind_addr:]rport:host:lport (host can't be endpoint_id yet)", action = ArgAction::Append)]
87 pub remote_forward: Vec<String>,
88
89 #[arg(
90 short = 'p',
91 long,
92 value_name = "PORT",
93 help = "Remote sshd port (default 22)"
94 )]
95 pub port: Option<u16>,
96
97 #[arg(short = 'o', value_name = "KEY=VALUE",
98 help = "Pass an ssh option (repeatable)", action = ArgAction::Append)]
99 pub options: Vec<String>,
100
101 #[arg(short = 'A', help = "Enable agent forwarding", action = ArgAction::SetTrue)]
102 pub agent: bool,
103
104 #[arg(short = 'a', help = "Disable agent forwarding", action = ArgAction::SetTrue)]
105 pub no_agent: bool,
106
107 #[arg(short = 'X', help = "Enable X11 forwarding", action = ArgAction::SetTrue)]
108 pub x11: bool,
109
110 #[arg(short = 'Y', help = "Enable trusted X11 forwarding", action = ArgAction::SetTrue)]
111 pub x11_trusted: bool,
112
113 #[arg(short = 'N', help = "Do not execute remote command", action = ArgAction::SetTrue)]
114 pub no_cmd: bool,
115
116 #[arg(short = 't', help = "Force pseudo-terminal", action = ArgAction::SetTrue)]
117 pub force_tty: bool,
118
119 #[arg(short = 'T', help = "Disable pseudo-terminal", action = ArgAction::SetTrue)]
120 pub no_tty: bool,
121
122 #[arg(short = 'v', help = "Increase verbosity",
123 action = ArgAction::Count)]
124 pub verbose: u8,
125
126 #[arg(short = 'q', help = "Quiet mode", action = ArgAction::SetTrue)]
127 pub quiet: bool,
128}
129
130#[derive(Args, Clone, Debug)]
131pub struct ServerArgs {
132 #[arg(long, default_value = "22")]
133 pub ssh_port: u16,
134
135 #[arg(short, long, default_value_t = false)]
136 pub persist: bool,
137}
138
139#[derive(Subcommand, Clone, Debug)]
140pub enum ServiceCmd {
141 Install {
142 #[arg(long, default_value = "22")]
143 ssh_port: u16,
144 },
145 Uninstall,
146}
147
148#[derive(Args, Clone, Debug)]
149pub struct ServiceArgs {
150 #[arg(long, default_value = "22")]
151 pub ssh_port: u16,
152}