ohmu
·
2026-10-15
1#include "common/printing.h"
2#include "common/jsonconfig.h"
3#include "common/strutil.h"
4#include "detection/terminalshell/terminalshell.h"
5#include "modules/shell/shell.h"
6
7bool ffPrintShell(FFShellOptions* options) {
8 const FFShellResult* result = ffDetectShell();
9
10 if (result->processName.length == 0) {
11 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect shell");
12 return false;
13 }
14
15 if (options->moduleArgs.outputFormat.length == 0) {
16 ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
17 ffStrbufWriteTo(&result->prettyName, stdout);
18
19 if (result->version.length > 0) {
20 putchar(' ');
21 ffStrbufWriteTo(&result->version, stdout);
22 }
23
24 putchar('\n');
25 } else {
26 FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
27 FF_ARG(result->processName, "process-name"),
28 FF_ARG(result->exe, "exe"),
29 FF_ARG(result->exeName, "exe-name"),
30 FF_ARG(result->version, "version"),
31 FF_ARG(result->pid, "pid"),
32 FF_ARG(result->prettyName, "pretty-name"),
33 FF_ARG(result->exePath, "exe-path"),
34 FF_ARG(result->tty, "tty"),
35 }));
36 }
37
38 return true;
39}
40
41void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module) {
42 yyjson_val *key, *val;
43 size_t idx, max;
44 yyjson_obj_foreach (module, idx, max, key, val) {
45 if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
46 continue;
47 }
48
49 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
50 }
51}
52
53[[gnu::cold]]
54void ffGenerateShellJsonConfig(FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
55 ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
56}
57
58bool ffGenerateShellJsonResult([[maybe_unused]] FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
59 const FFShellResult* result = ffDetectShell();
60
61 if (result->processName.length == 0) {
62 yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect shell");
63 return false;
64 }
65
66 yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
67 yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->exe);
68 yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->exeName);
69 yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &result->exePath);
70 yyjson_mut_obj_add_uint(doc, obj, "pid", result->pid);
71 yyjson_mut_obj_add_uint(doc, obj, "ppid", result->ppid);
72 yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->processName);
73 yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->prettyName);
74 yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->version);
75 if (result->tty >= 0) {
76 yyjson_mut_obj_add_int(doc, obj, "tty", result->tty);
77 } else {
78 yyjson_mut_obj_add_null(doc, obj, "tty");
79 }
80
81 return true;
82}
83
84void ffInitShellOptions(FFShellOptions* options) {
85 ffOptionInitModuleArg(&options->moduleArgs, "");
86}
87
88void ffDestroyShellOptions(FFShellOptions* options) {
89 ffOptionDestroyModuleArg(&options->moduleArgs);
90}
91
92FFModuleBaseInfo ffShellModuleInfo = {
93 .name = "Shell",
94 .description = "Print the current shell name and version",
95 .displayName = {
96 .en = "Shell",
97 .ar = "الصدفة",
98 .cs = "Shell",
99 .de = "Shell",
100 .es = "Shell",
101 .fi = "Komentotulkki",
102 .fr = "Shell",
103 .gl = "Shell",
104 .he = "מעטפת",
105 .id = "Shell",
106 .it = "Shell",
107 .ja = "シェル",
108 .ko = "셸",
109 .pl = "Powłoka",
110 .pt = "Shell",
111 .ru = "Оболочка",
112 .tr = "Kabuk",
113 .uk = "Оболонка",
114 .vi = "Shell",
115 .zh_CN = "命令行解释器",
116 .zh_TW = "命令列直譯器",
117 },
118 .initOptions = (void*) ffInitShellOptions,
119 .destroyOptions = (void*) ffDestroyShellOptions,
120 .parseJsonObject = (void*) ffParseShellJsonObject,
121 .printModule = (void*) ffPrintShell,
122 .generateJsonResult = (void*) ffGenerateShellJsonResult,
123 .generateJsonConfig = (void*) ffGenerateShellJsonConfig,
124 .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
125 { "Shell process name", "process-name" },
126 { "The first argument of the command line when running the shell", "exe" },
127 { "Shell base name of arg0", "exe-name" },
128 { "Shell version", "version" },
129 { "Shell pid", "pid" },
130 { "Shell pretty name", "pretty-name" },
131 { "Shell full exe path", "exe-path" },
132 { "Shell tty used", "tty" },
133 })),
134 .defaultOrder = 15,
135};