Skip to content

Commit

Permalink
Call kic-discover-visa if conditions are right
Browse files Browse the repository at this point in the history
  • Loading branch information
esarver committed Sep 4, 2024
1 parent 1f5f1fb commit b9a522f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions kic-discover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ tokio = { version = "1.36.0", features = ["full"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
tsp-toolkit-kic-lib = { workspace = true }
windows-sys = { version = "0.52.0", features = [
"Win32_System_Console",
"Win32_Foundation",
] }

29 changes: 29 additions & 0 deletions kic-discover/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ use clap::{command, Args, Command, FromArgMatches, Parser, Subcommand};

use kic_discover::DISC_INSTRUMENTS;

mod process;
use crate::process::Process;

#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
Expand Down Expand Up @@ -216,6 +219,32 @@ fn start_logger(
#[tokio::main]
#[instrument]
async fn main() -> anyhow::Result<()> {
let parent_dir: Option<std::path::PathBuf> = std::env::current_exe().map_or(None, |path| {
path.canonicalize()
.expect("should have canonicalized path")
.parent()
.map(std::convert::Into::into)
});

if tsp_toolkit_kic_lib::is_visa_installed() {
#[cfg(target_os = "windows")]
let kic_discover_visa_exe: Option<std::path::PathBuf> = parent_dir.clone().map(|d| d.join("kic-discover-visa.exe"));

#[cfg(target_family = "unix")]
let kic_discover_visa_exe: Option<std::path::PathBuf> = parent_dir.clone().map(|d| d.join("kic-discover-visa"));

if let Some(kv) = kic_discover_visa_exe {
if kv.exists() {
Process::new(kv.clone(), std::env::args().skip(1))
.exec_replace()
.context(format!(
"{} should have been launched because VISA was detected",
kv.display(),
))?;
return Ok(());
}
}
}
let cmd = command!()
.propagate_version(true)
.subcommand_required(true)
Expand Down
87 changes: 87 additions & 0 deletions kic-discover/src/process.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use std::{io::ErrorKind, path::PathBuf};

#[derive(Debug)]
pub struct Process {
path: PathBuf,
args: Vec<String>,
}
impl Process {
pub fn new<I>(path: PathBuf, args: I) -> Self
where
I: IntoIterator,
I::Item: AsRef<str>,
{
Self {
path,
args: args.into_iter().map(|s| s.as_ref().to_string()).collect(),
}
}

pub fn exec_replace(self) -> anyhow::Result<()> {
imp::exec_replace(&self)
}

#[cfg_attr(unix, allow(dead_code))]
pub fn exec(&self) -> anyhow::Result<()> {
let exit = std::process::Command::new(&self.path)
.args(&self.args)
.spawn()?
.wait()?;
if exit.success() {
Ok(())
} else {
Err(std::io::Error::new(
ErrorKind::Other,
format!(
"child process did not exit successfully: {}",
self.path.display()
),
)
.into())
}
}
}

#[cfg(windows)]
mod imp {
use std::io::ErrorKind;

use super::Process;
use windows_sys::Win32::{
Foundation::{BOOL, FALSE, TRUE},
System::Console::SetConsoleCtrlHandler,
};

#[allow(clippy::missing_const_for_fn)] // This lint seems to be broken for this specific case
unsafe extern "system" fn ctrlc_handler(_: u32) -> BOOL {
TRUE
}

pub(super) fn exec_replace(process: &Process) -> anyhow::Result<()> {
//Safety: This is an external handler that calls into the windows API. It is
// expected to be safe.
unsafe {
if SetConsoleCtrlHandler(Some(ctrlc_handler), TRUE) == FALSE {
return Err(std::io::Error::new(
ErrorKind::Other,
"Unable to set Ctrl+C Handler".to_string(),
)
.into());
}
}

process.exec()
}
}

#[cfg(unix)]
mod imp {
use crate::Process;
use std::os::unix::process::CommandExt;

pub(super) fn exec_replace(process: &Process) -> anyhow::Result<()> {
let mut command = std::process::Command::new(&process.path);
command.args(&process.args);
Err(command.exec().into()) // Exec replaces the current application's program memory, therefore execution will
}
}

0 comments on commit b9a522f

Please sign in to comment.