add non-zero exit codes when unrecoverable errors occur.

This commit is contained in:
Carson McManus 2022-02-21 11:57:19 -05:00
parent c6bd5b5dc4
commit b1d559ea00
2 changed files with 46 additions and 35 deletions

7
src/errors.rs Normal file
View file

@ -0,0 +1,7 @@
use thiserror::Error;
#[derive(Debug, Error)]
pub(crate) enum UserError {
#[error("User aborted the operation.")]
Aborted
}

View file

@ -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> {
@ -126,6 +127,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 +151,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 +159,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 +178,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 +206,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 +216,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 +234,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 +243,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 +254,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 +267,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 +295,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 +313,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 +322,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 +330,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 +352,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,7 +404,7 @@ 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)?;
} }
} }
} }
@ -432,7 +435,7 @@ fn main() {
} }
} }
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 +451,7 @@ fn main() {
'y' => {} 'y' => {}
_ => { _ => {
info!("Aborting!"); info!("Aborting!");
return; return Err(errors::UserError::Aborted.into());
} }
} }
@ -489,7 +492,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 +506,7 @@ fn main() {
println!("{}", code); println!("{}", code);
} }
} }
Ok(())
} }
fn do_login(account: &mut SteamGuardAccount) -> anyhow::Result<()> { fn do_login(account: &mut SteamGuardAccount) -> anyhow::Result<()> {