use std::process::Command; use tauri::Manager; use crate::app::APP; use crate::errors::*; use crate::state::AppState; pub async fn launch(use_base: bool) -> Result<(), LaunchTerminalError> { let app = APP.get().unwrap(); let state = app.state::(); // register_terminal_request() returns Err if there is another request pending if state.register_terminal_request().await.is_err() { return Ok(()); } let mut cmd = { let config = state.config.read().await; let mut cmd = Command::new(&config.terminal.exec); cmd.args(&config.terminal.args); cmd }; // if session is unlocked or empty, wait for credentials from frontend if !state.is_unlocked().await { app.emit_all("launch-terminal-request", ())?; let lease = state.acquire_visibility_lease(0).await .map_err(|_e| LaunchTerminalError::NoMainWindow)?; // automate conversion eventually? let (tx, rx) = tokio::sync::oneshot::channel(); app.once_global("credentials-event", move |e| { let success = match e.payload() { Some("\"unlocked\"") | Some("\"entered\"") => true, _ => false, }; let _ = tx.send(success); }); if !rx.await.unwrap_or(false) { state.unregister_terminal_request().await; return Ok(()); // request was canceled by user } lease.release(); } // more lock-management { let app_session = state.session.read().await; // session should really be unlocked at this point, but if the frontend misbehaves // (i.e. lies about unlocking) we could end up here with a locked session // this will result in an error popup to the user (see main hotkey handler) let (base_creds, session_creds) = app_session.try_get()?; if use_base { cmd.env("AWS_ACCESS_KEY_ID", &base_creds.access_key_id); cmd.env("AWS_SECRET_ACCESS_KEY", &base_creds.secret_access_key); } else { cmd.env("AWS_ACCESS_KEY_ID", &session_creds.access_key_id); cmd.env("AWS_SECRET_ACCESS_KEY", &session_creds.secret_access_key); cmd.env("AWS_SESSION_TOKEN", &session_creds.session_token); } } let res = match cmd.spawn() { Ok(_) => Ok(()), Err(e) if std::io::ErrorKind::NotFound == e.kind() => { Err(ExecError::NotFound(cmd.get_program().to_owned())) }, Err(e) => Err(ExecError::ExecutionFailed(e)), }; state.unregister_terminal_request().await; res?; // ? auto-conversion is more liberal than .into() Ok(()) }