diff --git a/CMakeLists.txt b/CMakeLists.txt index abe6a1199..3877d1a81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,6 @@ set(LIBFASTFETCH_SRC src/common/caching.c src/common/properties.c src/common/font.c - src/common/processing.c src/common/format.c src/common/parsing.c src/common/settings.c @@ -204,7 +203,6 @@ set(LIBFASTFETCH_SRC src/logo/image/im6.c src/detection/qt.c src/detection/gtk.c - src/detection/terminalShell.c src/detection/vulkan.c src/detection/datetime.c src/detection/title.c @@ -264,6 +262,15 @@ set(LIBFASTFETCH_SRC src/modules/users.c ) +if(LINUX OR APPLE OR ANDROID OR BSD) + list(APPEND LIBFASTFETCH_SRC + src/detection/users/users_linux.c + src/common/processing_linux.c + src/detection/disk/disk.c + src/detection/terminalShell/terminalShell_linux.c + ) +endif() + if(BSD OR APPLE) list(APPEND LIBFASTFETCH_SRC src/common/sysctl.c @@ -281,10 +288,8 @@ if(LINUX OR ANDROID OR BSD) list(APPEND LIBFASTFETCH_SRC src/detection/cpuUsage/cpuUsage_linux.c src/detection/disk/disk_linux.c - src/detection/disk/disk.c src/detection/poweradapter/poweradapter_linux.c src/detection/temps/temps_linux.c - src/detection/users/users_linux.c src/detection/opengl/opengl_linux.c src/detection/processes/processes_linux.c ) @@ -312,6 +317,7 @@ endif() if(WIN_MSYS) list(APPEND LIBFASTFETCH_SRC + src/common/processing_linux.c src/detection/host/host_windows.cpp src/detection/bios/bios_windows.cpp src/detection/board/board_windows.cpp @@ -329,13 +335,13 @@ if(WIN_MSYS) src/detection/cpuUsage/cpuUsage_nowait_windows.cpp src/detection/memory/memory_windows.cpp src/detection/font/font_windows.cpp + src/detection/terminalShell/terminalShell_linux.c + src/detection/terminalShell/terminalShell_windows.cpp src/util/windows/wmi.cpp # Shared src/detection/terminalfont/terminalfont_linux.c src/detection/poweradapter/poweradapter_linux.c - - # TODO src/detection/media/media_linux.c src/detection/temps/temps_linux.c ) @@ -359,11 +365,9 @@ if(APPLE) src/detection/terminalfont/terminalfont_apple.m src/detection/media/media_apple.m src/detection/disk/disk_apple.m - src/detection/disk/disk.c src/detection/wmtheme/wmtheme_apple.m src/detection/temps/temps_apple.c src/detection/font/font_apple.m - src/detection/users/users_linux.c src/detection/opengl/opengl_apple.c src/detection/processes/processes_apple.c ) diff --git a/src/common/processing.c b/src/common/processing_linux.c similarity index 100% rename from src/common/processing.c rename to src/common/processing_linux.c diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c new file mode 100644 index 000000000..f3bb64a2d --- /dev/null +++ b/src/common/processing_windows.c @@ -0,0 +1,69 @@ +#include "fastfetch.h" +#include "common/processing.h" + +#define WIN32_LEAN_AND_MEAN 1 +#include + +//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places. +const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) +{ + SECURITY_ATTRIBUTES saAttr = { + .nLength = sizeof(SECURITY_ATTRIBUTES), + .lpSecurityDescriptor = NULL, + .bInheritHandle = TRUE, + }; + + HANDLE hChildStdoutRead, hChildStdoutWrite; + if (!CreatePipe(&hChildStdoutRead, &hChildStdoutWrite, &saAttr, 0)) + return "CreatePipe() failed"; + + if (!SetHandleInformation(hChildStdoutRead, HANDLE_FLAG_INHERIT, 0)) + return "SetHandleInformation(hChildStdoutRead) failed"; + + PROCESS_INFORMATION piProcInfo = {0}; + STARTUPINFOA siStartInfo = { + .cb = sizeof(siStartInfo), + .dwFlags = STARTF_USESTDHANDLES, + .hStdOutput = hChildStdoutWrite, + }; + + FFstrbuf cmdline; + ffStrbufInit(&cmdline); + for(char* const* parg = argv; *parg; ++parg) + { + if(cmdline.length > 0) + ffStrbufAppendC(&cmdline, ' '); + ffStrbufAppendF(&cmdline, "\"%s\"", * parg); + } + + BOOL success = CreateProcessA( + NULL, // application name + cmdline.chars, // command line + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + 0, // creation flags + NULL, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &piProcInfo); // receives PROCESS_INFORMATION + + CloseHandle(hChildStdoutWrite); + if(!success) + { + CloseHandle(hChildStdoutRead); + return "CreateProcessA() failed"; + } + + char str[128]; + DWORD nRead; + while(ReadFile(hChildStdoutRead, str, sizeof(str), &nRead, NULL) && nRead > 0) + { + ffStrbufAppendNS(buffer, nRead, str); + if(nRead < sizeof(str)) + break; + } + + CloseHandle(hChildStdoutRead); + return NULL; +} diff --git a/src/detection/host/host_linux.c b/src/detection/host/host_linux.c index c518da1ec..ef9cfbf5e 100644 --- a/src/detection/host/host_linux.c +++ b/src/detection/host/host_linux.c @@ -95,7 +95,5 @@ void ffDetectHostImpl(FFHostResult* host) //On WSL, the real host can't be detected. Instead use WSL as host. if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL) ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL); - else if(getenv("MSYSTEM") != NULL && strcmp(getenv("MSYSTEM"), "MSYS") == 0) - ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_MSYS); } } diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 1eff1738f..66ab7965c 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -2,7 +2,7 @@ #include "common/properties.h" #include "common/processing.h" #include "detection/internal.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" static void detectAlacritty(const FFinstance* instance, FFTerminalFontResult* terminalFont) { FFstrbuf fontName; diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 8211ab1d2..24a9baacd 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "terminalfont.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" #include "common/io.h" #include diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m index ffe0064af..fb8c2769b 100644 --- a/src/detection/terminalfont/terminalfont_apple.m +++ b/src/detection/terminalfont/terminalfont_apple.m @@ -1,6 +1,6 @@ #include "terminalfont.h" #include "common/font.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" #include "util/apple/osascript.h" #include diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 24a62e9d5..74392b55e 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -2,7 +2,7 @@ #include "common/settings.h" #include "common/properties.h" #include "common/parsing.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" #include "detection/displayserver/displayserver.h" static const char* getSystemMonospaceFont(const FFinstance* instance) diff --git a/src/detection/terminalshell.h b/src/detection/terminalshell/terminalshell.h similarity index 100% rename from src/detection/terminalshell.h rename to src/detection/terminalshell/terminalshell.h diff --git a/src/detection/terminalShell.c b/src/detection/terminalshell/terminalshell_linux.c similarity index 96% rename from src/detection/terminalShell.c rename to src/detection/terminalshell/terminalshell_linux.c index 9ebe8bee1..a2c0a4eac 100644 --- a/src/detection/terminalShell.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -1,9 +1,9 @@ #include "fastfetch.h" #include "detection/host/host.h" -#include "detection/terminalshell.h" #include "common/io.h" #include "common/parsing.h" #include "common/processing.h" +#include "terminalshell.h" #include #include @@ -94,6 +94,7 @@ static void getTerminalShell(FFTerminalShellResult* result, const char* pid) strcasecmp(name, "ksh") == 0 || strcasecmp(name, "fish") == 0 || strcasecmp(name, "dash") == 0 || + strcasecmp(name, "pwsh") == 0 || strcasecmp(name, "git-shell") == 0 ) { ffStrbufAppendS(&result->shellProcessName, name); @@ -256,13 +257,19 @@ static void getShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* versio getShellVersionBash(exe, version); else if(strcasecmp(exeName, "zsh") == 0) getShellVersionZsh(exe, version); - else if(strcasecmp(exeName, "fish") == 0) + else if(strcasecmp(exeName, "fish") == 0 || strcasecmp(exeName, "pwsh") == 0) getShellVersionFish(exe, version); else getShellVersionGeneric(exe, exeName, version); } -const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) +const FFTerminalShellResult* +#if defined(__CYGWIN__) || defined(_WIN32) + ffDetectTerminalShellPosix +#else + ffDetectTerminalShell +#endif +(const FFinstance* instance) { FF_UNUSED(instance); diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp new file mode 100644 index 000000000..fdaf98a77 --- /dev/null +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -0,0 +1,149 @@ +extern "C" { +#include "terminalshell.h" +#include "common/processing.h" +} +#include "util/windows/wmi.hpp" + +#include +#include +#include + +struct ProcessInfo +{ + uint32_t pid; + FFstrbuf psName; +}; + +static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe) +{ + wchar_t query[256] = {}; + swprintf(query, 256, L"SELECT Name, ParentProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId = %" PRIu32, pid); + + IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, nullptr); + if(!pEnumerator) + return false; + + IWbemClassObject *pclsObj = NULL; + ULONG uReturn = 0; + + if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + { + pEnumerator->Release(); + return false; + } + + if(ppid) + { + uint64_t value; + ffGetWmiObjUnsigned(pclsObj, L"ParentProcessId", &value); + *ppid = (uint32_t) value; + } + + if(pname) + ffGetWmiObjString(pclsObj, L"Name", pname); + + if(exe) + ffGetWmiObjString(pclsObj, L"ExecutablePath", exe); + + pclsObj->Release(); + pEnumerator->Release(); + return true; +} + +static void getShellVersion(FFstrbuf* exe, FFstrbuf* version) +{ + char* const argv[] = { exe->chars, "--version", NULL }; + ffProcessAppendStdOut(version, argv); + ffStrbufTrimRight(version, '\n'); + ffStrbufSubstrAfterLastC(version, ' '); +} + +static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid) +{ + uint32_t ppid; + + if(!getProcessInfo(pid, &ppid, &result->shellProcessName, &result->shellExe)) + return 0; + result->shellExeName = result->shellExe.chars + ffStrbufLastIndexC(&result->shellExe, '\\') + 1; + + if(ffStrbufEndsWithIgnCaseS(&result->shellProcessName, ".exe")) + ffStrbufSubstrBefore(&result->shellProcessName, result->shellProcessName.length - 4); + + if(ffStrbufIgnCaseCompS(&result->shellProcessName, "pwsh") == 0) + { + ffStrbufSetS(&result->shellProcessName, "PowerShell"); + getShellVersion(&result->shellExe, &result->shellVersion); + } + else if(ffStrbufIgnCaseCompS(&result->shellProcessName, "powershell") == 0) + ffStrbufSetS(&result->shellProcessName, "Windows PowerShell"); + + return ppid; +} + +static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid) +{ + uint32_t ppid; + + if(!getProcessInfo(pid, &ppid, &result->terminalProcessName, &result->terminalExe)) + return 0; + result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\'); + + if(ffStrbufEndsWithIgnCaseS(&result->terminalProcessName, ".exe")) + result->terminalProcessName.length -= 4; + + if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "WindowsTerminal")) + ffStrbufSetS(&result->terminalProcessName, "Windows Terminal"); + else if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "conhost")) + ffStrbufSetS(&result->terminalProcessName, "Console Window Host"); + + return ppid; +} + +#ifdef __CYGWIN__ + extern "C" + const FFTerminalShellResult* ffDetectTerminalShellPosix(const FFinstance* instance); +#endif + +const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) +{ + #ifdef __CYGWIN__ + // This is hacky. + // When running inside MSYS2, the real Windows parent process doesn't exist and we must find it in Linux way ( /proc/self/xxx ) + // When running outside of MSYS2, /proc/self/xxx doesn't exist and we must find it in Windows way + if(getenv("MSYSTEM")) + return ffDetectTerminalShellPosix(instance); + #endif + + static FFTerminalShellResult result; + static bool init = false; + if(init) + return &result; + init = true; + + ffStrbufInit(&result.shellProcessName); + ffStrbufInitA(&result.shellExe, 128); + result.shellExeName = result.shellExe.chars; + ffStrbufInit(&result.shellVersion); + + ffStrbufInit(&result.terminalProcessName); + ffStrbufInitA(&result.terminalExe, 128); + result.terminalExeName = result.terminalExe.chars; + + ffStrbufInit(&result.userShellExe); + result.userShellExeName = result.userShellExe.chars; + ffStrbufInit(&result.userShellVersion); + + uint32_t ppid = GetCurrentProcessId(); + if(!getProcessInfo(ppid, &ppid, nullptr, nullptr)) + return &result; + + ppid = getShellInfo(&result, ppid); + if(ppid == 0) + return &result; + + ppid = getTerminalInfo(&result, ppid); + if(ppid == 0) + return &result; + + return &result; +} diff --git a/src/logo/logo.c b/src/logo/logo.c index e0340d571..93667ddd3 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -2,7 +2,7 @@ #include "common/io.h" #include "common/printing.h" #include "detection/os/os.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" #include #include diff --git a/src/modules/locale.c b/src/modules/locale.c index 1d1c27456..954e29383 100644 --- a/src/modules/locale.c +++ b/src/modules/locale.c @@ -2,7 +2,6 @@ #include "common/properties.h" #include "common/printing.h" #include "common/caching.h" -#include "common/processing.h" #include "common/parsing.h" #include diff --git a/src/modules/shell.c b/src/modules/shell.c index 3ea71f05e..b9486bc2c 100644 --- a/src/modules/shell.c +++ b/src/modules/shell.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" #define FF_SHELL_MODULE_NAME "Shell" #define FF_SHELL_NUM_FORMAT_ARGS 7 @@ -18,7 +18,7 @@ void ffPrintShell(FFinstance* instance) if(instance->config.shell.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shell.key); - fputs(result->shellExeName, stdout); + ffStrbufWriteTo(&result->shellProcessName, stdout); if(result->shellVersion.length > 0) { diff --git a/src/modules/terminal.c b/src/modules/terminal.c index 4d930a445..c89afbb78 100644 --- a/src/modules/terminal.c +++ b/src/modules/terminal.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/terminalshell.h" +#include "detection/terminalshell/terminalshell.h" #include @@ -20,11 +20,7 @@ void ffPrintTerminal(FFinstance* instance) if(instance->config.terminal.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminal.key); - - if(strncmp(result->terminalExeName, result->terminalProcessName.chars, result->terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName - puts(result->terminalExeName); - else - ffStrbufPutTo(&result->terminalProcessName, stdout); + ffStrbufPutTo(&result->terminalProcessName, stdout); } else {