From 55801384eb3baf19428185aad069bd607c97e2dd Mon Sep 17 00:00:00 2001 From: Joseph Montanaro Date: Mon, 15 Jul 2024 10:34:51 -0400 Subject: [PATCH] split into workspace so CLI can be a standalone crate --- src-tauri/Cargo.lock | 19 ++- src-tauri/Cargo.toml | 27 ++-- src-tauri/creddy_cli/Cargo.toml | 12 ++ src-tauri/{ => creddy_cli}/src/cli.rs | 120 +++++++----------- src-tauri/creddy_cli/src/lib.rs | 39 ++++++ .../creddy_cli.rs => creddy_cli/src/main.rs} | 22 +--- src-tauri/creddy_cli/src/proto.rs | 90 +++++++++++++ src-tauri/src/errors.rs | 6 +- src-tauri/src/lib.rs | 1 - src-tauri/src/main.rs | 9 +- src-tauri/src/srv/creddy_server.rs | 26 ++-- src-tauri/src/srv/mod.rs | 36 +++--- 12 files changed, 259 insertions(+), 148 deletions(-) create mode 100644 src-tauri/creddy_cli/Cargo.toml rename src-tauri/{ => creddy_cli}/src/cli.rs (63%) create mode 100644 src-tauri/creddy_cli/src/lib.rs rename src-tauri/{src/bin/creddy_cli.rs => creddy_cli/src/main.rs} (51%) create mode 100644 src-tauri/creddy_cli/src/proto.rs diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5a6de83..b289040 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1204,9 +1204,8 @@ dependencies = [ "aws-sdk-sts", "aws-smithy-types", "aws-types", - "base64 0.22.1", "chacha20poly1305", - "clap", + "creddy_cli", "dirs 5.0.1", "futures", "is-terminal", @@ -1241,6 +1240,18 @@ dependencies = [ "windows 0.51.1", ] +[[package]] +name = "creddy_cli" +version = "0.5.3" +dependencies = [ + "anyhow", + "clap", + "dirs 5.0.1", + "serde", + "serde_json", + "tokio", +] + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -4619,9 +4630,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.118" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa 1.0.11", "ryu", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 88f3924..d22c84d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -9,37 +9,40 @@ default-run = "creddy" edition = "2021" rust-version = "1.57" -[[bin]] -name = "creddy_cli" -path = "src/bin/creddy_cli.rs" - [[bin]] name = "creddy" path = "src/main.rs" +# we use a workspace so that we can split out the CLI and make it possible to build independently +[workspace] +members = ["creddy_cli"] + +[workspace.dependencies] +dirs = "5.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +tokio = { version = ">=1.19", features = ["full"] } + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] tauri-build = { version = "2.0.0-beta", features = [] } [dependencies] -serde_json = "1.0" -serde = { version = "1.0", features = ["derive"] } +creddy_cli = { path = "./creddy_cli" } tauri = { version = "2.0.0-beta", features = ["tray-icon"] } sodiumoxide = "0.2.7" -tokio = { version = ">=1.19", features = ["full"] } sysinfo = "0.26.8" aws-config = "1.5.3" aws-types = "1.3.2" aws-sdk-sts = "1.33.0" aws-smithy-types = "1.2.0" +dirs = { workspace = true } thiserror = "1.0.38" once_cell = "1.16.0" strum = "0.24" strum_macros = "0.24" auto-launch = "0.4.0" -dirs = "5.0" -clap = { version = "3.2.23", features = ["derive"] } is-terminal = "0.4.7" argon2 = { version = "0.5.0", features = ["std"] } chacha20poly1305 = { version = "0.10.1", features = ["std"] } @@ -55,7 +58,10 @@ ssh-agent-lib = "0.4.0" ssh-key = { version = "0.6.6", features = ["rsa", "ed25519", "encryption"] } signature = "2.2.0" tokio-stream = "0.1.15" +serde = { workspace = true } +serde_json = { workspace = true } sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio", "uuid"] } +tokio = { workspace = true } tokio-util = { version = "0.7.11", features = ["codec"] } futures = "0.3.30" openssl = "0.10.64" @@ -71,8 +77,5 @@ default = ["custom-protocol"] # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] -[dev-dependencies] -base64 = "0.22.1" - # [profile.dev.build-override] # opt-level = 3 diff --git a/src-tauri/creddy_cli/Cargo.toml b/src-tauri/creddy_cli/Cargo.toml new file mode 100644 index 0000000..e2f4572 --- /dev/null +++ b/src-tauri/creddy_cli/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "creddy_cli" +version = "0.5.3" +edition = "2021" + +[dependencies] +anyhow = "1.0.86" +clap = { version = "3.2.23", features = ["derive"] } +dirs = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } diff --git a/src-tauri/src/cli.rs b/src-tauri/creddy_cli/src/cli.rs similarity index 63% rename from src-tauri/src/cli.rs rename to src-tauri/creddy_cli/src/cli.rs index e082fd3..479f356 100644 --- a/src-tauri/src/cli.rs +++ b/src-tauri/creddy_cli/src/cli.rs @@ -1,9 +1,12 @@ -use std::ffi::OsString; +use std::env; use std::path::PathBuf; use std::process::Command as ChildCommand; +#[cfg(unix)] +use std::os::unix::process::CommandExt; #[cfg(windows)] use std::time::Duration; +use anyhow::{bail, Context}; use clap::{ Command, Arg, @@ -11,34 +14,22 @@ use clap::{ ArgAction, builder::PossibleValuesParser, value_parser, - }; +}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use crate::errors::*; -use crate::srv::{ - self, - Request, - Response -}; -use crate::shortcuts::ShortcutAction; - -#[cfg(unix)] -use { - std::os::unix::process::CommandExt, - tokio::net::UnixStream, -}; - -#[cfg(windows)] -use { - tokio::net::windows::named_pipe::{NamedPipeClient, ClientOptions}, - windows::Win32::Foundation::ERROR_PIPE_BUSY, +use crate::proto::{ + CliCredential, + CliRequest, + CliResponse, + ServerError, + ShortcutAction, }; pub fn parser() -> Command<'static> { Command::new("creddy") .version(env!("CARGO_PKG_VERSION")) - .about("A friendly AWS credentials manager") + .about("A friendly credential manager") .arg( Arg::new("server_addr") .short('a') @@ -102,56 +93,53 @@ pub fn parser() -> Command<'static> { } -pub fn get(args: &ArgMatches, global_args: &ArgMatches) -> Result<(), CliError> { +pub fn get(args: &ArgMatches, global_args: &ArgMatches) -> anyhow::Result<()> { let name = args.get_one("name").cloned(); let base = *args.get_one("base").unwrap_or(&false); let addr = global_args.get_one("server_addr").cloned(); - let output = match make_request(addr, &Request::GetAwsCredentials { name, base })? { - Response::AwsBase(creds) => serde_json::to_string(&creds).unwrap(), - Response::AwsSession(creds) => serde_json::to_string(&creds).unwrap(), - r => return Err(RequestError::Unexpected(r).into()), + let output = match make_request(addr, &CliRequest::GetCredential { name, base })?? { + CliResponse::Credential(c) => serde_json::to_string_pretty(&c).unwrap(), + r => bail!("Unexpected response from server: {r}"), }; println!("{output}"); Ok(()) } -pub fn exec(args: &ArgMatches, global_args: &ArgMatches) -> Result<(), CliError> { +pub fn exec(args: &ArgMatches, global_args: &ArgMatches) -> anyhow::Result<()> { let name = args.get_one("name").cloned(); let base = *args.get_one("base").unwrap_or(&false); let addr = global_args.get_one("server_addr").cloned(); - let mut cmd_line = args.get_many("command") - .ok_or(ExecError::NoCommand)?; - - let cmd_name: &String = cmd_line.next().unwrap(); // Clap guarantees that there will be at least one + // Clap guarantees that cmd_line will be a sequence of at least 1 item + // test this! + let mut cmd_line = args.get_many("command").unwrap(); + let cmd_name: &String = cmd_line.next().unwrap(); let mut cmd = ChildCommand::new(cmd_name); cmd.args(cmd_line); - match make_request(addr, &Request::GetAwsCredentials { name, base })? { - Response::AwsBase(creds) => { + match make_request(addr, &CliRequest::GetCredential { name, base })?? { + CliResponse::Credential(CliCredential::AwsBase(creds)) => { cmd.env("AWS_ACCESS_KEY_ID", creds.access_key_id); cmd.env("AWS_SECRET_ACCESS_KEY", creds.secret_access_key); }, - Response::AwsSession(creds) => { + CliResponse::Credential(CliCredential::AwsSession(creds)) => { cmd.env("AWS_ACCESS_KEY_ID", creds.access_key_id); cmd.env("AWS_SECRET_ACCESS_KEY", creds.secret_access_key); cmd.env("AWS_SESSION_TOKEN", creds.session_token); }, - r => return Err(RequestError::Unexpected(r).into()), + r => bail!("Unexpected response from server: {r}"), } #[cfg(unix)] { // cmd.exec() never returns if successful let e = cmd.exec(); - match e.kind() { - std::io::ErrorKind::NotFound => { - let name: OsString = cmd_name.into(); - Err(ExecError::NotFound(name).into()) - } - _ => Err(ExecError::ExecutionFailed(e).into()), - } + Err(e).with_context(|| { + // eventually figure out how to display the actual command + format!("Failed to execute command") + })?; + Ok(()) } #[cfg(windows)] @@ -172,7 +160,7 @@ pub fn exec(args: &ArgMatches, global_args: &ArgMatches) -> Result<(), CliError> } -pub fn invoke_shortcut(args: &ArgMatches, global_args: &ArgMatches) -> Result<(), CliError> { +pub fn invoke_shortcut(args: &ArgMatches, global_args: &ArgMatches) -> anyhow::Result<()> { let addr = global_args.get_one("server_addr").cloned(); let action = match args.get_one::("action").map(|s| s.as_str()) { Some("show_window") => ShortcutAction::ShowWindow, @@ -180,48 +168,32 @@ pub fn invoke_shortcut(args: &ArgMatches, global_args: &ArgMatches) -> Result<() Some(&_) | None => unreachable!("Unknown shortcut action"), // guaranteed by clap }; - let req = Request::InvokeShortcut(action); - match make_request(addr, &req) { - Ok(Response::Empty) => Ok(()), - Ok(r) => Err(RequestError::Unexpected(r).into()), - Err(e) => Err(e.into()), + let req = CliRequest::InvokeShortcut(action); + match make_request(addr, &req)?? { + CliResponse::Empty => Ok(()), + r => bail!("Unexpected response from server: {r}"), } } +// Explanation for double-result: the server will return a (serialized) Result +// to indicate when the operation succeeded or failed, which we deserialize. +// However, the operation may fail to even communicate with the server, in +// which case we return the outer Result #[tokio::main] -async fn make_request(addr: Option, req: &Request) -> Result { +async fn make_request( + addr: Option, + req: &CliRequest +) -> anyhow::Result> { let mut data = serde_json::to_string(req).unwrap(); // server expects newline marking end of request data.push('\n'); - let mut stream = connect(addr).await?; + let mut stream = crate::connect(addr).await?; stream.write_all(&data.as_bytes()).await?; let mut buf = Vec::with_capacity(1024); stream.read_to_end(&mut buf).await?; - let res: Result = serde_json::from_slice(&buf)?; - Ok(res?) -} - - -#[cfg(windows)] -async fn connect(addr: Option) -> Result { - // apparently attempting to connect can fail if there's already a client connected - loop { - let addr = addr.unwrap_or_else(|| srv::addr("creddy-server")); - match ClientOptions::new().open(&addr) { - Ok(stream) => return Ok(stream), - Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY.0 as i32) => (), - Err(e) => return Err(e), - } - tokio::time::sleep(Duration::from_millis(10)).await; - } -} - - -#[cfg(unix)] -async fn connect(addr: Option) -> Result { - let path = addr.unwrap_or_else(|| srv::addr("creddy-server")); - UnixStream::connect(&path).await + let res: Result = serde_json::from_slice(&buf)?; + Ok(res) } diff --git a/src-tauri/creddy_cli/src/lib.rs b/src-tauri/creddy_cli/src/lib.rs new file mode 100644 index 0000000..3cf050e --- /dev/null +++ b/src-tauri/creddy_cli/src/lib.rs @@ -0,0 +1,39 @@ +mod cli; +pub use cli::{ + exec, + get, + parser, + invoke_shortcut, +}; + +pub(crate) use platform::connect; +pub use platform::server_addr; + +mod proto; + + +#[cfg(unix)] +mod platform { + use std::path::PathBuf; + use tokio::net::UnixStream; + + pub async fn connect(addr: Option) -> Result { + let path = addr.unwrap_or_else(|| server_addr("creddy-server")); + UnixStream::connect(&path).await + } + + pub fn server_addr(sock_name: &str) -> PathBuf { + let mut path = dirs::runtime_dir() + .unwrap_or_else(|| PathBuf::from("/tmp")); + path.push(format!("{sock_name}.sock")); + path + } +} + + +#[cfg(windows)] +mod platform { + pub fn server_addr(sock_name: &str) -> String { + format!(r"\\.\pipe\{sock_name}") + } +} diff --git a/src-tauri/src/bin/creddy_cli.rs b/src-tauri/creddy_cli/src/main.rs similarity index 51% rename from src-tauri/src/bin/creddy_cli.rs rename to src-tauri/creddy_cli/src/main.rs index 593416c..d6e380a 100644 --- a/src-tauri/src/bin/creddy_cli.rs +++ b/src-tauri/creddy_cli/src/main.rs @@ -1,22 +1,14 @@ -// Windows isn't really amenable to having a single executable work as both a CLI and GUI app, -// so we just have a second binary for CLI usage -use creddy::{ - cli, - errors::CliError, -}; -use std::{ - env, - process::{self, Command}, -}; +use std::env; +use std::process::{self, Command}; fn main() { - let global_matches = cli::parser().get_matches(); + let global_matches = creddy_cli::parser().get_matches(); let res = match global_matches.subcommand() { None | Some(("run", _)) => launch_gui(), - Some(("get", m)) => cli::get(m, &global_matches), - Some(("exec", m)) => cli::exec(m, &global_matches), - Some(("shortcut", m)) => cli::invoke_shortcut(m, &global_matches), + Some(("get", m)) => creddy_cli::get(m, &global_matches), + Some(("exec", m)) => creddy_cli::exec(m, &global_matches), + Some(("shortcut", m)) => creddy_cli::invoke_shortcut(m, &global_matches), _ => unreachable!("Unknown subcommand"), }; @@ -27,7 +19,7 @@ fn main() { } -fn launch_gui() -> Result<(), CliError> { +fn launch_gui() -> anyhow::Result<()> { let mut path = env::current_exe()?; path.pop(); // bin dir diff --git a/src-tauri/creddy_cli/src/proto.rs b/src-tauri/creddy_cli/src/proto.rs new file mode 100644 index 0000000..4326da3 --- /dev/null +++ b/src-tauri/creddy_cli/src/proto.rs @@ -0,0 +1,90 @@ +use std::fmt::{ + Display, + Formatter, + Error as FmtError +}; + +use serde::{Serialize, Deserialize}; + + +#[derive(Debug, Serialize, Deserialize)] +pub enum CliRequest { + GetCredential { + name: Option, + base: bool, + }, + InvokeShortcut(ShortcutAction), +} + + +#[derive(Debug, Serialize, Deserialize)] +pub enum ShortcutAction { + ShowWindow, + LaunchTerminal, +} + + +#[derive(Debug, Serialize, Deserialize)] +pub enum CliResponse { + Credential(CliCredential), + Empty, +} + +impl Display for CliResponse { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + CliResponse::Credential(CliCredential::AwsBase(_)) => write!(f, "Credential (AwsBase)"), + CliResponse::Credential(CliCredential::AwsSession(_)) => write!(f, "Credential (AwsSession)"), + CliResponse::Empty => write!(f, "Empty"), + } + } +} + + +#[derive(Debug, Serialize, Deserialize)] +pub enum CliCredential { + AwsBase(AwsBaseCredential), + AwsSession(AwsSessionCredential), +} + + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct AwsBaseCredential { + #[serde(default = "default_aws_version")] + pub version: usize, + pub access_key_id: String, + pub secret_access_key: String, +} + + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct AwsSessionCredential { + #[serde(default = "default_aws_version")] + pub version: usize, + pub access_key_id: String, + pub secret_access_key: String, + pub session_token: String, + // we don't need to know the expiration for the CLI, so just use a string here + pub expiration: String, +} + + +fn default_aws_version() -> usize { 1 } + + +#[derive(Debug, Serialize, Deserialize)] +pub struct ServerError { + code: String, + msg: String, +} + +impl Display for ServerError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "Error response ({}) from server: {}", self.code, self.msg)?; + Ok(()) + } +} + +impl std::error::Error for ServerError {} diff --git a/src-tauri/src/errors.rs b/src-tauri/src/errors.rs index e30ec28..559819e 100644 --- a/src-tauri/src/errors.rs +++ b/src-tauri/src/errors.rs @@ -36,7 +36,7 @@ pub trait ShowError fn error_print_prefix(self, prefix: &str); } -impl ShowError for Result +impl ShowError for Result where E: std::fmt::Display { fn error_popup(self, title: &str) { @@ -91,7 +91,7 @@ impl Serialize for SerializeUpstream { } } -fn serialize_upstream_err(err: &E, map: &mut M) -> Result<(), M::Error> +fn serialize_upstream_err(err: &E, map: &mut M) -> Result<(), M::Error> where E: Error, M: serde::ser::SerializeMap, @@ -370,7 +370,7 @@ pub enum RequestError { #[error("Error response from server: {0}")] Server(ServerError), #[error("Unexpected response from server")] - Unexpected(crate::srv::Response), + Unexpected(crate::srv::CliResponse), #[error("The server did not respond with valid JSON")] InvalidJson(#[from] serde_json::Error), #[error("Error reading/writing stream: {0}")] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6674c23..f55c5b6 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,5 +1,4 @@ pub mod app; -pub mod cli; mod config; mod credentials; pub mod errors; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 827a021..587f126 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,21 +5,20 @@ use creddy::{ app, - cli, errors::ShowError, }; fn main() { - let global_matches = cli::parser().get_matches(); + let global_matches = creddy_cli::parser().get_matches(); let res = match global_matches.subcommand() { None | Some(("run", _)) => { app::run().error_popup("Creddy encountered an error"); Ok(()) }, - Some(("get", m)) => cli::get(m, &global_matches), - Some(("exec", m)) => cli::exec(m, &global_matches), - Some(("shortcut", m)) => cli::invoke_shortcut(m, &global_matches), + Some(("get", m)) => creddy_cli::get(m, &global_matches), + Some(("exec", m)) => creddy_cli::exec(m, &global_matches), + Some(("shortcut", m)) => creddy_cli::invoke_shortcut(m, &global_matches), _ => unreachable!(), }; diff --git a/src-tauri/src/srv/creddy_server.rs b/src-tauri/src/srv/creddy_server.rs index 08d9547..aa10f88 100644 --- a/src-tauri/src/srv/creddy_server.rs +++ b/src-tauri/src/srv/creddy_server.rs @@ -9,8 +9,9 @@ use crate::shortcuts::{self, ShortcutAction}; use crate::state::AppState; use super::{ CloseWaiter, - Request, - Response, + CliCredential, + CliRequest, + CliResponse, Stream, }; @@ -43,13 +44,12 @@ async fn handle( let waiter = CloseWaiter { stream: &mut stream }; - let req: Request = serde_json::from_slice(&buf)?; + let req: CliRequest = serde_json::from_slice(&buf)?; let res = match req { - Request::GetAwsCredentials { name, base } => get_aws_credentials( + CliRequest::GetCredential{ name, base } => get_aws_credentials( name, base, client, app_handle, waiter ).await, - Request::InvokeShortcut(action) => invoke_shortcut(action).await, - Request::GetSshSignature(_) => return Err(HandlerError::Denied), + CliRequest::InvokeShortcut(action) => invoke_shortcut(action).await, }; // doesn't make sense to send the error to the client if the client has already left @@ -63,9 +63,9 @@ async fn handle( } -async fn invoke_shortcut(action: ShortcutAction) -> Result { +async fn invoke_shortcut(action: ShortcutAction) -> Result { shortcuts::exec_shortcut(action); - Ok(Response::Empty) + Ok(CliResponse::Empty) } @@ -75,7 +75,7 @@ async fn get_aws_credentials( client: Client, app_handle: AppHandle, mut waiter: CloseWaiter<'_>, -) -> Result { +) -> Result { let state = app_handle.state::(); let rehide_ms = { let config = state.config.read().await; @@ -108,11 +108,11 @@ async fn get_aws_credentials( Approval::Approved => { if response.base { let creds = state.get_aws_base(name).await?; - Ok(Response::AwsBase(creds)) + Ok(CliResponse::Credential(CliCredential::AwsBase(creds))) } else { - let creds = state.get_aws_session(name).await?; - Ok(Response::AwsSession(creds.clone())) + let creds = state.get_aws_session(name).await?.clone(); + Ok(CliResponse::Credential(CliCredential::AwsSession(creds))) } }, Approval::Denied => Err(HandlerError::Denied), @@ -129,4 +129,4 @@ async fn get_aws_credentials( lease.release(); result -} \ No newline at end of file +} diff --git a/src-tauri/src/srv/mod.rs b/src-tauri/src/srv/mod.rs index 83f3a61..e033b62 100644 --- a/src-tauri/src/srv/mod.rs +++ b/src-tauri/src/srv/mod.rs @@ -6,7 +6,6 @@ use tauri::{ }; use tokio::io::AsyncReadExt; use serde::{Serialize, Deserialize}; -use ssh_agent_lib::proto::message::SignRequest; use crate::credentials::{AwsBaseCredential, AwsSessionCredential}; use crate::errors::*; @@ -15,25 +14,32 @@ use crate::shortcuts::ShortcutAction; pub mod creddy_server; pub mod agent; use platform::Stream; -pub use platform::addr; +// These types match what's defined in creddy_cli, but they are separate types +// so that we avoid polluting the standalone CLI with a bunch of dependencies +// that would make it impossible to build a completely static-linked version #[derive(Debug, Serialize, Deserialize)] -pub enum Request { - GetAwsCredentials { +pub enum CliRequest { + GetCredential { name: Option, base: bool, }, - GetSshSignature(SignRequest), InvokeShortcut(ShortcutAction), } #[derive(Debug, Serialize, Deserialize)] -pub enum Response { +pub enum CliResponse { + Credential(CliCredential), + Empty, +} + + +#[derive(Debug, Serialize, Deserialize)] +pub enum CliCredential { AwsBase(AwsBaseCredential), AwsSession(AwsSessionCredential), - Empty, } @@ -92,7 +98,7 @@ mod platform { pub type Stream = UnixStream; pub fn bind(sock_name: &str) -> std::io::Result<(UnixListener, PathBuf)> { - let path = addr(sock_name); + let path = creddy_cli::server_addr(sock_name); match std::fs::remove_file(&path) { Ok(_) => (), Err(e) if e.kind() == ErrorKind::NotFound => (), @@ -112,14 +118,6 @@ mod platform { Ok((stream, pid)) } - - - pub fn addr(sock_name: &str) -> PathBuf { - let mut path = dirs::runtime_dir() - .unwrap_or_else(|| PathBuf::from("/tmp")); - path.push(format!("{sock_name}.sock")); - path - } } @@ -140,7 +138,7 @@ mod platform { pub type Stream = NamedPipeServer; pub fn bind(sock_name: &str) -> std::io::Result<(String, NamedPipeServer)> { - let addr = addr(sock_name); + let addr = creddy_cli::server_addr(sock_name); let listener = ServerOptions::new() .first_pipe_instance(true) .create(&addr)?; @@ -163,8 +161,4 @@ mod platform { unsafe { GetNamedPipeClientProcessId(handle, &mut pid as *mut u32)? }; Ok((stream, pid)) } - - pub fn addr(sock_name: &str) -> String { - format!(r"\\.\pipe\{sock_name}") - } }