Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fine-frogs-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fnm": patch
---

fix: correct shell inference when path has spaces or trailing slash
33 changes: 21 additions & 12 deletions src/shell/infer/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use thiserror::Error;
#[derive(Debug)]
struct ProcessInfo {
parent_pid: Option<u32>,
parent_pid_str: String,
command: String,
}

Expand All @@ -28,13 +29,24 @@ pub fn infer_shell() -> Option<Box<dyn Shell>> {
err
})
.ok()?;
let binary = process_info
.command
.trim_start_matches('-')
.split('/')
.next_back()?;

debug!(
"pid {current_pid} parent process {} : {}",
process_info.parent_pid_str, process_info.command
);

let mut parts = process_info.command.trim_start_matches('-').split('/');

let mut binary = "";
while let Some(b) = parts.next_back() {
if !b.is_empty() {
binary = b;
break;
}
}

if let Some(shell) = super::shell_from_string(binary) {
debug!("Found supported shell: {:?}", shell);
return Some(shell);
}

Expand Down Expand Up @@ -69,18 +81,15 @@ fn get_process_info(pid: u32) -> Result<ProcessInfo, ProcessInfoError> {
.next()
.ok_or_else(|| Error::from(ErrorKind::NotFound))??;

let mut parts = line.split_whitespace();
let ppid = parts.next().ok_or_else(|| ProcessInfoError::Parse {
expectation: "Can't read the ppid from ps, should be the first item in the table",
got: line.to_string(),
})?;
let command = parts.next().ok_or_else(|| ProcessInfoError::Parse {
expectation: "Can't read the command from ps, should be the second item in the table",
let (ppid, command_raw) = line.trim().split_once(char::is_whitespace).ok_or_else(|| ProcessInfoError::Parse {
expectation: "Can't split the ppid and program from ps, should be first and second items in the table",
got: line.to_string(),
})?;
let command = command_raw.trim_start();

Ok(ProcessInfo {
parent_pid: ppid.parse().ok(),
parent_pid_str: ppid.into(),
command: command.into(),
})
}
Expand Down
7 changes: 4 additions & 3 deletions src/shell/infer/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ pub fn infer_shell() -> Option<Box<dyn Shell>> {
while let Some(pid) = current_pid {
if let Some(process) = system.process(pid) {
current_pid = process.parent();
debug!("pid {pid} parent process is {current_pid:?}");
let process_name = process
.exe()
let exe = process.exe();
debug!("pid {pid} parent process is {current_pid:?}: {exe:?}");
let process_name = exe
.and_then(|x| {
tap_none(x.file_stem(), || {
warn!("failed to get file stem from {:?}", x);
Expand All @@ -33,6 +33,7 @@ pub fn infer_shell() -> Option<Box<dyn Shell>> {
.map(|x| &x[..])
.and_then(super::shell_from_string)
{
debug!("Found supported shell: {:?}", shell);
return Some(shell);
}
} else {
Expand Down