refactor(TerminalShell): changing recursion into loops

This commit is contained in:
apocelipes
2024-01-12 23:57:56 +09:00
committed by Carter Li
parent 22cdb1247f
commit 269ad36df5
2 changed files with 154 additions and 139 deletions
@@ -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;
}
@@ -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;
}