summaryrefslogtreecommitdiffstats
path: root/src/detection/initsystem
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/initsystem')
-rw-r--r--src/detection/initsystem/initsystem.h13
-rw-r--r--src/detection/initsystem/initsystem_haiku.c35
-rw-r--r--src/detection/initsystem/initsystem_linux.c116
-rw-r--r--src/detection/initsystem/initsystem_nosupport.c5
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";
+}