summaryrefslogtreecommitdiffhomepage
path: root/mullvad_cli/src
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-07-06 15:55:53 +0200
committerLinus Färnstrand <linus@mullvad.net>2017-07-06 22:37:01 +0200
commit239e101a91d67ee83d8f5e1c55cea60a095bbbaa (patch)
treeb65156026e4089c37c1d0ba1bf05b7f956d6a9e7 /mullvad_cli/src
parent84ab812dfbbd6dae47eacc16d950d8856b1916be (diff)
downloadmullvadvpn-239e101a91d67ee83d8f5e1c55cea60a095bbbaa.tar.xz
mullvadvpn-239e101a91d67ee83d8f5e1c55cea60a095bbbaa.zip
Renamed talpid_cli to mullvad_cli
Diffstat (limited to 'mullvad_cli/src')
-rw-r--r--mullvad_cli/src/cli.rs24
-rw-r--r--mullvad_cli/src/main.rs75
2 files changed, 99 insertions, 0 deletions
diff --git a/mullvad_cli/src/cli.rs b/mullvad_cli/src/cli.rs
new file mode 100644
index 0000000000..c21e7f1562
--- /dev/null
+++ b/mullvad_cli/src/cli.rs
@@ -0,0 +1,24 @@
+use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
+
+pub fn get_matches() -> ArgMatches<'static> {
+ let app = create_app();
+ app.clone().get_matches()
+}
+
+fn create_app() -> App<'static, 'static> {
+ App::new(crate_name!())
+ .version(crate_version!())
+ .author(crate_authors!())
+ .about(crate_description!())
+ .setting(AppSettings::SubcommandRequired)
+ .subcommand(SubCommand::with_name("account")
+ .about("Control and display information about the configured Mullvad account")
+ .setting(AppSettings::SubcommandRequired)
+ .subcommand(SubCommand::with_name("set")
+ .about("Change the Mullvad account")
+ .arg(Arg::with_name("token")
+ .help("The Mullvad account token to configure the daemon with")
+ .required(true)))
+ .subcommand(SubCommand::with_name("get")
+ .about("Display information about the currently configured account")))
+}
diff --git a/mullvad_cli/src/main.rs b/mullvad_cli/src/main.rs
new file mode 100644
index 0000000000..0d87173418
--- /dev/null
+++ b/mullvad_cli/src/main.rs
@@ -0,0 +1,75 @@
+// `error_chain!` can recurse deeply
+#![recursion_limit = "1024"]
+
+extern crate talpid_ipc;
+#[macro_use]
+extern crate clap;
+#[macro_use]
+extern crate error_chain;
+#[macro_use]
+extern crate log;
+extern crate env_logger;
+extern crate serde;
+extern crate serde_json;
+
+use std::fs::File;
+use std::io::Read;
+
+mod cli;
+
+
+error_chain!{}
+
+quick_main!(run);
+
+fn run() -> Result<()> {
+ env_logger::init().chain_err(|| "Failed to bootstrap logging system")?;
+
+ let matches = cli::get_matches();
+ if let Some(matches) = matches.subcommand_matches("account") {
+ cmd_account(matches)
+ } else {
+ unreachable!("No subcommand matches.")
+ }
+}
+
+fn cmd_account(matches: &clap::ArgMatches) -> Result<()> {
+ if let Some(matches) = matches.subcommand_matches("set") {
+ let token = matches.value_of("token").unwrap();
+ call_rpc("set_account", &[token]).map(
+ |_| {
+ println!("Mullvad account {} set", token);
+ },
+ )
+ } else if let Some(_matches) = matches.subcommand_matches("get") {
+ match call_rpc("get_account", &[] as &[u8; 0])? {
+ serde_json::Value::String(token) => println!("Mullvad account: {:?}", token),
+ serde_json::Value::Null => println!("No account configured"),
+ _ => bail!("Unable to fetch account token"),
+ }
+ Ok(())
+ } else {
+ unreachable!("No account command given");
+ }
+}
+
+fn call_rpc<T>(method: &str, args: &T) -> Result<serde_json::Value>
+ where T: serde::Serialize
+{
+ let address = read_rpc_address()?;
+ info!("Using RPC address {}", address);
+ let mut rpc_client = talpid_ipc::WsIpcClient::new(address)
+ .chain_err(|| "Unable to create RPC client")?;
+ rpc_client.call(method, args).chain_err(|| "Unable to call RPC method")
+}
+
+fn read_rpc_address() -> Result<String> {
+ for path in &["./.mullvad_rpc_address", "../.mullvad_rpc_address"] {
+ debug!("Trying to read RPC address at {}", path);
+ let mut address = String::new();
+ if let Ok(_) = File::open(path).and_then(|mut file| file.read_to_string(&mut address)) {
+ return Ok(address);
+ }
+ }
+ bail!("Unable to read RPC address");
+}