add non-zero exit codes when unrecoverable errors occur.
This commit is contained in:
parent
c6bd5b5dc4
commit
b1d559ea00
2 changed files with 46 additions and 35 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
|
||||||
|
}
|
74
src/main.rs
74
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> {
|
||||||
|
@ -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<()> {
|
||||||
|
|
Loading…
Reference in a new issue