Merge pull request #134 from dyc3/non-zero-exit-codes
non zero exit codes
This commit is contained in:
commit
eb3c417ff2
2 changed files with 88 additions and 41 deletions
7
src/errors.rs
Normal file
7
src/errors.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub(crate) enum UserError {
|
||||||
|
#[error("User aborted the operation.")]
|
||||||
|
Aborted,
|
||||||
|
}
|
122
src/main.rs
122
src/main.rs
|
@ -24,6 +24,7 @@ extern crate ring;
|
||||||
mod accountmanager;
|
mod accountmanager;
|
||||||
mod demos;
|
mod demos;
|
||||||
mod encryption;
|
mod encryption;
|
||||||
|
mod errors;
|
||||||
mod tui;
|
mod tui;
|
||||||
|
|
||||||
fn cli() -> App<'static, 'static> {
|
fn cli() -> App<'static, 'static> {
|
||||||
|
@ -84,10 +85,15 @@ fn cli() -> App<'static, 'static> {
|
||||||
.about("Interactive interface for trade confirmations")
|
.about("Interactive interface for trade confirmations")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("accept-all")
|
Arg::with_name("accept-all")
|
||||||
.short("a")
|
.short("a")
|
||||||
.long("accept-all")
|
.long("accept-all")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Accept all open trade confirmations. Does not open interactive interface.")
|
.help("Accept all open trade confirmations. Does not open interactive interface.")
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("fail-fast")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("If submitting a confirmation response fails, exit immediately.")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
|
@ -126,6 +132,16 @@ fn cli() -> App<'static, 'static> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
std::process::exit(match run() {
|
||||||
|
Ok(_) => 0,
|
||||||
|
Err(e) => {
|
||||||
|
error!("{:?}", e);
|
||||||
|
255
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run() -> anyhow::Result<()> {
|
||||||
let matches = cli().get_matches();
|
let matches = cli().get_matches();
|
||||||
|
|
||||||
let verbosity = matches.occurrences_of("verbosity") as usize + 2;
|
let verbosity = matches.occurrences_of("verbosity") as usize + 2;
|
||||||
|
@ -140,7 +156,7 @@ fn main() {
|
||||||
if demo_matches.is_present("demo-conf-menu") {
|
if demo_matches.is_present("demo-conf-menu") {
|
||||||
demos::demo_confirmation_menu();
|
demos::demo_confirmation_menu();
|
||||||
}
|
}
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Some(completion_matches) = matches.subcommand_matches("completion") {
|
if let Some(completion_matches) = matches.subcommand_matches("completion") {
|
||||||
cli().gen_completions_to(
|
cli().gen_completions_to(
|
||||||
|
@ -148,7 +164,7 @@ fn main() {
|
||||||
Shell::from_str(completion_matches.value_of("shell").unwrap()).unwrap(),
|
Shell::from_str(completion_matches.value_of("shell").unwrap()).unwrap(),
|
||||||
&mut std::io::stdout(),
|
&mut std::io::stdout(),
|
||||||
);
|
);
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mafiles_dir = if matches.occurrences_of("mafiles-path") > 0 {
|
let mafiles_dir = if matches.occurrences_of("mafiles-path") > 0 {
|
||||||
|
@ -167,24 +183,16 @@ fn main() {
|
||||||
) {
|
) {
|
||||||
'n' => {
|
'n' => {
|
||||||
info!("Aborting!");
|
info!("Aborting!");
|
||||||
return;
|
return Err(errors::UserError::Aborted.into());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
std::fs::create_dir_all(mafiles_dir).expect("failed to create directory");
|
std::fs::create_dir_all(mafiles_dir)?;
|
||||||
|
|
||||||
manifest = accountmanager::Manifest::new(path.as_path());
|
manifest = accountmanager::Manifest::new(path.as_path());
|
||||||
manifest.save(&None).expect("Failed to save manifest");
|
manifest.save(&None)?;
|
||||||
} else {
|
} else {
|
||||||
match accountmanager::Manifest::load(path.as_path()) {
|
manifest = accountmanager::Manifest::load(path.as_path())?;
|
||||||
Ok(m) => {
|
|
||||||
manifest = m;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Could not load manifest: {}", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut passkey: Option<String> = matches.value_of("passkey").map(|s| s.into());
|
let mut passkey: Option<String> = matches.value_of("passkey").map(|s| s.into());
|
||||||
|
@ -203,7 +211,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Could not load accounts: {}", e);
|
error!("Could not load accounts: {}", e);
|
||||||
return;
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +221,7 @@ fn main() {
|
||||||
print!("Username: ");
|
print!("Username: ");
|
||||||
let username = tui::prompt();
|
let username = tui::prompt();
|
||||||
if manifest.account_exists(&username) {
|
if manifest.account_exists(&username) {
|
||||||
error!(
|
bail!(
|
||||||
"Account {} already exists in manifest, remove it first",
|
"Account {} already exists in manifest, remove it first",
|
||||||
username
|
username
|
||||||
);
|
);
|
||||||
|
@ -231,7 +239,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
Err(AccountLinkError::MustRemovePhoneNumber) => {
|
Err(AccountLinkError::MustRemovePhoneNumber) => {
|
||||||
println!("There is already a phone number on this account, please remove it and try again.");
|
println!("There is already a phone number on this account, please remove it and try again.");
|
||||||
return;
|
bail!("There is already a phone number on this account, please remove it and try again.");
|
||||||
}
|
}
|
||||||
Err(AccountLinkError::MustProvidePhoneNumber) => {
|
Err(AccountLinkError::MustProvidePhoneNumber) => {
|
||||||
println!("Enter your phone number in the following format: +1 123-456-7890");
|
println!("Enter your phone number in the following format: +1 123-456-7890");
|
||||||
|
@ -240,7 +248,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
Err(AccountLinkError::AuthenticatorPresent) => {
|
Err(AccountLinkError::AuthenticatorPresent) => {
|
||||||
println!("An authenticator is already present on this account.");
|
println!("An authenticator is already present on this account.");
|
||||||
return;
|
bail!("An authenticator is already present on this account.");
|
||||||
}
|
}
|
||||||
Err(AccountLinkError::MustConfirmEmail) => {
|
Err(AccountLinkError::MustConfirmEmail) => {
|
||||||
println!("Check your email and click the link.");
|
println!("Check your email and click the link.");
|
||||||
|
@ -251,7 +259,7 @@ fn main() {
|
||||||
"Failed to link authenticator. Account has not been linked. {}",
|
"Failed to link authenticator. Account has not been linked. {}",
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
return;
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +272,7 @@ fn main() {
|
||||||
"Just in case, here is the account info. Save it somewhere just in case!\n{:?}",
|
"Just in case, here is the account info. Save it somewhere just in case!\n{:?}",
|
||||||
manifest.accounts.last().unwrap().lock().unwrap()
|
manifest.accounts.last().unwrap().lock().unwrap()
|
||||||
);
|
);
|
||||||
return;
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,12 +300,12 @@ fn main() {
|
||||||
tries += 1;
|
tries += 1;
|
||||||
if tries >= 30 {
|
if tries >= 30 {
|
||||||
error!("Failed to finalize: unable to generate valid 2fa codes");
|
error!("Failed to finalize: unable to generate valid 2fa codes");
|
||||||
return;
|
bail!("Failed to finalize: unable to generate valid 2fa codes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to finalize: {}", err);
|
error!("Failed to finalize: {}", err);
|
||||||
return;
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,7 +318,7 @@ fn main() {
|
||||||
"Failed to save manifest, but we were able to save it before. {}",
|
"Failed to save manifest, but we were able to save it before. {}",
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
return;
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +327,7 @@ fn main() {
|
||||||
account.revocation_code
|
account.revocation_code
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return Ok(());
|
||||||
} else if let Some(import_matches) = matches.subcommand_matches("import") {
|
} else if let Some(import_matches) = matches.subcommand_matches("import") {
|
||||||
for file_path in import_matches.values_of("files").unwrap() {
|
for file_path in import_matches.values_of("files").unwrap() {
|
||||||
match manifest.import_account(file_path.into()) {
|
match manifest.import_account(file_path.into()) {
|
||||||
|
@ -327,13 +335,13 @@ fn main() {
|
||||||
info!("Imported account: {}", file_path);
|
info!("Imported account: {}", file_path);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to import account: {} {}", file_path, err);
|
bail!("Failed to import account: {} {}", file_path, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest.save(&passkey).expect("Failed to save manifest.");
|
manifest.save(&passkey)?;
|
||||||
return;
|
return Ok(());
|
||||||
} else if matches.is_present("encrypt") {
|
} else if matches.is_present("encrypt") {
|
||||||
if passkey.is_none() {
|
if passkey.is_none() {
|
||||||
loop {
|
loop {
|
||||||
|
@ -349,14 +357,14 @@ fn main() {
|
||||||
for entry in &mut manifest.entries {
|
for entry in &mut manifest.entries {
|
||||||
entry.encryption = Some(accountmanager::EntryEncryptionParams::generate());
|
entry.encryption = Some(accountmanager::EntryEncryptionParams::generate());
|
||||||
}
|
}
|
||||||
manifest.save(&passkey).expect("Failed to save manifest.");
|
manifest.save(&passkey)?;
|
||||||
return;
|
return Ok(());
|
||||||
} else if matches.is_present("decrypt") {
|
} else if matches.is_present("decrypt") {
|
||||||
for entry in &mut manifest.entries {
|
for entry in &mut manifest.entries {
|
||||||
entry.encryption = None;
|
entry.encryption = None;
|
||||||
}
|
}
|
||||||
manifest.save(&passkey).expect("Failed to save manifest.");
|
manifest.save(&passkey)?;
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut selected_accounts: Vec<Arc<Mutex<SteamGuardAccount>>> = vec![];
|
let mut selected_accounts: Vec<Arc<Mutex<SteamGuardAccount>>> = vec![];
|
||||||
|
@ -401,27 +409,54 @@ fn main() {
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
info!("failed to get trade confirmations, asking user to log in");
|
info!("failed to get trade confirmations, asking user to log in");
|
||||||
do_login(&mut account).expect("Failed to log in");
|
do_login(&mut account)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut any_failed = false;
|
||||||
|
let fail_fast = trade_matches.is_present("fail-fast");
|
||||||
if trade_matches.is_present("accept-all") {
|
if trade_matches.is_present("accept-all") {
|
||||||
info!("accepting all confirmations");
|
info!("accepting all confirmations");
|
||||||
for conf in &confirmations {
|
for conf in &confirmations {
|
||||||
let result = account.accept_confirmation(conf);
|
let result = account.accept_confirmation(conf);
|
||||||
debug!("accept confirmation result: {:?}", result);
|
if result.is_err() {
|
||||||
|
warn!("accept confirmation result: {:?}", result);
|
||||||
|
any_failed = true;
|
||||||
|
if fail_fast {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!("accept confirmation result: {:?}", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if termion::is_tty(&stdout()) {
|
if termion::is_tty(&stdout()) {
|
||||||
let (accept, deny) = tui::prompt_confirmation_menu(confirmations);
|
let (accept, deny) = tui::prompt_confirmation_menu(confirmations);
|
||||||
for conf in &accept {
|
for conf in &accept {
|
||||||
let result = account.accept_confirmation(conf);
|
let result = account.accept_confirmation(conf);
|
||||||
debug!("accept confirmation result: {:?}", result);
|
if result.is_err() {
|
||||||
|
warn!("accept confirmation result: {:?}", result);
|
||||||
|
any_failed = true;
|
||||||
|
if fail_fast {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!("accept confirmation result: {:?}", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for conf in &deny {
|
for conf in &deny {
|
||||||
let result = account.deny_confirmation(conf);
|
let result = account.deny_confirmation(conf);
|
||||||
debug!("deny confirmation result: {:?}", result);
|
debug!("deny confirmation result: {:?}", result);
|
||||||
|
if result.is_err() {
|
||||||
|
warn!("deny confirmation result: {:?}", result);
|
||||||
|
any_failed = true;
|
||||||
|
if fail_fast {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!("deny confirmation result: {:?}", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!("not a tty, not showing menu");
|
warn!("not a tty, not showing menu");
|
||||||
|
@ -430,9 +465,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if any_failed {
|
||||||
|
error!("Failed to respond to some confirmations.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest.save(&passkey).expect("Failed to save manifest");
|
manifest.save(&passkey)?;
|
||||||
} else if let Some(_) = matches.subcommand_matches("remove") {
|
} else if let Some(_) = matches.subcommand_matches("remove") {
|
||||||
println!(
|
println!(
|
||||||
"This will remove the mobile authenticator from {} accounts: {}",
|
"This will remove the mobile authenticator from {} accounts: {}",
|
||||||
|
@ -448,7 +487,7 @@ fn main() {
|
||||||
'y' => {}
|
'y' => {}
|
||||||
_ => {
|
_ => {
|
||||||
info!("Aborting!");
|
info!("Aborting!");
|
||||||
return;
|
return Err(errors::UserError::Aborted.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +528,7 @@ fn main() {
|
||||||
manifest.remove_account(account_name);
|
manifest.remove_account(account_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest.save(&passkey).expect("Failed to save manifest.");
|
manifest.save(&passkey)?;
|
||||||
} else {
|
} else {
|
||||||
let server_time = steamapi::get_server_time();
|
let server_time = steamapi::get_server_time();
|
||||||
debug!("Time used to generate codes: {}", server_time);
|
debug!("Time used to generate codes: {}", server_time);
|
||||||
|
@ -503,6 +542,7 @@ fn main() {
|
||||||
println!("{}", code);
|
println!("{}", code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_login(account: &mut SteamGuardAccount) -> anyhow::Result<()> {
|
fn do_login(account: &mut SteamGuardAccount) -> anyhow::Result<()> {
|
||||||
|
|
Loading…
Reference in a new issue