pshell/
lib.rs

1use std::process;
2use sysinfo::Process;
3use sysinfo::{Pid, System, IS_SUPPORTED_SYSTEM};
4
5/// Traverses up the parent processes to see if the name of any of them matches a `KNOWN_SHELL`
6pub fn find() -> Option<(String, u32)> {
7    const KNOWN_SHELLS: [&str; 10] = [
8        "bash",
9        "zsh",
10        "fish",
11        "tcsh",
12        "dash",
13        "csh",
14        "ksh",
15        "cmd",
16        "powershell",
17        "pwsh",
18    ];
19
20    if IS_SUPPORTED_SYSTEM {
21        let sys = System::new_all();
22        let mut process: Option<&Process> = sys.process(Pid::from_u32(process::id()));
23        while process.is_some() {
24            process = get_parent(&sys, process.unwrap());
25            if let Some(shell) = process {
26                if let Some(shell_name) = shell.name().to_str() {
27                    let mut shell_name = shell_name;
28                    if shell_name.ends_with(".exe") {
29                        shell_name = &shell_name[..shell_name.len() - 4];
30                    }
31                    if KNOWN_SHELLS.contains(&shell_name) {
32                        return Some((shell_name.to_owned(), shell.pid().as_u32()));
33                    }
34                };
35            }
36        }
37        None
38    } else {
39        None
40    }
41}
42
43fn get_parent<'a>(sys: &'a System, process: &Process) -> Option<&'a Process> {
44    if let Some(ppid) = process.parent() {
45        if let Some(parent) = sys.process(ppid) {
46            Some(parent)
47        } else {
48            None
49        }
50    } else {
51        None
52    }
53}