diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 2ec21dc43..06f8307b6 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -125,33 +125,37 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) pid_t ppid = 0; - if(getProcessNameAndPpid(pid, name, &ppid)) - return 0; + while (getProcessNameAndPpid(pid, name, &ppid) == NULL) + { + //Common programs that are between terminal and own process, but are not the shell + if( + ffStrEquals(name, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell + ffStrEquals(name, "sudo") || + ffStrEquals(name, "su") || + ffStrEquals(name, "strace") || + ffStrEquals(name, "sshd") || + ffStrEquals(name, "gdb") || + ffStrEquals(name, "lldb") || + ffStrEquals(name, "lldb-mi") || + ffStrEquals(name, "login") || + ffStrEquals(name, "ltrace") || + ffStrEquals(name, "perf") || + ffStrEquals(name, "guake-wrapped") || + ffStrContainsIgnCase(name, "debug") || + ffStrContainsIgnCase(name, "not-found") || + ffStrEndsWith(name, ".sh") + ) + { + pid = ppid; + continue; + } - //Common programs that are between terminal and own process, but are not the shell - if( - ffStrEquals(name, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell - ffStrEquals(name, "sudo") || - ffStrEquals(name, "su") || - ffStrEquals(name, "strace") || - ffStrEquals(name, "sshd") || - ffStrEquals(name, "gdb") || - ffStrEquals(name, "lldb") || - ffStrEquals(name, "lldb-mi") || - ffStrEquals(name, "login") || - ffStrEquals(name, "ltrace") || - ffStrEquals(name, "perf") || - ffStrEquals(name, "guake-wrapped") || - ffStrContainsIgnCase(name, "debug") || - ffStrContainsIgnCase(name, "not-found") || - ffStrEndsWith(name, ".sh") - ) - return getShellInfo(result, ppid); - - result->pid = (uint32_t) pid; - result->ppid = (uint32_t) ppid; - ffStrbufSetS(&result->processName, name); - getProcessInformation(pid, &result->processName, &result->exe, &result->exeName); + result->pid = (uint32_t) pid; + result->ppid = (uint32_t) ppid; + ffStrbufSetS(&result->processName, name); + getProcessInformation(pid, &result->processName, &result->exe, &result->exeName); + break; + } return ppid; } @@ -162,39 +166,46 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) pid_t ppid = 0; - if(getProcessNameAndPpid(pid, name, &ppid)) - return 0; + while (getProcessNameAndPpid(pid, name, &ppid) == NULL) + { + //Known shells + if ( + ffStrEquals(name, "ash") || + ffStrEquals(name, "bash") || + ffStrEquals(name, "zsh") || + ffStrEquals(name, "ksh") || + ffStrEquals(name, "mksh") || + ffStrEquals(name, "oksh") || + ffStrEquals(name, "csh") || + ffStrEquals(name, "tcsh") || + ffStrEquals(name, "fish") || + ffStrEquals(name, "dash") || + ffStrEquals(name, "pwsh") || + ffStrEquals(name, "nu") || + ffStrEquals(name, "git-shell") || + ffStrEquals(name, "elvish") || + ffStrEquals(name, "oil.ovm") || + (ffStrEquals(name, "python") && getenv("XONSH_VERSION")) + ) + { + pid = ppid; + continue; + } - //Known shells - if ( - ffStrEquals(name, "ash") || - ffStrEquals(name, "bash") || - ffStrEquals(name, "zsh") || - ffStrEquals(name, "ksh") || - ffStrEquals(name, "mksh") || - ffStrEquals(name, "oksh") || - ffStrEquals(name, "csh") || - ffStrEquals(name, "tcsh") || - ffStrEquals(name, "fish") || - ffStrEquals(name, "dash") || - ffStrEquals(name, "pwsh") || - ffStrEquals(name, "nu") || - ffStrEquals(name, "git-shell") || - ffStrEquals(name, "elvish") || - ffStrEquals(name, "oil.ovm") || - (ffStrEquals(name, "python") && getenv("XONSH_VERSION")) - ) - return getTerminalInfo(result, ppid); + #ifdef __APPLE__ + // https://github.com/fastfetch-cli/fastfetch/discussions/501 + if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)")) + { + if (__builtin_expect(getProcessNameAndPpid(ppid, name, &ppid) != NULL, false)) + return 0; + } + #endif - #ifdef __APPLE__ - // https://github.com/fastfetch-cli/fastfetch/discussions/501 - if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)")) - getProcessNameAndPpid(ppid, name, &ppid); - #endif - - result->pid = (uint32_t) pid; - ffStrbufSetS(&result->processName, name); - getProcessInformation(pid, &result->processName, &result->exe, &result->exeName); + result->pid = (uint32_t) pid; + ffStrbufSetS(&result->processName, name); + getProcessInformation(pid, &result->processName, &result->exe, &result->exeName); + break; + } return ppid; } diff --git a/src/detection/terminalshell/terminalshell_windows.c b/src/detection/terminalshell/terminalshell_windows.c index 29ff9b5cc..a462ab566 100644 --- a/src/detection/terminalshell/terminalshell_windows.c +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -87,48 +87,50 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid) { uint32_t ppid; - if(pid == 0 || !getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName)) - return 0; - - ffStrbufSet(&result->prettyName, &result->processName); - if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe")) - ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4); - - //Common programs that are between terminal and own process, but are not the shell - if( - ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") || - ffStrbufIgnCaseEqualS(&result->prettyName, "su") || - ffStrbufIgnCaseEqualS(&result->prettyName, "doas") || - ffStrbufIgnCaseEqualS(&result->prettyName, "strace") || - ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || - ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") || - ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") || - ffStrbufIgnCaseEqualS(&result->prettyName, "guake-wrapped") || - ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || //scoop warps the real binaries with a "shim" exe - ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") || - ffStrbufContainIgnCaseS(&result->prettyName, "debug") || - ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014 - ) { - ffStrbufClear(&result->processName); - ffStrbufClear(&result->prettyName); - ffStrbufClear(&result->exe); - result->exeName = NULL; - return getShellInfo(result, ppid); - } - - ffStrbufClear(&result->version); - fftsGetShellVersion(&result->exe, result->prettyName.chars, &result->version); - - result->pid = pid; - result->ppid = ppid; - - if(ffStrbufIgnCaseEqualS(&result->prettyName, "explorer")) + while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName)) { - ffStrbufSetS(&result->prettyName, "Windows Explorer"); // Started without shell - // In this case, terminal process will be created by fastfetch itself. - ppid = 0; - } + ffStrbufSet(&result->prettyName, &result->processName); + if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe")) + ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4); + //Common programs that are between terminal and own process, but are not the shell + if( + ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") || + ffStrbufIgnCaseEqualS(&result->prettyName, "su") || + ffStrbufIgnCaseEqualS(&result->prettyName, "doas") || + ffStrbufIgnCaseEqualS(&result->prettyName, "strace") || + ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || + ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") || + ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") || + ffStrbufIgnCaseEqualS(&result->prettyName, "guake-wrapped") || + ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || //scoop warps the real binaries with a "shim" exe + ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") || + ffStrbufContainIgnCaseS(&result->prettyName, "debug") || + ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014 + ) { + ffStrbufClear(&result->processName); + ffStrbufClear(&result->prettyName); + ffStrbufClear(&result->exe); + result->exeName = NULL; + pid = ppid; + continue; + } + + ffStrbufClear(&result->version); + fftsGetShellVersion(&result->exe, result->prettyName.chars, &result->version); + + result->pid = pid; + result->ppid = ppid; + + if(ffStrbufIgnCaseEqualS(&result->prettyName, "explorer")) + { + ffStrbufSetS(&result->prettyName, "Windows Explorer"); // Started without shell + // In this case, terminal process will be created by fastfetch itself. + ppid = 0; + } + + break; + } return ppid; } @@ -296,55 +298,57 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid) { uint32_t ppid; - if(pid == 0 || !getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName)) - return 0; + while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName)) + { + ffStrbufSet(&result->prettyName, &result->processName); + if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe")) + ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4); - ffStrbufSet(&result->prettyName, &result->processName); - if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe")) - ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4); - - if( - ffStrbufIgnCaseEqualS(&result->prettyName, "pwsh") || - ffStrbufIgnCaseEqualS(&result->prettyName, "cmd") || - ffStrbufIgnCaseEqualS(&result->prettyName, "bash") || - ffStrbufIgnCaseEqualS(&result->prettyName, "zsh") || - ffStrbufIgnCaseEqualS(&result->prettyName, "fish") || - ffStrbufIgnCaseEqualS(&result->prettyName, "nu") || - ffStrbufIgnCaseEqualS(&result->prettyName, "powershell") || - ffStrbufIgnCaseEqualS(&result->prettyName, "powershell_ise") || - ffStrbufIgnCaseEqualS(&result->prettyName, "wsl") || // running inside wsl - ffStrbufIgnCaseEqualS(&result->prettyName, "servercoreshell") || // ServerCore Shell Launcher - ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmuC") // wrapper process of ConEmu - ) { - //We are nested shell - ffStrbufClear(&result->processName); - ffStrbufClear(&result->prettyName); - ffStrbufClear(&result->exe); - result->exeName = ""; - return getTerminalInfo(result, ppid); - } - - if(ffStrbufIgnCaseEqualS(&result->prettyName, "sihost") || - ffStrbufIgnCaseEqualS(&result->prettyName, "explorer") - ) { - // A CUI program created by Windows Explorer will spawn a conhost as its child. - // However the conhost process is just a placeholder; - // The true terminal can be Windows Terminal or others. - if (!getTerminalFromEnv(result) && !detectDefaultTerminal(result)) - { + if( + ffStrbufIgnCaseEqualS(&result->prettyName, "pwsh") || + ffStrbufIgnCaseEqualS(&result->prettyName, "cmd") || + ffStrbufIgnCaseEqualS(&result->prettyName, "bash") || + ffStrbufIgnCaseEqualS(&result->prettyName, "zsh") || + ffStrbufIgnCaseEqualS(&result->prettyName, "fish") || + ffStrbufIgnCaseEqualS(&result->prettyName, "nu") || + ffStrbufIgnCaseEqualS(&result->prettyName, "powershell") || + ffStrbufIgnCaseEqualS(&result->prettyName, "powershell_ise") || + ffStrbufIgnCaseEqualS(&result->prettyName, "wsl") || // running inside wsl + ffStrbufIgnCaseEqualS(&result->prettyName, "servercoreshell") || // ServerCore Shell Launcher + ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmuC") // wrapper process of ConEmu + ) { + //We are nested shell ffStrbufClear(&result->processName); ffStrbufClear(&result->prettyName); ffStrbufClear(&result->exe); result->exeName = ""; - return 0; + pid = ppid; + continue; } - } - else - { - result->pid = pid; - result->ppid = ppid; - } + if(ffStrbufIgnCaseEqualS(&result->prettyName, "sihost") || + ffStrbufIgnCaseEqualS(&result->prettyName, "explorer") + ) { + // A CUI program created by Windows Explorer will spawn a conhost as its child. + // However the conhost process is just a placeholder; + // The true terminal can be Windows Terminal or others. + if (!getTerminalFromEnv(result) && !detectDefaultTerminal(result)) + { + ffStrbufClear(&result->processName); + ffStrbufClear(&result->prettyName); + ffStrbufClear(&result->exe); + result->exeName = ""; + return 0; + } + } + else + { + result->pid = pid; + result->ppid = ppid; + } + + break; + } return ppid; }