From 90690ba3150a8400c28ce91fe7be544cd724510e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 28 May 2024 23:46:13 +0800 Subject: [PATCH] InitSystem: add new module Fix #974 --- CMakeLists.txt | 6 + src/common/modules.c | 1 + src/common/processing.h | 4 +- src/common/processing_linux.c | 101 ++++++++----- src/detection/initsystem/initsystem.h | 12 ++ src/detection/initsystem/initsystem_linux.c | 14 ++ .../initsystem/initsystem_nosupport.c | 6 + .../terminalshell/terminalshell_linux.c | 109 +++++++------- src/modules/initsystem/initsystem.c | 134 ++++++++++++++++++ src/modules/initsystem/initsystem.h | 9 ++ src/modules/initsystem/option.h | 11 ++ src/modules/modules.h | 1 + src/modules/options.h | 1 + src/options/modules.c | 2 + src/options/modules.h | 1 + 15 files changed, 318 insertions(+), 94 deletions(-) create mode 100644 src/detection/initsystem/initsystem.h create mode 100644 src/detection/initsystem/initsystem_linux.c create mode 100644 src/detection/initsystem/initsystem_nosupport.c create mode 100644 src/modules/initsystem/initsystem.c create mode 100644 src/modules/initsystem/initsystem.h create mode 100644 src/modules/initsystem/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e531d2b87..297081458 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,6 +343,7 @@ set(LIBFASTFETCH_SRC src/modules/gpu/gpu.c src/modules/host/host.c src/modules/icons/icons.c + src/modules/initsystem/initsystem.c src/modules/gamepad/gamepad.c src/modules/kernel/kernel.c src/modules/lm/lm.c @@ -431,6 +432,7 @@ if(LINUX) src/detection/gtk_qt/gtk.c src/detection/host/host_linux.c src/detection/icons/icons_linux.c + src/detection/initsystem/initsystem_linux.c src/detection/libc/libc_linux.c src/detection/lm/lm_linux.c src/detection/loadavg/loadavg_linux.c @@ -489,6 +491,7 @@ elseif(ANDROID) src/detection/gpu/gpu_nosupport.c src/detection/host/host_android.c src/detection/icons/icons_nosupport.c + src/detection/initsystem/initsystem_linux.c src/detection/libc/libc_android.c src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_linux.c @@ -559,6 +562,7 @@ elseif(BSD) src/detection/host/host_bsd.c src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c + src/detection/initsystem/initsystem_linux.c src/detection/libc/libc_bsd.c src/detection/loadavg/loadavg_bsd.c src/detection/locale/locale_linux.c @@ -618,6 +622,7 @@ elseif(APPLE) src/detection/gpu/gpu_apple.m src/detection/host/host_apple.c src/detection/icons/icons_nosupport.c + src/detection/initsystem/initsystem_linux.c src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_bsd.c src/detection/libc/libc_apple.c @@ -676,6 +681,7 @@ elseif(WIN32) src/detection/gpu/gpu_windows.c src/detection/host/host_windows.c src/detection/icons/icons_windows.c + src/detection/initsystem/initsystem_nosupport.c src/detection/libc/libc_windows.cpp src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_nosupport.c diff --git a/src/common/modules.c b/src/common/modules.c index e7e2c20f8..9205cc0b5 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -59,6 +59,7 @@ static FFModuleBaseInfo* H[] = { static FFModuleBaseInfo* I[] = { (void*) &instance.config.modules.icons, + (void*) &instance.config.modules.initSystem, NULL, }; diff --git a/src/common/processing.h b/src/common/processing.h index 69d3ddc88..7208214db 100644 --- a/src/common/processing.h +++ b/src/common/processing.h @@ -2,6 +2,8 @@ #include "util/FFstrbuf.h" +#include + const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr); static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) @@ -24,5 +26,5 @@ static inline const char* ffProcessAppendStdErr(FFstrbuf* buffer, char* const ar bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName, FFstrbuf* exePath, bool* gui); #else void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, const char** exeName, FFstrbuf* exePath); -const char* ffProcessGetBasicInfoLinux(pid_t pid, char* name, pid_t* ppid, int32_t* tty); +const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, int32_t* tty); #endif diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index 442be9c59..2d9a82b90 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -3,6 +3,7 @@ #include "common/io/io.h" #include "common/time.h" #include "util/stringUtils.h" +#include "util/mallocHelper.h" #include #include @@ -17,6 +18,9 @@ #include #include #endif +#ifdef __APPLE__ + #include +#endif enum { FF_PIPE_BUFSIZ = 8192 }; @@ -119,20 +123,23 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons char filePath[64]; snprintf(filePath, sizeof(filePath), "/proc/%d/cmdline", (int)pid); - if(ffAppendFileBuffer(filePath, exe)) + if(ffReadFileBuffer(filePath, exe)) { - ffStrbufTrimRightSpace(exe); ffStrbufRecalculateLength(exe); //Trim the arguments + ffStrbufTrimRightSpace(exe); ffStrbufTrimLeft(exe, '-'); //Login shells start with a dash } - snprintf(filePath, sizeof(filePath), "/proc/%d/exe", (int)pid); - ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX); - ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1); - if (length > 0) // doesn't contain trailing NUL + if (exePath) { - exePath->chars[length] = '\0'; - exePath->length = (uint32_t) length; + snprintf(filePath, sizeof(filePath), "/proc/%d/exe", (int)pid); + ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX); + ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1); + if (length > 0) // doesn't contain trailing NUL + { + exePath->chars[length] = '\0'; + exePath->length = (uint32_t) length; + } } #elif defined(__APPLE__) @@ -140,7 +147,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons size_t len = 0; int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid }; if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), NULL, &len, NULL, 0) == 0) - { + {// try get arg0 #ifndef MAC_OS_X_VERSION_10_15 //don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version. len++; @@ -153,7 +160,8 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons const char* realExePath = procArgs2 + sizeof(argc); const char* arg0 = memchr(realExePath, '\0', len - (size_t) (realExePath - procArgs2)); - ffStrbufSetNS(exePath, (uint32_t) (arg0 - realExePath), realExePath); + if (exePath) + ffStrbufSetNS(exePath, (uint32_t) (arg0 - realExePath), realExePath); do arg0++; while (*arg0 == '\0'); assert(arg0 < procArgs2 + len); @@ -162,6 +170,17 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons ffStrbufSetS(exe, arg0); } } + else + { + ffStrbufEnsureFixedLengthFree(exe, PATH_MAX); + int length = proc_pidpath(pid, exe->chars, exe->allocated); + if (length > 0) + { + exe->length = (uint32_t) length; + if (exePath) + ffStrbufSet(exePath, exe); + } + } #elif defined(__FreeBSD__) @@ -170,7 +189,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons static_assert(ARG_MAX > PATH_MAX, ""); - if(sysctl( + if(exePath && sysctl( (int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}, 4, args, &size, NULL, 0 @@ -213,34 +232,46 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons *exeName = exe->chars + lastSlashIndex + 1; } -const char* ffProcessGetBasicInfoLinux(pid_t pid, char* name, pid_t* ppid, int32_t* tty) +const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, int32_t* tty) { if (pid <= 0) return "Invalid pid"; #ifdef __linux__ - char statFilePath[64]; - snprintf(statFilePath, sizeof(statFilePath), "/proc/%d/stat", (int)pid); - char buf[PROC_FILE_BUFFSIZ]; - ssize_t nRead = ffReadFileData(statFilePath, sizeof(buf) - 1, buf); - if(nRead < 0) - return "ffReadFileData(statFilePath, sizeof(buf)-1, buf) failed"; - buf[nRead] = '\0'; + char procFilePath[64]; + if (ppid) + { + snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/stat", (int)pid); + char buf[PROC_FILE_BUFFSIZ]; + ssize_t nRead = ffReadFileData(procFilePath, sizeof(buf) - 1, buf); + if(nRead < 0) + return "ffReadFileData(/proc/pid/stat, PROC_FILE_BUFFSIZ-1, buf) failed"; + buf[nRead] = '\0'; - *ppid = 0; - static_assert(sizeof(*ppid) == sizeof(int), ""); + *ppid = 0; + static_assert(sizeof(*ppid) == sizeof(int), ""); - int tty_; - if( - sscanf(buf, "%*s (%255[^)]) %*c %d %*d %*d %d", name, ppid, &tty_) < 2 || //stat (comm) state ppid pgrp session tty - !ffStrSet(name) || - *ppid == 0 - ) - return "sscanf(stat) failed"; + ffStrbufEnsureFixedLengthFree(name, 255); + int tty_; + if( + sscanf(buf, "%*s (%255[^)]) %*c %d %*d %*d %d", name->chars, ppid, &tty_) < 2 || //stat (comm) state ppid pgrp session tty + name->chars[0] == '\0' + ) + return "sscanf(stat) failed"; - if (tty) - *tty = tty_ & 0xFF; + ffStrbufRecalculateLength(name); + if (tty) + *tty = tty_ & 0xFF; + } + else + { + snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/comm", (int)pid); + ssize_t nRead = ffReadFileBuffer(procFilePath, name); + if(nRead < 0) + return "ffReadFileBuffer(/proc/pid/comm, name) failed"; + ffStrbufTrimRightSpace(name); + } #elif defined(__APPLE__) @@ -253,8 +284,9 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, char* name, pid_t* ppid, int32 )) return "sysctl(KERN_PROC_PID) failed"; - *ppid = (pid_t)proc.kp_eproc.e_ppid; - strcpy(name, proc.kp_proc.p_comm); //trancated to 16 chars + ffStrbufSetS(name, proc.kp_proc.p_comm); //trancated to 16 chars + if (ppid) + *ppid = (pid_t)proc.kp_eproc.e_ppid; if (tty) { *tty = ((proc.kp_eproc.e_tdev >> 24) & 0xFF) == 0x10 @@ -273,8 +305,9 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, char* name, pid_t* ppid, int32 )) return "sysctl(KERN_PROC_PID) failed"; - *ppid = (pid_t)proc.ki_ppid; - strcpy(name, proc.ki_comm); + ffStrbufSetS(name, proc.ki_comm); + if (ppid) + *ppid = (pid_t)proc.ki_ppid; if (tty) { if (proc.ki_tdev != NODEV && proc.ki_flag & P_CONTROLT) diff --git a/src/detection/initsystem/initsystem.h b/src/detection/initsystem/initsystem.h new file mode 100644 index 000000000..7c96fa123 --- /dev/null +++ b/src/detection/initsystem/initsystem.h @@ -0,0 +1,12 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFInitSystemResult +{ + uint32_t pid; + FFstrbuf name; + FFstrbuf exe; +} FFInitSystemResult; + +const char* ffDetectInitSystem(FFInitSystemResult* result); diff --git a/src/detection/initsystem/initsystem_linux.c b/src/detection/initsystem/initsystem_linux.c new file mode 100644 index 000000000..661f8c6f8 --- /dev/null +++ b/src/detection/initsystem/initsystem_linux.c @@ -0,0 +1,14 @@ +#include "initsystem.h" +#include "common/processing.h" + +const char* ffDetectInitSystem(FFInitSystemResult* result) +{ + const char* error = ffProcessGetBasicInfoLinux((int) result->pid, &result->name, NULL, NULL); + if (error) return error; + + const char* exeName; + + ffProcessGetInfoLinux((int) result->pid, &result->name, &result->exe, &exeName, NULL); + + return NULL; +} diff --git a/src/detection/initsystem/initsystem_nosupport.c b/src/detection/initsystem/initsystem_nosupport.c new file mode 100644 index 000000000..b22a6b33d --- /dev/null +++ b/src/detection/initsystem/initsystem_nosupport.c @@ -0,0 +1,6 @@ +#include "initsystem.h" + +const char* ffDetectInitSystem(FF_MAYBE_UNUSED FFInitSystemResult* result) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 6f6f6d804..1d0cfc6fd 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -4,7 +4,6 @@ #include "common/processing.h" #include "common/thread.h" #include "util/stringUtils.h" -#include "util/mallocHelper.h" #include #include @@ -20,9 +19,6 @@ static void setExeName(FFstrbuf* exe, const char** exeName) static pid_t getShellInfo(FFShellResult* result, pid_t pid) { - char name[256]; - name[0] = '\0'; - pid_t ppid = 0; int32_t tty = -1; @@ -35,35 +31,36 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) userShellName = instance.state.platform.userShell.chars + index + 1; } - while (ffProcessGetBasicInfoLinux(pid, name, &ppid, &tty) == NULL) + while (ffProcessGetBasicInfoLinux(pid, &result->processName, &ppid, &tty) == NULL) { - if (!ffStrEquals(userShellName, name)) + if (!ffStrbufEqualS(&result->processName, userShellName)) { //Common programs that are between terminal and own process, but are not the shell if( // tty < 0 || //A shell should connect to a tty - 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") || - ffStrEquals(name, "time") || - ffStrEquals(name, "hyfetch") || //when hyfetch uses fastfetch as backend - ffStrEquals(name, "clifm") || //https://github.com/leo-arch/clifm/issues/289 - ffStrEquals(name, "valgrind") || - ffStrContainsIgnCase(name, "debug") || - ffStrContainsIgnCase(name, "not-found") || - ffStrEndsWith(name, ".sh") + ffStrbufEqualS(&result->processName, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell + ffStrbufEqualS(&result->processName, "sudo") || + ffStrbufEqualS(&result->processName, "su") || + ffStrbufEqualS(&result->processName, "strace") || + ffStrbufEqualS(&result->processName, "sshd") || + ffStrbufEqualS(&result->processName, "gdb") || + ffStrbufEqualS(&result->processName, "lldb") || + ffStrbufEqualS(&result->processName, "lldb-mi") || + ffStrbufEqualS(&result->processName, "login") || + ffStrbufEqualS(&result->processName, "ltrace") || + ffStrbufEqualS(&result->processName, "perf") || + ffStrbufEqualS(&result->processName, "guake-wrapped") || + ffStrbufEqualS(&result->processName, "time") || + ffStrbufEqualS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend + ffStrbufEqualS(&result->processName, "clifm") || //https://github.com/leo-arch/clifm/issues/289 + ffStrbufEqualS(&result->processName, "valgrind") || + ffStrbufContainS(&result->processName, "debug") || + ffStrbufContainS(&result->processName, "not-found") || + ffStrbufEndsWithS(&result->processName, ".sh") ) { pid = ppid; + ffStrbufClear(&result->processName); continue; } } @@ -71,7 +68,6 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) result->pid = (uint32_t) pid; result->ppid = (uint32_t) ppid; result->tty = tty; - ffStrbufSetS(&result->processName, name); ffProcessGetInfoLinux(pid, &result->processName, &result->exe, &result->exeName, &result->exePath); break; } @@ -80,49 +76,47 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) { - char name[256]; - name[0] = '\0'; - pid_t ppid = 0; - while (ffProcessGetBasicInfoLinux(pid, name, &ppid, NULL) == NULL) + while (ffProcessGetBasicInfoLinux(pid, &result->processName, &ppid, NULL) == NULL) { //Known shells if ( - ffStrEquals(name, "sh") || - 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, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case - ffStrEquals(name, "login") || - ffStrEquals(name, "sshd") || - ffStrEquals(name, "clifm") || // https://github.com/leo-arch/clifm/issues/289 - ffStrEquals(name, "chezmoi") || // #762 + ffStrbufEqualS(&result->processName, "sh") || + ffStrbufEqualS(&result->processName, "ash") || + ffStrbufEqualS(&result->processName, "bash") || + ffStrbufEqualS(&result->processName, "zsh") || + ffStrbufEqualS(&result->processName, "ksh") || + ffStrbufEqualS(&result->processName, "mksh") || + ffStrbufEqualS(&result->processName, "oksh") || + ffStrbufEqualS(&result->processName, "csh") || + ffStrbufEqualS(&result->processName, "tcsh") || + ffStrbufEqualS(&result->processName, "fish") || + ffStrbufEqualS(&result->processName, "dash") || + ffStrbufEqualS(&result->processName, "pwsh") || + ffStrbufEqualS(&result->processName, "nu") || + ffStrbufEqualS(&result->processName, "git-shell") || + ffStrbufEqualS(&result->processName, "elvish") || + ffStrbufEqualS(&result->processName, "oil.ovm") || + ffStrbufEqualS(&result->processName, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case + ffStrbufEqualS(&result->processName, "login") || + ffStrbufEqualS(&result->processName, "sshd") || + ffStrbufEqualS(&result->processName, "clifm") || // https://github.com/leo-arch/clifm/issues/289 + ffStrbufEqualS(&result->processName, "chezmoi") || // #762 #ifdef __linux__ - ffStrStartsWith(name, "flatpak-") || // #707 + ffStrbufStartsWithS(&result->processName, "flatpak-") || // #707 #endif - ffStrEndsWith(name, ".sh") + ffStrbufEndsWithS(&result->processName, ".sh") ) { pid = ppid; + ffStrbufClear(&result->processName); continue; } #ifdef __APPLE__ // https://github.com/fastfetch-cli/fastfetch/discussions/501 - const char* pLeft = strstr(name, " ("); + const char* pLeft = strstr(result->processName.chars, " ("); if (pLeft) { pLeft += 2; @@ -132,7 +126,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) for (; pLeft < pRight; ++pLeft) if (*pLeft < 'a' || *pLeft > 'z') break; - if (pLeft == pRight && ffProcessGetBasicInfoLinux(ppid, name, &ppid, NULL) != NULL) + if (pLeft == pRight && ffProcessGetBasicInfoLinux(ppid, &result->processName, &ppid, NULL) != NULL) return 0; } } @@ -140,7 +134,6 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) result->pid = (uint32_t) pid; result->ppid = (uint32_t) ppid; - ffStrbufSetS(&result->processName, name); ffProcessGetInfoLinux(pid, &result->processName, &result->exe, &result->exeName, &result->exePath); break; } @@ -155,10 +148,8 @@ static bool getTerminalInfoByPidEnv(FFTerminalResult* result, const char* pidEnv pid_t pid = (pid_t) strtol(envStr, NULL, 10); result->pid = (uint32_t) pid; - char name[256]; - if (ffProcessGetBasicInfoLinux(pid, name, (pid_t*) &result->ppid, NULL) == NULL) + if (ffProcessGetBasicInfoLinux(pid, &result->processName, (pid_t*) &result->ppid, NULL) == NULL) { - ffStrbufSetS(&result->processName, name); ffProcessGetInfoLinux(pid, &result->processName, &result->exe, &result->exeName, &result->exePath); return true; } diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c new file mode 100644 index 000000000..7f378e2fd --- /dev/null +++ b/src/modules/initsystem/initsystem.c @@ -0,0 +1,134 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/initsystem/initsystem.h" +#include "modules/initsystem/initsystem.h" +#include "util/stringUtils.h" + +#define FF_INITSYSTEM_NUM_FORMAT_ARGS 3 +#define FF_INITSYSTEM_DISPLAY_NAME "Init System" + +void ffPrintInitSystem(FFInitSystemOptions* options) +{ + FFInitSystemResult result = { + .exe = ffStrbufCreate(), + .name = ffStrbufCreate(), + .pid = 1, + }; + + const char* error = ffDetectInitSystem(&result); + + if(error) + { + ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + goto exit; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&result.name, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_INITSYSTEM_NUM_FORMAT_ARGS, ((FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &result.name, "name"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result.exe, "exe"}, + {FF_FORMAT_ARG_TYPE_UINT, &result.pid, "pid"}, + })); + } + +exit: + ffStrbufDestroy(&result.name); + ffStrbufDestroy(&result.exe); +} + +bool ffParseInitSystemCommandOptions(FFInitSystemOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_INITSYSTEM_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseInitSystemJsonObject(FFInitSystemOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateInitSystemJsonConfig(FFInitSystemOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyInitSystemOptions))) FFInitSystemOptions defaultOptions; + ffInitInitSystemOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateInitSystemJsonResult(FF_MAYBE_UNUSED FFInitSystemOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFInitSystemResult result = { + .exe = ffStrbufCreate(), + .name = ffStrbufCreate(), + .pid = 1, + }; + + const char* error = ffDetectInitSystem(&result); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &result.name); + yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result.exe); + yyjson_mut_obj_add_uint(doc, obj, "pid", result.pid); + +exit: + ffStrbufDestroy(&result.name); + ffStrbufDestroy(&result.exe); +} + +void ffPrintInitSystemHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_INITSYSTEM_DISPLAY_NAME, "{1}", FF_INITSYSTEM_NUM_FORMAT_ARGS, ((const char* []) { + "init system name - name", + "init system exe path - exe", + "init system pid - pid", + })); +} + +void ffInitInitSystemOptions(FFInitSystemOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_INITSYSTEM_MODULE_NAME, + "Print init system (pid 1) name", + ffParseInitSystemCommandOptions, + ffParseInitSystemJsonObject, + ffPrintInitSystem, + ffGenerateInitSystemJsonResult, + ffPrintInitSystemHelpFormat, + ffGenerateInitSystemJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs); +} + +void ffDestroyInitSystemOptions(FFInitSystemOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/initsystem/initsystem.h b/src/modules/initsystem/initsystem.h new file mode 100644 index 000000000..718f6691b --- /dev/null +++ b/src/modules/initsystem/initsystem.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_INITSYSTEM_MODULE_NAME "InitSystem" + +void ffPrintInitSystem(FFInitSystemOptions* options); +void ffInitInitSystemOptions(FFInitSystemOptions* options); +void ffDestroyInitSystemOptions(FFInitSystemOptions* options); diff --git a/src/modules/initsystem/option.h b/src/modules/initsystem/option.h new file mode 100644 index 000000000..aa4620670 --- /dev/null +++ b/src/modules/initsystem/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFInitSystemOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFInitSystemOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 7971b4abf..aebd0ac6f 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -28,6 +28,7 @@ #include "modules/gpu/gpu.h" #include "modules/host/host.h" #include "modules/icons/icons.h" +#include "modules/initsystem/initsystem.h" #include "modules/kernel/kernel.h" #include "modules/lm/lm.h" #include "modules/loadavg/loadavg.h" diff --git a/src/modules/options.h b/src/modules/options.h index e75dd6bce..f3df14ee2 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -28,6 +28,7 @@ #include "modules/gamepad/option.h" #include "modules/gpu/option.h" #include "modules/icons/option.h" +#include "modules/initsystem/option.h" #include "modules/kernel/option.h" #include "modules/loadavg/option.h" #include "modules/locale/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index 64faf0e63..728bccf4d 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -29,6 +29,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitGamepadOptions(&options->gamepad); ffInitHostOptions(&options->host); ffInitIconsOptions(&options->icons); + ffInitInitSystemOptions(&options->initSystem); ffInitKernelOptions(&options->kernel); ffInitLMOptions(&options->lm); ffInitLoadavgOptions(&options->loadavg); @@ -97,6 +98,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyGamepadOptions(&options->gamepad); ffDestroyHostOptions(&options->host); ffDestroyIconsOptions(&options->icons); + ffDestroyInitSystemOptions(&options->initSystem); ffDestroyKernelOptions(&options->kernel); ffDestroyLMOptions(&options->lm); ffDestroyLoadavgOptions(&options->loadavg); diff --git a/src/options/modules.h b/src/options/modules.h index aeebe33fc..79e25ce2e 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -30,6 +30,7 @@ typedef struct FFOptionsModules FFGamepadOptions gamepad; FFHostOptions host; FFIconsOptions icons; + FFInitSystemOptions initSystem; FFKernelOptions kernel; FFLMOptions lm; FFLoadavgOptions loadavg;