rlib/
cli.rs

1use clap::{App, Arg, SubCommand};
2use std::io::stdin;
3use std::io::stdout;
4use std::io::Write;
5use std::string::String;
6
7pub fn error(msg: &str) {
8    println!("Error: {}", msg);
9}
10
11pub fn yesorno(msg: &str) -> bool {
12    let mut ans = String::new();
13    stdout()
14        .write_all(format!("{} [y/n] ", msg).as_bytes())
15        .expect("Failed writing to stdout");
16    stdout().flush().expect("Failed to flush stdout");
17    stdin()
18        .read_line(&mut ans)
19        .expect("Failed reading from stdin");
20
21    match ans.to_ascii_lowercase().replace("\n", "").as_str() {
22        "y" | "yes" => true,
23        "n" | "no" => false,
24        _ => yesorno("Please eneter y or n"),
25    }
26}
27pub fn password(msg: &str) -> String {
28    rpassword::prompt_password_stdout(msg).unwrap()
29}
30
31pub mod xclip {
32    use std::io::prelude::*;
33    use std::process::Command;
34
35    #[cfg(target_os = "macos")]
36    pub fn to_clipboard(s: &str) {
37        let mut clip = Command::new("pbcopy")
38            .stdin(std::process::Stdio::piped())
39            .spawn()
40            .expect("Failed getting pw");
41
42        clip.stdin
43            .as_mut()
44            .unwrap()
45            .write_all(s.as_bytes())
46            .expect("Failed to open stdin");
47    }
48
49    #[cfg(target_os = "linux")]
50    pub fn to_clipboard(s: &str) {
51        let mut clip = Command::new("xclip")
52            .stdin(std::process::Stdio::piped())
53            .arg("-selection")
54            .arg("clipboard")
55            .spawn()
56            .expect("Failed getting pw");
57
58        clip.stdin
59            .as_mut()
60            .unwrap()
61            .write_all(s.as_bytes())
62            .expect("Failed to open stdin");
63    }
64}
65
66pub fn build() -> clap::App<'static, 'static> {
67    let mut app = App::new("rpw - the rusty password manager")
68        .version("2021")
69        .author("Patrik Lundgren <patrik.lundgren@outlook.com>")
70        .about(
71            "rpw is a small cli-only password manager for your terminal
72            copy pasting needs.",
73        );
74
75    app = app.subcommand(
76        SubCommand::with_name("open")
77            .about("Open a password encrypted vault.")
78            .arg(Arg::with_name("vault").required(true).takes_value(true)),
79    );
80
81    app = app.subcommand(
82        SubCommand::with_name("clear")
83            .about("Clear the clipboard register.")
84            .arg(Arg::with_name("sec").takes_value(true).required(true)),
85    );
86
87    app = app.subcommand(
88        SubCommand::with_name("get")
89            .about("Decrypt the vault and fetch a password to the clipboard.")
90            .arg(Arg::with_name("vault").long("vault").short("v"))
91            .arg(
92                Arg::with_name("password")
93                    .long("password")
94                    .short("p")
95                    .takes_value(true),
96            )
97            .arg(Arg::with_name("alias").required(true).takes_value(true)),
98    );
99
100    app = app.subcommand(
101        SubCommand::with_name("list")
102            .about("List the stored passwords of a vault by alias.")
103            .arg(
104                Arg::with_name("vault")
105                    .long("vault")
106                    .short("v")
107                    .takes_value(true),
108            )
109            .arg(
110                Arg::with_name("password")
111                    .long("password")
112                    .short("p")
113                    .takes_value(true),
114            ),
115    );
116
117    app = app.subcommand(
118        SubCommand::with_name("export")
119            .about("Export the vault to a plain-text json format.")
120            .arg(
121                Arg::with_name("vault")
122                    .long("vault")
123                    .short("v")
124                    .takes_value(true),
125            )
126            .arg(Arg::with_name("file-path").required(true).takes_value(true))
127            .arg(
128                Arg::with_name("password")
129                    .long("password")
130                    .short("p")
131                    .takes_value(true),
132            ),
133    );
134
135    app = app.subcommand(
136        SubCommand::with_name("new")
137            .about("Create a new password encrypted vault.")
138            .arg(
139                Arg::with_name("vault")
140                    .long("vault")
141                    .short("v")
142                    .required(true)
143                    .takes_value(true),
144            )
145            .arg(
146                Arg::with_name("password")
147                    .long("password")
148                    .short("p")
149                    .takes_value(true),
150            )
151            .arg(
152                Arg::with_name("verify")
153                    .long("verify")
154                    .short("v")
155                    .takes_value(true),
156            ),
157    );
158
159    app = app.subcommand(
160        SubCommand::with_name("delete")
161            .about("Delete an existing vault.")
162            .arg(
163                Arg::with_name("vault")
164                    .long("vault")
165                    .short("v")
166                    .required(true)
167                    .takes_value(true),
168            )
169            .arg(
170                Arg::with_name("password")
171                    .long("password")
172                    .short("p")
173                    .takes_value(true),
174            )
175            .arg(
176                Arg::with_name("verify")
177                    .long("verify")
178                    .short("v")
179                    .takes_value(true),
180            ),
181    );
182
183    app = app.subcommand(
184        SubCommand::with_name("add")
185            .about("Add a password to the vault.")
186            .arg(
187                Arg::with_name("vault")
188                    .long("vault")
189                    .short("v")
190                    .takes_value(true),
191            )
192            .arg(Arg::with_name("alias").required(true).takes_value(true))
193            .arg(
194                Arg::with_name("password")
195                    .long("password")
196                    .short("p")
197                    .takes_value(true),
198            )
199            .arg(
200                Arg::with_name("new-password")
201                    .long("new-password")
202                    .short("n")
203                    .takes_value(true),
204            ),
205    );
206
207    app
208}