master ohmu/fastfetch-openbsd / src / modules / os / os.c
ohmu  ·  2026-10-15
  1#include "common/printing.h"
  2#include "common/jsonconfig.h"
  3#include "common/option.h"
  4#include "common/strutil.h"
  5#include "detection/os/os.h"
  6#include "modules/os/os.h"
  7
  8#include <ctype.h>
  9
 10static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) {
 11    // Create the basic output
 12    if (os->name.length > 0) {
 13        ffStrbufAppend(result, &os->name);
 14    } else if (os->prettyName.length > 0) {
 15        ffStrbufAppend(result, &os->prettyName);
 16    } else if (os->id.length > 0) {
 17        ffStrbufAppend(result, &os->id);
 18    } else {
 19        ffStrbufAppend(result, &instance.state.platform.sysinfo.name);
 20    }
 21
 22    // Append code name if it is missing
 23    if (os->codename.length > 0 && !ffStrbufContainIgnCase(result, &os->codename)) {
 24        ffStrbufAppendC(result, ' ');
 25        ffStrbufAppend(result, &os->codename);
 26    }
 27
 28    // Append version if it is missing
 29    if (os->versionID.length > 0 && !ffStrbufContainIgnCase(result, &os->versionID)) {
 30        ffStrbufAppendC(result, ' ');
 31        ffStrbufAppend(result, &os->versionID);
 32    } else if (os->versionID.length == 0 && os->version.length > 0 && !ffStrbufContainIgnCase(result, &os->version)) {
 33        ffStrbufAppendC(result, ' ');
 34        ffStrbufAppend(result, &os->version);
 35    }
 36
 37    // Append variant if it is missing
 38    if (os->variant.length > 0 && !ffStrbufContainIgnCase(result, &os->variant)) {
 39        ffStrbufAppendS(result, " (");
 40        ffStrbufAppend(result, &os->variant);
 41        ffStrbufAppendC(result, ')');
 42    } else if (os->variant.length == 0 && os->variantID.length > 0 && !ffStrbufContainIgnCase(result, &os->variantID)) {
 43        ffStrbufAppendS(result, " (");
 44        ffStrbufAppend(result, &os->variantID);
 45        ffStrbufAppendC(result, ')');
 46    }
 47}
 48
 49bool ffPrintOS(FFOSOptions* options) {
 50    const FFOSResult* os = ffDetectOS();
 51
 52    if (os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0) {
 53        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Could not detect OS");
 54        return false;
 55    }
 56
 57    FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
 58
 59    if (options->moduleArgs.key.length == 0) {
 60        ffStrbufSetStatic(&key, FF_MODULE_GET_DISPLAY_NAME(OS));
 61    } else {
 62        FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
 63                                                                           FF_ARG(instance.state.platform.sysinfo.name, "sysname"),
 64                                                                           FF_ARG(os->name, "name"),
 65                                                                           FF_ARG(options->moduleArgs.keyIcon, "icon"),
 66                                                                           FF_ARG(FF_MODULE_GET_DISPLAY_NAME(OS), "module-name"),
 67                                                                       }));
 68    }
 69
 70    if (options->moduleArgs.outputFormat.length == 0) {
 71        FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
 72
 73        if (os->prettyName.length > 0) {
 74            ffStrbufAppend(&result, &os->prettyName);
 75        } else {
 76            buildOutputDefault(os, &result);
 77        }
 78
 79        // Append architecture if it is missing
 80        if (!ffStrbufContainIgnCase(&result, &instance.state.platform.sysinfo.architecture)) {
 81            ffStrbufAppendC(&result, ' ');
 82            ffStrbufAppend(&result, &instance.state.platform.sysinfo.architecture);
 83        }
 84
 85        ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
 86        ffStrbufPutTo(&result, stdout);
 87    } else {
 88        FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
 89                                                                                                     FF_ARG(instance.state.platform.sysinfo.name, "sysname"),
 90                                                                                                     FF_ARG(os->name, "name"),
 91                                                                                                     FF_ARG(os->prettyName, "pretty-name"),
 92                                                                                                     FF_ARG(os->id, "id"),
 93                                                                                                     FF_ARG(os->idLike, "id-like"),
 94                                                                                                     FF_ARG(os->variant, "variant"),
 95                                                                                                     FF_ARG(os->variantID, "variant-id"),
 96                                                                                                     FF_ARG(os->version, "version"),
 97                                                                                                     FF_ARG(os->versionID, "version-id"),
 98                                                                                                     FF_ARG(os->codename, "codename"),
 99                                                                                                     FF_ARG(os->buildID, "build-id"),
100                                                                                                     FF_ARG(instance.state.platform.sysinfo.architecture, "arch"),
101                                                                                                     FF_ARG(instance.state.platform.sysinfo.release, "kernel-release"),
102                                                                                                 }));
103    }
104
105    return true;
106}
107
108void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module) {
109    yyjson_val *key, *val;
110    size_t idx, max;
111    yyjson_obj_foreach (module, idx, max, key, val) {
112        if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
113            continue;
114        }
115
116        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
117    }
118}
119
120[[gnu::cold]]
121void ffGenerateOSJsonConfig(FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
122    ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
123}
124
125bool ffGenerateOSJsonResult([[maybe_unused]] FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
126    const FFOSResult* os = ffDetectOS();
127
128    if (os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0) {
129        yyjson_mut_obj_add_str(doc, module, "error", "Could not detect OS");
130        return false;
131    }
132
133    yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
134    yyjson_mut_obj_add_strbuf(doc, obj, "buildID", &os->buildID);
135    yyjson_mut_obj_add_strbuf(doc, obj, "codename", &os->codename);
136    yyjson_mut_obj_add_strbuf(doc, obj, "id", &os->id);
137    yyjson_mut_obj_add_strbuf(doc, obj, "idLike", &os->idLike);
138    yyjson_mut_obj_add_strbuf(doc, obj, "name", &os->name);
139    yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &os->prettyName);
140    yyjson_mut_obj_add_strbuf(doc, obj, "variant", &os->variant);
141    yyjson_mut_obj_add_strbuf(doc, obj, "variantID", &os->variantID);
142    yyjson_mut_obj_add_strbuf(doc, obj, "version", &os->version);
143    yyjson_mut_obj_add_strbuf(doc, obj, "versionID", &os->versionID);
144
145    return true;
146}
147
148void ffInitOSOptions(FFOSOptions* options) {
149    ffOptionInitModuleArg(&options->moduleArgs,
150#ifdef _WIN32
151        ""
152#elif __APPLE__
153        ""
154#elif __FreeBSD__
155        "󰣠"
156#elif __ANDROID__
157        ""
158#elif __linux__
159        ""
160#elif __sun
161        ""
162#elif __OpenBSD__
163        ""
164#elif __Haiku__
165        ""
166#else
167        "󰢻"
168#endif
169    );
170}
171
172void ffDestroyOSOptions(FFOSOptions* options) {
173    ffOptionDestroyModuleArg(&options->moduleArgs);
174}
175
176FFModuleBaseInfo ffOSModuleInfo = {
177    .name = "OS",
178    .description = "Print the OS or Linux distribution name and version",
179    .displayName = {
180        .en = "OS",
181        .ar = "نظام التشغيل",
182        .cs = "OS",
183        .de = "Betriebssystem",
184        .es = "Sistema operativo",
185        .fi = "Käyttöjärjestelmä",
186        .fr = "Système d'exploitation",
187        .gl = "Sistema operativo",
188        .he = "מערכת הפעלה",
189        .id = "OS",
190        .it = "Sistema operativo",
191        .ja = "オペレーティングシステム",
192        .ko = "운영 체제",
193        .pl = "System operacyjny",
194        .pt = "Sistema operacional",
195        .ru = "Операционная система",
196        .tr = "İşletim Sistemi",
197        .uk = "ОС",
198        .vi = "Hệ điều hành",
199        .zh_CN = "操作系统",
200        .zh_TW = "操作系統",
201    },
202    .initOptions = (void*) ffInitOSOptions,
203    .destroyOptions = (void*) ffDestroyOSOptions,
204    .parseJsonObject = (void*) ffParseOSJsonObject,
205    .printModule = (void*) ffPrintOS,
206    .generateJsonResult = (void*) ffGenerateOSJsonResult,
207    .generateJsonConfig = (void*) ffGenerateOSJsonConfig,
208    .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
209        { "Name of the kernel *", "sysname" },
210        { "Name of the OS *", "name" },
211        { "Pretty name of the OS, if available", "pretty-name" },
212        { "ID of the OS", "id" },
213        { "ID like of the OS", "id-like" },
214        { "Variant of the OS", "variant" },
215        { "Variant ID of the OS", "variant-id" },
216        { "Version of the OS", "version" },
217        { "Version ID of the OS", "version-id" },
218        { "Version codename of the OS", "codename" },
219        { "Build ID of the OS", "build-id" },
220        { "Architecture of the OS", "arch" },
221        { "Release of the kernel", "kernel-release" },
222    })),
223    .defaultOrder = 3,
224};