mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-30 00:37:23 +01:00
TerminalShell: split terminal detection and shell detection
This commit is contained in:
@@ -118,7 +118,7 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
static pid_t getShellInfo(FFTerminalShellResult* result, pid_t pid)
|
||||
{
|
||||
char name[256];
|
||||
name[0] = '\0';
|
||||
@@ -126,7 +126,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
pid_t ppid = 0;
|
||||
|
||||
if(getProcessNameAndPpid(pid, name, &ppid))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
//Common programs that are between terminal and own process, but are not the shell
|
||||
if(
|
||||
@@ -137,6 +137,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
strcasecmp(name, "sshd") == 0 ||
|
||||
strcasecmp(name, "gdb") == 0 ||
|
||||
strcasecmp(name, "lldb") == 0 ||
|
||||
strcasecmp(name, "lldb-mi") == 0 ||
|
||||
strcasecmp(name, "login") == 0 ||
|
||||
strcasecmp(name, "ltrace") == 0 ||
|
||||
strcasecmp(name, "perf") == 0 ||
|
||||
@@ -144,10 +145,24 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
strcasestr(name, "debug") != NULL ||
|
||||
strcasestr(name, "command-not-found") != NULL ||
|
||||
ffStrEndsWith(name, ".sh")
|
||||
) {
|
||||
getTerminalShell(result, ppid);
|
||||
return;
|
||||
}
|
||||
)
|
||||
return getShellInfo(result, ppid);
|
||||
|
||||
result->shellPid = (uint32_t) pid;
|
||||
ffStrbufSetS(&result->shellProcessName, name);
|
||||
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
static pid_t getTerminalInfo(FFTerminalShellResult* result, pid_t pid)
|
||||
{
|
||||
char name[256];
|
||||
name[0] = '\0';
|
||||
|
||||
pid_t ppid = 0;
|
||||
|
||||
if(getProcessNameAndPpid(pid, name, &ppid))
|
||||
return 0;
|
||||
|
||||
//Known shells
|
||||
if (
|
||||
@@ -167,17 +182,8 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
strcasecmp(name, "elvish") == 0 ||
|
||||
strcasecmp(name, "oil.ovm") == 0 ||
|
||||
(strcasecmp(name, "python") == 0 && getenv("XONSH_VERSION"))
|
||||
) {
|
||||
if (result->shellProcessName.length == 0)
|
||||
{
|
||||
result->shellPid = (uint32_t) pid;
|
||||
ffStrbufSetS(&result->shellProcessName, name);
|
||||
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
|
||||
}
|
||||
|
||||
getTerminalShell(result, ppid);
|
||||
return;
|
||||
}
|
||||
)
|
||||
return getTerminalInfo(result, ppid);
|
||||
|
||||
#ifdef __APPLE__
|
||||
// https://github.com/fastfetch-cli/fastfetch/discussions/501
|
||||
@@ -188,6 +194,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
result->terminalPid = (uint32_t) pid;
|
||||
ffStrbufSetS(&result->terminalProcessName, name);
|
||||
getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
@@ -288,6 +295,80 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
|
||||
|
||||
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
|
||||
|
||||
static void setShellInfoDetails(FFTerminalShellResult* result)
|
||||
{
|
||||
ffStrbufClear(&result->shellVersion);
|
||||
fftsGetShellVersion(&result->shellExe, result->shellExeName, &result->shellVersion);
|
||||
|
||||
if(ffStrbufEqualS(&result->shellProcessName, "pwsh"))
|
||||
ffStrbufInitStatic(&result->shellPrettyName, "PowerShell");
|
||||
else if(ffStrbufEqualS(&result->shellProcessName, "nu"))
|
||||
ffStrbufInitStatic(&result->shellPrettyName, "nushell");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->shellProcessName, "python") && getenv("XONSH_VERSION"))
|
||||
ffStrbufInitStatic(&result->shellPrettyName, "xonsh");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->shellProcessName, "oil.ovm"))
|
||||
ffStrbufInitStatic(&result->shellPrettyName, "Oils");
|
||||
else
|
||||
{
|
||||
// https://github.com/fastfetch-cli/fastfetch/discussions/280#discussioncomment-3831734
|
||||
ffStrbufInitS(&result->shellPrettyName, result->shellExeName);
|
||||
}
|
||||
}
|
||||
|
||||
static void setTerminalInfoDetails(FFTerminalShellResult* result)
|
||||
{
|
||||
if(result->terminalExeName[0] == '.' && ffStrEndsWith(result->terminalExeName, "-wrapped"))
|
||||
{
|
||||
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
|
||||
// We use terminalProcessName when detecting version and font, overriding it for simplification
|
||||
ffStrbufSetNS(
|
||||
&result->terminalProcessName,
|
||||
(uint32_t) (strlen(result->terminalExeName) - strlen(".-wrapped")),
|
||||
result->terminalExeName + 1);
|
||||
}
|
||||
|
||||
if(ffStrbufEqualS(&result->terminalProcessName, "wezterm-gui"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "WezTerm");
|
||||
if(ffStrbufStartsWithS(&result->terminalProcessName, "tmux:"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "tmux");
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
else if(ffStrbufEqualS(&result->terminalProcessName, "com.termux"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "Termux");
|
||||
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
else if(ffStrbufStartsWithS(&result->terminalProcessName, "gnome-terminal-"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "GNOME Terminal");
|
||||
else if(ffStrbufStartsWithS(&result->terminalProcessName, "kgx"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "GNOME Console");
|
||||
else if(ffStrbufEqualS(&result->terminalProcessName, "urxvt") ||
|
||||
ffStrbufEqualS(&result->terminalProcessName, "urxvtd") ||
|
||||
ffStrbufEqualS(&result->terminalProcessName, "rxvt")
|
||||
)
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "rxvt-unicode");
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
else if(ffStrbufEqualS(&result->terminalProcessName, "iTerm.app") || ffStrbufStartsWithS(&result->terminalProcessName, "iTermServer-"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "iTerm");
|
||||
else if(ffStrbufEqualS(&result->terminalProcessName, "Apple_Terminal"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "Apple Terminal");
|
||||
else if(ffStrbufEqualS(&result->terminalProcessName, "WarpTerminal"))
|
||||
ffStrbufInitStatic(&result->terminalPrettyName, "Warp");
|
||||
|
||||
#endif
|
||||
|
||||
else if(strncmp(result->terminalExeName, result->terminalProcessName.chars, result->terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
|
||||
ffStrbufInitS(&result->terminalPrettyName, result->terminalExeName);
|
||||
else
|
||||
ffStrbufInitCopy(&result->terminalPrettyName, &result->terminalProcessName);
|
||||
|
||||
ffStrbufInit(&result->terminalVersion);
|
||||
fftsGetTerminalVersion(&result->terminalProcessName, &result->terminalExe, &result->terminalVersion);
|
||||
}
|
||||
|
||||
const FFTerminalShellResult* ffDetectTerminalShell()
|
||||
{
|
||||
static FFTerminalShellResult result;
|
||||
@@ -317,78 +398,15 @@ const FFTerminalShellResult* ffDetectTerminalShell()
|
||||
result.terminalExeName = result.terminalExe.chars;
|
||||
result.terminalPid = 0;
|
||||
|
||||
getTerminalShell(&result, getppid());
|
||||
|
||||
getTerminalFromEnv(&result);
|
||||
pid_t ppid = getppid();
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
getUserShellFromEnv(&result);
|
||||
setShellInfoDetails(&result);
|
||||
|
||||
ffStrbufClear(&result.shellVersion);
|
||||
fftsGetShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion);
|
||||
|
||||
if(ffStrbufEqualS(&result.shellProcessName, "pwsh"))
|
||||
ffStrbufInitStatic(&result.shellPrettyName, "PowerShell");
|
||||
else if(ffStrbufEqualS(&result.shellProcessName, "nu"))
|
||||
ffStrbufInitStatic(&result.shellPrettyName, "nushell");
|
||||
else if(ffStrbufIgnCaseEqualS(&result.shellProcessName, "python") && getenv("XONSH_VERSION"))
|
||||
ffStrbufInitStatic(&result.shellPrettyName, "xonsh");
|
||||
else if(ffStrbufIgnCaseEqualS(&result.shellProcessName, "oil.ovm"))
|
||||
ffStrbufInitStatic(&result.shellPrettyName, "Oils");
|
||||
else
|
||||
{
|
||||
// https://github.com/fastfetch-cli/fastfetch/discussions/280#discussioncomment-3831734
|
||||
ffStrbufInitS(&result.shellPrettyName, result.shellExeName);
|
||||
}
|
||||
|
||||
if(result.terminalExeName[0] == '.' && ffStrEndsWith(result.terminalExeName, "-wrapped"))
|
||||
{
|
||||
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
|
||||
// We use terminalProcessName when detecting version and font, overriding it for simplification
|
||||
ffStrbufSetNS(
|
||||
&result.terminalProcessName,
|
||||
(uint32_t) (strlen(result.terminalExeName) - strlen(".-wrapped")),
|
||||
result.terminalExeName + 1);
|
||||
}
|
||||
|
||||
if(ffStrbufEqualS(&result.terminalProcessName, "wezterm-gui"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "WezTerm");
|
||||
if(ffStrbufStartsWithS(&result.terminalProcessName, "tmux:"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "tmux");
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "com.termux"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "Termux");
|
||||
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
else if(ffStrbufStartsWithS(&result.terminalProcessName, "gnome-terminal-"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Terminal");
|
||||
else if(ffStrbufStartsWithS(&result.terminalProcessName, "kgx"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Console");
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "urxvt") ||
|
||||
ffStrbufEqualS(&result.terminalProcessName, "urxvtd") ||
|
||||
ffStrbufEqualS(&result.terminalProcessName, "rxvt")
|
||||
)
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "rxvt-unicode");
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "iTerm.app") || ffStrbufStartsWithS(&result.terminalProcessName, "iTermServer-"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "iTerm");
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "Apple_Terminal"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "Apple Terminal");
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "WarpTerminal"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "Warp");
|
||||
|
||||
#endif
|
||||
|
||||
else if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
|
||||
ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName);
|
||||
else
|
||||
ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName);
|
||||
|
||||
ffStrbufInit(&result.terminalVersion);
|
||||
fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
|
||||
if (ppid)
|
||||
ppid = getTerminalInfo(&result, ppid);
|
||||
getTerminalFromEnv(&result);
|
||||
setTerminalInfoDetails(&result);
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
@@ -120,6 +120,19 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion);
|
||||
|
||||
result->shellPid = pid;
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "explorer"))
|
||||
{
|
||||
ffStrbufSetS(&result->shellPrettyName, "Windows Explorer"); // Started without shell
|
||||
// In this case, terminal process will be created by fastfetch itself.
|
||||
ppid = 0;
|
||||
}
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
static void setShellInfoDetails(FFTerminalShellResult* result)
|
||||
{
|
||||
if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "pwsh"))
|
||||
ffStrbufSetS(&result->shellPrettyName, "PowerShell");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "powershell"))
|
||||
@@ -131,7 +144,7 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
ffStrbufClear(&result->shellPrettyName);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE snapshot = NULL;
|
||||
while(!(snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid)) && GetLastError() == ERROR_BAD_LENGTH) {}
|
||||
while(!(snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, result->shellPid)) && GetLastError() == ERROR_BAD_LENGTH) {}
|
||||
|
||||
if(snapshot)
|
||||
{
|
||||
@@ -154,13 +167,7 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "nu"))
|
||||
ffStrbufSetS(&result->shellPrettyName, "nushell");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "explorer"))
|
||||
{
|
||||
ffStrbufSetS(&result->shellPrettyName, "Windows Explorer"); // Started without shell
|
||||
// In this case, terminal process will be created by fastfetch itself.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ppid;
|
||||
ffStrbufSetS(&result->shellPrettyName, "Windows Explorer");
|
||||
}
|
||||
|
||||
static bool getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
@@ -198,7 +205,7 @@ static bool getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
if(!term && (
|
||||
getenv("WT_SESSION") != NULL ||
|
||||
getenv("WT_PROFILE_ID") != NULL
|
||||
)) term = "Windows Terminal";
|
||||
)) term = "WindowsTerminal";
|
||||
|
||||
//Alacritty
|
||||
if(!term && (
|
||||
@@ -334,6 +341,11 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
else
|
||||
result->terminalPid = pid;
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
static void setTerminalInfoDetails(FFTerminalShellResult* result)
|
||||
{
|
||||
if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "WindowsTerminal"))
|
||||
ffStrbufSetStatic(&result->terminalPrettyName, ffStrbufContainIgnCaseS(&result->terminalExe, ".WindowsTerminalPreview_")
|
||||
? "Windows Terminal Preview"
|
||||
@@ -347,8 +359,6 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
ffStrbufSetStatic(&result->terminalPrettyName, "Windows Explorer");
|
||||
else if(ffStrbufEqualS(&result->terminalPrettyName, "wezterm-gui"))
|
||||
ffStrbufSetStatic(&result->terminalPrettyName, "WezTerm");
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
|
||||
@@ -379,12 +389,16 @@ const FFTerminalShellResult* ffDetectTerminalShell(void)
|
||||
return &result;
|
||||
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
setShellInfoDetails(&result);
|
||||
|
||||
if(ppid)
|
||||
getTerminalInfo(&result, ppid);
|
||||
|
||||
if(result.terminalProcessName.length == 0)
|
||||
getTerminalFromEnv(&result);
|
||||
|
||||
setTerminalInfoDetails(&result);
|
||||
|
||||
ffStrbufInit(&result.terminalVersion);
|
||||
fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user