summaryrefslogtreecommitdiffstats
path: root/src/modules/uptime
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/modules/uptime
Add the files
Diffstat (limited to 'src/modules/uptime')
-rw-r--r--src/modules/uptime/option.h9
-rw-r--r--src/modules/uptime/uptime.c106
-rw-r--r--src/modules/uptime/uptime.h11
3 files changed, 126 insertions, 0 deletions
diff --git a/src/modules/uptime/option.h b/src/modules/uptime/option.h
new file mode 100644
index 0000000..34be61a
--- /dev/null
+++ b/src/modules/uptime/option.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "common/option.h"
+
+typedef struct FFUptimeOptions {
+ FFModuleArgs moduleArgs;
+} FFUptimeOptions;
+
+static_assert(sizeof(FFUptimeOptions) <= FF_OPTION_MAX_SIZE, "FFUptimeOptions size exceeds maximum allowed size");
diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c
new file mode 100644
index 0000000..e096bfc
--- /dev/null
+++ b/src/modules/uptime/uptime.c
@@ -0,0 +1,106 @@
+#include "common/duration.h"
+#include "common/printing.h"
+#include "common/jsonconfig.h"
+#include "common/time.h"
+#include "common/strutil.h"
+#include "detection/uptime/uptime.h"
+#include "modules/uptime/uptime.h"
+
+bool ffPrintUptime(FFUptimeOptions* options) {
+ FFUptimeResult result = {};
+
+ const char* error = ffDetectUptime(&result);
+
+ if (error) {
+ ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
+ return false;
+ }
+
+ uint64_t uptime = result.uptime;
+ FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
+ ffDurationAppendNum((uptime + 500) / 1000, &buffer);
+
+ if (options->moduleArgs.outputFormat.length == 0) {
+ ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
+ ffStrbufPutTo(&buffer, stdout);
+ } else {
+ uint32_t milliseconds = (uint32_t) (uptime % 1000);
+ uptime /= 1000;
+ uint32_t seconds = (uint32_t) (uptime % 60);
+ uptime /= 60;
+ uint32_t minutes = (uint32_t) (uptime % 60);
+ uptime /= 60;
+ uint32_t hours = (uint32_t) (uptime % 24);
+ uptime /= 24;
+ uint32_t days = (uint32_t) uptime;
+
+ FFTimeGetAgeResult age = ffTimeGetAge(result.bootTime, ffTimeGetNow());
+
+ FF_PRINT_FORMAT_CHECKED(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(days, "days"), FF_ARG(hours, "hours"), FF_ARG(minutes, "minutes"), FF_ARG(seconds, "seconds"), FF_ARG(milliseconds, "milliseconds"), { FF_ARG_TYPE_STRING, ffTimeToShortStr(result.bootTime), "boot-time" }, FF_ARG(age.years, "years"), FF_ARG(age.daysOfYear, "days-of-year"), FF_ARG(age.yearsFraction, "years-fraction"), FF_ARG(buffer, "formatted") }));
+ }
+
+ return true;
+}
+
+void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module) {
+ yyjson_val *key, *val;
+ size_t idx, max;
+ yyjson_obj_foreach (module, idx, max, key, val) {
+ if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
+ continue;
+ }
+
+ ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
+ }
+}
+
+void ffGenerateUptimeJsonConfig(FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
+ ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
+}
+
+bool ffGenerateUptimeJsonResult(FF_A_UNUSED FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
+ FFUptimeResult result;
+ const char* error = ffDetectUptime(&result);
+
+ if (error) {
+ yyjson_mut_obj_add_str(doc, module, "error", error);
+ return false;
+ }
+
+ yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
+ yyjson_mut_obj_add_uint(doc, obj, "uptime", result.uptime);
+ yyjson_mut_obj_add_strcpy(doc, obj, "bootTime", ffTimeToFullStr(result.bootTime));
+
+ return true;
+}
+
+void ffInitUptimeOptions(FFUptimeOptions* options) {
+ ffOptionInitModuleArg(&options->moduleArgs, "");
+}
+
+void ffDestroyUptimeOptions(FFUptimeOptions* options) {
+ ffOptionDestroyModuleArg(&options->moduleArgs);
+}
+
+FFModuleBaseInfo ffUptimeModuleInfo = {
+ .name = FF_UPTIME_MODULE_NAME,
+ .description = "Print how long the system has been running",
+ .initOptions = (void*) ffInitUptimeOptions,
+ .destroyOptions = (void*) ffDestroyUptimeOptions,
+ .parseJsonObject = (void*) ffParseUptimeJsonObject,
+ .printModule = (void*) ffPrintUptime,
+ .generateJsonResult = (void*) ffGenerateUptimeJsonResult,
+ .generateJsonConfig = (void*) ffGenerateUptimeJsonConfig,
+ .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
+ { "Days after boot", "days" },
+ { "Hours after boot", "hours" },
+ { "Minutes after boot", "minutes" },
+ { "Seconds after boot", "seconds" },
+ { "Milliseconds after boot", "milliseconds" },
+ { "Boot time in local timezone", "boot-time" },
+ { "Years integer after boot", "years" },
+ { "Days of year after boot", "days-of-year" },
+ { "Years fraction after boot", "years-fraction" },
+ { "Formatted uptime", "formatted" },
+ }))
+};
diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h
new file mode 100644
index 0000000..dec5f95
--- /dev/null
+++ b/src/modules/uptime/uptime.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "option.h"
+
+#define FF_UPTIME_MODULE_NAME "Uptime"
+
+bool ffPrintUptime(FFUptimeOptions* options);
+void ffInitUptimeOptions(FFUptimeOptions* options);
+void ffDestroyUptimeOptions(FFUptimeOptions* options);
+
+extern FFModuleBaseInfo ffUptimeModuleInfo;