ohmu
·
2026-10-15
1#include "common/printing.h"
2#include "common/jsonconfig.h"
3#include "common/strutil.h"
4#include "detection/host/host.h"
5#include "modules/host/host.h"
6
7bool ffPrintHost(FFHostOptions* options) {
8 bool success = false;
9 FFHostResult host;
10 ffStrbufInit(&host.family);
11 ffStrbufInit(&host.name);
12 ffStrbufInit(&host.version);
13 ffStrbufInit(&host.sku);
14 ffStrbufInit(&host.serial);
15 ffStrbufInit(&host.uuid);
16 ffStrbufInit(&host.vendor);
17
18 const char* error = ffDetectHost(&host);
19 if (error) {
20 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
21 goto exit;
22 }
23
24 if (host.name.length == 0 && host.family.length == 0) {
25 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "neither product_family nor product_name is set by O.E.M.");
26 goto exit;
27 }
28
29 if (options->moduleArgs.outputFormat.length == 0) {
30 ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
31
32 FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
33
34 if (host.name.length > 0) {
35 ffStrbufAppend(&output, &host.name);
36 } else {
37 ffStrbufAppend(&output, &host.family);
38 }
39
40 if (host.version.length > 0) {
41 ffStrbufAppendF(&output, " (%s)", host.version.chars);
42 }
43
44 ffStrbufPutTo(&output, stdout);
45 } else {
46 FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
47 FF_ARG(host.family, "family"),
48 FF_ARG(host.name, "name"),
49 FF_ARG(host.version, "version"),
50 FF_ARG(host.sku, "sku"),
51 FF_ARG(host.vendor, "vendor"),
52 FF_ARG(host.serial, "serial"),
53 FF_ARG(host.uuid, "uuid"),
54 }));
55 }
56 success = true;
57
58exit:
59 ffStrbufDestroy(&host.family);
60 ffStrbufDestroy(&host.name);
61 ffStrbufDestroy(&host.version);
62 ffStrbufDestroy(&host.sku);
63 ffStrbufDestroy(&host.serial);
64 ffStrbufDestroy(&host.uuid);
65 ffStrbufDestroy(&host.vendor);
66
67 return success;
68}
69
70void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module) {
71 yyjson_val *key, *val;
72 size_t idx, max;
73 yyjson_obj_foreach (module, idx, max, key, val) {
74 if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
75 continue;
76 }
77
78 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
79 }
80}
81
82[[gnu::cold]]
83void ffGenerateHostJsonConfig(FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
84 ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
85}
86
87bool ffGenerateHostJsonResult([[maybe_unused]] FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
88 bool success = false;
89 FFHostResult host;
90 ffStrbufInit(&host.family);
91 ffStrbufInit(&host.name);
92 ffStrbufInit(&host.version);
93 ffStrbufInit(&host.sku);
94 ffStrbufInit(&host.serial);
95 ffStrbufInit(&host.uuid);
96 ffStrbufInit(&host.vendor);
97
98 const char* error = ffDetectHost(&host);
99 if (error) {
100 yyjson_mut_obj_add_str(doc, module, "error", error);
101 goto exit;
102 }
103
104 if (host.family.length == 0 && host.name.length == 0) {
105 yyjson_mut_obj_add_str(doc, module, "error", "neither product_family nor product_name is set by O.E.M.");
106 goto exit;
107 }
108
109 yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
110 yyjson_mut_obj_add_strbuf(doc, obj, "family", &host.family);
111 yyjson_mut_obj_add_strbuf(doc, obj, "name", &host.name);
112 yyjson_mut_obj_add_strbuf(doc, obj, "version", &host.version);
113 yyjson_mut_obj_add_strbuf(doc, obj, "sku", &host.sku);
114 yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &host.vendor);
115 yyjson_mut_obj_add_strbuf(doc, obj, "serial", &host.serial);
116 yyjson_mut_obj_add_strbuf(doc, obj, "uuid", &host.uuid);
117 success = true;
118
119exit:
120 ffStrbufDestroy(&host.family);
121 ffStrbufDestroy(&host.name);
122 ffStrbufDestroy(&host.version);
123 ffStrbufDestroy(&host.sku);
124 ffStrbufDestroy(&host.serial);
125 ffStrbufDestroy(&host.uuid);
126 ffStrbufDestroy(&host.vendor);
127
128 return success;
129}
130
131void ffInitHostOptions(FFHostOptions* options) {
132 ffOptionInitModuleArg(&options->moduleArgs, "");
133}
134
135void ffDestroyHostOptions(FFHostOptions* options) {
136 ffOptionDestroyModuleArg(&options->moduleArgs);
137}
138
139FFModuleBaseInfo ffHostModuleInfo = {
140 .name = "Host",
141 .description = "Print your computer's product name",
142 .displayName = {
143 .en = "Host",
144 .ar = "المضيف",
145 .cs = "Hostitel",
146 .de = "Rechner",
147 .es = "Host",
148 .fi = "Isäntä",
149 .fr = "Hôte",
150 .gl = "Host",
151 .he = "מארח",
152 .id = "Host",
153 .it = "Host",
154 .ja = "ホスト",
155 .ko = "호스트",
156 .pl = "Host",
157 .pt = "Host",
158 .ru = "Модель",
159 .tr = "Cihaz",
160 .uk = "Хост",
161 .vi = "Máy chủ",
162 .zh_CN = "主机",
163 .zh_TW = "主機",
164 },
165 .initOptions = (void*) ffInitHostOptions,
166 .destroyOptions = (void*) ffDestroyHostOptions,
167 .parseJsonObject = (void*) ffParseHostJsonObject,
168 .printModule = (void*) ffPrintHost,
169 .generateJsonResult = (void*) ffGenerateHostJsonResult,
170 .generateJsonConfig = (void*) ffGenerateHostJsonConfig,
171 .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
172 { "Product family", "family" },
173 { "Product name", "name" },
174 { "Product version", "version" },
175 { "Product sku", "sku" },
176 { "Product vendor", "vendor" },
177 { "Product serial number", "serial" },
178 { "Product uuid", "uuid" },
179 })),
180 .defaultOrder = 4,
181};