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}