diff options
Diffstat (limited to 'src/detection/initsystem')
| -rw-r--r-- | src/detection/initsystem/initsystem.h | 13 | ||||
| -rw-r--r-- | src/detection/initsystem/initsystem_haiku.c | 35 | ||||
| -rw-r--r-- | src/detection/initsystem/initsystem_linux.c | 116 | ||||
| -rw-r--r-- | src/detection/initsystem/initsystem_nosupport.c | 5 |
4 files changed, 169 insertions, 0 deletions
diff --git a/src/detection/initsystem/initsystem.h b/src/detection/initsystem/initsystem.h new file mode 100644 index 0000000..3c59cf0 --- /dev/null +++ b/src/detection/initsystem/initsystem.h @@ -0,0 +1,13 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/initsystem/option.h" + +typedef struct FFInitSystemResult { + FFstrbuf name; + FFstrbuf exe; + FFstrbuf version; + uint32_t pid; +} FFInitSystemResult; + +const char* ffDetectInitSystem(FFInitSystemResult* result); diff --git a/src/detection/initsystem/initsystem_haiku.c b/src/detection/initsystem/initsystem_haiku.c new file mode 100644 index 0000000..04857bc --- /dev/null +++ b/src/detection/initsystem/initsystem_haiku.c @@ -0,0 +1,35 @@ +#include "initsystem.h" +#include "common/strutil.h" +#include "common/haiku/version.h" +#include "common/io.h" + +#include <OS.h> +#include <unistd.h> + +const char* ffDetectInitSystem(FFInitSystemResult* result) { + // Since it runs first, registrar does not know about it, + // so we can't query be_roster for it. + const char* path = "/boot/system/servers/launch_daemon"; + if (!ffPathExists(path, FF_PATHTYPE_FILE)) { + return "launch_daemon is not found"; + } + + ffStrbufSetStatic(&result->exe, path); + ffStrbufSetStatic(&result->name, "launch_daemon"); + result->pid = 0; + + team_info teamInfo; + int32 cookie = 0; + while (get_next_team_info(&cookie, &teamInfo) == B_OK) { + if (ffStrEquals(teamInfo.args, path)) { + result->pid = (uint32_t) teamInfo.team; + break; + } + } + + if (instance.config.general.detectVersion) { + ffGetFileVersion(path, &result->version); + } + + return NULL; +} diff --git a/src/detection/initsystem/initsystem_linux.c b/src/detection/initsystem/initsystem_linux.c new file mode 100644 index 0000000..445657b --- /dev/null +++ b/src/detection/initsystem/initsystem_linux.c @@ -0,0 +1,116 @@ +#include "initsystem.h" +#include "common/processing.h" +#include "common/binary.h" +#include "common/strutil.h" + +#include <libgen.h> +#include <unistd.h> + +FF_A_UNUSED static bool extractSystemdVersion(const char* str, uint32_t len, void* userdata) { + if (!ffStrStartsWith(str, "systemd ")) { + return true; + } + const char* pstart = str + strlen("systemd "); + const char* pend = memmem(pstart, len - strlen("systemd "), " running in ", strlen(" running in ")); + if (!pend) { + return true; + } + ffStrbufSetNS((FFstrbuf*) userdata, (uint32_t) (pend - pstart), pstart); + return false; +} + +const char* ffDetectInitSystem(FFInitSystemResult* result) { + const char* error = ffProcessGetBasicInfoLinux((int) result->pid, &result->name, NULL, NULL); + if (error) { +#ifdef __ANDROID__ + if (access("/system/bin/init", F_OK) == 0) { + ffStrbufSetStatic(&result->exe, "/system/bin/init"); + ffStrbufSetStatic(&result->name, "init"); + return NULL; + } +#endif + return error; + } + + const char* _; + // In linux /proc/1/exe is not readable + ffProcessGetInfoLinux((int) result->pid, &result->name, &result->exe, &_, NULL); + if (result->exe.chars[0] == '/') { + // In some old system, /sbin/init is a symlink + char buf[PATH_MAX]; + if (realpath(result->exe.chars, buf)) { + ffStrbufSetS(&result->exe, buf); + ffStrbufSetS(&result->name, basename(result->exe.chars)); + } + } + + if (instance.config.general.detectVersion) { +#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__GNU__) + if (ffStrbufEqualS(&result->name, "systemd")) { + ffBinaryExtractStrings(result->exe.chars, extractSystemdVersion, &result->version, (uint32_t) strlen("systemd 0.0 running in x")); + if (result->version.length == 0) { + if (ffProcessAppendStdOut(&result->version, (char* const[]) { + ffStrbufEndsWithS(&result->exe, "/systemd") ? result->exe.chars : "systemctl", // use exe path in case users have another systemd installed + "--version", + NULL, + }) == NULL && + result->version.length) { + uint32_t iStart = ffStrbufFirstIndexC(&result->version, '('); + if (iStart < result->version.length) { + uint32_t iEnd = ffStrbufNextIndexC(&result->version, iStart + 1, ')'); + ffStrbufSubstrBefore(&result->version, iEnd); + ffStrbufSubstrAfter(&result->version, iStart); + } + } + } + } else if (ffStrbufEqualS(&result->name, "dinit")) { + if (ffProcessAppendStdOut(&result->version, (char* const[]) { + ffStrbufEndsWithS(&result->exe, "/dinit") ? result->exe.chars : "dinit", + "--version", + NULL, + }) == NULL && + result->version.length) { + // Dinit version 0.18.0. + ffStrbufSubstrBeforeFirstC(&result->version, '\n'); + ffStrbufTrimRight(&result->version, '.'); + ffStrbufSubstrAfterLastC(&result->version, ' '); + } + } else if (ffStrbufEqualS(&result->name, "shepherd")) { + if (ffProcessAppendStdOut(&result->version, (char* const[]) { + ffStrbufEndsWithS(&result->exe, "/shepherd") ? result->exe.chars : "shepherd", + "--version", + NULL, + }) == NULL && + result->version.length) { + // shepherd (GNU Shepherd) 1.0.6 + // The first line in the output might not contain the version + if (!ffStrbufStartsWithS(&result->version, "shepherd")) { + ffStrbufSubstrAfterFirstC(&result->version, '\n'); + } + + ffStrbufSubstrBeforeFirstC(&result->version, '\n'); + ffStrbufSubstrAfterLastC(&result->version, ' '); + } + } +#elif __APPLE__ + if (ffStrbufEqualS(&result->name, "launchd")) { + if (ffProcessAppendStdOut(&result->version, (char* const[]) { + "/bin/launchctl", + "version", + NULL, + }) == NULL && + result->version.length) { + uint32_t iStart = ffStrbufFirstIndexS(&result->version, "Version "); + if (iStart < result->version.length) { + iStart += (uint32_t) strlen("Version"); + uint32_t iEnd = ffStrbufNextIndexC(&result->version, iStart + 1, ':'); + ffStrbufSubstrBefore(&result->version, iEnd); + ffStrbufSubstrAfter(&result->version, iStart); + } + } + } +#endif + } + + return NULL; +} diff --git a/src/detection/initsystem/initsystem_nosupport.c b/src/detection/initsystem/initsystem_nosupport.c new file mode 100644 index 0000000..e8ccb8e --- /dev/null +++ b/src/detection/initsystem/initsystem_nosupport.c @@ -0,0 +1,5 @@ +#include "initsystem.h" + +const char* ffDetectInitSystem(FF_A_UNUSED FFInitSystemResult* result) { + return "Not supported on this platform"; +} |