From bfe30eec7941d0ce78a35825b87738a750185dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 17:05:06 +0800 Subject: [PATCH 001/109] Doc: updates changelog [ci skip] --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 598addb3a..7eab173fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # 2.67.1 Bugfixes: -* Fixed a `Symbol not found` error when running on macOS 10.15. (Codec, macOS) -* Fixed Alacritty font size never being parsed from the TOML config. (TerminalFont) +* Fixed a `Symbol not found` error when running on macOS 10.15. (#2499, Codec, macOS) +* Fixed Alacritty font size never being parsed from the TOML config. (#2501, TerminalFont) * Fixed bright colors incorrectly being active when the terminal uses a light theme. (#2509, Display) * Fixed Ghostty terminal font detection (TerminalFont) * Now tries to load the config with the `.ghostty` extension. (#2500) From 51f36fa4b46bf594fb8f448f6ed0ffeea078f4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 17:54:36 +0800 Subject: [PATCH 002/109] FFstrbuf: adds comments [ci skip] --- src/common/impl/FFstrbuf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/impl/FFstrbuf.c b/src/common/impl/FFstrbuf.c index 2ed3e9de8..27cb4d66a 100644 --- a/src/common/impl/FFstrbuf.c +++ b/src/common/impl/FFstrbuf.c @@ -83,6 +83,7 @@ void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free) { // Round up to the next power of 2. // If the value is already a power of 2, it will be rounded up to the next power of 2. + // allocate = __builtin_stdc_bit_ceil(allocate + 1); // Currently generates worse asm code allocate = 1U << (32 - __builtin_clz(allocate)); } From 858d3749f49febf4c3602ff0181411a3d2bdfdc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 18:27:53 +0800 Subject: [PATCH 003/109] FFstrbuf: adds `FF_STRBUF_STATIC` --- src/common/FFstrbuf.h | 2 ++ tests/strbuf.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/common/FFstrbuf.h b/src/common/FFstrbuf.h index e3722ad82..d84ed3506 100644 --- a/src/common/FFstrbuf.h +++ b/src/common/FFstrbuf.h @@ -8,6 +8,7 @@ #include #include #include "common/memrchr.h" +#include "common/arrutil.h" #ifdef FF_USE_SYSTEM_YYJSON #include @@ -628,3 +629,4 @@ static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) { bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf); #define FF_STRBUF_AUTO_DESTROY [[gnu::cleanup(ffStrbufDestroy)]] FFstrbuf +#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) ARRAY_SIZE(str) - 1, .chars = str } diff --git a/tests/strbuf.c b/tests/strbuf.c index a8e698caf..d1ca64265 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -23,6 +23,8 @@ int shouldNotBeCalled(int c) { exit(1); } +const FFstrbuf testCreateStatic = FF_STRBUF_STATIC("TEST"); + int main(void) { FFstrbuf strbuf; From 3908c39ce21bb9dbe28d643ed15d31e8f5e01bd7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 14 Aug 2026 20:38:58 +0800 Subject: [PATCH 004/109] Modules: adds l10n strings --- src/common/option.h | 17 +++++++++++++++++ src/modules/battery/battery.c | 14 ++++++++++++++ src/modules/bios/bios.c | 14 ++++++++++++++ src/modules/bluetooth/bluetooth.c | 14 ++++++++++++++ src/modules/bluetoothradio/bluetoothradio.c | 14 ++++++++++++++ src/modules/board/board.c | 14 ++++++++++++++ src/modules/bootmgr/bootmgr.c | 14 ++++++++++++++ src/modules/break/break.c | 14 ++++++++++++++ src/modules/brightness/brightness.c | 14 ++++++++++++++ src/modules/btrfs/btrfs.c | 14 ++++++++++++++ src/modules/camera/camera.c | 14 ++++++++++++++ src/modules/chassis/chassis.c | 14 ++++++++++++++ src/modules/codec/codec.c | 14 ++++++++++++++ src/modules/colors/colors.c | 14 ++++++++++++++ src/modules/command/command.c | 14 ++++++++++++++ src/modules/cpu/cpu.c | 14 ++++++++++++++ src/modules/cpucache/cpucache.c | 14 ++++++++++++++ src/modules/cpuusage/cpuusage.c | 14 ++++++++++++++ src/modules/cursor/cursor.c | 14 ++++++++++++++ src/modules/custom/custom.c | 14 ++++++++++++++ src/modules/datetime/datetime.c | 14 ++++++++++++++ src/modules/de/de.c | 14 ++++++++++++++ src/modules/disk/disk.c | 14 ++++++++++++++ src/modules/diskio/diskio.c | 14 ++++++++++++++ src/modules/display/display.c | 14 ++++++++++++++ src/modules/dns/dns.c | 14 ++++++++++++++ src/modules/editor/editor.c | 14 ++++++++++++++ src/modules/font/font.c | 14 ++++++++++++++ src/modules/gamepad/gamepad.c | 14 ++++++++++++++ src/modules/gpu/gpu.c | 14 ++++++++++++++ src/modules/host/host.c | 14 ++++++++++++++ src/modules/icons/icons.c | 14 ++++++++++++++ src/modules/initsystem/initsystem.c | 14 ++++++++++++++ src/modules/kernel/kernel.c | 14 ++++++++++++++ src/modules/keyboard/keyboard.c | 14 ++++++++++++++ src/modules/lm/lm.c | 14 ++++++++++++++ src/modules/loadavg/loadavg.c | 14 ++++++++++++++ src/modules/locale/locale.c | 14 ++++++++++++++ src/modules/localip/localip.c | 14 ++++++++++++++ src/modules/logo/logo.c | 14 ++++++++++++++ src/modules/media/media.c | 14 ++++++++++++++ src/modules/memory/memory.c | 14 ++++++++++++++ src/modules/monitor/monitor.c | 14 ++++++++++++++ src/modules/mouse/mouse.c | 14 ++++++++++++++ src/modules/netio/netio.c | 14 ++++++++++++++ src/modules/opencl/opencl.c | 14 ++++++++++++++ src/modules/opengl/opengl.c | 14 ++++++++++++++ src/modules/os/os.c | 14 ++++++++++++++ src/modules/packages/packages.c | 14 ++++++++++++++ src/modules/physicaldisk/physicaldisk.c | 14 ++++++++++++++ src/modules/physicalmemory/physicalmemory.c | 14 ++++++++++++++ src/modules/player/player.c | 14 ++++++++++++++ src/modules/poweradapter/poweradapter.c | 14 ++++++++++++++ src/modules/processes/processes.c | 14 ++++++++++++++ src/modules/publicip/publicip.c | 14 ++++++++++++++ src/modules/separator/separator.c | 14 ++++++++++++++ src/modules/shell/shell.c | 14 ++++++++++++++ src/modules/sound/sound.c | 14 ++++++++++++++ src/modules/swap/swap.c | 14 ++++++++++++++ src/modules/terminal/terminal.c | 14 ++++++++++++++ src/modules/terminalfont/terminalfont.c | 14 ++++++++++++++ src/modules/terminalsize/terminalsize.c | 14 ++++++++++++++ src/modules/terminaltheme/terminaltheme.c | 14 ++++++++++++++ src/modules/theme/theme.c | 14 ++++++++++++++ src/modules/title/title.c | 14 ++++++++++++++ src/modules/tpm/tpm.c | 14 ++++++++++++++ src/modules/uptime/uptime.c | 14 ++++++++++++++ src/modules/users/users.c | 14 ++++++++++++++ src/modules/version/version.c | 14 ++++++++++++++ src/modules/vulkan/vulkan.c | 14 ++++++++++++++ src/modules/wallpaper/wallpaper.c | 14 ++++++++++++++ src/modules/weather/weather.c | 14 ++++++++++++++ src/modules/wifi/wifi.c | 14 ++++++++++++++ src/modules/wm/wm.c | 14 ++++++++++++++ src/modules/wmtheme/wmtheme.c | 14 ++++++++++++++ src/modules/zpool/zpool.c | 14 ++++++++++++++ 76 files changed, 1067 insertions(+) diff --git a/src/common/option.h b/src/common/option.h index e2697042c..bda031690 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -18,10 +18,27 @@ typedef struct FFModuleFormatArgList { #define FF_FORMAT_ARG_LIST(list) { .args = list, .count = sizeof(list) / sizeof(FFModuleFormatArg) } +typedef struct FFModuleDisplayName { + const char* en; // English + + const char* de; // German + const char* es; // Spanish + const char* fr; // French + const char* it; // Italian + const char* ja; // Japanese + const char* ko; // Korean + const char* pl; // Polish + const char* pt_BR; // Brazilian Portuguese + const char* ru; // Russian + const char* zh_CN; // Simplified Chinese + const char* zh_TW; // Traditional Chinese +} FFModuleDisplayName; + // Must be the first field of FFModuleOptions typedef struct FFModuleBaseInfo { const char* name; const char* description; + FFModuleDisplayName displayName; // A dirty polymorphic implementation in C. // This is UB, because `void*` is not compatible with `FF*Options*`. // However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 7b8405e71..da2279624 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -299,6 +299,20 @@ void ffDestroyBatteryOptions(FFBatteryOptions* options) { FFModuleBaseInfo ffBatteryModuleInfo = { .name = FF_BATTERY_MODULE_NAME, .description = "Print battery information", + .displayName = { + .en = "Battery", + .de = "Akku", + .es = "Batería", + .fr = "Batterie", + .it = "Batteria", + .ja = "バッテリー", + .ko = "배터리", + .pl = "Bateria", + .pt_BR = "Bateria", + .ru = "Батарея", + .zh_CN = "电池", + .zh_TW = "電池", + }, .initOptions = (void*) ffInitBatteryOptions, .destroyOptions = (void*) ffDestroyBatteryOptions, .parseJsonObject = (void*) ffParseBatteryJsonObject, diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index c000080f4..b494dae21 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -132,6 +132,20 @@ void ffDestroyBiosOptions(FFBiosOptions* options) { FFModuleBaseInfo ffBiosModuleInfo = { .name = FF_BIOS_MODULE_NAME, .description = "Print first-stage bootloader information (name, version, release date, etc.)", + .displayName = { + .en = "BIOS", + .de = "BIOS", + .es = "BIOS", + .fr = "BIOS", + .it = "BIOS", + .ja = "BIOS", + .ko = "BIOS", + .pl = "BIOS", + .pt_BR = "BIOS", + .ru = "BIOS", + .zh_CN = "BIOS", + .zh_TW = "BIOS", + }, .initOptions = (void*) ffInitBiosOptions, .destroyOptions = (void*) ffDestroyBiosOptions, .parseJsonObject = (void*) ffParseBiosJsonObject, diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 42a251886..50d4de366 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -153,6 +153,20 @@ void ffDestroyBluetoothOptions(FFBluetoothOptions* options) { FFModuleBaseInfo ffBluetoothModuleInfo = { .name = FF_BLUETOOTH_MODULE_NAME, .description = "List connected Bluetooth devices", + .displayName = { + .en = "Bluetooth", + .de = "Bluetooth", + .es = "Bluetooth", + .fr = "Bluetooth", + .it = "Bluetooth", + .ja = "ブルートゥース", + .ko = "블루투스", + .pl = "Bluetooth", + .pt_BR = "Bluetooth", + .ru = "Блютус", + .zh_CN = "蓝牙", + .zh_TW = "藍牙", + }, .initOptions = (void*) ffInitBluetoothOptions, .destroyOptions = (void*) ffDestroyBluetoothOptions, .parseJsonObject = (void*) ffParseBluetoothJsonObject, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index fc113fc83..911519997 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -192,6 +192,20 @@ void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) { FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .name = FF_BLUETOOTHRADIO_MODULE_NAME, .description = "List Bluetooth radios (supported versions, vendors, etc.)", + .displayName = { + .en = "Bluetooth Radio", + .de = "Bluetooth-Adapter", + .es = "Adaptador Bluetooth", + .fr = "Adaptateur Bluetooth", + .it = "Adattatore Bluetooth", + .ja = "ブルートゥースアダプター", + .ko = "블루투스 어댑터", + .pl = "Adapter Bluetooth", + .pt_BR = "Adaptador Bluetooth", + .ru = "Блютус-адаптер", + .zh_CN = "蓝牙适配器", + .zh_TW = "藍牙配接器", + }, .initOptions = (void*) ffInitBluetoothRadioOptions, .destroyOptions = (void*) ffDestroyBluetoothRadioOptions, .parseJsonObject = (void*) ffParseBluetoothRadioJsonObject, diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 1a85ea393..070070a01 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -110,6 +110,20 @@ void ffDestroyBoardOptions(FFBoardOptions* options) { FFModuleBaseInfo ffBoardModuleInfo = { .name = FF_BOARD_MODULE_NAME, .description = "Print motherboard name and other information", + .displayName = { + .en = "Board", + .de = "Mainboard", + .es = "Placa base", + .fr = "Carte mère", + .it = "Scheda madre", + .ja = "マザーボード", + .ko = "메인보드", + .pl = "Płyta główna", + .pt_BR = "Placa-mãe", + .ru = "Материнская плата", + .zh_CN = "主板", + .zh_TW = "主機板", + }, .initOptions = (void*) ffInitBoardOptions, .destroyOptions = (void*) ffDestroyBoardOptions, .parseJsonObject = (void*) ffParseBoardJsonObject, diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 494885fd6..037de24bd 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -105,6 +105,20 @@ void ffDestroyBootmgrOptions(FFBootmgrOptions* options) { FFModuleBaseInfo ffBootmgrModuleInfo = { .name = FF_BOOTMGR_MODULE_NAME, .description = "Print second-stage bootloader information (name, firmware, etc.)", + .displayName = { + .en = "Boot Manager", + .de = "Boot-Manager", + .es = "Administrador de arranque", + .fr = "Gestionnaire de démarrage", + .it = "Gestore di avvio", + .ja = "ブートマネージャー", + .ko = "부트 매니저", + .pl = "Menedżer rozruchu", + .pt_BR = "Gerenciador de inicialização", + .ru = "Менеджер загрузки", + .zh_CN = "启动管理器", + .zh_TW = "啟動管理器", + }, .initOptions = (void*) ffInitBootmgrOptions, .destroyOptions = (void*) ffDestroyBootmgrOptions, .parseJsonObject = (void*) ffParseBootmgrJsonObject, diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 011458a28..c627f339b 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -29,6 +29,20 @@ void ffDestroyBreakOptions([[maybe_unused]] FFBreakOptions* options) { FFModuleBaseInfo ffBreakModuleInfo = { .name = FF_BREAK_MODULE_NAME, .description = "Print an empty line", + .displayName = { + .en = "Break", + .de = "Umbruch", + .es = "Salto de línea", + .fr = "Saut de ligne", + .it = "Interruzione", + .ja = "改行", + .ko = "줄 바꿈", + .pl = "Przerwa", + .pt_BR = "Quebra", + .ru = "Разрыв", + .zh_CN = "换行", + .zh_TW = "換行", + }, .initOptions = (void*) ffInitBreakOptions, .destroyOptions = (void*) ffDestroyBreakOptions, .parseJsonObject = (void*) ffParseBreakJsonObject, diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 479a2ccb9..835711c2c 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -192,6 +192,20 @@ void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { FFModuleBaseInfo ffBrightnessModuleInfo = { .name = FF_BRIGHTNESS_MODULE_NAME, .description = "Print the current brightness level of your monitors", + .displayName = { + .en = "Brightness", + .de = "Helligkeit", + .es = "Brillo", + .fr = "Luminosité", + .it = "Luminosità", + .ja = "明るさ", + .ko = "밝기", + .pl = "Jasność", + .pt_BR = "Brilho", + .ru = "Яркость", + .zh_CN = "亮度", + .zh_TW = "亮度", + }, .initOptions = (void*) ffInitBrightnessOptions, .destroyOptions = (void*) ffDestroyBrightnessOptions, .parseJsonObject = (void*) ffParseBrightnessJsonObject, diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 21068e85d..12ed8977b 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -200,6 +200,20 @@ void ffDestroyBtrfsOptions(FFBtrfsOptions* options) { FFModuleBaseInfo ffBtrfsModuleInfo = { .name = FF_BTRFS_MODULE_NAME, .description = "Print Linux BTRFS volumes", + .displayName = { + .en = "BTRFS", + .de = "BTRFS", + .es = "BTRFS", + .fr = "BTRFS", + .it = "BTRFS", + .ja = "BTRFS", + .ko = "BTRFS", + .pl = "BTRFS", + .pt_BR = "BTRFS", + .ru = "BTRFS", + .zh_CN = "BTRFS", + .zh_TW = "BTRFS", + }, .initOptions = (void*) ffInitBtrfsOptions, .destroyOptions = (void*) ffDestroyBtrfsOptions, .parseJsonObject = (void*) ffParseBtrfsJsonObject, diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 02c454bbb..4a35509c0 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -117,6 +117,20 @@ void ffDestroyCameraOptions(FFCameraOptions* options) { FFModuleBaseInfo ffCameraModuleInfo = { .name = FF_CAMERA_MODULE_NAME, .description = "Print available cameras", + .displayName = { + .en = "Camera", + .de = "Kamera", + .es = "Cámara", + .fr = "Caméra", + .it = "Fotocamera", + .ja = "カメラ", + .ko = "카메라", + .pl = "Kamera", + .pt_BR = "Câmera", + .ru = "Камера", + .zh_CN = "摄像头", + .zh_TW = "攝像頭", + }, .initOptions = (void*) ffInitCameraOptions, .destroyOptions = (void*) ffDestroyCameraOptions, .parseJsonObject = (void*) ffParseCameraJsonObject, diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 9b5b21e7a..2a88c5c89 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -112,6 +112,20 @@ void ffDestroyChassisOptions(FFChassisOptions* options) { FFModuleBaseInfo ffChassisModuleInfo = { .name = FF_CHASSIS_MODULE_NAME, .description = "Print chassis type information (desktop, laptop, etc.)", + .displayName = { + .en = "Chassis", + .de = "Gehäuse", + .es = "Chasis", + .fr = "Châssis", + .it = "Telaio", + .ja = "シャーシ", + .ko = "섀시", + .pl = "Obudowa", + .pt_BR = "Chassi", + .ru = "Шасси", + .zh_CN = "机箱", + .zh_TW = "機箱", + }, .initOptions = (void*) ffInitChassisOptions, .destroyOptions = (void*) ffDestroyChassisOptions, .parseJsonObject = (void*) ffParseChassisJsonObject, diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index a9a465bf8..f55ed20e5 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -253,6 +253,20 @@ void ffDestroyCodecOptions(FFCodecOptions* options) { FFModuleBaseInfo ffCodecModuleInfo = { .name = FF_CODEC_MODULE_NAME, .description = "Print hardware video acceleration codec types (decode / encode)", + .displayName = { + .en = "Codec", + .de = "Codec", + .es = "Códec", + .fr = "Codec", + .it = "Codec", + .ja = "コーデック", + .ko = "코덱", + .pl = "Kodek", + .pt_BR = "Codec", + .ru = "Кодек", + .zh_CN = "编解码器", + .zh_TW = "編解碼器", + }, .initOptions = (void*) ffInitCodecOptions, .destroyOptions = (void*) ffDestroyCodecOptions, .parseJsonObject = (void*) ffParseCodecJsonObject, diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 8d225d4bf..ba6890c67 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -297,6 +297,20 @@ void ffDestroyColorsOptions(FFColorsOptions* options) { FFModuleBaseInfo ffColorsModuleInfo = { .name = FF_COLORS_MODULE_NAME, .description = "Display the terminal's 16-color palette", + .displayName = { + .en = "Colors", + .de = "Farben", + .es = "Colores", + .fr = "Couleurs", + .it = "Colori", + .ja = "色", + .ko = "색상", + .pl = "Kolory", + .pt_BR = "Cores", + .ru = "Цвета", + .zh_CN = "颜色", + .zh_TW = "顏色", + }, .initOptions = (void*) ffInitColorsOptions, .destroyOptions = (void*) ffDestroyColorsOptions, .parseJsonObject = (void*) ffParseColorsJsonObject, diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 4de947a79..b86da3a17 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -155,6 +155,20 @@ void ffDestroyCommandOptions(FFCommandOptions* options) { FFModuleBaseInfo ffCommandModuleInfo = { .name = FF_COMMAND_MODULE_NAME, .description = "Run custom shell scripts", + .displayName = { + .en = "Command", + .de = "Befehl", + .es = "Comando", + .fr = "Commande", + .it = "Comando", + .ja = "コマンド", + .ko = "명령어", + .pl = "Polecenie", + .pt_BR = "Comando", + .ru = "Команда", + .zh_CN = "命令", + .zh_TW = "命令", + }, .initOptions = (void*) ffInitCommandOptions, .destroyOptions = (void*) ffDestroyCommandOptions, .parseJsonObject = (void*) ffParseCommandJsonObject, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 2716b2e03..5cccddba2 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -253,6 +253,20 @@ void ffDestroyCPUOptions(FFCPUOptions* options) { FFModuleBaseInfo ffCPUModuleInfo = { .name = FF_CPU_MODULE_NAME, .description = "Print CPU name, frequency, etc.", + .displayName = { + .en = "CPU", + .de = "CPU", + .es = "CPU", + .fr = "CPU", + .it = "CPU", + .ja = "CPU", + .ko = "CPU", + .pl = "CPU", + .pt_BR = "CPU", + .ru = "CPU", + .zh_CN = "CPU", + .zh_TW = "CPU", + }, .initOptions = (void*) ffInitCPUOptions, .destroyOptions = (void*) ffDestroyCPUOptions, .parseJsonObject = (void*) ffParseCPUJsonObject, diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 7dd39d1cb..4fe29a735 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -225,6 +225,20 @@ void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options) { FFModuleBaseInfo ffCPUCacheModuleInfo = { .name = FF_CPUCACHE_MODULE_NAME, .description = "Print CPU cache sizes", + .displayName = { + .en = "CPU Cache", + .de = "CPU-Cache", + .es = "Caché de CPU", + .fr = "Cache CPU", + .it = "Cache CPU", + .ja = "CPUキャッシュ", + .ko = "CPU 캐시", + .pl = "Pamięć podręczna CPU", + .pt_BR = "Cache da CPU", + .ru = "Кэш процессора", + .zh_CN = "CPU缓存", + .zh_TW = "CPU快取記憶體", + }, .initOptions = (void*) ffInitCPUCacheOptions, .destroyOptions = (void*) ffDestroyCPUCacheOptions, .parseJsonObject = (void*) ffParseCPUCacheJsonObject, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index ea592a273..d9d342bb9 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -183,6 +183,20 @@ void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) { FFModuleBaseInfo ffCPUUsageModuleInfo = { .name = FF_CPUUSAGE_MODULE_NAME, .description = "Print CPU usage. Collecting data takes some time", + .displayName = { + .en = "CPU Usage", + .de = "CPU-Auslastung", + .es = "Uso del CPU", + .fr = "Utilisation du CPU", + .it = "Utilizzo della CPU", + .ja = "CPU使用率", + .ko = "CPU 사용량", + .pl = "Użycie CPU", + .pt_BR = "Uso da CPU", + .ru = "Использование ЦП", + .zh_CN = "CPU使用率", + .zh_TW = "CPU使用率", + }, .initOptions = (void*) ffInitCPUUsageOptions, .destroyOptions = (void*) ffDestroyCPUUsageOptions, .parseJsonObject = (void*) ffParseCPUUsageJsonObject, diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 1be3ac6e3..74c8c65e5 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -102,6 +102,20 @@ void ffDestroyCursorOptions(FFCursorOptions* options) { FFModuleBaseInfo ffCursorModuleInfo = { .name = FF_CURSOR_MODULE_NAME, .description = "Print cursor style name", + .displayName = { + .en = "Cursor", + .de = "Mauszeiger", + .es = "Cursor", + .fr = "Curseur", + .it = "Cursore", + .ja = "カーソル", + .ko = "커서", + .pl = "Kursor", + .pt_BR = "Cursor", + .ru = "Курсор", + .zh_CN = "光标", + .zh_TW = "游標", + }, .initOptions = (void*) ffInitCursorOptions, .destroyOptions = (void*) ffDestroyCursorOptions, .parseJsonObject = (void*) ffParseCursorJsonObject, diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 054f3704c..0806be5b5 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -37,6 +37,20 @@ void ffDestroyCustomOptions(FFCustomOptions* options) { FFModuleBaseInfo ffCustomModuleInfo = { .name = FF_CUSTOM_MODULE_NAME, .description = "Print a custom string, with or without key", + .displayName = { + .en = "Custom", + .de = "Benutzerdefiniert", + .es = "Personalizado", + .fr = "Personnalisé", + .it = "Personalizzato", + .ja = "カスタム", + .ko = "사용자 정의", + .pl = "Niestandardowy", + .pt_BR = "Personalizado", + .ru = "Пользовательский", + .zh_CN = "自定义", + .zh_TW = "自訂", + }, .initOptions = (void*) ffInitCustomOptions, .destroyOptions = (void*) ffDestroyCustomOptions, .parseJsonObject = (void*) ffParseCustomJsonObject, diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 14e3b8251..b8bbb6d43 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -154,6 +154,20 @@ void ffDestroyDateTimeOptions(FFDateTimeOptions* options) { FFModuleBaseInfo ffDateTimeModuleInfo = { .name = FF_DATETIME_MODULE_NAME, .description = "Print the current date and time", + .displayName = { + .en = "Date & Time", + .de = "Datum & Uhrzeit", + .es = "Fecha y hora", + .fr = "Date et heure", + .it = "Data e ora", + .ja = "日付と時刻", + .ko = "날짜/시간", + .pl = "Data i godzina", + .pt_BR = "Data e hora", + .ru = "Дата и время", + .zh_CN = "日期时间", + .zh_TW = "日期時間", + }, .initOptions = (void*) ffInitDateTimeOptions, .destroyOptions = (void*) ffDestroyDateTimeOptions, .parseJsonObject = (void*) ffParseDateTimeJsonObject, diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 8e301fa32..3111343d7 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -84,6 +84,20 @@ void ffDestroyDEOptions(FFDEOptions* options) { FFModuleBaseInfo ffDEModuleInfo = { .name = FF_DE_MODULE_NAME, .description = "Print desktop environment name", + .displayName = { + .en = "Desktop Environment", + .de = "Desktop-Umgebung", + .es = "Entorno de Escritorio", + .fr = "Environnement de Bureau", + .it = "Ambiente Desktop", + .ja = "デスクトップ環境", + .ko = "데스크탑 환경", + .pl = "Środowisko graficzne", + .pt_BR = "Ambiente de desktop", + .ru = "Рабочая среда", + .zh_CN = "桌面环境", + .zh_TW = "桌面環境", + }, .initOptions = (void*) ffInitDEOptions, .destroyOptions = (void*) ffDestroyDEOptions, .parseJsonObject = (void*) ffParseDEJsonObject, diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 74b648855..891d2af61 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -453,6 +453,20 @@ void ffDestroyDiskOptions(FFDiskOptions* options) { FFModuleBaseInfo ffDiskModuleInfo = { .name = FF_DISK_MODULE_NAME, .description = "Print partitions, space usage, file system, etc", + .displayName = { + .en = "Disk", + .de = "Festplatte", + .es = "Disco", + .fr = "Disque", + .it = "Disco", + .ja = "ディスク", + .ko = "디스크", + .pl = "Dysk", + .pt_BR = "Disco", + .ru = "Диск", + .zh_CN = "磁盘", + .zh_TW = "磁碟", + }, .initOptions = (void*) ffInitDiskOptions, .destroyOptions = (void*) ffDestroyDiskOptions, .parseJsonObject = (void*) ffParseDiskJsonObject, diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 372910d10..5f31a1eb1 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -174,6 +174,20 @@ void ffDestroyDiskIOOptions(FFDiskIOOptions* options) { FFModuleBaseInfo ffDiskIOModuleInfo = { .name = FF_DISKIO_MODULE_NAME, .description = "Print physical disk I/O throughput", + .displayName = { + .en = "Disk I/O", + .de = "Festplatten I/O", + .es = "E/S de disco", + .fr = "Entrée/Sortie disque", + .it = "I/O del disco", + .ja = "ディスク I/O", + .ko = "디스크 I/O", + .pl = "Dysk I/O", + .pt_BR = "Disco I/O", + .ru = "Диск I/O", + .zh_CN = "磁盘 I/O", + .zh_TW = "磁碟 I/O", + }, .initOptions = (void*) ffInitDiskIOOptions, .destroyOptions = (void*) ffDestroyDiskIOOptions, .parseJsonObject = (void*) ffParseDiskIOJsonObject, diff --git a/src/modules/display/display.c b/src/modules/display/display.c index eceb9a2d1..e6870538a 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -413,6 +413,20 @@ void ffDestroyDisplayOptions(FFDisplayOptions* options) { FFModuleBaseInfo ffDisplayModuleInfo = { .name = FF_DISPLAY_MODULE_NAME, .description = "Print resolutions, refresh rates, etc", + .displayName = { + .en = "Display", + .de = "Anzeige", + .es = "Pantalla", + .fr = "Écran", + .it = "Display", + .ja = "ディスプレイ", + .ko = "디스플레이", + .pl = "Wyświetlacz", + .pt_BR = "Tela", + .ru = "Дисплей", + .zh_CN = "显示器", + .zh_TW = "顯示器", + }, .initOptions = (void*) ffInitDisplayOptions, .destroyOptions = (void*) ffDestroyDisplayOptions, .parseJsonObject = (void*) ffParseDisplayJsonObject, diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 396c3bd43..7524434c6 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -136,6 +136,20 @@ void ffDestroyDNSOptions(FFDNSOptions* options) { FFModuleBaseInfo ffDNSModuleInfo = { .name = FF_DNS_MODULE_NAME, .description = "Print configured DNS servers", + .displayName = { + .en = "DNS", + .de = "DNS", + .es = "DNS", + .fr = "DNS", + .it = "DNS", + .ja = "DNS", + .ko = "DNS", + .pl = "DNS", + .pt_BR = "DNS", + .ru = "DNS", + .zh_CN = "DNS", + .zh_TW = "DNS", + }, .initOptions = (void*) ffInitDNSOptions, .destroyOptions = (void*) ffDestroyDNSOptions, .parseJsonObject = (void*) ffParseDNSJsonObject, diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 342b31812..b1a7438fc 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -105,6 +105,20 @@ void ffDestroyEditorOptions(FFEditorOptions* options) { FFModuleBaseInfo ffEditorModuleInfo = { .name = FF_EDITOR_MODULE_NAME, .description = "Print information about the default editor ($VISUAL or $EDITOR)", + .displayName = { + .en = "Editor", + .de = "Editor", + .es = "Editor", + .fr = "Éditeur", + .it = "Editor", + .ja = "エディター", + .ko = "편집기", + .pl = "Edytor", + .pt_BR = "Editor", + .ru = "Редактор", + .zh_CN = "编辑器", + .zh_TW = "編輯器", + }, .initOptions = (void*) ffInitEditorOptions, .destroyOptions = (void*) ffDestroyEditorOptions, .parseJsonObject = (void*) ffParseEditorJsonObject, diff --git a/src/modules/font/font.c b/src/modules/font/font.c index be940b32d..9763f257d 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -97,6 +97,20 @@ void ffDestroyFontOptions(FFFontOptions* options) { FFModuleBaseInfo ffFontModuleInfo = { .name = FF_FONT_MODULE_NAME, .description = "Print system font names", + .displayName = { + .en = "Font", + .de = "Schriftart", + .es = "Fuente", + .fr = "Police", + .it = "Carattere", + .ja = "フォント", + .ko = "글꼴", + .pl = "Czcionka", + .pt_BR = "Fonte", + .ru = "Шрифт", + .zh_CN = "字体", + .zh_TW = "字型", + }, .initOptions = (void*) ffInitFontOptions, .destroyOptions = (void*) ffDestroyFontOptions, .parseJsonObject = (void*) ffParseFontJsonObject, diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index f3c3bdfe4..8eb2cf720 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -191,6 +191,20 @@ void ffDestroyGamepadOptions(FFGamepadOptions* options) { FFModuleBaseInfo ffGamepadModuleInfo = { .name = FF_GAMEPAD_MODULE_NAME, .description = "List connected gamepads", + .displayName = { + .en = "Gamepad", + .de = "Gamepad", + .es = "Gamepad", + .fr = "Manette", + .it = "Gamepad", + .ja = "ゲームパッド", + .ko = "게임패드", + .pl = "Gamepad", + .pt_BR = "Gamepad", + .ru = "Геймпад", + .zh_CN = "游戏手柄", + .zh_TW = "遊戲手把", + }, .initOptions = (void*) ffInitGamepadOptions, .destroyOptions = (void*) ffDestroyGamepadOptions, .parseJsonObject = (void*) ffParseGamepadJsonObject, diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 19ba8c868..b11615464 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -481,6 +481,20 @@ void ffDestroyGPUOptions(FFGPUOptions* options) { FFModuleBaseInfo ffGPUModuleInfo = { .name = FF_GPU_MODULE_NAME, .description = "Print GPU names, memory sizes, types, etc", + .displayName = { + .en = "GPU", + .de = "GPU", + .es = "GPU", + .fr = "GPU", + .it = "GPU", + .ja = "GPU", + .ko = "GPU", + .pl = "GPU", + .pt_BR = "GPU", + .ru = "GPU", + .zh_CN = "显卡", + .zh_TW = "顯卡", + }, .initOptions = (void*) ffInitGPUOptions, .destroyOptions = (void*) ffDestroyGPUOptions, .parseJsonObject = (void*) ffParseGPUJsonObject, diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 041ab712e..5a2e2a856 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -138,6 +138,20 @@ void ffDestroyHostOptions(FFHostOptions* options) { FFModuleBaseInfo ffHostModuleInfo = { .name = FF_HOST_MODULE_NAME, .description = "Print your computer's product name", + .displayName = { + .en = "Host", + .de = "Rechner", + .es = "Host", + .fr = "Hôte", + .it = "Host", + .ja = "ホスト", + .ko = "호스트", + .pl = "Host", + .pt_BR = "Host", + .ru = "Хост", + .zh_CN = "主机", + .zh_TW = "主機", + }, .initOptions = (void*) ffInitHostOptions, .destroyOptions = (void*) ffDestroyHostOptions, .parseJsonObject = (void*) ffParseHostJsonObject, diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 15dea0928..971a9655d 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -96,6 +96,20 @@ void ffDestroyIconsOptions(FFIconsOptions* options) { FFModuleBaseInfo ffIconsModuleInfo = { .name = FF_ICONS_MODULE_NAME, .description = "Print icon style name", + .displayName = { + .en = "Icons", + .de = "Symbole", + .es = "Iconos", + .fr = "Icônes", + .it = "Icone", + .ja = "アイコン", + .ko = "아이콘", + .pl = "Ikony", + .pt_BR = "Ícones", + .ru = "Иконки", + .zh_CN = "图标", + .zh_TW = "圖示", + }, .initOptions = (void*) ffInitIconsOptions, .destroyOptions = (void*) ffDestroyIconsOptions, .parseJsonObject = (void*) ffParseIconsJsonObject, diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index 7a02e0309..a6421f9f7 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -105,6 +105,20 @@ void ffDestroyInitSystemOptions(FFInitSystemOptions* options) { FFModuleBaseInfo ffInitSystemModuleInfo = { .name = FF_INITSYSTEM_MODULE_NAME, .description = "Print init system (pid 1) name and version", + .displayName = { + .en = "Init System", + .de = "Init-System", + .es = "Sistema de inicio", + .fr = "Système d'init", + .it = "Sistema di init", + .ja = "initシステム", + .ko = "초기화 시스템", + .pl = "System init", + .pt_BR = "Sistema de inicialização", + .ru = "Init-система", + .zh_CN = "Init 系统", + .zh_TW = "Init 系統", + }, .initOptions = (void*) ffInitInitSystemOptions, .destroyOptions = (void*) ffDestroyInitSystemOptions, .parseJsonObject = (void*) ffParseInitSystemJsonObject, diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 9ae5878df..5cd76a0bb 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -64,6 +64,20 @@ void ffDestroyKernelOptions(FFKernelOptions* options) { FFModuleBaseInfo ffKernelModuleInfo = { .name = FF_KERNEL_MODULE_NAME, .description = "Print system kernel version", + .displayName = { + .en = "Kernel", + .de = "Kernel", + .es = "Kernel", + .fr = "Kernel", + .it = "Kernel", + .ja = "カーネル", + .ko = "커널", + .pl = "Jądro", + .pt_BR = "Kernel", + .ru = "Ядро", + .zh_CN = "内核", + .zh_TW = "核心", + }, .initOptions = (void*) ffInitKernelOptions, .destroyOptions = (void*) ffDestroyKernelOptions, .parseJsonObject = (void*) ffParseKernelJsonObject, diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 76e6c36f9..00bfb1664 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -151,6 +151,20 @@ void ffDestroyKeyboardOptions(FFKeyboardOptions* options) { FFModuleBaseInfo ffKeyboardModuleInfo = { .name = FF_KEYBOARD_MODULE_NAME, .description = "List connected keyboards", + .displayName = { + .en = "Keyboard", + .de = "Tastatur", + .es = "Teclado", + .fr = "Clavier", + .it = "Tastiera", + .ja = "キーボード", + .ko = "키보드", + .pl = "Klawiatura", + .pt_BR = "Teclado", + .ru = "Клавиатура", + .zh_CN = "键盘", + .zh_TW = "鍵盤", + }, .initOptions = (void*) ffInitKeyboardOptions, .destroyOptions = (void*) ffDestroyKeyboardOptions, .parseJsonObject = (void*) ffParseKeyboardJsonObject, diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index ed945bad4..8bfe44442 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -108,6 +108,20 @@ void ffDestroyLMOptions(FFLMOptions* options) { FFModuleBaseInfo ffLMModuleInfo = { .name = FF_LM_MODULE_NAME, .description = "Print login manager (desktop manager) name and version", + .displayName = { + .en = "Login Manager", + .de = "Anmeldemanager", + .es = "Administrador de inicio de sesión", + .fr = "Gestionnaire de connexion", + .it = "Gestore di accesso", + .ja = "ログインマネージャー", + .ko = "로그인 관리자", + .pl = "Menedżer logowania", + .pt_BR = "Gerenciador de login", + .ru = "Менеджер входа", + .zh_CN = "登录管理器", + .zh_TW = "登入管理器", + }, .initOptions = (void*) ffInitLMOptions, .destroyOptions = (void*) ffDestroyLMOptions, .parseJsonObject = (void*) ffParseLMJsonObject, diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index a6fb6f800..8f6a8ed85 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -150,6 +150,20 @@ void ffDestroyLoadavgOptions(FFLoadavgOptions* options) { FFModuleBaseInfo ffLoadavgModuleInfo = { .name = FF_LOADAVG_MODULE_NAME, .description = "Print system load averages", + .displayName = { + .en = "Load Average", + .de = "Systemlast", + .es = "Promedio de carga", + .fr = "Charge moyenne", + .it = "Carico medio", + .ja = "ロードアベレージ", + .ko = "시스템 부하 평균", + .pl = "Średnie obciążenie", + .pt_BR = "Média de carga", + .ru = "Средняя нагрузка", + .zh_CN = "系统负载", + .zh_TW = "系統負載", + }, .initOptions = (void*) ffInitLoadavgOptions, .destroyOptions = (void*) ffDestroyLoadavgOptions, .parseJsonObject = (void*) ffParseLoadavgJsonObject, diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index cb9c8e7ec..4bc3e9658 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -69,6 +69,20 @@ void ffDestroyLocaleOptions(FFLocaleOptions* options) { FFModuleBaseInfo ffLocaleModuleInfo = { .name = FF_LOCALE_MODULE_NAME, .description = "Print system locale name", + .displayName = { + .en = "Locale", + .de = "Sprachraum", + .es = "Configuración regional", + .fr = "Paramètres régionaux", + .it = "Impostazioni locali", + .ja = "ロケール", + .ko = "로케일", + .pl = "Ustawienia regionalne", + .pt_BR = "Configuração regional", + .ru = "Локаль", + .zh_CN = "语言环境", + .zh_TW = "語言環境", + }, .initOptions = (void*) ffInitLocaleOptions, .destroyOptions = (void*) ffDestroyLocaleOptions, .parseJsonObject = (void*) ffParseLocaleJsonObject, diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index eeb304e28..bc438be7e 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -424,6 +424,20 @@ void ffDestroyLocalIpOptions(FFLocalIpOptions* options) { FFModuleBaseInfo ffLocalIPModuleInfo = { .name = FF_LOCALIP_MODULE_NAME, .description = "List local IP addresses (IPv4 or IPv6), MAC addresses, etc", + .displayName = { + .en = "Local IP", + .de = "Lokale IP", + .es = "IP local", + .fr = "IP locale", + .it = "IP locale", + .ja = "ローカル IP", + .ko = "로컬 IP", + .pl = "Lokalny adres IP", + .pt_BR = "IP local", + .ru = "Локальный IP", + .zh_CN = "本地 IP", + .zh_TW = "區域 IP", + }, .initOptions = (void*) ffInitLocalIpOptions, .destroyOptions = (void*) ffDestroyLocalIpOptions, .parseJsonObject = (void*) ffParseLocalIpJsonObject, diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index a2fd7d2d1..432a1fa82 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -79,6 +79,20 @@ void ffDestroyLogoOptions([[maybe_unused]] FFLogoOptions* options) { FFModuleBaseInfo ffLogoModuleInfo = { .name = FF_LOGO_MODULE_NAME, .description = "Query built-in logo for JSON output", + .displayName = { + .en = "Logo", + .de = "Logo", + .es = "Logo", + .fr = "Logo", + .it = "Logo", + .ja = "ロゴ", + .ko = "로고", + .pl = "Logo", + .pt_BR = "Logo", + .ru = "Логотип", + .zh_CN = "徽标", + .zh_TW = "標誌", + }, .initOptions = (void*) ffInitLogoOptions, .destroyOptions = (void*) ffDestroyLogoOptions, .parseJsonObject = (void*) ffParseLogoJsonObject, diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 5f926d115..80bc087be 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -255,6 +255,20 @@ void ffDestroyMediaOptions(FFMediaOptions* options) { FFModuleBaseInfo ffMediaModuleInfo = { .name = FF_MEDIA_MODULE_NAME, .description = "Print the name of the currently playing song", + .displayName = { + .en = "Media", + .de = "Medien", + .es = "Medios", + .fr = "Médias", + .it = "Media", + .ja = "メディア", + .ko = "미디어", + .pl = "Media", + .pt_BR = "Mídia", + .ru = "Медиа", + .zh_CN = "媒体", + .zh_TW = "媒體", + }, .initOptions = (void*) ffInitMediaOptions, .destroyOptions = (void*) ffDestroyMediaOptions, .parseJsonObject = (void*) ffParseMediaJsonObject, diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 73a8fc173..7a7f58e09 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -120,6 +120,20 @@ void ffDestroyMemoryOptions(FFMemoryOptions* options) { FFModuleBaseInfo ffMemoryModuleInfo = { .name = FF_MEMORY_MODULE_NAME, .description = "Print system memory usage information", + .displayName = { + .en = "Memory", + .de = "Speicher", + .es = "Memoria", + .fr = "Mémoire", + .it = "Memoria", + .ja = "メモリ", + .ko = "메모리", + .pl = "Pamięć", + .pt_BR = "Memória", + .ru = "Память", + .zh_CN = "内存", + .zh_TW = "記憶體", + }, .initOptions = (void*) ffInitMemoryOptions, .destroyOptions = (void*) ffDestroyMemoryOptions, .parseJsonObject = (void*) ffParseMemoryJsonObject, diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 6c8bed170..27911bccf 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -106,6 +106,20 @@ void ffDestroyMonitorOptions(FFMonitorOptions* options) { FFModuleBaseInfo ffMonitorModuleInfo = { .name = FF_MONITOR_MODULE_NAME, .description = "Same as Display module, but with a different default output format", + .displayName = { + .en = "Monitor", + .de = "Monitor", + .es = "Monitor", + .fr = "Moniteur", + .it = "Monitor", + .ja = "モニター", + .ko = "모니터", + .pl = "Monitor", + .pt_BR = "Monitor", + .ru = "Монитор", + .zh_CN = "显示器", + .zh_TW = "顯示器", + }, .initOptions = (void*) ffInitMonitorOptions, .destroyOptions = (void*) ffDestroyMonitorOptions, .parseJsonObject = (void*) ffParseMonitorJsonObject, diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index 82dd6b053..c14b6e998 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -154,6 +154,20 @@ void ffDestroyMouseOptions(FFMouseOptions* options) { FFModuleBaseInfo ffMouseModuleInfo = { .name = FF_MOUSE_MODULE_NAME, .description = "List connected mice", + .displayName = { + .en = "Mouse", + .de = "Maus", + .es = "Ratón", + .fr = "Souris", + .it = "Mouse", + .ja = "マウス", + .ko = "마우스", + .pl = "Mysz", + .pt_BR = "Mouse", + .ru = "Мышь", + .zh_CN = "鼠标", + .zh_TW = "滑鼠", + }, .initOptions = (void*) ffInitMouseOptions, .destroyOptions = (void*) ffDestroyMouseOptions, .parseJsonObject = (void*) ffParseMouseJsonObject, diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 8607a21af..cad480b18 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -201,6 +201,20 @@ void ffDestroyNetIOOptions(FFNetIOOptions* options) { FFModuleBaseInfo ffNetIOModuleInfo = { .name = FF_NETIO_MODULE_NAME, .description = "Print network I/O throughput", + .displayName = { + .en = "Network I/O", + .de = "Netzwerk I/O", + .es = "E/S de red", + .fr = "E/S réseau", + .it = "I/O di rete", + .ja = "ネットワークI/O", + .ko = "네트워크 I/O", + .pl = "I/O sieciowe", + .pt_BR = "E/S de rede", + .ru = "Сетевой I/O", + .zh_CN = "网络 I/O", + .zh_TW = "網路 I/O", + }, .initOptions = (void*) ffInitNetIOOptions, .destroyOptions = (void*) ffDestroyNetIOOptions, .parseJsonObject = (void*) ffParseNetIOJsonObject, diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 0a80d9d16..353615b64 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -122,6 +122,20 @@ void ffDestroyOpenCLOptions(FFOpenCLOptions* options) { FFModuleBaseInfo ffOpenCLModuleInfo = { .name = FF_OPENCL_MODULE_NAME, .description = "Print the highest OpenCL version supported by the GPU", + .displayName = { + .en = "OpenCL", + .de = "OpenCL", + .es = "OpenCL", + .fr = "OpenCL", + .it = "OpenCL", + .ja = "OpenCL", + .ko = "OpenCL", + .pl = "OpenCL", + .pt_BR = "OpenCL", + .ru = "OpenCL", + .zh_CN = "OpenCL", + .zh_TW = "OpenCL", + }, .initOptions = (void*) ffInitOpenCLOptions, .destroyOptions = (void*) ffDestroyOpenCLOptions, .parseJsonObject = (void*) ffParseOpenCLJsonObject, diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 29adcf0f0..c10ec7e20 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -129,6 +129,20 @@ void ffDestroyOpenGLOptions(FFOpenGLOptions* options) { FFModuleBaseInfo ffOpenGLModuleInfo = { .name = FF_OPENGL_MODULE_NAME, .description = "Print the highest OpenGL version supported by the GPU", + .displayName = { + .en = "OpenGL", + .de = "OpenGL", + .es = "OpenGL", + .fr = "OpenGL", + .it = "OpenGL", + .ja = "OpenGL", + .ko = "OpenGL", + .pl = "OpenGL", + .pt_BR = "OpenGL", + .ru = "OpenGL", + .zh_CN = "OpenGL", + .zh_TW = "OpenGL", + }, .initOptions = (void*) ffInitOpenGLOptions, .destroyOptions = (void*) ffDestroyOpenGLOptions, .parseJsonObject = (void*) ffParseOpenGLJsonObject, diff --git a/src/modules/os/os.c b/src/modules/os/os.c index d0dc5600b..65168a609 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -174,6 +174,20 @@ void ffDestroyOSOptions(FFOSOptions* options) { FFModuleBaseInfo ffOSModuleInfo = { .name = FF_OS_MODULE_NAME, .description = "Print the OS or Linux distribution name and version", + .displayName = { + .en = "OS", + .de = "Betriebssystem", + .es = "Sistema operativo", + .fr = "Système d'exploitation", + .it = "Sistema operativo", + .ja = "オペレーティングシステム", + .ko = "운영 체제", + .pl = "System operacyjny", + .pt_BR = "Sistema operacional", + .ru = "Операционная система", + .zh_CN = "操作系统", + .zh_TW = "操作系統", + }, .initOptions = (void*) ffInitOSOptions, .destroyOptions = (void*) ffDestroyOSOptions, .parseJsonObject = (void*) ffParseOSJsonObject, diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 1553893f1..258e0f369 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -512,6 +512,20 @@ void ffDestroyPackagesOptions(FFPackagesOptions* options) { FFModuleBaseInfo ffPackagesModuleInfo = { .name = FF_PACKAGES_MODULE_NAME, .description = "List installed package managers and count of installed packages", + .displayName = { + .en = "Packages", + .de = "Pakete", + .es = "Paquetes", + .fr = "Paquets", + .it = "Pacchetti", + .ja = "パッケージ", + .ko = "패키지", + .pl = "Pakiety", + .pt_BR = "Pacotes", + .ru = "Пакеты", + .zh_CN = "软件包", + .zh_TW = "軟體包", + }, .initOptions = (void*) ffInitPackagesOptions, .destroyOptions = (void*) ffDestroyPackagesOptions, .parseJsonObject = (void*) ffParsePackagesJsonObject, diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 893543884..d897e131e 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -267,6 +267,20 @@ void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) { FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .name = FF_PHYSICALDISK_MODULE_NAME, .description = "Print physical disk information", + .displayName = { + .en = "Physical Disk", + .de = "Physische Festplatte", + .es = "Disco físico", + .fr = "Disque physique", + .it = "Disco fisico", + .ja = "物理ディスク", + .ko = "물리 디스크", + .pl = "Dysk fizyczny", + .pt_BR = "Disco físico", + .ru = "Физический диск", + .zh_CN = "物理磁盘", + .zh_TW = "物理磁碟", + }, .initOptions = (void*) ffInitPhysicalDiskOptions, .destroyOptions = (void*) ffDestroyPhysicalDiskOptions, .parseJsonObject = (void*) ffParsePhysicalDiskJsonObject, diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index f044e5907..64e53957d 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -161,6 +161,20 @@ void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) { FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .name = FF_PHYSICALMEMORY_MODULE_NAME, .description = "Print system physical memory devices", + .displayName = { + .en = "Physical Memory", + .de = "Physischer Speicher", + .es = "Memoria física", + .fr = "Mémoire physique", + .it = "Memoria fisica", + .ja = "物理メモリ", + .ko = "물리 메모리", + .pl = "Pamięć fizyczna", + .pt_BR = "Memória física", + .ru = "Физическая память", + .zh_CN = "物理内存", + .zh_TW = "實體記憶體", + }, .initOptions = (void*) ffInitPhysicalMemoryOptions, .destroyOptions = (void*) ffDestroyPhysicalMemoryOptions, .parseJsonObject = (void*) ffParsePhysicalMemoryJsonObject, diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 0d1fd03b8..a01471446 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -111,6 +111,20 @@ void ffDestroyPlayerOptions(FFPlayerOptions* options) { FFModuleBaseInfo ffPlayerModuleInfo = { .name = FF_PLAYER_MODULE_NAME, .description = "Print the music player name that is currently active", + .displayName = { + .en = "Media Player", + .de = "Medienplayer", + .es = "Reproductor multimedia", + .fr = "Lecteur multimédia", + .it = "Lettore multimediale", + .ja = "メディアプレイヤー", + .ko = "미디어 플레이어", + .pl = "Odtwarzacz multimediów", + .pt_BR = "Reprodutor de mídia", + .ru = "Медиаплеер", + .zh_CN = "媒体播放器", + .zh_TW = "媒體播放器", + }, .initOptions = (void*) ffInitPlayerOptions, .destroyOptions = (void*) ffDestroyPlayerOptions, .parseJsonObject = (void*) ffParsePlayerJsonObject, diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index be20d2a6d..74f0bfe89 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -112,6 +112,20 @@ void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options) { FFModuleBaseInfo ffPowerAdapterModuleInfo = { .name = FF_POWERADAPTER_MODULE_NAME, .description = "Print power adapter name and charging watts", + .displayName = { + .en = "Power Adapter", + .de = "Netzteil", + .es = "Adaptador de corriente", + .fr = "Adaptateur secteur", + .it = "Alimentatore", + .ja = "電源アダプター", + .ko = "전원 어댑터", + .pl = "Zasilacz", + .pt_BR = "Fonte de alimentação", + .ru = "Блок питания", + .zh_CN = "电源适配器", + .zh_TW = "電源轉接器", + }, .initOptions = (void*) ffInitPowerAdapterOptions, .destroyOptions = (void*) ffDestroyPowerAdapterOptions, .parseJsonObject = (void*) ffParsePowerAdapterJsonObject, diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index daf7a23ed..1d02bac2e 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -65,6 +65,20 @@ void ffDestroyProcessesOptions(FFProcessesOptions* options) { FFModuleBaseInfo ffProcessesModuleInfo = { .name = FF_PROCESSES_MODULE_NAME, .description = "Print number of running processes", + .displayName = { + .en = "Processes", + .de = "Prozesse", + .es = "Procesos", + .fr = "Processus", + .it = "Processi", + .ja = "プロセス", + .ko = "프로세스", + .pl = "Procesy", + .pt_BR = "Processos", + .ru = "Процессы", + .zh_CN = "进程数", + .zh_TW = "進程數", + }, .initOptions = (void*) ffInitProcessesOptions, .destroyOptions = (void*) ffDestroyProcessesOptions, .parseJsonObject = (void*) ffParseProcessesJsonObject, diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 5d52e74a7..fe5002a43 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -112,6 +112,20 @@ void ffDestroyPublicIpOptions(FFPublicIPOptions* options) { FFModuleBaseInfo ffPublicIPModuleInfo = { .name = FF_PUBLICIP_MODULE_NAME, .description = "Print your public IP address and related information", + .displayName = { + .en = "Public IP", + .de = "Öffentliche IP", + .es = "IP pública", + .fr = "IP publique", + .it = "IP pubblica", + .ja = "パブリックIP", + .ko = "공용 IP", + .pl = "Publiczne IP", + .pt_BR = "IP público", + .ru = "Публичный IP", + .zh_CN = "公网 IP", + .zh_TW = "公網 IP", + }, .initOptions = (void*) ffInitPublicIpOptions, .destroyOptions = (void*) ffDestroyPublicIpOptions, .parseJsonObject = (void*) ffParsePublicIpJsonObject, diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index bd84d7a40..eaf912819 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -123,6 +123,20 @@ void ffDestroySeparatorOptions(FFSeparatorOptions* options) { FFModuleBaseInfo ffSeparatorModuleInfo = { .name = FF_SEPARATOR_MODULE_NAME, .description = "Print a separator line", + .displayName = { + .en = "Separator", + .de = "Trennlinie", + .es = "Separador", + .fr = "Séparateur", + .it = "Separatore", + .ja = "セパレーター", + .ko = "구분선", + .pl = "Separator", + .pt_BR = "Separador", + .ru = "Разделитель", + .zh_CN = "分隔线", + .zh_TW = "分隔線", + }, .initOptions = (void*) ffInitSeparatorOptions, .destroyOptions = (void*) ffDestroySeparatorOptions, .parseJsonObject = (void*) ffParseSeparatorJsonObject, diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 84db1baca..a1df091c3 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -91,6 +91,20 @@ void ffDestroyShellOptions(FFShellOptions* options) { FFModuleBaseInfo ffShellModuleInfo = { .name = FF_SHELL_MODULE_NAME, .description = "Print the current shell name and version", + .displayName = { + .en = "Shell", + .de = "Shell", + .es = "Shell", + .fr = "Shell", + .it = "Shell", + .ja = "シェル", + .ko = "셸", + .pl = "Powłoka", + .pt_BR = "Shell", + .ru = "Оболочка", + .zh_CN = "Shell", + .zh_TW = "Shell", + }, .initOptions = (void*) ffInitShellOptions, .destroyOptions = (void*) ffDestroyShellOptions, .parseJsonObject = (void*) ffParseShellJsonObject, diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 6bc73cbe7..eaa0d44b7 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -201,6 +201,20 @@ void ffDestroySoundOptions(FFSoundOptions* options) { FFModuleBaseInfo ffSoundModuleInfo = { .name = FF_SOUND_MODULE_NAME, .description = "Print sound devices, volume levels, etc", + .displayName = { + .en = "Sound", + .de = "Sound", + .es = "Sonido", + .fr = "Son", + .it = "Audio", + .ja = "サウンド", + .ko = "사운드", + .pl = "Dźwięk", + .pt_BR = "Som", + .ru = "Звук", + .zh_CN = "声音", + .zh_TW = "聲音", + }, .initOptions = (void*) ffInitSoundOptions, .destroyOptions = (void*) ffDestroySoundOptions, .parseJsonObject = (void*) ffParseSoundJsonObject, diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index cf9d107c6..5b7c1117e 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -184,6 +184,20 @@ void ffDestroySwapOptions(FFSwapOptions* options) { FFModuleBaseInfo ffSwapModuleInfo = { .name = FF_SWAP_MODULE_NAME, .description = "Print swap (paging file) space usage", + .displayName = { + .en = "Swap", + .de = "Swap", + .es = "Swap", + .fr = "Swap", + .it = "Swap", + .ja = "スワップ", + .ko = "스왑", + .pl = "Swap", + .pt_BR = "Swap", + .ru = "Своп", + .zh_CN = "交换空间", + .zh_TW = "交換空間", + }, .initOptions = (void*) ffInitSwapOptions, .destroyOptions = (void*) ffDestroySwapOptions, .parseJsonObject = (void*) ffParseSwapJsonObject, diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 5b2e9305f..7aa4e1a18 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -85,6 +85,20 @@ void ffDestroyTerminalOptions(FFTerminalOptions* options) { FFModuleBaseInfo ffTerminalModuleInfo = { .name = FF_TERMINAL_MODULE_NAME, .description = "Print the current terminal name and version", + .displayName = { + .en = "Terminal", + .de = "Terminal", + .es = "Terminal", + .fr = "Terminal", + .it = "Terminale", + .ja = "ターミナル", + .ko = "터미널", + .pl = "Terminal", + .pt_BR = "Terminal", + .ru = "Терминал", + .zh_CN = "终端", + .zh_TW = "終端機", + }, .initOptions = (void*) ffInitTerminalOptions, .destroyOptions = (void*) ffDestroyTerminalOptions, .parseJsonObject = (void*) ffParseTerminalJsonObject, diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 87a083718..6c840889d 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -107,6 +107,20 @@ void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options) { FFModuleBaseInfo ffTerminalFontModuleInfo = { .name = FF_TERMINALFONT_MODULE_NAME, .description = "Print the font name and size used by the current terminal", + .displayName = { + .en = "Terminal Font", + .de = "Terminalschriftart", + .es = "Fuente del terminal", + .fr = "Police du terminal", + .it = "Carattere del terminale", + .ja = "ターミナルフォント", + .ko = "터미널 글꼴", + .pl = "Czcionka terminala", + .pt_BR = "Fonte do terminal", + .ru = "Шрифт терминала", + .zh_CN = "终端字体", + .zh_TW = "終端機字型", + }, .initOptions = (void*) ffInitTerminalFontOptions, .destroyOptions = (void*) ffDestroyTerminalFontOptions, .parseJsonObject = (void*) ffParseTerminalFontJsonObject, diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 088b97fce..11e34551b 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -78,6 +78,20 @@ void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) { FFModuleBaseInfo ffTerminalSizeModuleInfo = { .name = FF_TERMINALSIZE_MODULE_NAME, .description = "Print the current terminal size", + .displayName = { + .en = "Terminal Size", + .de = "Terminalgröße", + .es = "Tamaño del terminal", + .fr = "Taille du terminal", + .it = "Dimensioni terminale", + .ja = "ターミナルサイズ", + .ko = "터미널 크기", + .pl = "Rozmiar terminala", + .pt_BR = "Tamanho do terminal", + .ru = "Размер терминала", + .zh_CN = "终端大小", + .zh_TW = "終端機大小", + }, .initOptions = (void*) ffInitTerminalSizeOptions, .destroyOptions = (void*) ffDestroyTerminalSizeOptions, .parseJsonObject = (void*) ffParseTerminalSizeJsonObject, diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 3d5239b2f..053db3453 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -95,6 +95,20 @@ void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options) { FFModuleBaseInfo ffTerminalThemeModuleInfo = { .name = FF_TERMINALTHEME_MODULE_NAME, .description = "Print the current terminal theme (foreground and background colors)", + .displayName = { + .en = "Terminal Theme", + .de = "Terminalthema", + .es = "Tema del terminal", + .fr = "Thème du terminal", + .it = "Tema del terminale", + .ja = "ターミナルテーマ", + .ko = "터미널 테마", + .pl = "Motyw terminala", + .pt_BR = "Tema do terminal", + .ru = "Тема терминала", + .zh_CN = "终端主题", + .zh_TW = "終端機主題", + }, .initOptions = (void*) ffInitTerminalThemeOptions, .destroyOptions = (void*) ffDestroyTerminalThemeOptions, .parseJsonObject = (void*) ffParseTerminalThemeJsonObject, diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index f51a4aac6..1769d5fc3 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -89,6 +89,20 @@ void ffDestroyThemeOptions(FFThemeOptions* options) { FFModuleBaseInfo ffThemeModuleInfo = { .name = FF_THEME_MODULE_NAME, .description = "Print the current desktop environment theme", + .displayName = { + .en = "Theme", + .de = "Thema", + .es = "Tema", + .fr = "Thème", + .it = "Tema", + .ja = "テーマ", + .ko = "테마", + .pl = "Motyw", + .pt_BR = "Tema", + .ru = "Тема", + .zh_CN = "主题", + .zh_TW = "主題", + }, .initOptions = (void*) ffInitThemeOptions, .destroyOptions = (void*) ffDestroyThemeOptions, .parseJsonObject = (void*) ffParseThemeJsonObject, diff --git a/src/modules/title/title.c b/src/modules/title/title.c index ce877caed..3d8fe1a79 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -178,6 +178,20 @@ void ffDestroyTitleOptions(FFTitleOptions* options) { FFModuleBaseInfo ffTitleModuleInfo = { .name = FF_TITLE_MODULE_NAME, .description = "Print the title, including your username and hostname", + .displayName = { + .en = "Title", + .de = "Titel", + .es = "Título", + .fr = "Titre", + .it = "Titolo", + .ja = "タイトル", + .ko = "제목", + .pl = "Tytuł", + .pt_BR = "Título", + .ru = "Заголовок", + .zh_CN = "标题", + .zh_TW = "標題", + }, .initOptions = (void*) ffInitTitleOptions, .destroyOptions = (void*) ffDestroyTitleOptions, .parseJsonObject = (void*) ffParseTitleJsonObject, diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 6596d6261..3471d5a12 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -85,6 +85,20 @@ void ffDestroyTPMOptions(FFTPMOptions* options) { FFModuleBaseInfo ffTPMModuleInfo = { .name = FF_TPM_MODULE_NAME, .description = "Print information about the Trusted Platform Module (TPM) security device", + .displayName = { + .en = "TPM", + .de = "TPM", + .es = "TPM", + .fr = "TPM", + .it = "TPM", + .ja = "TPM", + .ko = "TPM", + .pl = "TPM", + .pt_BR = "TPM", + .ru = "TPM", + .zh_CN = "TPM", + .zh_TW = "TPM", + }, .initOptions = (void*) ffInitTPMOptions, .destroyOptions = (void*) ffDestroyTPMOptions, .parseJsonObject = (void*) ffParseTPMJsonObject, diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 41ac4526a..b4299d7a5 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -85,6 +85,20 @@ void ffDestroyUptimeOptions(FFUptimeOptions* options) { FFModuleBaseInfo ffUptimeModuleInfo = { .name = FF_UPTIME_MODULE_NAME, .description = "Print how long the system has been running", + .displayName = { + .en = "Uptime", + .de = "Betriebszeit", + .es = "Tiempo de actividad", + .fr = "Temps de fonctionnement", + .it = "Tempo di attività", + .ja = "稼働時間", + .ko = "업타임", + .pl = "Czas pracy", + .pt_BR = "Tempo de atividade", + .ru = "Время работы", + .zh_CN = "运行时间", + .zh_TW = "運行時間", + }, .initOptions = (void*) ffInitUptimeOptions, .destroyOptions = (void*) ffDestroyUptimeOptions, .parseJsonObject = (void*) ffParseUptimeJsonObject, diff --git a/src/modules/users/users.c b/src/modules/users/users.c index fbf1ffaa8..f67073e18 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -182,6 +182,20 @@ void ffDestroyUsersOptions(FFUsersOptions* options) { FFModuleBaseInfo ffUsersModuleInfo = { .name = FF_USERS_MODULE_NAME, .description = "Print users who are currently logged in", + .displayName = { + .en = "Users", + .de = "Benutzer", + .es = "Usuarios", + .fr = "Utilisateurs", + .it = "Utenti", + .ja = "ユーザー", + .ko = "사용자", + .pl = "Użytkownicy", + .pt_BR = "Usuários", + .ru = "Пользователи", + .zh_CN = "用户", + .zh_TW = "使用者", + }, .initOptions = (void*) ffInitUsersOptions, .destroyOptions = (void*) ffDestroyUsersOptions, .parseJsonObject = (void*) ffParseUsersJsonObject, diff --git a/src/modules/version/version.c b/src/modules/version/version.c index fa3b59fe7..2bd906a21 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -96,6 +96,20 @@ void ffDestroyVersionOptions(FFVersionOptions* options) { FFModuleBaseInfo ffVersionModuleInfo = { .name = FF_VERSION_MODULE_NAME, .description = "Print the Fastfetch version and build information", + .displayName = { + .en = "Version", + .de = "Version", + .es = "Versión", + .fr = "Version", + .it = "Versione", + .ja = "バージョン", + .ko = "버전", + .pl = "Wersja", + .pt_BR = "Versão", + .ru = "Версия", + .zh_CN = "版本", + .zh_TW = "版本", + }, .initOptions = (void*) ffInitVersionOptions, .destroyOptions = (void*) ffDestroyVersionOptions, .parseJsonObject = (void*) ffParseVersionJsonObject, diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 03123b7ae..9dedfd9cc 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -134,6 +134,20 @@ void ffDestroyVulkanOptions(FFVulkanOptions* options) { FFModuleBaseInfo ffVulkanModuleInfo = { .name = FF_VULKAN_MODULE_NAME, .description = "Print the highest Vulkan version supported by the GPU", + .displayName = { + .en = "Vulkan", + .de = "Vulkan", + .es = "Vulkan", + .fr = "Vulkan", + .it = "Vulkan", + .ja = "Vulkan", + .ko = "Vulkan", + .pl = "Vulkan", + .pt_BR = "Vulkan", + .ru = "Vulkan", + .zh_CN = "Vulkan", + .zh_TW = "Vulkan", + }, .initOptions = (void*) ffInitVulkanOptions, .destroyOptions = (void*) ffDestroyVulkanOptions, .parseJsonObject = (void*) ffParseVulkanJsonObject, diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index b5fab48f5..fc1393fb9 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -77,6 +77,20 @@ void ffDestroyWallpaperOptions(FFWallpaperOptions* options) { FFModuleBaseInfo ffWallpaperModuleInfo = { .name = FF_WALLPAPER_MODULE_NAME, .description = "Print the file path of the current wallpaper", + .displayName = { + .en = "Wallpaper", + .de = "Hintergrundbild", + .es = "Fondo de pantalla", + .fr = "Fond d'écran", + .it = "Sfondo", + .ja = "壁紙", + .ko = "배경화면", + .pl = "Tapeta", + .pt_BR = "Papel de parede", + .ru = "Обои", + .zh_CN = "壁纸", + .zh_TW = "桌布", + }, .initOptions = (void*) ffInitWallpaperOptions, .destroyOptions = (void*) ffDestroyWallpaperOptions, .parseJsonObject = (void*) ffParseWallpaperJsonObject, diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 152cb057b..8307ce422 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -94,6 +94,20 @@ void ffDestroyWeatherOptions(FFWeatherOptions* options) { FFModuleBaseInfo ffWeatherModuleInfo = { .name = FF_WEATHER_MODULE_NAME, .description = "Print weather information", + .displayName = { + .en = "Weather", + .de = "Wetter", + .es = "Clima", + .fr = "Météo", + .it = "Meteo", + .ja = "天気", + .ko = "날씨", + .pl = "Pogoda", + .pt_BR = "Clima", + .ru = "Погода", + .zh_CN = "天气", + .zh_TW = "天氣", + }, .initOptions = (void*) ffInitWeatherOptions, .destroyOptions = (void*) ffDestroyWeatherOptions, .parseJsonObject = (void*) ffParseWeatherJsonObject, diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 0e9df22c9..58e5da965 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -215,6 +215,20 @@ void ffDestroyWifiOptions(FFWifiOptions* options) { FFModuleBaseInfo ffWifiModuleInfo = { .name = FF_WIFI_MODULE_NAME, .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", + .displayName = { + .en = "Wi-Fi", + .de = "WLAN", + .es = "Wi-Fi", + .fr = "Wi-Fi", + .it = "Wi-Fi", + .ja = "Wi-Fi", + .ko = "와이파이", + .pl = "Wi-Fi", + .pt_BR = "Wi-Fi", + .ru = "Wi-Fi", + .zh_CN = "无线网络", + .zh_TW = "無線網路", + }, .initOptions = (void*) ffInitWifiOptions, .destroyOptions = (void*) ffDestroyWifiOptions, .parseJsonObject = (void*) ffParseWifiJsonObject, diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 5e23826e1..3545bfc9e 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -122,6 +122,20 @@ void ffDestroyWMOptions(FFWMOptions* options) { FFModuleBaseInfo ffWMModuleInfo = { .name = FF_WM_MODULE_NAME, .description = "Print the window manager name and version", + .displayName = { + .en = "WM", + .de = "Fenstermanager", + .es = "Gestor de ventanas", + .fr = "Gestionnaire de fenêtres", + .it = "Gestore finestre", + .ja = "ウィンドウマネージャー", + .ko = "윈도우 관리자", + .pl = "Menedżer okien", + .pt_BR = "Gerenciador de janelas", + .ru = "Менеджер окон", + .zh_CN = "窗口管理器", + .zh_TW = "視窗管理員", + }, .initOptions = (void*) ffInitWMOptions, .destroyOptions = (void*) ffDestroyWMOptions, .parseJsonObject = (void*) ffParseWMJsonObject, diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index f1ab4105f..7061f66ae 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -63,6 +63,20 @@ void ffDestroyWMThemeOptions(FFWMThemeOptions* options) { FFModuleBaseInfo ffWMThemeModuleInfo = { .name = FF_WMTHEME_MODULE_NAME, .description = "Print the current window manager theme", + .displayName = { + .en = "WM Theme", + .de = "Fenstermanager-Thema", + .es = "Tema del gestor de ventanas", + .fr = "Thème du gestionnaire de fenêtres", + .it = "Tema del gestore finestre", + .ja = "ウィンドウマネージャのテーマ", + .ko = "윈도우 관리자 테마", + .pl = "Motyw menedżera okien", + .pt_BR = "Tema do gerenciador de janelas", + .ru = "Тема менеджера окон", + .zh_CN = "窗口管理器主题", + .zh_TW = "視窗管理員主題", + }, .initOptions = (void*) ffInitWMThemeOptions, .destroyOptions = (void*) ffDestroyWMThemeOptions, .parseJsonObject = (void*) ffParseWMThemeJsonObject, diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 7e5f03a52..b155ff3b1 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -194,6 +194,20 @@ void ffDestroyZpoolOptions(FFZpoolOptions* options) { FFModuleBaseInfo ffZpoolModuleInfo = { .name = FF_ZPOOL_MODULE_NAME, .description = "Print ZFS storage pools", + .displayName = { + .en = "Zpool", + .de = "Zpool", + .es = "Zpool", + .fr = "Zpool", + .it = "Zpool", + .ja = "Zpool", + .ko = "Zpool", + .pl = "Zpool", + .pt_BR = "Zpool", + .ru = "Zpool", + .zh_CN = "Zpool", + .zh_TW = "Zpool", + }, .initOptions = (void*) ffInitZpoolOptions, .destroyOptions = (void*) ffDestroyZpoolOptions, .parseJsonObject = (void*) ffParseZpoolJsonObject, From f95167e907bf89eb74fc4a1ff5fcea81a2b42e7d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 14 Aug 2026 23:33:54 +0800 Subject: [PATCH 005/109] Global: adds option `key-language` Fixes #2503 --- doc/help.json | 24 +++++ doc/json_schema.json | 70 ++++++++++++ src/common/impl/commandoption.c | 12 +-- src/common/impl/jsonconfig.c | 12 +-- src/common/option.h | 2 + src/modules/battery/battery.c | 12 +-- src/modules/battery/battery.h | 2 - src/modules/bios/bios.c | 10 +- src/modules/bios/bios.h | 2 - src/modules/bluetooth/bluetooth.c | 12 +-- src/modules/bluetooth/bluetooth.h | 2 - src/modules/bluetoothradio/bluetoothradio.c | 14 ++- src/modules/bluetoothradio/bluetoothradio.h | 2 - src/modules/board/board.c | 12 +-- src/modules/board/board.h | 2 - src/modules/bootmgr/bootmgr.c | 10 +- src/modules/bootmgr/bootmgr.h | 2 - src/modules/break/break.c | 4 +- src/modules/break/break.h | 2 - src/modules/brightness/brightness.c | 12 +-- src/modules/brightness/brightness.h | 2 - src/modules/btrfs/btrfs.c | 12 +-- src/modules/btrfs/btrfs.h | 2 - src/modules/camera/camera.c | 12 +-- src/modules/camera/camera.h | 2 - src/modules/chassis/chassis.c | 12 +-- src/modules/chassis/chassis.h | 2 - src/modules/codec/codec.c | 14 +-- src/modules/codec/codec.h | 2 - src/modules/colors/colors.c | 22 ++-- src/modules/colors/colors.h | 2 - src/modules/command/command.c | 16 +-- src/modules/command/command.h | 2 - src/modules/cpu/cpu.c | 14 +-- src/modules/cpu/cpu.h | 2 - src/modules/cpucache/cpucache.c | 14 ++- src/modules/cpucache/cpucache.h | 2 - src/modules/cpuusage/cpuusage.c | 12 +-- src/modules/cpuusage/cpuusage.h | 2 - src/modules/cursor/cursor.c | 10 +- src/modules/cursor/cursor.h | 2 - src/modules/custom/custom.c | 6 +- src/modules/custom/custom.h | 2 - src/modules/datetime/datetime.c | 12 +-- src/modules/datetime/datetime.h | 2 - src/modules/de/de.c | 12 +-- src/modules/de/de.h | 2 - src/modules/disk/disk.c | 10 +- src/modules/disk/disk.h | 2 - src/modules/diskio/diskio.c | 10 +- src/modules/diskio/diskio.h | 2 - src/modules/display/display.c | 18 ++-- src/modules/display/display.h | 2 - src/modules/dns/dns.c | 14 +-- src/modules/dns/dns.h | 2 - src/modules/editor/editor.c | 10 +- src/modules/editor/editor.h | 2 - src/modules/font/font.c | 10 +- src/modules/font/font.h | 2 - src/modules/gamepad/gamepad.c | 14 +-- src/modules/gamepad/gamepad.h | 2 - src/modules/gpu/gpu.c | 16 +-- src/modules/gpu/gpu.h | 2 - src/modules/host/host.c | 12 +-- src/modules/host/host.h | 2 - src/modules/icons/icons.c | 10 +- src/modules/icons/icons.h | 2 - src/modules/initsystem/initsystem.c | 12 +-- src/modules/initsystem/initsystem.h | 2 - src/modules/kernel/kernel.c | 8 +- src/modules/kernel/kernel.h | 2 - src/modules/keyboard/keyboard.c | 14 +-- src/modules/keyboard/keyboard.h | 2 - src/modules/lm/lm.c | 12 +-- src/modules/lm/lm.h | 2 - src/modules/loadavg/loadavg.c | 12 +-- src/modules/loadavg/loadavg.h | 2 - src/modules/locale/locale.c | 10 +- src/modules/locale/locale.h | 2 - src/modules/localip/localip.c | 15 ++- src/modules/localip/localip.h | 2 - src/modules/logo/logo.c | 6 +- src/modules/logo/logo.h | 2 - src/modules/media/media.c | 10 +- src/modules/media/media.h | 2 - src/modules/memory/memory.c | 10 +- src/modules/memory/memory.h | 2 - src/modules/monitor/monitor.c | 8 +- src/modules/monitor/monitor.h | 2 - src/modules/mouse/mouse.c | 14 +-- src/modules/mouse/mouse.h | 2 - src/modules/netio/netio.c | 10 +- src/modules/netio/netio.h | 2 - src/modules/opencl/opencl.c | 10 +- src/modules/opencl/opencl.h | 2 - src/modules/opengl/opengl.c | 12 +-- src/modules/opengl/opengl.h | 2 - src/modules/os/os.c | 8 +- src/modules/os/os.h | 2 - src/modules/packages/packages.c | 16 +-- src/modules/packages/packages.h | 2 - src/modules/physicaldisk/physicaldisk.c | 14 ++- src/modules/physicaldisk/physicaldisk.h | 2 - src/modules/physicalmemory/physicalmemory.c | 14 ++- src/modules/physicalmemory/physicalmemory.h | 2 - src/modules/player/player.c | 14 ++- src/modules/player/player.h | 2 - src/modules/poweradapter/poweradapter.c | 14 ++- src/modules/poweradapter/poweradapter.h | 2 - src/modules/processes/processes.c | 10 +- src/modules/processes/processes.h | 2 - src/modules/publicip/publicip.c | 12 +-- src/modules/publicip/publicip.h | 2 - src/modules/separator/separator.c | 6 +- src/modules/separator/separator.h | 2 - src/modules/shell/shell.c | 10 +- src/modules/shell/shell.h | 2 - src/modules/sound/sound.c | 14 +-- src/modules/sound/sound.h | 2 - src/modules/swap/swap.c | 10 +- src/modules/swap/swap.h | 2 - src/modules/terminal/terminal.c | 10 +- src/modules/terminal/terminal.h | 2 - src/modules/terminalfont/terminalfont.c | 12 +-- src/modules/terminalfont/terminalfont.h | 2 - src/modules/terminalsize/terminalsize.c | 12 +-- src/modules/terminalsize/terminalsize.h | 2 - src/modules/terminaltheme/terminaltheme.c | 12 +-- src/modules/terminaltheme/terminaltheme.h | 2 - src/modules/theme/theme.c | 10 +- src/modules/theme/theme.h | 2 - src/modules/title/title.c | 8 +- src/modules/title/title.h | 2 - src/modules/tpm/tpm.c | 10 +- src/modules/tpm/tpm.h | 2 - src/modules/uptime/uptime.c | 10 +- src/modules/uptime/uptime.h | 2 - src/modules/users/users.c | 14 +-- src/modules/users/users.h | 2 - src/modules/version/version.c | 8 +- src/modules/version/version.h | 2 - src/modules/vulkan/vulkan.c | 10 +- src/modules/vulkan/vulkan.h | 2 - src/modules/wallpaper/wallpaper.c | 10 +- src/modules/wallpaper/wallpaper.h | 2 - src/modules/weather/weather.c | 10 +- src/modules/weather/weather.h | 2 - src/modules/wifi/wifi.c | 12 +-- src/modules/wifi/wifi.h | 2 - src/modules/wm/wm.c | 10 +- src/modules/wm/wm.h | 2 - src/modules/wmtheme/wmtheme.c | 12 +-- src/modules/wmtheme/wmtheme.h | 2 - src/modules/zpool/zpool.c | 12 +-- src/modules/zpool/zpool.h | 2 - src/options/display.c | 113 ++++++++++++++++++++ src/options/display.h | 1 + 157 files changed, 638 insertions(+), 611 deletions(-) diff --git a/doc/help.json b/doc/help.json index e24d294fc..d1a148202 100644 --- a/doc/help.json +++ b/doc/help.json @@ -585,6 +585,30 @@ "default": "string" } }, + { + "long": "key-language", + "desc": "Specify the language used for module keys", + "remark": "Leave empty for auto-detection based on the system locale", + "arg": { + "type": "enum", + "default": "en", + "optional": true, + "enum": { + "en": "English", + "de": "German", + "es": "Spanish", + "fr": "French", + "it": "Italian", + "ja": "Japanese", + "ko": "Korean", + "pl": "Polish", + "pt_BR": "Brazilian Portuguese", + "ru": "Russian", + "zh_CN": "Simplified Chinese", + "zh_TW": "Traditional Chinese" + } + } + }, { "long": "bright-color", "desc": "Specify whether keys, title, and ASCII logo should be printed in bright color", diff --git a/doc/json_schema.json b/doc/json_schema.json index 797e03b4d..01ef306de 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1057,6 +1057,76 @@ "description": "Left padding for keys", "minimum": 0, "default": 0 + }, + "language": { + "description": "Language used for module keys. `null` for auto detection based on system locale", + "oneOf": [ + { + "type": "null", + "description": "Auto detection based on system locale" + }, + { + "type": "string", + "const": "en", + "description": "English" + }, + { + "type": "string", + "const": "de", + "description": "German" + }, + { + "type": "string", + "const": "es", + "description": "Spanish" + }, + { + "type": "string", + "const": "fr", + "description": "French" + }, + { + "type": "string", + "const": "it", + "description": "Italian" + }, + { + "type": "string", + "const": "ja", + "description": "Japanese" + }, + { + "type": "string", + "const": "ko", + "description": "Korean" + }, + { + "type": "string", + "const": "pl", + "description": "Polish" + }, + { + "type": "string", + "const": "pt_BR", + "description": "Brazilian Portuguese" + }, + { + "type": "string", + "const": "ru", + "description": "Russian" + }, + { + "type": "string", + "const": "zh_CN", + "description": "Simplified Chinese" + }, + { + "type": "string", + "const": "zh_TW", + "description": "Traditional Chinese" + } + ], + "default": "en" } } }, diff --git a/src/common/impl/commandoption.c b/src/common/impl/commandoption.c index c4225a711..a8764d610 100644 --- a/src/common/impl/commandoption.c +++ b/src/common/impl/commandoption.c @@ -67,13 +67,13 @@ void ffPrepareCommandOption(FFdata* data) { char* moduleType = nullptr; size_t moduleLen = 0; while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure)) { -#define FF_IF_MODULE_MATCH(moduleNameConstant) if (moduleLen == strlen(moduleNameConstant) && ffStrEqualsIgnCase(moduleType, moduleNameConstant) && !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':')) +#define FF_IF_MODULE_MATCH(moduleNameConstant) if (ffStrEqualsIgnCase(moduleType, moduleNameConstant) && !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':')) switch (moduleType[0]) { #if !FF_MODULE_DISABLE_CPUUSAGE case 'C': case 'c': - FF_IF_MODULE_MATCH(FF_CPUUSAGE_MODULE_NAME) + FF_IF_MODULE_MATCH(ffCPUUsageModuleInfo.name) ffPrepareCPUUsage(); break; #endif @@ -81,7 +81,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_DISKIO case 'D': case 'd': - FF_IF_MODULE_MATCH(FF_DISKIO_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffDiskIOModuleInfo.name) { [[gnu::cleanup(ffDestroyDiskIOOptions)]] FFDiskIOOptions options; ffInitDiskIOOptions(&options); ffPrepareDiskIO(&options); @@ -92,7 +92,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_NETIO case 'N': case 'n': - FF_IF_MODULE_MATCH(FF_NETIO_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffNetIOModuleInfo.name) { [[gnu::cleanup(ffDestroyNetIOOptions)]] FFNetIOOptions options; ffInitNetIOOptions(&options); ffPrepareNetIO(&options); @@ -103,7 +103,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_PUBLICIP case 'P': case 'p': - FF_IF_MODULE_MATCH(FF_PUBLICIP_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffPublicIPModuleInfo.name) { [[gnu::cleanup(ffDestroyPublicIpOptions)]] FFPublicIPOptions options; ffInitPublicIpOptions(&options); ffPreparePublicIp(&options); @@ -114,7 +114,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_WEATHER case 'W': case 'w': - FF_IF_MODULE_MATCH(FF_WEATHER_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffWeatherModuleInfo.name) { [[gnu::cleanup(ffDestroyWeatherOptions)]] FFWeatherOptions options; ffInitWeatherOptions(&options); ffPrepareWeather(&options); diff --git a/src/common/impl/jsonconfig.c b/src/common/impl/jsonconfig.c index 5179d5b5d..7c9d44a88 100644 --- a/src/common/impl/jsonconfig.c +++ b/src/common/impl/jsonconfig.c @@ -136,9 +136,9 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_CPUUSAGE case 'c': case 'C': { - if (ffStrEqualsIgnCase(type, FF_CPUUSAGE_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffCPUUsageModuleInfo.name)) { ffPrepareCPUUsage(); - } else if (ffStrEqualsIgnCase(type, FF_COMMAND_MODULE_NAME)) { + } else if (ffStrEqualsIgnCase(type, ffCommandModuleInfo.name)) { [[gnu::cleanup(ffDestroyCommandOptions)]] FFCommandOptions options; ffInitCommandOptions(&options); if (module) { @@ -153,7 +153,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_DISKIO case 'd': case 'D': { - if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffDiskIOModuleInfo.name)) { [[gnu::cleanup(ffDestroyDiskIOOptions)]] FFDiskIOOptions options; ffInitDiskIOOptions(&options); if (module) { @@ -168,7 +168,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_NETIO case 'n': case 'N': { - if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffNetIOModuleInfo.name)) { [[gnu::cleanup(ffDestroyNetIOOptions)]] FFNetIOOptions options; ffInitNetIOOptions(&options); if (module) { @@ -183,7 +183,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_PUBLICIP case 'p': case 'P': { - if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffPublicIPModuleInfo.name)) { [[gnu::cleanup(ffDestroyPublicIpOptions)]] FFPublicIPOptions options; ffInitPublicIpOptions(&options); if (module) { @@ -198,7 +198,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_WEATHER case 'w': case 'W': { - if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffWeatherModuleInfo.name)) { [[gnu::cleanup(ffDestroyWeatherOptions)]] FFWeatherOptions options; ffInitWeatherOptions(&options); if (module) { diff --git a/src/common/option.h b/src/common/option.h index bda031690..2647cd7ed 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -111,3 +111,5 @@ static inline void ffOptionDestroyModuleArg(FFModuleArgs* args) { } enum { FF_OPTION_MAX_SIZE = 1 << 8 }; // Maximum size of a single option value, used for static allocation + +#define FF_MODULE_GET_DISPLAY_NAME(moduleName) (*(const char**) ((uint8_t*) &ff ## moduleName ## ModuleInfo.displayName + instance.config.display.keyLanguage)) diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index da2279624..99a44b676 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -11,9 +11,9 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (result->modelName.length > 0) { - ffStrbufSetF(&key, "%s (%s)", FF_BATTERY_MODULE_NAME, result->modelName.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Battery), result->modelName.chars); } else { - ffStrbufSetS(&key, FF_BATTERY_MODULE_NAME); + ffStrbufSetS(&key, FF_MODULE_GET_DISPLAY_NAME(Battery)); } } else { ffStrbufClear(&key); @@ -170,11 +170,11 @@ bool ffPrintBattery(FFBatteryOptions* options) { const char* error = ffDetectBattery(options, &results); if (error) { - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found"); return false; } @@ -209,7 +209,7 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -297,7 +297,7 @@ void ffDestroyBatteryOptions(FFBatteryOptions* options) { } FFModuleBaseInfo ffBatteryModuleInfo = { - .name = FF_BATTERY_MODULE_NAME, + .name = "Battery", .description = "Print battery information", .displayName = { .en = "Battery", diff --git a/src/modules/battery/battery.h b/src/modules/battery/battery.h index 16ad027d8..7157b51a7 100644 --- a/src/modules/battery/battery.h +++ b/src/modules/battery/battery.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BATTERY_MODULE_NAME "Battery" - bool ffPrintBattery(FFBatteryOptions* options); void ffInitBatteryOptions(FFBatteryOptions* options); void ffDestroyBatteryOptions(FFBatteryOptions* options); diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index b494dae21..94e602228 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -18,12 +18,12 @@ bool ffPrintBios(FFBiosOptions* options) { FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (error) { - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (bios.version.length == 0) { - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "bios_version is not set."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "bios_version is not set."); goto exit; } @@ -34,7 +34,7 @@ bool ffPrintBios(FFBiosOptions* options) { ffStrbufSetStatic(&bios.type, "Legacy"); } - ffStrbufSetF(&key, FF_BIOS_MODULE_NAME " (%s)", bios.type.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Bios), bios.type.chars); } else { ffStrbufClear(&key); FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -80,7 +80,7 @@ void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -130,7 +130,7 @@ void ffDestroyBiosOptions(FFBiosOptions* options) { } FFModuleBaseInfo ffBiosModuleInfo = { - .name = FF_BIOS_MODULE_NAME, + .name = "BIOS", .description = "Print first-stage bootloader information (name, version, release date, etc.)", .displayName = { .en = "BIOS", diff --git a/src/modules/bios/bios.h b/src/modules/bios/bios.h index d3b077e4d..d34978d8d 100644 --- a/src/modules/bios/bios.h +++ b/src/modules/bios/bios.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BIOS_MODULE_NAME "BIOS" - bool ffPrintBios(FFBiosOptions* options); void ffInitBiosOptions(FFBiosOptions* options); void ffDestroyBiosOptions(FFBiosOptions* options); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 50d4de366..232728dc5 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -8,7 +8,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* device, uint8_t index) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); bool showBatteryLevel = device->battery > 0 && device->battery <= 100; @@ -44,7 +44,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->address, "address"), FF_ARG(device->type, "type"), @@ -60,12 +60,12 @@ bool ffPrintBluetooth(FFBluetoothOptions* options) { const char* error = ffDetectBluetooth(options, &devices); if (error) { - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (devices.length == 0) { - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found"); return false; } @@ -100,7 +100,7 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -151,7 +151,7 @@ void ffDestroyBluetoothOptions(FFBluetoothOptions* options) { } FFModuleBaseInfo ffBluetoothModuleInfo = { - .name = FF_BLUETOOTH_MODULE_NAME, + .name = "Bluetooth", .description = "List connected Bluetooth devices", .displayName = { .en = "Bluetooth", diff --git a/src/modules/bluetooth/bluetooth.h b/src/modules/bluetooth/bluetooth.h index d9aa059e3..fc6fdd8ce 100644 --- a/src/modules/bluetooth/bluetooth.h +++ b/src/modules/bluetooth/bluetooth.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BLUETOOTH_MODULE_NAME "Bluetooth" - bool ffPrintBluetooth(FFBluetoothOptions* options); void ffInitBluetoothOptions(FFBluetoothOptions* options); void ffDestroyBluetoothOptions(FFBluetoothOptions* options); diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 911519997..1419eaec5 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -5,8 +5,6 @@ #include "detection/bluetoothradio/bluetoothradio.h" #include "modules/bluetoothradio/bluetoothradio.h" -#define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio" - static void destroyBluetoothRadios(FFlist* radios) { FF_LIST_FOR_EACH (FFBluetoothRadioResult, radio, *radios) { ffStrbufDestroy(&radio->name); @@ -18,7 +16,7 @@ static void destroyBluetoothRadios(FFlist* radios) { static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) { FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_BLUETOOTHRADIO_DISPLAY_NAME, radio->name.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), radio->name.chars); } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { FF_ARG(index, "index"), @@ -101,7 +99,7 @@ bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) { const char* error = ffDetectBluetoothRadio(&radios); if (error) { - ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -117,9 +115,9 @@ bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) { if (index == 0) { if (radios.length > 0) { - ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled"); } else { - ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); } destroyBluetoothRadios(&radios); return false; @@ -137,7 +135,7 @@ void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_va continue; } - ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -190,7 +188,7 @@ void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) { } FFModuleBaseInfo ffBluetoothRadioModuleInfo = { - .name = FF_BLUETOOTHRADIO_MODULE_NAME, + .name = "BluetoothRadio", .description = "List Bluetooth radios (supported versions, vendors, etc.)", .displayName = { .en = "Bluetooth Radio", diff --git a/src/modules/bluetoothradio/bluetoothradio.h b/src/modules/bluetoothradio/bluetoothradio.h index 4707f1ba5..391ea64a0 100644 --- a/src/modules/bluetoothradio/bluetoothradio.h +++ b/src/modules/bluetoothradio/bluetoothradio.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio" - bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options); void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options); void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options); diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 070070a01..324bfe95b 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -14,24 +14,24 @@ bool ffPrintBoard(FFBoardOptions* options) { const char* error = ffDetectBoard(&result); if (error) { - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (result.name.length == 0) { - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "board_name is not set."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "board_name is not set."); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.name, stdout); if (result.version.length) { printf(" (%s)", result.version.chars); } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.name, "name"), FF_ARG(result.vendor, "vendor"), FF_ARG(result.version, "version"), @@ -56,7 +56,7 @@ void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -108,7 +108,7 @@ void ffDestroyBoardOptions(FFBoardOptions* options) { } FFModuleBaseInfo ffBoardModuleInfo = { - .name = FF_BOARD_MODULE_NAME, + .name = "Board", .description = "Print motherboard name and other information", .displayName = { .en = "Board", diff --git a/src/modules/board/board.h b/src/modules/board/board.h index eae3d73c1..af819fbba 100644 --- a/src/modules/board/board.h +++ b/src/modules/board/board.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BOARD_MODULE_NAME "Board" - bool ffPrintBoard(FFBoardOptions* options); void ffInitBoardOptions(FFBoardOptions* options); void ffDestroyBoardOptions(FFBoardOptions* options); diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 037de24bd..d45030225 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -14,7 +14,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) { const char* error = ffDetectBootmgr(&bootmgr); if (error) { - ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } else { FF_STRBUF_AUTO_DESTROY firmwareName = ffStrbufCreateCopy(&bootmgr.firmware); @@ -25,7 +25,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) { #endif if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&bootmgr.name, stdout); if (firmwareName.length > 0) { printf(" - %s\n", firmwareName.chars); @@ -33,7 +33,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) { putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(bootmgr.name, "name"), FF_ARG(bootmgr.firmware, "firmware-path"), FF_ARG(firmwareName, "firmware-name"), @@ -59,7 +59,7 @@ void ffParseBootmgrJsonObject(FFBootmgrOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -103,7 +103,7 @@ void ffDestroyBootmgrOptions(FFBootmgrOptions* options) { } FFModuleBaseInfo ffBootmgrModuleInfo = { - .name = FF_BOOTMGR_MODULE_NAME, + .name = "Bootmgr", .description = "Print second-stage bootloader information (name, firmware, etc.)", .displayName = { .en = "Boot Manager", diff --git a/src/modules/bootmgr/bootmgr.h b/src/modules/bootmgr/bootmgr.h index 4f6a2bac2..947163bd5 100644 --- a/src/modules/bootmgr/bootmgr.h +++ b/src/modules/bootmgr/bootmgr.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BOOTMGR_MODULE_NAME "Bootmgr" - bool ffPrintBootmgr(FFBootmgrOptions* options); void ffInitBootmgrOptions(FFBootmgrOptions* options); void ffDestroyBootmgrOptions(FFBootmgrOptions* options); diff --git a/src/modules/break/break.c b/src/modules/break/break.c index c627f339b..b66963ecd 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -16,7 +16,7 @@ void ffParseBreakJsonObject([[maybe_unused]] FFBreakOptions* options, [[maybe_un continue; } - ffPrintError(FF_BREAK_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Break), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -27,7 +27,7 @@ void ffDestroyBreakOptions([[maybe_unused]] FFBreakOptions* options) { } FFModuleBaseInfo ffBreakModuleInfo = { - .name = FF_BREAK_MODULE_NAME, + .name = "Break", .description = "Print an empty line", .displayName = { .en = "Break", diff --git a/src/modules/break/break.h b/src/modules/break/break.h index f611b7379..9b11ebad8 100644 --- a/src/modules/break/break.h +++ b/src/modules/break/break.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BREAK_MODULE_NAME "Break" - bool ffPrintBreak(FFBreakOptions* options); void ffInitBreakOptions(FFBreakOptions* options); void ffDestroyBreakOptions(FFBreakOptions* options); diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 835711c2c..28fa28be0 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -11,12 +11,12 @@ bool ffPrintBrightness(FFBrightnessOptions* options) { const char* error = ffDetectBrightness(options, &result); if (error) { - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result is detected."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result is detected."); return false; } @@ -34,7 +34,7 @@ bool ffPrintBrightness(FFBrightnessOptions* options) { ffPercentAppendNum(&str, percent, options->percent, false, &options->moduleArgs); } - ffPrintLogoAndKey(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&str, stdout); return true; } @@ -44,7 +44,7 @@ bool ffPrintBrightness(FFBrightnessOptions* options) { uint32_t index = 0; FF_LIST_FOR_EACH (FFBrightnessResult, item, result) { if (options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_BRIGHTNESS_MODULE_NAME, item->name.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Brightness), item->name.chars); } else { uint32_t moduleIndex = result.length == 1 ? 0 : index + 1; FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -130,7 +130,7 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul continue; } - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -190,7 +190,7 @@ void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { } FFModuleBaseInfo ffBrightnessModuleInfo = { - .name = FF_BRIGHTNESS_MODULE_NAME, + .name = "Brightness", .description = "Print the current brightness level of your monitors", .displayName = { .en = "Brightness", diff --git a/src/modules/brightness/brightness.h b/src/modules/brightness/brightness.h index 085366141..0e03c1ce3 100644 --- a/src/modules/brightness/brightness.h +++ b/src/modules/brightness/brightness.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BRIGHTNESS_MODULE_NAME "Brightness" - bool ffPrintBrightness(FFBrightnessOptions* options); void ffInitBrightnessOptions(FFBrightnessOptions* options); void ffDestroyBrightnessOptions(FFBrightnessOptions* options); diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 12ed8977b..442a4406d 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -10,9 +10,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (result->name.length > 0) { - ffStrbufSetF(&buffer, "%s (%s)", FF_BTRFS_MODULE_NAME, result->name.chars); + ffStrbufSetF(&buffer, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Btrfs), result->name.chars); } else { - ffStrbufSetS(&buffer, FF_BTRFS_MODULE_NAME); + ffStrbufSetS(&buffer, FF_MODULE_GET_DISPLAY_NAME(Btrfs)); } } else { ffStrbufClear(&buffer); @@ -100,11 +100,11 @@ bool ffPrintBtrfs(FFBtrfsOptions* options) { const char* error = ffDetectBtrfs(&results); if (error) { - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No btrfs drive found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No btrfs drive found"); return false; } @@ -136,7 +136,7 @@ void ffParseBtrfsJsonObject(FFBtrfsOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -198,7 +198,7 @@ void ffDestroyBtrfsOptions(FFBtrfsOptions* options) { } FFModuleBaseInfo ffBtrfsModuleInfo = { - .name = FF_BTRFS_MODULE_NAME, + .name = "Btrfs", .description = "Print Linux BTRFS volumes", .displayName = { .en = "BTRFS", diff --git a/src/modules/btrfs/btrfs.h b/src/modules/btrfs/btrfs.h index fc0c6abf4..813ff8a2b 100644 --- a/src/modules/btrfs/btrfs.h +++ b/src/modules/btrfs/btrfs.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BTRFS_MODULE_NAME "Btrfs" - bool ffPrintBtrfs(FFBtrfsOptions* options); void ffInitBtrfsOptions(FFBtrfsOptions* options); void ffDestroyBtrfsOptions(FFBtrfsOptions* options); diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 4a35509c0..f74831065 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -5,7 +5,7 @@ static void printDevice(FFCameraOptions* options, const FFCameraResult* device, uint8_t index) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&device->name, stdout); if (device->colorspace.length > 0) { @@ -19,7 +19,7 @@ static void printDevice(FFCameraOptions* options, const FFCameraResult* device, putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->vendor, "vendor"), FF_ARG(device->colorspace, "colorspace"), @@ -35,12 +35,12 @@ bool ffPrintCamera(FFCameraOptions* options) { const char* error = ffDetectCamera(&result); if (error) { - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found"); return false; } @@ -67,7 +67,7 @@ void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -115,7 +115,7 @@ void ffDestroyCameraOptions(FFCameraOptions* options) { } FFModuleBaseInfo ffCameraModuleInfo = { - .name = FF_CAMERA_MODULE_NAME, + .name = "Camera", .description = "Print available cameras", .displayName = { .en = "Camera", diff --git a/src/modules/camera/camera.h b/src/modules/camera/camera.h index e8b356040..f87a8595e 100644 --- a/src/modules/camera/camera.h +++ b/src/modules/camera/camera.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CAMERA_MODULE_NAME "Camera" - bool ffPrintCamera(FFCameraOptions* options); void ffInitCameraOptions(FFCameraOptions* options); void ffDestroyCameraOptions(FFCameraOptions* options); diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 2a88c5c89..ae25f19b6 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -16,24 +16,24 @@ bool ffPrintChassis(FFChassisOptions* options) { const char* error = ffDetectChassis(&result); if (error) { - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (result.type.length == 0) { - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "chassis_type is not set by O.E.M."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "chassis_type is not set by O.E.M."); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.type, stdout); if (result.version.length) { printf(" (%s)", result.version.chars); } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.type, "type"), FF_ARG(result.vendor, "vendor"), FF_ARG(result.version, "version"), @@ -58,7 +58,7 @@ void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -110,7 +110,7 @@ void ffDestroyChassisOptions(FFChassisOptions* options) { } FFModuleBaseInfo ffChassisModuleInfo = { - .name = FF_CHASSIS_MODULE_NAME, + .name = "Chassis", .description = "Print chassis type information (desktop, laptop, etc.)", .displayName = { .en = "Chassis", diff --git a/src/modules/chassis/chassis.h b/src/modules/chassis/chassis.h index d3ba4892c..a57f7b876 100644 --- a/src/modules/chassis/chassis.h +++ b/src/modules/chassis/chassis.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CHASSIS_MODULE_NAME "Chassis" - bool ffPrintChassis(FFChassisOptions* options); void ffInitChassisOptions(FFChassisOptions* options); void ffDestroyChassisOptions(FFChassisOptions* options); diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index f55ed20e5..f71dfe283 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -51,9 +51,9 @@ static void printCodecLine(const FFCodecOptions* options, uint8_t index, FFstrbu FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (gpu->length > 0) { - ffStrbufSetF(&key, "%s (%s - %s)", FF_CODEC_MODULE_NAME, direction, gpu->chars); + ffStrbufSetF(&key, "%s (%s - %s)", FF_MODULE_GET_DISPLAY_NAME(Codec), direction, gpu->chars); } else { - ffStrbufSetF(&key, "%s (%s)", FF_CODEC_MODULE_NAME, direction); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Codec), direction); } } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]){ @@ -100,12 +100,12 @@ bool ffPrintCodec(FFCodecOptions* options) { const char* error = ffDetectCodec(options, &result); if (error) { - ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found"); return false; } @@ -174,14 +174,14 @@ void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_CODEC_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->showType = (FFCodecShowType) value; } continue; } - ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -251,7 +251,7 @@ void ffDestroyCodecOptions(FFCodecOptions* options) { } FFModuleBaseInfo ffCodecModuleInfo = { - .name = FF_CODEC_MODULE_NAME, + .name = "Codec", .description = "Print hardware video acceleration codec types (decode / encode)", .displayName = { .en = "Codec", diff --git a/src/modules/codec/codec.h b/src/modules/codec/codec.h index efd3d7c01..20b9fbd35 100644 --- a/src/modules/codec/codec.h +++ b/src/modules/codec/codec.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CODEC_MODULE_NAME "Codec" - bool ffPrintCodec(FFCodecOptions* options); void ffInitCodecOptions(FFCodecOptions* options); void ffDestroyCodecOptions(FFCodecOptions* options); diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ba6890c67..ac1ef742f 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -37,7 +37,7 @@ bool ffPrintColors(FFColorsOptions* options) { } } if (result.length > 0) { - ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); flag = true; if (options->paddingLeft > 0) { @@ -122,7 +122,7 @@ bool ffPrintColors(FFColorsOptions* options) { if (flag) { ffLogoPrintLine(); } else { - ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); flag = true; } @@ -136,7 +136,7 @@ bool ffPrintColors(FFColorsOptions* options) { } if (!flag) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Nothing to print"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Nothing to print"); return false; } @@ -164,7 +164,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->symbol = (FFColorsSymbol) value; } @@ -178,7 +178,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "block")) { if (!yyjson_is_obj(val)) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key)); } else { yyjson_val* width = yyjson_obj_get(val, "width"); if (width) { @@ -188,14 +188,14 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { yyjson_val* range = yyjson_obj_get(val, "range"); if (range) { if (!yyjson_is_arr(range) || yyjson_arr_size(range) != 2) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key)); } else { uint8_t start = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 0)); uint8_t end = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 1)); if (start > end) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key)); } else if (end > 15) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key)); } else { options->block.range[0] = start; options->block.range[1] = end; @@ -215,14 +215,14 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->brightness = (FFColorsBrightness) value; } continue; } - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -295,7 +295,7 @@ void ffDestroyColorsOptions(FFColorsOptions* options) { } FFModuleBaseInfo ffColorsModuleInfo = { - .name = FF_COLORS_MODULE_NAME, + .name = "Colors", .description = "Display the terminal's 16-color palette", .displayName = { .en = "Colors", diff --git a/src/modules/colors/colors.h b/src/modules/colors/colors.h index c88ccd7a5..d7558aff7 100644 --- a/src/modules/colors/colors.h +++ b/src/modules/colors/colors.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_COLORS_MODULE_NAME "Colors" - bool ffPrintColors(FFColorsOptions* options); void ffInitColorsOptions(FFColorsOptions* options); void ffDestroyColorsOptions(FFColorsOptions* options); diff --git a/src/modules/command/command.c b/src/modules/command/command.c index b86da3a17..d606e033f 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -8,12 +8,12 @@ bool ffPrintCommand(FFCommandOptions* options) { const char* error = ffDetectCommand(options, &result); if (error) { - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result generated"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result generated"); return false; } @@ -23,18 +23,18 @@ bool ffPrintCommand(FFCommandOptions* options) { size_t len = 0; while (ffStrbufGetline(&line, &len, &result)) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Command), ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(line); } else { - FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(line, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Command), ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(line, "result") })); } } } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&result, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result") })); } } @@ -79,7 +79,7 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -153,7 +153,7 @@ void ffDestroyCommandOptions(FFCommandOptions* options) { } FFModuleBaseInfo ffCommandModuleInfo = { - .name = FF_COMMAND_MODULE_NAME, + .name = "Command", .description = "Run custom shell scripts", .displayName = { .en = "Command", diff --git a/src/modules/command/command.h b/src/modules/command/command.h index e0e143e01..bd55f3fbd 100644 --- a/src/modules/command/command.h +++ b/src/modules/command/command.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_COMMAND_MODULE_NAME "Command" - bool ffPrepareCommand(FFCommandOptions* options); bool ffPrintCommand(FFCommandOptions* options); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 5cccddba2..20236c9dd 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -23,9 +23,9 @@ bool ffPrintCPU(FFCPUOptions* options) { const char* error = ffDetectCPU(options, &cpu); if (error) { - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); } else if (cpu.vendor.length == 0 && cpu.name.length == 0 && cpu.coresOnline <= 1) { - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No CPU detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No CPU detected"); } else { FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate(); if (options->showPeCoreCount) { @@ -43,7 +43,7 @@ bool ffPrintCPU(FFCPUOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); @@ -85,7 +85,7 @@ bool ffPrintCPU(FFCPUOptions* options) { FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); - FF_PRINT_FORMAT_CHECKED(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(cpu.name, "name"), FF_ARG(cpu.vendor, "vendor"), FF_ARG(cpu.coresPhysical, "cores-physical"), @@ -131,7 +131,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) { } if (unsafe_yyjson_equals_str(key, "freqNdigits")) { - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits"); continue; } @@ -140,7 +140,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -251,7 +251,7 @@ void ffDestroyCPUOptions(FFCPUOptions* options) { } FFModuleBaseInfo ffCPUModuleInfo = { - .name = FF_CPU_MODULE_NAME, + .name = "CPU", .description = "Print CPU name, frequency, etc.", .displayName = { .en = "CPU", diff --git a/src/modules/cpu/cpu.h b/src/modules/cpu/cpu.h index 33fff6bf5..ce816a772 100644 --- a/src/modules/cpu/cpu.h +++ b/src/modules/cpu/cpu.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CPU_MODULE_NAME "CPU" - bool ffPrintCPU(FFCPUOptions* options); void ffInitCPUOptions(FFCPUOptions* options); void ffDestroyCPUOptions(FFCPUOptions* options); diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 4fe29a735..1c5c3e858 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -5,8 +5,6 @@ #include "detection/cpucache/cpucache.h" #include "modules/cpucache/cpucache.h" -#define FF_CPUCACHE_DISPLAY_NAME "CPU Cache" - static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOptions* options) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); @@ -16,7 +14,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption ffStrbufClear(&key); levelStr[1] = (char) ('1' + i); if (options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_CPUCACHE_DISPLAY_NAME, levelStr); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(CPUCache), levelStr); } else { uint32_t index = i + 1; FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -88,12 +86,12 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&buffer, stdout); } else { FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); ffSizeAppendNum(sum, &buffer2); - FF_PRINT_FORMAT_CHECKED(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(buffer, "result"), FF_ARG(buffer2, "sum"), })); @@ -114,7 +112,7 @@ bool ffPrintCPUCache(FFCPUCacheOptions* options) { const char* error = ffDetectCPUCache(&result); if (error) { - ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } @@ -147,7 +145,7 @@ void ffParseCPUCacheJsonObject(FFCPUCacheOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -223,7 +221,7 @@ void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options) { } FFModuleBaseInfo ffCPUCacheModuleInfo = { - .name = FF_CPUCACHE_MODULE_NAME, + .name = "CPUCache", .description = "Print CPU cache sizes", .displayName = { .en = "CPU Cache", diff --git a/src/modules/cpucache/cpucache.h b/src/modules/cpucache/cpucache.h index 5061b4441..2bc16fe5f 100644 --- a/src/modules/cpucache/cpucache.h +++ b/src/modules/cpucache/cpucache.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CPUCACHE_MODULE_NAME "CPUCache" - bool ffPrintCPUCache(FFCPUCacheOptions* options); void ffInitCPUCacheOptions(FFCPUCacheOptions* options); void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options); diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index d9d342bb9..5c9a4135a 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -5,14 +5,12 @@ #include "detection/cpuusage/cpuusage.h" #include "modules/cpuusage/cpuusage.h" -#define FF_CPUUSAGE_DISPLAY_NAME "CPU Usage" - bool ffPrintCPUUsage(FFCPUUsageOptions* options) { FF_LIST_AUTO_DESTROY percentages = ffListCreate(); const char* error = ffGetCpuUsageResult(options, &percentages); if (error) { - ffPrintError(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -54,7 +52,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (!options->separate) { @@ -102,7 +100,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options) { ffPercentAppendBar(&maxBar, maxValue, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(avgNum, "avg"), FF_ARG(maxNum, "max"), FF_ARG(maxIndex, "max-index"), @@ -139,7 +137,7 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -181,7 +179,7 @@ void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) { } FFModuleBaseInfo ffCPUUsageModuleInfo = { - .name = FF_CPUUSAGE_MODULE_NAME, + .name = "CPUUsage", .description = "Print CPU usage. Collecting data takes some time", .displayName = { .en = "CPU Usage", diff --git a/src/modules/cpuusage/cpuusage.h b/src/modules/cpuusage/cpuusage.h index efa8b485c..bd009a833 100644 --- a/src/modules/cpuusage/cpuusage.h +++ b/src/modules/cpuusage/cpuusage.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CPUUSAGE_MODULE_NAME "CPUUsage" - void ffPrepareCPUUsage(); bool ffPrintCPUUsage(FFCPUUsageOptions* options); diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 74c8c65e5..04808456f 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -14,7 +14,7 @@ bool ffPrintCursor(FFCursorOptions* options) { ffDetectCursor(&result); if (result.error.length) { - ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result.error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result.error.chars); } else { ffStrbufRemoveIgnCaseEndS(&result.theme, "cursors"); ffStrbufRemoveIgnCaseEndS(&result.theme, "cursor"); @@ -25,7 +25,7 @@ bool ffPrintCursor(FFCursorOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.theme, stdout); if (result.size.length > 0 && !ffStrbufEqualS(&result.size, "0")) { @@ -34,7 +34,7 @@ bool ffPrintCursor(FFCursorOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.theme, "theme"), FF_ARG(result.size, "size"), })); @@ -58,7 +58,7 @@ void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -100,7 +100,7 @@ void ffDestroyCursorOptions(FFCursorOptions* options) { } FFModuleBaseInfo ffCursorModuleInfo = { - .name = FF_CURSOR_MODULE_NAME, + .name = "Cursor", .description = "Print cursor style name", .displayName = { .en = "Cursor", diff --git a/src/modules/cursor/cursor.h b/src/modules/cursor/cursor.h index e7695692c..e94a259b5 100644 --- a/src/modules/cursor/cursor.h +++ b/src/modules/cursor/cursor.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CURSOR_MODULE_NAME "Cursor" - bool ffPrintCursor(FFCursorOptions* options); void ffInitCursorOptions(FFCursorOptions* options); void ffDestroyCursorOptions(FFCursorOptions* options); diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 0806be5b5..e728b634b 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -5,7 +5,7 @@ #include "modules/custom/custom.h" bool ffPrintCustom(FFCustomOptions* options) { - ffPrintFormat(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {})); + ffPrintFormat(FF_MODULE_GET_DISPLAY_NAME(Custom), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {})); return true; } @@ -21,7 +21,7 @@ void ffParseCustomJsonObject(FFCustomOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Custom), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -35,7 +35,7 @@ void ffDestroyCustomOptions(FFCustomOptions* options) { } FFModuleBaseInfo ffCustomModuleInfo = { - .name = FF_CUSTOM_MODULE_NAME, + .name = "Custom", .description = "Print a custom string, with or without key", .displayName = { .en = "Custom", diff --git a/src/modules/custom/custom.h b/src/modules/custom/custom.h index 628a621a3..f84dd1266 100644 --- a/src/modules/custom/custom.h +++ b/src/modules/custom/custom.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CUSTOM_MODULE_NAME "Custom" - bool ffPrintCustom(FFCustomOptions* options); void ffInitCustomOptions(FFCustomOptions* options); void ffDestroyCustomOptions(FFCustomOptions* options); diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index b8bbb6d43..347b81d53 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -8,8 +8,6 @@ #pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format -#define FF_DATETIME_DISPLAY_NAME "Date & Time" - typedef struct FFDateTimeResult { // Examples for 21.02.2022 - 15:18:37 uint16_t year; // 2022 @@ -67,7 +65,7 @@ static void printDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) { strftime(result.amPm, sizeof(result.amPm), "%p", tm); FF_PRINT_FORMAT_CHECKED( - FF_DATETIME_DISPLAY_NAME, + FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, moduleArgs, FF_PRINT_TYPE_DEFAULT, @@ -112,11 +110,11 @@ bool ffPrintDateTime(FFDateTimeOptions* options) { char buffer[32]; if (strftime(buffer, ARRAY_SIZE(buffer), "%F %T", tm) == 0) // yyyy-MM-dd HH:mm:ss { - ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "strftime() failed"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "strftime() failed"); return false; } - ffPrintLogoAndKey(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(buffer); return true; @@ -130,7 +128,7 @@ void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -152,7 +150,7 @@ void ffDestroyDateTimeOptions(FFDateTimeOptions* options) { } FFModuleBaseInfo ffDateTimeModuleInfo = { - .name = FF_DATETIME_MODULE_NAME, + .name = "DateTime", .description = "Print the current date and time", .displayName = { .en = "Date & Time", diff --git a/src/modules/datetime/datetime.h b/src/modules/datetime/datetime.h index 29c6f54e4..44123ed1a 100644 --- a/src/modules/datetime/datetime.h +++ b/src/modules/datetime/datetime.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DATETIME_MODULE_NAME "DateTime" - bool ffPrintDateTime(FFDateTimeOptions* options); void ffInitDateTimeOptions(FFDateTimeOptions* options); void ffDestroyDateTimeOptions(FFDateTimeOptions* options); diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 3111343d7..628cf49b4 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -9,7 +9,7 @@ bool ffPrintDE(FFDEOptions* options) { const FFDisplayServerResult* result = ffConnectDisplayServer(); if (result->dePrettyName.length == 0) { - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No DE found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No DE found"); return false; } @@ -17,7 +17,7 @@ bool ffPrintDE(FFDEOptions* options) { ffDetectDEVersion(&result->dePrettyName, &version, options); if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result->dePrettyName, stdout); @@ -28,7 +28,7 @@ bool ffPrintDE(FFDEOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->deProcessName, "process-name"), FF_ARG(result->dePrettyName, "pretty-name"), FF_ARG(version, "version") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->deProcessName, "process-name"), FF_ARG(result->dePrettyName, "pretty-name"), FF_ARG(version, "version") })); } return true; @@ -43,11 +43,11 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module) { } if (unsafe_yyjson_equals_str(key, "slowVersionDetection")) { - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true"); continue; } - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -82,7 +82,7 @@ void ffDestroyDEOptions(FFDEOptions* options) { } FFModuleBaseInfo ffDEModuleInfo = { - .name = FF_DE_MODULE_NAME, + .name = "DE", .description = "Print desktop environment name", .displayName = { .en = "Desktop Environment", diff --git a/src/modules/de/de.h b/src/modules/de/de.h index 8aaf642d0..857524bd7 100644 --- a/src/modules/de/de.h +++ b/src/modules/de/de.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DE_MODULE_NAME "DE" - bool ffPrintDE(FFDEOptions* options); void ffInitDEOptions(FFDEOptions* options); void ffDestroyDEOptions(FFDEOptions* options); diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 891d2af61..11d696294 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -16,7 +16,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(&key, "%s (%s)", FF_DISK_MODULE_NAME, disk->mountpoint.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Disk), disk->mountpoint.chars); } else { FF_STRBUF_AUTO_DESTROY mountpointLink = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY nameLink = ffStrbufCreate(); @@ -187,12 +187,12 @@ bool ffPrintDisk(FFDiskOptions* options) { const char* error = ffDetectDisks(options, &disks); if (error) { - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Disk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (disks.length == 0) { - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disks found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Disk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disks found"); return false; } @@ -327,7 +327,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Disk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -451,7 +451,7 @@ void ffDestroyDiskOptions(FFDiskOptions* options) { } FFModuleBaseInfo ffDiskModuleInfo = { - .name = FF_DISK_MODULE_NAME, + .name = "Disk", .description = "Print partitions, space usage, file system, etc", .displayName = { .en = "Disk", diff --git a/src/modules/disk/disk.h b/src/modules/disk/disk.h index 5f7820ac7..4d5bf76ad 100644 --- a/src/modules/disk/disk.h +++ b/src/modules/disk/disk.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DISK_MODULE_NAME "Disk" - bool ffPrintDisk(FFDiskOptions* options); void ffInitDiskOptions(FFDiskOptions* options); void ffDestroyDiskOptions(FFDiskOptions* options); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 5f31a1eb1..9acfbe511 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -5,15 +5,13 @@ #include "detection/diskio/diskio.h" #include "modules/diskio/diskio.h" -#define FF_DISKIO_DISPLAY_NAME "Disk IO" - static int sortDevices(const FFDiskIOResult* left, const FFDiskIOResult* right) { return ffStrbufComp(&left->name, &right->name); } static void formatKey(const FFDiskIOOptions* options, FFDiskIOResult* dev, uint32_t index, FFstrbuf* key) { if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(key, FF_DISKIO_DISPLAY_NAME " (%s)", dev->name.length ? dev->name.chars : dev->devPath.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(DiskIO), dev->name.length ? dev->name.chars : dev->devPath.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -30,7 +28,7 @@ bool ffPrintDiskIO(FFDiskIOOptions* options) { const char* error = ffDetectDiskIO(&result, options); if (error) { - ffPrintError(FF_DISKIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DiskIO), 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error); return false; } @@ -116,7 +114,7 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DiskIO), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -172,7 +170,7 @@ void ffDestroyDiskIOOptions(FFDiskIOOptions* options) { } FFModuleBaseInfo ffDiskIOModuleInfo = { - .name = FF_DISKIO_MODULE_NAME, + .name = "DiskIO", .description = "Print physical disk I/O throughput", .displayName = { .en = "Disk I/O", diff --git a/src/modules/diskio/diskio.h b/src/modules/diskio/diskio.h index 7fba81c9d..4bbfc3492 100644 --- a/src/modules/diskio/diskio.h +++ b/src/modules/diskio/diskio.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DISKIO_MODULE_NAME "DiskIO" - void ffPrepareDiskIO(FFDiskIOOptions* options); bool ffPrintDiskIO(FFDiskIOOptions* options); diff --git a/src/modules/display/display.c b/src/modules/display/display.c index e6870538a..2df6c787c 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -19,7 +19,7 @@ bool ffPrintDisplay(FFDisplayOptions* options) { const FFDisplayServerResult* dsResult = ffConnectDisplayServer(); if (dsResult->displays.length == 0) { - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect display"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect display"); return false; } @@ -28,7 +28,7 @@ bool ffPrintDisplay(FFDisplayOptions* options) { } if (options->compactType != FF_DISPLAY_COMPACT_TYPE_NONE) { - ffPrintLogoAndKey(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_LIST_FOR_EACH (FFDisplayResult, result, dsResult->displays) { @@ -71,11 +71,11 @@ bool ffPrintDisplay(FFDisplayOptions* options) { ffStrbufClear(&key); if (options->moduleArgs.key.length == 0) { if (result->name.length) { - ffStrbufAppendF(&key, "%s (%s)", FF_DISPLAY_MODULE_NAME, result->name.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Display), result->name.chars); } else if (moduleIndex > 0) { - ffStrbufAppendF(&key, "%s (%d)", FF_DISPLAY_MODULE_NAME, moduleIndex); + ffStrbufAppendF(&key, "%s (%d)", FF_MODULE_GET_DISPLAY_NAME(Display), moduleIndex); } else { - ffStrbufAppendS(&key, FF_DISPLAY_MODULE_NAME); + ffStrbufAppendS(&key, FF_MODULE_GET_DISPLAY_NAME(Display)); } } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -221,7 +221,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->compactType = (FFDisplayCompactType) value; } @@ -246,7 +246,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->order = (FFDisplayOrder) value; } @@ -254,7 +254,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -411,7 +411,7 @@ void ffDestroyDisplayOptions(FFDisplayOptions* options) { } FFModuleBaseInfo ffDisplayModuleInfo = { - .name = FF_DISPLAY_MODULE_NAME, + .name = "Display", .description = "Print resolutions, refresh rates, etc", .displayName = { .en = "Display", diff --git a/src/modules/display/display.h b/src/modules/display/display.h index a0a4b3095..c74e734d5 100644 --- a/src/modules/display/display.h +++ b/src/modules/display/display.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DISPLAY_MODULE_NAME "Display" - bool ffPrintDisplay(FFDisplayOptions* options); void ffInitDisplayOptions(FFDisplayOptions* options); void ffDestroyDisplayOptions(FFDisplayOptions* options); diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 7524434c6..6e63c44d8 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -10,12 +10,12 @@ bool ffPrintDNS(FFDNSOptions* options) { const char* error = ffDetectDNS(options, &result); if (error) { - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "NO DNS servers detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "NO DNS servers detected"); return false; } @@ -40,11 +40,11 @@ bool ffPrintDNS(FFDNSOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&buf, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(buf, "result"), })); } @@ -73,14 +73,14 @@ void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_DNS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->showType = (FFDNSShowType) value; } continue; } - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -134,7 +134,7 @@ void ffDestroyDNSOptions(FFDNSOptions* options) { } FFModuleBaseInfo ffDNSModuleInfo = { - .name = FF_DNS_MODULE_NAME, + .name = "DNS", .description = "Print configured DNS servers", .displayName = { .en = "DNS", diff --git a/src/modules/dns/dns.h b/src/modules/dns/dns.h index aec4e85fc..6fbffe33d 100644 --- a/src/modules/dns/dns.h +++ b/src/modules/dns/dns.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DNS_MODULE_NAME "DNS" - bool ffPrintDNS(FFDNSOptions* options); void ffInitDNSOptions(FFDNSOptions* options); void ffDestroyDNSOptions(FFDNSOptions* options); diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index b1a7438fc..de3e5c96c 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -16,12 +16,12 @@ bool ffPrintEditor(FFEditorOptions* options) { const char* error = ffDetectEditor(&result); if (error) { - ffPrintError(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.exe.length) { ffStrbufWriteTo(&result.exe, stdout); if (result.version.length) { @@ -32,7 +32,7 @@ bool ffPrintEditor(FFEditorOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.type, "type"), FF_ARG(result.name, "name"), FF_ARG(result.exe, "exe-name"), @@ -57,7 +57,7 @@ void ffParseEditorJsonObject(FFEditorOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -103,7 +103,7 @@ void ffDestroyEditorOptions(FFEditorOptions* options) { } FFModuleBaseInfo ffEditorModuleInfo = { - .name = FF_EDITOR_MODULE_NAME, + .name = "Editor", .description = "Print information about the default editor ($VISUAL or $EDITOR)", .displayName = { .en = "Editor", diff --git a/src/modules/editor/editor.h b/src/modules/editor/editor.h index 293d0a6e1..19d48b756 100644 --- a/src/modules/editor/editor.h +++ b/src/modules/editor/editor.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_EDITOR_MODULE_NAME "Editor" - bool ffPrintEditor(FFEditorOptions* options); void ffInitEditorOptions(FFEditorOptions* options); void ffDestroyEditorOptions(FFEditorOptions* options); diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 9763f257d..6df480717 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -15,13 +15,13 @@ bool ffPrintFont(FFFontOptions* options) { const char* error = ffDetectFont(&font); if (error) { - ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&font.display, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(font.fonts[0], "font1"), FF_ARG(font.fonts[1], "font2"), FF_ARG(font.fonts[2], "font3"), @@ -49,7 +49,7 @@ void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -95,7 +95,7 @@ void ffDestroyFontOptions(FFFontOptions* options) { } FFModuleBaseInfo ffFontModuleInfo = { - .name = FF_FONT_MODULE_NAME, + .name = "Font", .description = "Print system font names", .displayName = { .en = "Font", diff --git a/src/modules/font/font.h b/src/modules/font/font.h index b793b9fdd..9af717487 100644 --- a/src/modules/font/font.h +++ b/src/modules/font/font.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_FONT_MODULE_NAME "Font" - bool ffPrintFont(FFFontOptions* options); void ffInitFontOptions(FFFontOptions* options); void ffDestroyFontOptions(FFFontOptions* options); diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 8eb2cf720..c0e01b619 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -8,7 +8,7 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device, uint8_t index) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Gamepad), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); bool showBatteryLevel = device->battery > 0 && device->battery <= 100; @@ -39,7 +39,7 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Gamepad), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->serial, "serial"), FF_ARG(percentageNum, "battery-percentage"), @@ -54,12 +54,12 @@ bool ffPrintGamepad(FFGamepadOptions* options) { const char* error = ffDetectGamepad(&result); if (error) { - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); return false; } @@ -80,7 +80,7 @@ bool ffPrintGamepad(FFGamepadOptions* options) { bool ret = true; if (!filtered.length) { - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); ret = false; } else { uint8_t index = 0; @@ -122,7 +122,7 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -189,7 +189,7 @@ void ffDestroyGamepadOptions(FFGamepadOptions* options) { } FFModuleBaseInfo ffGamepadModuleInfo = { - .name = FF_GAMEPAD_MODULE_NAME, + .name = "Gamepad", .description = "List connected gamepads", .displayName = { .en = "Gamepad", diff --git a/src/modules/gamepad/gamepad.h b/src/modules/gamepad/gamepad.h index 395c90b2e..9855a7b72 100644 --- a/src/modules/gamepad/gamepad.h +++ b/src/modules/gamepad/gamepad.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_GAMEPAD_MODULE_NAME "Gamepad" - bool ffPrintGamepad(FFGamepadOptions* options); void ffInitGamepadOptions(FFGamepadOptions* options); void ffDestroyGamepadOptions(FFGamepadOptions* options); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index b11615464..d22f3436c 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -28,7 +28,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(GPU), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); @@ -145,7 +145,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu snprintf(currSpeed, sizeof(currSpeed), "%d x%d", gpu->psCurr.gen, gpu->psCurr.lanes); } - FF_PRINT_FORMAT_CHECKED(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(GPU), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(gpu->vendor, "vendor"), FF_ARG(gpu->name, "name"), FF_ARG(gpu->driver, "driver"), @@ -176,7 +176,7 @@ bool ffPrintGPU(FFGPUOptions* options) { FF_LIST_AUTO_DESTROY gpus = ffListCreate(); const char* error = ffDetectGPU(options, &gpus); if (error) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -213,7 +213,7 @@ bool ffPrintGPU(FFGPUOptions* options) { } if (selectedGPUs.length == 0) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (gpus.length > 0 ? "GPUs found but all hidden by hideType option" : "No GPUs detected")); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (gpus.length > 0 ? "GPUs found but all hidden by hideType option" : "No GPUs detected")); return false; } @@ -249,7 +249,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->detectionMethod = (FFGPUDetectionMethod) value; } @@ -269,7 +269,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->hideType = (FFGPUType) value; } @@ -281,7 +281,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -479,7 +479,7 @@ void ffDestroyGPUOptions(FFGPUOptions* options) { } FFModuleBaseInfo ffGPUModuleInfo = { - .name = FF_GPU_MODULE_NAME, + .name = "GPU", .description = "Print GPU names, memory sizes, types, etc", .displayName = { .en = "GPU", diff --git a/src/modules/gpu/gpu.h b/src/modules/gpu/gpu.h index e2a6f1424..c2a3c7a41 100644 --- a/src/modules/gpu/gpu.h +++ b/src/modules/gpu/gpu.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_GPU_MODULE_NAME "GPU" - bool ffPrintGPU(FFGPUOptions* options); void ffInitGPUOptions(FFGPUOptions* options); void ffDestroyGPUOptions(FFGPUOptions* options); diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 5a2e2a856..1fafa659a 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -17,17 +17,17 @@ bool ffPrintHost(FFHostOptions* options) { const char* error = ffDetectHost(&host); if (error) { - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (host.name.length == 0 && host.family.length == 0) { - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "neither product_family nor product_name is set by O.E.M."); + 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."); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); @@ -43,7 +43,7 @@ bool ffPrintHost(FFHostOptions* options) { ffStrbufPutTo(&output, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(host.family, "family"), FF_ARG(host.name, "name"), FF_ARG(host.version, "version"), @@ -75,7 +75,7 @@ void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -136,7 +136,7 @@ void ffDestroyHostOptions(FFHostOptions* options) { } FFModuleBaseInfo ffHostModuleInfo = { - .name = FF_HOST_MODULE_NAME, + .name = "Host", .description = "Print your computer's product name", .displayName = { .en = "Host", diff --git a/src/modules/host/host.h b/src/modules/host/host.h index 1f98fd406..cf2ed1871 100644 --- a/src/modules/host/host.h +++ b/src/modules/host/host.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_HOST_MODULE_NAME "Host" - bool ffPrintHost(FFHostOptions* options); void ffInitHostOptions(FFHostOptions* options); void ffDestroyHostOptions(FFHostOptions* options); diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 971a9655d..eaa1341bd 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -13,12 +13,12 @@ bool ffPrintIcons(FFIconsOptions* options) { const char* error = ffDetectIcons(&result); if (error) { - ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.icons1.length) { ffStrbufWriteTo(&result.icons1, stdout); } @@ -30,7 +30,7 @@ bool ffPrintIcons(FFIconsOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.icons1, "icons1"), FF_ARG(result.icons2, "icons2"), })); @@ -52,7 +52,7 @@ void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -94,7 +94,7 @@ void ffDestroyIconsOptions(FFIconsOptions* options) { } FFModuleBaseInfo ffIconsModuleInfo = { - .name = FF_ICONS_MODULE_NAME, + .name = "Icons", .description = "Print icon style name", .displayName = { .en = "Icons", diff --git a/src/modules/icons/icons.h b/src/modules/icons/icons.h index a583a2257..ee1e74f04 100644 --- a/src/modules/icons/icons.h +++ b/src/modules/icons/icons.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_ICONS_MODULE_NAME "Icons" - bool ffPrintIcons(FFIconsOptions* options); void ffInitIconsOptions(FFIconsOptions* options); void ffDestroyIconsOptions(FFIconsOptions* options); diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index a6421f9f7..b5adbc906 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -4,8 +4,6 @@ #include "detection/initsystem/initsystem.h" #include "modules/initsystem/initsystem.h" -#define FF_INITSYSTEM_DISPLAY_NAME "Init System" - bool ffPrintInitSystem(FFInitSystemOptions* options) { bool success = false; FFInitSystemResult result = { @@ -18,12 +16,12 @@ bool ffPrintInitSystem(FFInitSystemOptions* options) { const char* error = ffDetectInitSystem(&result); if (error) { - ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.name, stdout); if (result.version.length) { printf(" %s\n", result.version.chars); @@ -31,7 +29,7 @@ bool ffPrintInitSystem(FFInitSystemOptions* options) { putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.name, "name"), FF_ARG(result.exe, "exe"), FF_ARG(result.version, "version"), @@ -56,7 +54,7 @@ void ffParseInitSystemJsonObject(FFInitSystemOptions* options, yyjson_val* modul continue; } - ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -103,7 +101,7 @@ void ffDestroyInitSystemOptions(FFInitSystemOptions* options) { } FFModuleBaseInfo ffInitSystemModuleInfo = { - .name = FF_INITSYSTEM_MODULE_NAME, + .name = "InitSystem", .description = "Print init system (pid 1) name and version", .displayName = { .en = "Init System", diff --git a/src/modules/initsystem/initsystem.h b/src/modules/initsystem/initsystem.h index 381b95543..f6379f595 100644 --- a/src/modules/initsystem/initsystem.h +++ b/src/modules/initsystem/initsystem.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_INITSYSTEM_MODULE_NAME "InitSystem" - bool ffPrintInitSystem(FFInitSystemOptions* options); void ffInitInitSystemOptions(FFInitSystemOptions* options); void ffDestroyInitSystemOptions(FFInitSystemOptions* options); diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 5cd76a0bb..055dd5fe1 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -7,12 +7,12 @@ bool ffPrintKernel(FFKernelOptions* options) { const FFPlatformSysinfo* info = &instance.state.platform.sysinfo; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Kernel), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%s %s\n", info->name.chars, info->release.chars); } else { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); ffSizeAppendNum(info->pageSize, &str); - FF_PRINT_FORMAT_CHECKED(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Kernel), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(info->name, "sysname"), FF_ARG(info->release, "release"), FF_ARG(info->version, "version"), @@ -32,7 +32,7 @@ void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Kernel), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -62,7 +62,7 @@ void ffDestroyKernelOptions(FFKernelOptions* options) { } FFModuleBaseInfo ffKernelModuleInfo = { - .name = FF_KERNEL_MODULE_NAME, + .name = "Kernel", .description = "Print system kernel version", .displayName = { .en = "Kernel", diff --git a/src/modules/kernel/kernel.h b/src/modules/kernel/kernel.h index 010ec54c4..faf621268 100644 --- a/src/modules/kernel/kernel.h +++ b/src/modules/kernel/kernel.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_KERNEL_MODULE_NAME "Kernel" - bool ffPrintKernel(FFKernelOptions* options); void ffInitKernelOptions(FFKernelOptions* options); void ffDestroyKernelOptions(FFKernelOptions* options); diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 00bfb1664..755ac6764 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -7,10 +7,10 @@ static void printDevice(FFKeyboardOptions* options, const FFKeyboardDevice* device, uint8_t index) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Keyboard), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&device->name, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Keyboard), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->serial, "serial"), })); @@ -23,12 +23,12 @@ bool ffPrintKeyboard(FFKeyboardOptions* options) { const char* error = ffDetectKeyboard(&result); if (error) { - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); return false; } @@ -49,7 +49,7 @@ bool ffPrintKeyboard(FFKeyboardOptions* options) { bool ret = true; if (!filtered.length) { - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); ret = false; } else { uint8_t index = 0; @@ -84,7 +84,7 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -149,7 +149,7 @@ void ffDestroyKeyboardOptions(FFKeyboardOptions* options) { } FFModuleBaseInfo ffKeyboardModuleInfo = { - .name = FF_KEYBOARD_MODULE_NAME, + .name = "Keyboard", .description = "List connected keyboards", .displayName = { .en = "Keyboard", diff --git a/src/modules/keyboard/keyboard.h b/src/modules/keyboard/keyboard.h index bd6e69c56..d862173a1 100644 --- a/src/modules/keyboard/keyboard.h +++ b/src/modules/keyboard/keyboard.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_KEYBOARD_MODULE_NAME "Keyboard" - bool ffPrintKeyboard(FFKeyboardOptions* options); void ffInitKeyboardOptions(FFKeyboardOptions* options); void ffDestroyKeyboardOptions(FFKeyboardOptions* options); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 8bfe44442..8c919056b 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -13,17 +13,17 @@ bool ffPrintLM(FFLMOptions* options) { const char* error = ffDetectLM(&result); if (error) { - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (result.service.length == 0) { - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No LM service found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No LM service found"); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.service, stdout); if (result.version.length) { printf(" %s", result.version.chars); @@ -33,7 +33,7 @@ bool ffPrintLM(FFLMOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.service, "service"), FF_ARG(result.type, "type"), FF_ARG(result.version, "version"), @@ -57,7 +57,7 @@ void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -106,7 +106,7 @@ void ffDestroyLMOptions(FFLMOptions* options) { } FFModuleBaseInfo ffLMModuleInfo = { - .name = FF_LM_MODULE_NAME, + .name = "LM", .description = "Print login manager (desktop manager) name and version", .displayName = { .en = "Login Manager", diff --git a/src/modules/lm/lm.h b/src/modules/lm/lm.h index 1ec33b649..8329d9b77 100644 --- a/src/modules/lm/lm.h +++ b/src/modules/lm/lm.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LM_MODULE_NAME "LM" - bool ffPrintLM(FFLMOptions* options); void ffInitLMOptions(FFLMOptions* options); void ffDestroyLMOptions(FFLMOptions* options); diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 8f6a8ed85..4bd0065e1 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -11,13 +11,13 @@ bool ffPrintLoadavg(FFLoadavgOptions* options) { const char* error = ffDetectLoadavg(result); if (error) { - ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { if (options->compact) { - ffPrintLogoAndKey(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%.*f, %.*f, %.*f\n", options->ndigits, result[0], options->ndigits, result[1], options->ndigits, result[2]); } else { FFCPUResult cpu = { @@ -34,7 +34,7 @@ bool ffPrintLoadavg(FFLoadavgOptions* options) { uint32_t duration = index == 0 ? 1 : index == 1 ? 5 : 15; if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(&buffer, "%s (%d min)", FF_LOADAVG_MODULE_NAME, duration); + ffStrbufSetF(&buffer, "%s (%d min)", FF_MODULE_GET_DISPLAY_NAME(Loadavg), duration); } else { ffStrbufClear(&buffer); FF_PARSE_FORMAT_STRING_CHECKED(&buffer, &options->moduleArgs.key, ((FFformatarg[]) { @@ -72,7 +72,7 @@ bool ffPrintLoadavg(FFLoadavgOptions* options) { } } } else { - FF_PRINT_FORMAT_CHECKED(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result[0], "loadavg1"), FF_ARG(result[1], "loadavg2"), FF_ARG(result[2], "loadavg3"), @@ -104,7 +104,7 @@ void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -148,7 +148,7 @@ void ffDestroyLoadavgOptions(FFLoadavgOptions* options) { } FFModuleBaseInfo ffLoadavgModuleInfo = { - .name = FF_LOADAVG_MODULE_NAME, + .name = "Loadavg", .description = "Print system load averages", .displayName = { .en = "Load Average", diff --git a/src/modules/loadavg/loadavg.h b/src/modules/loadavg/loadavg.h index 9af2786f9..8a2c6a8f5 100644 --- a/src/modules/loadavg/loadavg.h +++ b/src/modules/loadavg/loadavg.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOADAVG_MODULE_NAME "Loadavg" - bool ffPrintLoadavg(FFLoadavgOptions* options); void ffInitLoadavgOptions(FFLoadavgOptions* options); void ffDestroyLoadavgOptions(FFLoadavgOptions* options); diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 4bc3e9658..8d3f31474 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -8,15 +8,15 @@ bool ffPrintLocale(FFLocaleOptions* options) { const char* error = ffDetectLocale(&locale); if (error) { - ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&locale, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(locale, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(locale, "result") })); } return true; @@ -30,7 +30,7 @@ void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -67,7 +67,7 @@ void ffDestroyLocaleOptions(FFLocaleOptions* options) { } FFModuleBaseInfo ffLocaleModuleInfo = { - .name = FF_LOCALE_MODULE_NAME, + .name = "Locale", .description = "Print system locale name", .displayName = { .en = "Locale", diff --git a/src/modules/locale/locale.h b/src/modules/locale/locale.h index fd86e42c3..a5b6a0981 100644 --- a/src/modules/locale/locale.h +++ b/src/modules/locale/locale.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOCALE_MODULE_NAME "Locale" - bool ffPrintLocale(FFLocaleOptions* options); void ffInitLocaleOptions(FFLocaleOptions* options); void ffDestroyLocaleOptions(FFLocaleOptions* options); diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index bc438be7e..46319e97c 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -4,7 +4,6 @@ #include "detection/localip/localip.h" #include "modules/localip/localip.h" -#define FF_LOCALIP_DISPLAY_NAME "Local IP" #pragma GCC diagnostic ignored "-Wsign-conversion" static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) { @@ -17,7 +16,7 @@ static void formatKey(const FFLocalIpOptions* options, FFLocalIpResult* ip, uint ffStrbufSetF(&ip->name, "unknown %u", (unsigned) index); } - ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(LocalIP), ip->name.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -100,12 +99,12 @@ bool ffPrintLocalIp(FFLocalIpOptions* options) { const char* error = ffDetectLocalIps(options, &results); if (error) { - ffPrintError(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect any IPs"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect any IPs"); return false; } @@ -114,7 +113,7 @@ bool ffPrintLocalIp(FFLocalIpOptions* options) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT) { - ffPrintLogoAndKey(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_LIST_FOR_EACH (FFLocalIpResult, ip, results) { if (buffer.length) { @@ -201,7 +200,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->showType |= FF_LOCALIP_TYPE_IPV6_BIT; options->ipv6Type = (FFLocalIpIpv6Type) value; @@ -296,7 +295,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -422,7 +421,7 @@ void ffDestroyLocalIpOptions(FFLocalIpOptions* options) { } FFModuleBaseInfo ffLocalIPModuleInfo = { - .name = FF_LOCALIP_MODULE_NAME, + .name = "LocalIp", .description = "List local IP addresses (IPv4 or IPv6), MAC addresses, etc", .displayName = { .en = "Local IP", diff --git a/src/modules/localip/localip.h b/src/modules/localip/localip.h index f9e9c4e43..2580fac2e 100644 --- a/src/modules/localip/localip.h +++ b/src/modules/localip/localip.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOCALIP_MODULE_NAME "LocalIp" - bool ffPrintLocalIp(FFLocalIpOptions* options); void ffInitLocalIpOptions(FFLocalIpOptions* options); void ffDestroyLocalIpOptions(FFLocalIpOptions* options); diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 432a1fa82..0b68a64f6 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -4,7 +4,7 @@ #include "options/logo.h" bool ffPrintLogo([[maybe_unused]] FFLogoOptions* options) { - ffPrintError(FF_LOGO_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_DEFAULT, "Supported in JSON format only"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Logo), 0, nullptr, FF_PRINT_TYPE_DEFAULT, "Supported in JSON format only"); return false; } @@ -16,7 +16,7 @@ void ffParseLogoJsonObject([[maybe_unused]] FFLogoOptions* options, [[maybe_unus continue; } - ffPrintError(FF_LOGO_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Logo), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -77,7 +77,7 @@ void ffDestroyLogoOptions([[maybe_unused]] FFLogoOptions* options) { } FFModuleBaseInfo ffLogoModuleInfo = { - .name = FF_LOGO_MODULE_NAME, + .name = "Logo", .description = "Query built-in logo for JSON output", .displayName = { .en = "Logo", diff --git a/src/modules/logo/logo.h b/src/modules/logo/logo.h index 7f48e2dd6..af8ca7a0e 100644 --- a/src/modules/logo/logo.h +++ b/src/modules/logo/logo.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOGO_MODULE_NAME "Logo" - bool ffPrintLogo(FFLogoOptions* options); void ffInitLogoOptions(FFLogoOptions* options); void ffDestroyLogoOptions(FFLogoOptions* options); diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 80bc087be..08f550a5f 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -56,7 +56,7 @@ bool ffPrintMedia(FFMediaOptions* options) { const FFMediaResult* media = ffDetectMedia(false); if (media->error.length > 0) { - ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); return false; } @@ -110,7 +110,7 @@ bool ffPrintMedia(FFMediaOptions* options) { ffStrbufClear(&artistPretty); } - ffPrintLogoAndKey(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (artistPretty.length > 0) { ffStrbufWriteTo(&artistPretty, stdout); @@ -171,7 +171,7 @@ bool ffPrintMedia(FFMediaOptions* options) { &options->moduleArgs); } } - FF_PRINT_FORMAT_CHECKED(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_ARG(songPretty, "combined"), FF_ARG(media->song, "title"), FF_ARG(media->artist, "artist"), @@ -201,7 +201,7 @@ void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -253,7 +253,7 @@ void ffDestroyMediaOptions(FFMediaOptions* options) { } FFModuleBaseInfo ffMediaModuleInfo = { - .name = FF_MEDIA_MODULE_NAME, + .name = "Media", .description = "Print the name of the currently playing song", .displayName = { .en = "Media", diff --git a/src/modules/media/media.h b/src/modules/media/media.h index 8320227d8..10f995eaa 100644 --- a/src/modules/media/media.h +++ b/src/modules/media/media.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MEDIA_MODULE_NAME "Media" - bool ffPrintMedia(FFMediaOptions* options); void ffInitMediaOptions(FFMediaOptions* options); void ffDestroyMediaOptions(FFMediaOptions* options); diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 7a7f58e09..065808c29 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -11,7 +11,7 @@ bool ffPrintMemory(FFMemoryOptions* options) { const char* error = ffDetectMemory(&storage); if (error) { - ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -27,7 +27,7 @@ bool ffPrintMemory(FFMemoryOptions* options) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (storage.bytesTotal == 0) { puts("Disabled"); } else { @@ -59,7 +59,7 @@ bool ffPrintMemory(FFMemoryOptions* options) { ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(usedPretty, "used"), FF_ARG(totalPretty, "total"), FF_ARG(percentageNum, "percentage"), @@ -82,7 +82,7 @@ void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -118,7 +118,7 @@ void ffDestroyMemoryOptions(FFMemoryOptions* options) { } FFModuleBaseInfo ffMemoryModuleInfo = { - .name = FF_MEMORY_MODULE_NAME, + .name = "Memory", .description = "Print system memory usage information", .displayName = { .en = "Memory", diff --git a/src/modules/memory/memory.h b/src/modules/memory/memory.h index 7ed026fc3..7883da2d8 100644 --- a/src/modules/memory/memory.h +++ b/src/modules/memory/memory.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MEMORY_MODULE_NAME "Memory" - bool ffPrintMemory(FFMemoryOptions* options); void ffInitMemoryOptions(FFMemoryOptions* options); void ffDestroyMemoryOptions(FFMemoryOptions* options); diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 27911bccf..c5c9877c1 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -10,7 +10,7 @@ bool ffPrintMonitor(FFMonitorOptions* options) { const FFDisplayServerResult* result = ffConnectDisplayServer(); if (!result->displays.length) { - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Monitor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); return false; } @@ -23,7 +23,7 @@ bool ffPrintMonitor(FFMonitorOptions* options) { ffStrbufClear(&key); if (options->moduleArgs.key.length == 0) { - ffStrbufAppendS(&key, FF_MONITOR_MODULE_NAME); + ffStrbufAppendS(&key, FF_MODULE_GET_DISPLAY_NAME(Monitor)); if (display->name.length > 0) { ffStrbufAppendF(&key, " (%s)", display->name.chars); } @@ -82,7 +82,7 @@ void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Monitor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -104,7 +104,7 @@ void ffDestroyMonitorOptions(FFMonitorOptions* options) { } FFModuleBaseInfo ffMonitorModuleInfo = { - .name = FF_MONITOR_MODULE_NAME, + .name = "Monitor", .description = "Same as Display module, but with a different default output format", .displayName = { .en = "Monitor", diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h index 82f9491fe..598d22692 100644 --- a/src/modules/monitor/monitor.h +++ b/src/modules/monitor/monitor.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MONITOR_MODULE_NAME "Monitor" - bool ffPrintMonitor(FFMonitorOptions* options); void ffInitMonitorOptions(FFMonitorOptions* options); void ffDestroyMonitorOptions(FFMonitorOptions* options); diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index c14b6e998..dd8f8be6e 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -7,10 +7,10 @@ static void printDevice(FFMouseOptions* options, const FFMouseDevice* device, uint8_t index) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Mouse), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&device->name, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Mouse), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->serial, "serial"), })); @@ -23,12 +23,12 @@ bool ffPrintMouse(FFMouseOptions* options) { const char* error = ffDetectMouse(&result); if (error) { - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); return false; } @@ -49,7 +49,7 @@ bool ffPrintMouse(FFMouseOptions* options) { bool ret = true; if (!filtered.length) { - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); ret = false; } else { uint8_t index = 0; @@ -87,7 +87,7 @@ void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -152,7 +152,7 @@ void ffDestroyMouseOptions(FFMouseOptions* options) { } FFModuleBaseInfo ffMouseModuleInfo = { - .name = FF_MOUSE_MODULE_NAME, + .name = "Mouse", .description = "List connected mice", .displayName = { .en = "Mouse", diff --git a/src/modules/mouse/mouse.h b/src/modules/mouse/mouse.h index afbc20ff9..f042cbfa4 100644 --- a/src/modules/mouse/mouse.h +++ b/src/modules/mouse/mouse.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MOUSE_MODULE_NAME "Mouse" - bool ffPrintMouse(FFMouseOptions* options); void ffInitMouseOptions(FFMouseOptions* options); void ffDestroyMouseOptions(FFMouseOptions* options); diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index cad480b18..e062a55c8 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -5,8 +5,6 @@ #include "detection/netio/netio.h" #include "modules/netio/netio.h" -#define FF_NETIO_DISPLAY_NAME "Network IO" - static int sortInfs(const FFNetIOResult* left, const FFNetIOResult* right) { return ffStrbufComp(&left->name, &right->name); } @@ -17,7 +15,7 @@ static void formatKey(const FFNetIOOptions* options, FFNetIOResult* inf, uint32_ ffStrbufSetF(&inf->name, "unknown %u", (unsigned) index); } - ffStrbufSetF(key, FF_NETIO_DISPLAY_NAME " (%s)", inf->name.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(NetIO), inf->name.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -33,7 +31,7 @@ bool ffPrintNetIO(FFNetIOOptions* options) { const char* error = ffDetectNetIO(&result, options); if (error) { - ffPrintError(FF_NETIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(NetIO), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -131,7 +129,7 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(NetIO), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -199,7 +197,7 @@ void ffDestroyNetIOOptions(FFNetIOOptions* options) { } FFModuleBaseInfo ffNetIOModuleInfo = { - .name = FF_NETIO_MODULE_NAME, + .name = "NetIO", .description = "Print network I/O throughput", .displayName = { .en = "Network I/O", diff --git a/src/modules/netio/netio.h b/src/modules/netio/netio.h index 653b7e97c..2f048e5a3 100644 --- a/src/modules/netio/netio.h +++ b/src/modules/netio/netio.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_NETIO_MODULE_NAME "NetIO" - void ffPrepareNetIO(FFNetIOOptions* options); bool ffPrintNetIO(FFNetIOOptions* options); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 353615b64..18e9b85d6 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -9,15 +9,15 @@ bool ffPrintOpenCL(FFOpenCLOptions* options) { FFOpenCLResult* result = ffDetectOpenCL(); if (result->error != nullptr) { - ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result->error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result->error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&result->version, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->version, "version"), FF_ARG(result->name, "name"), FF_ARG(result->vendor, "vendor"), @@ -35,7 +35,7 @@ void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -120,7 +120,7 @@ void ffDestroyOpenCLOptions(FFOpenCLOptions* options) { } FFModuleBaseInfo ffOpenCLModuleInfo = { - .name = FF_OPENCL_MODULE_NAME, + .name = "OpenCL", .description = "Print the highest OpenCL version supported by the GPU", .displayName = { .en = "OpenCL", diff --git a/src/modules/opencl/opencl.h b/src/modules/opencl/opencl.h index aafab369f..d7dbe3661 100644 --- a/src/modules/opencl/opencl.h +++ b/src/modules/opencl/opencl.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_OPENCL_MODULE_NAME "OpenCL" - bool ffPrintOpenCL(FFOpenCLOptions* options); void ffInitOpenCLOptions(FFOpenCLOptions* options); void ffDestroyOpenCLOptions(FFOpenCLOptions* options); diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index c10ec7e20..ad8e431e5 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -15,13 +15,13 @@ bool ffPrintOpenGL(FFOpenGLOptions* options) { const char* error = ffDetectOpenGL(options, &result); if (error) { - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(result.version.chars); } else { - FF_PRINT_FORMAT_CHECKED(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.version, "version"), FF_ARG(result.renderer, "renderer"), FF_ARG(result.vendor, "vendor"), @@ -58,14 +58,14 @@ void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->library = (FFOpenGLLibrary) value; } continue; } - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -127,7 +127,7 @@ void ffDestroyOpenGLOptions(FFOpenGLOptions* options) { } FFModuleBaseInfo ffOpenGLModuleInfo = { - .name = FF_OPENGL_MODULE_NAME, + .name = "OpenGL", .description = "Print the highest OpenGL version supported by the GPU", .displayName = { .en = "OpenGL", diff --git a/src/modules/opengl/opengl.h b/src/modules/opengl/opengl.h index 8caffa5a5..f7f4c05cc 100644 --- a/src/modules/opengl/opengl.h +++ b/src/modules/opengl/opengl.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_OPENGL_MODULE_NAME "OpenGL" - bool ffPrintOpenGL(FFOpenGLOptions* options); void ffInitOpenGLOptions(FFOpenGLOptions* options); void ffDestroyOpenGLOptions(FFOpenGLOptions* options); diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 65168a609..1d6a18cd0 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -50,14 +50,14 @@ bool ffPrintOS(FFOSOptions* options) { const FFOSResult* os = ffDetectOS(); if (os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0) { - ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Could not detect OS"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Could not detect OS"); return false; } FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { - ffStrbufSetStatic(&key, FF_OS_MODULE_NAME); + ffStrbufSetStatic(&key, FF_MODULE_GET_DISPLAY_NAME(OS)); } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { FF_ARG(instance.state.platform.sysinfo.name, "sysname"), @@ -112,7 +112,7 @@ void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -172,7 +172,7 @@ void ffDestroyOSOptions(FFOSOptions* options) { } FFModuleBaseInfo ffOSModuleInfo = { - .name = FF_OS_MODULE_NAME, + .name = "OS", .description = "Print the OS or Linux distribution name and version", .displayName = { .en = "OS", diff --git a/src/modules/os/os.h b/src/modules/os/os.h index a53d28516..77312c620 100644 --- a/src/modules/os/os.h +++ b/src/modules/os/os.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_OS_MODULE_NAME "OS" - bool ffPrintOS(FFOSOptions* options); void ffInitOSOptions(FFOSOptions* options); void ffDestroyOSOptions(FFOSOptions* options); diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 258e0f369..710894c3c 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -11,12 +11,12 @@ bool ffPrintPackages(FFPackagesOptions* options) { const char* error = ffDetectPackages(&counts, options); if (error) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (counts.all == 0) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No packages from known package managers found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No packages from known package managers found"); return false; } @@ -29,7 +29,7 @@ bool ffPrintPackages(FFPackagesOptions* options) { uint32_t scoopAll = counts.scoopUser + counts.scoopGlobal; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); @@ -141,7 +141,7 @@ bool ffPrintPackages(FFPackagesOptions* options) { output.chars[output.length - 1] = '\n'; ffStrbufWriteTo(&output, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_PACKAGES_MODULE_NAME, + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, @@ -219,7 +219,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { #if !FF_PACKAGES_REMOVE_DISABLED if (unsafe_yyjson_equals_str(key, "disabled")) { if (!yyjson_is_null(val) && !yyjson_is_arr(val)) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); continue; } @@ -230,7 +230,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { size_t flagIdx, flagMax; yyjson_arr_foreach (val, flagIdx, flagMax, flagObj) { if (!yyjson_is_str(flagObj)) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); continue; } const char* flag = unsafe_yyjson_get_str(flagObj); @@ -366,7 +366,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -510,7 +510,7 @@ void ffDestroyPackagesOptions(FFPackagesOptions* options) { } FFModuleBaseInfo ffPackagesModuleInfo = { - .name = FF_PACKAGES_MODULE_NAME, + .name = "Packages", .description = "List installed package managers and count of installed packages", .displayName = { .en = "Packages", diff --git a/src/modules/packages/packages.h b/src/modules/packages/packages.h index 4e5876870..caf7832d8 100644 --- a/src/modules/packages/packages.h +++ b/src/modules/packages/packages.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PACKAGES_MODULE_NAME "Packages" - bool ffPrintPackages(FFPackagesOptions* options); void ffInitPackagesOptions(FFPackagesOptions* options); void ffDestroyPackagesOptions(FFPackagesOptions* options); diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index d897e131e..d9e2f3649 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -5,15 +5,13 @@ #include "detection/physicaldisk/physicaldisk.h" #include "modules/physicaldisk/physicaldisk.h" -#define FF_PHYSICALDISK_DISPLAY_NAME "Physical Disk" - static int sortDevices(const FFPhysicalDiskResult* left, const FFPhysicalDiskResult* right) { return ffStrbufComp(&left->name, &right->name); } static void formatKey(const FFPhysicalDiskOptions* options, FFPhysicalDiskResult* dev, uint32_t index, FFstrbuf* key) { if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(key, FF_PHYSICALDISK_DISPLAY_NAME " (%s)", dev->name.length ? dev->name.chars : dev->devPath.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), dev->name.length ? dev->name.chars : dev->devPath.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -30,7 +28,7 @@ bool ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) { const char* error = ffDetectPhysicalDisk(&result, options); if (error) { - ffPrintError(FF_PHYSICALDISK_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -140,7 +138,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m if (unsafe_yyjson_equals_str(key, "hideVirtual")) { if (!yyjson_is_bool(val)) { - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideVirtual must be a boolean"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideVirtual must be a boolean"); } else { if (unsafe_yyjson_is_true(val)) { options->hideType |= FF_PHYSICALDISK_TYPE_VIRTUAL; @@ -153,7 +151,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m if (unsafe_yyjson_equals_str(key, "hideUnused")) { if (!yyjson_is_bool(val)) { - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideUnused must be a boolean"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideUnused must be a boolean"); } else { if (unsafe_yyjson_is_true(val)) { options->hideType |= FF_PHYSICALDISK_TYPE_UNUSED; @@ -168,7 +166,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m continue; } - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -265,7 +263,7 @@ void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) { } FFModuleBaseInfo ffPhysicalDiskModuleInfo = { - .name = FF_PHYSICALDISK_MODULE_NAME, + .name = "PhysicalDisk", .description = "Print physical disk information", .displayName = { .en = "Physical Disk", diff --git a/src/modules/physicaldisk/physicaldisk.h b/src/modules/physicaldisk/physicaldisk.h index aaad8883e..41a8d9987 100644 --- a/src/modules/physicaldisk/physicaldisk.h +++ b/src/modules/physicaldisk/physicaldisk.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PHYSICALDISK_MODULE_NAME "PhysicalDisk" - bool ffPrintPhysicalDisk(FFPhysicalDiskOptions* options); void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options); void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options); diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 64e53957d..dbb263ad4 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -4,19 +4,17 @@ #include "detection/physicalmemory/physicalmemory.h" #include "modules/physicalmemory/physicalmemory.h" -#define FF_PHYSICALMEMORY_DISPLAY_NAME "Physical Memory" - bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { FF_LIST_AUTO_DESTROY result = ffListCreate(); const char* error = ffDetectPhysicalMemory(options, &result); if (error) { - ffPrintError(FF_PHYSICALMEMORY_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_PHYSICALMEMORY_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory devices detected"); return false; } @@ -30,7 +28,7 @@ bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PHYSICALMEMORY_DISPLAY_NAME, result.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), result.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (device->installed) { fputs(prettySize.chars, stdout); @@ -59,7 +57,7 @@ bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_PHYSICALMEMORY_DISPLAY_NAME, (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->size, "bytes"), FF_ARG(prettySize, "size"), FF_ARG(device->maxSpeed, "max-speed"), @@ -103,7 +101,7 @@ void ffParsePhysicalMemoryJsonObject(FFPhysicalMemoryOptions* options, yyjson_va continue; } - ffPrintError(FF_PHYSICALMEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -159,7 +157,7 @@ void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) { } FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { - .name = FF_PHYSICALMEMORY_MODULE_NAME, + .name = "PhysicalMemory", .description = "Print system physical memory devices", .displayName = { .en = "Physical Memory", diff --git a/src/modules/physicalmemory/physicalmemory.h b/src/modules/physicalmemory/physicalmemory.h index feb3d1d29..ae4ae985a 100644 --- a/src/modules/physicalmemory/physicalmemory.h +++ b/src/modules/physicalmemory/physicalmemory.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PHYSICALMEMORY_MODULE_NAME "PhysicalMemory" - bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options); void ffInitPhysicalMemoryOptions(FFPhysicalMemoryOptions* options); void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options); diff --git a/src/modules/player/player.c b/src/modules/player/player.c index a01471446..ca19fbefe 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -6,18 +6,16 @@ #include -#define FF_PLAYER_DISPLAY_NAME "Media Player" - bool ffPrintPlayer(FFPlayerOptions* options) { const FFMediaResult* media = ffDetectMedia(false); if (media->error.length > 0) { - ffPrintError(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); return false; } if (media->player.length == 0) { - ffPrintError(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No media player detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No media player detected"); return false; } @@ -65,10 +63,10 @@ bool ffPrintPlayer(FFPlayerOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&playerPretty, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(playerPretty, "player"), FF_ARG(media->player, "name"), FF_ARG(media->playerId, "id"), @@ -87,7 +85,7 @@ void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_PLAYER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -109,7 +107,7 @@ void ffDestroyPlayerOptions(FFPlayerOptions* options) { } FFModuleBaseInfo ffPlayerModuleInfo = { - .name = FF_PLAYER_MODULE_NAME, + .name = "Player", .description = "Print the music player name that is currently active", .displayName = { .en = "Media Player", diff --git a/src/modules/player/player.h b/src/modules/player/player.h index 8b18d2982..001d81e37 100644 --- a/src/modules/player/player.h +++ b/src/modules/player/player.h @@ -3,8 +3,6 @@ #include "option.h" -#define FF_PLAYER_MODULE_NAME "Player" - bool ffPrintPlayer(FFPlayerOptions* options); void ffInitPlayerOptions(FFPlayerOptions* options); void ffDestroyPlayerOptions(FFPlayerOptions* options); diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 74f0bfe89..39866ed19 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -4,20 +4,18 @@ #include "detection/poweradapter/poweradapter.h" #include "modules/poweradapter/poweradapter.h" -#define FF_POWERADAPTER_DISPLAY_NAME "Power Adapter" - bool ffPrintPowerAdapter(FFPowerAdapterOptions* options) { FF_LIST_AUTO_DESTROY results = ffListCreate(); const char* error = ffDetectPowerAdapter(&results); if (error) { - ffPrintError(FF_POWERADAPTER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_POWERADAPTER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No power adapters found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No power adapters found"); return false; } @@ -25,7 +23,7 @@ bool ffPrintPowerAdapter(FFPowerAdapterOptions* options) { FFPowerAdapterResult* result = FF_LIST_GET(FFPowerAdapterResult, results, i); if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result->name.length > 0) { puts(result->name.chars); @@ -33,7 +31,7 @@ bool ffPrintPowerAdapter(FFPowerAdapterOptions* options) { printf("%dW\n", result->watts); } } else { - FF_PRINT_FORMAT_CHECKED(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->watts, "watts"), FF_ARG(result->name, "name"), FF_ARG(result->manufacturer, "manufacturer"), @@ -65,7 +63,7 @@ void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* m continue; } - ffPrintError(FF_POWERADAPTER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -110,7 +108,7 @@ void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options) { } FFModuleBaseInfo ffPowerAdapterModuleInfo = { - .name = FF_POWERADAPTER_MODULE_NAME, + .name = "PowerAdapter", .description = "Print power adapter name and charging watts", .displayName = { .en = "Power Adapter", diff --git a/src/modules/poweradapter/poweradapter.h b/src/modules/poweradapter/poweradapter.h index 3e6102550..f4d1170c2 100644 --- a/src/modules/poweradapter/poweradapter.h +++ b/src/modules/poweradapter/poweradapter.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_POWERADAPTER_MODULE_NAME "PowerAdapter" - bool ffPrintPowerAdapter(FFPowerAdapterOptions* options); void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options); void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 1d02bac2e..ef6f4bee3 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -9,16 +9,16 @@ bool ffPrintProcesses(FFProcessesOptions* options) { const char* error = ffDetectProcesses(&numProcesses); if (error) { - ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%u\n", numProcesses); } else { - FF_PRINT_FORMAT_CHECKED(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") })); } return true; @@ -32,7 +32,7 @@ void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -63,7 +63,7 @@ void ffDestroyProcessesOptions(FFProcessesOptions* options) { } FFModuleBaseInfo ffProcessesModuleInfo = { - .name = FF_PROCESSES_MODULE_NAME, + .name = "Processes", .description = "Print number of running processes", .displayName = { .en = "Processes", diff --git a/src/modules/processes/processes.h b/src/modules/processes/processes.h index 0220c17dd..6fe14cb87 100644 --- a/src/modules/processes/processes.h +++ b/src/modules/processes/processes.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PROCESSES_MODULE_NAME "Processes" - bool ffPrintProcesses(FFProcessesOptions* options); void ffInitProcessesOptions(FFProcessesOptions* options); void ffDestroyProcessesOptions(FFProcessesOptions* options); diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index fe5002a43..6cb741ca1 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -4,8 +4,6 @@ #include "modules/publicip/publicip.h" #include "detection/publicip/publicip.h" -#define FF_PUBLICIP_DISPLAY_NAME "Public IP" - bool ffPrintPublicIp(FFPublicIPOptions* options) { FFPublicIpResult result; ffStrbufInit(&result.ip); @@ -13,19 +11,19 @@ bool ffPrintPublicIp(FFPublicIPOptions* options) { const char* error = ffDetectPublicIp(options, &result); if (error) { - ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.location.length) { printf("%s (%s)\n", result.ip.chars, result.location.chars); } else { ffStrbufPutTo(&result.ip, stdout); } } else { - FF_PRINT_FORMAT_CHECKED(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.ip, "ip"), FF_ARG(result.location, "location"), })); @@ -60,7 +58,7 @@ void ffParsePublicIpJsonObject(FFPublicIPOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_PUBLICIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -110,7 +108,7 @@ void ffDestroyPublicIpOptions(FFPublicIPOptions* options) { } FFModuleBaseInfo ffPublicIPModuleInfo = { - .name = FF_PUBLICIP_MODULE_NAME, + .name = "PublicIp", .description = "Print your public IP address and related information", .displayName = { .en = "Public IP", diff --git a/src/modules/publicip/publicip.h b/src/modules/publicip/publicip.h index 92768cbb6..65b934baf 100644 --- a/src/modules/publicip/publicip.h +++ b/src/modules/publicip/publicip.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PUBLICIP_MODULE_NAME "PublicIp" - void ffPreparePublicIp(FFPublicIPOptions* options); bool ffPrintPublicIp(FFPublicIPOptions* options); diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index eaf912819..4ef3a3af2 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -95,11 +95,11 @@ void ffParseSeparatorJsonObject(FFSeparatorOptions* options, yyjson_val* module) } if (unsafe_yyjson_equals_str(key, "length")) { - ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "The option length has been renamed to times."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Separator), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "The option length has been renamed to times."); continue; } - ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Separator), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -121,7 +121,7 @@ void ffDestroySeparatorOptions(FFSeparatorOptions* options) { } FFModuleBaseInfo ffSeparatorModuleInfo = { - .name = FF_SEPARATOR_MODULE_NAME, + .name = "Separator", .description = "Print a separator line", .displayName = { .en = "Separator", diff --git a/src/modules/separator/separator.h b/src/modules/separator/separator.h index eebf39af3..2ad9c8fab 100644 --- a/src/modules/separator/separator.h +++ b/src/modules/separator/separator.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SEPARATOR_MODULE_NAME "Separator" - bool ffPrintSeparator(FFSeparatorOptions* options); void ffInitSeparatorOptions(FFSeparatorOptions* options); void ffDestroySeparatorOptions(FFSeparatorOptions* options); diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index a1df091c3..dd161759c 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -8,12 +8,12 @@ bool ffPrintShell(FFShellOptions* options) { const FFShellResult* result = ffDetectShell(); if (result->processName.length == 0) { - ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect shell"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect shell"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result->prettyName, stdout); if (result->version.length > 0) { @@ -23,7 +23,7 @@ bool ffPrintShell(FFShellOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->processName, "process-name"), FF_ARG(result->exe, "exe"), FF_ARG(result->exeName, "exe-name"), @@ -46,7 +46,7 @@ void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -89,7 +89,7 @@ void ffDestroyShellOptions(FFShellOptions* options) { } FFModuleBaseInfo ffShellModuleInfo = { - .name = FF_SHELL_MODULE_NAME, + .name = "Shell", .description = "Print the current shell name and version", .displayName = { .en = "Shell", diff --git a/src/modules/shell/shell.h b/src/modules/shell/shell.h index 50a094c80..c8aec5574 100644 --- a/src/modules/shell/shell.h +++ b/src/modules/shell/shell.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SHELL_MODULE_NAME "Shell" - bool ffPrintShell(FFShellOptions* options); void ffInitShellOptions(FFShellOptions* options); void ffDestroyShellOptions(FFShellOptions* options); diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index eaa0d44b7..c29cb574e 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -8,7 +8,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, uint8_t index) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Sound), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { @@ -54,7 +54,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui bool isMain = !!(device->type & FF_SOUND_TYPE_MAIN); bool isActive = !!(device->type & FF_SOUND_TYPE_ACTIVE); - FF_PRINT_FORMAT_CHECKED(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Sound), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(isMain, "is-main"), FF_ARG(isActive, "is-active"), FF_ARG(device->name, "name"), @@ -73,12 +73,12 @@ bool ffPrintSound(FFSoundOptions* options) { const char* error = ffDetectSound(options, &result); if (error) { - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No matched sound devices found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No matched sound devices found"); return false; } @@ -113,7 +113,7 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->soundType = (FFSoundType) value; } @@ -124,7 +124,7 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -199,7 +199,7 @@ void ffDestroySoundOptions(FFSoundOptions* options) { } FFModuleBaseInfo ffSoundModuleInfo = { - .name = FF_SOUND_MODULE_NAME, + .name = "Sound", .description = "Print sound devices, volume levels, etc", .displayName = { .en = "Sound", diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h index a23f8d5e1..651d640bf 100644 --- a/src/modules/sound/sound.h +++ b/src/modules/sound/sound.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SOUND_MODULE_NAME "Sound" - bool ffPrintSound(FFSoundOptions* options); void ffInitSoundOptions(FFSoundOptions* options); void ffDestroySoundOptions(FFSoundOptions* options); diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 5b7c1117e..a0ef87368 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -11,9 +11,9 @@ void printSwap(FFSwapOptions* options, uint8_t index, uint32_t totalCount, FFSwa if (options->moduleArgs.key.length == 0) { if (storage->name.length > 0) { - ffStrbufSetF(&key, "%s (%s)", FF_SWAP_MODULE_NAME, storage->name.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Swap), storage->name.chars); } else { - ffStrbufSetS(&key, FF_SWAP_MODULE_NAME); + ffStrbufSetS(&key, FF_MODULE_GET_DISPLAY_NAME(Swap)); } } else { ffStrbufClear(&key); @@ -90,7 +90,7 @@ bool ffPrintSwap(FFSwapOptions* options) { const char* error = ffDetectSwap(&result); if (error) { - ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Swap), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -136,7 +136,7 @@ void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Swap), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -182,7 +182,7 @@ void ffDestroySwapOptions(FFSwapOptions* options) { } FFModuleBaseInfo ffSwapModuleInfo = { - .name = FF_SWAP_MODULE_NAME, + .name = "Swap", .description = "Print swap (paging file) space usage", .displayName = { .en = "Swap", diff --git a/src/modules/swap/swap.h b/src/modules/swap/swap.h index e6b9a8b8e..7c0bf13eb 100644 --- a/src/modules/swap/swap.h +++ b/src/modules/swap/swap.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SWAP_MODULE_NAME "Swap" - bool ffPrintSwap(FFSwapOptions* options); void ffInitSwapOptions(FFSwapOptions* options); void ffDestroySwapOptions(FFSwapOptions* options); diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 7aa4e1a18..1b06dc485 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -8,12 +8,12 @@ bool ffPrintTerminal(FFTerminalOptions* options) { const FFTerminalResult* result = ffDetectTerminal(); if (result->processName.length == 0) { - ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect terminal"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect terminal"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result->version.length) { printf("%s %s\n", result->prettyName.chars, result->version.chars); @@ -21,7 +21,7 @@ bool ffPrintTerminal(FFTerminalOptions* options) { ffStrbufPutTo(&result->prettyName, stdout); } } else { - FF_PRINT_FORMAT_CHECKED(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->processName, "process-name"), FF_ARG(result->exe, "exe"), FF_ARG(result->exeName, "exe-name"), @@ -44,7 +44,7 @@ void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -83,7 +83,7 @@ void ffDestroyTerminalOptions(FFTerminalOptions* options) { } FFModuleBaseInfo ffTerminalModuleInfo = { - .name = FF_TERMINAL_MODULE_NAME, + .name = "Terminal", .description = "Print the current terminal name and version", .displayName = { .en = "Terminal", diff --git a/src/modules/terminal/terminal.h b/src/modules/terminal/terminal.h index bb7c9a10d..c8a207246 100644 --- a/src/modules/terminal/terminal.h +++ b/src/modules/terminal/terminal.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINAL_MODULE_NAME "Terminal" - bool ffPrintTerminal(FFTerminalOptions* options); void ffInitTerminalOptions(FFTerminalOptions* options); void ffDestroyTerminalOptions(FFTerminalOptions* options); diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 6c840889d..cea077d47 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -4,8 +4,6 @@ #include "detection/terminalfont/terminalfont.h" #include "modules/terminalfont/terminalfont.h" -#define FF_TERMINALFONT_DISPLAY_NAME "Terminal Font" - bool ffPrintTerminalFont(FFTerminalFontOptions* options) { bool success = false; FFTerminalFontResult terminalFont; @@ -14,10 +12,10 @@ bool ffPrintTerminalFont(FFTerminalFontOptions* options) { ffStrbufInit(&terminalFont.error); if (!ffDetectTerminalFont(&terminalFont)) { - ffPrintError(FF_TERMINALFONT_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", terminalFont.error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", terminalFont.error.chars); } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINALFONT_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&terminalFont.font.pretty, stdout); if (terminalFont.fallback.pretty.length) { fputs(" / ", stdout); @@ -25,7 +23,7 @@ bool ffPrintTerminalFont(FFTerminalFontOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_TERMINALFONT_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(terminalFont.font.pretty, "combined"), FF_ARG(terminalFont.font.name, "name"), FF_ARG(terminalFont.font.size, "size"), @@ -50,7 +48,7 @@ void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* m continue; } - ffPrintError(FF_TERMINALFONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -105,7 +103,7 @@ void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options) { } FFModuleBaseInfo ffTerminalFontModuleInfo = { - .name = FF_TERMINALFONT_MODULE_NAME, + .name = "TerminalFont", .description = "Print the font name and size used by the current terminal", .displayName = { .en = "Terminal Font", diff --git a/src/modules/terminalfont/terminalfont.h b/src/modules/terminalfont/terminalfont.h index 04987a61e..a32e2e0b4 100644 --- a/src/modules/terminalfont/terminalfont.h +++ b/src/modules/terminalfont/terminalfont.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINALFONT_MODULE_NAME "TerminalFont" - bool ffPrintTerminalFont(FFTerminalFontOptions* options); void ffInitTerminalFontOptions(FFTerminalFontOptions* options); void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options); diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 11e34551b..6fd7bf5d8 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -4,18 +4,16 @@ #include "detection/terminalsize/terminalsize.h" #include "modules/terminalsize/terminalsize.h" -#define FF_TERMINALSIZE_DISPLAY_NAME "Terminal Size" - bool ffPrintTerminalSize(FFTerminalSizeOptions* options) { FFTerminalSizeResult result = {}; if (!ffDetectTerminalSize(&result)) { - ffPrintError(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal size"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal size"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%u columns x %u rows", result.columns, result.rows); if (result.width != 0 && result.height != 0) { @@ -24,7 +22,7 @@ bool ffPrintTerminalSize(FFTerminalSizeOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.rows, "rows"), FF_ARG(result.columns, "columns"), FF_ARG(result.width, "width"), @@ -42,7 +40,7 @@ void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* m continue; } - ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -76,7 +74,7 @@ void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) { } FFModuleBaseInfo ffTerminalSizeModuleInfo = { - .name = FF_TERMINALSIZE_MODULE_NAME, + .name = "TerminalSize", .description = "Print the current terminal size", .displayName = { .en = "Terminal Size", diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h index 3cd05d5b2..0745b6a00 100644 --- a/src/modules/terminalsize/terminalsize.h +++ b/src/modules/terminalsize/terminalsize.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINALSIZE_MODULE_NAME "TerminalSize" - bool ffPrintTerminalSize(FFTerminalSizeOptions* options); void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options); void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 053db3453..c8925e78d 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -6,18 +6,16 @@ #include -#define FF_TERMINALTHEME_DISPLAY_NAME "Terminal Theme" - bool ffPrintTerminalTheme(FFTerminalThemeOptions* options) { FFTerminalThemeResult result = {}; if (!ffDetectTerminalTheme(&result, false)) { - ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal theme"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal theme"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("#%02" PRIX16 "%02" PRIX16 "%02" PRIX16 " (FG) - #%02" PRIX16 "%02" PRIX16 "%02" PRIX16 " (BG) [%s]\n", result.fg.r, result.fg.g, @@ -32,7 +30,7 @@ bool ffPrintTerminalTheme(FFTerminalThemeOptions* options) { const char* bgType = result.bg.dark ? "Dark" : "Light"; snprintf(fg, ARRAY_SIZE(fg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.fg.r, result.fg.g, result.fg.b); snprintf(bg, ARRAY_SIZE(bg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.bg.r, result.bg.g, result.bg.b); - FF_PRINT_FORMAT_CHECKED(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(fg, "fg-color"), FF_ARG(fgType, "fg-type"), FF_ARG(bg, "bg-color"), @@ -51,7 +49,7 @@ void ffParseTerminalThemeJsonObject(FFTerminalThemeOptions* options, yyjson_val* continue; } - ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -93,7 +91,7 @@ void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options) { } FFModuleBaseInfo ffTerminalThemeModuleInfo = { - .name = FF_TERMINALTHEME_MODULE_NAME, + .name = "TerminalTheme", .description = "Print the current terminal theme (foreground and background colors)", .displayName = { .en = "Terminal Theme", diff --git a/src/modules/terminaltheme/terminaltheme.h b/src/modules/terminaltheme/terminaltheme.h index db120f74c..e48bca083 100644 --- a/src/modules/terminaltheme/terminaltheme.h +++ b/src/modules/terminaltheme/terminaltheme.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINALTHEME_MODULE_NAME "TerminalTheme" - bool ffPrintTerminalTheme(FFTerminalThemeOptions* options); void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options); void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options); diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 1769d5fc3..44ab11cc1 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -12,12 +12,12 @@ bool ffPrintTheme(FFThemeOptions* options) { const char* error = ffDetectTheme(&result); if (error) { - ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.theme1.length) { ffStrbufWriteTo(&result.theme1, stdout); } @@ -29,7 +29,7 @@ bool ffPrintTheme(FFThemeOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.theme1, "theme1"), FF_ARG(result.theme2, "theme2"), })); @@ -48,7 +48,7 @@ void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -87,7 +87,7 @@ void ffDestroyThemeOptions(FFThemeOptions* options) { } FFModuleBaseInfo ffThemeModuleInfo = { - .name = FF_THEME_MODULE_NAME, + .name = "Theme", .description = "Print the current desktop environment theme", .displayName = { .en = "Theme", diff --git a/src/modules/theme/theme.h b/src/modules/theme/theme.h index 56ba49c81..83278d764 100644 --- a/src/modules/theme/theme.h +++ b/src/modules/theme/theme.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_THEME_MODULE_NAME "Theme" - bool ffPrintTheme(FFThemeOptions* options); void ffInitThemeOptions(FFThemeOptions* options); void ffDestroyThemeOptions(FFThemeOptions* options); diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 3d8fe1a79..cce1c6bb1 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -45,7 +45,7 @@ bool ffPrintTitle(FFTitleOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Title), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&userNameColored, stdout); ffStrbufWriteTo(&atColored, stdout); @@ -68,7 +68,7 @@ bool ffPrintTitle(FFTitleOptions* options) { ffStrbufTrimRight(&cwdTilde, '/'); } - FF_PRINT_FORMAT_CHECKED(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Title), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(instance.state.platform.userName, "user-name"), FF_ARG(hostName, "host-name"), FF_ARG(instance.state.platform.homeDir, "home-dir"), @@ -124,7 +124,7 @@ void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_TITLE_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Title), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -176,7 +176,7 @@ void ffDestroyTitleOptions(FFTitleOptions* options) { } FFModuleBaseInfo ffTitleModuleInfo = { - .name = FF_TITLE_MODULE_NAME, + .name = "Title", .description = "Print the title, including your username and hostname", .displayName = { .en = "Title", diff --git a/src/modules/title/title.h b/src/modules/title/title.h index 83c949654..ce44461fa 100644 --- a/src/modules/title/title.h +++ b/src/modules/title/title.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TITLE_MODULE_NAME "Title" - bool ffPrintTitle(FFTitleOptions* options); void ffInitTitleOptions(FFTitleOptions* options); void ffDestroyTitleOptions(FFTitleOptions* options); diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 3471d5a12..1b85104e7 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -12,19 +12,19 @@ bool ffPrintTPM(FFTPMOptions* options) { const char* error = ffDetectTPM(&result); if (error) { - ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.description.length > 0) { ffStrbufPutTo(&result.description, stdout); } else { ffStrbufPutTo(&result.version, stdout); } } else { - FF_PRINT_FORMAT_CHECKED(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.version, "version"), FF_ARG(result.description, "description"), })); @@ -44,7 +44,7 @@ void ffParseTPMJsonObject(FFTPMOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -83,7 +83,7 @@ void ffDestroyTPMOptions(FFTPMOptions* options) { } FFModuleBaseInfo ffTPMModuleInfo = { - .name = FF_TPM_MODULE_NAME, + .name = "TPM", .description = "Print information about the Trusted Platform Module (TPM) security device", .displayName = { .en = "TPM", diff --git a/src/modules/tpm/tpm.h b/src/modules/tpm/tpm.h index 215f8c98a..72ce6aac0 100644 --- a/src/modules/tpm/tpm.h +++ b/src/modules/tpm/tpm.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TPM_MODULE_NAME "TPM" - bool ffPrintTPM(FFTPMOptions* options); void ffInitTPMOptions(FFTPMOptions* options); void ffDestroyTPMOptions(FFTPMOptions* options); diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index b4299d7a5..0bed6ea13 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -12,7 +12,7 @@ bool ffPrintUptime(FFUptimeOptions* options) { const char* error = ffDetectUptime(&result); if (error) { - ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -21,7 +21,7 @@ bool ffPrintUptime(FFUptimeOptions* options) { ffDurationAppendNum((uptime + 500) / 1000, &buffer); if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&buffer, stdout); } else { uint32_t milliseconds = (uint32_t) (uptime % 1000); @@ -36,7 +36,7 @@ bool ffPrintUptime(FFUptimeOptions* options) { 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") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Uptime), 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; @@ -50,7 +50,7 @@ void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -83,7 +83,7 @@ void ffDestroyUptimeOptions(FFUptimeOptions* options) { } FFModuleBaseInfo ffUptimeModuleInfo = { - .name = FF_UPTIME_MODULE_NAME, + .name = "Uptime", .description = "Print how long the system has been running", .displayName = { .en = "Uptime", diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h index dec5f95e5..c9db7dcd3 100644 --- a/src/modules/uptime/uptime.h +++ b/src/modules/uptime/uptime.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_UPTIME_MODULE_NAME "Uptime" - bool ffPrintUptime(FFUptimeOptions* options); void ffInitUptimeOptions(FFUptimeOptions* options); void ffDestroyUptimeOptions(FFUptimeOptions* options); diff --git a/src/modules/users/users.c b/src/modules/users/users.c index f67073e18..c59373bee 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -13,18 +13,18 @@ bool ffPrintUsers(FFUsersOptions* options) { const char* error = ffDetectUsers(options, &users); if (error) { - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (users.length == 0) { - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Unable to detect any users"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Unable to detect any users"); return false; } if (options->moduleArgs.outputFormat.length == 0) { if (options->compact) { - ffPrintLogoAndKey(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); for (uint32_t i = 0; i < users.length; ++i) { @@ -39,7 +39,7 @@ bool ffPrintUsers(FFUsersOptions* options) { for (uint32_t i = 0; i < users.length; ++i) { FFUserResult* user = FF_LIST_GET(FFUserResult, users, i); - ffPrintLogoAndKey(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Users), users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateCopy(&user->name); if (user->hostName.length) { @@ -71,7 +71,7 @@ bool ffPrintUsers(FFUsersOptions* options) { FFTimeGetAgeResult age = ffTimeGetAge(user->loginTime, ffTimeGetNow()); - FF_PRINT_FORMAT_CHECKED(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Users), users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(user->name, "name"), FF_ARG(user->hostName, "host-name"), FF_ARG(user->sessionName, "session-name"), @@ -121,7 +121,7 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -180,7 +180,7 @@ void ffDestroyUsersOptions(FFUsersOptions* options) { } FFModuleBaseInfo ffUsersModuleInfo = { - .name = FF_USERS_MODULE_NAME, + .name = "Users", .description = "Print users who are currently logged in", .displayName = { .en = "Users", diff --git a/src/modules/users/users.h b/src/modules/users/users.h index 44c8b01d7..2567b395c 100644 --- a/src/modules/users/users.h +++ b/src/modules/users/users.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_USERS_MODULE_NAME "Users" - bool ffPrintUsers(FFUsersOptions* options); void ffInitUsersOptions(FFUsersOptions* options); void ffDestroyUsersOptions(FFUsersOptions* options); diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 2bd906a21..56c142d76 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -9,7 +9,7 @@ bool ffPrintVersion(FFVersionOptions* options) { FFVersionResult* result = &ffVersionResult; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Version), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%s %s%s%s (%s)\n", result->projectName, result->version, result->versionTweak, result->debugMode ? "-debug" : "", result->architecture); } else { FFLibcResult libcResult; @@ -23,7 +23,7 @@ bool ffPrintVersion(FFVersionOptions* options) { } const char* buildType = result->debugMode ? "debug" : "release"; - FF_PRINT_FORMAT_CHECKED(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Version), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->projectName, "project-name"), FF_ARG(result->version, "version"), FF_ARG(result->versionTweak, "version-tweak"), @@ -48,7 +48,7 @@ void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Version), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -94,7 +94,7 @@ void ffDestroyVersionOptions(FFVersionOptions* options) { } FFModuleBaseInfo ffVersionModuleInfo = { - .name = FF_VERSION_MODULE_NAME, + .name = "Version", .description = "Print the Fastfetch version and build information", .displayName = { .en = "Version", diff --git a/src/modules/version/version.h b/src/modules/version/version.h index add5e1198..5cfaf1f14 100644 --- a/src/modules/version/version.h +++ b/src/modules/version/version.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_VERSION_MODULE_NAME "Version" - bool ffPrintVersion(FFVersionOptions* options); void ffInitVersionOptions(FFVersionOptions* options); void ffDestroyVersionOptions(FFVersionOptions* options); diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 9dedfd9cc..a16cac601 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -9,12 +9,12 @@ bool ffPrintVulkan(FFVulkanOptions* options) { const FFVulkanResult* vulkan = ffDetectVulkan(); if (vulkan->error) { - ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", vulkan->error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", vulkan->error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (vulkan->apiVersion.length == 0 && vulkan->driver.length == 0) { ffStrbufWriteTo(&vulkan->instanceVersion, stdout); @@ -35,7 +35,7 @@ bool ffPrintVulkan(FFVulkanOptions* options) { putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(vulkan->driver, "driver"), FF_ARG(vulkan->apiVersion, "api-version"), FF_ARG(vulkan->conformanceVersion, "conformance-version"), @@ -54,7 +54,7 @@ void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -132,7 +132,7 @@ void ffDestroyVulkanOptions(FFVulkanOptions* options) { } FFModuleBaseInfo ffVulkanModuleInfo = { - .name = FF_VULKAN_MODULE_NAME, + .name = "Vulkan", .description = "Print the highest Vulkan version supported by the GPU", .displayName = { .en = "Vulkan", diff --git a/src/modules/vulkan/vulkan.h b/src/modules/vulkan/vulkan.h index c838028c5..141ad9933 100644 --- a/src/modules/vulkan/vulkan.h +++ b/src/modules/vulkan/vulkan.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_VULKAN_MODULE_NAME "Vulkan" - bool ffPrintVulkan(FFVulkanOptions* options); void ffInitVulkanOptions(FFVulkanOptions* options); void ffDestroyVulkanOptions(FFVulkanOptions* options); diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index fc1393fb9..e0f203a58 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -21,15 +21,15 @@ bool ffPrintWallpaper(FFWallpaperOptions* options) { : fullpath.chars + index; if (error) { - ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(filename); } else { - FF_PRINT_FORMAT_CHECKED(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(filename, "file-name"), FF_ARG(fullpath, "full-path"), })); @@ -46,7 +46,7 @@ void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -75,7 +75,7 @@ void ffDestroyWallpaperOptions(FFWallpaperOptions* options) { } FFModuleBaseInfo ffWallpaperModuleInfo = { - .name = FF_WALLPAPER_MODULE_NAME, + .name = "Wallpaper", .description = "Print the file path of the current wallpaper", .displayName = { .en = "Wallpaper", diff --git a/src/modules/wallpaper/wallpaper.h b/src/modules/wallpaper/wallpaper.h index c3e72911b..eed2fa21c 100644 --- a/src/modules/wallpaper/wallpaper.h +++ b/src/modules/wallpaper/wallpaper.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WALLPAPER_MODULE_NAME "Wallpaper" - bool ffPrintWallpaper(FFWallpaperOptions* options); void ffInitWallpaperOptions(FFWallpaperOptions* options); void ffDestroyWallpaperOptions(FFWallpaperOptions* options); diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 8307ce422..7a2192a79 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -9,15 +9,15 @@ bool ffPrintWeather(FFWeatherOptions* options) { const char* error = ffDetectWeather(options, &result); if (error) { - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&result, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result"), })); } @@ -48,7 +48,7 @@ void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -92,7 +92,7 @@ void ffDestroyWeatherOptions(FFWeatherOptions* options) { } FFModuleBaseInfo ffWeatherModuleInfo = { - .name = FF_WEATHER_MODULE_NAME, + .name = "Weather", .description = "Print weather information", .displayName = { .en = "Weather", diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h index f28a4c233..e2b8394ea 100644 --- a/src/modules/weather/weather.h +++ b/src/modules/weather/weather.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WEATHER_MODULE_NAME "Weather" - void ffPrepareWeather(FFWeatherOptions* options); bool ffPrintWeather(FFWeatherOptions* options); diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 58e5da965..d5baa00ff 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -9,11 +9,11 @@ bool ffPrintWifi(FFWifiOptions* options) { const char* error = ffDetectWifi(&result); if (error) { - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wifi), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No Wifi interfaces found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wifi), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No Wifi interfaces found"); return false; } @@ -46,7 +46,7 @@ bool ffPrintWifi(FFWifiOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (item->conn.ssid.length) { @@ -95,7 +95,7 @@ bool ffPrintWifi(FFWifiOptions* options) { ffPercentAppendBar(&percentBar, item->conn.signalQuality, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(item->inf.description, "inf-desc"), FF_ARG(item->inf.status, "inf-status"), FF_ARG(item->conn.status, "status"), @@ -138,7 +138,7 @@ void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wifi), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -213,7 +213,7 @@ void ffDestroyWifiOptions(FFWifiOptions* options) { } FFModuleBaseInfo ffWifiModuleInfo = { - .name = FF_WIFI_MODULE_NAME, + .name = "Wifi", .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", .displayName = { .en = "Wi-Fi", diff --git a/src/modules/wifi/wifi.h b/src/modules/wifi/wifi.h index 506e1e22a..dd640815c 100644 --- a/src/modules/wifi/wifi.h +++ b/src/modules/wifi/wifi.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WIFI_MODULE_NAME "Wifi" - bool ffPrintWifi(FFWifiOptions* options); void ffInitWifiOptions(FFWifiOptions* options); void ffDestroyWifiOptions(FFWifiOptions* options); diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 3545bfc9e..35e58c4f1 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -9,7 +9,7 @@ bool ffPrintWM(FFWMOptions* options) { const FFDisplayServerResult* result = ffConnectDisplayServer(); if (result->wmPrettyName.length == 0) { - ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No WM found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No WM found"); return false; } @@ -24,7 +24,7 @@ bool ffPrintWM(FFWMOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result->wmPrettyName, stdout); @@ -47,7 +47,7 @@ bool ffPrintWM(FFWMOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->wmProcessName, "process-name"), FF_ARG(result->wmPrettyName, "pretty-name"), FF_ARG(result->wmProtocolName, "protocol-name"), @@ -72,7 +72,7 @@ void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -120,7 +120,7 @@ void ffDestroyWMOptions(FFWMOptions* options) { } FFModuleBaseInfo ffWMModuleInfo = { - .name = FF_WM_MODULE_NAME, + .name = "WM", .description = "Print the window manager name and version", .displayName = { .en = "WM", diff --git a/src/modules/wm/wm.h b/src/modules/wm/wm.h index 4819d7394..5e085ef01 100644 --- a/src/modules/wm/wm.h +++ b/src/modules/wm/wm.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WM_MODULE_NAME "WM" - bool ffPrintWM(FFWMOptions* options); void ffInitWMOptions(FFWMOptions* options); void ffDestroyWMOptions(FFWMOptions* options); diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 7061f66ae..8c7e3afe3 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -4,20 +4,18 @@ #include "detection/wmtheme/wmtheme.h" #include "modules/wmtheme/wmtheme.h" -#define FF_WMTHEME_DISPLAY_NAME "WM Theme" - bool ffPrintWMTheme(FFWMThemeOptions* options) { FF_STRBUF_AUTO_DESTROY themeOrError = ffStrbufCreate(); if (!ffDetectWmTheme(&themeOrError)) { - ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", themeOrError.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", themeOrError.chars); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(themeOrError.chars); } else { - FF_PRINT_FORMAT_CHECKED(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(themeOrError, "result"), })); } @@ -33,7 +31,7 @@ void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -61,7 +59,7 @@ void ffDestroyWMThemeOptions(FFWMThemeOptions* options) { } FFModuleBaseInfo ffWMThemeModuleInfo = { - .name = FF_WMTHEME_MODULE_NAME, + .name = "WMTheme", .description = "Print the current window manager theme", .displayName = { .en = "WM Theme", diff --git a/src/modules/wmtheme/wmtheme.h b/src/modules/wmtheme/wmtheme.h index 5142ca42c..46c8299c3 100644 --- a/src/modules/wmtheme/wmtheme.h +++ b/src/modules/wmtheme/wmtheme.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WMTHEME_MODULE_NAME "WMTheme" - bool ffPrintWMTheme(FFWMThemeOptions* options); void ffInitWMThemeOptions(FFWMThemeOptions* options); void ffDestroyWMThemeOptions(FFWMThemeOptions* options); diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index b155ff3b1..0e447d5e4 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -11,9 +11,9 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (result->name.length > 0) { - ffStrbufSetF(&buffer, "%s (%s)", FF_ZPOOL_MODULE_NAME, result->name.chars); + ffStrbufSetF(&buffer, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Zpool), result->name.chars); } else { - ffStrbufSetS(&buffer, FF_ZPOOL_MODULE_NAME); + ffStrbufSetS(&buffer, FF_MODULE_GET_DISPLAY_NAME(Zpool)); } } else { ffStrbufClear(&buffer); @@ -105,11 +105,11 @@ bool ffPrintZpool(FFZpoolOptions* options) { const char* error = ffDetectZpool(&results); if (error) { - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Zpool), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No zpool found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Zpool), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No zpool found"); return false; } @@ -138,7 +138,7 @@ void ffParseZpoolJsonObject(FFZpoolOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Zpool), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -192,7 +192,7 @@ void ffDestroyZpoolOptions(FFZpoolOptions* options) { } FFModuleBaseInfo ffZpoolModuleInfo = { - .name = FF_ZPOOL_MODULE_NAME, + .name = "Zpool", .description = "Print ZFS storage pools", .displayName = { .en = "Zpool", diff --git a/src/modules/zpool/zpool.h b/src/modules/zpool/zpool.h index 35706bb35..3faed199f 100644 --- a/src/modules/zpool/zpool.h +++ b/src/modules/zpool/zpool.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_ZPOOL_MODULE_NAME "Zpool" - bool ffPrintZpool(FFZpoolOptions* options); void ffInitZpoolOptions(FFZpoolOptions* options); void ffDestroyZpoolOptions(FFZpoolOptions* options); diff --git a/src/options/display.c b/src/options/display.c index d515e92c1..434048e92 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -8,9 +8,68 @@ #if !FF_MODULE_DISABLE_TERMINALTHEME #include "detection/terminaltheme/terminaltheme.h" #endif +#if !FF_MODULE_DISABLE_LOCALE + #include "detection/locale/locale.h" +#endif #include +// @returns offsetof(FFModuleDisplayName, ) +// @see src/common/option.h +static uint32_t optionParseLanguageString(FFstrbuf* language) { + if (language->length == 0) { +#if !FF_MODULE_DISABLE_LOCALE + ffDetectLocale(language); +#else + fputs("Error: --key-language requires a value\n", stderr); + exit(477); +#endif + } + + // The language code is expected to be in the format of "en", "en_US", "de", "de_DE", etc. + // First try to match the full language code, then try to match just the first two characters (the language part). + // If no match is found, report a language not supported error. + // en_US -> offsetof(FFModuleDisplayName, en) + // de_DE -> offsetof(FFModuleDisplayName, de) + // zh_CN -> offsetof(FFModuleDisplayName, zh_CN) + // ar -> Error: Language 'ar' is not supported + + // Try to match the full language code, e.g. "en", "pt_BR", "zh_CN" + static const FFKeyValuePair pairs[] = { + { "en", offsetof(FFModuleDisplayName, en) }, + { "de", offsetof(FFModuleDisplayName, de) }, + { "es", offsetof(FFModuleDisplayName, es) }, + { "fr", offsetof(FFModuleDisplayName, fr) }, + { "it", offsetof(FFModuleDisplayName, it) }, + { "ja", offsetof(FFModuleDisplayName, ja) }, + { "ko", offsetof(FFModuleDisplayName, ko) }, + { "pl", offsetof(FFModuleDisplayName, pl) }, + { "pt_BR", offsetof(FFModuleDisplayName, pt_BR) }, + { "ru", offsetof(FFModuleDisplayName, ru) }, + { "zh_CN", offsetof(FFModuleDisplayName, zh_CN) }, + { "zh_TW", offsetof(FFModuleDisplayName, zh_TW) }, + {}, + }; + + for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { + if (ffStrbufIgnCaseEqualS(language, pair->key)) { + return (uint32_t) pair->value; + } + } + + // Try to match just the first two characters (the language part), e.g. "en" from "en_US", "de" from "de_DE" + if (language->length >= 2) { + for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { + if (ffStrbufStartsWithIgnCaseS(language, pair->key)) { + return (uint32_t) pair->value; + } + } + } + + fprintf(stderr, "Error: Language '%s' is not supported\n", language->chars); + exit(477); +} + const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root, yyjson_val** pkey) { yyjson_val* object = yyjson_obj_get(root, "display"); if (!object) { @@ -483,6 +542,17 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va if (paddingLeft) { options->keyPaddingLeft = (uint16_t) yyjson_get_uint(paddingLeft); } + + yyjson_val* language = yyjson_obj_get(val, "language"); + if (language) { + FF_STRBUF_AUTO_DESTROY languageBuffer = ffStrbufCreate(); + if (yyjson_is_str(language)) { + ffStrbufSetJsonVal(&languageBuffer, language); + } else if (!yyjson_is_null(language)) { + return "display.key.language must be a string or null"; + } + options->keyLanguage = optionParseLanguageString(&languageBuffer); + } } else { return "display.key must be an object"; } @@ -651,6 +721,9 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key options->keyType = (FFModuleKeyType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { { "none", FF_MODULE_KEY_TYPE_NONE }, { "string", FF_MODULE_KEY_TYPE_STRING }, { "icon", FF_MODULE_KEY_TYPE_ICON }, { "both", FF_MODULE_KEY_TYPE_BOTH }, { "both-0", FF_MODULE_KEY_TYPE_BOTH_0 }, { "both-1", FF_MODULE_KEY_TYPE_BOTH_1 }, { "both-2", FF_MODULE_KEY_TYPE_BOTH_2 }, { "both-3", FF_MODULE_KEY_TYPE_BOTH_3 }, { "both-4", FF_MODULE_KEY_TYPE_BOTH_4 }, {} }); } else if (ffStrEqualsIgnCase(subkey, "padding-left")) { options->keyPaddingLeft = (uint16_t) ffOptionParseUInt32(key, value); + } else if (ffStrEqualsIgnCase(subkey, "language")) { + FF_STRBUF_AUTO_DESTROY language = ffStrbufCreateStatic(value); + options->keyLanguage = optionParseLanguageString(&language); } else { return false; } @@ -867,6 +940,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) { options->keyWidth = 0; options->keyPaddingLeft = 0; options->keyType = FF_MODULE_KEY_TYPE_STRING; + options->keyLanguage = offsetof(FFModuleDisplayName, en); options->tempUnit = FF_TEMPERATURE_UNIT_DEFAULT; options->tempNdigits = 1; @@ -1168,6 +1242,45 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) } yyjson_mut_obj_add_uint(doc, key, "paddingLeft", options->keyPaddingLeft); + + switch (options->keyLanguage) { + case offsetof(FFModuleDisplayName, en): + yyjson_mut_obj_add_str(doc, key, "language", "en"); + break; + case offsetof(FFModuleDisplayName, de): + yyjson_mut_obj_add_str(doc, key, "language", "de"); + break; + case offsetof(FFModuleDisplayName, es): + yyjson_mut_obj_add_str(doc, key, "language", "es"); + break; + case offsetof(FFModuleDisplayName, fr): + yyjson_mut_obj_add_str(doc, key, "language", "fr"); + break; + case offsetof(FFModuleDisplayName, it): + yyjson_mut_obj_add_str(doc, key, "language", "it"); + break; + case offsetof(FFModuleDisplayName, ja): + yyjson_mut_obj_add_str(doc, key, "language", "ja"); + break; + case offsetof(FFModuleDisplayName, ko): + yyjson_mut_obj_add_str(doc, key, "language", "ko"); + break; + case offsetof(FFModuleDisplayName, pl): + yyjson_mut_obj_add_str(doc, key, "language", "pl"); + break; + case offsetof(FFModuleDisplayName, pt_BR): + yyjson_mut_obj_add_str(doc, key, "language", "pt_BR"); + break; + case offsetof(FFModuleDisplayName, ru): + yyjson_mut_obj_add_str(doc, key, "language", "ru"); + break; + case offsetof(FFModuleDisplayName, zh_CN): + yyjson_mut_obj_add_str(doc, key, "language", "zh_CN"); + break; + case offsetof(FFModuleDisplayName, zh_TW): + yyjson_mut_obj_add_str(doc, key, "language", "zh_TW"); + break; + } } { diff --git a/src/options/display.h b/src/options/display.h index 8e234b08a..2706a3e96 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -80,6 +80,7 @@ typedef struct FFOptionsDisplay { uint8_t percentWidth; bool noBuffer; FFModuleKeyType keyType; + uint32_t keyLanguage; // Offset of FFModuleDisplayName member uint16_t keyWidth; uint16_t keyPaddingLeft; int8_t freqNdigits; From bdba78c45c3448bb4e3505a8c87a6e112a02ea64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 23:56:29 +0800 Subject: [PATCH 006/109] CI: silences codespell errors --- .codespellrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index 66e8f1098..1554e6270 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*,./src/common/impl/genconfig.c -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement From e5c3fa40231b37b7f0ca3d53558d219b53250dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 15 Aug 2026 00:00:27 +0800 Subject: [PATCH 007/109] CI: fixes compiling errors --- src/common/FFstrbuf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/FFstrbuf.h b/src/common/FFstrbuf.h index d84ed3506..0f4f405a6 100644 --- a/src/common/FFstrbuf.h +++ b/src/common/FFstrbuf.h @@ -629,4 +629,4 @@ static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) { bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf); #define FF_STRBUF_AUTO_DESTROY [[gnu::cleanup(ffStrbufDestroy)]] FFstrbuf -#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) ARRAY_SIZE(str) - 1, .chars = str } +#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) sizeof(str) - 1, .chars = str } From 4dc27b365fa0550af51cd849c3c89bea8f598283 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 15 Aug 2026 08:51:45 +0800 Subject: [PATCH 008/109] DiskIO / NetIO: fixes I/O rate calculation precision, prevent div-by-zero --- src/detection/diskio/diskio.c | 3 +-- src/detection/netio/netio.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c index 73f0075a7..a2f53439c 100644 --- a/src/detection/diskio/diskio.c +++ b/src/detection/diskio/diskio.c @@ -72,8 +72,7 @@ const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) { uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); uint64_t temp = *currValue; - *currValue -= *prevValue; - *currValue /= (time2 - time1) / 1000 /* seconds */; + *currValue = (*currValue - *prevValue) * 1000 / (time2 - time1); // Calculate per second // For next function call *prevValue = temp; diff --git a/src/detection/netio/netio.c b/src/detection/netio/netio.c index a6348265b..3c986a863 100644 --- a/src/detection/netio/netio.c +++ b/src/detection/netio/netio.c @@ -70,8 +70,7 @@ const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options) { uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); uint64_t temp = *currValue; - *currValue -= *prevValue; - *currValue /= (time2 - time1) / 1000 /* seconds */; + *currValue = (*currValue - *prevValue) * 1000 / (time2 - time1); // Calculate per second *prevValue = temp; } } From 8d82eedaef9dbbd0abe2c58f7ce8b013414a836b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 15 Aug 2026 08:53:00 +0800 Subject: [PATCH 009/109] DiskIO / NetIO: updates default value of waitTime to reduce latency Also corrects docs. --- doc/json_schema.json | 8 ++++---- src/modules/diskio/diskio.c | 2 +- src/modules/netio/netio.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 01ef306de..5ae9bcc27 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -2655,8 +2655,8 @@ }, "waitTime": { "type": "integer", - "description": "Wait time (in ms). Disk I/O = (totalBytesEnd - totalBytesStart) / waitTime", - "default": 200, + "description": "Wait time (in ms) used to measure the I/O rate (calculated in bytes/sec).\nAvoid setting this too low, as the kernel requires time to accurately update counters.\nIgnored if 'detectTotal' is true.", + "default": 500, "minimum": 1 }, "key": { @@ -3556,8 +3556,8 @@ }, "waitTime": { "type": "integer", - "description": "Wait time (in ms). Net I/O = (totalBytesEnd - totalBytesStart) / waitTime", - "default": 200, + "description": "Wait time (in ms) used to measure the I/O rate (calculated in bytes/sec).\nAvoid setting this too low, as the kernel requires time to accurately update counters.\nIgnored if 'detectTotal' is true.", + "default": 500, "minimum": 1 }, "key": { diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 9acfbe511..87a18c54d 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -161,7 +161,7 @@ void ffInitDiskIOOptions(FFDiskIOOptions* options) { ffStrbufInit(&options->namePrefix); options->detectTotal = false; - options->waitTime = 1000; + options->waitTime = 500; } void ffDestroyDiskIOOptions(FFDiskIOOptions* options) { diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index e062a55c8..602368790 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -188,7 +188,7 @@ void ffInitNetIOOptions(FFNetIOOptions* options) { #endif ; options->detectTotal = false; - options->waitTime = 1000; + options->waitTime = 500; } void ffDestroyNetIOOptions(FFNetIOOptions* options) { From b677f1e902932b728f547dcfef8eaafdabe99230 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 15 Aug 2026 09:03:12 +0800 Subject: [PATCH 010/109] Theme: improves GTK theme/icons/font detection on standalone WMs (Hyprland, sway, niri, i3) Fixes #2504 --- src/detection/gtk_qt/gtk.c | 99 +++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 43 deletions(-) diff --git a/src/detection/gtk_qt/gtk.c b/src/detection/gtk_qt/gtk.c index 12aaeac14..1740630e1 100644 --- a/src/detection/gtk_qt/gtk.c +++ b/src/detection/gtk_qt/gtk.c @@ -62,50 +62,63 @@ static void detectGTKFromSettings(FFGTKResult* result) { const FFDisplayServerResult* wmde = ffConnectDisplayServer(); - if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4)) { - themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, nullptr, testXfconfWallpaperPropKey).strValue; - } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON)) { - themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; - } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE)) { - themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", nullptr, "picture-filename", FF_VARIANT_TYPE_STRING).strValue; - } else if ( - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_NEBIDE)) { - themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; - } else if ( - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_ENLIGHTENMENT)) { - ffEnlightenmentSettings settings = {}; - if (ffSettingsGetEnlightenmentProperty(&settings)) { - themeName = settings.theme; - iconsName = settings.icon_theme; - fontName = settings.font; - cursorTheme = settings.use_e_cursor ? "Enlightenment" : "Application"; - cursorSize = settings.cursor_size; - wallpaper = settings.desktop_default_background; + if (wmde->dePrettyName.length > 0) { + if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4)) { + themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, nullptr, testXfconfWallpaperPropKey).strValue; + } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON)) { + themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; + } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE)) { + themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", nullptr, "picture-filename", FF_VARIANT_TYPE_STRING).strValue; + } else if ( + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_NEBIDE)) { + themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; + } else if ( + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_ENLIGHTENMENT)) { + ffEnlightenmentSettings settings = {}; + if (ffSettingsGetEnlightenmentProperty(&settings)) { + themeName = settings.theme; + iconsName = settings.icon_theme; + fontName = settings.font; + cursorTheme = settings.use_e_cursor ? "Enlightenment" : "Application"; + cursorSize = settings.cursor_size; + wallpaper = settings.desktop_default_background; + } } + } else { + // Standalone WMs (Hyprland, sway, niri, i3, ...) report no DE and have no settings + // daemon, but GTK apps on them still read org.gnome.desktop.interface. + // Read via DConf, not GSettings: GSettings synthesises the schema default for keys + // the user never set, DConf returns nothing. Runs last; applyGTKSettings() only + // fills still-empty fields, so config files always win. + themeName = ffSettingsGetDConf("/org/gnome/desktop/interface/gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetDConf("/org/gnome/desktop/interface/icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetDConf("/org/gnome/desktop/interface/font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetDConf("/org/gnome/desktop/interface/cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetDConf("/org/gnome/desktop/interface/cursor-size", FF_VARIANT_TYPE_INT).intValue; } applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper); From 233c481f7a8746e210db6c59fc755acfd0b4f7b5 Mon Sep 17 00:00:00 2001 From: Guiorgy Date: Sat, 15 Aug 2026 05:15:03 +0400 Subject: [PATCH 011/109] CMAKE: bumps minimum CMake version to 3.21.0 (#2517) C_STANDARD 23 was added in 3.21 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 687e89b5e..13a6fa83a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url +cmake_minimum_required(VERSION 3.21.0) # C_STANDARD project(fastfetch VERSION 2.67.1 From 45f9de6cd2b26ed70cb48029dd0dc9ee77bc6eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:27:20 +0800 Subject: [PATCH 012/109] L10n: improves performance --- src/options/display.c | 84 +++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/src/options/display.c b/src/options/display.c index 434048e92..9ce0a9677 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -19,53 +19,75 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { if (language->length == 0) { #if !FF_MODULE_DISABLE_LOCALE - ffDetectLocale(language); + const char* error = ffDetectLocale(language); + if (__builtin_expect(error != nullptr, false)) { + fprintf(stderr, "ffDetectLocale: %s\n", error); + exit(477); + } #else fputs("Error: --key-language requires a value\n", stderr); exit(477); #endif } + ffStrbufSubstrBeforeFirstC(language, '.'); // Remove the encoding part of the locale + #if __linux__ + ffStrbufSubstrBeforeFirstC(language, '@'); // Remove the modifier part of the locale (Linux only) + #endif + ffStrbufLowerCase(language); + + if (language->length <= 1) { + if (language->chars[0] == 'c') { + return offsetof(FFModuleDisplayName, en); + } else { + goto error; + } + } else if (language->length > 2) { + if (language->chars[2] == '-') { + language->chars[2] = '_'; + } else if (__builtin_expect(language->chars[2] != '_', false)) { + goto error; + } + } + // The language code is expected to be in the format of "en", "en_US", "de", "de_DE", etc. // First try to match the full language code, then try to match just the first two characters (the language part). // If no match is found, report a language not supported error. // en_US -> offsetof(FFModuleDisplayName, en) - // de_DE -> offsetof(FFModuleDisplayName, de) + // en -> offsetof(FFModuleDisplayName, en) // zh_CN -> offsetof(FFModuleDisplayName, zh_CN) - // ar -> Error: Language 'ar' is not supported + // zh -> Error: Language 'zh' is not supported. This is an intentional design decision, as the language code 'zh' could refer to either Simplified or Traditional Chinese. - // Try to match the full language code, e.g. "en", "pt_BR", "zh_CN" - static const FFKeyValuePair pairs[] = { - { "en", offsetof(FFModuleDisplayName, en) }, - { "de", offsetof(FFModuleDisplayName, de) }, - { "es", offsetof(FFModuleDisplayName, es) }, - { "fr", offsetof(FFModuleDisplayName, fr) }, - { "it", offsetof(FFModuleDisplayName, it) }, - { "ja", offsetof(FFModuleDisplayName, ja) }, - { "ko", offsetof(FFModuleDisplayName, ko) }, - { "pl", offsetof(FFModuleDisplayName, pl) }, - { "pt_BR", offsetof(FFModuleDisplayName, pt_BR) }, - { "ru", offsetof(FFModuleDisplayName, ru) }, - { "zh_CN", offsetof(FFModuleDisplayName, zh_CN) }, - { "zh_TW", offsetof(FFModuleDisplayName, zh_TW) }, - {}, - }; - - for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { - if (ffStrbufIgnCaseEqualS(language, pair->key)) { - return (uint32_t) pair->value; - } - } - - // Try to match just the first two characters (the language part), e.g. "en" from "en_US", "de" from "de_DE" - if (language->length >= 2) { - for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { - if (ffStrbufStartsWithIgnCaseS(language, pair->key)) { - return (uint32_t) pair->value; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmultichar" + switch (language->chars[0] << 8 | language->chars[1]) { + case 'en': return offsetof(FFModuleDisplayName, en); + case 'de': return offsetof(FFModuleDisplayName, de); + case 'es': return offsetof(FFModuleDisplayName, es); + case 'fr': return offsetof(FFModuleDisplayName, fr); + case 'it': return offsetof(FFModuleDisplayName, it); + case 'ja': return offsetof(FFModuleDisplayName, ja); + case 'ko': return offsetof(FFModuleDisplayName, ko); + case 'pl': return offsetof(FFModuleDisplayName, pl); + case 'pt': { + if (ffStrbufEqualS(language, "pt_br")) { + return offsetof(FFModuleDisplayName, pt_BR); } + goto error; + } + case 'ru': return offsetof(FFModuleDisplayName, ru); + case 'zh': { + if (ffStrbufEqualS(language, "zh_cn")) { + return offsetof(FFModuleDisplayName, zh_CN); + } else if (ffStrbufEqualS(language, "zh_tw")) { + return offsetof(FFModuleDisplayName, zh_TW); + } + goto error; } } +#pragma GCC diagnostic pop +error: fprintf(stderr, "Error: Language '%s' is not supported\n", language->chars); exit(477); } From 359cb0a79a3531e382fdb0c99357252936f08bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:37:06 +0800 Subject: [PATCH 013/109] L10n (Pt): renames `pt_BR` to `pt` --- doc/help.json | 2 +- doc/json_schema.json | 4 ++-- src/common/option.h | 2 +- src/modules/battery/battery.c | 2 +- src/modules/bios/bios.c | 2 +- src/modules/bluetooth/bluetooth.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 2 +- src/modules/board/board.c | 2 +- src/modules/bootmgr/bootmgr.c | 2 +- src/modules/break/break.c | 2 +- src/modules/brightness/brightness.c | 2 +- src/modules/btrfs/btrfs.c | 2 +- src/modules/camera/camera.c | 2 +- src/modules/chassis/chassis.c | 2 +- src/modules/codec/codec.c | 2 +- src/modules/colors/colors.c | 2 +- src/modules/command/command.c | 2 +- src/modules/cpu/cpu.c | 2 +- src/modules/cpucache/cpucache.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/cursor/cursor.c | 2 +- src/modules/custom/custom.c | 2 +- src/modules/datetime/datetime.c | 2 +- src/modules/de/de.c | 2 +- src/modules/disk/disk.c | 2 +- src/modules/diskio/diskio.c | 2 +- src/modules/display/display.c | 2 +- src/modules/dns/dns.c | 2 +- src/modules/editor/editor.c | 2 +- src/modules/font/font.c | 2 +- src/modules/gamepad/gamepad.c | 2 +- src/modules/gpu/gpu.c | 2 +- src/modules/host/host.c | 2 +- src/modules/icons/icons.c | 2 +- src/modules/initsystem/initsystem.c | 2 +- src/modules/kernel/kernel.c | 2 +- src/modules/keyboard/keyboard.c | 2 +- src/modules/lm/lm.c | 2 +- src/modules/loadavg/loadavg.c | 2 +- src/modules/locale/locale.c | 2 +- src/modules/localip/localip.c | 2 +- src/modules/logo/logo.c | 2 +- src/modules/media/media.c | 2 +- src/modules/memory/memory.c | 2 +- src/modules/monitor/monitor.c | 2 +- src/modules/mouse/mouse.c | 2 +- src/modules/netio/netio.c | 2 +- src/modules/opencl/opencl.c | 2 +- src/modules/opengl/opengl.c | 2 +- src/modules/os/os.c | 2 +- src/modules/packages/packages.c | 2 +- src/modules/physicaldisk/physicaldisk.c | 2 +- src/modules/physicalmemory/physicalmemory.c | 2 +- src/modules/player/player.c | 2 +- src/modules/poweradapter/poweradapter.c | 2 +- src/modules/processes/processes.c | 2 +- src/modules/publicip/publicip.c | 2 +- src/modules/separator/separator.c | 2 +- src/modules/shell/shell.c | 2 +- src/modules/sound/sound.c | 2 +- src/modules/swap/swap.c | 2 +- src/modules/terminal/terminal.c | 2 +- src/modules/terminalfont/terminalfont.c | 2 +- src/modules/terminalsize/terminalsize.c | 2 +- src/modules/terminaltheme/terminaltheme.c | 2 +- src/modules/theme/theme.c | 2 +- src/modules/title/title.c | 2 +- src/modules/tpm/tpm.c | 2 +- src/modules/uptime/uptime.c | 2 +- src/modules/users/users.c | 2 +- src/modules/version/version.c | 2 +- src/modules/vulkan/vulkan.c | 2 +- src/modules/wallpaper/wallpaper.c | 2 +- src/modules/weather/weather.c | 2 +- src/modules/wifi/wifi.c | 2 +- src/modules/wm/wm.c | 2 +- src/modules/wmtheme/wmtheme.c | 2 +- src/modules/zpool/zpool.c | 2 +- src/options/display.c | 8 ++++---- 79 files changed, 83 insertions(+), 83 deletions(-) diff --git a/doc/help.json b/doc/help.json index d1a148202..4331d2b63 100644 --- a/doc/help.json +++ b/doc/help.json @@ -602,7 +602,7 @@ "ja": "Japanese", "ko": "Korean", "pl": "Polish", - "pt_BR": "Brazilian Portuguese", + "pt": "Portuguese", "ru": "Russian", "zh_CN": "Simplified Chinese", "zh_TW": "Traditional Chinese" diff --git a/doc/json_schema.json b/doc/json_schema.json index 5ae9bcc27..7075bc47e 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1107,8 +1107,8 @@ }, { "type": "string", - "const": "pt_BR", - "description": "Brazilian Portuguese" + "const": "pt", + "description": "Portuguese" }, { "type": "string", diff --git a/src/common/option.h b/src/common/option.h index 2647cd7ed..be7c475f8 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -28,7 +28,7 @@ typedef struct FFModuleDisplayName { const char* ja; // Japanese const char* ko; // Korean const char* pl; // Polish - const char* pt_BR; // Brazilian Portuguese + const char* pt; // (Brazilian) Portuguese const char* ru; // Russian const char* zh_CN; // Simplified Chinese const char* zh_TW; // Traditional Chinese diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 99a44b676..66334abb7 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -308,7 +308,7 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .ja = "バッテリー", .ko = "배터리", .pl = "Bateria", - .pt_BR = "Bateria", + .pt = "Bateria", .ru = "Батарея", .zh_CN = "电池", .zh_TW = "電池", diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 94e602228..34dfcb08a 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -141,7 +141,7 @@ FFModuleBaseInfo ffBiosModuleInfo = { .ja = "BIOS", .ko = "BIOS", .pl = "BIOS", - .pt_BR = "BIOS", + .pt = "BIOS", .ru = "BIOS", .zh_CN = "BIOS", .zh_TW = "BIOS", diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 232728dc5..22606b77e 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -162,7 +162,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .ja = "ブルートゥース", .ko = "블루투스", .pl = "Bluetooth", - .pt_BR = "Bluetooth", + .pt = "Bluetooth", .ru = "Блютус", .zh_CN = "蓝牙", .zh_TW = "藍牙", diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 1419eaec5..330bf8948 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -199,7 +199,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .ja = "ブルートゥースアダプター", .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", - .pt_BR = "Adaptador Bluetooth", + .pt = "Adaptador Bluetooth", .ru = "Блютус-адаптер", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 324bfe95b..e9f883b1a 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -119,7 +119,7 @@ FFModuleBaseInfo ffBoardModuleInfo = { .ja = "マザーボード", .ko = "메인보드", .pl = "Płyta główna", - .pt_BR = "Placa-mãe", + .pt = "Placa-mãe", .ru = "Материнская плата", .zh_CN = "主板", .zh_TW = "主機板", diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index d45030225..f0538f68a 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -114,7 +114,7 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .ja = "ブートマネージャー", .ko = "부트 매니저", .pl = "Menedżer rozruchu", - .pt_BR = "Gerenciador de inicialização", + .pt = "Gerenciador de inicialização", .ru = "Менеджер загрузки", .zh_CN = "启动管理器", .zh_TW = "啟動管理器", diff --git a/src/modules/break/break.c b/src/modules/break/break.c index b66963ecd..d81400de7 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -38,7 +38,7 @@ FFModuleBaseInfo ffBreakModuleInfo = { .ja = "改行", .ko = "줄 바꿈", .pl = "Przerwa", - .pt_BR = "Quebra", + .pt = "Quebra", .ru = "Разрыв", .zh_CN = "换行", .zh_TW = "換行", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 28fa28be0..f70bd1349 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -201,7 +201,7 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .ja = "明るさ", .ko = "밝기", .pl = "Jasność", - .pt_BR = "Brilho", + .pt = "Brilho", .ru = "Яркость", .zh_CN = "亮度", .zh_TW = "亮度", diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 442a4406d..9df262265 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -209,7 +209,7 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .ja = "BTRFS", .ko = "BTRFS", .pl = "BTRFS", - .pt_BR = "BTRFS", + .pt = "BTRFS", .ru = "BTRFS", .zh_CN = "BTRFS", .zh_TW = "BTRFS", diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index f74831065..7758229c3 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -126,7 +126,7 @@ FFModuleBaseInfo ffCameraModuleInfo = { .ja = "カメラ", .ko = "카메라", .pl = "Kamera", - .pt_BR = "Câmera", + .pt = "Câmera", .ru = "Камера", .zh_CN = "摄像头", .zh_TW = "攝像頭", diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index ae25f19b6..576d3b83d 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -121,7 +121,7 @@ FFModuleBaseInfo ffChassisModuleInfo = { .ja = "シャーシ", .ko = "섀시", .pl = "Obudowa", - .pt_BR = "Chassi", + .pt = "Chassi", .ru = "Шасси", .zh_CN = "机箱", .zh_TW = "機箱", diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index f71dfe283..202a82236 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -262,7 +262,7 @@ FFModuleBaseInfo ffCodecModuleInfo = { .ja = "コーデック", .ko = "코덱", .pl = "Kodek", - .pt_BR = "Codec", + .pt = "Codec", .ru = "Кодек", .zh_CN = "编解码器", .zh_TW = "編解碼器", diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ac1ef742f..ace03ddd6 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -306,7 +306,7 @@ FFModuleBaseInfo ffColorsModuleInfo = { .ja = "色", .ko = "색상", .pl = "Kolory", - .pt_BR = "Cores", + .pt = "Cores", .ru = "Цвета", .zh_CN = "颜色", .zh_TW = "顏色", diff --git a/src/modules/command/command.c b/src/modules/command/command.c index d606e033f..13131f627 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -164,7 +164,7 @@ FFModuleBaseInfo ffCommandModuleInfo = { .ja = "コマンド", .ko = "명령어", .pl = "Polecenie", - .pt_BR = "Comando", + .pt = "Comando", .ru = "Команда", .zh_CN = "命令", .zh_TW = "命令", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 20236c9dd..b9c4166f5 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -262,7 +262,7 @@ FFModuleBaseInfo ffCPUModuleInfo = { .ja = "CPU", .ko = "CPU", .pl = "CPU", - .pt_BR = "CPU", + .pt = "CPU", .ru = "CPU", .zh_CN = "CPU", .zh_TW = "CPU", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 1c5c3e858..feeb337d6 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -232,7 +232,7 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .ja = "CPUキャッシュ", .ko = "CPU 캐시", .pl = "Pamięć podręczna CPU", - .pt_BR = "Cache da CPU", + .pt = "Cache da CPU", .ru = "Кэш процессора", .zh_CN = "CPU缓存", .zh_TW = "CPU快取記憶體", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 5c9a4135a..b33c44f08 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -190,7 +190,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .ja = "CPU使用率", .ko = "CPU 사용량", .pl = "Użycie CPU", - .pt_BR = "Uso da CPU", + .pt = "Uso da CPU", .ru = "Использование ЦП", .zh_CN = "CPU使用率", .zh_TW = "CPU使用率", diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 04808456f..3cba64db8 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -111,7 +111,7 @@ FFModuleBaseInfo ffCursorModuleInfo = { .ja = "カーソル", .ko = "커서", .pl = "Kursor", - .pt_BR = "Cursor", + .pt = "Cursor", .ru = "Курсор", .zh_CN = "光标", .zh_TW = "游標", diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index e728b634b..9b3044d51 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -46,7 +46,7 @@ FFModuleBaseInfo ffCustomModuleInfo = { .ja = "カスタム", .ko = "사용자 정의", .pl = "Niestandardowy", - .pt_BR = "Personalizado", + .pt = "Personalizado", .ru = "Пользовательский", .zh_CN = "自定义", .zh_TW = "自訂", diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 347b81d53..180831799 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -161,7 +161,7 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .ja = "日付と時刻", .ko = "날짜/시간", .pl = "Data i godzina", - .pt_BR = "Data e hora", + .pt = "Data e hora", .ru = "Дата и время", .zh_CN = "日期时间", .zh_TW = "日期時間", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 628cf49b4..42b1e3c5b 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -93,7 +93,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .ja = "デスクトップ環境", .ko = "데스크탑 환경", .pl = "Środowisko graficzne", - .pt_BR = "Ambiente de desktop", + .pt = "Ambiente de desktop", .ru = "Рабочая среда", .zh_CN = "桌面环境", .zh_TW = "桌面環境", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 11d696294..7e34a6d57 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -462,7 +462,7 @@ FFModuleBaseInfo ffDiskModuleInfo = { .ja = "ディスク", .ko = "디스크", .pl = "Dysk", - .pt_BR = "Disco", + .pt = "Disco", .ru = "Диск", .zh_CN = "磁盘", .zh_TW = "磁碟", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 87a18c54d..b035133b5 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -181,7 +181,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .ja = "ディスク I/O", .ko = "디스크 I/O", .pl = "Dysk I/O", - .pt_BR = "Disco I/O", + .pt = "Disco I/O", .ru = "Диск I/O", .zh_CN = "磁盘 I/O", .zh_TW = "磁碟 I/O", diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 2df6c787c..c4d2e76a8 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -422,7 +422,7 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .ja = "ディスプレイ", .ko = "디스플레이", .pl = "Wyświetlacz", - .pt_BR = "Tela", + .pt = "Tela", .ru = "Дисплей", .zh_CN = "显示器", .zh_TW = "顯示器", diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 6e63c44d8..d7d7c0ad3 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -145,7 +145,7 @@ FFModuleBaseInfo ffDNSModuleInfo = { .ja = "DNS", .ko = "DNS", .pl = "DNS", - .pt_BR = "DNS", + .pt = "DNS", .ru = "DNS", .zh_CN = "DNS", .zh_TW = "DNS", diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index de3e5c96c..4fdddfc97 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -114,7 +114,7 @@ FFModuleBaseInfo ffEditorModuleInfo = { .ja = "エディター", .ko = "편집기", .pl = "Edytor", - .pt_BR = "Editor", + .pt = "Editor", .ru = "Редактор", .zh_CN = "编辑器", .zh_TW = "編輯器", diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 6df480717..80bc7bcb7 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -106,7 +106,7 @@ FFModuleBaseInfo ffFontModuleInfo = { .ja = "フォント", .ko = "글꼴", .pl = "Czcionka", - .pt_BR = "Fonte", + .pt = "Fonte", .ru = "Шрифт", .zh_CN = "字体", .zh_TW = "字型", diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index c0e01b619..d3e6503ee 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -200,7 +200,7 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .ja = "ゲームパッド", .ko = "게임패드", .pl = "Gamepad", - .pt_BR = "Gamepad", + .pt = "Gamepad", .ru = "Геймпад", .zh_CN = "游戏手柄", .zh_TW = "遊戲手把", diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index d22f3436c..996c48338 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -490,7 +490,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { .ja = "GPU", .ko = "GPU", .pl = "GPU", - .pt_BR = "GPU", + .pt = "GPU", .ru = "GPU", .zh_CN = "显卡", .zh_TW = "顯卡", diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 1fafa659a..e8b549f30 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -147,7 +147,7 @@ FFModuleBaseInfo ffHostModuleInfo = { .ja = "ホスト", .ko = "호스트", .pl = "Host", - .pt_BR = "Host", + .pt = "Host", .ru = "Хост", .zh_CN = "主机", .zh_TW = "主機", diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index eaa1341bd..d1c4e66c8 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -105,7 +105,7 @@ FFModuleBaseInfo ffIconsModuleInfo = { .ja = "アイコン", .ko = "아이콘", .pl = "Ikony", - .pt_BR = "Ícones", + .pt = "Ícones", .ru = "Иконки", .zh_CN = "图标", .zh_TW = "圖示", diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index b5adbc906..f6315380c 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -112,7 +112,7 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .ja = "initシステム", .ko = "초기화 시스템", .pl = "System init", - .pt_BR = "Sistema de inicialização", + .pt = "Sistema de inicialização", .ru = "Init-система", .zh_CN = "Init 系统", .zh_TW = "Init 系統", diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 055dd5fe1..3e576816c 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -73,7 +73,7 @@ FFModuleBaseInfo ffKernelModuleInfo = { .ja = "カーネル", .ko = "커널", .pl = "Jądro", - .pt_BR = "Kernel", + .pt = "Kernel", .ru = "Ядро", .zh_CN = "内核", .zh_TW = "核心", diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 755ac6764..9af46f0d9 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -160,7 +160,7 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .ja = "キーボード", .ko = "키보드", .pl = "Klawiatura", - .pt_BR = "Teclado", + .pt = "Teclado", .ru = "Клавиатура", .zh_CN = "键盘", .zh_TW = "鍵盤", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 8c919056b..c8b54c4eb 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -117,7 +117,7 @@ FFModuleBaseInfo ffLMModuleInfo = { .ja = "ログインマネージャー", .ko = "로그인 관리자", .pl = "Menedżer logowania", - .pt_BR = "Gerenciador de login", + .pt = "Gerenciador de login", .ru = "Менеджер входа", .zh_CN = "登录管理器", .zh_TW = "登入管理器", diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 4bd0065e1..85d504964 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -159,7 +159,7 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .ja = "ロードアベレージ", .ko = "시스템 부하 평균", .pl = "Średnie obciążenie", - .pt_BR = "Média de carga", + .pt = "Média de carga", .ru = "Средняя нагрузка", .zh_CN = "系统负载", .zh_TW = "系統負載", diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 8d3f31474..f194edf0c 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -78,7 +78,7 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .ja = "ロケール", .ko = "로케일", .pl = "Ustawienia regionalne", - .pt_BR = "Configuração regional", + .pt = "Configuração regional", .ru = "Локаль", .zh_CN = "语言环境", .zh_TW = "語言環境", diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 46319e97c..e7e098626 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -432,7 +432,7 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .ja = "ローカル IP", .ko = "로컬 IP", .pl = "Lokalny adres IP", - .pt_BR = "IP local", + .pt = "IP local", .ru = "Локальный IP", .zh_CN = "本地 IP", .zh_TW = "區域 IP", diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 0b68a64f6..7e3aed314 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -88,7 +88,7 @@ FFModuleBaseInfo ffLogoModuleInfo = { .ja = "ロゴ", .ko = "로고", .pl = "Logo", - .pt_BR = "Logo", + .pt = "Logo", .ru = "Логотип", .zh_CN = "徽标", .zh_TW = "標誌", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 08f550a5f..6211b7c95 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -264,7 +264,7 @@ FFModuleBaseInfo ffMediaModuleInfo = { .ja = "メディア", .ko = "미디어", .pl = "Media", - .pt_BR = "Mídia", + .pt = "Mídia", .ru = "Медиа", .zh_CN = "媒体", .zh_TW = "媒體", diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 065808c29..d5a63f6b0 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -129,7 +129,7 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .ja = "メモリ", .ko = "메모리", .pl = "Pamięć", - .pt_BR = "Memória", + .pt = "Memória", .ru = "Память", .zh_CN = "内存", .zh_TW = "記憶體", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index c5c9877c1..aa55c022a 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -115,7 +115,7 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .ja = "モニター", .ko = "모니터", .pl = "Monitor", - .pt_BR = "Monitor", + .pt = "Monitor", .ru = "Монитор", .zh_CN = "显示器", .zh_TW = "顯示器", diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index dd8f8be6e..f542c8375 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -163,7 +163,7 @@ FFModuleBaseInfo ffMouseModuleInfo = { .ja = "マウス", .ko = "마우스", .pl = "Mysz", - .pt_BR = "Mouse", + .pt = "Mouse", .ru = "Мышь", .zh_CN = "鼠标", .zh_TW = "滑鼠", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 602368790..e750ea92d 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -208,7 +208,7 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .ja = "ネットワークI/O", .ko = "네트워크 I/O", .pl = "I/O sieciowe", - .pt_BR = "E/S de rede", + .pt = "E/S de rede", .ru = "Сетевой I/O", .zh_CN = "网络 I/O", .zh_TW = "網路 I/O", diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 18e9b85d6..fbc36c39a 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -131,7 +131,7 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .ja = "OpenCL", .ko = "OpenCL", .pl = "OpenCL", - .pt_BR = "OpenCL", + .pt = "OpenCL", .ru = "OpenCL", .zh_CN = "OpenCL", .zh_TW = "OpenCL", diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index ad8e431e5..bac96afc7 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -138,7 +138,7 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .ja = "OpenGL", .ko = "OpenGL", .pl = "OpenGL", - .pt_BR = "OpenGL", + .pt = "OpenGL", .ru = "OpenGL", .zh_CN = "OpenGL", .zh_TW = "OpenGL", diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 1d6a18cd0..71661bf0a 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -183,7 +183,7 @@ FFModuleBaseInfo ffOSModuleInfo = { .ja = "オペレーティングシステム", .ko = "운영 체제", .pl = "System operacyjny", - .pt_BR = "Sistema operacional", + .pt = "Sistema operacional", .ru = "Операционная система", .zh_CN = "操作系统", .zh_TW = "操作系統", diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 710894c3c..c21ef4ca6 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -521,7 +521,7 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .ja = "パッケージ", .ko = "패키지", .pl = "Pakiety", - .pt_BR = "Pacotes", + .pt = "Pacotes", .ru = "Пакеты", .zh_CN = "软件包", .zh_TW = "軟體包", diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index d9e2f3649..b85ec4410 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -274,7 +274,7 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .ja = "物理ディスク", .ko = "물리 디스크", .pl = "Dysk fizyczny", - .pt_BR = "Disco físico", + .pt = "Disco físico", .ru = "Физический диск", .zh_CN = "物理磁盘", .zh_TW = "物理磁碟", diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index dbb263ad4..0ab65cdb5 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -168,7 +168,7 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .ja = "物理メモリ", .ko = "물리 메모리", .pl = "Pamięć fizyczna", - .pt_BR = "Memória física", + .pt = "Memória física", .ru = "Физическая память", .zh_CN = "物理内存", .zh_TW = "實體記憶體", diff --git a/src/modules/player/player.c b/src/modules/player/player.c index ca19fbefe..0693423e0 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -118,7 +118,7 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .ja = "メディアプレイヤー", .ko = "미디어 플레이어", .pl = "Odtwarzacz multimediów", - .pt_BR = "Reprodutor de mídia", + .pt = "Reprodutor de mídia", .ru = "Медиаплеер", .zh_CN = "媒体播放器", .zh_TW = "媒體播放器", diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 39866ed19..71899d26e 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -119,7 +119,7 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .ja = "電源アダプター", .ko = "전원 어댑터", .pl = "Zasilacz", - .pt_BR = "Fonte de alimentação", + .pt = "Fonte de alimentação", .ru = "Блок питания", .zh_CN = "电源适配器", .zh_TW = "電源轉接器", diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index ef6f4bee3..bb42ca59e 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -74,7 +74,7 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .ja = "プロセス", .ko = "프로세스", .pl = "Procesy", - .pt_BR = "Processos", + .pt = "Processos", .ru = "Процессы", .zh_CN = "进程数", .zh_TW = "進程數", diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 6cb741ca1..92c790544 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -119,7 +119,7 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .ja = "パブリックIP", .ko = "공용 IP", .pl = "Publiczne IP", - .pt_BR = "IP público", + .pt = "IP público", .ru = "Публичный IP", .zh_CN = "公网 IP", .zh_TW = "公網 IP", diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 4ef3a3af2..f70c7a7bd 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -132,7 +132,7 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .ja = "セパレーター", .ko = "구분선", .pl = "Separator", - .pt_BR = "Separador", + .pt = "Separador", .ru = "Разделитель", .zh_CN = "分隔线", .zh_TW = "分隔線", diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index dd161759c..55e0da630 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -100,7 +100,7 @@ FFModuleBaseInfo ffShellModuleInfo = { .ja = "シェル", .ko = "셸", .pl = "Powłoka", - .pt_BR = "Shell", + .pt = "Shell", .ru = "Оболочка", .zh_CN = "Shell", .zh_TW = "Shell", diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index c29cb574e..7f3a691e5 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -210,7 +210,7 @@ FFModuleBaseInfo ffSoundModuleInfo = { .ja = "サウンド", .ko = "사운드", .pl = "Dźwięk", - .pt_BR = "Som", + .pt = "Som", .ru = "Звук", .zh_CN = "声音", .zh_TW = "聲音", diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index a0ef87368..ea0ac62de 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -193,7 +193,7 @@ FFModuleBaseInfo ffSwapModuleInfo = { .ja = "スワップ", .ko = "스왑", .pl = "Swap", - .pt_BR = "Swap", + .pt = "Swap", .ru = "Своп", .zh_CN = "交换空间", .zh_TW = "交換空間", diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 1b06dc485..3752b45e0 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -94,7 +94,7 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .ja = "ターミナル", .ko = "터미널", .pl = "Terminal", - .pt_BR = "Terminal", + .pt = "Terminal", .ru = "Терминал", .zh_CN = "终端", .zh_TW = "終端機", diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index cea077d47..fdb7990be 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -114,7 +114,7 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .ja = "ターミナルフォント", .ko = "터미널 글꼴", .pl = "Czcionka terminala", - .pt_BR = "Fonte do terminal", + .pt = "Fonte do terminal", .ru = "Шрифт терминала", .zh_CN = "终端字体", .zh_TW = "終端機字型", diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 6fd7bf5d8..70f6139d1 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -85,7 +85,7 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .ja = "ターミナルサイズ", .ko = "터미널 크기", .pl = "Rozmiar terminala", - .pt_BR = "Tamanho do terminal", + .pt = "Tamanho do terminal", .ru = "Размер терминала", .zh_CN = "终端大小", .zh_TW = "終端機大小", diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index c8925e78d..4e40876f3 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -102,7 +102,7 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .ja = "ターミナルテーマ", .ko = "터미널 테마", .pl = "Motyw terminala", - .pt_BR = "Tema do terminal", + .pt = "Tema do terminal", .ru = "Тема терминала", .zh_CN = "终端主题", .zh_TW = "終端機主題", diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 44ab11cc1..948e0d469 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -98,7 +98,7 @@ FFModuleBaseInfo ffThemeModuleInfo = { .ja = "テーマ", .ko = "테마", .pl = "Motyw", - .pt_BR = "Tema", + .pt = "Tema", .ru = "Тема", .zh_CN = "主题", .zh_TW = "主題", diff --git a/src/modules/title/title.c b/src/modules/title/title.c index cce1c6bb1..939f4daf9 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -187,7 +187,7 @@ FFModuleBaseInfo ffTitleModuleInfo = { .ja = "タイトル", .ko = "제목", .pl = "Tytuł", - .pt_BR = "Título", + .pt = "Título", .ru = "Заголовок", .zh_CN = "标题", .zh_TW = "標題", diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 1b85104e7..c216b05b5 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -94,7 +94,7 @@ FFModuleBaseInfo ffTPMModuleInfo = { .ja = "TPM", .ko = "TPM", .pl = "TPM", - .pt_BR = "TPM", + .pt = "TPM", .ru = "TPM", .zh_CN = "TPM", .zh_TW = "TPM", diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 0bed6ea13..9cc364c41 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -94,7 +94,7 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .ja = "稼働時間", .ko = "업타임", .pl = "Czas pracy", - .pt_BR = "Tempo de atividade", + .pt = "Tempo de atividade", .ru = "Время работы", .zh_CN = "运行时间", .zh_TW = "運行時間", diff --git a/src/modules/users/users.c b/src/modules/users/users.c index c59373bee..d2e127076 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -191,7 +191,7 @@ FFModuleBaseInfo ffUsersModuleInfo = { .ja = "ユーザー", .ko = "사용자", .pl = "Użytkownicy", - .pt_BR = "Usuários", + .pt = "Usuários", .ru = "Пользователи", .zh_CN = "用户", .zh_TW = "使用者", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 56c142d76..d023abe88 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -105,7 +105,7 @@ FFModuleBaseInfo ffVersionModuleInfo = { .ja = "バージョン", .ko = "버전", .pl = "Wersja", - .pt_BR = "Versão", + .pt = "Versão", .ru = "Версия", .zh_CN = "版本", .zh_TW = "版本", diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index a16cac601..2d6dbfd22 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -143,7 +143,7 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .ja = "Vulkan", .ko = "Vulkan", .pl = "Vulkan", - .pt_BR = "Vulkan", + .pt = "Vulkan", .ru = "Vulkan", .zh_CN = "Vulkan", .zh_TW = "Vulkan", diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index e0f203a58..e57082fc5 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -86,7 +86,7 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .ja = "壁紙", .ko = "배경화면", .pl = "Tapeta", - .pt_BR = "Papel de parede", + .pt = "Papel de parede", .ru = "Обои", .zh_CN = "壁纸", .zh_TW = "桌布", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 7a2192a79..9f7dae54d 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -103,7 +103,7 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .ja = "天気", .ko = "날씨", .pl = "Pogoda", - .pt_BR = "Clima", + .pt = "Clima", .ru = "Погода", .zh_CN = "天气", .zh_TW = "天氣", diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index d5baa00ff..39e99a38e 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -224,7 +224,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { .ja = "Wi-Fi", .ko = "와이파이", .pl = "Wi-Fi", - .pt_BR = "Wi-Fi", + .pt = "Wi-Fi", .ru = "Wi-Fi", .zh_CN = "无线网络", .zh_TW = "無線網路", diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 35e58c4f1..4c40bc206 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -131,7 +131,7 @@ FFModuleBaseInfo ffWMModuleInfo = { .ja = "ウィンドウマネージャー", .ko = "윈도우 관리자", .pl = "Menedżer okien", - .pt_BR = "Gerenciador de janelas", + .pt = "Gerenciador de janelas", .ru = "Менеджер окон", .zh_CN = "窗口管理器", .zh_TW = "視窗管理員", diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 8c7e3afe3..b7ed26b42 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -70,7 +70,7 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .ja = "ウィンドウマネージャのテーマ", .ko = "윈도우 관리자 테마", .pl = "Motyw menedżera okien", - .pt_BR = "Tema do gerenciador de janelas", + .pt = "Tema do gerenciador de janelas", .ru = "Тема менеджера окон", .zh_CN = "窗口管理器主题", .zh_TW = "視窗管理員主題", diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 0e447d5e4..f6ea00c40 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -203,7 +203,7 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .ja = "Zpool", .ko = "Zpool", .pl = "Zpool", - .pt_BR = "Zpool", + .pt = "Zpool", .ru = "Zpool", .zh_CN = "Zpool", .zh_TW = "Zpool", diff --git a/src/options/display.c b/src/options/display.c index 9ce0a9677..78ea684ce 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -70,8 +70,8 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { case 'ko': return offsetof(FFModuleDisplayName, ko); case 'pl': return offsetof(FFModuleDisplayName, pl); case 'pt': { - if (ffStrbufEqualS(language, "pt_br")) { - return offsetof(FFModuleDisplayName, pt_BR); + if (ffStrbufEqualS(language, "pt")) { + return offsetof(FFModuleDisplayName, pt); } goto error; } @@ -1290,8 +1290,8 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, pl): yyjson_mut_obj_add_str(doc, key, "language", "pl"); break; - case offsetof(FFModuleDisplayName, pt_BR): - yyjson_mut_obj_add_str(doc, key, "language", "pt_BR"); + case offsetof(FFModuleDisplayName, pt): + yyjson_mut_obj_add_str(doc, key, "language", "pt"); break; case offsetof(FFModuleDisplayName, ru): yyjson_mut_obj_add_str(doc, key, "language", "ru"); From b700d9ded52a514e0a65f09129c19f74b979046a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:39:10 +0800 Subject: [PATCH 014/109] =?UTF-8?q?L10n=20(Ru):=20changes=20`=D0=91=D0=BB?= =?UTF-8?q?=D1=8E=D1=82=D1=83=D1=81`=20to=20`=D0=91=D0=BB=D1=8E=D1=82?= =?UTF-8?q?=D1=83=D0=B7`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref: https://github.com/fastfetch-cli/fastfetch/issues/2503#issuecomment-5304614812 --- src/modules/bluetooth/bluetooth.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 22606b77e..125c68fb2 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -163,7 +163,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .ko = "블루투스", .pl = "Bluetooth", .pt = "Bluetooth", - .ru = "Блютус", + .ru = "Блютуз", .zh_CN = "蓝牙", .zh_TW = "藍牙", }, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 330bf8948..cbb041f58 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -200,7 +200,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", .pt = "Adaptador Bluetooth", - .ru = "Блютус-адаптер", + .ru = "Блютуз-адаптер", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", }, From 2de674ec9a7160c5427e90ad2a80df9c45581997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:51:42 +0800 Subject: [PATCH 015/109] L10n (Ar / He): adds support Fixes #2520 --- doc/help.json | 2 ++ doc/json_schema.json | 10 ++++++++++ src/common/option.h | 2 ++ src/modules/battery/battery.c | 2 ++ src/modules/bios/bios.c | 2 ++ src/modules/bluetooth/bluetooth.c | 2 ++ src/modules/bluetoothradio/bluetoothradio.c | 2 ++ src/modules/board/board.c | 2 ++ src/modules/bootmgr/bootmgr.c | 2 ++ src/modules/break/break.c | 2 ++ src/modules/brightness/brightness.c | 2 ++ src/modules/btrfs/btrfs.c | 2 ++ src/modules/camera/camera.c | 2 ++ src/modules/chassis/chassis.c | 2 ++ src/modules/codec/codec.c | 2 ++ src/modules/colors/colors.c | 2 ++ src/modules/command/command.c | 2 ++ src/modules/cpu/cpu.c | 2 ++ src/modules/cpucache/cpucache.c | 2 ++ src/modules/cpuusage/cpuusage.c | 2 ++ src/modules/cursor/cursor.c | 2 ++ src/modules/custom/custom.c | 2 ++ src/modules/datetime/datetime.c | 2 ++ src/modules/de/de.c | 2 ++ src/modules/disk/disk.c | 2 ++ src/modules/diskio/diskio.c | 2 ++ src/modules/display/display.c | 2 ++ src/modules/dns/dns.c | 2 ++ src/modules/editor/editor.c | 2 ++ src/modules/font/font.c | 2 ++ src/modules/gamepad/gamepad.c | 2 ++ src/modules/gpu/gpu.c | 2 ++ src/modules/host/host.c | 2 ++ src/modules/icons/icons.c | 2 ++ src/modules/initsystem/initsystem.c | 2 ++ src/modules/kernel/kernel.c | 2 ++ src/modules/keyboard/keyboard.c | 2 ++ src/modules/lm/lm.c | 2 ++ src/modules/loadavg/loadavg.c | 2 ++ src/modules/locale/locale.c | 2 ++ src/modules/localip/localip.c | 2 ++ src/modules/logo/logo.c | 2 ++ src/modules/media/media.c | 2 ++ src/modules/memory/memory.c | 2 ++ src/modules/monitor/monitor.c | 2 ++ src/modules/mouse/mouse.c | 2 ++ src/modules/netio/netio.c | 2 ++ src/modules/opencl/opencl.c | 2 ++ src/modules/opengl/opengl.c | 2 ++ src/modules/os/os.c | 2 ++ src/modules/packages/packages.c | 2 ++ src/modules/physicaldisk/physicaldisk.c | 2 ++ src/modules/physicalmemory/physicalmemory.c | 2 ++ src/modules/player/player.c | 2 ++ src/modules/poweradapter/poweradapter.c | 2 ++ src/modules/processes/processes.c | 2 ++ src/modules/publicip/publicip.c | 2 ++ src/modules/separator/separator.c | 2 ++ src/modules/shell/shell.c | 2 ++ src/modules/sound/sound.c | 2 ++ src/modules/swap/swap.c | 2 ++ src/modules/terminal/terminal.c | 2 ++ src/modules/terminalfont/terminalfont.c | 2 ++ src/modules/terminalsize/terminalsize.c | 2 ++ src/modules/terminaltheme/terminaltheme.c | 2 ++ src/modules/theme/theme.c | 2 ++ src/modules/title/title.c | 2 ++ src/modules/tpm/tpm.c | 2 ++ src/modules/uptime/uptime.c | 2 ++ src/modules/users/users.c | 2 ++ src/modules/version/version.c | 2 ++ src/modules/vulkan/vulkan.c | 2 ++ src/modules/wallpaper/wallpaper.c | 2 ++ src/modules/weather/weather.c | 2 ++ src/modules/wifi/wifi.c | 2 ++ src/modules/wm/wm.c | 2 ++ src/modules/wmtheme/wmtheme.c | 2 ++ src/modules/zpool/zpool.c | 2 ++ src/options/display.c | 8 ++++++++ 79 files changed, 172 insertions(+) diff --git a/doc/help.json b/doc/help.json index 4331d2b63..b1cfbfa56 100644 --- a/doc/help.json +++ b/doc/help.json @@ -595,9 +595,11 @@ "optional": true, "enum": { "en": "English", + "ar": "Arabic", "de": "German", "es": "Spanish", "fr": "French", + "he": "Hebrew", "it": "Italian", "ja": "Japanese", "ko": "Korean", diff --git a/doc/json_schema.json b/doc/json_schema.json index 7075bc47e..3dbc06e98 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1070,6 +1070,11 @@ "const": "en", "description": "English" }, + { + "type": "string", + "const": "ar", + "description": "Arabic" + }, { "type": "string", "const": "de", @@ -1085,6 +1090,11 @@ "const": "fr", "description": "French" }, + { + "type": "string", + "const": "he", + "description": "Hebrew" + }, { "type": "string", "const": "it", diff --git a/src/common/option.h b/src/common/option.h index be7c475f8..e8f2dca1d 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -21,9 +21,11 @@ typedef struct FFModuleFormatArgList { typedef struct FFModuleDisplayName { const char* en; // English + const char* ar; // Arabic const char* de; // German const char* es; // Spanish const char* fr; // French + const char* he; // Hebrew const char* it; // Italian const char* ja; // Japanese const char* ko; // Korean diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 66334abb7..9fd8c4572 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -301,9 +301,11 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .description = "Print battery information", .displayName = { .en = "Battery", + .ar = "البطارية", .de = "Akku", .es = "Batería", .fr = "Batterie", + .he = "סוללה", .it = "Batteria", .ja = "バッテリー", .ko = "배터리", diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 34dfcb08a..6b129213c 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -134,9 +134,11 @@ FFModuleBaseInfo ffBiosModuleInfo = { .description = "Print first-stage bootloader information (name, version, release date, etc.)", .displayName = { .en = "BIOS", + .ar = "BIOS", .de = "BIOS", .es = "BIOS", .fr = "BIOS", + .he = "BIOS", .it = "BIOS", .ja = "BIOS", .ko = "BIOS", diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 125c68fb2..ab98f1f46 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -155,9 +155,11 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .description = "List connected Bluetooth devices", .displayName = { .en = "Bluetooth", + .ar = "بلوتوث", .de = "Bluetooth", .es = "Bluetooth", .fr = "Bluetooth", + .he = "בלוטות'", .it = "Bluetooth", .ja = "ブルートゥース", .ko = "블루투스", diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index cbb041f58..f8b22a9f4 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -192,9 +192,11 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .description = "List Bluetooth radios (supported versions, vendors, etc.)", .displayName = { .en = "Bluetooth Radio", + .ar = "راديو بلوتوث", .de = "Bluetooth-Adapter", .es = "Adaptador Bluetooth", .fr = "Adaptateur Bluetooth", + .he = "רדיו בלוטות'", .it = "Adattatore Bluetooth", .ja = "ブルートゥースアダプター", .ko = "블루투스 어댑터", diff --git a/src/modules/board/board.c b/src/modules/board/board.c index e9f883b1a..b82d90bc5 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -112,9 +112,11 @@ FFModuleBaseInfo ffBoardModuleInfo = { .description = "Print motherboard name and other information", .displayName = { .en = "Board", + .ar = "اللوحة الأم", .de = "Mainboard", .es = "Placa base", .fr = "Carte mère", + .he = "לוח אם", .it = "Scheda madre", .ja = "マザーボード", .ko = "메인보드", diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index f0538f68a..db7a9c473 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -107,9 +107,11 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .description = "Print second-stage bootloader information (name, firmware, etc.)", .displayName = { .en = "Boot Manager", + .ar = "مدير الإقلاع", .de = "Boot-Manager", .es = "Administrador de arranque", .fr = "Gestionnaire de démarrage", + .he = "מנהל אתחול", .it = "Gestore di avvio", .ja = "ブートマネージャー", .ko = "부트 매니저", diff --git a/src/modules/break/break.c b/src/modules/break/break.c index d81400de7..f0ef529bc 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -31,9 +31,11 @@ FFModuleBaseInfo ffBreakModuleInfo = { .description = "Print an empty line", .displayName = { .en = "Break", + .ar = "فاصل", .de = "Umbruch", .es = "Salto de línea", .fr = "Saut de ligne", + .he = "מעבר שורה", .it = "Interruzione", .ja = "改行", .ko = "줄 바꿈", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index f70bd1349..16ff8e8b0 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -194,9 +194,11 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .description = "Print the current brightness level of your monitors", .displayName = { .en = "Brightness", + .ar = "السطوع", .de = "Helligkeit", .es = "Brillo", .fr = "Luminosité", + .he = "בהירות", .it = "Luminosità", .ja = "明るさ", .ko = "밝기", diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 9df262265..bbba974e8 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -202,9 +202,11 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .description = "Print Linux BTRFS volumes", .displayName = { .en = "BTRFS", + .ar = "BTRFS", .de = "BTRFS", .es = "BTRFS", .fr = "BTRFS", + .he = "BTRFS", .it = "BTRFS", .ja = "BTRFS", .ko = "BTRFS", diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 7758229c3..82cf79c03 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -119,9 +119,11 @@ FFModuleBaseInfo ffCameraModuleInfo = { .description = "Print available cameras", .displayName = { .en = "Camera", + .ar = "الكاميرا", .de = "Kamera", .es = "Cámara", .fr = "Caméra", + .he = "מצלמה", .it = "Fotocamera", .ja = "カメラ", .ko = "카메라", diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 576d3b83d..904f4d113 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -114,9 +114,11 @@ FFModuleBaseInfo ffChassisModuleInfo = { .description = "Print chassis type information (desktop, laptop, etc.)", .displayName = { .en = "Chassis", + .ar = "الهيكل", .de = "Gehäuse", .es = "Chasis", .fr = "Châssis", + .he = "מארז", .it = "Telaio", .ja = "シャーシ", .ko = "섀시", diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index 202a82236..6f7a3a1bb 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -255,9 +255,11 @@ FFModuleBaseInfo ffCodecModuleInfo = { .description = "Print hardware video acceleration codec types (decode / encode)", .displayName = { .en = "Codec", + .ar = "الترميز", .de = "Codec", .es = "Códec", .fr = "Codec", + .he = "קודק", .it = "Codec", .ja = "コーデック", .ko = "코덱", diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ace03ddd6..38ce77ce6 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -299,9 +299,11 @@ FFModuleBaseInfo ffColorsModuleInfo = { .description = "Display the terminal's 16-color palette", .displayName = { .en = "Colors", + .ar = "الألوان", .de = "Farben", .es = "Colores", .fr = "Couleurs", + .he = "צבעים", .it = "Colori", .ja = "色", .ko = "색상", diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 13131f627..a8e1b3f64 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -157,9 +157,11 @@ FFModuleBaseInfo ffCommandModuleInfo = { .description = "Run custom shell scripts", .displayName = { .en = "Command", + .ar = "الأمر", .de = "Befehl", .es = "Comando", .fr = "Commande", + .he = "פקודה", .it = "Comando", .ja = "コマンド", .ko = "명령어", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index b9c4166f5..5754fd08d 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -255,9 +255,11 @@ FFModuleBaseInfo ffCPUModuleInfo = { .description = "Print CPU name, frequency, etc.", .displayName = { .en = "CPU", + .ar = "المعالج", .de = "CPU", .es = "CPU", .fr = "CPU", + .he = "מעבד", .it = "CPU", .ja = "CPU", .ko = "CPU", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index feeb337d6..bf78de62d 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -225,9 +225,11 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .description = "Print CPU cache sizes", .displayName = { .en = "CPU Cache", + .ar = "ذاكرة المعالج المؤقتة", .de = "CPU-Cache", .es = "Caché de CPU", .fr = "Cache CPU", + .he = "מטמון מעבד", .it = "Cache CPU", .ja = "CPUキャッシュ", .ko = "CPU 캐시", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index b33c44f08..b649edba9 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -183,9 +183,11 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .description = "Print CPU usage. Collecting data takes some time", .displayName = { .en = "CPU Usage", + .ar = "استخدام المعالج", .de = "CPU-Auslastung", .es = "Uso del CPU", .fr = "Utilisation du CPU", + .he = "שימוש במעבד", .it = "Utilizzo della CPU", .ja = "CPU使用率", .ko = "CPU 사용량", diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 3cba64db8..f2c133bb6 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -104,9 +104,11 @@ FFModuleBaseInfo ffCursorModuleInfo = { .description = "Print cursor style name", .displayName = { .en = "Cursor", + .ar = "المؤشر", .de = "Mauszeiger", .es = "Cursor", .fr = "Curseur", + .he = "סמן", .it = "Cursore", .ja = "カーソル", .ko = "커서", diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 9b3044d51..c29bea05c 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -39,9 +39,11 @@ FFModuleBaseInfo ffCustomModuleInfo = { .description = "Print a custom string, with or without key", .displayName = { .en = "Custom", + .ar = "مخصص", .de = "Benutzerdefiniert", .es = "Personalizado", .fr = "Personnalisé", + .he = "מותאם אישית", .it = "Personalizzato", .ja = "カスタム", .ko = "사용자 정의", diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 180831799..1fb7ab9c5 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -154,9 +154,11 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .description = "Print the current date and time", .displayName = { .en = "Date & Time", + .ar = "التاريخ والوقت", .de = "Datum & Uhrzeit", .es = "Fecha y hora", .fr = "Date et heure", + .he = "תאריך ושעה", .it = "Data e ora", .ja = "日付と時刻", .ko = "날짜/시간", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 42b1e3c5b..9e4dcc3df 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -86,9 +86,11 @@ FFModuleBaseInfo ffDEModuleInfo = { .description = "Print desktop environment name", .displayName = { .en = "Desktop Environment", + .ar = "بيئة سطح المكتب", .de = "Desktop-Umgebung", .es = "Entorno de Escritorio", .fr = "Environnement de Bureau", + .he = "סביבת שולחן עבודה", .it = "Ambiente Desktop", .ja = "デスクトップ環境", .ko = "데스크탑 환경", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 7e34a6d57..dd823bc2b 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -455,9 +455,11 @@ FFModuleBaseInfo ffDiskModuleInfo = { .description = "Print partitions, space usage, file system, etc", .displayName = { .en = "Disk", + .ar = "القرص", .de = "Festplatte", .es = "Disco", .fr = "Disque", + .he = "דיסק", .it = "Disco", .ja = "ディスク", .ko = "디스크", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index b035133b5..51fc95fec 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -174,9 +174,11 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .description = "Print physical disk I/O throughput", .displayName = { .en = "Disk I/O", + .ar = "إدخال/إخراج القرص", .de = "Festplatten I/O", .es = "E/S de disco", .fr = "Entrée/Sortie disque", + .he = "קלט/פלט דיסק", .it = "I/O del disco", .ja = "ディスク I/O", .ko = "디스크 I/O", diff --git a/src/modules/display/display.c b/src/modules/display/display.c index c4d2e76a8..b7f0eefe5 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -415,9 +415,11 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .description = "Print resolutions, refresh rates, etc", .displayName = { .en = "Display", + .ar = "الشاشة", .de = "Anzeige", .es = "Pantalla", .fr = "Écran", + .he = "תצוגה", .it = "Display", .ja = "ディスプレイ", .ko = "디스플레이", diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index d7d7c0ad3..7067de9ca 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -138,9 +138,11 @@ FFModuleBaseInfo ffDNSModuleInfo = { .description = "Print configured DNS servers", .displayName = { .en = "DNS", + .ar = "DNS", .de = "DNS", .es = "DNS", .fr = "DNS", + .he = "DNS", .it = "DNS", .ja = "DNS", .ko = "DNS", diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 4fdddfc97..09cc37238 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -107,9 +107,11 @@ FFModuleBaseInfo ffEditorModuleInfo = { .description = "Print information about the default editor ($VISUAL or $EDITOR)", .displayName = { .en = "Editor", + .ar = "المحرر", .de = "Editor", .es = "Editor", .fr = "Éditeur", + .he = "עורך", .it = "Editor", .ja = "エディター", .ko = "편집기", diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 80bc7bcb7..22a464563 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -99,9 +99,11 @@ FFModuleBaseInfo ffFontModuleInfo = { .description = "Print system font names", .displayName = { .en = "Font", + .ar = "الخط", .de = "Schriftart", .es = "Fuente", .fr = "Police", + .he = "גופן", .it = "Carattere", .ja = "フォント", .ko = "글꼴", diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index d3e6503ee..7273156de 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -193,9 +193,11 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .description = "List connected gamepads", .displayName = { .en = "Gamepad", + .ar = "يد التحكم", .de = "Gamepad", .es = "Gamepad", .fr = "Manette", + .he = "משטח משחק", .it = "Gamepad", .ja = "ゲームパッド", .ko = "게임패드", diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 996c48338..d0caa2fcf 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -483,9 +483,11 @@ FFModuleBaseInfo ffGPUModuleInfo = { .description = "Print GPU names, memory sizes, types, etc", .displayName = { .en = "GPU", + .ar = "معالج الرسوميات", .de = "GPU", .es = "GPU", .fr = "GPU", + .he = "מעבד גרפי", .it = "GPU", .ja = "GPU", .ko = "GPU", diff --git a/src/modules/host/host.c b/src/modules/host/host.c index e8b549f30..ffe5c5225 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -140,9 +140,11 @@ FFModuleBaseInfo ffHostModuleInfo = { .description = "Print your computer's product name", .displayName = { .en = "Host", + .ar = "المضيف", .de = "Rechner", .es = "Host", .fr = "Hôte", + .he = "מארח", .it = "Host", .ja = "ホスト", .ko = "호스트", diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index d1c4e66c8..5da212d33 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -98,9 +98,11 @@ FFModuleBaseInfo ffIconsModuleInfo = { .description = "Print icon style name", .displayName = { .en = "Icons", + .ar = "الأيقونات", .de = "Symbole", .es = "Iconos", .fr = "Icônes", + .he = "סמלים", .it = "Icone", .ja = "アイコン", .ko = "아이콘", diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index f6315380c..395d10261 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -105,9 +105,11 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .description = "Print init system (pid 1) name and version", .displayName = { .en = "Init System", + .ar = "نظام الإقلاع", .de = "Init-System", .es = "Sistema de inicio", .fr = "Système d'init", + .he = "מערכת אתחול", .it = "Sistema di init", .ja = "initシステム", .ko = "초기화 시스템", diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 3e576816c..f0deb4727 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -66,9 +66,11 @@ FFModuleBaseInfo ffKernelModuleInfo = { .description = "Print system kernel version", .displayName = { .en = "Kernel", + .ar = "النواة", .de = "Kernel", .es = "Kernel", .fr = "Kernel", + .he = "ליבה", .it = "Kernel", .ja = "カーネル", .ko = "커널", diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 9af46f0d9..998e04262 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -153,9 +153,11 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .description = "List connected keyboards", .displayName = { .en = "Keyboard", + .ar = "لوحة المفاتيح", .de = "Tastatur", .es = "Teclado", .fr = "Clavier", + .he = "מקלדת", .it = "Tastiera", .ja = "キーボード", .ko = "키보드", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index c8b54c4eb..0b7d68649 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -110,9 +110,11 @@ FFModuleBaseInfo ffLMModuleInfo = { .description = "Print login manager (desktop manager) name and version", .displayName = { .en = "Login Manager", + .ar = "مدير تسجيل الدخول", .de = "Anmeldemanager", .es = "Administrador de inicio de sesión", .fr = "Gestionnaire de connexion", + .he = "מנהל התחברות", .it = "Gestore di accesso", .ja = "ログインマネージャー", .ko = "로그인 관리자", diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 85d504964..cfa36f857 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -152,9 +152,11 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .description = "Print system load averages", .displayName = { .en = "Load Average", + .ar = "متوسط الحمل", .de = "Systemlast", .es = "Promedio de carga", .fr = "Charge moyenne", + .he = "עומס ממוצע", .it = "Carico medio", .ja = "ロードアベレージ", .ko = "시스템 부하 평균", diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index f194edf0c..ca523c90c 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -71,9 +71,11 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .description = "Print system locale name", .displayName = { .en = "Locale", + .ar = "اللغة", .de = "Sprachraum", .es = "Configuración regional", .fr = "Paramètres régionaux", + .he = "לוקאל", .it = "Impostazioni locali", .ja = "ロケール", .ko = "로케일", diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index e7e098626..accff5f47 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -425,9 +425,11 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .description = "List local IP addresses (IPv4 or IPv6), MAC addresses, etc", .displayName = { .en = "Local IP", + .ar = "عنوان IP المحلي", .de = "Lokale IP", .es = "IP local", .fr = "IP locale", + .he = "IP מקומי", .it = "IP locale", .ja = "ローカル IP", .ko = "로컬 IP", diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 7e3aed314..860960b6e 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -81,9 +81,11 @@ FFModuleBaseInfo ffLogoModuleInfo = { .description = "Query built-in logo for JSON output", .displayName = { .en = "Logo", + .ar = "الشعار", .de = "Logo", .es = "Logo", .fr = "Logo", + .he = "לוגו", .it = "Logo", .ja = "ロゴ", .ko = "로고", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 6211b7c95..5e7188905 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -257,9 +257,11 @@ FFModuleBaseInfo ffMediaModuleInfo = { .description = "Print the name of the currently playing song", .displayName = { .en = "Media", + .ar = "الوسائط", .de = "Medien", .es = "Medios", .fr = "Médias", + .he = "מדיה", .it = "Media", .ja = "メディア", .ko = "미디어", diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index d5a63f6b0..d375bd9cc 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -122,9 +122,11 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .description = "Print system memory usage information", .displayName = { .en = "Memory", + .ar = "الذاكرة", .de = "Speicher", .es = "Memoria", .fr = "Mémoire", + .he = "זיכרון", .it = "Memoria", .ja = "メモリ", .ko = "메모리", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index aa55c022a..5019f7e7e 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -108,9 +108,11 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .description = "Same as Display module, but with a different default output format", .displayName = { .en = "Monitor", + .ar = "الشاشة", .de = "Monitor", .es = "Monitor", .fr = "Moniteur", + .he = "צג", .it = "Monitor", .ja = "モニター", .ko = "모니터", diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index f542c8375..b6db69243 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -156,9 +156,11 @@ FFModuleBaseInfo ffMouseModuleInfo = { .description = "List connected mice", .displayName = { .en = "Mouse", + .ar = "الفأرة", .de = "Maus", .es = "Ratón", .fr = "Souris", + .he = "עכבר", .it = "Mouse", .ja = "マウス", .ko = "마우스", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index e750ea92d..328cc3613 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -201,9 +201,11 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .description = "Print network I/O throughput", .displayName = { .en = "Network I/O", + .ar = "إدخال/إخراج الشبكة", .de = "Netzwerk I/O", .es = "E/S de red", .fr = "E/S réseau", + .he = "קלט/פלט רשת", .it = "I/O di rete", .ja = "ネットワークI/O", .ko = "네트워크 I/O", diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index fbc36c39a..78352f306 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -124,9 +124,11 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .description = "Print the highest OpenCL version supported by the GPU", .displayName = { .en = "OpenCL", + .ar = "OpenCL", .de = "OpenCL", .es = "OpenCL", .fr = "OpenCL", + .he = "OpenCL", .it = "OpenCL", .ja = "OpenCL", .ko = "OpenCL", diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index bac96afc7..8093e135d 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -131,9 +131,11 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .description = "Print the highest OpenGL version supported by the GPU", .displayName = { .en = "OpenGL", + .ar = "OpenGL", .de = "OpenGL", .es = "OpenGL", .fr = "OpenGL", + .he = "OpenGL", .it = "OpenGL", .ja = "OpenGL", .ko = "OpenGL", diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 71661bf0a..3e0fecc75 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -176,9 +176,11 @@ FFModuleBaseInfo ffOSModuleInfo = { .description = "Print the OS or Linux distribution name and version", .displayName = { .en = "OS", + .ar = "نظام التشغيل", .de = "Betriebssystem", .es = "Sistema operativo", .fr = "Système d'exploitation", + .he = "מערכת הפעלה", .it = "Sistema operativo", .ja = "オペレーティングシステム", .ko = "운영 체제", diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index c21ef4ca6..2c6143189 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -514,9 +514,11 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .description = "List installed package managers and count of installed packages", .displayName = { .en = "Packages", + .ar = "الحزم", .de = "Pakete", .es = "Paquetes", .fr = "Paquets", + .he = "חבילות", .it = "Pacchetti", .ja = "パッケージ", .ko = "패키지", diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index b85ec4410..929ca4b69 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -267,9 +267,11 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .description = "Print physical disk information", .displayName = { .en = "Physical Disk", + .ar = "القرص الفعلي", .de = "Physische Festplatte", .es = "Disco físico", .fr = "Disque physique", + .he = "דיסק פיזי", .it = "Disco fisico", .ja = "物理ディスク", .ko = "물리 디스크", diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 0ab65cdb5..5c0d6ecec 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -161,9 +161,11 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .description = "Print system physical memory devices", .displayName = { .en = "Physical Memory", + .ar = "الذاكرة الفعلية", .de = "Physischer Speicher", .es = "Memoria física", .fr = "Mémoire physique", + .he = "זיכרון פיזי", .it = "Memoria fisica", .ja = "物理メモリ", .ko = "물리 메모리", diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 0693423e0..c12da175d 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -111,9 +111,11 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .description = "Print the music player name that is currently active", .displayName = { .en = "Media Player", + .ar = "مشغل الوسائط", .de = "Medienplayer", .es = "Reproductor multimedia", .fr = "Lecteur multimédia", + .he = "נגן מדיה", .it = "Lettore multimediale", .ja = "メディアプレイヤー", .ko = "미디어 플레이어", diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 71899d26e..a70d3a36f 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -112,9 +112,11 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .description = "Print power adapter name and charging watts", .displayName = { .en = "Power Adapter", + .ar = "محول الطاقة", .de = "Netzteil", .es = "Adaptador de corriente", .fr = "Adaptateur secteur", + .he = "מתאם מתח", .it = "Alimentatore", .ja = "電源アダプター", .ko = "전원 어댑터", diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index bb42ca59e..824fd89d6 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -67,9 +67,11 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .description = "Print number of running processes", .displayName = { .en = "Processes", + .ar = "العمليات", .de = "Prozesse", .es = "Procesos", .fr = "Processus", + .he = "תהליכים", .it = "Processi", .ja = "プロセス", .ko = "프로세스", diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 92c790544..4fa09c32f 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -112,9 +112,11 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .description = "Print your public IP address and related information", .displayName = { .en = "Public IP", + .ar = "عنوان IP العام", .de = "Öffentliche IP", .es = "IP pública", .fr = "IP publique", + .he = "IP ציבורי", .it = "IP pubblica", .ja = "パブリックIP", .ko = "공용 IP", diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index f70c7a7bd..34af6a286 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -125,9 +125,11 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .description = "Print a separator line", .displayName = { .en = "Separator", + .ar = "الفاصل", .de = "Trennlinie", .es = "Separador", .fr = "Séparateur", + .he = "מפריד", .it = "Separatore", .ja = "セパレーター", .ko = "구분선", diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 55e0da630..4c9adf343 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -93,9 +93,11 @@ FFModuleBaseInfo ffShellModuleInfo = { .description = "Print the current shell name and version", .displayName = { .en = "Shell", + .ar = "الصدفة", .de = "Shell", .es = "Shell", .fr = "Shell", + .he = "מעטפת", .it = "Shell", .ja = "シェル", .ko = "셸", diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 7f3a691e5..fa87482f1 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -203,9 +203,11 @@ FFModuleBaseInfo ffSoundModuleInfo = { .description = "Print sound devices, volume levels, etc", .displayName = { .en = "Sound", + .ar = "الصوت", .de = "Sound", .es = "Sonido", .fr = "Son", + .he = "קול", .it = "Audio", .ja = "サウンド", .ko = "사운드", diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index ea0ac62de..201282dc0 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -186,9 +186,11 @@ FFModuleBaseInfo ffSwapModuleInfo = { .description = "Print swap (paging file) space usage", .displayName = { .en = "Swap", + .ar = "الذاكرة التبادلية", .de = "Swap", .es = "Swap", .fr = "Swap", + .he = "זיכרון החלפה", .it = "Swap", .ja = "スワップ", .ko = "스왑", diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 3752b45e0..58e6ae9cf 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -87,9 +87,11 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .description = "Print the current terminal name and version", .displayName = { .en = "Terminal", + .ar = "الطرفية", .de = "Terminal", .es = "Terminal", .fr = "Terminal", + .he = "טרמינל", .it = "Terminale", .ja = "ターミナル", .ko = "터미널", diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index fdb7990be..ae792843b 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -107,9 +107,11 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .description = "Print the font name and size used by the current terminal", .displayName = { .en = "Terminal Font", + .ar = "خط الطرفية", .de = "Terminalschriftart", .es = "Fuente del terminal", .fr = "Police du terminal", + .he = "גופן טרמינל", .it = "Carattere del terminale", .ja = "ターミナルフォント", .ko = "터미널 글꼴", diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 70f6139d1..08c2c9de0 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -78,9 +78,11 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .description = "Print the current terminal size", .displayName = { .en = "Terminal Size", + .ar = "حجم الطرفية", .de = "Terminalgröße", .es = "Tamaño del terminal", .fr = "Taille du terminal", + .he = "גודל טרמינל", .it = "Dimensioni terminale", .ja = "ターミナルサイズ", .ko = "터미널 크기", diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 4e40876f3..52e3feebf 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -95,9 +95,11 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .description = "Print the current terminal theme (foreground and background colors)", .displayName = { .en = "Terminal Theme", + .ar = "سمة الطرفية", .de = "Terminalthema", .es = "Tema del terminal", .fr = "Thème du terminal", + .he = "ערכת נושא של טרמינל", .it = "Tema del terminale", .ja = "ターミナルテーマ", .ko = "터미널 테마", diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 948e0d469..4ceaf14cb 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -91,9 +91,11 @@ FFModuleBaseInfo ffThemeModuleInfo = { .description = "Print the current desktop environment theme", .displayName = { .en = "Theme", + .ar = "السمة", .de = "Thema", .es = "Tema", .fr = "Thème", + .he = "ערכת נושא", .it = "Tema", .ja = "テーマ", .ko = "테마", diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 939f4daf9..788ab2eec 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -180,9 +180,11 @@ FFModuleBaseInfo ffTitleModuleInfo = { .description = "Print the title, including your username and hostname", .displayName = { .en = "Title", + .ar = "العنوان", .de = "Titel", .es = "Título", .fr = "Titre", + .he = "כותרת", .it = "Titolo", .ja = "タイトル", .ko = "제목", diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index c216b05b5..3ff4a4e8d 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -87,9 +87,11 @@ FFModuleBaseInfo ffTPMModuleInfo = { .description = "Print information about the Trusted Platform Module (TPM) security device", .displayName = { .en = "TPM", + .ar = "TPM", .de = "TPM", .es = "TPM", .fr = "TPM", + .he = "TPM", .it = "TPM", .ja = "TPM", .ko = "TPM", diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 9cc364c41..d7ee69e05 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -87,9 +87,11 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .description = "Print how long the system has been running", .displayName = { .en = "Uptime", + .ar = "مدة التشغيل", .de = "Betriebszeit", .es = "Tiempo de actividad", .fr = "Temps de fonctionnement", + .he = "זמן פעילות", .it = "Tempo di attività", .ja = "稼働時間", .ko = "업타임", diff --git a/src/modules/users/users.c b/src/modules/users/users.c index d2e127076..e355f40d7 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -184,9 +184,11 @@ FFModuleBaseInfo ffUsersModuleInfo = { .description = "Print users who are currently logged in", .displayName = { .en = "Users", + .ar = "المستخدمون", .de = "Benutzer", .es = "Usuarios", .fr = "Utilisateurs", + .he = "משתמשים", .it = "Utenti", .ja = "ユーザー", .ko = "사용자", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index d023abe88..f90585a73 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -98,9 +98,11 @@ FFModuleBaseInfo ffVersionModuleInfo = { .description = "Print the Fastfetch version and build information", .displayName = { .en = "Version", + .ar = "الإصدار", .de = "Version", .es = "Versión", .fr = "Version", + .he = "גרסה", .it = "Versione", .ja = "バージョン", .ko = "버전", diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 2d6dbfd22..990b56f1a 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -136,9 +136,11 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .description = "Print the highest Vulkan version supported by the GPU", .displayName = { .en = "Vulkan", + .ar = "Vulkan", .de = "Vulkan", .es = "Vulkan", .fr = "Vulkan", + .he = "Vulkan", .it = "Vulkan", .ja = "Vulkan", .ko = "Vulkan", diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index e57082fc5..9ed7d4014 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -79,9 +79,11 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .description = "Print the file path of the current wallpaper", .displayName = { .en = "Wallpaper", + .ar = "الخلفية", .de = "Hintergrundbild", .es = "Fondo de pantalla", .fr = "Fond d'écran", + .he = "טפט", .it = "Sfondo", .ja = "壁紙", .ko = "배경화면", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 9f7dae54d..5eab9a6c7 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -96,9 +96,11 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .description = "Print weather information", .displayName = { .en = "Weather", + .ar = "الطقس", .de = "Wetter", .es = "Clima", .fr = "Météo", + .he = "מזג אוויר", .it = "Meteo", .ja = "天気", .ko = "날씨", diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 39e99a38e..8aad2884e 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -217,9 +217,11 @@ FFModuleBaseInfo ffWifiModuleInfo = { .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", .displayName = { .en = "Wi-Fi", + .ar = "واي فاي", .de = "WLAN", .es = "Wi-Fi", .fr = "Wi-Fi", + .he = "Wi-Fi", .it = "Wi-Fi", .ja = "Wi-Fi", .ko = "와이파이", diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 4c40bc206..8b7d8ec26 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -124,9 +124,11 @@ FFModuleBaseInfo ffWMModuleInfo = { .description = "Print the window manager name and version", .displayName = { .en = "WM", + .ar = "مدير النوافذ", .de = "Fenstermanager", .es = "Gestor de ventanas", .fr = "Gestionnaire de fenêtres", + .he = "מנהל חלונות", .it = "Gestore finestre", .ja = "ウィンドウマネージャー", .ko = "윈도우 관리자", diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index b7ed26b42..5394b0963 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -63,9 +63,11 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .description = "Print the current window manager theme", .displayName = { .en = "WM Theme", + .ar = "سمة مدير النوافذ", .de = "Fenstermanager-Thema", .es = "Tema del gestor de ventanas", .fr = "Thème du gestionnaire de fenêtres", + .he = "ערכת נושא של מנהל חלונות", .it = "Tema del gestore finestre", .ja = "ウィンドウマネージャのテーマ", .ko = "윈도우 관리자 테마", diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index f6ea00c40..aafb5d4d9 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -196,9 +196,11 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .description = "Print ZFS storage pools", .displayName = { .en = "Zpool", + .ar = "Zpool", .de = "Zpool", .es = "Zpool", .fr = "Zpool", + .he = "Zpool", .it = "Zpool", .ja = "Zpool", .ko = "Zpool", diff --git a/src/options/display.c b/src/options/display.c index 78ea684ce..20625be92 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -62,9 +62,11 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { #pragma GCC diagnostic ignored "-Wmultichar" switch (language->chars[0] << 8 | language->chars[1]) { case 'en': return offsetof(FFModuleDisplayName, en); + case 'ar': return offsetof(FFModuleDisplayName, ar); case 'de': return offsetof(FFModuleDisplayName, de); case 'es': return offsetof(FFModuleDisplayName, es); case 'fr': return offsetof(FFModuleDisplayName, fr); + case 'he': return offsetof(FFModuleDisplayName, he); case 'it': return offsetof(FFModuleDisplayName, it); case 'ja': return offsetof(FFModuleDisplayName, ja); case 'ko': return offsetof(FFModuleDisplayName, ko); @@ -1269,6 +1271,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, en): yyjson_mut_obj_add_str(doc, key, "language", "en"); break; + case offsetof(FFModuleDisplayName, ar): + yyjson_mut_obj_add_str(doc, key, "language", "ar"); + break; case offsetof(FFModuleDisplayName, de): yyjson_mut_obj_add_str(doc, key, "language", "de"); break; @@ -1278,6 +1283,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, fr): yyjson_mut_obj_add_str(doc, key, "language", "fr"); break; + case offsetof(FFModuleDisplayName, he): + yyjson_mut_obj_add_str(doc, key, "language", "he"); + break; case offsetof(FFModuleDisplayName, it): yyjson_mut_obj_add_str(doc, key, "language", "it"); break; From bbb906ba10c9b9bcc664c3f0fe016fe6459749c4 Mon Sep 17 00:00:00 2001 From: Hashing <88584784+HashimAbdulaziz@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:15:39 +0300 Subject: [PATCH 016/109] L10n (Pt): matches all Portuguese locales, not only bare `pt` (#2521) 359cb0a79a3531e382fdb0c99357252936f08bf2 renamed the key from `pt_BR` to `pt` but kept the exact-match guard, so only the literal string `pt` matched. Every real Portuguese locale (`pt_BR`, `pt_PT` and their charset and modifier variants) fell through to `goto error` and aborted. Return the offset unconditionally, matching every other two-letter case. --- src/options/display.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/options/display.c b/src/options/display.c index 20625be92..36d408f78 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -71,12 +71,7 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { case 'ja': return offsetof(FFModuleDisplayName, ja); case 'ko': return offsetof(FFModuleDisplayName, ko); case 'pl': return offsetof(FFModuleDisplayName, pl); - case 'pt': { - if (ffStrbufEqualS(language, "pt")) { - return offsetof(FFModuleDisplayName, pt); - } - goto error; - } + case 'pt': return offsetof(FFModuleDisplayName, pt); case 'ru': return offsetof(FFModuleDisplayName, ru); case 'zh': { if (ffStrbufEqualS(language, "zh_cn")) { From 7fbd06a135ceb4666c9dd56b83ef8df95efcfc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 22:16:52 +0800 Subject: [PATCH 017/109] Doc: updates README.md [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f2481cbd..84ec8e975 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ See the Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building * View all data that fastfetch detects: `fastfetch -s [:][:] --format json` * Display help messages: `fastfetch --help` * Generate a minimal config file: `fastfetch [-s [:]] --gen-config []` - * Use: `--gen-config-full` to generate a full config file with all optional options + * Use [The online configuration generator](https://fastfetch-cli.github.io/fastfetch-config/) to generate a full config file with all optional options ## Customization From 9ff7969acf6da6db32a6940b36a6bd489691ec8a Mon Sep 17 00:00:00 2001 From: Wehrwolfmann Date: Sun, 16 Aug 2026 17:45:24 +0200 Subject: [PATCH 018/109] Bluetooth / BluetoothRadio: keeps the brand name in Latin script in Russian keys --- src/modules/bluetooth/bluetooth.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index ab98f1f46..95a0bae93 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -165,7 +165,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .ko = "블루투스", .pl = "Bluetooth", .pt = "Bluetooth", - .ru = "Блютуз", + .ru = "Bluetooth", .zh_CN = "蓝牙", .zh_TW = "藍牙", }, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index f8b22a9f4..5a6b47d71 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -202,7 +202,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", .pt = "Adaptador Bluetooth", - .ru = "Блютуз-адаптер", + .ru = "Bluetooth-адаптер", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", }, From bcb48774a0a0cd92a28ec0ec89157288a5bf4fbf Mon Sep 17 00:00:00 2001 From: Wehrwolfmann Date: Sun, 16 Aug 2026 17:51:44 +0200 Subject: [PATCH 019/109] Modules: proofreads Russian l10n strings --- src/modules/chassis/chassis.c | 2 +- src/modules/cpu/cpu.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/de/de.c | 2 +- src/modules/diskio/diskio.c | 2 +- src/modules/gpu/gpu.c | 2 +- src/modules/host/host.c | 2 +- src/modules/initsystem/initsystem.c | 2 +- src/modules/poweradapter/poweradapter.c | 2 +- src/modules/publicip/publicip.c | 2 +- src/modules/swap/swap.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 904f4d113..ae99ba9c5 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -124,7 +124,7 @@ FFModuleBaseInfo ffChassisModuleInfo = { .ko = "섀시", .pl = "Obudowa", .pt = "Chassi", - .ru = "Шасси", + .ru = "Корпус", .zh_CN = "机箱", .zh_TW = "機箱", }, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 5754fd08d..ec14dd363 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -265,7 +265,7 @@ FFModuleBaseInfo ffCPUModuleInfo = { .ko = "CPU", .pl = "CPU", .pt = "CPU", - .ru = "CPU", + .ru = "Процессор", .zh_CN = "CPU", .zh_TW = "CPU", }, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index b649edba9..e2b09a03a 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -193,7 +193,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .ko = "CPU 사용량", .pl = "Użycie CPU", .pt = "Uso da CPU", - .ru = "Использование ЦП", + .ru = "Использование процессора", .zh_CN = "CPU使用率", .zh_TW = "CPU使用率", }, diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 9e4dcc3df..c8b188d48 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -96,7 +96,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .ko = "데스크탑 환경", .pl = "Środowisko graficzne", .pt = "Ambiente de desktop", - .ru = "Рабочая среда", + .ru = "Рабочее окружение", .zh_CN = "桌面环境", .zh_TW = "桌面環境", }, diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 51fc95fec..3ebb8ce30 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -184,7 +184,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .ko = "디스크 I/O", .pl = "Dysk I/O", .pt = "Disco I/O", - .ru = "Диск I/O", + .ru = "Дисковый I/O", .zh_CN = "磁盘 I/O", .zh_TW = "磁碟 I/O", }, diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index d0caa2fcf..f030795da 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -493,7 +493,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { .ko = "GPU", .pl = "GPU", .pt = "GPU", - .ru = "GPU", + .ru = "Видеокарта", .zh_CN = "显卡", .zh_TW = "顯卡", }, diff --git a/src/modules/host/host.c b/src/modules/host/host.c index ffe5c5225..0159423bf 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -150,7 +150,7 @@ FFModuleBaseInfo ffHostModuleInfo = { .ko = "호스트", .pl = "Host", .pt = "Host", - .ru = "Хост", + .ru = "Модель", .zh_CN = "主机", .zh_TW = "主機", }, diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index 395d10261..edd3d8fdc 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -115,7 +115,7 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .ko = "초기화 시스템", .pl = "System init", .pt = "Sistema de inicialização", - .ru = "Init-система", + .ru = "Система инициализации", .zh_CN = "Init 系统", .zh_TW = "Init 系統", }, diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index a70d3a36f..d9506c41b 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -122,7 +122,7 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .ko = "전원 어댑터", .pl = "Zasilacz", .pt = "Fonte de alimentação", - .ru = "Блок питания", + .ru = "Адаптер питания", .zh_CN = "电源适配器", .zh_TW = "電源轉接器", }, diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 4fa09c32f..afad49017 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -122,7 +122,7 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .ko = "공용 IP", .pl = "Publiczne IP", .pt = "IP público", - .ru = "Публичный IP", + .ru = "Внешний IP", .zh_CN = "公网 IP", .zh_TW = "公網 IP", }, diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 201282dc0..796cf7271 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -196,7 +196,7 @@ FFModuleBaseInfo ffSwapModuleInfo = { .ko = "스왑", .pl = "Swap", .pt = "Swap", - .ru = "Своп", + .ru = "Подкачка", .zh_CN = "交换空间", .zh_TW = "交換空間", }, From 5e9c31ac311da08043877c5032f3c0405128dcb9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 10:32:40 +0800 Subject: [PATCH 020/109] Completion (Fish): prints enum description [ci skip] --- completions/fastfetch.fish | 80 ++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/completions/fastfetch.fish b/completions/fastfetch.fish index f4804f5f5..45397a6b7 100755 --- a/completions/fastfetch.fish +++ b/completions/fastfetch.fish @@ -63,46 +63,78 @@ echo ' import json, subprocess, sys +def escape_fish_dq(s: str) -> str: + """Escape special characters for Fish double quotes to prevent unexpected expansions. One slash in output needs four slashes in script""" + return str(s).replace("\\\\", "\\\\\\\\").replace("\\"", "\\\\\\"").replace("$", "\\\\$") + + def main(): data: dict[str, list[dict]] = json.loads(subprocess.check_output(["fastfetch", "--help-raw"])) + enum_functions = [] + complete_commands = [] + for key in data: for flag in data[key]: - if flag["long"] == "logo-color-[1-9]": + long_name = flag.get("long", "") + + # Handle pseudo flag logo-color-[1-9] + if long_name == "logo-color-[1-9]": + safe_desc_global = escape_fish_dq(flag.get("desc", "")) for i in range(1, 10): - print(f"""complete -c fastfetch -d "{flag["desc"]}" -l "logo-color-{i}" -x -a "(__fastfetch_complete_color)" """) + complete_commands.append(f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"logo-color-{i}\" -x -a \"(__fastfetch_complete_color)\"") continue if flag.get("pseudo", False): continue - command_prefix = f"""complete -c fastfetch -d "{flag["desc"]}" -l "{flag["long"]}\"""" + safe_desc_global = escape_fish_dq(flag.get("desc", "")) + command_prefix = f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"{long_name}\"" + if "short" in flag: - command_prefix += f""" -o {flag["short"]}""" + short_name = flag["short"] + command_prefix += f" -o {short_name}" if "arg" in flag: - type: str = flag["arg"]["type"] - if type == "bool": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"") - elif type == "color": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"") - elif type == "command": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"") - elif type == "config": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"") - elif type == "enum": - temp: str = " ".join(flag["arg"]["enum"]) - print(f"{command_prefix} -x -a \"{temp}\"") - elif type == "logo": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"") - elif type == "structure": - print(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"") - elif type == "path": - print(f"{command_prefix} -r -F") + arg_type: str = flag["arg"]["type"] + if arg_type == "bool": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"") + elif arg_type == "color": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"") + elif arg_type == "command": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"") + elif arg_type == "config": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"") + elif arg_type == "enum": + # Sanitize flag name to create a valid Fish function name + func_name = long_name.replace("-", "_").replace("[", "_").replace("]", "_") + func_name = f"__fastfetch_complete_enum_{func_name}" + + # Generate the enum function + func_lines = [f"function {func_name}"] + for enum_val, enum_desc in flag["arg"]["enum"].items(): + safe_val = escape_fish_dq(enum_val) + safe_desc = escape_fish_dq(enum_desc) + func_lines.append(f" echo -e \"{safe_val}\\t{safe_desc}\"") + func_lines.append("end\n") + enum_functions.append("\n".join(func_lines)) + + # Append complete command pointing to the new function + complete_commands.append(f"{command_prefix} -x -a \"({func_name})\"") + elif arg_type == "logo": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"") + elif arg_type == "structure": + complete_commands.append(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"") + elif arg_type == "path": + complete_commands.append(f"{command_prefix} -r -F") else: - print(f"{command_prefix} -x") + complete_commands.append(f"{command_prefix} -x") else: - print(f"{command_prefix} -f") + complete_commands.append(f"{command_prefix} -f") + + # Print generated enum functions first, then complete rules + print("\n".join(enum_functions)) + print("\n".join(complete_commands)) if __name__ == "__main__": From 2ca7e037ef2b6c249faa801fbbe2a3193fdd8880 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 13:36:09 +0800 Subject: [PATCH 021/109] L10n (Zh): translates `shell` --- src/modules/shell/shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 4c9adf343..8abd01d52 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -104,8 +104,8 @@ FFModuleBaseInfo ffShellModuleInfo = { .pl = "Powłoka", .pt = "Shell", .ru = "Оболочка", - .zh_CN = "Shell", - .zh_TW = "Shell", + .zh_CN = "命令行解释器", + .zh_TW = "命令列直譯器", }, .initOptions = (void*) ffInitShellOptions, .destroyOptions = (void*) ffDestroyShellOptions, From 72d240f3259b70abd6dec323a30056934fdeee84 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 13:42:30 +0800 Subject: [PATCH 022/109] L10n (Zh): clarifies `Bluetooth` actually detects `Bluetooth devices` --- src/modules/bluetooth/bluetooth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 95a0bae93..d4adae821 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -166,8 +166,8 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .pl = "Bluetooth", .pt = "Bluetooth", .ru = "Bluetooth", - .zh_CN = "蓝牙", - .zh_TW = "藍牙", + .zh_CN = "蓝牙设备", + .zh_TW = "藍牙裝置", }, .initOptions = (void*) ffInitBluetoothOptions, .destroyOptions = (void*) ffDestroyBluetoothOptions, From 679d868b4ad99d1d345b8cdab103e38f7b39d1b9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 13:57:23 +0800 Subject: [PATCH 023/109] L10n (Zh): clarifies `Disk` actually detects `Disk partitions` --- src/modules/disk/disk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index dd823bc2b..fddd4580f 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -466,8 +466,8 @@ FFModuleBaseInfo ffDiskModuleInfo = { .pl = "Dysk", .pt = "Disco", .ru = "Диск", - .zh_CN = "磁盘", - .zh_TW = "磁碟", + .zh_CN = "磁盘分区", + .zh_TW = "硬碟分割", }, .initOptions = (void*) ffInitDiskOptions, .destroyOptions = (void*) ffDestroyDiskOptions, From e6d90c2081b907a27a922a4dce2cd1af6ab028c8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 14:20:46 +0800 Subject: [PATCH 024/109] L10n (Zh): uses a different name for `Monitor` --- src/modules/monitor/monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 5019f7e7e..a9959187b 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -119,8 +119,8 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .pl = "Monitor", .pt = "Monitor", .ru = "Монитор", - .zh_CN = "显示器", - .zh_TW = "顯示器", + .zh_CN = "监视器", + .zh_TW = "監視器", }, .initOptions = (void*) ffInitMonitorOptions, .destroyOptions = (void*) ffDestroyMonitorOptions, From 6cb15885c7376519faf4daf2e5bc2c401d9b2185 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 09:11:50 +0800 Subject: [PATCH 025/109] L10n: don't use `ffStrbufCreateStatic` for buffers that will be modified later --- src/options/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options/display.c b/src/options/display.c index 36d408f78..994296d78 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -741,7 +741,7 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key } else if (ffStrEqualsIgnCase(subkey, "padding-left")) { options->keyPaddingLeft = (uint16_t) ffOptionParseUInt32(key, value); } else if (ffStrEqualsIgnCase(subkey, "language")) { - FF_STRBUF_AUTO_DESTROY language = ffStrbufCreateStatic(value); + FF_STRBUF_AUTO_DESTROY language = ffStrbufCreateS(value); options->keyLanguage = optionParseLanguageString(&language); } else { return false; From e5b6e3612ac477058503e28bb217a44931a20f9d Mon Sep 17 00:00:00 2001 From: Wehrwolfmann Date: Tue, 18 Aug 2026 02:04:01 +0200 Subject: [PATCH 026/109] L10n: falls back to English when the auto-detected locale is unsupported --key-language with an empty value (and "language": null in the config) asks for the system locale, not for a specific language. When that locale has no translation, fastfetch aborted with exit 477 instead of printing anything, so the same config broke on every locale outside the twelve supported ones, and under LC_ALL=C variants such as POSIX. Auto-detected locales now fall back to English. An explicitly requested language still errors out, so typos and zh are still reported. --- doc/help.json | 2 +- src/options/display.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/help.json b/doc/help.json index b1cfbfa56..b575aa47b 100644 --- a/doc/help.json +++ b/doc/help.json @@ -588,7 +588,7 @@ { "long": "key-language", "desc": "Specify the language used for module keys", - "remark": "Leave empty for auto-detection based on the system locale", + "remark": "Leave empty for auto-detection based on the system locale. Unsupported locales fall back to English", "arg": { "type": "enum", "default": "en", diff --git a/src/options/display.c b/src/options/display.c index 994296d78..a352af719 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -17,7 +17,9 @@ // @returns offsetof(FFModuleDisplayName, ) // @see src/common/option.h static uint32_t optionParseLanguageString(FFstrbuf* language) { - if (language->length == 0) { + const bool detected = language->length == 0; + + if (detected) { #if !FF_MODULE_DISABLE_LOCALE const char* error = ffDetectLocale(language); if (__builtin_expect(error != nullptr, false)) { @@ -52,7 +54,7 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { // The language code is expected to be in the format of "en", "en_US", "de", "de_DE", etc. // First try to match the full language code, then try to match just the first two characters (the language part). - // If no match is found, report a language not supported error. + // If no match is found, report a language not supported error, unless the language was auto-detected. // en_US -> offsetof(FFModuleDisplayName, en) // en -> offsetof(FFModuleDisplayName, en) // zh_CN -> offsetof(FFModuleDisplayName, zh_CN) @@ -85,6 +87,10 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { #pragma GCC diagnostic pop error: + // The user asked for the system locale, not for this specific language. Most locales have no + // translation, so falling back to English is friendlier than aborting fastfetch entirely. + if (detected) return offsetof(FFModuleDisplayName, en); + fprintf(stderr, "Error: Language '%s' is not supported\n", language->chars); exit(477); } From 7c93f9c82af5b909935c5d2dcfa275f49662b2b7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 15:56:33 +0800 Subject: [PATCH 027/109] GPU (macOS): removes useless `@available` tests --- src/detection/gpu/gpu_apple.m | 122 ++++++++++++++++------------------ 1 file changed, 58 insertions(+), 64 deletions(-) diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index 24ede6de2..9596dbe76 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -14,74 +14,68 @@ #define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005) #endif -const char* ffGpuDetectDriverVersion(FFlist* gpus) -{ - if (@available(macOS 10.7, *)) - { - NSMutableArray* arr = NSMutableArray.new; - FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) - [arr addObject:@(x->driver.chars)]; - - NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)arr, (__bridge CFArrayRef)@[@"CFBundleVersion"])); - FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) - { - NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"]; - if (version) - { - ffStrbufAppendC(&x->driver, ' '); - ffStrbufAppendS(&x->driver, version.UTF8String); - } - } - return nullptr; +const char* ffGpuDetectDriverVersion(FFlist* gpus) { + NSMutableArray* arr = NSMutableArray.new; + FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) { + [arr addObject:@(x->driver.chars)]; } - return "Unsupported macOS version"; + + NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef) arr, (__bridge CFArrayRef) @[ @"CFBundleVersion" ])); + FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) { + NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"]; + if (version) { + ffStrbufAppendC(&x->driver, ' '); + ffStrbufAppendS(&x->driver, version.UTF8String); + } + } + return nullptr; } -const char* ffGpuDetectMetal(FFlist* gpus) -{ - if (@available(macOS 10.13, *)) - { - for (id device in MTLCopyAllDevices()) - { - FFGPUResult* gpu = nullptr; - FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) - { - if (x->deviceId == device.registryID) - { - gpu = x; - break; - } +const char* ffGpuDetectMetal(FFlist* gpus) { + // Metal.framework is statically linked into the application, + // so `MTLCopyAllDevices` is always available, or the application will not start. + for (id device in MTLCopyAllDevices()) { + FFGPUResult* gpu = nullptr; + FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) { + if (x->deviceId == device.registryID) { + gpu = x; + break; } - if (!gpu) continue; - - #ifndef MAC_OS_X_VERSION_10_15 - if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2"); - else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1"); - #else // MAC_OS_X_VERSION_10_15 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunguarded-availability-new" - if ([device supportsFamily:MTLGPUFamilyMetal4]) - ffStrbufSetStatic(&gpu->platformApi, "Metal 4"); - else if ([device supportsFamily:MTLGPUFamilyMetal3]) - ffStrbufSetStatic(&gpu->platformApi, "Metal 3"); - #pragma clang diagnostic pop - else if ([device supportsFamily:MTLGPUFamilyCommon3]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3"); - else if ([device supportsFamily:MTLGPUFamilyCommon2]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2"); - else if ([device supportsFamily:MTLGPUFamilyCommon1]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); - - gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - gpu->index = (uint32_t) device.locationNumber; - - if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) - gpu->shared.total = device.recommendedMaxWorkingSetSize; - #endif } - return nullptr; + if (!gpu) { + continue; + } + +#ifndef MAC_OS_X_VERSION_10_15 + if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2"); + } else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1"); + } +#else // MAC_OS_X_VERSION_10_15 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability-new" + if ([device supportsFamily:MTLGPUFamilyMetal4]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal 4"); + } else if ([device supportsFamily:MTLGPUFamilyMetal3]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal 3"); + } + #pragma clang diagnostic pop + else if ([device supportsFamily:MTLGPUFamilyCommon3]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3"); + } else if ([device supportsFamily:MTLGPUFamilyCommon2]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2"); + } else if ([device supportsFamily:MTLGPUFamilyCommon1]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); + } + + gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + gpu->index = (uint32_t) device.locationNumber; + + if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) { + gpu->shared.total = device.recommendedMaxWorkingSetSize; + } +#endif } - return "Metal API is not supported by this macOS version"; + return nullptr; } From 232cd6659ba39fdff71a1cb74f53e9833eb270b1 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 15:28:25 +0800 Subject: [PATCH 028/109] Wifi (Linux): adds channel width and device driver detection --- src/detection/wifi/wifi.h | 2 + src/detection/wifi/wifi_linux.c | 179 +++++++++++++++++++++++++++++++- src/modules/wifi/wifi.c | 8 ++ 3 files changed, 184 insertions(+), 5 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index e457295c3..7ad22855d 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -6,6 +6,7 @@ struct FFWifiInterface { FFstrbuf description; FFstrbuf status; + FFstrbuf driver; }; struct FFWifiConnection { @@ -18,6 +19,7 @@ struct FFWifiConnection { double rxRate; double txRate; uint16_t channel; + uint16_t channelWidth; // MHz uint16_t frequency; // MHz }; diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index c609c25c4..1fe21b0c4 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -212,8 +212,9 @@ static bool ffWifiNlInit(FFWifiNlContext* ctx) { return true; } -static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFstrbuf* protocol) { +static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFstrbuf* protocol, uint16_t* channelWidth) { double rate = -DBL_MAX; + uint16_t width = 0; size_t remaining = ffWifiNlAttrPayload(rateAttr); for (const struct nlattr* info = (const struct nlattr*) ffWifiNlAttrData(rateAttr); @@ -223,6 +224,40 @@ static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFst size_t payload = ffWifiNlAttrPayload(info); switch (type) { + case NL80211_RATE_INFO_40_MHZ_WIDTH: + width = 40; + break; + case NL80211_RATE_INFO_80_MHZ_WIDTH: + case NL80211_RATE_INFO_80P80_MHZ_WIDTH: + width = 80; + break; + case NL80211_RATE_INFO_160_MHZ_WIDTH: + width = 160; + break; + case 18 /* NL80211_RATE_INFO_320_MHZ_WIDTH */: + width = 320; + break; + case NL80211_RATE_INFO_10_MHZ_WIDTH: + width = 10; + break; + case NL80211_RATE_INFO_5_MHZ_WIDTH: + width = 5; + break; + case 25 /* NL80211_RATE_INFO_1_MHZ_WIDTH */: + width = 1; + break; + case 26 /* NL80211_RATE_INFO_2_MHZ_WIDTH */: + width = 2; + break; + case 27 /* NL80211_RATE_INFO_4_MHZ_WIDTH */: + width = 4; + break; + case 28 /* NL80211_RATE_INFO_8_MHZ_WIDTH */: + width = 8; + break; + case 29 /* NL80211_RATE_INFO_16_MHZ_WIDTH */: + width = 16; + break; case 30 /* NL80211_RATE_INFO_UHR_MCS */: ffStrbufSetStatic(protocol, "802.11bn (Wi-Fi 8)"); break; @@ -254,9 +289,126 @@ static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFst } } + if (rate != -DBL_MAX && *channelWidth == 0) { + *channelWidth = width; + } + return rate; } +static uint16_t ffWifiChannelWidthToMhz(uint32_t width) { + switch (width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + return 20; + case NL80211_CHAN_WIDTH_40: + return 40; + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + return 80; + case NL80211_CHAN_WIDTH_160: + return 160; + case NL80211_CHAN_WIDTH_5: + return 5; + case NL80211_CHAN_WIDTH_10: + return 10; + case NL80211_CHAN_WIDTH_1: + return 1; + case NL80211_CHAN_WIDTH_2: + return 2; + case NL80211_CHAN_WIDTH_4: + return 4; + case NL80211_CHAN_WIDTH_8: + return 8; + case NL80211_CHAN_WIDTH_16: + return 16; + case 13 /* NL80211_CHAN_WIDTH_320 */: + return 320; + default: + return 0; + } +} + +static bool ffWifiFetchInterfaceInfo(FFWifiNlContext* ctx, FFWifiResult* item, uint32_t ifIndex) { + struct { + struct nlmsghdr nlh; + struct genlmsghdr genl; + char attrs[32]; + } req = { + .nlh = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr)), + .nlmsg_type = ctx->nl80211FamilyId, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .nlmsg_seq = ++ctx->seq, + .nlmsg_pid = ctx->portId, + }, + .genl = { + .cmd = NL80211_CMD_GET_INTERFACE, + .version = 0, + }, + }; + + if (!ffWifiNlAppendAttr(&req.nlh, sizeof(req), NL80211_ATTR_IFINDEX, &ifIndex, sizeof(ifIndex))) { + FF_DEBUG("Failed to build nl80211 interface request"); + return false; + } + + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + }; + + ssize_t sent = sendto(ctx->sockFd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*) &addr, sizeof(addr)); + if (sent != (ssize_t) req.nlh.nlmsg_len) { + FF_DEBUG("Failed to send nl80211 interface request"); + return false; + } + + uint8_t buffer[8192]; + while (true) { + ssize_t received = recvfrom(ctx->sockFd, buffer, sizeof(buffer), 0, nullptr, nullptr); + if (received < 0) { + FF_DEBUG("Failed to receive nl80211 interface reply: %s", strerror(errno)); + return false; + } + + for (const struct nlmsghdr* nlh = (const struct nlmsghdr*) buffer; + NLMSG_OK(nlh, received); + nlh = NLMSG_NEXT(nlh, received)) { + if (nlh->nlmsg_seq != req.nlh.nlmsg_seq) { + continue; + } + + if (nlh->nlmsg_type == NLMSG_ERROR) { + const struct nlmsgerr* err = (const struct nlmsgerr*) NLMSG_DATA(nlh); + if (err->error != 0) { + FF_DEBUG("nl80211 interface request failed: %s", strerror(-err->error)); + } + return false; + } + + if (nlh->nlmsg_type != ctx->nl80211FamilyId) { + continue; + } + + const struct genlmsghdr* genl = (const struct genlmsghdr*) NLMSG_DATA(nlh); + size_t attrRemaining = nlh->nlmsg_len - NLMSG_HDRLEN - GENL_HDRLEN; + for (const struct nlattr* attr = (const struct nlattr*) ((const char*) genl + GENL_HDRLEN); + ffWifiNlAttrOk(attr, attrRemaining); + attr = ffWifiNlAttrNext(attr, &attrRemaining)) { + if ((attr->nla_type & NLA_TYPE_MASK) != NL80211_ATTR_CHANNEL_WIDTH || + ffWifiNlAttrPayload(attr) < sizeof(uint32_t)) { + continue; + } + + item->conn.channelWidth = ffWifiChannelWidthToMhz(*(const uint32_t*) ffWifiNlAttrData(attr)); + return item->conn.channelWidth != 0; + } + + return false; + } + } +} + static void ffWifiApplySecurityFlags(FFWifiResult* item, const FFWifiSecurityFlags* sec) { ffStrbufClear(&item->conn.security); @@ -566,13 +718,13 @@ static void ffWifiParseStationInfo(const struct nlattr* staInfoAttr, FFWifiResul if (type == NL80211_STA_INFO_SIGNAL && payload >= sizeof(uint8_t) && item->conn.signalQuality == -DBL_MAX) { int rssi = (int8_t) *(const uint8_t*) ffWifiNlAttrData(attr); item->conn.signalQuality = rssiToSignalQuality(rssi); - } else if (type == NL80211_STA_INFO_TX_BITRATE && item->conn.txRate == -DBL_MAX) { - double tx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol); + } else if (type == NL80211_STA_INFO_TX_BITRATE && (item->conn.txRate == -DBL_MAX || item->conn.channelWidth == 0)) { + double tx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol, &item->conn.channelWidth); if (tx != -DBL_MAX) { item->conn.txRate = tx; } - } else if (type == NL80211_STA_INFO_RX_BITRATE && item->conn.rxRate == -DBL_MAX) { - double rx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol); + } else if (type == NL80211_STA_INFO_RX_BITRATE && (item->conn.rxRate == -DBL_MAX || item->conn.channelWidth == 0)) { + double rx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol, &item->conn.channelWidth); if (rx != -DBL_MAX) { item->conn.rxRate = rx; } @@ -680,6 +832,7 @@ static const char* detectWithNetlink(FFWifiNlContext* ctx, FFWifiResult* item, u if (ffWifiFetchScanInfo(ctx, item, ifIndex)) { FF_DEBUG("found associated BSS: %s", item->conn.ssid.chars); ffStrbufSetStatic(&item->conn.status, "connected"); + ffWifiFetchInterfaceInfo(ctx, item, ifIndex); ffWifiFetchStationInfo(ctx, item, ifIndex); if (!item->conn.protocol.length && item->conn.txRate != -DBL_MAX) { FF_DEBUG("nl80211 station info did not include MCS family fields"); @@ -914,6 +1067,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -923,8 +1077,23 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; + { + ffStrbufSetF(&buffer, "/sys/class/net/%s/device/driver", i->if_name); + char pathBuf[PATH_MAX]; + ssize_t resultLength = readlink(buffer.chars, pathBuf, ARRAY_SIZE(pathBuf)); + if (resultLength > 0) { + const char* p = memrchr(pathBuf, '/', (size_t) resultLength); + if (p) { + ++p; + ffStrbufSetNS(&item->inf.driver, (uint32_t) (resultLength - (p - pathBuf)), p); + } + } + } + + char operstate; ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name); if (!ffReadFileData(buffer.chars, 1, &operstate)) { diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 8aad2884e..f96d58e0b 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -98,6 +98,7 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(item->inf.description, "inf-desc"), FF_ARG(item->inf.status, "inf-status"), + FF_ARG(item->inf.driver, "inf-driver"), FF_ARG(item->conn.status, "status"), FF_ARG(item->conn.ssid, "ssid"), FF_ARG(item->conn.bssid, "bssid"), @@ -108,6 +109,7 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_ARG(item->conn.security, "security"), FF_ARG(percentBar, "signal-quality-bar"), FF_ARG(item->conn.channel, "channel"), + FF_ARG(item->conn.channelWidth, "channel-width"), FF_ARG(bandStr, "band"), })); } @@ -116,6 +118,7 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); + ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -163,6 +166,7 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu yyjson_mut_val* inf = yyjson_mut_obj_add_obj(doc, obj, "inf"); yyjson_mut_obj_add_strbuf(doc, inf, "description", &wifi->inf.description); yyjson_mut_obj_add_strbuf(doc, inf, "status", &wifi->inf.status); + yyjson_mut_obj_add_strbuf(doc, inf, "driver", &wifi->inf.driver); yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn"); yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status); @@ -186,12 +190,14 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu yyjson_mut_obj_add_null(doc, conn, "txRate"); } yyjson_mut_obj_add_uint(doc, conn, "channel", wifi->conn.channel); + yyjson_mut_obj_add_uint(doc, conn, "channelWidth", wifi->conn.channelWidth); yyjson_mut_obj_add_uint(doc, conn, "frequency", wifi->conn.frequency); } FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); + ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -240,6 +246,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { { "Interface description", "inf-desc" }, { "Interface status", "inf-status" }, + { "Interface driver", "inf-driver" }, { "Connection status", "status" }, { "Connection SSID", "ssid" }, { "Connection BSSID", "bssid" }, @@ -250,6 +257,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { { "Connection Security algorithm", "security" }, { "Connection signal quality (percentage bar)", "signal-quality-bar" }, { "Connection channel number", "channel" }, + { "Connection channel width in MHz", "channel-width" }, { "Connection channel band in GHz", "band" }, })), .defaultOrder = 51, From 514efab8ebbc28467d2c8b0b9dd4a6e71b11de4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 18 Aug 2026 16:41:11 +0800 Subject: [PATCH 029/109] Wifi (Windows): adds channel width and device driver detection --- src/common/windows/nt.h | 2 +- src/detection/wifi/wifi_windows.c | 149 +++++++++++++++++++++++++----- 2 files changed, 126 insertions(+), 25 deletions(-) diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index 730a75ba8..4a61b8226 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -169,7 +169,7 @@ NTSTATUS NTAPI NtQuerySystemEnvironmentValueEx( ); NTSTATUS NTAPI RtlGUIDFromString(IN PCUNICODE_STRING GuidString, OUT GUID* Guid); -NTSTATUS NTAPI RtlStringFromGUIDEx(IN GUID* Guid, OUT PCUNICODE_STRING GuidString, _In_ BOOLEAN AllocateGuidString); +NTSTATUS NTAPI RtlStringFromGUIDEx(IN const GUID* Guid, OUT PUNICODE_STRING GuidString, IN BOOLEAN AllocateGuidString); typedef struct _SYSTEM_SECUREBOOT_INFORMATION { BOOLEAN SecureBootEnabled; diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 8e900ad42..51adcdc33 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -1,45 +1,118 @@ #include "wifi.h" #include "common/library.h" #include "common/windows/unicode.h" +#include "common/windows/registry.h" #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch" - static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result) { switch (state) { case wlan_interface_state_not_ready: - ffStrbufAppendS(result, "Not ready"); + ffStrbufSetStatic(result, "Not ready"); break; case wlan_interface_state_connected: - ffStrbufAppendS(result, "Connected"); + ffStrbufSetStatic(result, "Connected"); break; case wlan_interface_state_ad_hoc_network_formed: - ffStrbufAppendS(result, "Ad hoc network formed"); + ffStrbufSetStatic(result, "Ad hoc network formed"); break; case wlan_interface_state_disconnecting: - ffStrbufAppendS(result, "Disconnecting"); + ffStrbufSetStatic(result, "Disconnecting"); break; case wlan_interface_state_disconnected: - ffStrbufAppendS(result, "Disconnected"); + ffStrbufSetStatic(result, "Disconnected"); break; case wlan_interface_state_associating: - ffStrbufAppendS(result, "Associating"); + ffStrbufSetStatic(result, "Associating"); break; case wlan_interface_state_discovering: - ffStrbufAppendS(result, "Discovering"); + ffStrbufSetStatic(result, "Discovering"); break; case wlan_interface_state_authenticating: - ffStrbufAppendS(result, "Authenticating"); + ffStrbufSetStatic(result, "Authenticating"); break; default: - ffStrbufAppendS(result, "Unknown"); + ffStrbufSetStatic(result, "Unknown"); break; } } +typedef struct _WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO { + UCHAR ucLinkID; + ULONG ulChannelCenterFrequencyMhz; + ULONG ulBandwidth; + LONG lRssi; + WLAN_RATE_SET wlanRateSet; +} WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO, *PWLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO; + +typedef struct _WLAN_REALTIME_CONNECTION_QUALITY { + DOT11_PHY_TYPE dot11PhyType; + ULONG ulLinkQuality; + ULONG ulRxRate; + ULONG ulTxRate; + BOOL bIsMLOConnection; + ULONG ulNumLinks; + // Array of size ulNumLinks + WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO linksInfo[]; +} WLAN_REALTIME_CONNECTION_QUALITY, *PWLAN_REALTIME_CONNECTION_QUALITY; + +enum { wlan_intf_opcode_realtime_connection_quality = 19 }; + +#define WIFI_DRIVER_REG_PATH L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +static bool detectWifiDriver(const GUID* interfaceGuid, FFstrbuf* driver) { + char interfaceGuidA[64]; + snprintf(interfaceGuidA, sizeof(interfaceGuidA), + "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + (unsigned) interfaceGuid->Data1, + (unsigned) interfaceGuid->Data2, + (unsigned) interfaceGuid->Data3, + (unsigned) interfaceGuid->Data4[0], (unsigned) interfaceGuid->Data4[1], + (unsigned) interfaceGuid->Data4[2], (unsigned) interfaceGuid->Data4[3], + (unsigned) interfaceGuid->Data4[4], (unsigned) interfaceGuid->Data4[5], + (unsigned) interfaceGuid->Data4[6], (unsigned) interfaceGuid->Data4[7]); + + FF_AUTO_CLOSE_FD HANDLE hClassKey = nullptr; + if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, WIFI_DRIVER_REG_PATH, &hClassKey, nullptr)) { + return false; + } + + wchar_t subKeyW[16]; + + for (uint32_t i = 0;; ++i) { + _snwprintf(subKeyW, ARRAY_SIZE(subKeyW), L"%04u", i); + + FF_AUTO_CLOSE_FD HANDLE hDeviceKey = nullptr; + if (!ffRegOpenSubkeyForRead(hClassKey, subKeyW, &hDeviceKey, nullptr)) { + return false; + } + + FF_STRBUF_AUTO_DESTROY netCfgInstanceId = ffStrbufCreate(); + if (!ffRegReadStrbuf(hDeviceKey, L"NetCfgInstanceId", &netCfgInstanceId, nullptr)) { + continue; + } + + if (!ffStrbufEqualS(&netCfgInstanceId, interfaceGuidA)) { + continue; + } + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffRegReadStrbuf(hDeviceKey, L"ProviderName", &buffer, nullptr)) { + ffStrbufSet(driver, &buffer); + } + + if (ffRegReadStrbuf(hDeviceKey, L"DriverVersion", &buffer, nullptr)) { + if (driver->length) { + ffStrbufAppendC(driver, ' '); + } + ffStrbufAppend(driver, &buffer); + } + + return true; + } +} + const char* ffDetectWifi(FFlist* result) { FF_LIBRARY_LOAD_MESSAGE(wlanapi, "wlanapi" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle) @@ -54,7 +127,7 @@ const char* ffDetectWifi(FFlist* result) { WLAN_INTERFACE_INFO_LIST* ifList = nullptr; const char* error = nullptr; - if (ffWlanOpenHandle(2, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) { + if (ffWlanOpenHandle(2 /*maxClientVersion*/, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) { error = "WlanOpenHandle() failed"; goto exit; } @@ -70,6 +143,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitWS(&item->inf.description, ifInfo->strInterfaceDescription); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -79,8 +153,10 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; + detectWifiDriver(&ifInfo->InterfaceGuid, &item->inf.driver); convertIfStateToString(ifInfo->isState, &item->inf.status); if (ifInfo->isState != wlan_interface_state_connected) { @@ -200,17 +276,44 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufAppendS(&item->conn.security, "Insecure"); } - WLAN_BSS_LIST* bssList = nullptr; - if (ffWlanGetNetworkBssList(hClient, + WLAN_REALTIME_CONNECTION_QUALITY* connectionQuality = nullptr; + bufSize = 0; + if (ffWlanQueryInterface(hClient, &ifInfo->InterfaceGuid, - &connInfo->wlanAssociationAttributes.dot11Ssid, - connInfo->wlanAssociationAttributes.dot11BssType, - connInfo->wlanSecurityAttributes.bSecurityEnabled, + wlan_intf_opcode_realtime_connection_quality, nullptr, - &bssList) == ERROR_SUCCESS && - bssList->dwNumberOfItems > 0) { - item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000); - ffWlanFreeMemory(bssList); + &bufSize, + (PVOID*) &connectionQuality, + &opCode) == ERROR_SUCCESS) { + const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* bestLink = nullptr; + for (ULONG linkIndex = 0; linkIndex < connectionQuality->ulNumLinks; ++linkIndex) { + const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* link = &connectionQuality->linksInfo[linkIndex]; + if (!bestLink || link->lRssi > bestLink->lRssi) { + bestLink = link; + } + } + if (bestLink) { + item->conn.channelWidth = (uint16_t) bestLink->ulBandwidth; + item->conn.frequency = (uint16_t) bestLink->ulChannelCenterFrequencyMhz; + } + } + if (connectionQuality) { + ffWlanFreeMemory(connectionQuality); + } + + if (item->conn.frequency == 0) { + WLAN_BSS_LIST* bssList = nullptr; + if (ffWlanGetNetworkBssList(hClient, + &ifInfo->InterfaceGuid, + &connInfo->wlanAssociationAttributes.dot11Ssid, + connInfo->wlanAssociationAttributes.dot11BssType, + connInfo->wlanSecurityAttributes.bSecurityEnabled, + nullptr, + &bssList) == ERROR_SUCCESS && + bssList->dwNumberOfItems > 0) { + item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000); + ffWlanFreeMemory(bssList); + } } ffWlanFreeMemory(connInfo); @@ -238,5 +341,3 @@ exit: } return error; } - -#pragma GCC diagnostic pop From f04a53337de0b92276a45c0483386b3e93da2556 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 15:35:41 +0800 Subject: [PATCH 030/109] Wifi (macOS): adds channel width, accurate channel frequency and device driver detection --- src/detection/wifi/wifi_apple.m | 104 +++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index f718179bd..d84bd2a81 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -1,29 +1,32 @@ #include "wifi.h" #include "common/processing.h" #include "common/strutil.h" +#include "common/apple/cf_helpers.h" #import +#import +#import -static inline double rssiToSignalQuality(int rssi) -{ - return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2); +static inline double rssiToSignalQuality(int rssi) { + return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0 + : (rssi + 100) * 2); } -@interface CWNetworkProfile() -@property(readonly, retain, nullable) NSArray *bssidList; +@interface CWNetworkProfile () +@property (readonly, retain, nullable) NSArray* bssidList; @end -const char* ffDetectWifi(FFlist* result) -{ +const char* ffDetectWifi(FFlist* result) { NSArray* interfaces = CWWiFiClient.sharedWiFiClient.interfaces; - if (!interfaces) + if (!interfaces) { return "CWWiFiClient.sharedWiFiClient.interfaces is nil"; + } - for (CWInterface* inf in interfaces) - { + for (CWInterface* inf in interfaces) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -33,37 +36,69 @@ const char* ffDetectWifi(FFlist* result) item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; - ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String); + ffStrbufSetS(&item->inf.description, inf.interfaceName.UTF8String); ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off"); - if(!inf.powerOn) + + FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); + FF_IOOBJECT_AUTO_RELEASE io_object_t parentService = IO_OBJECT_NULL; + while (!IOObjectConformsTo(service, "IOUserNetworkWLAN")) { + if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { + IOObjectRelease(service); + service = parentService; + parentService = IO_OBJECT_NULL; + } else { + IOObjectRelease(service); + service = IO_OBJECT_NULL; + break; + } + } + + if (service != IO_OBJECT_NULL) { + if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { // AppleBCMWLANCore + FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions); // Chipsets other than Broadcom? + if (driverName) { + ffCfStrGetString(driverName, &item->inf.driver); + ffStrbufReplaceAllC(&item->inf.driver, '-', ' '); + } else { + driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions); + ffCfStrGetString(driverName, &item->inf.driver); + } + } + } + + if (!inf.powerOn) { continue; + } ffStrbufSetStatic(&item->conn.status, inf.interfaceMode != kCWInterfaceModeNone ? "Active" : "Inactive"); - if(inf.interfaceMode == kCWInterfaceModeNone) + if (inf.interfaceMode == kCWInterfaceModeNone) { continue; + } FF_STRBUF_AUTO_DESTROY ipconfig = ffStrbufCreate(); CWNetworkProfile* networkProfile = inf.configuration.networkProfiles.firstObject; - if (inf.ssid) // https://developer.apple.com/forums/thread/732431 + if (inf.ssid) { // https://developer.apple.com/forums/thread/732431 ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); - else if (networkProfile.ssid) + } else if (networkProfile.ssid) { ffStrbufSetStatic(&item->conn.ssid, inf.configuration.networkProfiles.firstObject.ssid.UTF8String); - else + } else { ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 + } - if (inf.bssid) + if (inf.bssid) { ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String); - else if (networkProfile.bssidList) + } else if (networkProfile.bssidList) { ffStrbufSetStatic(&item->conn.bssid, [networkProfile.bssidList.firstObject[@"BSSID"] UTF8String]); - else + } else { ffStrbufSetStatic(&item->conn.bssid, ""); + } - switch(inf.activePHYMode) - { + switch (inf.activePHYMode) { case kCWPHYModeNone: ffStrbufSetStatic(&item->conn.protocol, "none"); break; @@ -89,15 +124,15 @@ const char* ffDetectWifi(FFlist* result) ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: - if (inf.activePHYMode < 8) + if (inf.activePHYMode < 8) { ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode); + } break; } item->conn.signalQuality = rssiToSignalQuality((int) inf.rssiValue); item->conn.txRate = inf.transmitRate; - switch(inf.security) - { + switch (inf.security) { case kCWSecurityNone: ffStrbufSetStatic(&item->conn.security, "Insecure"); break; @@ -152,12 +187,21 @@ const char* ffDetectWifi(FFlist* result) } item->conn.channel = (uint16_t) inf.wlanChannel.channelNumber; - switch (inf.wlanChannel.channelBand) - { - case kCWChannelBand2GHz: item->conn.frequency = 2400; break; - case kCWChannelBand5GHz: item->conn.frequency = 5400; break; - case 3 /*kCWChannelBand6GHz*/: item->conn.frequency = 6400; break; - default: item->conn.frequency = 0; break; + switch (inf.wlanChannel.channelWidth) { + case kCWChannelWidth20MHz: item->conn.channelWidth = 20; break; + case kCWChannelWidth40MHz: item->conn.channelWidth = 40; break; + case kCWChannelWidth80MHz: item->conn.channelWidth = 80; break; + case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break; + default: item->conn.channelWidth = 0; break; + } + if (service != IO_OBJECT_NULL) { + FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions); + if (frequency) { + int64_t value; + if (ffCfNumGetInt64(frequency, &value) == nil) { + item->conn.frequency = (uint16_t) value; + } + } } } From 124bbb06f90d33188e3346a3c1d8cd189c899291 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 23:25:07 +0800 Subject: [PATCH 031/109] Wifi (macOS): fixes compatibility for old Intel MBP --- src/detection/wifi/wifi_apple.m | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index d84bd2a81..24ed6deba 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -44,7 +44,9 @@ const char* ffDetectWifi(FFlist* result) { FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); FF_IOOBJECT_AUTO_RELEASE io_object_t parentService = IO_OBJECT_NULL; - while (!IOObjectConformsTo(service, "IOUserNetworkWLAN")) { + FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency; + // Note: IO80211ChannelFrequency is only available when the interface is connected + while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) { if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { IOObjectRelease(service); service = parentService; @@ -58,12 +60,11 @@ const char* ffDetectWifi(FFlist* result) { if (service != IO_OBJECT_NULL) { if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { // AppleBCMWLANCore - FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions); // Chipsets other than Broadcom? - if (driverName) { + FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = nullptr; // Chipsets other than Broadcom? + if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions)) || (driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("IO80211Family.BuildTag"), nullptr, kNilOptions))) { ffCfStrGetString(driverName, &item->inf.driver); ffStrbufReplaceAllC(&item->inf.driver, '-', ' '); - } else { - driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions); + } else if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions))) { ffCfStrGetString(driverName, &item->inf.driver); } } @@ -194,13 +195,10 @@ const char* ffDetectWifi(FFlist* result) { case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break; default: item->conn.channelWidth = 0; break; } - if (service != IO_OBJECT_NULL) { - FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions); - if (frequency) { - int64_t value; - if (ffCfNumGetInt64(frequency, &value) == nil) { - item->conn.frequency = (uint16_t) value; - } + if (frequency) { + int64_t value; + if (ffCfNumGetInt64(frequency, &value) == nil) { + item->conn.frequency = (uint16_t) value; } } } From 54fe4ffece284613903a23400fcef57a6840f6d9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 09:32:27 +0800 Subject: [PATCH 032/109] Wifi (FreeBSD): adds channel width detection --- src/detection/wifi/wifi_bsd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index 7ef816ad5..ce634637e 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -27,6 +27,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); @@ -37,6 +38,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; char ssid[IEEE80211_NWID_LEN + 1] = {}; @@ -80,6 +82,16 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channel = curchan.ic_ieee; item->conn.frequency = curchan.ic_freq; + // Determine channel width from channel flags + if (curchan.ic_flags & IEEE80211_CHAN_VHT160) + item->conn.channelWidth = 160; + else if (curchan.ic_flags & IEEE80211_CHAN_VHT80) + item->conn.channelWidth = 80; + else if (curchan.ic_flags & IEEE80211_CHAN_HT40) + item->conn.channelWidth = 40; + else + item->conn.channelWidth = 20; + #ifdef IEEE80211_IS_CHAN_HE // for future use if (IEEE80211_IS_CHAN_HE(&curchan)) { ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); From 6d0d093d62d14e208f7df5918c55b29b549ddf95 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 10:15:30 +0800 Subject: [PATCH 033/109] Wifi (NetBSD): adds channel width detection --- src/detection/wifi/wifi_nbsd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/detection/wifi/wifi_nbsd.c b/src/detection/wifi/wifi_nbsd.c index ea8c2ace7..8265873ef 100644 --- a/src/detection/wifi/wifi_nbsd.c +++ b/src/detection/wifi/wifi_nbsd.c @@ -38,6 +38,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -47,6 +48,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; char ssid[IEEE80211_NWID_LEN + 1] = {}; @@ -91,6 +93,16 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq); item->conn.frequency = curchan.ic_freq; + // Determine channel width from channel flags + if (curchan.ic_flags & IEEE80211_CHAN_VHT160) + item->conn.channelWidth = 160; + else if (curchan.ic_flags & IEEE80211_CHAN_VHT80) + item->conn.channelWidth = 80; + else if (curchan.ic_flags & IEEE80211_CHAN_HT40) + item->conn.channelWidth = 40; + else + item->conn.channelWidth = 20; + #ifdef IEEE80211_IS_CHAN_HE // for future use if (IEEE80211_IS_CHAN_HE(&curchan)) { ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); From 93566cb73c9d8507d7379fde490d609dd323015a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 10:16:30 +0800 Subject: [PATCH 034/109] Wifi (Android / OpenBSD): inits unsupported properties --- src/detection/wifi/wifi_android.c | 2 ++ src/detection/wifi/wifi_obsd.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index 4fbc4afb2..12f7ac747 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -33,6 +33,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -42,6 +43,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; ffStrbufAppendJsonVal(&item->inf.status, yyjson_obj_get(root, "supplicant_state")); diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index bcaec97fd..18e46566f 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -28,6 +28,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -37,6 +38,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; struct ieee80211_nodereq nr = {}; From f0765b1a132a4e6a768f1c2abcf3a24f888f02e0 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 10:34:01 +0800 Subject: [PATCH 035/109] Wifi (SunOS): adds basic Wifi detection impl --- CMakeLists.txt | 2 +- src/detection/wifi/wifi_sunos.c | 210 ++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/detection/wifi/wifi_sunos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 13a6fa83a..52d42dde0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1235,7 +1235,7 @@ elseif(SunOS) src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c - src/detection/wifi/wifi_nosupport.c + src/detection/wifi/wifi_sunos.c src/detection/wm/wm_nosupport.c src/detection/de/de_linux.c src/detection/wmtheme/wmtheme_linux.c diff --git a/src/detection/wifi/wifi_sunos.c b/src/detection/wifi/wifi_sunos.c new file mode 100644 index 000000000..bf0cca369 --- /dev/null +++ b/src/detection/wifi/wifi_sunos.c @@ -0,0 +1,210 @@ +#include "wifi.h" +#include "common/io.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include +#include + +#include + +static bool getWifiParam(int fd, uint32_t id, size_t minLength, wldp_t* buffer) { + memset(buffer, 0, MAX_BUF_LEN); + buffer->wldp_type = NET_802_11; + buffer->wldp_id = id; + + struct strioctl request = { + .ic_cmd = WLAN_GET_PARAM, + .ic_timout = 0, + .ic_len = MAX_BUF_LEN, + .ic_dp = (char*) buffer, + }; + + return ioctl(fd, I_STR, &request) == 0 + && buffer->wldp_result == WL_SUCCESS + && buffer->wldp_length >= WIFI_BUF_OFFSET + minLength + && buffer->wldp_length <= MAX_BUF_LEN; +} + +static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wldp_t* buffer) { + if (!getWifiParam(fd, id, valueSize, buffer)) { + return false; + } + + memcpy(value, buffer->wldp_buf, valueSize); + return true; +} + +static void initWifiResult(FFWifiResult* item, const char* name) { + ffStrbufInitS(&item->inf.description, name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; +} + +static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) { + switch (subtype) { + case WL_FHSS: ffStrbufSetStatic(protocol, "802.11 (FHSS)"); break; + case WL_DSSS: ffStrbufSetStatic(protocol, "802.11 (DSSS)"); break; + case WL_IRBASE: ffStrbufSetStatic(protocol, "802.11 (IR)"); break; + case WL_OFDM: ffStrbufSetStatic(protocol, "802.11a"); break; + case WL_HRDS: ffStrbufSetStatic(protocol, "802.11b"); break; + case WL_ERP: ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g"); break; + default: break; + } +} + +static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAuthMode, uint32_t authMode) { + switch (encryption) { + case WL_NOENCRYPTION: + ffStrbufSetStatic(security, "Insecure"); + break; + case WL_ENC_WEP: + ffStrbufSetStatic(security, "WEP"); + break; + case WL_ENC_WPA: + ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA"); + break; + default: + break; + } +} + +const char* ffDetectWifi(FFlist* result) { + FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); + if (!directory) { + return nullptr; + } + + FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN); + if (!bufferMemory) { + return "malloc() failed"; + } + wldp_t* buffer = (wldp_t*) bufferMemory; + + struct dirent* entry; + while ((entry = readdir(directory)) != nullptr) { + size_t nameLength = strlen(entry->d_name); + if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') { + continue; + } + + char devicePath[PATH_MAX]; + int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name); + if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) { + continue; + } + + FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); + if (fd < 0) { + continue; + } + + FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); + initWifiResult(item, entry->d_name); + + wl_vendor_t vendor = {}; + wl_product_t product = {}; + if (getWifiParam(fd, WL_VENDOR_ID, sizeof(vendor), buffer)) { + memcpy(vendor, buffer->wldp_buf, sizeof(vendor)); + vendor[sizeof(vendor) - 1] = '\0'; + } + if (getWifiParam(fd, WL_PRODUCT_ID, sizeof(product), buffer)) { + memcpy(product, buffer->wldp_buf, sizeof(product)); + product[sizeof(product) - 1] = '\0'; + } + if (vendor[0]) { + ffStrbufSetS(&item->inf.driver, vendor); + } + if (product[0]) { + if (item->inf.driver.length) { + ffStrbufAppendC(&item->inf.driver, ' '); + } + ffStrbufAppendS(&item->inf.driver, product); + } + + wl_radio_t radio; + if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { + ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down"); + } else { + ffStrbufSetStatic(&item->inf.status, "Unknown"); + } + + wl_linkstatus_t linkStatus; + if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) { + ffStrbufSetStatic(&item->conn.status, "Unknown"); + continue; + } + if (linkStatus != WL_CONNECTED) { + ffStrbufSetStatic(&item->conn.status, "Not connected"); + continue; + } + ffStrbufSetStatic(&item->conn.status, "Connected"); + + wl_essid_t essid; + if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) + && essid.wl_essid_length < sizeof(essid.wl_essid_essid) + && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { + ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); + } + + wl_bssid_t bssid; + if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + + wl_rssi_t rssi; + if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) { + item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0; + } + + wl_phy_conf_t phy; + if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) { + uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype; + switch (subtype) { + case WL_FHSS: + item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_DSSS: + item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_OFDM: + item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency; + item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled); + break; + case WL_ERP: + item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel; + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled); + break; + default: + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + } + } + + wl_encryption_t encryption; + wl_authmode_t authMode; + bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer); + bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer); + if (haveEncryption) { + setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode); + } + } + + return nullptr; +} From db8ee8159d775f750661e67d25c7d2ad9016a879 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 11:05:35 +0800 Subject: [PATCH 036/109] Wifi (Haiku): adds basic Wifi detection impl --- CMakeLists.txt | 2 +- src/detection/wifi/wifi_haiku.cpp | 102 ++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/detection/wifi/wifi_haiku.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 52d42dde0..9f6b0629f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1305,7 +1305,7 @@ elseif(Haiku) src/detection/uptime/uptime_haiku.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_haiku.cpp - src/detection/wifi/wifi_nosupport.c + src/detection/wifi/wifi_haiku.cpp src/detection/wm/wm_nosupport.c src/detection/de/de_nosupport.c src/detection/wmtheme/wmtheme_haiku.cpp diff --git a/src/detection/wifi/wifi_haiku.cpp b/src/detection/wifi/wifi_haiku.cpp new file mode 100644 index 000000000..c5669caa5 --- /dev/null +++ b/src/detection/wifi/wifi_haiku.cpp @@ -0,0 +1,102 @@ +extern "C" { + #include "wifi.h" +} + +#include +#include +#include + +static void initWifiResult(FFWifiResult* item, const char* name) { + ffStrbufInitS(&item->inf.description, name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; +} + +static void setWifiSecurity(FFstrbuf* security, const wireless_network& network) { + switch (network.authentication_mode) { + case B_NETWORK_AUTHENTICATION_NONE: + if (network.flags & B_NETWORK_IS_ENCRYPTED) { + ffStrbufSetStatic(security, "Encrypted"); + } else { + ffStrbufSetStatic(security, "Insecure"); + } + break; + case B_NETWORK_AUTHENTICATION_WEP: + ffStrbufSetStatic(security, "WEP"); + break; + case B_NETWORK_AUTHENTICATION_WPA: + ffStrbufSetStatic(security, "WPA"); + break; + case B_NETWORK_AUTHENTICATION_WPA2: + ffStrbufSetStatic(security, "WPA2"); + break; + case B_NETWORK_AUTHENTICATION_EAP: + ffStrbufSetStatic(security, "WPA Enterprise"); + break; + default: + ffStrbufSetF(security, "Unknown (%lu)", (unsigned long) network.authentication_mode); + break; + } +} + +static void setWifiBssid(FFstrbuf* bssid, const wireless_network& network) { + const uint8* address = network.address.LinkLevelAddress(); + if (address == nullptr || network.address.LinkLevelAddressLength() < 6) { + return; + } + + ffStrbufSetF(bssid, "%02X:%02X:%02X:%02X:%02X:%02X", + address[0], address[1], address[2], address[3], address[4], address[5]); +} + +const char* ffDetectWifi(FFlist* result) { + BNetworkRoster& roster = BNetworkRoster::Default(); + BNetworkInterface interface; + uint32 cookie = 0; + + while (roster.GetNextInterface(&cookie, interface) == B_OK) { + if (!interface.Exists()) { + continue; + } + + BNetworkDevice device(interface.Name()); + if (!device.Exists() || !device.IsWireless()) { + continue; + } + + FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); + initWifiResult(item, interface.Name()); + + ffStrbufSetStatic(&item->inf.status, interface.HasLink() ? "Up" : "Down"); + if (!interface.HasLink() || !device.HasLink()) { + ffStrbufSetStatic(&item->conn.status, "Not connected"); + continue; + } + + ffStrbufSetStatic(&item->conn.status, "Connected"); + + uint32 networkCookie = 0; + wireless_network network = {}; + if (device.GetNextAssociatedNetwork(networkCookie, network) != B_OK) { + continue; + } + + ffStrbufSetNS(&item->conn.ssid, strnlen(network.name, sizeof(network.name)), network.name); + setWifiBssid(&item->conn.bssid, network); + item->conn.signalQuality = network.signal_strength > 100 ? 100 : network.signal_strength; + setWifiSecurity(&item->conn.security, network); + } + + return nullptr; +} From cafe82b462ad13aff25a7b19f82c6f1ac56f838e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 13:24:05 +0800 Subject: [PATCH 037/109] Battery (SunOS): adds basic detection impl --- CMakeLists.txt | 2 +- src/detection/battery/battery_sunos.c | 113 ++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/detection/battery/battery_sunos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f6b0629f..9d4070af9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1169,7 +1169,7 @@ elseif(SunOS) src/common/impl/FFPlatform_unix.c src/common/impl/binary_linux.c src/common/impl/kmod_sunos.c - src/detection/battery/battery_nosupport.c + src/detection/battery/battery_sunos.c src/detection/bios/bios_windows.c src/detection/board/board_windows.c src/detection/bootmgr/bootmgr_nosupport.c diff --git a/src/detection/battery/battery_sunos.c b/src/detection/battery/battery_sunos.c new file mode 100644 index 000000000..e31b7bb9f --- /dev/null +++ b/src/detection/battery/battery_sunos.c @@ -0,0 +1,113 @@ +#include "battery.h" + +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) { + assert(pkc); + if (*pkc) { + kstat_close(*pkc); + } +} + +static bool getUint32(kstat_t* ksp, const char* name, uint32_t* value) { + kstat_named_t* stat = kstat_data_lookup(ksp, name); + if (!stat) { + return false; + } + + switch (stat->data_type) { + case KSTAT_DATA_UINT32: + *value = stat->value.ui32; + return true; + case KSTAT_DATA_INT32: + if (stat->value.i32 >= 0) { + *value = (uint32_t) stat->value.i32; + return true; + } + break; +#ifdef _INT64_TYPE + case KSTAT_DATA_UINT64: + if (stat->value.ui64 <= UINT32_MAX) { + *value = (uint32_t) stat->value.ui64; + return true; + } + break; + case KSTAT_DATA_INT64: + if (stat->value.i64 >= 0 && (uint64_t) stat->value.i64 <= UINT32_MAX) { + *value = (uint32_t) stat->value.i64; + return true; + } + break; +#endif + default: + break; + } + + return false; +} + +const char* ffDetectBattery([[maybe_unused]] FFBatteryOptions* options, FFlist* results) { + // https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/powertop/common/battery.c + [[gnu::cleanup(kstatFreeWrap)]] kstat_ctl_t* kc = kstat_open(); + if (!kc) { + return "kstat_open() failed"; + } + + // illumos exposes battery information through either of these modules. + const char* modules[] = { "battery", "acpi_drv" }; + kstat_t* bif = nullptr; + kstat_t* bst = nullptr; + for (size_t i = 0; i < ARRAY_SIZE(modules); ++i) { + bif = kstat_lookup(kc, modules[i], 0, "battery BIF0"); + bst = kstat_lookup(kc, modules[i], 0, "battery BST0"); + if (bif && bst) { + break; + } + bif = nullptr; + bst = nullptr; + } + + if (!bif || !bst || kstat_read(kc, bif, nullptr) < 0 || kstat_read(kc, bst, nullptr) < 0) { + return nullptr; + } + + uint32_t lastCapacity, remainingCapacity, rate, state; + if (!getUint32(bif, "bif_last_cap", &lastCapacity) || + !getUint32(bst, "bst_rem_cap", &remainingCapacity) || + !getUint32(bst, "bst_state", &state)) { + return "kstat_data_lookup() failed"; + } + + if (lastCapacity == 0 || remainingCapacity == UINT32_MAX) { + return nullptr; + } + + FFBatteryResult* battery = FF_LIST_ADD(FFBatteryResult, *results); + ffStrbufInit(&battery->manufacturer); + ffStrbufInit(&battery->manufactureDate); + ffStrbufInit(&battery->modelName); + ffStrbufInit(&battery->technology); + ffStrbufInit(&battery->serial); + battery->status = FF_BATTERY_STATUS_NONE; + battery->capacity = (double) remainingCapacity * 100.0 / (double) lastCapacity; + battery->temperature = FF_BATTERY_TEMP_UNSET; + battery->cycleCount = 0; + battery->timeRemaining = -1; + + // illumos BST state: bit 0 discharging, bit 1 charging, bit 2 critical. + if (state & (1u << 0)) { + battery->status |= FF_BATTERY_STATUS_DISCHARGING; + } + if (state & (1u << 1)) { + battery->status |= FF_BATTERY_STATUS_CHARGING; + } + if (state & (1u << 2)) { + battery->status |= FF_BATTERY_STATUS_CRITICAL; + } + + if ((state & (1u << 0)) && getUint32(bst, "bst_rate", &rate) && rate > 0 && rate != UINT32_MAX) { + battery->timeRemaining = (int32_t) (((uint64_t) remainingCapacity * 3600) / rate); + } + + return nullptr; +} From 2a269bfd4c1807f51df7c193f61ce95d37249060 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 16:10:11 +0800 Subject: [PATCH 038/109] Wifi: removes driver detection support --- src/detection/wifi/wifi.h | 1 - src/detection/wifi/wifi_android.c | 1 - src/detection/wifi/wifi_apple.m | 44 ++-- src/detection/wifi/wifi_bsd.c | 1 - src/detection/wifi/wifi_haiku.cpp | 3 +- src/detection/wifi/wifi_linux.c | 15 -- src/detection/wifi/wifi_nbsd.c | 1 - src/detection/wifi/wifi_obsd.c | 1 - src/detection/wifi/wifi_sunos.c | 324 ++++++++++++++---------------- src/detection/wifi/wifi_windows.c | 57 ------ src/modules/wifi/wifi.c | 5 - 11 files changed, 170 insertions(+), 283 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index 7ad22855d..a7ea62d48 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -6,7 +6,6 @@ struct FFWifiInterface { FFstrbuf description; FFstrbuf status; - FFstrbuf driver; }; struct FFWifiConnection { diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index 12f7ac747..0fd5b3a9d 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -33,7 +33,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 24ed6deba..3807ef0e8 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -26,7 +26,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -42,34 +41,6 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufSetS(&item->inf.description, inf.interfaceName.UTF8String); ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off"); - FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); - FF_IOOBJECT_AUTO_RELEASE io_object_t parentService = IO_OBJECT_NULL; - FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency; - // Note: IO80211ChannelFrequency is only available when the interface is connected - while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) { - if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { - IOObjectRelease(service); - service = parentService; - parentService = IO_OBJECT_NULL; - } else { - IOObjectRelease(service); - service = IO_OBJECT_NULL; - break; - } - } - - if (service != IO_OBJECT_NULL) { - if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { // AppleBCMWLANCore - FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = nullptr; // Chipsets other than Broadcom? - if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions)) || (driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("IO80211Family.BuildTag"), nullptr, kNilOptions))) { - ffCfStrGetString(driverName, &item->inf.driver); - ffStrbufReplaceAllC(&item->inf.driver, '-', ' '); - } else if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions))) { - ffCfStrGetString(driverName, &item->inf.driver); - } - } - } - if (!inf.powerOn) { continue; } @@ -195,6 +166,21 @@ const char* ffDetectWifi(FFlist* result) { case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break; default: item->conn.channelWidth = 0; break; } + + FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); + FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency; + // Note: IO80211ChannelFrequency is only available when the interface is connected + while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) { + io_object_t parentService = IO_OBJECT_NULL; + if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { + IOObjectRelease(service); + service = parentService; + } else { + IOObjectRelease(service); + service = IO_OBJECT_NULL; + break; + } + } if (frequency) { int64_t value; if (ffCfNumGetInt64(frequency, &value) == nil) { diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index ce634637e..4b55d0257 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -27,7 +27,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); diff --git a/src/detection/wifi/wifi_haiku.cpp b/src/detection/wifi/wifi_haiku.cpp index c5669caa5..309cfcd5a 100644 --- a/src/detection/wifi/wifi_haiku.cpp +++ b/src/detection/wifi/wifi_haiku.cpp @@ -9,7 +9,6 @@ extern "C" { static void initWifiResult(FFWifiResult* item, const char* name) { ffStrbufInitS(&item->inf.description, name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -92,7 +91,7 @@ const char* ffDetectWifi(FFlist* result) { continue; } - ffStrbufSetNS(&item->conn.ssid, strnlen(network.name, sizeof(network.name)), network.name); + ffStrbufSetNS(&item->conn.ssid, (uint32_t) strnlen(network.name, sizeof(network.name)), network.name); setWifiBssid(&item->conn.bssid, network); item->conn.signalQuality = network.signal_strength > 100 ? 100 : network.signal_strength; setWifiSecurity(&item->conn.security, network); diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 1fe21b0c4..87e8e7378 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1067,7 +1067,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -1080,20 +1079,6 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channelWidth = 0; item->conn.frequency = 0; - { - ffStrbufSetF(&buffer, "/sys/class/net/%s/device/driver", i->if_name); - char pathBuf[PATH_MAX]; - ssize_t resultLength = readlink(buffer.chars, pathBuf, ARRAY_SIZE(pathBuf)); - if (resultLength > 0) { - const char* p = memrchr(pathBuf, '/', (size_t) resultLength); - if (p) { - ++p; - ffStrbufSetNS(&item->inf.driver, (uint32_t) (resultLength - (p - pathBuf)), p); - } - } - } - - char operstate; ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name); if (!ffReadFileData(buffer.chars, 1, &operstate)) { diff --git a/src/detection/wifi/wifi_nbsd.c b/src/detection/wifi/wifi_nbsd.c index 8265873ef..e2b083679 100644 --- a/src/detection/wifi/wifi_nbsd.c +++ b/src/detection/wifi/wifi_nbsd.c @@ -38,7 +38,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index 18e46566f..6def7b63b 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -28,7 +28,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); diff --git a/src/detection/wifi/wifi_sunos.c b/src/detection/wifi/wifi_sunos.c index bf0cca369..ad58f1922 100644 --- a/src/detection/wifi/wifi_sunos.c +++ b/src/detection/wifi/wifi_sunos.c @@ -10,201 +10,185 @@ #include -static bool getWifiParam(int fd, uint32_t id, size_t minLength, wldp_t* buffer) { - memset(buffer, 0, MAX_BUF_LEN); - buffer->wldp_type = NET_802_11; - buffer->wldp_id = id; - - struct strioctl request = { - .ic_cmd = WLAN_GET_PARAM, - .ic_timout = 0, - .ic_len = MAX_BUF_LEN, - .ic_dp = (char*) buffer, - }; - - return ioctl(fd, I_STR, &request) == 0 - && buffer->wldp_result == WL_SUCCESS - && buffer->wldp_length >= WIFI_BUF_OFFSET + minLength - && buffer->wldp_length <= MAX_BUF_LEN; -} - static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wldp_t* buffer) { - if (!getWifiParam(fd, id, valueSize, buffer)) { - return false; - } + memset(buffer, 0, MAX_BUF_LEN); + buffer->wldp_type = NET_802_11; + buffer->wldp_id = id; - memcpy(value, buffer->wldp_buf, valueSize); - return true; + struct strioctl request = { + .ic_cmd = WLAN_GET_PARAM, + .ic_timout = 0, + .ic_len = MAX_BUF_LEN, + .ic_dp = (char*) buffer, + }; + + if (ioctl(fd, I_STR, &request) != 0 || buffer->wldp_result != WL_SUCCESS || buffer->wldp_length < WIFI_BUF_OFFSET + valueSize || buffer->wldp_length > MAX_BUF_LEN) { + return false; + } + + memcpy(value, buffer->wldp_buf, valueSize); + return true; } static void initWifiResult(FFWifiResult* item, const char* name) { - ffStrbufInitS(&item->inf.description, name); - ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); - ffStrbufInit(&item->conn.status); - ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.bssid); - ffStrbufInit(&item->conn.protocol); - ffStrbufInit(&item->conn.security); - item->conn.signalQuality = -DBL_MAX; - item->conn.rxRate = -DBL_MAX; - item->conn.txRate = -DBL_MAX; - item->conn.channel = 0; - item->conn.channelWidth = 0; - item->conn.frequency = 0; + ffStrbufInitS(&item->inf.description, name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; } static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) { - switch (subtype) { - case WL_FHSS: ffStrbufSetStatic(protocol, "802.11 (FHSS)"); break; - case WL_DSSS: ffStrbufSetStatic(protocol, "802.11 (DSSS)"); break; - case WL_IRBASE: ffStrbufSetStatic(protocol, "802.11 (IR)"); break; - case WL_OFDM: ffStrbufSetStatic(protocol, "802.11a"); break; - case WL_HRDS: ffStrbufSetStatic(protocol, "802.11b"); break; - case WL_ERP: ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g"); break; - default: break; - } + switch (subtype) { + case WL_FHSS: + ffStrbufSetStatic(protocol, "802.11 (FHSS)"); + break; + case WL_DSSS: + ffStrbufSetStatic(protocol, "802.11 (DSSS)"); + break; + case WL_IRBASE: + ffStrbufSetStatic(protocol, "802.11 (IR)"); + break; + case WL_OFDM: + ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11a"); + break; + case WL_HRDS: + ffStrbufSetStatic(protocol, "802.11b"); + break; + case WL_ERP: + ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g"); + break; + default: + break; + } } static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAuthMode, uint32_t authMode) { - switch (encryption) { - case WL_NOENCRYPTION: - ffStrbufSetStatic(security, "Insecure"); - break; - case WL_ENC_WEP: - ffStrbufSetStatic(security, "WEP"); - break; - case WL_ENC_WPA: - ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA"); - break; - default: - break; - } + switch (encryption) { + case WL_NOENCRYPTION: + ffStrbufSetStatic(security, "Insecure"); + break; + case WL_ENC_WEP: + ffStrbufSetStatic(security, "WEP"); + break; + case WL_ENC_WPA: + ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA"); + break; + default: + ffStrbufSetStatic(security, "Unknown"); + break; + } } const char* ffDetectWifi(FFlist* result) { - FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); - if (!directory) { - return nullptr; - } + FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); + if (!directory) { + return nullptr; + } - FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN); - if (!bufferMemory) { - return "malloc() failed"; - } - wldp_t* buffer = (wldp_t*) bufferMemory; + FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN); + if (!bufferMemory) { + return "malloc() failed"; + } + wldp_t* buffer = (wldp_t*) bufferMemory; - struct dirent* entry; - while ((entry = readdir(directory)) != nullptr) { - size_t nameLength = strlen(entry->d_name); - if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') { - continue; - } + struct dirent* entry; + while ((entry = readdir(directory)) != nullptr) { + size_t nameLength = strlen(entry->d_name); + if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') { + continue; + } - char devicePath[PATH_MAX]; - int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name); - if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) { - continue; - } + char devicePath[PATH_MAX]; + int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name); + if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) { + continue; + } - FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); - if (fd < 0) { - continue; - } + FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); + if (fd < 0) { + continue; + } - FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); - initWifiResult(item, entry->d_name); + FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); + initWifiResult(item, entry->d_name); - wl_vendor_t vendor = {}; - wl_product_t product = {}; - if (getWifiParam(fd, WL_VENDOR_ID, sizeof(vendor), buffer)) { - memcpy(vendor, buffer->wldp_buf, sizeof(vendor)); - vendor[sizeof(vendor) - 1] = '\0'; - } - if (getWifiParam(fd, WL_PRODUCT_ID, sizeof(product), buffer)) { - memcpy(product, buffer->wldp_buf, sizeof(product)); - product[sizeof(product) - 1] = '\0'; - } - if (vendor[0]) { - ffStrbufSetS(&item->inf.driver, vendor); - } - if (product[0]) { - if (item->inf.driver.length) { - ffStrbufAppendC(&item->inf.driver, ' '); - } - ffStrbufAppendS(&item->inf.driver, product); - } + wl_radio_t radio; + if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { + ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down"); + } else { + ffStrbufSetStatic(&item->inf.status, "Unknown"); + } - wl_radio_t radio; - if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { - ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down"); - } else { - ffStrbufSetStatic(&item->inf.status, "Unknown"); - } + wl_linkstatus_t linkStatus; + if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) { + ffStrbufSetStatic(&item->conn.status, "Unknown"); + continue; + } + if (linkStatus != WL_CONNECTED) { + ffStrbufSetStatic(&item->conn.status, "Not connected"); + continue; + } + ffStrbufSetStatic(&item->conn.status, "Connected"); - wl_linkstatus_t linkStatus; - if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) { - ffStrbufSetStatic(&item->conn.status, "Unknown"); - continue; - } - if (linkStatus != WL_CONNECTED) { - ffStrbufSetStatic(&item->conn.status, "Not connected"); - continue; - } - ffStrbufSetStatic(&item->conn.status, "Connected"); + wl_essid_t essid; + if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { + ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); + } - wl_essid_t essid; - if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) - && essid.wl_essid_length < sizeof(essid.wl_essid_essid) - && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { - ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); - } + wl_bssid_t bssid; + if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } - wl_bssid_t bssid; - if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { - ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); - } + wl_rssi_t rssi; + if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) { + item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0; + } - wl_rssi_t rssi; - if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) { - item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0; - } + wl_phy_conf_t phy; + if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) { + uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype; + switch (subtype) { + case WL_FHSS: + item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_DSSS: + item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_OFDM: + item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency; + item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled); + break; + case WL_ERP: + item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel; + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled); + break; + default: + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + } + } - wl_phy_conf_t phy; - if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) { - uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype; - switch (subtype) { - case WL_FHSS: - item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel; - setWifiProtocol(&item->conn.protocol, subtype, false); - break; - case WL_DSSS: - item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel; - setWifiProtocol(&item->conn.protocol, subtype, false); - break; - case WL_OFDM: - item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency; - item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); - setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled); - break; - case WL_ERP: - item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel; - setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled); - break; - default: - setWifiProtocol(&item->conn.protocol, subtype, false); - break; - } - } + wl_encryption_t encryption; + wl_authmode_t authMode; + bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer); + bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer); + if (haveEncryption) { + setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode); + } + } - wl_encryption_t encryption; - wl_authmode_t authMode; - bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer); - bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer); - if (haveEncryption) { - setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode); - } - } - - return nullptr; + return nullptr; } diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 51adcdc33..838295484 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -1,7 +1,6 @@ #include "wifi.h" #include "common/library.h" #include "common/windows/unicode.h" -#include "common/windows/registry.h" #include #include @@ -59,60 +58,6 @@ typedef struct _WLAN_REALTIME_CONNECTION_QUALITY { enum { wlan_intf_opcode_realtime_connection_quality = 19 }; -#define WIFI_DRIVER_REG_PATH L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" - -static bool detectWifiDriver(const GUID* interfaceGuid, FFstrbuf* driver) { - char interfaceGuidA[64]; - snprintf(interfaceGuidA, sizeof(interfaceGuidA), - "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - (unsigned) interfaceGuid->Data1, - (unsigned) interfaceGuid->Data2, - (unsigned) interfaceGuid->Data3, - (unsigned) interfaceGuid->Data4[0], (unsigned) interfaceGuid->Data4[1], - (unsigned) interfaceGuid->Data4[2], (unsigned) interfaceGuid->Data4[3], - (unsigned) interfaceGuid->Data4[4], (unsigned) interfaceGuid->Data4[5], - (unsigned) interfaceGuid->Data4[6], (unsigned) interfaceGuid->Data4[7]); - - FF_AUTO_CLOSE_FD HANDLE hClassKey = nullptr; - if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, WIFI_DRIVER_REG_PATH, &hClassKey, nullptr)) { - return false; - } - - wchar_t subKeyW[16]; - - for (uint32_t i = 0;; ++i) { - _snwprintf(subKeyW, ARRAY_SIZE(subKeyW), L"%04u", i); - - FF_AUTO_CLOSE_FD HANDLE hDeviceKey = nullptr; - if (!ffRegOpenSubkeyForRead(hClassKey, subKeyW, &hDeviceKey, nullptr)) { - return false; - } - - FF_STRBUF_AUTO_DESTROY netCfgInstanceId = ffStrbufCreate(); - if (!ffRegReadStrbuf(hDeviceKey, L"NetCfgInstanceId", &netCfgInstanceId, nullptr)) { - continue; - } - - if (!ffStrbufEqualS(&netCfgInstanceId, interfaceGuidA)) { - continue; - } - - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - if (ffRegReadStrbuf(hDeviceKey, L"ProviderName", &buffer, nullptr)) { - ffStrbufSet(driver, &buffer); - } - - if (ffRegReadStrbuf(hDeviceKey, L"DriverVersion", &buffer, nullptr)) { - if (driver->length) { - ffStrbufAppendC(driver, ' '); - } - ffStrbufAppend(driver, &buffer); - } - - return true; - } -} - const char* ffDetectWifi(FFlist* result) { FF_LIBRARY_LOAD_MESSAGE(wlanapi, "wlanapi" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle) @@ -143,7 +88,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitWS(&item->inf.description, ifInfo->strInterfaceDescription); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -156,7 +100,6 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channelWidth = 0; item->conn.frequency = 0; - detectWifiDriver(&ifInfo->InterfaceGuid, &item->inf.driver); convertIfStateToString(ifInfo->isState, &item->inf.status); if (ifInfo->isState != wlan_interface_state_connected) { diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index f96d58e0b..a9462418d 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -98,7 +98,6 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(item->inf.description, "inf-desc"), FF_ARG(item->inf.status, "inf-status"), - FF_ARG(item->inf.driver, "inf-driver"), FF_ARG(item->conn.status, "status"), FF_ARG(item->conn.ssid, "ssid"), FF_ARG(item->conn.bssid, "bssid"), @@ -118,7 +117,6 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); - ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -166,7 +164,6 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu yyjson_mut_val* inf = yyjson_mut_obj_add_obj(doc, obj, "inf"); yyjson_mut_obj_add_strbuf(doc, inf, "description", &wifi->inf.description); yyjson_mut_obj_add_strbuf(doc, inf, "status", &wifi->inf.status); - yyjson_mut_obj_add_strbuf(doc, inf, "driver", &wifi->inf.driver); yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn"); yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status); @@ -197,7 +194,6 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); - ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -246,7 +242,6 @@ FFModuleBaseInfo ffWifiModuleInfo = { .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { { "Interface description", "inf-desc" }, { "Interface status", "inf-status" }, - { "Interface driver", "inf-driver" }, { "Connection status", "status" }, { "Connection SSID", "ssid" }, { "Connection BSSID", "bssid" }, From d8452f71ede84613a839193dfb9c87bdac1a41ef Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 15:03:56 +0800 Subject: [PATCH 039/109] Wifi (SunOS): fortifies code --- src/detection/wifi/wifi_sunos.c | 41 +++++++++++++++++---------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/detection/wifi/wifi_sunos.c b/src/detection/wifi/wifi_sunos.c index ad58f1922..0b2e24ae2 100644 --- a/src/detection/wifi/wifi_sunos.c +++ b/src/detection/wifi/wifi_sunos.c @@ -30,22 +30,6 @@ static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wld return true; } -static void initWifiResult(FFWifiResult* item, const char* name) { - ffStrbufInitS(&item->inf.description, name); - ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->conn.status); - ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.bssid); - ffStrbufInit(&item->conn.protocol); - ffStrbufInit(&item->conn.security); - item->conn.signalQuality = -DBL_MAX; - item->conn.rxRate = -DBL_MAX; - item->conn.txRate = -DBL_MAX; - item->conn.channel = 0; - item->conn.channelWidth = 0; - item->conn.frequency = 0; -} - static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) { switch (subtype) { case WL_FHSS: @@ -89,6 +73,8 @@ static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAu } const char* ffDetectWifi(FFlist* result) { + // https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/cmd-inet/usr.sbin/wificonfig/wificonfig.c + FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); if (!directory) { return nullptr; @@ -113,13 +99,28 @@ const char* ffDetectWifi(FFlist* result) { continue; } - FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); + FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR | O_CLOEXEC); if (fd < 0) { continue; } + if (!isastream(fd)) { + continue; + } FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); - initWifiResult(item, entry->d_name); + ffStrbufInitS(&item->inf.description, entry->d_name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; wl_radio_t radio; if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { @@ -140,13 +141,13 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufSetStatic(&item->conn.status, "Connected"); wl_essid_t essid; - if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { + if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length > 0 && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); } wl_bssid_t bssid; if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { - ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", (uint8_t) bssid[0], (uint8_t) bssid[1], (uint8_t) bssid[2], (uint8_t) bssid[3], (uint8_t) bssid[4], (uint8_t) bssid[5]); } wl_rssi_t rssi; From b1f2bf35269be84098e376e7a53a76ba8568e2db Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 15:23:21 +0800 Subject: [PATCH 040/109] WM: uses full name in EN, as DE and LM modules do --- src/modules/wm/wm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 8b7d8ec26..e1868120b 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -123,7 +123,7 @@ FFModuleBaseInfo ffWMModuleInfo = { .name = "WM", .description = "Print the window manager name and version", .displayName = { - .en = "WM", + .en = "Window Manager", .ar = "مدير النوافذ", .de = "Fenstermanager", .es = "Gestor de ventanas", From 8b40117c08236b71acc2d2caea899e981efc12eb Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 16:04:00 +0800 Subject: [PATCH 041/109] Wifi (OpenBSD): fortifies detection and adds channel to frequency helper --- src/detection/wifi/wifi.h | 17 +++++++++- src/detection/wifi/wifi_obsd.c | 58 +++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index a7ea62d48..faee5de46 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -19,7 +19,7 @@ struct FFWifiConnection { double txRate; uint16_t channel; uint16_t channelWidth; // MHz - uint16_t frequency; // MHz + uint16_t frequency; // MHz }; typedef struct FFWifiResult { @@ -61,3 +61,18 @@ static inline uint16_t ffWifiFreqToChannel(uint16_t frequency) { return 0; } + +static inline uint16_t ffWifiChannelToFreq(uint16_t channel) { + // Inverse of ffWifiFreqToChannel for the common 2.4 GHz and 5 GHz bands. + // 4.9 GHz and 6 GHz channels overlap numerically, so they are not handled here. + if (channel == 14) { + return 2484; + } + if (channel >= 1 && channel <= 13) { + return (uint16_t) (2407 + 5 * channel); + } + if (channel >= 36 && channel <= 177) { // 5 GHz: 5000 + 5*channel covers 36..177 + return (uint16_t) (5000 + 5 * channel); + } + return 0; +} diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index 6def7b63b..a9817c051 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -1,6 +1,5 @@ #include "wifi.h" #include "common/io.h" -#include "common/strutil.h" #include #include @@ -17,12 +16,20 @@ const char* ffDetectWifi(FFlist* result) { FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { + if_freenameindex(infs); return "socket() failed"; } for (struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == nullptr); ++i) { - if (!ffStrStartsWith(i->if_name, "iwm")) { - continue; + struct ieee80211_nodereq nr = {}; + strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname)); + + int err = 0; + if (ioctl(sock, SIOCG80211NODE, &nr) < 0) { + err = errno; + if (err == ENXIO || err == ENODEV || err == EINVAL || err == ENOTTY) { + continue; // Not a Wi-Fi interface + } } FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); @@ -37,12 +44,9 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; - item->conn.channelWidth = 0; + item->conn.channelWidth = 0; // not exposed by ieee80211_nodereq item->conn.frequency = 0; - struct ieee80211_nodereq nr = {}; - strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname)); - struct ifreq ifr = {}; strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name)); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { @@ -51,31 +55,34 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down"); } - if (ioctl(sock, SIOCG80211NODE, &nr) < 0) { - ffStrbufSetStatic(&item->conn.status, "Not associated"); - continue; - } - - if (nr.nr_nwid_len > 0) { - ffStrbufSetStatic(&item->conn.status, "Associated"); - ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid); - } else { + if (err != 0 || nr.nr_nwid_len == 0) { ffStrbufSetStatic(&item->conn.status, "Not associated"); continue; } + ffStrbufSetStatic(&item->conn.status, "Associated"); + ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid); ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2], nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]); item->conn.channel = nr.nr_channel; + if (item->conn.channel == 0) { + struct ieee80211chanreq chreq = {}; + strlcpy(chreq.i_name, i->if_name, sizeof(chreq.i_name)); + if (ioctl(sock, SIOCG80211CHANNEL, &chreq) >= 0) { + item->conn.channel = chreq.i_channel; + } + } + item->conn.frequency = ffWifiChannelToFreq(item->conn.channel); if (nr.nr_max_rssi) { - item->conn.signalQuality = ((float) nr.nr_rssi / nr.nr_max_rssi) * 100.0; + item->conn.signalQuality = ((double) nr.nr_rssi / (double) nr.nr_max_rssi) * 100.0; } - if (nr.nr_flags & IEEE80211_NODEREQ_HT) { - ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); - } else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) { + // VHT implies HT, so test VHT first + if (nr.nr_flags & IEEE80211_NODEREQ_VHT) { ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); + } else if (nr.nr_flags & IEEE80211_NODEREQ_HT) { + ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); } else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) { ffStrbufSetStatic(&item->conn.protocol, "802.11a"); } else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) { @@ -86,15 +93,22 @@ const char* ffDetectWifi(FFlist* result) { strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name)); if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) { - if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) { + if (wpa.i_akms & IEEE80211_WPA_AKM_SAE) { + if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) { + ffStrbufSetStatic(&item->conn.security, "WPA2/WPA3"); + } else { + ffStrbufSetStatic(&item->conn.security, "WPA3"); + } + } else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) { ffStrbufSetStatic(&item->conn.security, "WPA2"); } else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1) { ffStrbufSetStatic(&item->conn.security, "WPA"); + } else { + ffStrbufSetStatic(&item->conn.security, "Unknown"); } } else { struct ieee80211_nwkey nwkey = {}; strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name)); - if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) { if (nwkey.i_wepon) { ffStrbufSetStatic(&item->conn.security, "WEP"); From 5d11b65d533fe98a91213c9c6ef99fd6bdfeb188 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 16:18:07 +0800 Subject: [PATCH 042/109] TerminalFont (Android): adds font size detection --- src/detection/terminalfont/terminalfont_android.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 666cf3e2b..7ef0f5250 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -2,6 +2,7 @@ #include "terminalfont.h" #include "detection/terminalshell/terminalshell.h" #include "common/io.h" +#include "common/properties.h" #ifdef FF_HAVE_FREETYPE #include "common/library.h" @@ -10,10 +11,17 @@ #endif #define FF_TERMUX_FONT_PATH FASTFETCH_TARGET_DIR_HOME "/.termux/font.ttf" +#define FF_TERMUX_PREF_PATH "/data/data/com.termux/shared_prefs/com.termux_preferences.xml" const char* detectTermux(FFTerminalFontResult* terminalFont) { + FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); + // SharedPreferences XML: 14, in px + if (ffParsePropFile(FF_TERMUX_PREF_PATH, "", &fontSize)) { + ffStrbufAppendS(&fontSize, "px"); + } + if (!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE)) { - ffFontInitCopy(&terminalFont->font, "monospace"); + ffFontInitValues(&terminalFont->font, "monospace", fontSize.length ? fontSize.chars : nullptr); return nullptr; } @@ -39,7 +47,7 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) { goto exit; } - ffFontInitCopy(&terminalFont->font, face->family_name); + ffFontInitValues(&terminalFont->font, face->family_name, fontSize.length ? fontSize.chars : nullptr); exit: if (face) { @@ -53,7 +61,7 @@ exit: #else - FF_UNUSED(terminalFont); + ffFontInitValues(&terminalFont->font, "monospace", fontSize.length ? fontSize.chars : nullptr); return "Fastfetch was built without freetype2 support"; #endif From 0c4ec62cac9eb68936f93a9df5a1b2c179b0ee90 Mon Sep 17 00:00:00 2001 From: Samuel Torres Date: Thu, 20 Aug 2026 16:25:32 +0000 Subject: [PATCH 043/109] L10n: (gl) Added Galician Support --- doc/help.json | 1 + doc/json_schema.json | 5 +++++ src/common/option.h | 1 + src/modules/battery/battery.c | 1 + src/modules/bios/bios.c | 1 + src/modules/bluetooth/bluetooth.c | 1 + src/modules/bluetoothradio/bluetoothradio.c | 1 + src/modules/board/board.c | 1 + src/modules/bootmgr/bootmgr.c | 1 + src/modules/break/break.c | 1 + src/modules/brightness/brightness.c | 1 + src/modules/btrfs/btrfs.c | 1 + src/modules/camera/camera.c | 1 + src/modules/chassis/chassis.c | 1 + src/modules/codec/codec.c | 1 + src/modules/colors/colors.c | 1 + src/modules/command/command.c | 1 + src/modules/cpu/cpu.c | 1 + src/modules/cpucache/cpucache.c | 1 + src/modules/cpuusage/cpuusage.c | 1 + src/modules/cursor/cursor.c | 1 + src/modules/datetime/datetime.c | 1 + src/modules/de/de.c | 1 + src/modules/disk/disk.c | 1 + src/modules/diskio/diskio.c | 1 + src/modules/display/display.c | 1 + src/modules/dns/dns.c | 1 + src/modules/editor/editor.c | 1 + src/modules/font/font.c | 1 + src/modules/gamepad/gamepad.c | 1 + src/modules/gpu/gpu.c | 1 + src/modules/host/host.c | 1 + src/modules/icons/icons.c | 1 + src/modules/initsystem/initsystem.c | 1 + src/modules/kernel/kernel.c | 1 + src/modules/keyboard/keyboard.c | 1 + src/modules/lm/lm.c | 1 + src/modules/loadavg/loadavg.c | 1 + src/modules/locale/locale.c | 1 + src/modules/localip/localip.c | 1 + src/modules/logo/logo.c | 1 + src/modules/media/media.c | 1 + src/modules/memory/memory.c | 1 + src/modules/monitor/monitor.c | 1 + src/modules/mouse/mouse.c | 1 + src/modules/netio/netio.c | 1 + src/modules/opencl/opencl.c | 1 + src/modules/opengl/opengl.c | 1 + src/modules/os/os.c | 1 + src/modules/packages/packages.c | 1 + src/modules/physicaldisk/physicaldisk.c | 1 + src/modules/physicalmemory/physicalmemory.c | 1 + src/modules/player/player.c | 1 + src/modules/poweradapter/poweradapter.c | 1 + src/modules/processes/processes.c | 1 + src/modules/publicip/publicip.c | 1 + src/modules/separator/separator.c | 1 + src/modules/shell/shell.c | 1 + src/modules/sound/sound.c | 1 + src/modules/swap/swap.c | 1 + src/modules/terminal/terminal.c | 1 + src/modules/terminalfont/terminalfont.c | 1 + src/modules/terminaltheme/terminaltheme.c | 1 + src/modules/theme/theme.c | 1 + src/modules/title/title.c | 1 + src/modules/tpm/tpm.c | 1 + src/modules/uptime/uptime.c | 1 + src/modules/users/users.c | 1 + src/modules/version/version.c | 1 + src/modules/vulkan/vulkan.c | 1 + src/modules/wallpaper/wallpaper.c | 1 + src/modules/weather/weather.c | 1 + src/modules/wifi/wifi.c | 1 + src/modules/wm/wm.c | 1 + src/modules/wmtheme/wmtheme.c | 1 + src/modules/zpool/zpool.c | 1 + src/options/display.c | 4 ++++ 77 files changed, 84 insertions(+) diff --git a/doc/help.json b/doc/help.json index b575aa47b..4e056a5c8 100644 --- a/doc/help.json +++ b/doc/help.json @@ -599,6 +599,7 @@ "de": "German", "es": "Spanish", "fr": "French", + "gl": "Galician", "he": "Hebrew", "it": "Italian", "ja": "Japanese", diff --git a/doc/json_schema.json b/doc/json_schema.json index 3dbc06e98..d1db92493 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1090,6 +1090,11 @@ "const": "fr", "description": "French" }, + { + "type": "string", + "const": "gl", + "description": "Galician" + }, { "type": "string", "const": "he", diff --git a/src/common/option.h b/src/common/option.h index e8f2dca1d..1980e8051 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -25,6 +25,7 @@ typedef struct FFModuleDisplayName { const char* de; // German const char* es; // Spanish const char* fr; // French + const char* gl; // Galician const char* he; // Hebrew const char* it; // Italian const char* ja; // Japanese diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 9fd8c4572..ad71499aa 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -305,6 +305,7 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .de = "Akku", .es = "Batería", .fr = "Batterie", + .gl = "Batería", .he = "סוללה", .it = "Batteria", .ja = "バッテリー", diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 6b129213c..980906717 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -138,6 +138,7 @@ FFModuleBaseInfo ffBiosModuleInfo = { .de = "BIOS", .es = "BIOS", .fr = "BIOS", + .gl = "BIOS", .he = "BIOS", .it = "BIOS", .ja = "BIOS", diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index d4adae821..bd90ec887 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -159,6 +159,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .de = "Bluetooth", .es = "Bluetooth", .fr = "Bluetooth", + .gl = "Bluetooth", .he = "בלוטות'", .it = "Bluetooth", .ja = "ブルートゥース", diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 5a6b47d71..23284244f 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -196,6 +196,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .de = "Bluetooth-Adapter", .es = "Adaptador Bluetooth", .fr = "Adaptateur Bluetooth", + .gl = "Adaptador Bluetooth", .he = "רדיו בלוטות'", .it = "Adattatore Bluetooth", .ja = "ブルートゥースアダプター", diff --git a/src/modules/board/board.c b/src/modules/board/board.c index b82d90bc5..9436c7071 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -116,6 +116,7 @@ FFModuleBaseInfo ffBoardModuleInfo = { .de = "Mainboard", .es = "Placa base", .fr = "Carte mère", + .gl = "Placa base", .he = "לוח אם", .it = "Scheda madre", .ja = "マザーボード", diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index db7a9c473..e4059356d 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -111,6 +111,7 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .de = "Boot-Manager", .es = "Administrador de arranque", .fr = "Gestionnaire de démarrage", + .gl = "Xestor de arranque", .he = "מנהל אתחול", .it = "Gestore di avvio", .ja = "ブートマネージャー", diff --git a/src/modules/break/break.c b/src/modules/break/break.c index f0ef529bc..751694abd 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -35,6 +35,7 @@ FFModuleBaseInfo ffBreakModuleInfo = { .de = "Umbruch", .es = "Salto de línea", .fr = "Saut de ligne", + .gl = "Salto de liña", .he = "מעבר שורה", .it = "Interruzione", .ja = "改行", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 16ff8e8b0..d018a4dcd 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -198,6 +198,7 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .de = "Helligkeit", .es = "Brillo", .fr = "Luminosité", + .gl = "Brillo", .he = "בהירות", .it = "Luminosità", .ja = "明るさ", diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index bbba974e8..fc41ef402 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -206,6 +206,7 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .de = "BTRFS", .es = "BTRFS", .fr = "BTRFS", + .gl = "BTRFS", .he = "BTRFS", .it = "BTRFS", .ja = "BTRFS", diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 82cf79c03..1dcc89e19 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -123,6 +123,7 @@ FFModuleBaseInfo ffCameraModuleInfo = { .de = "Kamera", .es = "Cámara", .fr = "Caméra", + .gl = "Cámara", .he = "מצלמה", .it = "Fotocamera", .ja = "カメラ", diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index ae99ba9c5..7ba77a0d0 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -118,6 +118,7 @@ FFModuleBaseInfo ffChassisModuleInfo = { .de = "Gehäuse", .es = "Chasis", .fr = "Châssis", + .gl = "Chasis", .he = "מארז", .it = "Telaio", .ja = "シャーシ", diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index 6f7a3a1bb..d5c1d0e96 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -259,6 +259,7 @@ FFModuleBaseInfo ffCodecModuleInfo = { .de = "Codec", .es = "Códec", .fr = "Codec", + .gl = "Códec", .he = "קודק", .it = "Codec", .ja = "コーデック", diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 38ce77ce6..2f33f9162 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -303,6 +303,7 @@ FFModuleBaseInfo ffColorsModuleInfo = { .de = "Farben", .es = "Colores", .fr = "Couleurs", + .gl = "Cores", .he = "צבעים", .it = "Colori", .ja = "色", diff --git a/src/modules/command/command.c b/src/modules/command/command.c index a8e1b3f64..6878af3f2 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -161,6 +161,7 @@ FFModuleBaseInfo ffCommandModuleInfo = { .de = "Befehl", .es = "Comando", .fr = "Commande", + .gl = "Comando", .he = "פקודה", .it = "Comando", .ja = "コマンド", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index ec14dd363..23f652b77 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -259,6 +259,7 @@ FFModuleBaseInfo ffCPUModuleInfo = { .de = "CPU", .es = "CPU", .fr = "CPU", + .gl = "CPU", .he = "מעבד", .it = "CPU", .ja = "CPU", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index bf78de62d..97881382f 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -229,6 +229,7 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .de = "CPU-Cache", .es = "Caché de CPU", .fr = "Cache CPU", + .gl = "Caché da CPU", .he = "מטמון מעבד", .it = "Cache CPU", .ja = "CPUキャッシュ", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index e2b09a03a..bab07de65 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -187,6 +187,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .de = "CPU-Auslastung", .es = "Uso del CPU", .fr = "Utilisation du CPU", + .gl = "Uso da CPU", .he = "שימוש במעבד", .it = "Utilizzo della CPU", .ja = "CPU使用率", diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index f2c133bb6..54f605bb6 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -108,6 +108,7 @@ FFModuleBaseInfo ffCursorModuleInfo = { .de = "Mauszeiger", .es = "Cursor", .fr = "Curseur", + .gl = "Cursor", .he = "סמן", .it = "Cursore", .ja = "カーソル", diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 1fb7ab9c5..46131bcd5 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -158,6 +158,7 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .de = "Datum & Uhrzeit", .es = "Fecha y hora", .fr = "Date et heure", + .gl = "Data e hora", .he = "תאריך ושעה", .it = "Data e ora", .ja = "日付と時刻", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index c8b188d48..ec5445d34 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -90,6 +90,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .de = "Desktop-Umgebung", .es = "Entorno de Escritorio", .fr = "Environnement de Bureau", + .gl = "Contorno do Escritorio", .he = "סביבת שולחן עבודה", .it = "Ambiente Desktop", .ja = "デスクトップ環境", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index fddd4580f..2d80a18a5 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -459,6 +459,7 @@ FFModuleBaseInfo ffDiskModuleInfo = { .de = "Festplatte", .es = "Disco", .fr = "Disque", + .gl = "Disco", .he = "דיסק", .it = "Disco", .ja = "ディスク", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 3ebb8ce30..033317d66 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -178,6 +178,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .de = "Festplatten I/O", .es = "E/S de disco", .fr = "Entrée/Sortie disque", + .gl = "E/S do disco", .he = "קלט/פלט דיסק", .it = "I/O del disco", .ja = "ディスク I/O", diff --git a/src/modules/display/display.c b/src/modules/display/display.c index b7f0eefe5..4eda35233 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -419,6 +419,7 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .de = "Anzeige", .es = "Pantalla", .fr = "Écran", + .gl = "Pantalla", .he = "תצוגה", .it = "Display", .ja = "ディスプレイ", diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 7067de9ca..c0f20d2c5 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -142,6 +142,7 @@ FFModuleBaseInfo ffDNSModuleInfo = { .de = "DNS", .es = "DNS", .fr = "DNS", + .gl = "DNS", .he = "DNS", .it = "DNS", .ja = "DNS", diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 09cc37238..7d04c8445 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -111,6 +111,7 @@ FFModuleBaseInfo ffEditorModuleInfo = { .de = "Editor", .es = "Editor", .fr = "Éditeur", + .gl = "Editor", .he = "עורך", .it = "Editor", .ja = "エディター", diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 22a464563..dfbdd712f 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -103,6 +103,7 @@ FFModuleBaseInfo ffFontModuleInfo = { .de = "Schriftart", .es = "Fuente", .fr = "Police", + .gl = "Fonte", .he = "גופן", .it = "Carattere", .ja = "フォント", diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 7273156de..ae31b96cb 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -197,6 +197,7 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .de = "Gamepad", .es = "Gamepad", .fr = "Manette", + .gl = "Gamepad", .he = "משטח משחק", .it = "Gamepad", .ja = "ゲームパッド", diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index f030795da..1292a6256 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -487,6 +487,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { .de = "GPU", .es = "GPU", .fr = "GPU", + .gl = "GPU", .he = "מעבד גרפי", .it = "GPU", .ja = "GPU", diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 0159423bf..a79fbdc3b 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -144,6 +144,7 @@ FFModuleBaseInfo ffHostModuleInfo = { .de = "Rechner", .es = "Host", .fr = "Hôte", + .gl = "Host", .he = "מארח", .it = "Host", .ja = "ホスト", diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 5da212d33..c8b9d8cb4 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -102,6 +102,7 @@ FFModuleBaseInfo ffIconsModuleInfo = { .de = "Symbole", .es = "Iconos", .fr = "Icônes", + .gl = "Iconas", .he = "סמלים", .it = "Icone", .ja = "アイコン", diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index edd3d8fdc..f5f4238fd 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -109,6 +109,7 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .de = "Init-System", .es = "Sistema de inicio", .fr = "Système d'init", + .gl = "Sistema de inicio", .he = "מערכת אתחול", .it = "Sistema di init", .ja = "initシステム", diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index f0deb4727..3e8334e2c 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -70,6 +70,7 @@ FFModuleBaseInfo ffKernelModuleInfo = { .de = "Kernel", .es = "Kernel", .fr = "Kernel", + .gl = "Kernel", .he = "ליבה", .it = "Kernel", .ja = "カーネル", diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 998e04262..df7b2cef6 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -157,6 +157,7 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .de = "Tastatur", .es = "Teclado", .fr = "Clavier", + .gl = "Teclado", .he = "מקלדת", .it = "Tastiera", .ja = "キーボード", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 0b7d68649..4f96fb457 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -114,6 +114,7 @@ FFModuleBaseInfo ffLMModuleInfo = { .de = "Anmeldemanager", .es = "Administrador de inicio de sesión", .fr = "Gestionnaire de connexion", + .gl = "Xestor de inicio de sesión", .he = "מנהל התחברות", .it = "Gestore di accesso", .ja = "ログインマネージャー", diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index cfa36f857..a23c3edf6 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -156,6 +156,7 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .de = "Systemlast", .es = "Promedio de carga", .fr = "Charge moyenne", + .gl = "Carga media", .he = "עומס ממוצע", .it = "Carico medio", .ja = "ロードアベレージ", diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index ca523c90c..835937a0e 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -75,6 +75,7 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .de = "Sprachraum", .es = "Configuración regional", .fr = "Paramètres régionaux", + .gl = "Configuración rexional", .he = "לוקאל", .it = "Impostazioni locali", .ja = "ロケール", diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index accff5f47..13a4692c7 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -429,6 +429,7 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .de = "Lokale IP", .es = "IP local", .fr = "IP locale", + .gl = "IP local", .he = "IP מקומי", .it = "IP locale", .ja = "ローカル IP", diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 860960b6e..4f73084f9 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -85,6 +85,7 @@ FFModuleBaseInfo ffLogoModuleInfo = { .de = "Logo", .es = "Logo", .fr = "Logo", + .gl = "Logo", .he = "לוגו", .it = "Logo", .ja = "ロゴ", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 5e7188905..4f6a81c55 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -261,6 +261,7 @@ FFModuleBaseInfo ffMediaModuleInfo = { .de = "Medien", .es = "Medios", .fr = "Médias", + .gl = "Multimedia", .he = "מדיה", .it = "Media", .ja = "メディア", diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index d375bd9cc..d338d177e 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -126,6 +126,7 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .de = "Speicher", .es = "Memoria", .fr = "Mémoire", + .gl = "Memoria", .he = "זיכרון", .it = "Memoria", .ja = "メモリ", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index a9959187b..13cf74124 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -112,6 +112,7 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .de = "Monitor", .es = "Monitor", .fr = "Moniteur", + .gl = "Monitor", .he = "צג", .it = "Monitor", .ja = "モニター", diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index b6db69243..f8f06a937 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -160,6 +160,7 @@ FFModuleBaseInfo ffMouseModuleInfo = { .de = "Maus", .es = "Ratón", .fr = "Souris", + .gl = "Rato", .he = "עכבר", .it = "Mouse", .ja = "マウス", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 328cc3613..6d2a72cef 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -205,6 +205,7 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .de = "Netzwerk I/O", .es = "E/S de red", .fr = "E/S réseau", + .gl = "E/S da rede", .he = "קלט/פלט רשת", .it = "I/O di rete", .ja = "ネットワークI/O", diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 78352f306..c13c8c2d9 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -128,6 +128,7 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .de = "OpenCL", .es = "OpenCL", .fr = "OpenCL", + .gl = "OpenCL", .he = "OpenCL", .it = "OpenCL", .ja = "OpenCL", diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 8093e135d..4b325cbec 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -135,6 +135,7 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .de = "OpenGL", .es = "OpenGL", .fr = "OpenGL", + .gl = "OpenGL", .he = "OpenGL", .it = "OpenGL", .ja = "OpenGL", diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 3e0fecc75..51c89cbba 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -180,6 +180,7 @@ FFModuleBaseInfo ffOSModuleInfo = { .de = "Betriebssystem", .es = "Sistema operativo", .fr = "Système d'exploitation", + .gl = "Sistema operativo", .he = "מערכת הפעלה", .it = "Sistema operativo", .ja = "オペレーティングシステム", diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 2c6143189..fc39603b4 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -518,6 +518,7 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .de = "Pakete", .es = "Paquetes", .fr = "Paquets", + .gl = "Paquetes", .he = "חבילות", .it = "Pacchetti", .ja = "パッケージ", diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 929ca4b69..a4e7bb0f8 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -271,6 +271,7 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .de = "Physische Festplatte", .es = "Disco físico", .fr = "Disque physique", + .gl = "Disco físico", .he = "דיסק פיזי", .it = "Disco fisico", .ja = "物理ディスク", diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 5c0d6ecec..4c9ee7001 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -165,6 +165,7 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .de = "Physischer Speicher", .es = "Memoria física", .fr = "Mémoire physique", + .gl = "Memoria física", .he = "זיכרון פיזי", .it = "Memoria fisica", .ja = "物理メモリ", diff --git a/src/modules/player/player.c b/src/modules/player/player.c index c12da175d..c5bdfcf13 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -115,6 +115,7 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .de = "Medienplayer", .es = "Reproductor multimedia", .fr = "Lecteur multimédia", + .gl = "Reprodutor multimedia", .he = "נגן מדיה", .it = "Lettore multimediale", .ja = "メディアプレイヤー", diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index d9506c41b..5d8d2e2c1 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -116,6 +116,7 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .de = "Netzteil", .es = "Adaptador de corriente", .fr = "Adaptateur secteur", + .gl = "Adaptador de corrente", .he = "מתאם מתח", .it = "Alimentatore", .ja = "電源アダプター", diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 824fd89d6..a73c2c463 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -71,6 +71,7 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .de = "Prozesse", .es = "Procesos", .fr = "Processus", + .gl = "Procesos", .he = "תהליכים", .it = "Processi", .ja = "プロセス", diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index afad49017..110b0dfc8 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -116,6 +116,7 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .de = "Öffentliche IP", .es = "IP pública", .fr = "IP publique", + .gl = "IP pública", .he = "IP ציבורי", .it = "IP pubblica", .ja = "パブリックIP", diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 34af6a286..0c19a89cc 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -129,6 +129,7 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .de = "Trennlinie", .es = "Separador", .fr = "Séparateur", + .gl = "Separador", .he = "מפריד", .it = "Separatore", .ja = "セパレーター", diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 8abd01d52..bce575b2a 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -97,6 +97,7 @@ FFModuleBaseInfo ffShellModuleInfo = { .de = "Shell", .es = "Shell", .fr = "Shell", + .gl = "Shell", .he = "מעטפת", .it = "Shell", .ja = "シェル", diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index fa87482f1..0c6436833 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -207,6 +207,7 @@ FFModuleBaseInfo ffSoundModuleInfo = { .de = "Sound", .es = "Sonido", .fr = "Son", + .gl = "Son", .he = "קול", .it = "Audio", .ja = "サウンド", diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 796cf7271..3848b62d0 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -190,6 +190,7 @@ FFModuleBaseInfo ffSwapModuleInfo = { .de = "Swap", .es = "Swap", .fr = "Swap", + .gl = "Swap", .he = "זיכרון החלפה", .it = "Swap", .ja = "スワップ", diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 58e6ae9cf..80c901693 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -91,6 +91,7 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .de = "Terminal", .es = "Terminal", .fr = "Terminal", + .gl = "Terminal", .he = "טרמינל", .it = "Terminale", .ja = "ターミナル", diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index ae792843b..d9e5a81f5 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -111,6 +111,7 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .de = "Terminalschriftart", .es = "Fuente del terminal", .fr = "Police du terminal", + .gl = "Fonte do terminal", .he = "גופן טרמינל", .it = "Carattere del terminale", .ja = "ターミナルフォント", diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 52e3feebf..faa1ef285 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -99,6 +99,7 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .de = "Terminalthema", .es = "Tema del terminal", .fr = "Thème du terminal", + .gl = "Tema do terminal", .he = "ערכת נושא של טרמינל", .it = "Tema del terminale", .ja = "ターミナルテーマ", diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 4ceaf14cb..263dd9875 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -95,6 +95,7 @@ FFModuleBaseInfo ffThemeModuleInfo = { .de = "Thema", .es = "Tema", .fr = "Thème", + .gl = "Tema", .he = "ערכת נושא", .it = "Tema", .ja = "テーマ", diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 788ab2eec..3cad3941d 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -184,6 +184,7 @@ FFModuleBaseInfo ffTitleModuleInfo = { .de = "Titel", .es = "Título", .fr = "Titre", + .gl = "Título", .he = "כותרת", .it = "Titolo", .ja = "タイトル", diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 3ff4a4e8d..1e2e03f10 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -91,6 +91,7 @@ FFModuleBaseInfo ffTPMModuleInfo = { .de = "TPM", .es = "TPM", .fr = "TPM", + .gl = "TPM", .he = "TPM", .it = "TPM", .ja = "TPM", diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index d7ee69e05..5937711bf 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -91,6 +91,7 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .de = "Betriebszeit", .es = "Tiempo de actividad", .fr = "Temps de fonctionnement", + .gl = "Tempo de actividade", .he = "זמן פעילות", .it = "Tempo di attività", .ja = "稼働時間", diff --git a/src/modules/users/users.c b/src/modules/users/users.c index e355f40d7..e381297ec 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -188,6 +188,7 @@ FFModuleBaseInfo ffUsersModuleInfo = { .de = "Benutzer", .es = "Usuarios", .fr = "Utilisateurs", + .gl = "Usuarios", .he = "משתמשים", .it = "Utenti", .ja = "ユーザー", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index f90585a73..04fb1a6ff 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -102,6 +102,7 @@ FFModuleBaseInfo ffVersionModuleInfo = { .de = "Version", .es = "Versión", .fr = "Version", + .gl = "Versión", .he = "גרסה", .it = "Versione", .ja = "バージョン", diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 990b56f1a..4c2c8c85f 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -140,6 +140,7 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .de = "Vulkan", .es = "Vulkan", .fr = "Vulkan", + .gl = "Vulkan", .he = "Vulkan", .it = "Vulkan", .ja = "Vulkan", diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index 9ed7d4014..472587d9a 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -83,6 +83,7 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .de = "Hintergrundbild", .es = "Fondo de pantalla", .fr = "Fond d'écran", + .gl = "Fondo de escritorio", .he = "טפט", .it = "Sfondo", .ja = "壁紙", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 5eab9a6c7..d630de141 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -100,6 +100,7 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .de = "Wetter", .es = "Clima", .fr = "Météo", + .gl = "Tempo", .he = "מזג אוויר", .it = "Meteo", .ja = "天気", diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index a9462418d..a7ad22c22 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -223,6 +223,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { .de = "WLAN", .es = "Wi-Fi", .fr = "Wi-Fi", + .gl = "Wi-Fi", .he = "Wi-Fi", .it = "Wi-Fi", .ja = "Wi-Fi", diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index e1868120b..2812a97ce 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -128,6 +128,7 @@ FFModuleBaseInfo ffWMModuleInfo = { .de = "Fenstermanager", .es = "Gestor de ventanas", .fr = "Gestionnaire de fenêtres", + .gl = "Xestor de xanelas", .he = "מנהל חלונות", .it = "Gestore finestre", .ja = "ウィンドウマネージャー", diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 5394b0963..f6f40979a 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -67,6 +67,7 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .de = "Fenstermanager-Thema", .es = "Tema del gestor de ventanas", .fr = "Thème du gestionnaire de fenêtres", + .gl = "Tema do xestor de xanelas", .he = "ערכת נושא של מנהל חלונות", .it = "Tema del gestore finestre", .ja = "ウィンドウマネージャのテーマ", diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index aafb5d4d9..7657c9489 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -200,6 +200,7 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .de = "Zpool", .es = "Zpool", .fr = "Zpool", + .gl = "Zpool", .he = "Zpool", .it = "Zpool", .ja = "Zpool", diff --git a/src/options/display.c b/src/options/display.c index a352af719..0e6b7141c 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -68,6 +68,7 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { case 'de': return offsetof(FFModuleDisplayName, de); case 'es': return offsetof(FFModuleDisplayName, es); case 'fr': return offsetof(FFModuleDisplayName, fr); + case 'gl': return offsetof(FFModuleDisplayName, gl); case 'he': return offsetof(FFModuleDisplayName, he); case 'it': return offsetof(FFModuleDisplayName, it); case 'ja': return offsetof(FFModuleDisplayName, ja); @@ -1284,6 +1285,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, fr): yyjson_mut_obj_add_str(doc, key, "language", "fr"); break; + case offsetof(FFModuleDisplayName, gl): + yyjson_mut_obj_add_str(doc, key, "language", "gl"); + break; case offsetof(FFModuleDisplayName, he): yyjson_mut_obj_add_str(doc, key, "language", "he"); break; From 6570a7accc91417c123e4fc59bf828b4a630a86c Mon Sep 17 00:00:00 2001 From: Samuel Torres Date: Fri, 21 Aug 2026 00:31:42 +0000 Subject: [PATCH 044/109] L10n (ES): fixes Spanish translations (#2537) --- src/modules/bootmgr/bootmgr.c | 2 +- src/modules/cpucache/cpucache.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/de/de.c | 2 +- src/modules/diskio/diskio.c | 2 +- src/modules/lm/lm.c | 2 +- src/modules/media/media.c | 2 +- src/modules/netio/netio.c | 2 +- src/modules/weather/weather.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index e4059356d..8ad60faf2 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -109,7 +109,7 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .en = "Boot Manager", .ar = "مدير الإقلاع", .de = "Boot-Manager", - .es = "Administrador de arranque", + .es = "Gestor de arranque", .fr = "Gestionnaire de démarrage", .gl = "Xestor de arranque", .he = "מנהל אתחול", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 97881382f..55d92baa3 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -227,7 +227,7 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .en = "CPU Cache", .ar = "ذاكرة المعالج المؤقتة", .de = "CPU-Cache", - .es = "Caché de CPU", + .es = "Caché de la CPU", .fr = "Cache CPU", .gl = "Caché da CPU", .he = "מטמון מעבד", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index bab07de65..3670ced0d 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -185,7 +185,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .en = "CPU Usage", .ar = "استخدام المعالج", .de = "CPU-Auslastung", - .es = "Uso del CPU", + .es = "Uso de la CPU", .fr = "Utilisation du CPU", .gl = "Uso da CPU", .he = "שימוש במעבד", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index ec5445d34..b1942d694 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -88,7 +88,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .en = "Desktop Environment", .ar = "بيئة سطح المكتب", .de = "Desktop-Umgebung", - .es = "Entorno de Escritorio", + .es = "Entorno de escritorio", .fr = "Environnement de Bureau", .gl = "Contorno do Escritorio", .he = "סביבת שולחן עבודה", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 033317d66..e76f09364 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -176,7 +176,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .en = "Disk I/O", .ar = "إدخال/إخراج القرص", .de = "Festplatten I/O", - .es = "E/S de disco", + .es = "E/S del disco", .fr = "Entrée/Sortie disque", .gl = "E/S do disco", .he = "קלט/פלט דיסק", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 4f96fb457..88b7b0ed4 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -112,7 +112,7 @@ FFModuleBaseInfo ffLMModuleInfo = { .en = "Login Manager", .ar = "مدير تسجيل الدخول", .de = "Anmeldemanager", - .es = "Administrador de inicio de sesión", + .es = "Gestor de inicio de sesión", .fr = "Gestionnaire de connexion", .gl = "Xestor de inicio de sesión", .he = "מנהל התחברות", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 4f6a81c55..da5c13c42 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -259,7 +259,7 @@ FFModuleBaseInfo ffMediaModuleInfo = { .en = "Media", .ar = "الوسائط", .de = "Medien", - .es = "Medios", + .es = "Multimedia", .fr = "Médias", .gl = "Multimedia", .he = "מדיה", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 6d2a72cef..2bc95d615 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -203,7 +203,7 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .en = "Network I/O", .ar = "إدخال/إخراج الشبكة", .de = "Netzwerk I/O", - .es = "E/S de red", + .es = "E/S de la red", .fr = "E/S réseau", .gl = "E/S da rede", .he = "קלט/פלט רשת", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index d630de141..6878ab8d9 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -98,7 +98,7 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .en = "Weather", .ar = "الطقس", .de = "Wetter", - .es = "Clima", + .es = "Tiempo", .fr = "Météo", .gl = "Tempo", .he = "מזג אוויר", From e0c239729b22b702542d262b2f8991149c616b54 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Aug 2026 10:19:06 +0800 Subject: [PATCH 045/109] L10n: adds `cs` `id` `tr` `uk` `vi` Assisted-By: LLM --- .codespellrc | 2 +- doc/help.json | 5 +++++ doc/json_schema.json | 25 +++++++++++++++++++++ src/common/option.h | 5 +++++ src/modules/battery/battery.c | 5 +++++ src/modules/bios/bios.c | 5 +++++ src/modules/bluetooth/bluetooth.c | 5 +++++ src/modules/bluetoothradio/bluetoothradio.c | 5 +++++ src/modules/board/board.c | 5 +++++ src/modules/bootmgr/bootmgr.c | 5 +++++ src/modules/break/break.c | 5 +++++ src/modules/brightness/brightness.c | 5 +++++ src/modules/btrfs/btrfs.c | 5 +++++ src/modules/camera/camera.c | 5 +++++ src/modules/chassis/chassis.c | 5 +++++ src/modules/codec/codec.c | 5 +++++ src/modules/colors/colors.c | 5 +++++ src/modules/command/command.c | 5 +++++ src/modules/cpu/cpu.c | 5 +++++ src/modules/cpucache/cpucache.c | 5 +++++ src/modules/cpuusage/cpuusage.c | 5 +++++ src/modules/cursor/cursor.c | 5 +++++ src/modules/custom/custom.c | 5 +++++ src/modules/datetime/datetime.c | 5 +++++ src/modules/de/de.c | 5 +++++ src/modules/disk/disk.c | 5 +++++ src/modules/diskio/diskio.c | 5 +++++ src/modules/display/display.c | 5 +++++ src/modules/dns/dns.c | 5 +++++ src/modules/editor/editor.c | 5 +++++ src/modules/font/font.c | 5 +++++ src/modules/gamepad/gamepad.c | 5 +++++ src/modules/gpu/gpu.c | 5 +++++ src/modules/host/host.c | 5 +++++ src/modules/icons/icons.c | 5 +++++ src/modules/initsystem/initsystem.c | 5 +++++ src/modules/kernel/kernel.c | 5 +++++ src/modules/keyboard/keyboard.c | 5 +++++ src/modules/lm/lm.c | 5 +++++ src/modules/loadavg/loadavg.c | 5 +++++ src/modules/locale/locale.c | 5 +++++ src/modules/localip/localip.c | 5 +++++ src/modules/logo/logo.c | 5 +++++ src/modules/media/media.c | 5 +++++ src/modules/memory/memory.c | 5 +++++ src/modules/monitor/monitor.c | 5 +++++ src/modules/mouse/mouse.c | 5 +++++ src/modules/netio/netio.c | 5 +++++ src/modules/opencl/opencl.c | 5 +++++ src/modules/opengl/opengl.c | 5 +++++ src/modules/os/os.c | 5 +++++ src/modules/packages/packages.c | 5 +++++ src/modules/physicaldisk/physicaldisk.c | 5 +++++ src/modules/physicalmemory/physicalmemory.c | 5 +++++ src/modules/player/player.c | 5 +++++ src/modules/poweradapter/poweradapter.c | 5 +++++ src/modules/processes/processes.c | 5 +++++ src/modules/publicip/publicip.c | 5 +++++ src/modules/separator/separator.c | 5 +++++ src/modules/shell/shell.c | 5 +++++ src/modules/sound/sound.c | 5 +++++ src/modules/swap/swap.c | 5 +++++ src/modules/terminal/terminal.c | 5 +++++ src/modules/terminalfont/terminalfont.c | 5 +++++ src/modules/terminalsize/terminalsize.c | 5 +++++ src/modules/terminaltheme/terminaltheme.c | 5 +++++ src/modules/theme/theme.c | 5 +++++ src/modules/title/title.c | 5 +++++ src/modules/tpm/tpm.c | 5 +++++ src/modules/uptime/uptime.c | 5 +++++ src/modules/users/users.c | 5 +++++ src/modules/version/version.c | 5 +++++ src/modules/vulkan/vulkan.c | 5 +++++ src/modules/wallpaper/wallpaper.c | 5 +++++ src/modules/weather/weather.c | 5 +++++ src/modules/wifi/wifi.c | 5 +++++ src/modules/wm/wm.c | 5 +++++ src/modules/wmtheme/wmtheme.c | 5 +++++ src/modules/zpool/zpool.c | 5 +++++ src/options/display.c | 20 +++++++++++++++++ 80 files changed, 431 insertions(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index 1554e6270..d07ab39fa 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*,./src/common/impl/genconfig.c -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement,Sistem,Lokal,Lokal,Sistem,Paket,Hava diff --git a/doc/help.json b/doc/help.json index 4e056a5c8..1d882d133 100644 --- a/doc/help.json +++ b/doc/help.json @@ -596,17 +596,22 @@ "enum": { "en": "English", "ar": "Arabic", + "cs": "Czech", "de": "German", "es": "Spanish", "fr": "French", "gl": "Galician", "he": "Hebrew", + "id": "Indonesian", "it": "Italian", "ja": "Japanese", "ko": "Korean", "pl": "Polish", "pt": "Portuguese", "ru": "Russian", + "tr": "Turkish", + "uk": "Ukrainian", + "vi": "Vietnamese", "zh_CN": "Simplified Chinese", "zh_TW": "Traditional Chinese" } diff --git a/doc/json_schema.json b/doc/json_schema.json index d1db92493..9e0aabc34 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1075,6 +1075,11 @@ "const": "ar", "description": "Arabic" }, + { + "type": "string", + "const": "cs", + "description": "Czech" + }, { "type": "string", "const": "de", @@ -1100,6 +1105,11 @@ "const": "he", "description": "Hebrew" }, + { + "type": "string", + "const": "id", + "description": "Indonesian" + }, { "type": "string", "const": "it", @@ -1130,6 +1140,21 @@ "const": "ru", "description": "Russian" }, + { + "type": "string", + "const": "tr", + "description": "Turkish" + }, + { + "type": "string", + "const": "uk", + "description": "Ukrainian" + }, + { + "type": "string", + "const": "vi", + "description": "Vietnamese" + }, { "type": "string", "const": "zh_CN", diff --git a/src/common/option.h b/src/common/option.h index 1980e8051..0afaa449d 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -22,17 +22,22 @@ typedef struct FFModuleDisplayName { const char* en; // English const char* ar; // Arabic + const char* cs; // Czech const char* de; // German const char* es; // Spanish const char* fr; // French const char* gl; // Galician const char* he; // Hebrew + const char* id; // Indonesian const char* it; // Italian const char* ja; // Japanese const char* ko; // Korean const char* pl; // Polish const char* pt; // (Brazilian) Portuguese const char* ru; // Russian + const char* tr; // Turkish + const char* uk; // Ukrainian + const char* vi; // Vietnamese const char* zh_CN; // Simplified Chinese const char* zh_TW; // Traditional Chinese } FFModuleDisplayName; diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index ad71499aa..33e969436 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -302,17 +302,22 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .displayName = { .en = "Battery", .ar = "البطارية", + .cs = "Baterie", .de = "Akku", .es = "Batería", .fr = "Batterie", .gl = "Batería", .he = "סוללה", + .id = "Baterai", .it = "Batteria", .ja = "バッテリー", .ko = "배터리", .pl = "Bateria", .pt = "Bateria", .ru = "Батарея", + .tr = "Pil", + .uk = "Батарея", + .vi = "Pin", .zh_CN = "电池", .zh_TW = "電池", }, diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 980906717..fc4f7ac73 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -135,17 +135,22 @@ FFModuleBaseInfo ffBiosModuleInfo = { .displayName = { .en = "BIOS", .ar = "BIOS", + .cs = "BIOS", .de = "BIOS", .es = "BIOS", .fr = "BIOS", .gl = "BIOS", .he = "BIOS", + .id = "BIOS", .it = "BIOS", .ja = "BIOS", .ko = "BIOS", .pl = "BIOS", .pt = "BIOS", .ru = "BIOS", + .tr = "BIOS", + .uk = "BIOS", + .vi = "BIOS", .zh_CN = "BIOS", .zh_TW = "BIOS", }, diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index bd90ec887..9f6986392 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -156,17 +156,22 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .displayName = { .en = "Bluetooth", .ar = "بلوتوث", + .cs = "Bluetooth", .de = "Bluetooth", .es = "Bluetooth", .fr = "Bluetooth", .gl = "Bluetooth", .he = "בלוטות'", + .id = "Bluetooth", .it = "Bluetooth", .ja = "ブルートゥース", .ko = "블루투스", .pl = "Bluetooth", .pt = "Bluetooth", .ru = "Bluetooth", + .tr = "Bluetooth", + .uk = "Bluetooth", + .vi = "Bluetooth", .zh_CN = "蓝牙设备", .zh_TW = "藍牙裝置", }, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 23284244f..0596fb47e 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -193,17 +193,22 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .displayName = { .en = "Bluetooth Radio", .ar = "راديو بلوتوث", + .cs = "Bluetooth rádio", .de = "Bluetooth-Adapter", .es = "Adaptador Bluetooth", .fr = "Adaptateur Bluetooth", .gl = "Adaptador Bluetooth", .he = "רדיו בלוטות'", + .id = "Radio Bluetooth", .it = "Adattatore Bluetooth", .ja = "ブルートゥースアダプター", .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", .pt = "Adaptador Bluetooth", .ru = "Bluetooth-адаптер", + .tr = "Bluetooth Radyosu", + .uk = "Радіомодуль Bluetooth", + .vi = "Radio Bluetooth", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", }, diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 9436c7071..c0f49baaa 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -113,17 +113,22 @@ FFModuleBaseInfo ffBoardModuleInfo = { .displayName = { .en = "Board", .ar = "اللوحة الأم", + .cs = "Základní deska", .de = "Mainboard", .es = "Placa base", .fr = "Carte mère", .gl = "Placa base", .he = "לוח אם", + .id = "Papan Induk", .it = "Scheda madre", .ja = "マザーボード", .ko = "메인보드", .pl = "Płyta główna", .pt = "Placa-mãe", .ru = "Материнская плата", + .tr = "Anakart", + .uk = "Материнська плата", + .vi = "Bo mạch chủ", .zh_CN = "主板", .zh_TW = "主機板", }, diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 8ad60faf2..45e29bbbb 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -108,17 +108,22 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .displayName = { .en = "Boot Manager", .ar = "مدير الإقلاع", + .cs = "Správce spouštění", .de = "Boot-Manager", .es = "Gestor de arranque", .fr = "Gestionnaire de démarrage", .gl = "Xestor de arranque", .he = "מנהל אתחול", + .id = "Manajer Boot", .it = "Gestore di avvio", .ja = "ブートマネージャー", .ko = "부트 매니저", .pl = "Menedżer rozruchu", .pt = "Gerenciador de inicialização", .ru = "Менеджер загрузки", + .tr = "Önyükleme Yöneticisi", + .uk = "Менеджер завантаження", + .vi = "Trình quản lý khởi động", .zh_CN = "启动管理器", .zh_TW = "啟動管理器", }, diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 751694abd..5a6f35673 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -32,17 +32,22 @@ FFModuleBaseInfo ffBreakModuleInfo = { .displayName = { .en = "Break", .ar = "فاصل", + .cs = "Konec řádku", .de = "Umbruch", .es = "Salto de línea", .fr = "Saut de ligne", .gl = "Salto de liña", .he = "מעבר שורה", + .id = "Baris Baru", .it = "Interruzione", .ja = "改行", .ko = "줄 바꿈", .pl = "Przerwa", .pt = "Quebra", .ru = "Разрыв", + .tr = "Satır Sonu", + .uk = "Розрив рядка", + .vi = "Xuống dòng", .zh_CN = "换行", .zh_TW = "換行", }, diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index d018a4dcd..5c6fc1544 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -195,17 +195,22 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .displayName = { .en = "Brightness", .ar = "السطوع", + .cs = "Jas", .de = "Helligkeit", .es = "Brillo", .fr = "Luminosité", .gl = "Brillo", .he = "בהירות", + .id = "Kecerahan", .it = "Luminosità", .ja = "明るさ", .ko = "밝기", .pl = "Jasność", .pt = "Brilho", .ru = "Яркость", + .tr = "Parlaklık", + .uk = "Яскравість", + .vi = "Độ sáng", .zh_CN = "亮度", .zh_TW = "亮度", }, diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index fc41ef402..052cf32dc 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -203,17 +203,22 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .displayName = { .en = "BTRFS", .ar = "BTRFS", + .cs = "BTRFS", .de = "BTRFS", .es = "BTRFS", .fr = "BTRFS", .gl = "BTRFS", .he = "BTRFS", + .id = "BTRFS", .it = "BTRFS", .ja = "BTRFS", .ko = "BTRFS", .pl = "BTRFS", .pt = "BTRFS", .ru = "BTRFS", + .tr = "BTRFS", + .uk = "BTRFS", + .vi = "BTRFS", .zh_CN = "BTRFS", .zh_TW = "BTRFS", }, diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 1dcc89e19..95101c23d 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -120,17 +120,22 @@ FFModuleBaseInfo ffCameraModuleInfo = { .displayName = { .en = "Camera", .ar = "الكاميرا", + .cs = "Kamera", .de = "Kamera", .es = "Cámara", .fr = "Caméra", .gl = "Cámara", .he = "מצלמה", + .id = "Kamera", .it = "Fotocamera", .ja = "カメラ", .ko = "카메라", .pl = "Kamera", .pt = "Câmera", .ru = "Камера", + .tr = "Kamera", + .uk = "Камера", + .vi = "Máy ảnh", .zh_CN = "摄像头", .zh_TW = "攝像頭", }, diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 7ba77a0d0..6049d533d 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -115,17 +115,22 @@ FFModuleBaseInfo ffChassisModuleInfo = { .displayName = { .en = "Chassis", .ar = "الهيكل", + .cs = "Skříň", .de = "Gehäuse", .es = "Chasis", .fr = "Châssis", .gl = "Chasis", .he = "מארז", + .id = "Casing", .it = "Telaio", .ja = "シャーシ", .ko = "섀시", .pl = "Obudowa", .pt = "Chassi", .ru = "Корпус", + .tr = "Kasa", + .uk = "Корпус", + .vi = "Vỏ máy", .zh_CN = "机箱", .zh_TW = "機箱", }, diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index d5c1d0e96..2e5b87983 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -256,17 +256,22 @@ FFModuleBaseInfo ffCodecModuleInfo = { .displayName = { .en = "Codec", .ar = "الترميز", + .cs = "Kodek", .de = "Codec", .es = "Códec", .fr = "Codec", .gl = "Códec", .he = "קודק", + .id = "Kodek", .it = "Codec", .ja = "コーデック", .ko = "코덱", .pl = "Kodek", .pt = "Codec", .ru = "Кодек", + .tr = "Kodek", + .uk = "Кодек", + .vi = "Codec", .zh_CN = "编解码器", .zh_TW = "編解碼器", }, diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 2f33f9162..b9fa813e7 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -300,17 +300,22 @@ FFModuleBaseInfo ffColorsModuleInfo = { .displayName = { .en = "Colors", .ar = "الألوان", + .cs = "Barvy", .de = "Farben", .es = "Colores", .fr = "Couleurs", .gl = "Cores", .he = "צבעים", + .id = "Warna", .it = "Colori", .ja = "色", .ko = "색상", .pl = "Kolory", .pt = "Cores", .ru = "Цвета", + .tr = "Renkler", + .uk = "Кольори", + .vi = "Màu sắc", .zh_CN = "颜色", .zh_TW = "顏色", }, diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 6878af3f2..21ac4378c 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -158,17 +158,22 @@ FFModuleBaseInfo ffCommandModuleInfo = { .displayName = { .en = "Command", .ar = "الأمر", + .cs = "Příkaz", .de = "Befehl", .es = "Comando", .fr = "Commande", .gl = "Comando", .he = "פקודה", + .id = "Perintah", .it = "Comando", .ja = "コマンド", .ko = "명령어", .pl = "Polecenie", .pt = "Comando", .ru = "Команда", + .tr = "Komut", + .uk = "Команда", + .vi = "Lệnh", .zh_CN = "命令", .zh_TW = "命令", }, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 23f652b77..9d5257687 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -256,17 +256,22 @@ FFModuleBaseInfo ffCPUModuleInfo = { .displayName = { .en = "CPU", .ar = "المعالج", + .cs = "CPU", .de = "CPU", .es = "CPU", .fr = "CPU", .gl = "CPU", .he = "מעבד", + .id = "CPU", .it = "CPU", .ja = "CPU", .ko = "CPU", .pl = "CPU", .pt = "CPU", .ru = "Процессор", + .tr = "CPU", + .uk = "CPU", + .vi = "CPU", .zh_CN = "CPU", .zh_TW = "CPU", }, diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 55d92baa3..efb9407e4 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -226,17 +226,22 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .displayName = { .en = "CPU Cache", .ar = "ذاكرة المعالج المؤقتة", + .cs = "Mezipaměť CPU", .de = "CPU-Cache", .es = "Caché de la CPU", .fr = "Cache CPU", .gl = "Caché da CPU", .he = "מטמון מעבד", + .id = "Cache CPU", .it = "Cache CPU", .ja = "CPUキャッシュ", .ko = "CPU 캐시", .pl = "Pamięć podręczna CPU", .pt = "Cache da CPU", .ru = "Кэш процессора", + .tr = "CPU Önbelleği", + .uk = "Кеш ЦП", + .vi = "Bộ nhớ đệm CPU", .zh_CN = "CPU缓存", .zh_TW = "CPU快取記憶體", }, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 3670ced0d..96c45c28d 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -184,17 +184,22 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .displayName = { .en = "CPU Usage", .ar = "استخدام المعالج", + .cs = "Využití CPU", .de = "CPU-Auslastung", .es = "Uso de la CPU", .fr = "Utilisation du CPU", .gl = "Uso da CPU", .he = "שימוש במעבד", + .id = "Penggunaan CPU", .it = "Utilizzo della CPU", .ja = "CPU使用率", .ko = "CPU 사용량", .pl = "Użycie CPU", .pt = "Uso da CPU", .ru = "Использование процессора", + .tr = "CPU Kullanımı", + .uk = "Використання ЦП", + .vi = "Mức sử dụng CPU", .zh_CN = "CPU使用率", .zh_TW = "CPU使用率", }, diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 54f605bb6..7bc274802 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -105,17 +105,22 @@ FFModuleBaseInfo ffCursorModuleInfo = { .displayName = { .en = "Cursor", .ar = "المؤشر", + .cs = "Kurzor", .de = "Mauszeiger", .es = "Cursor", .fr = "Curseur", .gl = "Cursor", .he = "סמן", + .id = "Kursor", .it = "Cursore", .ja = "カーソル", .ko = "커서", .pl = "Kursor", .pt = "Cursor", .ru = "Курсор", + .tr = "İmleç", + .uk = "Курсор", + .vi = "Con trỏ", .zh_CN = "光标", .zh_TW = "游標", }, diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index c29bea05c..79c3d02f8 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -40,16 +40,21 @@ FFModuleBaseInfo ffCustomModuleInfo = { .displayName = { .en = "Custom", .ar = "مخصص", + .cs = "Vlastní", .de = "Benutzerdefiniert", .es = "Personalizado", .fr = "Personnalisé", .he = "מותאם אישית", + .id = "Kustom", .it = "Personalizzato", .ja = "カスタム", .ko = "사용자 정의", .pl = "Niestandardowy", .pt = "Personalizado", .ru = "Пользовательский", + .tr = "Özel", + .uk = "Власний", + .vi = "Tùy chỉnh", .zh_CN = "自定义", .zh_TW = "自訂", }, diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 46131bcd5..1a7b12f25 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -155,17 +155,22 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .displayName = { .en = "Date & Time", .ar = "التاريخ والوقت", + .cs = "Datum a čas", .de = "Datum & Uhrzeit", .es = "Fecha y hora", .fr = "Date et heure", .gl = "Data e hora", .he = "תאריך ושעה", + .id = "Tanggal & Waktu", .it = "Data e ora", .ja = "日付と時刻", .ko = "날짜/시간", .pl = "Data i godzina", .pt = "Data e hora", .ru = "Дата и время", + .tr = "Tarih ve Saat", + .uk = "Дата й час", + .vi = "Ngày giờ", .zh_CN = "日期时间", .zh_TW = "日期時間", }, diff --git a/src/modules/de/de.c b/src/modules/de/de.c index b1942d694..a7bb99c3a 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -87,17 +87,22 @@ FFModuleBaseInfo ffDEModuleInfo = { .displayName = { .en = "Desktop Environment", .ar = "بيئة سطح المكتب", + .cs = "Pracovní prostředí", .de = "Desktop-Umgebung", .es = "Entorno de escritorio", .fr = "Environnement de Bureau", .gl = "Contorno do Escritorio", .he = "סביבת שולחן עבודה", + .id = "Lingkungan Desktop", .it = "Ambiente Desktop", .ja = "デスクトップ環境", .ko = "데스크탑 환경", .pl = "Środowisko graficzne", .pt = "Ambiente de desktop", .ru = "Рабочее окружение", + .tr = "Masaüstü Ortamı", + .uk = "Стільниче середовище", + .vi = "Môi trường desktop", .zh_CN = "桌面环境", .zh_TW = "桌面環境", }, diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 2d80a18a5..da6fe9fab 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -456,17 +456,22 @@ FFModuleBaseInfo ffDiskModuleInfo = { .displayName = { .en = "Disk", .ar = "القرص", + .cs = "Disk", .de = "Festplatte", .es = "Disco", .fr = "Disque", .gl = "Disco", .he = "דיסק", + .id = "Disk", .it = "Disco", .ja = "ディスク", .ko = "디스크", .pl = "Dysk", .pt = "Disco", .ru = "Диск", + .tr = "Disk", + .uk = "Диск", + .vi = "Ổ đĩa", .zh_CN = "磁盘分区", .zh_TW = "硬碟分割", }, diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index e76f09364..71f6970d8 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -175,17 +175,22 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .displayName = { .en = "Disk I/O", .ar = "إدخال/إخراج القرص", + .cs = "Diskové I/O", .de = "Festplatten I/O", .es = "E/S del disco", .fr = "Entrée/Sortie disque", .gl = "E/S do disco", .he = "קלט/פלט דיסק", + .id = "I/O Disk", .it = "I/O del disco", .ja = "ディスク I/O", .ko = "디스크 I/O", .pl = "Dysk I/O", .pt = "Disco I/O", .ru = "Дисковый I/O", + .tr = "Disk G/Ç", + .uk = "Диск В/В", + .vi = "Đĩa I/O", .zh_CN = "磁盘 I/O", .zh_TW = "磁碟 I/O", }, diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 4eda35233..8d169d7db 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -416,17 +416,22 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .displayName = { .en = "Display", .ar = "الشاشة", + .cs = "Displej", .de = "Anzeige", .es = "Pantalla", .fr = "Écran", .gl = "Pantalla", .he = "תצוגה", + .id = "Tampilan", .it = "Display", .ja = "ディスプレイ", .ko = "디스플레이", .pl = "Wyświetlacz", .pt = "Tela", .ru = "Дисплей", + .tr = "Ekran", + .uk = "Дисплей", + .vi = "Hiển thị", .zh_CN = "显示器", .zh_TW = "顯示器", }, diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index c0f20d2c5..517deb4ad 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -139,17 +139,22 @@ FFModuleBaseInfo ffDNSModuleInfo = { .displayName = { .en = "DNS", .ar = "DNS", + .cs = "DNS", .de = "DNS", .es = "DNS", .fr = "DNS", .gl = "DNS", .he = "DNS", + .id = "DNS", .it = "DNS", .ja = "DNS", .ko = "DNS", .pl = "DNS", .pt = "DNS", .ru = "DNS", + .tr = "DNS", + .uk = "DNS", + .vi = "DNS", .zh_CN = "DNS", .zh_TW = "DNS", }, diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 7d04c8445..b55a24c69 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -108,17 +108,22 @@ FFModuleBaseInfo ffEditorModuleInfo = { .displayName = { .en = "Editor", .ar = "المحرر", + .cs = "Editor", .de = "Editor", .es = "Editor", .fr = "Éditeur", .gl = "Editor", .he = "עורך", + .id = "Editor", .it = "Editor", .ja = "エディター", .ko = "편집기", .pl = "Edytor", .pt = "Editor", .ru = "Редактор", + .tr = "Düzenleyici", + .uk = "Редактор", + .vi = "Trình soạn thảo", .zh_CN = "编辑器", .zh_TW = "編輯器", }, diff --git a/src/modules/font/font.c b/src/modules/font/font.c index dfbdd712f..47b6d8f2d 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -100,17 +100,22 @@ FFModuleBaseInfo ffFontModuleInfo = { .displayName = { .en = "Font", .ar = "الخط", + .cs = "Písmo", .de = "Schriftart", .es = "Fuente", .fr = "Police", .gl = "Fonte", .he = "גופן", + .id = "Font", .it = "Carattere", .ja = "フォント", .ko = "글꼴", .pl = "Czcionka", .pt = "Fonte", .ru = "Шрифт", + .tr = "Yazı Tipi", + .uk = "Шрифт", + .vi = "Phông chữ", .zh_CN = "字体", .zh_TW = "字型", }, diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index ae31b96cb..470abd8e3 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -194,17 +194,22 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .displayName = { .en = "Gamepad", .ar = "يد التحكم", + .cs = "Gamepad", .de = "Gamepad", .es = "Gamepad", .fr = "Manette", .gl = "Gamepad", .he = "משטח משחק", + .id = "Gamepad", .it = "Gamepad", .ja = "ゲームパッド", .ko = "게임패드", .pl = "Gamepad", .pt = "Gamepad", .ru = "Геймпад", + .tr = "Oyun Kumandası", + .uk = "Геймпад", + .vi = "Tay cầm chơi game", .zh_CN = "游戏手柄", .zh_TW = "遊戲手把", }, diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 1292a6256..159cbaf6b 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -484,17 +484,22 @@ FFModuleBaseInfo ffGPUModuleInfo = { .displayName = { .en = "GPU", .ar = "معالج الرسوميات", + .cs = "GPU", .de = "GPU", .es = "GPU", .fr = "GPU", .gl = "GPU", .he = "מעבד גרפי", + .id = "GPU", .it = "GPU", .ja = "GPU", .ko = "GPU", .pl = "GPU", .pt = "GPU", .ru = "Видеокарта", + .tr = "GPU", + .uk = "GPU", + .vi = "GPU", .zh_CN = "显卡", .zh_TW = "顯卡", }, diff --git a/src/modules/host/host.c b/src/modules/host/host.c index a79fbdc3b..ef7288776 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -141,17 +141,22 @@ FFModuleBaseInfo ffHostModuleInfo = { .displayName = { .en = "Host", .ar = "المضيف", + .cs = "Hostitel", .de = "Rechner", .es = "Host", .fr = "Hôte", .gl = "Host", .he = "מארח", + .id = "Host", .it = "Host", .ja = "ホスト", .ko = "호스트", .pl = "Host", .pt = "Host", .ru = "Модель", + .tr = "Ana Bilgisayar", + .uk = "Хост", + .vi = "Máy chủ", .zh_CN = "主机", .zh_TW = "主機", }, diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index c8b9d8cb4..358cc3dba 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -99,17 +99,22 @@ FFModuleBaseInfo ffIconsModuleInfo = { .displayName = { .en = "Icons", .ar = "الأيقونات", + .cs = "Ikony", .de = "Symbole", .es = "Iconos", .fr = "Icônes", .gl = "Iconas", .he = "סמלים", + .id = "Ikon", .it = "Icone", .ja = "アイコン", .ko = "아이콘", .pl = "Ikony", .pt = "Ícones", .ru = "Иконки", + .tr = "Simgeler", + .uk = "Піктограми", + .vi = "Biểu tượng", .zh_CN = "图标", .zh_TW = "圖示", }, diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index f5f4238fd..3b5db0d8b 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -106,17 +106,22 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .displayName = { .en = "Init System", .ar = "نظام الإقلاع", + .cs = "Init systém", .de = "Init-System", .es = "Sistema de inicio", .fr = "Système d'init", .gl = "Sistema de inicio", .he = "מערכת אתחול", + .id = "Sistem Init", .it = "Sistema di init", .ja = "initシステム", .ko = "초기화 시스템", .pl = "System init", .pt = "Sistema de inicialização", .ru = "Система инициализации", + .tr = "Init Sistemi", + .uk = "Init-система", + .vi = "Hệ thống init", .zh_CN = "Init 系统", .zh_TW = "Init 系統", }, diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 3e8334e2c..7c3165ac3 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -67,17 +67,22 @@ FFModuleBaseInfo ffKernelModuleInfo = { .displayName = { .en = "Kernel", .ar = "النواة", + .cs = "Jádro", .de = "Kernel", .es = "Kernel", .fr = "Kernel", .gl = "Kernel", .he = "ליבה", + .id = "Kernel", .it = "Kernel", .ja = "カーネル", .ko = "커널", .pl = "Jądro", .pt = "Kernel", .ru = "Ядро", + .tr = "Çekirdek", + .uk = "Ядро", + .vi = "Nhân", .zh_CN = "内核", .zh_TW = "核心", }, diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index df7b2cef6..b1ff75871 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -154,17 +154,22 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .displayName = { .en = "Keyboard", .ar = "لوحة المفاتيح", + .cs = "Klávesnice", .de = "Tastatur", .es = "Teclado", .fr = "Clavier", .gl = "Teclado", .he = "מקלדת", + .id = "Papan Ketik", .it = "Tastiera", .ja = "キーボード", .ko = "키보드", .pl = "Klawiatura", .pt = "Teclado", .ru = "Клавиатура", + .tr = "Klavye", + .uk = "Клавіатура", + .vi = "Bàn phím", .zh_CN = "键盘", .zh_TW = "鍵盤", }, diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 88b7b0ed4..ca9debe11 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -111,17 +111,22 @@ FFModuleBaseInfo ffLMModuleInfo = { .displayName = { .en = "Login Manager", .ar = "مدير تسجيل الدخول", + .cs = "Správce přihlášení", .de = "Anmeldemanager", .es = "Gestor de inicio de sesión", .fr = "Gestionnaire de connexion", .gl = "Xestor de inicio de sesión", .he = "מנהל התחברות", + .id = "Manajer Login", .it = "Gestore di accesso", .ja = "ログインマネージャー", .ko = "로그인 관리자", .pl = "Menedżer logowania", .pt = "Gerenciador de login", .ru = "Менеджер входа", + .tr = "Oturum Açma Yöneticisi", + .uk = "Менеджер входу", + .vi = "Trình quản lý đăng nhập", .zh_CN = "登录管理器", .zh_TW = "登入管理器", }, diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index a23c3edf6..40aa8115b 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -153,17 +153,22 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .displayName = { .en = "Load Average", .ar = "متوسط الحمل", + .cs = "Průměrná zátěž", .de = "Systemlast", .es = "Promedio de carga", .fr = "Charge moyenne", .gl = "Carga media", .he = "עומס ממוצע", + .id = "Beban Rata-rata", .it = "Carico medio", .ja = "ロードアベレージ", .ko = "시스템 부하 평균", .pl = "Średnie obciążenie", .pt = "Média de carga", .ru = "Средняя нагрузка", + .tr = "Sistem Yükü", + .uk = "Середнє навантаження", + .vi = "Tải trung bình", .zh_CN = "系统负载", .zh_TW = "系統負載", }, diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 835937a0e..4c91a04f5 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -72,17 +72,22 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .displayName = { .en = "Locale", .ar = "اللغة", + .cs = "Národní prostředí", .de = "Sprachraum", .es = "Configuración regional", .fr = "Paramètres régionaux", .gl = "Configuración rexional", .he = "לוקאל", + .id = "Lokal", .it = "Impostazioni locali", .ja = "ロケール", .ko = "로케일", .pl = "Ustawienia regionalne", .pt = "Configuração regional", .ru = "Локаль", + .tr = "Yerel Ayar", + .uk = "Локаль", + .vi = "Bản địa", .zh_CN = "语言环境", .zh_TW = "語言環境", }, diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 13a4692c7..c1c53be23 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -426,17 +426,22 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .displayName = { .en = "Local IP", .ar = "عنوان IP المحلي", + .cs = "Místní IP", .de = "Lokale IP", .es = "IP local", .fr = "IP locale", .gl = "IP local", .he = "IP מקומי", + .id = "IP Lokal", .it = "IP locale", .ja = "ローカル IP", .ko = "로컬 IP", .pl = "Lokalny adres IP", .pt = "IP local", .ru = "Локальный IP", + .tr = "Yerel IP", + .uk = "Локальна IP", + .vi = "IP cục bộ", .zh_CN = "本地 IP", .zh_TW = "區域 IP", }, diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 4f73084f9..dfa92ce06 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -82,17 +82,22 @@ FFModuleBaseInfo ffLogoModuleInfo = { .displayName = { .en = "Logo", .ar = "الشعار", + .cs = "Logo", .de = "Logo", .es = "Logo", .fr = "Logo", .gl = "Logo", .he = "לוגו", + .id = "Logo", .it = "Logo", .ja = "ロゴ", .ko = "로고", .pl = "Logo", .pt = "Logo", .ru = "Логотип", + .tr = "Logo", + .uk = "Логотип", + .vi = "Logo", .zh_CN = "徽标", .zh_TW = "標誌", }, diff --git a/src/modules/media/media.c b/src/modules/media/media.c index da5c13c42..6090e6eca 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -258,17 +258,22 @@ FFModuleBaseInfo ffMediaModuleInfo = { .displayName = { .en = "Media", .ar = "الوسائط", + .cs = "Média", .de = "Medien", .es = "Multimedia", .fr = "Médias", .gl = "Multimedia", .he = "מדיה", + .id = "Media", .it = "Media", .ja = "メディア", .ko = "미디어", .pl = "Media", .pt = "Mídia", .ru = "Медиа", + .tr = "Medya", + .uk = "Медіа", + .vi = "Phương tiện", .zh_CN = "媒体", .zh_TW = "媒體", }, diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index d338d177e..6e4092d22 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -123,17 +123,22 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .displayName = { .en = "Memory", .ar = "الذاكرة", + .cs = "Paměť", .de = "Speicher", .es = "Memoria", .fr = "Mémoire", .gl = "Memoria", .he = "זיכרון", + .id = "Memori", .it = "Memoria", .ja = "メモリ", .ko = "메모리", .pl = "Pamięć", .pt = "Memória", .ru = "Память", + .tr = "Bellek", + .uk = "Пам'ять", + .vi = "Bộ nhớ", .zh_CN = "内存", .zh_TW = "記憶體", }, diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 13cf74124..b5ac69f69 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -109,17 +109,22 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .displayName = { .en = "Monitor", .ar = "الشاشة", + .cs = "Monitor", .de = "Monitor", .es = "Monitor", .fr = "Moniteur", .gl = "Monitor", .he = "צג", + .id = "Monitor", .it = "Monitor", .ja = "モニター", .ko = "모니터", .pl = "Monitor", .pt = "Monitor", .ru = "Монитор", + .tr = "Monitör", + .uk = "Монітор", + .vi = "Màn hình", .zh_CN = "监视器", .zh_TW = "監視器", }, diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index f8f06a937..293f31931 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -157,17 +157,22 @@ FFModuleBaseInfo ffMouseModuleInfo = { .displayName = { .en = "Mouse", .ar = "الفأرة", + .cs = "Myš", .de = "Maus", .es = "Ratón", .fr = "Souris", .gl = "Rato", .he = "עכבר", + .id = "Tetikus", .it = "Mouse", .ja = "マウス", .ko = "마우스", .pl = "Mysz", .pt = "Mouse", .ru = "Мышь", + .tr = "Fare", + .uk = "Миша", + .vi = "Chuột", .zh_CN = "鼠标", .zh_TW = "滑鼠", }, diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 2bc95d615..0729b444e 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -202,17 +202,22 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .displayName = { .en = "Network I/O", .ar = "إدخال/إخراج الشبكة", + .cs = "Síťové I/O", .de = "Netzwerk I/O", .es = "E/S de la red", .fr = "E/S réseau", .gl = "E/S da rede", .he = "קלט/פלט רשת", + .id = "I/O Jaringan", .it = "I/O di rete", .ja = "ネットワークI/O", .ko = "네트워크 I/O", .pl = "I/O sieciowe", .pt = "E/S de rede", .ru = "Сетевой I/O", + .tr = "Ağ G/Ç", + .uk = "Мережа В/В", + .vi = "Mạng I/O", .zh_CN = "网络 I/O", .zh_TW = "網路 I/O", }, diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index c13c8c2d9..c483c430d 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -125,17 +125,22 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .displayName = { .en = "OpenCL", .ar = "OpenCL", + .cs = "OpenCL", .de = "OpenCL", .es = "OpenCL", .fr = "OpenCL", .gl = "OpenCL", .he = "OpenCL", + .id = "OpenCL", .it = "OpenCL", .ja = "OpenCL", .ko = "OpenCL", .pl = "OpenCL", .pt = "OpenCL", .ru = "OpenCL", + .tr = "OpenCL", + .uk = "OpenCL", + .vi = "OpenCL", .zh_CN = "OpenCL", .zh_TW = "OpenCL", }, diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 4b325cbec..0ef5472c8 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -132,17 +132,22 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .displayName = { .en = "OpenGL", .ar = "OpenGL", + .cs = "OpenGL", .de = "OpenGL", .es = "OpenGL", .fr = "OpenGL", .gl = "OpenGL", .he = "OpenGL", + .id = "OpenGL", .it = "OpenGL", .ja = "OpenGL", .ko = "OpenGL", .pl = "OpenGL", .pt = "OpenGL", .ru = "OpenGL", + .tr = "OpenGL", + .uk = "OpenGL", + .vi = "OpenGL", .zh_CN = "OpenGL", .zh_TW = "OpenGL", }, diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 51c89cbba..12dd2740a 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -177,17 +177,22 @@ FFModuleBaseInfo ffOSModuleInfo = { .displayName = { .en = "OS", .ar = "نظام التشغيل", + .cs = "OS", .de = "Betriebssystem", .es = "Sistema operativo", .fr = "Système d'exploitation", .gl = "Sistema operativo", .he = "מערכת הפעלה", + .id = "OS", .it = "Sistema operativo", .ja = "オペレーティングシステム", .ko = "운영 체제", .pl = "System operacyjny", .pt = "Sistema operacional", .ru = "Операционная система", + .tr = "İşletim Sistemi", + .uk = "ОС", + .vi = "Hệ điều hành", .zh_CN = "操作系统", .zh_TW = "操作系統", }, diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index fc39603b4..f31275a86 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -515,17 +515,22 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .displayName = { .en = "Packages", .ar = "الحزم", + .cs = "Balíčky", .de = "Pakete", .es = "Paquetes", .fr = "Paquets", .gl = "Paquetes", .he = "חבילות", + .id = "Paket", .it = "Pacchetti", .ja = "パッケージ", .ko = "패키지", .pl = "Pakiety", .pt = "Pacotes", .ru = "Пакеты", + .tr = "Paketler", + .uk = "Пакети", + .vi = "Gói phần mềm", .zh_CN = "软件包", .zh_TW = "軟體包", }, diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index a4e7bb0f8..3b396d1f7 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -268,17 +268,22 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .displayName = { .en = "Physical Disk", .ar = "القرص الفعلي", + .cs = "Fyzický disk", .de = "Physische Festplatte", .es = "Disco físico", .fr = "Disque physique", .gl = "Disco físico", .he = "דיסק פיזי", + .id = "Disk Fisik", .it = "Disco fisico", .ja = "物理ディスク", .ko = "물리 디스크", .pl = "Dysk fizyczny", .pt = "Disco físico", .ru = "Физический диск", + .tr = "Fiziksel Disk", + .uk = "Фізичний диск", + .vi = "Ổ đĩa vật lý", .zh_CN = "物理磁盘", .zh_TW = "物理磁碟", }, diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 4c9ee7001..a374422e6 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -162,17 +162,22 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .displayName = { .en = "Physical Memory", .ar = "الذاكرة الفعلية", + .cs = "Fyzická paměť", .de = "Physischer Speicher", .es = "Memoria física", .fr = "Mémoire physique", .gl = "Memoria física", .he = "זיכרון פיזי", + .id = "Memori Fisik", .it = "Memoria fisica", .ja = "物理メモリ", .ko = "물리 메모리", .pl = "Pamięć fizyczna", .pt = "Memória física", .ru = "Физическая память", + .tr = "Fiziksel Bellek", + .uk = "Фізична пам'ять", + .vi = "Bộ nhớ vật lý", .zh_CN = "物理内存", .zh_TW = "實體記憶體", }, diff --git a/src/modules/player/player.c b/src/modules/player/player.c index c5bdfcf13..1474494c2 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -112,17 +112,22 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .displayName = { .en = "Media Player", .ar = "مشغل الوسائط", + .cs = "Přehrávač médií", .de = "Medienplayer", .es = "Reproductor multimedia", .fr = "Lecteur multimédia", .gl = "Reprodutor multimedia", .he = "נגן מדיה", + .id = "Pemutar Media", .it = "Lettore multimediale", .ja = "メディアプレイヤー", .ko = "미디어 플레이어", .pl = "Odtwarzacz multimediów", .pt = "Reprodutor de mídia", .ru = "Медиаплеер", + .tr = "Medya Oynatıcı", + .uk = "Медіаплеєр", + .vi = "Trình phát phương tiện", .zh_CN = "媒体播放器", .zh_TW = "媒體播放器", }, diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 5d8d2e2c1..2174a1b26 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -113,17 +113,22 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .displayName = { .en = "Power Adapter", .ar = "محول الطاقة", + .cs = "Napájecí adaptér", .de = "Netzteil", .es = "Adaptador de corriente", .fr = "Adaptateur secteur", .gl = "Adaptador de corrente", .he = "מתאם מתח", + .id = "Adaptor Daya", .it = "Alimentatore", .ja = "電源アダプター", .ko = "전원 어댑터", .pl = "Zasilacz", .pt = "Fonte de alimentação", .ru = "Адаптер питания", + .tr = "Güç Adaptörü", + .uk = "Блок живлення", + .vi = "Bộ chuyển đổi nguồn", .zh_CN = "电源适配器", .zh_TW = "電源轉接器", }, diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index a73c2c463..428120456 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -68,17 +68,22 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .displayName = { .en = "Processes", .ar = "العمليات", + .cs = "Procesy", .de = "Prozesse", .es = "Procesos", .fr = "Processus", .gl = "Procesos", .he = "תהליכים", + .id = "Proses", .it = "Processi", .ja = "プロセス", .ko = "프로세스", .pl = "Procesy", .pt = "Processos", .ru = "Процессы", + .tr = "Süreçler", + .uk = "Процеси", + .vi = "Tiến trình", .zh_CN = "进程数", .zh_TW = "進程數", }, diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 110b0dfc8..e93f34e09 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -113,17 +113,22 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .displayName = { .en = "Public IP", .ar = "عنوان IP العام", + .cs = "Veřejná IP", .de = "Öffentliche IP", .es = "IP pública", .fr = "IP publique", .gl = "IP pública", .he = "IP ציבורי", + .id = "IP Publik", .it = "IP pubblica", .ja = "パブリックIP", .ko = "공용 IP", .pl = "Publiczne IP", .pt = "IP público", .ru = "Внешний IP", + .tr = "Genel IP", + .uk = "Публічна IP", + .vi = "IP công khai", .zh_CN = "公网 IP", .zh_TW = "公網 IP", }, diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 0c19a89cc..60ab8e1ce 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -126,17 +126,22 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .displayName = { .en = "Separator", .ar = "الفاصل", + .cs = "Oddělovač", .de = "Trennlinie", .es = "Separador", .fr = "Séparateur", .gl = "Separador", .he = "מפריד", + .id = "Pemisah", .it = "Separatore", .ja = "セパレーター", .ko = "구분선", .pl = "Separator", .pt = "Separador", .ru = "Разделитель", + .tr = "Ayraç", + .uk = "Роздільник", + .vi = "Dấu phân cách", .zh_CN = "分隔线", .zh_TW = "分隔線", }, diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index bce575b2a..849a905be 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -94,17 +94,22 @@ FFModuleBaseInfo ffShellModuleInfo = { .displayName = { .en = "Shell", .ar = "الصدفة", + .cs = "Shell", .de = "Shell", .es = "Shell", .fr = "Shell", .gl = "Shell", .he = "מעטפת", + .id = "Shell", .it = "Shell", .ja = "シェル", .ko = "셸", .pl = "Powłoka", .pt = "Shell", .ru = "Оболочка", + .tr = "Kabuk", + .uk = "Оболонка", + .vi = "Shell", .zh_CN = "命令行解释器", .zh_TW = "命令列直譯器", }, diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 0c6436833..dc506efb1 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -204,17 +204,22 @@ FFModuleBaseInfo ffSoundModuleInfo = { .displayName = { .en = "Sound", .ar = "الصوت", + .cs = "Zvuk", .de = "Sound", .es = "Sonido", .fr = "Son", .gl = "Son", .he = "קול", + .id = "Suara", .it = "Audio", .ja = "サウンド", .ko = "사운드", .pl = "Dźwięk", .pt = "Som", .ru = "Звук", + .tr = "Ses", + .uk = "Звук", + .vi = "Âm thanh", .zh_CN = "声音", .zh_TW = "聲音", }, diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 3848b62d0..7fe8b900b 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -187,17 +187,22 @@ FFModuleBaseInfo ffSwapModuleInfo = { .displayName = { .en = "Swap", .ar = "الذاكرة التبادلية", + .cs = "Odkládací prostor", .de = "Swap", .es = "Swap", .fr = "Swap", .gl = "Swap", .he = "זיכרון החלפה", + .id = "Swap", .it = "Swap", .ja = "スワップ", .ko = "스왑", .pl = "Swap", .pt = "Swap", .ru = "Подкачка", + .tr = "Takas", + .uk = "Своп", + .vi = "Swap", .zh_CN = "交换空间", .zh_TW = "交換空間", }, diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 80c901693..b13e32e9e 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -88,17 +88,22 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .displayName = { .en = "Terminal", .ar = "الطرفية", + .cs = "Terminál", .de = "Terminal", .es = "Terminal", .fr = "Terminal", .gl = "Terminal", .he = "טרמינל", + .id = "Terminal", .it = "Terminale", .ja = "ターミナル", .ko = "터미널", .pl = "Terminal", .pt = "Terminal", .ru = "Терминал", + .tr = "Terminal", + .uk = "Термінал", + .vi = "Terminal", .zh_CN = "终端", .zh_TW = "終端機", }, diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index d9e5a81f5..ecfb58548 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -108,17 +108,22 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .displayName = { .en = "Terminal Font", .ar = "خط الطرفية", + .cs = "Písmo terminálu", .de = "Terminalschriftart", .es = "Fuente del terminal", .fr = "Police du terminal", .gl = "Fonte do terminal", .he = "גופן טרמינל", + .id = "Font Terminal", .it = "Carattere del terminale", .ja = "ターミナルフォント", .ko = "터미널 글꼴", .pl = "Czcionka terminala", .pt = "Fonte do terminal", .ru = "Шрифт терминала", + .tr = "Terminal Yazı Tipi", + .uk = "Шрифт терміналу", + .vi = "Phông chữ Terminal", .zh_CN = "终端字体", .zh_TW = "終端機字型", }, diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 08c2c9de0..12470cd7a 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -79,16 +79,21 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .displayName = { .en = "Terminal Size", .ar = "حجم الطرفية", + .cs = "Velikost terminálu", .de = "Terminalgröße", .es = "Tamaño del terminal", .fr = "Taille du terminal", .he = "גודל טרמינל", + .id = "Ukuran Terminal", .it = "Dimensioni terminale", .ja = "ターミナルサイズ", .ko = "터미널 크기", .pl = "Rozmiar terminala", .pt = "Tamanho do terminal", .ru = "Размер терминала", + .tr = "Terminal Boyutu", + .uk = "Розмір терміналу", + .vi = "Kích thước Terminal", .zh_CN = "终端大小", .zh_TW = "終端機大小", }, diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index faa1ef285..a3daf4f42 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -96,17 +96,22 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .displayName = { .en = "Terminal Theme", .ar = "سمة الطرفية", + .cs = "Motiv terminálu", .de = "Terminalthema", .es = "Tema del terminal", .fr = "Thème du terminal", .gl = "Tema do terminal", .he = "ערכת נושא של טרמינל", + .id = "Tema Terminal", .it = "Tema del terminale", .ja = "ターミナルテーマ", .ko = "터미널 테마", .pl = "Motyw terminala", .pt = "Tema do terminal", .ru = "Тема терминала", + .tr = "Terminal Teması", + .uk = "Тема терміналу", + .vi = "Chủ đề Terminal", .zh_CN = "终端主题", .zh_TW = "終端機主題", }, diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 263dd9875..1f7917930 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -92,17 +92,22 @@ FFModuleBaseInfo ffThemeModuleInfo = { .displayName = { .en = "Theme", .ar = "السمة", + .cs = "Motiv", .de = "Thema", .es = "Tema", .fr = "Thème", .gl = "Tema", .he = "ערכת נושא", + .id = "Tema", .it = "Tema", .ja = "テーマ", .ko = "테마", .pl = "Motyw", .pt = "Tema", .ru = "Тема", + .tr = "Tema", + .uk = "Тема", + .vi = "Chủ đề", .zh_CN = "主题", .zh_TW = "主題", }, diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 3cad3941d..b5a7acace 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -181,17 +181,22 @@ FFModuleBaseInfo ffTitleModuleInfo = { .displayName = { .en = "Title", .ar = "العنوان", + .cs = "Titulek", .de = "Titel", .es = "Título", .fr = "Titre", .gl = "Título", .he = "כותרת", + .id = "Judul", .it = "Titolo", .ja = "タイトル", .ko = "제목", .pl = "Tytuł", .pt = "Título", .ru = "Заголовок", + .tr = "Başlık", + .uk = "Заголовок", + .vi = "Tiêu đề", .zh_CN = "标题", .zh_TW = "標題", }, diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 1e2e03f10..8902efe70 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -88,17 +88,22 @@ FFModuleBaseInfo ffTPMModuleInfo = { .displayName = { .en = "TPM", .ar = "TPM", + .cs = "TPM", .de = "TPM", .es = "TPM", .fr = "TPM", .gl = "TPM", .he = "TPM", + .id = "TPM", .it = "TPM", .ja = "TPM", .ko = "TPM", .pl = "TPM", .pt = "TPM", .ru = "TPM", + .tr = "TPM", + .uk = "TPM", + .vi = "TPM", .zh_CN = "TPM", .zh_TW = "TPM", }, diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 5937711bf..25b8d1f45 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -88,17 +88,22 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .displayName = { .en = "Uptime", .ar = "مدة التشغيل", + .cs = "Doba běhu", .de = "Betriebszeit", .es = "Tiempo de actividad", .fr = "Temps de fonctionnement", .gl = "Tempo de actividade", .he = "זמן פעילות", + .id = "Waktu Aktif", .it = "Tempo di attività", .ja = "稼働時間", .ko = "업타임", .pl = "Czas pracy", .pt = "Tempo de atividade", .ru = "Время работы", + .tr = "Çalışma Süresi", + .uk = "Час роботи", + .vi = "Thời gian hoạt động", .zh_CN = "运行时间", .zh_TW = "運行時間", }, diff --git a/src/modules/users/users.c b/src/modules/users/users.c index e381297ec..6f24527ed 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -185,17 +185,22 @@ FFModuleBaseInfo ffUsersModuleInfo = { .displayName = { .en = "Users", .ar = "المستخدمون", + .cs = "Uživatelé", .de = "Benutzer", .es = "Usuarios", .fr = "Utilisateurs", .gl = "Usuarios", .he = "משתמשים", + .id = "Pengguna", .it = "Utenti", .ja = "ユーザー", .ko = "사용자", .pl = "Użytkownicy", .pt = "Usuários", .ru = "Пользователи", + .tr = "Kullanıcılar", + .uk = "Користувачі", + .vi = "Người dùng", .zh_CN = "用户", .zh_TW = "使用者", }, diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 04fb1a6ff..13e6f52b0 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -99,17 +99,22 @@ FFModuleBaseInfo ffVersionModuleInfo = { .displayName = { .en = "Version", .ar = "الإصدار", + .cs = "Verze", .de = "Version", .es = "Versión", .fr = "Version", .gl = "Versión", .he = "גרסה", + .id = "Versi", .it = "Versione", .ja = "バージョン", .ko = "버전", .pl = "Wersja", .pt = "Versão", .ru = "Версия", + .tr = "Sürüm", + .uk = "Версія", + .vi = "Phiên bản", .zh_CN = "版本", .zh_TW = "版本", }, diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 4c2c8c85f..938c67e23 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -137,17 +137,22 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .displayName = { .en = "Vulkan", .ar = "Vulkan", + .cs = "Vulkan", .de = "Vulkan", .es = "Vulkan", .fr = "Vulkan", .gl = "Vulkan", .he = "Vulkan", + .id = "Vulkan", .it = "Vulkan", .ja = "Vulkan", .ko = "Vulkan", .pl = "Vulkan", .pt = "Vulkan", .ru = "Vulkan", + .tr = "Vulkan", + .uk = "Vulkan", + .vi = "Vulkan", .zh_CN = "Vulkan", .zh_TW = "Vulkan", }, diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index 472587d9a..38c7b204a 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -80,17 +80,22 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .displayName = { .en = "Wallpaper", .ar = "الخلفية", + .cs = "Tapeta", .de = "Hintergrundbild", .es = "Fondo de pantalla", .fr = "Fond d'écran", .gl = "Fondo de escritorio", .he = "טפט", + .id = "Wallpaper", .it = "Sfondo", .ja = "壁紙", .ko = "배경화면", .pl = "Tapeta", .pt = "Papel de parede", .ru = "Обои", + .tr = "Duvar Kağıdı", + .uk = "Шпалери", + .vi = "Hình nền", .zh_CN = "壁纸", .zh_TW = "桌布", }, diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 6878ab8d9..17753251c 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -97,17 +97,22 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .displayName = { .en = "Weather", .ar = "الطقس", + .cs = "Počasí", .de = "Wetter", .es = "Tiempo", .fr = "Météo", .gl = "Tempo", .he = "מזג אוויר", + .id = "Cuaca", .it = "Meteo", .ja = "天気", .ko = "날씨", .pl = "Pogoda", .pt = "Clima", .ru = "Погода", + .tr = "Hava Durumu", + .uk = "Погода", + .vi = "Thời tiết", .zh_CN = "天气", .zh_TW = "天氣", }, diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index a7ad22c22..c48e46f51 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -220,17 +220,22 @@ FFModuleBaseInfo ffWifiModuleInfo = { .displayName = { .en = "Wi-Fi", .ar = "واي فاي", + .cs = "Wi-Fi", .de = "WLAN", .es = "Wi-Fi", .fr = "Wi-Fi", .gl = "Wi-Fi", .he = "Wi-Fi", + .id = "Wi-Fi", .it = "Wi-Fi", .ja = "Wi-Fi", .ko = "와이파이", .pl = "Wi-Fi", .pt = "Wi-Fi", .ru = "Wi-Fi", + .tr = "Wi-Fi", + .uk = "Wi-Fi", + .vi = "Wi-Fi", .zh_CN = "无线网络", .zh_TW = "無線網路", }, diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 2812a97ce..c094e45c6 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -125,17 +125,22 @@ FFModuleBaseInfo ffWMModuleInfo = { .displayName = { .en = "Window Manager", .ar = "مدير النوافذ", + .cs = "Správce oken", .de = "Fenstermanager", .es = "Gestor de ventanas", .fr = "Gestionnaire de fenêtres", .gl = "Xestor de xanelas", .he = "מנהל חלונות", + .id = "Manajer Jendela", .it = "Gestore finestre", .ja = "ウィンドウマネージャー", .ko = "윈도우 관리자", .pl = "Menedżer okien", .pt = "Gerenciador de janelas", .ru = "Менеджер окон", + .tr = "Pencere Yöneticisi", + .uk = "Менеджер вікон", + .vi = "Trình quản lý cửa sổ", .zh_CN = "窗口管理器", .zh_TW = "視窗管理員", }, diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index f6f40979a..89caff388 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -64,17 +64,22 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .displayName = { .en = "WM Theme", .ar = "سمة مدير النوافذ", + .cs = "Motiv správce oken", .de = "Fenstermanager-Thema", .es = "Tema del gestor de ventanas", .fr = "Thème du gestionnaire de fenêtres", .gl = "Tema do xestor de xanelas", .he = "ערכת נושא של מנהל חלונות", + .id = "Tema Manajer Jendela", .it = "Tema del gestore finestre", .ja = "ウィンドウマネージャのテーマ", .ko = "윈도우 관리자 테마", .pl = "Motyw menedżera okien", .pt = "Tema do gerenciador de janelas", .ru = "Тема менеджера окон", + .tr = "WM Teması", + .uk = "Тема менеджера вікон", + .vi = "Chủ đề trình quản lý cửa sổ", .zh_CN = "窗口管理器主题", .zh_TW = "視窗管理員主題", }, diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 7657c9489..c974f9630 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -197,17 +197,22 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .displayName = { .en = "Zpool", .ar = "Zpool", + .cs = "Zpool", .de = "Zpool", .es = "Zpool", .fr = "Zpool", .gl = "Zpool", .he = "Zpool", + .id = "Zpool", .it = "Zpool", .ja = "Zpool", .ko = "Zpool", .pl = "Zpool", .pt = "Zpool", .ru = "Zpool", + .tr = "Zpool", + .uk = "Zpool", + .vi = "Zpool", .zh_CN = "Zpool", .zh_TW = "Zpool", }, diff --git a/src/options/display.c b/src/options/display.c index 0e6b7141c..3dbfce1ec 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -65,17 +65,22 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { switch (language->chars[0] << 8 | language->chars[1]) { case 'en': return offsetof(FFModuleDisplayName, en); case 'ar': return offsetof(FFModuleDisplayName, ar); + case 'cs': return offsetof(FFModuleDisplayName, cs); case 'de': return offsetof(FFModuleDisplayName, de); case 'es': return offsetof(FFModuleDisplayName, es); case 'fr': return offsetof(FFModuleDisplayName, fr); case 'gl': return offsetof(FFModuleDisplayName, gl); case 'he': return offsetof(FFModuleDisplayName, he); + case 'id': return offsetof(FFModuleDisplayName, id); case 'it': return offsetof(FFModuleDisplayName, it); case 'ja': return offsetof(FFModuleDisplayName, ja); case 'ko': return offsetof(FFModuleDisplayName, ko); case 'pl': return offsetof(FFModuleDisplayName, pl); case 'pt': return offsetof(FFModuleDisplayName, pt); case 'ru': return offsetof(FFModuleDisplayName, ru); + case 'tr': return offsetof(FFModuleDisplayName, tr); + case 'uk': return offsetof(FFModuleDisplayName, uk); + case 'vi': return offsetof(FFModuleDisplayName, vi); case 'zh': { if (ffStrbufEqualS(language, "zh_cn")) { return offsetof(FFModuleDisplayName, zh_CN); @@ -1276,6 +1281,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, ar): yyjson_mut_obj_add_str(doc, key, "language", "ar"); break; + case offsetof(FFModuleDisplayName, cs): + yyjson_mut_obj_add_str(doc, key, "language", "cs"); + break; case offsetof(FFModuleDisplayName, de): yyjson_mut_obj_add_str(doc, key, "language", "de"); break; @@ -1291,6 +1299,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, he): yyjson_mut_obj_add_str(doc, key, "language", "he"); break; + case offsetof(FFModuleDisplayName, id): + yyjson_mut_obj_add_str(doc, key, "language", "id"); + break; case offsetof(FFModuleDisplayName, it): yyjson_mut_obj_add_str(doc, key, "language", "it"); break; @@ -1309,6 +1320,15 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, ru): yyjson_mut_obj_add_str(doc, key, "language", "ru"); break; + case offsetof(FFModuleDisplayName, tr): + yyjson_mut_obj_add_str(doc, key, "language", "tr"); + break; + case offsetof(FFModuleDisplayName, uk): + yyjson_mut_obj_add_str(doc, key, "language", "uk"); + break; + case offsetof(FFModuleDisplayName, vi): + yyjson_mut_obj_add_str(doc, key, "language", "vi"); + break; case offsetof(FFModuleDisplayName, zh_CN): yyjson_mut_obj_add_str(doc, key, "language", "zh_CN"); break; From e7ecba4460e16b823c7036ecd5030482943884d9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Aug 2026 10:40:50 +0800 Subject: [PATCH 046/109] Doc: updates README [ci skip] --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eab173fc..ed5407df9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +# Unreleased + +Changes: +* The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations. + +Features: +* Added module key localization support. (General) + * Added a new option `--key-language ` (`display.key.language: ""` in JSON config). When left empty, it defaults to the system locale. + * See `fastfetch -h key-language` for all supported languages. +* Improved Wi-Fi module + * Added Wifi channel width detection, exposed via `{channel-width}` in custom format (reports 0 when not supported). + * Improved Wifi channel frequency accuracy and fortified detection on Windows, macOS. + * Added Wifi detection support on SunOS, Haiku. +* Added Battery detection support on SunOS. (Battery, SunOS) +* Added terminal font size detection support on Termux. (TerminalFont, Android) +* Improved GTK theme/icons/font detection on standalone WMs such as Hyprland, sway, niri and i3. (Theme, Linux) +* Improved fish completion scripts to print enum descriptions. (Completion) + +Bugfixes: +* Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO) +* Some internal cleanups and optimizations. + # 2.67.1 Bugfixes: From 6d5cb520eded8ce5be4343755a364e116b287f93 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Aug 2026 13:38:44 +0800 Subject: [PATCH 047/109] Logo (Builtin): adds artix2 in --- src/logo/ascii/a.inc | 12 +++++++++++ src/logo/ascii/a/artix2.txt | 40 ++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/logo/ascii/a.inc b/src/logo/ascii/a.inc index dfda555db..38ebae9b3 100644 --- a/src/logo/ascii/a.inc +++ b/src/logo/ascii/a.inc @@ -633,6 +633,18 @@ static const FFlogo A[] = { .colorTitle = FF_COLOR_FG_CYAN, }, #endif + #ifdef FASTFETCH_DATATEXT_LOGO_ARTIX2 + // Artix2 + { + .names = { "artix2" }, + .lines = FASTFETCH_DATATEXT_LOGO_ARTIX2, + .colors = { + FF_COLOR_FG_CYAN, + }, + .colorKeys = FF_COLOR_FG_CYAN, + .colorTitle = FF_COLOR_FG_CYAN, + }, + #endif #ifdef FASTFETCH_DATATEXT_LOGO_ARTIX_SMALL // ArtixSmall { diff --git a/src/logo/ascii/a/artix2.txt b/src/logo/ascii/a/artix2.txt index 0e87beb2e..68d839952 100644 --- a/src/logo/ascii/a/artix2.txt +++ b/src/logo/ascii/a/artix2.txt @@ -1,20 +1,20 @@ - .: - .==: - .====: - .======: - .========: - .==========: - .============: - .-===========: - .:-========: - .-:. .:======: - .======:.. :-===. - .============:.. .:=. - .==================:.. - .=======================: - .====================::. . - ================::. :-=== - ============-:. .:======== - ========-:. :-========== - =====:. ..:-===== - =::. ..:: + .: + .==: + .====: + .======: + .========: + .==========: + .============: + .-===========: + .:-========: + .-:. .:======: + .======:.. :-===. + .============:.. .:=. + .==================:.. + .=======================: + .====================::. . + ================::. :-=== + ============-:. .:======== + ========-:. :-========== + =====:. ..:-===== + =::. ..:: \ No newline at end of file From 5edda068f2e703508789e39ef643c89efada6529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 24 Aug 2026 20:58:33 +0800 Subject: [PATCH 048/109] =?UTF-8?q?PhysicalDisk=20(DragonFly):=20eliminate?= =?UTF-8?q?s=E2=80=8C=20compiler=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detection/physicaldisk/physicaldisk_bsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index cda7adda5..d17905388 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -122,6 +122,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } #else const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { + FF_UNUSED(result, options); return "Fastfetch was compiled without libgeom support"; } #endif From 83cc7a94a41266d315908a1afdb7f3dac4dd063c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 24 Aug 2026 16:05:36 +0800 Subject: [PATCH 049/109] Top: adds new module --- CMakeLists.txt | 13 ++ doc/json_schema.json | 77 ++++++++++- src/common/impl/commandoption.c | 8 ++ src/common/impl/jsonconfig.c | 10 ++ src/detection/top/top.c | 117 ++++++++++++++++ src/detection/top/top.h | 27 ++++ src/detection/top/top_apple.c | 57 ++++++++ src/detection/top/top_bsd.c | 67 ++++++++++ src/detection/top/top_dbsd.c | 67 ++++++++++ src/detection/top/top_gnu.c | 78 +++++++++++ src/detection/top/top_haiku.c | 47 +++++++ src/detection/top/top_linux.c | 126 ++++++++++++++++++ src/detection/top/top_nbsd.c | 65 +++++++++ src/detection/top/top_obsd.c | 44 ++++++ src/detection/top/top_sunos.c | 66 +++++++++ src/detection/top/top_windows.c | 48 +++++++ src/modules/modules.c | 3 + src/modules/modules.h | 1 + src/modules/options.h | 1 + src/modules/top/option.h | 23 ++++ src/modules/top/top.c | 229 ++++++++++++++++++++++++++++++++ src/modules/top/top.h | 11 ++ 22 files changed, 1183 insertions(+), 2 deletions(-) create mode 100644 src/detection/top/top.c create mode 100644 src/detection/top/top.h create mode 100644 src/detection/top/top_apple.c create mode 100644 src/detection/top/top_bsd.c create mode 100644 src/detection/top/top_dbsd.c create mode 100644 src/detection/top/top_gnu.c create mode 100644 src/detection/top/top_haiku.c create mode 100644 src/detection/top/top_linux.c create mode 100644 src/detection/top/top_nbsd.c create mode 100644 src/detection/top/top_obsd.c create mode 100644 src/detection/top/top_sunos.c create mode 100644 src/detection/top/top_windows.c create mode 100644 src/modules/top/option.h create mode 100644 src/modules/top/top.c create mode 100644 src/modules/top/top.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d4070af9..d8313c345 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -484,6 +484,7 @@ set(LIBFASTFETCH_SRC src/detection/physicalmemory/physicalmemory.c src/detection/publicip/publicip.c src/detection/terminaltheme/terminaltheme.c + src/detection/top/top.c src/detection/terminalfont/terminalfont.c src/detection/terminalshell/terminalshell.c src/detection/version/version.c @@ -559,6 +560,7 @@ set(LIBFASTFETCH_SRC src/modules/terminalsize/terminalsize.c src/modules/theme/theme.c src/modules/title/title.c + src/modules/top/top.c src/modules/tpm/tpm.c src/modules/uptime/uptime.c src/modules/users/users.c @@ -651,6 +653,7 @@ if(LINUX) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_linux.c src/detection/tpm/tpm_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c @@ -822,11 +825,13 @@ elseif(FreeBSD) if(DragonFly) list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_nosupport.c + src/detection/top/top_dbsd.c src/detection/wifi/wifi_nosupport.c ) else() list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_bsd.c + src/detection/top/top_bsd.c src/detection/wifi/wifi_bsd.c ) endif() @@ -904,6 +909,7 @@ elseif(NetBSD) src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c src/detection/tpm/tpm_nosupport.c + src/detection/top/top_nbsd.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -990,6 +996,7 @@ elseif(OpenBSD) src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c src/detection/tpm/tpm_nosupport.c + src/detection/top/top_obsd.c src/detection/uptime/uptime_bsd.c src/detection/users/users_obsd.c src/detection/wallpaper/wallpaper_linux.c @@ -1057,6 +1064,7 @@ elseif(APPLE) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_apple.c + src/detection/top/top_apple.c src/detection/tpm/tpm_apple.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c @@ -1149,6 +1157,7 @@ elseif(WIN32) src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c src/detection/theme/theme_windows.c + src/detection/top/top_windows.c src/detection/tpm/tpm_windows.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c @@ -1231,6 +1240,7 @@ elseif(SunOS) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_sunos.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c @@ -1301,6 +1311,7 @@ elseif(Haiku) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/top/top_haiku.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_haiku.c src/detection/users/users_linux.c @@ -1385,6 +1396,7 @@ elseif(GNU) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_gnu.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c @@ -1995,6 +2007,7 @@ elseif(SunOS) elseif(GNU) target_link_libraries(libfastfetch PRIVATE "m" + PRIVATE "ps" ) elseif(ANDROID) target_link_libraries(libfastfetch diff --git a/doc/json_schema.json b/doc/json_schema.json index 9e0aabc34..411cb9ce0 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -322,7 +322,7 @@ "type": "string" }, "cpuFormat": { - "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count\n 13. {code-name}: CPU code name\n 14. {technology}: CPU technology", + "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count", "type": "string" }, "cpucacheFormat": { @@ -505,6 +505,10 @@ "description": "Output format for the `Title` module. See Wiki for formatting syntax\n 1. {user-name}: User name\n 2. {host-name}: Host name\n 3. {home-dir}: Home directory\n 4. {exe-path}: Executable path of current process\n 5. {user-shell}: User's default shell\n 6. {user-name-colored}: User name (colored)\n 7. {at-symbol-colored}: @ symbol (colored)\n 8. {host-name-colored}: Host name (colored)\n 9. {full-user-name}: Full user name\n 10. {user-id}: UID (*nix) / SID (Windows)\n 11. {pid}: PID of current process\n 12. {cwd}: CWD with home dir replaced by `~`", "type": "string" }, + "topFormat": { + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second\n 7. {disk-write}: Disk write bytes per second\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", + "type": "string" + }, "themeFormat": { "description": "Output format for the `Theme` module. See Wiki for formatting syntax\n 1. {theme1}: Theme part 1\n 2. {theme2}: Theme part 2", "type": "string" @@ -542,7 +546,7 @@ "type": "string" }, "wifiFormat": { - "description": "Output format for the `Wifi` module. See Wiki for formatting syntax\n 1. {inf-desc}: Interface description\n 2. {inf-status}: Interface status\n 3. {status}: Connection status\n 4. {ssid}: Connection SSID\n 5. {bssid}: Connection BSSID\n 6. {protocol}: Connection protocol\n 7. {signal-quality}: Connection signal quality (percentage num)\n 8. {rx-rate}: Connection RX rate\n 9. {tx-rate}: Connection TX rate\n 10. {security}: Connection Security algorithm\n 11. {signal-quality-bar}: Connection signal quality (percentage bar)\n 12. {channel}: Connection channel number\n 13. {band}: Connection channel band in GHz", + "description": "Output format for the `Wifi` module. See Wiki for formatting syntax\n 1. {inf-desc}: Interface description\n 2. {inf-status}: Interface status\n 3. {status}: Connection status\n 4. {ssid}: Connection SSID\n 5. {bssid}: Connection BSSID\n 6. {protocol}: Connection protocol\n 7. {signal-quality}: Connection signal quality (percentage num)\n 8. {rx-rate}: Connection RX rate\n 9. {tx-rate}: Connection TX rate\n 10. {security}: Connection Security algorithm\n 11. {signal-quality-bar}: Connection signal quality (percentage bar)\n 12. {channel}: Connection channel number\n 13. {channel-width}: Connection channel width in MHz\n 14. {band}: Connection channel band in GHz", "type": "string" }, "wmthemeFormat": { @@ -1592,6 +1596,7 @@ "poweradapter", "processes", "publicip", + "top", "separator", "shell", "sound", @@ -4424,6 +4429,74 @@ } } }, + { + "title": "Top", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "const": "top", + "description": "Print processes with the highest CPU or memory usage" + }, + "sort": { + "type": "string", + "description": "Sort processes by CPU, memory or disk IO usage", + "enum": [ + "cpu", + "memory", + "disk-read", + "disk-write" + ], + "default": "cpu" + }, + "processes": { + "type": "integer", + "description": "Number of top processes to print", + "minimum": 1, + "default": 5 + }, + "waitTime": { + "type": "integer", + "description": "Wait time between process samples, in milliseconds", + "minimum": 1, + "default": 500 + }, + "compact": { + "type": "boolean", + "description": "Print all process on a single line", + "default": false + }, + "kernelTask": { + "type": "boolean", + "description": "Whether to include kernel tasks (kworker, System, kernel_task) in the process list", + "default": false + }, + "percent": { + "$ref": "#/$defs/percent" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyIcon": { + "$ref": "#/$defs/keyIcon" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "format": { + "$ref": "#/$defs/topFormat" + }, + "condition": { + "$ref": "#/$defs/conditions" + } + } + }, { "title": "TPM", "type": "object", diff --git a/src/common/impl/commandoption.c b/src/common/impl/commandoption.c index a8764d610..d8922a48e 100644 --- a/src/common/impl/commandoption.c +++ b/src/common/impl/commandoption.c @@ -111,6 +111,14 @@ void ffPrepareCommandOption(FFdata* data) { break; #endif + #if !FF_MODULE_DISABLE_TOP + case 'T': + case 't': + FF_IF_MODULE_MATCH(ffTopModuleInfo.name) + ffPrepareTopProcesses(); + break; + #endif + #if !FF_MODULE_DISABLE_WEATHER case 'W': case 'w': diff --git a/src/common/impl/jsonconfig.c b/src/common/impl/jsonconfig.c index 7c9d44a88..3d26e922e 100644 --- a/src/common/impl/jsonconfig.c +++ b/src/common/impl/jsonconfig.c @@ -195,6 +195,16 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { } #endif + #if !FF_MODULE_DISABLE_TOP + case 't': + case 'T': { + if (ffStrEqualsIgnCase(type, ffTopModuleInfo.name)) { + ffPrepareTopProcesses(); + } + break; + } + #endif + #if !FF_MODULE_DISABLE_WEATHER case 'w': case 'W': { diff --git a/src/detection/top/top.c b/src/detection/top/top.c new file mode 100644 index 000000000..659b47f0e --- /dev/null +++ b/src/detection/top/top.c @@ -0,0 +1,117 @@ +#include "top.h" + +#include "common/time.h" + +static FFlist first; +static double startTick; + +void ffPrepareTopProcesses(void) { + if (startTick != 0) { + return; // Already prepared + } + + ffListInit(&first); + startTick = ffTimeGetTick(); + ffTopGetProcessSnapshot(&first); +} + +// clang-format off +static int compareCpuResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->cpuPercent < b->cpuPercent) return 1; + if (a->cpuPercent > b->cpuPercent) return -1; + return (int) (a->pid - b->pid); +} + +static int compareMemoryResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->memBytes < b->memBytes) return 1; + if (a->memBytes > b->memBytes) return -1; + return (int) (a->pid - b->pid); +} + +static int compareDiskReadResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->bytesRead < b->bytesRead) return 1; + if (a->bytesRead > b->bytesRead) return -1; + return (int) (a->pid - b->pid); +} + +static int compareDiskWriteResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->bytesWritten < b->bytesWritten) return 1; + if (a->bytesWritten > b->bytesWritten) return -1; + return (int) (a->pid - b->pid); +} +// clang-format on + +const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { + ffListClear(result); + if (options->nProcesses == 0) { + return nullptr; + } + + if (startTick == 0) { + ffPrepareTopProcesses(); + } + + double elapsedTime = ffTimeGetTick() - startTick; + if (elapsedTime < (double) options->waitTime) { + ffTimeSleep(options->waitTime - (uint32_t) elapsedTime); + } + + if (first.length == 0) { + return "No processes found"; + } + + FF_LIST_AUTO_DESTROY second = ffListCreate(); + const char* error = ffTopGetProcessSnapshot(&second); + const double elapsed = ffTimeGetTick() - startTick; + + if (error || elapsed <= 0) { + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + ffStrbufDestroy(&item->name); + } + return error ?: "Invalid process sampling interval"; + } + + ffListInitA(result, sizeof(FFTopProcessResult), first.length < options->nProcesses ? first.length : options->nProcesses); + FF_LIST_FOR_EACH (FFTopProcessSnapshot, oldItem, first) { + FFTopProcessSnapshot* newItem = nullptr; + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + if (item->pid == oldItem->pid) { + newItem = item; + break; + } + } + if (!newItem || newItem->startTime != oldItem->startTime || newItem->cpuTime < oldItem->cpuTime || newItem->bytesRead < oldItem->bytesRead || newItem->bytesWritten < oldItem->bytesWritten) { + ffStrbufDestroy(&oldItem->name); + continue; + } + + FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); + item->pid = newItem->pid; + item->memBytes = newItem->memBytes; + item->bytesRead = (newItem->bytesRead - oldItem->bytesRead) * 1000u / (uint64_t) elapsed; + item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; + item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; + item->startTime = newItem->startTime; + ffStrbufInitMove(&item->name, &oldItem->name); + } + + const void* compare = options->sort == FF_TOP_SORT_DISK_WRITE ? (void*) compareDiskWriteResults + : options->sort == FF_TOP_SORT_DISK_READ ? (void*) compareDiskReadResults + : options->sort == FF_TOP_SORT_MEMORY ? (void*) compareMemoryResults + : (void*) compareCpuResults; + ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); + if (result->length > options->nProcesses) { + FFTopProcessResult* items = (FFTopProcessResult*) result->data; + for (uint32_t i = options->nProcesses; i < result->length; ++i) { + ffStrbufDestroy(&items[i].name); + } + result->length = options->nProcesses; + } + + // Reuse `second` as the baseline of the next call + ffListDestroy(&first); + ffListInitMove(&first, &second); + startTick = ffTimeGetTick(); + + return nullptr; +} diff --git a/src/detection/top/top.h b/src/detection/top/top.h new file mode 100644 index 000000000..b732a1fd6 --- /dev/null +++ b/src/detection/top/top.h @@ -0,0 +1,27 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/top/option.h" + +typedef struct FFTopProcessResult { + FFstrbuf name; + uint64_t startTime; + double cpuPercent; + uint64_t memBytes; + uint64_t bytesRead; + uint64_t bytesWritten; + uint32_t pid; +} FFTopProcessResult; + +typedef struct FFTopProcessSnapshot { + FFstrbuf name; // comm + uint64_t cpuTime; // user_time + system_time + uint64_t memBytes; // RSS + uint64_t bytesRead; // Physical storage read + uint64_t bytesWritten; // Physical storage written + uint64_t startTime; // Differs between platforms + uint32_t pid; +} FFTopProcessSnapshot; + +const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result); +const char* ffTopGetProcessSnapshot(FFlist* snapshots); diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c new file mode 100644 index 000000000..0fdcb00be --- /dev/null +++ b/src/detection/top/top_apple.c @@ -0,0 +1,57 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc); + struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + pid_t pid = proc->kp_proc.p_pid; + if (pid <= 0) { + continue; + } + + struct rusage_info_v2 rusage; + if (proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*) &rusage) != 0) { + continue; // The process may have exited + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + ffStrbufInitS(&item->name, proc->kp_proc.p_comm); + item->pid = (uint32_t) pid; + item->cpuTime = (rusage.ri_user_time + rusage.ri_system_time) / 1000000u; // ns -> ms + item->memBytes = rusage.ri_resident_size; + item->bytesRead = rusage.ri_diskio_bytesread; + item->bytesWritten = rusage.ri_diskio_byteswritten; + item->startTime = rusage.ri_proc_start_abstime; + } + + return nullptr; +} diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c new file mode 100644 index 000000000..87a67bba2 --- /dev/null +++ b/src/detection/top/top_bsd.c @@ -0,0 +1,67 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc); + struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + + if (proc->ki_flag & P_KPROC) { + continue; + } + + uint32_t pid = (uint32_t) proc->ki_pid; + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, proc->ki_comm); + item->pid = pid; + + uint64_t userMs = (uint64_t) proc->ki_rusage.ru_utime.tv_sec * 1000 + + (uint64_t) proc->ki_rusage.ru_utime.tv_usec / 1000; + uint64_t sysMs = (uint64_t) proc->ki_rusage.ru_stime.tv_sec * 1000 + + (uint64_t) proc->ki_rusage.ru_stime.tv_usec / 1000; + item->cpuTime = userMs + sysMs; + + item->memBytes = (uint64_t) proc->ki_rssize * (uint64_t) pageSize; + + item->startTime = (uint64_t) proc->ki_start.tv_sec * 1000 + + (uint64_t) proc->ki_start.tv_usec / 1000; + + item->bytesRead = (uint64_t) proc->ki_rusage.ru_inblock * DEV_BSIZE; + item->bytesWritten = (uint64_t) proc->ki_rusage.ru_oublock * DEV_BSIZE; + } + + return NULL; +} diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c new file mode 100644 index 000000000..872ba97f8 --- /dev/null +++ b/src/detection/top/top_dbsd.c @@ -0,0 +1,67 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc); + struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + + // Kernel threads are reported with P_SYSTEM flags and pid -1. + if ((proc->kp_flags & P_SYSTEM) || proc->kp_stat == SZOMB) { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, proc->kp_comm); + item->pid = (uint32_t) proc->kp_pid; + + // kp_ru only accounts for exited lwps; the cpu times of live lwps are + // kept in microseconds in kp_lwp.kl_uticks/kl_sticks (see calcru(9)). + uint64_t exitedMs = (uint64_t) (proc->kp_ru.ru_utime.tv_sec + proc->kp_ru.ru_stime.tv_sec) * 1000 + + (uint64_t) (proc->kp_ru.ru_utime.tv_usec + proc->kp_ru.ru_stime.tv_usec) / 1000; + uint64_t liveMs = (proc->kp_lwp.kl_uticks + proc->kp_lwp.kl_sticks) / 1000; + item->cpuTime = exitedMs + liveMs; + + item->memBytes = (uint64_t) proc->kp_vm_rssize * pageSize; + + item->startTime = (uint64_t) proc->kp_start.tv_sec * 1000 + + (uint64_t) proc->kp_start.tv_usec / 1000; + + item->bytesRead = (uint64_t) (proc->kp_ru.ru_inblock + proc->kp_lwp.kl_ru.ru_inblock) * DEV_BSIZE; + item->bytesWritten = (uint64_t) (proc->kp_ru.ru_oublock + proc->kp_lwp.kl_ru.ru_oublock) * DEV_BSIZE; + } + + return nullptr; +} diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c new file mode 100644 index 000000000..3545ddac0 --- /dev/null +++ b/src/detection/top/top_gnu.c @@ -0,0 +1,78 @@ +#include "top.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + struct ps_context* context = nullptr; + if (ps_context_create(getproc(), &context) != 0) { + return "ps_context_create(getproc()) failed"; + } + + const char* error = nullptr; + struct proc_stat_list* list = nullptr; + if (proc_stat_list_create(context, &list) != 0) { + error = "proc_stat_list_create() failed"; + goto done; + } + + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + error = "proc_stat_list_add_all() failed"; + goto done; + } + + // Flags that cannot be fetched for some process are simply left unset; + // each field must be checked before use. + if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { + error = "proc_stat_list_set_flags() failed"; + goto done; + } + + for (unsigned i = 0; i < list->num_procs; ++i) { + struct proc_stat* stat = list->proc_stats[i]; + + if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) { + continue; + } + if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + // There is no kernel-side comm on the Hurd; use the first argument. + ffStrbufInit(&item->name); + if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) { + size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat)); + ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat)); + } + if (item->name.length == 0) { + ffStrbufAppendS(&item->name, "(unknown)"); + } + + item->pid = (uint32_t) proc_stat_pid(stat); + + if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { + const task_basic_info_t info = proc_stat_task_basic_info(stat); + item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + + (uint64_t) info->user_time.microseconds / 1000 + + (uint64_t) info->system_time.seconds * 1000 + + (uint64_t) info->system_time.microseconds / 1000; + item->memBytes = (uint64_t) info->resident_size; + } + + // Neither process start times nor storage io counters are exposed by + // the Hurd; leave them zeroed. + item->startTime = 0; + item->bytesRead = 0; + item->bytesWritten = 0; + } + +done: + if (list) { + proc_stat_list_free(list); + } + ps_context_free(context); + return error; +} diff --git a/src/detection/top/top_haiku.c b/src/detection/top/top_haiku.c new file mode 100644 index 000000000..39efdb2b0 --- /dev/null +++ b/src/detection/top/top_haiku.c @@ -0,0 +1,47 @@ +#include "top.h" + +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int32 cookie = 0; + team_info team; + while (get_next_team_info(&cookie, &team) == B_OK) { + if (team.team == B_SYSTEM_TEAM) { + continue; // The kernel team + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, team.name); + + item->pid = (uint32_t) team.team; + + // User and kernel time of all threads of the team combined in microseconds. + item->cpuTime = 0; + team_usage_info usage; + if (get_team_usage_info(team.team, B_TEAM_USAGE_SELF, &usage) == B_OK) { + item->cpuTime = ((uint64_t) usage.user_time + (uint64_t) usage.kernel_time) / 1000; + } + + // Sum up the physically resident memory of all areas of the team; + // ram_size is the amount of physical pages committed to an area, + // whereas size is just its virtual reservation. + uint64_t memBytes = 0; + ssize_t areaCookie = 0; + area_info area; + while (get_next_area_info(team.team, &areaCookie, &area) == B_OK) { + memBytes += area.ram_size; + } + item->memBytes = memBytes; + + // start_time is microseconds since boot. + item->startTime = (uint64_t) team.start_time; + + // Storage io counters are not exposed by Haiku; leave them zeroed. + item->bytesRead = 0; + item->bytesWritten = 0; + } + + return nullptr; +} diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c new file mode 100644 index 000000000..81b53c957 --- /dev/null +++ b/src/detection/top/top_linux.c @@ -0,0 +1,126 @@ +#include "top.h" + +#include "common/io.h" +#include "common/memrchr.h" +#include "common/strutil.h" + +#include + +#define PF_KTHREAD 0x00200000 // defined in kernel include/linux/sched.h + +static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* result) { + const char* open = strchr(buffer, '('); + const char* close = (const char*) memrchr(buffer, ')', length); + if (!open || !close || close <= open || close + 2 >= buffer + length) { + return false; + } + + ffStrbufSetNS(&result->name, (uint32_t) (close - open - 1), open + 1); + const char* cursor = close + 2; // state, then fields 4.. + if (*cursor == '\0') { + return false; + } + ++cursor; + + uint64_t values[19]; + for (uint32_t field = 4; field <= 22; ++field) { + while (*cursor == ' ') { + ++cursor; + } + if (*cursor == '\0') { + return false; + } + char* end; + errno = 0; + unsigned long long value = strtoull(cursor, &end, 10); + if (end == cursor || errno == ERANGE) { + return false; + } + values[field - 4] = (uint64_t) value; + cursor = end; + } + + if (values[5] & PF_KTHREAD) { // values[5] is field 9 (flags) + return false; + } + + result->cpuTime = values[11] + values[12]; // user + system + result->startTime = values[18]; + return true; +} + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + const long ticks = sysconf(_SC_CLK_TCK); + const long pageSize = instance.state.platform.sysinfo.pageSize; + if (ticks <= 0 || pageSize <= 0) { + return "sysconf(_SC_CLK_TCK or _SC_PAGESIZE) failed"; + } + + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); + if (!dir) { + return "opendir(\"/proc\") failed"; + } + + int procfd = dirfd(dir); + + struct dirent* entry; + char statBuffer[4096]; + char statmBuffer[256]; + while ((entry = readdir(dir))) { + if (!entry->d_name[0] || !ffCharIsDigit(entry->d_name[0])) { + continue; + } + + unsigned long pid = strtoul(entry->d_name, nullptr, 10); + if (pid == 0 || pid > UINT32_MAX) { + continue; + } + + FF_AUTO_CLOSE_FD int subfd = openat(procfd, entry->d_name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) { + continue; + } + + ssize_t statLength; + if ((statLength = ffReadFileDataRelative(subfd, "stat", sizeof(statBuffer) - 1, statBuffer)) < 0) { + continue; + } + statBuffer[statLength] = '\0'; + + ssize_t statmLength; + if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { + continue; + } + statmBuffer[statmLength] = '\0'; + + char ioBuffer[512]; + ssize_t ioLength; + if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { + continue; + } + ioBuffer[ioLength] = '\0'; + + auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + ffStrbufInit(&snapshot->name); + if (!parseStat(statBuffer, (size_t) statLength, snapshot)) { + ffStrbufDestroy(&snapshot->name); + --snapshots->length; + continue; + } + + unsigned long long rssPages; + if (__builtin_expect(sscanf(statmBuffer, "%*llu %llu", &rssPages) != 1, false)) { + ffStrbufDestroy(&snapshot->name); + --snapshots->length; + continue; + } + + snapshot->pid = (uint32_t) pid; + snapshot->memBytes = rssPages * (uint64_t) pageSize; + snapshot->bytesRead = 0; + snapshot->bytesWritten = 0; + sscanf(ioBuffer, "rchar: %*" SCNu64 "\nwchar: %*" SCNu64 "\nsyscr: %*" SCNu64 "\nsyscw: %*" SCNu64 "\nread_bytes: %" SCNu64 "\nwrite_bytes: %" SCNu64, &snapshot->bytesRead, &snapshot->bytesWritten); + snapshot->cpuTime = snapshot->cpuTime * 1000u / (uint64_t) ticks; + } + return nullptr; +} diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c new file mode 100644 index 000000000..3fee77049 --- /dev/null +++ b/src/detection/top/top_nbsd.c @@ -0,0 +1,65 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc2* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc2); + struct kinfo_proc2* newProcesses = (struct kinfo_proc2*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc2[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc2)); + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc2* proc = &processes[i]; + + if ((proc->p_flag & P_SYSTEM) || !proc->p_uvalid) { // Kernel process or zombie + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, proc->p_comm); + item->pid = (uint32_t) proc->p_pid; + + uint64_t userMs = (uint64_t) proc->p_uutime_sec * 1000 + + (uint64_t) proc->p_uutime_usec / 1000; + uint64_t sysMs = (uint64_t) proc->p_ustime_sec * 1000 + + (uint64_t) proc->p_ustime_usec / 1000; + item->cpuTime = userMs + sysMs; + + item->memBytes = (uint64_t) proc->p_vm_rssize * (uint64_t) pageSize; + + item->startTime = (uint64_t) proc->p_ustart_sec * 1000 + + (uint64_t) proc->p_ustart_usec / 1000; + + item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; + item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + } + + return NULL; +} diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c new file mode 100644 index 000000000..99d7b0a8f --- /dev/null +++ b/src/detection/top/top_obsd.c @@ -0,0 +1,44 @@ +#include "top.h" + +#include +#include // DEV_BSIZE +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + if (!kd) { + return "kvm_open() failed"; + } + + int count = 0; + // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads + const struct kinfo_proc* processes = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); + if (!processes) { + kvm_close(kd); + return "kvm_getprocs() failed"; + } + + const uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (int i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + + if (!proc->p_uvalid) { // Zombie process; p_u* members are invalid + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + ffStrbufInitS(&item->name, proc->p_comm); + item->pid = (uint32_t) proc->p_pid; + item->cpuTime = ((uint64_t) proc->p_uutime_sec * 1000 + (uint64_t) proc->p_uutime_usec / 1000) + + ((uint64_t) proc->p_ustime_sec * 1000 + (uint64_t) proc->p_ustime_usec / 1000); + item->memBytes = (uint64_t) proc->p_vm_rssize * pageSize; + item->startTime = (uint64_t) proc->p_ustart_sec * 1000 + (uint64_t) proc->p_ustart_usec / 1000; + item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; + item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + } + + kvm_close(kd); + return nullptr; +} diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c new file mode 100644 index 000000000..b00ce50ce --- /dev/null +++ b/src/detection/top/top_sunos.c @@ -0,0 +1,66 @@ +#include "top.h" + +#include "common/io.h" +#include "common/strutil.h" + +#include +#include +#include // DEV_BSIZE + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/proc"); + if (!dirp) { + return "opendir(\"/proc\") failed"; + } + + int procfd = dirfd(dirp); + + struct dirent* dp; + while ((dp = readdir(dirp))) { + if (!ffCharIsDigit(dp->d_name[0])) { // Skip "." and ".." + continue; + } + + FF_AUTO_CLOSE_FD int subfd = openat(procfd, dp->d_name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) { + continue; + } + + // The data model of the returned structure depends on the data model of + // the calling process, not of the observed process. + psinfo_t psinfo; + if (ffReadFileDataRelative(subfd, "psinfo", sizeof(psinfo), &psinfo) != (ssize_t) sizeof(psinfo)) { + continue; // The process may have exited + } + + // pr_nlwp is zero for system processes and zombies + if (psinfo.pr_nlwp == 0 || psinfo.pr_lwp.pr_sname == 'Z') { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, psinfo.pr_fname); + + item->pid = (uint32_t) psinfo.pr_pid; + + item->cpuTime = (uint64_t) psinfo.pr_time.tv_sec * 1000 + + (uint64_t) psinfo.pr_time.tv_nsec / 1000000; + + item->memBytes = (uint64_t) psinfo.pr_rssize * 1024; + + item->startTime = (uint64_t) psinfo.pr_start.tv_sec * 1000 + + (uint64_t) psinfo.pr_start.tv_nsec / 1000000; + + prusage_t usage; + if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { + item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE; + item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE; + } else { + item->bytesRead = 0; + item->bytesWritten = 0; + } + } + + return nullptr; +} diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c new file mode 100644 index 000000000..b27ad962e --- /dev/null +++ b/src/detection/top/top_windows.c @@ -0,0 +1,48 @@ +#include "top.h" + +#include "common/mallocHelper.h" +#include "common/windows/unicode.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; + + // Multiple attempts in case processes change while + // we are in the middle of querying them. + ULONG size = 0; + for (int attempts = 0;; ++attempts) { + if (size) { + pstart = (SYSTEM_PROCESS_INFORMATION*) realloc(pstart, size); + assert(pstart); + } + NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, pstart, size, &size); + if (NT_SUCCESS(status)) { + break; + } else if (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 4) { + size += sizeof(SYSTEM_PROCESS_INFORMATION) * 5; + } else { + return "NtQuerySystemInformation(SystemProcessInformation) failed"; + } + } + + for (SYSTEM_PROCESS_INFORMATION* info = pstart;; info = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) info + info->NextEntryOffset)) { + uintptr_t pidValue = (uintptr_t) info->UniqueProcessId; + if (pidValue <= UINT32_MAX && info->CreateTime.QuadPart > 0) { + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + item->pid = (uint32_t) pidValue; + item->startTime = info->CreateTime.QuadPart > 0 ? (uint64_t) info->CreateTime.QuadPart : 0; + item->cpuTime = ((uint64_t) info->UserTime.QuadPart + (uint64_t) info->KernelTime.QuadPart) / 10000u; + item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize; + item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount; + item->bytesWritten = (uint64_t) info->IoCounters.WriteTransferCount; + ffStrbufInitNWS(&item->name, info->ImageName.Length / sizeof(wchar_t), info->ImageName.Buffer); + } + if (info->NextEntryOffset == 0) { + break; + } + } + return nullptr; +} diff --git a/src/modules/modules.c b/src/modules/modules.c index bcc4afdf4..ba4c95536 100644 --- a/src/modules/modules.c +++ b/src/modules/modules.c @@ -271,6 +271,9 @@ static FFModuleBaseInfo* T[] = { #if !FF_MODULE_DISABLE_TITLE &ffTitleModuleInfo, #endif +#if !FF_MODULE_DISABLE_TOP + &ffTopModuleInfo, +#endif #if !FF_MODULE_DISABLE_THEME &ffThemeModuleInfo, #endif diff --git a/src/modules/modules.h b/src/modules/modules.h index 37ee242f0..5d2cd99e8 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -64,6 +64,7 @@ #include "modules/terminaltheme/terminaltheme.h" #include "modules/theme/theme.h" #include "modules/title/title.h" +#include "modules/top/top.h" #include "modules/tpm/tpm.h" #include "modules/uptime/uptime.h" #include "modules/users/users.h" diff --git a/src/modules/options.h b/src/modules/options.h index 7cf98c127..3c0bd6ee8 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -64,6 +64,7 @@ #include "modules/terminaltheme/option.h" #include "modules/theme/option.h" #include "modules/title/option.h" +#include "modules/top/option.h" #include "modules/tpm/option.h" #include "modules/uptime/option.h" #include "modules/users/option.h" diff --git a/src/modules/top/option.h b/src/modules/top/option.h new file mode 100644 index 000000000..d40cff6fc --- /dev/null +++ b/src/modules/top/option.h @@ -0,0 +1,23 @@ +#pragma once + +#include "common/option.h" +#include "common/percent.h" + +typedef enum FFTopSortType { + FF_TOP_SORT_CPU = 0, + FF_TOP_SORT_MEMORY, + FF_TOP_SORT_DISK_READ, + FF_TOP_SORT_DISK_WRITE, +} FFTopSortType; + +typedef struct FFTopOptions { + FFModuleArgs moduleArgs; + FFTopSortType sort; + uint32_t nProcesses; + uint32_t waitTime; + FFPercentageModuleConfig percent; + bool compact; + bool kernelTask; // Whether to include kernel tasks (kworker, System, kernel_task) in the process list +} FFTopOptions; + +static_assert(sizeof(FFTopOptions) <= FF_OPTION_MAX_SIZE, "FFTopOptions size exceeds maximum allowed size"); diff --git a/src/modules/top/top.c b/src/modules/top/top.c new file mode 100644 index 000000000..a8b924fe3 --- /dev/null +++ b/src/modules/top/top.c @@ -0,0 +1,229 @@ +#include "common/jsonconfig.h" +#include "common/percent.h" +#include "common/printing.h" +#include "common/size.h" +#include "detection/top/top.h" +#include "modules/top/top.h" + +static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total, FFTopProcessResult* process) { + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + if (options->moduleArgs.outputFormat.length == 0) { + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); + ffStrbufAppendF(&output, "%s (%u) - ", process->name.chars, process->pid); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { + ffStrbufAppendS(&output, "CPU "); + ffPercentAppendNum(&output, process->cpuPercent, options->percent, false, &options->moduleArgs); + } + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { + ffStrbufAppendS(&output, " - MEM "); + ffSizeAppendNum(process->memBytes, &output); + ffStrbufAppendS(&output, " - DSK "); + ffSizeAppendNum(process->bytesRead, &output); + ffStrbufAppendS(&output, "/s / "); + ffSizeAppendNum(process->bytesWritten, &output); + ffStrbufAppendS(&output, "/s"); + } + ffStrbufPutTo(&output, stdout); + } else { + FF_STRBUF_AUTO_DESTROY cpuFormatted = ffStrbufCreate(); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { + ffPercentAppendNum(&cpuFormatted, process->cpuPercent, options->percent, false, &options->moduleArgs); + } + FF_STRBUF_AUTO_DESTROY memFormatted = ffStrbufCreate(); + ffSizeAppendNum(process->memBytes, &memFormatted); + FF_STRBUF_AUTO_DESTROY diskReadFormatted = ffStrbufCreate(); + ffSizeAppendNum(process->bytesRead, &diskReadFormatted); + ffStrbufAppendS(&diskReadFormatted, "/s"); + FF_STRBUF_AUTO_DESTROY diskWriteFormatted = ffStrbufCreate(); + ffSizeAppendNum(process->bytesWritten, &diskWriteFormatted); + ffStrbufAppendS(&diskWriteFormatted, "/s"); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), (uint8_t) index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ + FF_ARG(process->name, "name"), + FF_ARG(process->pid, "pid"), + FF_ARG(process->cpuPercent, "cpu"), + FF_ARG(process->memBytes, "mem"), + FF_ARG(process->bytesRead, "disk-read"), + FF_ARG(process->bytesWritten, "disk-write"), + FF_ARG(cpuFormatted, "cpu-percentage"), + FF_ARG(memFormatted, "mem-formatted"), + FF_ARG(diskReadFormatted, "disk-read-formatted"), + FF_ARG(diskWriteFormatted, "disk-write-formatted"), + })); + } +} + +bool ffPrintTop(FFTopOptions* options) { + FF_LIST_AUTO_DESTROY results = ffListCreate(); + const char* error = ffDetectTopProcesses(options, &results); + if (error) { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return false; + } + + if (!options->compact) { + FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { + printTopResult(options, (uint32_t) (process - (FFTopProcessResult*) results.data), results.length, process); + } + } else { + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { + ffStrbufWriteTo(&process->name, stdout); + if ((void*) process != results.data) { + putchar(' '); + } + } + } + + FF_LIST_FOR_EACH (FFTopProcessResult, item, results) { + ffStrbufDestroy(&item->name); + } + return true; +} + +void ffParseTopJsonObject(FFTopOptions* 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; + } + if (unsafe_yyjson_equals_str(key, "sort")) { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ + { "cpu", FF_TOP_SORT_CPU }, + { "memory", FF_TOP_SORT_MEMORY }, + { "disk-read", FF_TOP_SORT_DISK_READ }, + { "disk-write", FF_TOP_SORT_DISK_WRITE }, + {}, + }); + if (error) { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + } else { + options->sort = (FFTopSortType) value; + } + continue; + } else if (unsafe_yyjson_equals_str(key, "processes")) { + options->nProcesses = (uint32_t) yyjson_get_uint(val); + } else if (unsafe_yyjson_equals_str(key, "waitTime")) { + options->waitTime = (uint32_t) yyjson_get_uint(val); + } else if (unsafe_yyjson_equals_str(key, "compact")) { + options->compact = yyjson_get_bool(val); + } else if (ffPercentParseJsonObject(key, val, &options->percent)) { + continue; + } else { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + } + } +} + +void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + yyjson_mut_obj_add_str(doc, module, "type", "top"); + switch (options->sort) { + case FF_TOP_SORT_CPU: + yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); + break; + case FF_TOP_SORT_MEMORY: + yyjson_mut_obj_add_str(doc, module, "sort", "memory"); + break; + case FF_TOP_SORT_DISK_READ: + yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); + break; + case FF_TOP_SORT_DISK_WRITE: + yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); + break; + } + yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); + yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); + yyjson_mut_obj_add_bool(doc, module, "kernelTask", options->kernelTask); + ffPercentGenerateJsonConfig(doc, module, options->percent); +} + +bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { + FF_LIST_AUTO_DESTROY results = ffListCreate(); + const char* error = ffDetectTopProcesses(options, &results); + if (error) { + yyjson_mut_obj_add_str(doc, module, "error", error); + return false; + } + yyjson_mut_val* array = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { + yyjson_mut_val* item = yyjson_mut_arr_add_obj(doc, array); + yyjson_mut_obj_add_strbuf(doc, item, "name", &process->name); + yyjson_mut_obj_add_uint(doc, item, "pid", process->pid); + yyjson_mut_obj_add_real(doc, item, "cpuPercent", process->cpuPercent); + yyjson_mut_obj_add_uint(doc, item, "mem", process->memBytes); + yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); + yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); + yyjson_mut_obj_add_uint(doc, item, "startTime", process->startTime); + } + + FF_LIST_FOR_EACH (FFTopProcessResult, item, results) { + ffStrbufDestroy(&item->name); + } + return true; +} + +void ffInitTopOptions(FFTopOptions* options) { + ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); + options->sort = FF_TOP_SORT_CPU; + options->nProcesses = 5; + options->waitTime = 500; + options->compact = false; + options->kernelTask = false; + options->percent = (FFPercentageModuleConfig){ 50, 80, 0 }; +} + +void ffDestroyTopOptions(FFTopOptions* options) { + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTopModuleInfo = { + .name = "Top", + .description = "Print processes with the highest CPU, memory or disk I/O usage", + .displayName = { + .en = "Top Processes", + .ar = "أعلى العمليات", + .cs = "Nejvytíženější procesy", + .de = "Top-Prozesse", + .es = "Procesos principales", + .fr = "Processus principaux", + .gl = "Procesos principais", + .he = "התהליכים המובילים", + .id = "Proses teratas", + .it = "Processi principali", + .ja = "上位プロセス", + .ko = "상위 프로세스", + .pl = "Najaktywniejsze procesy", + .pt = "Processos principais", + .ru = "Топ процессов", + .tr = "En yoğun işlemler", + .uk = "Найактивніші процеси", + .vi = "Tiến trình hàng đầu", + .zh_CN = "进程排行", + .zh_TW = "進程排行", + }, + .initOptions = (void*) ffInitTopOptions, + .destroyOptions = (void*) ffDestroyTopOptions, + .parseJsonObject = (void*) ffParseTopJsonObject, + .printModule = (void*) ffPrintTop, + .generateJsonResult = (void*) ffGenerateTopJsonResult, + .generateJsonConfig = (void*) ffGenerateTopJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){ + { "Process name", "name" }, + { "Executable path", "path" }, + { "Process ID", "pid" }, + { "CPU usage", "cpu" }, + { "Memory usage (RSS) in bytes", "mem" }, + { "Disk read bytes per second", "disk-read" }, + { "Disk write bytes per second", "disk-write" }, + { "CPU usage percentage", "cpu-percentage" }, + { "Memory usage (RSS) formatted", "mem-formatted" }, + { "Disk read formatted", "disk-read-formatted" }, + { "Disk write formatted", "disk-write-formatted" }, + })), + .defaultOrder = 36, +}; diff --git a/src/modules/top/top.h b/src/modules/top/top.h new file mode 100644 index 000000000..144130fd6 --- /dev/null +++ b/src/modules/top/top.h @@ -0,0 +1,11 @@ +#pragma once + +#include "option.h" + +void ffPrepareTopProcesses(void); + +bool ffPrintTop(FFTopOptions* options); +void ffInitTopOptions(FFTopOptions* options); +void ffDestroyTopOptions(FFTopOptions* options); + +extern FFModuleBaseInfo ffTopModuleInfo; From b5897f784f2f87eeb98d2974b479bcacf09d7205 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 24 Aug 2026 22:43:37 +0800 Subject: [PATCH 050/109] Processes (GNU): uses native impl --- CMakeLists.txt | 2 +- src/detection/processes/processes_gnu.c | 33 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/detection/processes/processes_gnu.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d8313c345..94177dc51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1388,7 +1388,7 @@ elseif(GNU) src/detection/packages/packages_linux.c src/detection/packages/packages_nix.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_linux.c + src/detection/processes/processes_gnu.c src/detection/gtk_qt/qt.c src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c new file mode 100644 index 000000000..7dc739d2b --- /dev/null +++ b/src/detection/processes/processes_gnu.c @@ -0,0 +1,33 @@ +#include "processes.h" + +#include +#include + +const char* ffDetectProcesses(uint32_t* result) { + struct ps_context* context = nullptr; + if (ps_context_create(getproc(), &context) != 0) { + return "ps_context_create(getproc()) failed"; + } + + const char* error = nullptr; + struct proc_stat_list* list = nullptr; + if (proc_stat_list_create(context, &list) != 0) { + error = "proc_stat_list_create() failed"; + goto done; + } + + // No flags are needed; we only count the processes. + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + error = "proc_stat_list_add_all() failed"; + goto done; + } + + *result = (uint32_t) list->num_procs; + +done: + if (list) { + proc_stat_list_free(list); + } + ps_context_free(context); + return error; +} From a979d8ae818a310e900d509a17aaea857ad11a4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 18:07:14 +0000 Subject: [PATCH 051/109] CI: Bump the github-actions group with 4 updates Bumps the github-actions group with 4 updates: [cross-platform-actions/action](https://github.com/cross-platform-actions/action), [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request). Updates `cross-platform-actions/action` from 1.3.0 to 1.4.0 - [Release notes](https://github.com/cross-platform-actions/action/releases) - [Changelog](https://github.com/cross-platform-actions/action/blob/master/changelog.md) - [Commits](https://github.com/cross-platform-actions/action/compare/5ea7e8e4677bd726033a10b094ba1c5762b15dee...24ef01df165c76df1ed2b9f9e9212e78dc2fc963) Updates `github/codeql-action/init` from 4.37.6 to 4.37.7 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd) Updates `github/codeql-action/analyze` from 4.37.6 to 4.37.7 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd) Updates `signpath/github-action-submit-signing-request` from 2.2 to 2.3 - [Release notes](https://github.com/signpath/github-action-submit-signing-request/releases) - [Commits](https://github.com/signpath/github-action-submit-signing-request/compare/b9d91eadd323de506c0c81cf0c7fe7438f3360fd...c92b958760219087e01f8d67a1669ed57afe2627) --- updated-dependencies: - dependency-name: cross-platform-actions/action dependency-version: 1.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/init dependency-version: 4.37.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.37.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: signpath/github-action-submit-signing-request dependency-version: '2.3' dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-dragonfly-amd64.yml | 2 +- .github/workflows/build-freebsd-amd64.yml | 2 +- .github/workflows/build-haiku-amd64.yml | 2 +- .github/workflows/build-linux-hosts.yml | 4 ++-- .github/workflows/build-netbsd-amd64.yml | 2 +- .github/workflows/build-omnios-amd64.yml | 2 +- .github/workflows/build-openbsd-amd64.yml | 2 +- .github/workflows/build-windows-hosts.yml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-dragonfly-amd64.yml b/.github/workflows/build-dragonfly-amd64.yml index c036d0d9d..c3aec5d6e 100644 --- a/.github/workflows/build-dragonfly-amd64.yml +++ b/.github/workflows/build-dragonfly-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: dragonflybsd version: '6.4.2' diff --git a/.github/workflows/build-freebsd-amd64.yml b/.github/workflows/build-freebsd-amd64.yml index b75d67be8..1cbbcae4c 100644 --- a/.github/workflows/build-freebsd-amd64.yml +++ b/.github/workflows/build-freebsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: freebsd version: '15.1' diff --git a/.github/workflows/build-haiku-amd64.yml b/.github/workflows/build-haiku-amd64.yml index b85fef26e..41aa30680 100644 --- a/.github/workflows/build-haiku-amd64.yml +++ b/.github/workflows/build-haiku-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: haiku version: 'r1beta5' diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index bcd5069c4..612e7165f 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -52,7 +52,7 @@ jobs: - name: Initialize CodeQL if: inputs.arch == 'amd64' - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: languages: c @@ -64,7 +64,7 @@ jobs: - name: perform CodeQL analysis if: inputs.arch == 'amd64' - uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 - name: list features run: ./fastfetch --list-features diff --git a/.github/workflows/build-netbsd-amd64.yml b/.github/workflows/build-netbsd-amd64.yml index 9a6283a06..87a8dc497 100644 --- a/.github/workflows/build-netbsd-amd64.yml +++ b/.github/workflows/build-netbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: netbsd version: '10.1' diff --git a/.github/workflows/build-omnios-amd64.yml b/.github/workflows/build-omnios-amd64.yml index a473b0817..a72108088 100644 --- a/.github/workflows/build-omnios-amd64.yml +++ b/.github/workflows/build-omnios-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: omnios version: 'r151058' diff --git a/.github/workflows/build-openbsd-amd64.yml b/.github/workflows/build-openbsd-amd64.yml index a22919f69..9db8c4cef 100644 --- a/.github/workflows/build-openbsd-amd64.yml +++ b/.github/workflows/build-openbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: openbsd version: '7.9' diff --git a/.github/workflows/build-windows-hosts.yml b/.github/workflows/build-windows-hosts.yml index fa1b3b374..2ef399f97 100644 --- a/.github/workflows/build-windows-hosts.yml +++ b/.github/workflows/build-windows-hosts.yml @@ -94,7 +94,7 @@ jobs: - if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch' name: submit signing request - uses: signpath/github-action-submit-signing-request@b9d91eadd323de506c0c81cf0c7fe7438f3360fd # v2.2 + uses: signpath/github-action-submit-signing-request@c92b958760219087e01f8d67a1669ed57afe2627 # v2.3 with: api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' organization-id: '${{ vars.SIGNPATH_ORG_ID }}' From 143939f19b61ae65feaec12c7c95a2f3d813bf00 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 09:08:35 +0800 Subject: [PATCH 052/109] DE (Android): adds asus zenfone support Fixes #2541 --- src/detection/displayserver/displayserver_android.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index 13f5fab0e..d847c82ea 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -174,6 +174,11 @@ static bool detectDE(FFDisplayServerResult* ds) { ffStrbufPrependS(&ds->dePrettyName, "OxygenOS"); return true; } + if (ffSettingsGetAndroidProperty("ro.product.brand", &ds->dePrettyName) && ffStrbufEqualS(&ds->dePrettyName, "asus")) { + ffStrbufClear(&ds->dePrettyName); + ffSettingsGetAndroidProperty("ro.build.version.incremental", &ds->dePrettyName); + return true; + } if (ffSettingsGetAndroidProperty("ro.build.display.id", &ds->dePrettyName)) { if (ffStrbufStartsWithS(&ds->dePrettyName, "RedMagicOS")) { ffStrbufInsertNC(&ds->dePrettyName, strlen("RedMagicOS"), 1, ' '); From 880284fa9c308f01497f440390e617b4780cd2f4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 13:32:28 +0800 Subject: [PATCH 053/109] DisplayServer (Android): enables Wayland support Fixes #2530 --- CMakeLists.txt | 9 ++++++- .../displayserver/displayserver_android.c | 24 +++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94177dc51..c921b5501 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ endif() include(CMakeDependentOption) cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF) -cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF) +cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "ANDROID OR LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF) cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF) cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF) cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF) @@ -694,6 +694,13 @@ elseif(ANDROID) src/detection/physicalmemory/physicalmemory_nosupport.c src/detection/diskio/diskio_linux.c src/detection/displayserver/displayserver_android.c + src/detection/displayserver/linux/wayland/wayland.c + src/detection/displayserver/linux/wayland/global-output.c + src/detection/displayserver/linux/wayland/kde-output.c + src/detection/displayserver/linux/wayland/wl-output-protocol.c + src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c + src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c + src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/common.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index d847c82ea..4e666eb1d 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -192,13 +192,23 @@ static bool detectDE(FFDisplayServerResult* ds) { } void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { - const char* error = ffdsConnectXcbRandr(ds); - if (error) { - error = ffdsConnectXrandr(ds); - } - if (!error) { - ffdsDetectWMDE(ds); - return; + // Keep the same display-server preference as Linux: Wayland provides the + // richest output information, followed by XCB and XRandR. + if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) { + ffdsConnectWayland(ds); + + if (ds->displays.length == 0) { + ffdsConnectXcbRandr(ds); + } + + if (ds->displays.length == 0) { + ffdsConnectXrandr(ds); + } + + if (ds->displays.length > 0) { + ffdsDetectWMDE(ds); + return; + } } // https://source.android.com/docs/core/graphics/surfaceflinger-windowmanager From 55bfcd6d866e407df9776fc0612c61810bbaf934 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 13:35:32 +0800 Subject: [PATCH 054/109] Top (Android): fixes building --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c921b5501..7f4605509 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -736,6 +736,7 @@ elseif(ANDROID) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_linux.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c From f15a1e96ce7b7a12853c832561e2817421acb29b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 16:27:53 +0800 Subject: [PATCH 055/109] Top (Linux): don't error out when reading `/proc/pid/io` fails --- src/detection/top/top_linux.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 81b53c957..1c78c5e2b 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -1,5 +1,6 @@ #include "top.h" +#include "common/debug.h" #include "common/io.h" #include "common/memrchr.h" #include "common/strutil.h" @@ -12,12 +13,14 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r const char* open = strchr(buffer, '('); const char* close = (const char*) memrchr(buffer, ')', length); if (!open || !close || close <= open || close + 2 >= buffer + length) { + FF_DEBUG("parseStat: malformed stat content"); return false; } ffStrbufSetNS(&result->name, (uint32_t) (close - open - 1), open + 1); const char* cursor = close + 2; // state, then fields 4.. if (*cursor == '\0') { + FF_DEBUG("parseStat(%s): truncated after state field", result->name.chars); return false; } ++cursor; @@ -28,12 +31,14 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r ++cursor; } if (*cursor == '\0') { + FF_DEBUG("parseStat(%s): truncated at field %u", result->name.chars, field); return false; } char* end; errno = 0; unsigned long long value = strtoull(cursor, &end, 10); if (end == cursor || errno == ERANGE) { + FF_DEBUG("parseStat(%s): invalid number at field %u", result->name.chars, field); return false; } values[field - 4] = (uint64_t) value; @@ -41,6 +46,7 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r } if (values[5] & PF_KTHREAD) { // values[5] is field 9 (flags) + FF_DEBUG("Skip kernel thread: %s", result->name.chars); return false; } @@ -52,12 +58,14 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r const char* ffTopGetProcessSnapshot(FFlist* snapshots) { const long ticks = sysconf(_SC_CLK_TCK); const long pageSize = instance.state.platform.sysinfo.pageSize; + FF_DEBUG("Scanning /proc: clk_tck=%ld, pageSize=%ld", ticks, pageSize); if (ticks <= 0 || pageSize <= 0) { return "sysconf(_SC_CLK_TCK or _SC_PAGESIZE) failed"; } FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (!dir) { + FF_DEBUG("opendir(\"/proc\") failed: %s", strerror(errno)); return "opendir(\"/proc\") failed"; } @@ -73,22 +81,26 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { unsigned long pid = strtoul(entry->d_name, nullptr, 10); if (pid == 0 || pid > UINT32_MAX) { + FF_DEBUG("Skip invalid pid directory: %s", entry->d_name); continue; } FF_AUTO_CLOSE_FD int subfd = openat(procfd, entry->d_name, O_RDONLY | O_DIRECTORY); if (subfd < 0) { + FF_DEBUG("openat(/proc/%s) failed: %s", entry->d_name, strerror(errno)); continue; } ssize_t statLength; if ((statLength = ffReadFileDataRelative(subfd, "stat", sizeof(statBuffer) - 1, statBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/stat: %s", entry->d_name, strerror(errno)); continue; } statBuffer[statLength] = '\0'; ssize_t statmLength; if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/statm: %s", entry->d_name, strerror(errno)); continue; } statmBuffer[statmLength] = '\0'; @@ -96,7 +108,8 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { char ioBuffer[512]; ssize_t ioLength; if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { - continue; + FF_DEBUG("Failed to read /proc/%s/io: %s", entry->d_name, strerror(errno)); + ioLength = 0; } ioBuffer[ioLength] = '\0'; @@ -108,8 +121,9 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { continue; } - unsigned long long rssPages; - if (__builtin_expect(sscanf(statmBuffer, "%*llu %llu", &rssPages) != 1, false)) { + uint64_t rssPages; + if (__builtin_expect(sscanf(statmBuffer, "%*u %" SCNu64, &rssPages) != 1, false)) { + FF_DEBUG("Failed to parse statm of /proc/%lu", pid); ffStrbufDestroy(&snapshot->name); --snapshots->length; continue; @@ -119,8 +133,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { snapshot->memBytes = rssPages * (uint64_t) pageSize; snapshot->bytesRead = 0; snapshot->bytesWritten = 0; - sscanf(ioBuffer, "rchar: %*" SCNu64 "\nwchar: %*" SCNu64 "\nsyscr: %*" SCNu64 "\nsyscw: %*" SCNu64 "\nread_bytes: %" SCNu64 "\nwrite_bytes: %" SCNu64, &snapshot->bytesRead, &snapshot->bytesWritten); + if (ioLength > 0) { + sscanf(ioBuffer, "rchar: %*u\nwchar: %*u\nsyscr: %*u\nsyscw: %*u\nread_bytes: %" SCNu64 "\nwrite_bytes: %" SCNu64, &snapshot->bytesRead, &snapshot->bytesWritten); + } snapshot->cpuTime = snapshot->cpuTime * 1000u / (uint64_t) ticks; + FF_DEBUG( + "Captured process %u (%s): cpuTime=%" PRIu64 "ms, mem=%" PRIu64 "B, diskRead=%" PRIu64 "B, diskWrite=%" PRIu64 "B", + snapshot->pid, snapshot->name.chars, snapshot->cpuTime, snapshot->memBytes, snapshot->bytesRead, snapshot->bytesWritten); } + FF_DEBUG("Captured %u process snapshots in total", snapshots->length); return nullptr; } From 63d16ca854fc8795e9b1314baaf715b78525a5a9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 16:30:04 +0800 Subject: [PATCH 056/109] Top: removes option `kernelTask` (never implemented) --- doc/json_schema.json | 5 ----- src/modules/top/option.h | 1 - src/modules/top/top.c | 6 ++---- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 411cb9ce0..a34d00fcf 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -4466,11 +4466,6 @@ "description": "Print all process on a single line", "default": false }, - "kernelTask": { - "type": "boolean", - "description": "Whether to include kernel tasks (kworker, System, kernel_task) in the process list", - "default": false - }, "percent": { "$ref": "#/$defs/percent" }, diff --git a/src/modules/top/option.h b/src/modules/top/option.h index d40cff6fc..3b58118a2 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -17,7 +17,6 @@ typedef struct FFTopOptions { uint32_t waitTime; FFPercentageModuleConfig percent; bool compact; - bool kernelTask; // Whether to include kernel tasks (kworker, System, kernel_task) in the process list } FFTopOptions; static_assert(sizeof(FFTopOptions) <= FF_OPTION_MAX_SIZE, "FFTopOptions size exceeds maximum allowed size"); diff --git a/src/modules/top/top.c b/src/modules/top/top.c index a8b924fe3..b36a3a1cc 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -138,7 +138,6 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); - yyjson_mut_obj_add_bool(doc, module, "kernelTask", options->kernelTask); ffPercentGenerateJsonConfig(doc, module, options->percent); } @@ -173,7 +172,6 @@ void ffInitTopOptions(FFTopOptions* options) { options->nProcesses = 5; options->waitTime = 500; options->compact = false; - options->kernelTask = false; options->percent = (FFPercentageModuleConfig){ 50, 80, 0 }; } @@ -218,8 +216,8 @@ FFModuleBaseInfo ffTopModuleInfo = { { "Process ID", "pid" }, { "CPU usage", "cpu" }, { "Memory usage (RSS) in bytes", "mem" }, - { "Disk read bytes per second", "disk-read" }, - { "Disk write bytes per second", "disk-write" }, + { "Disk read bytes per second (0 if unsupported)", "disk-read" }, + { "Disk write bytes per second (0 if unsupported)", "disk-write" }, { "CPU usage percentage", "cpu-percentage" }, { "Memory usage (RSS) formatted", "mem-formatted" }, { "Disk read formatted", "disk-read-formatted" }, From b7d8c120150535fc4c0a26fa223f3fa3cfb02e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 18:23:02 +0800 Subject: [PATCH 057/109] CI: adds `top` module --- presets/all.jsonc | 1 + presets/ci.jsonc | 1 + 2 files changed, 2 insertions(+) diff --git a/presets/all.jsonc b/presets/all.jsonc index c9f951659..fdb33ac2b 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -19,6 +19,7 @@ "uptime", "loadavg", "processes", + "top", "packages", "shell", "editor", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 52eb9b442..bbc03613f 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -21,6 +21,7 @@ "uptime", "loadavg", "processes", + "top", "packages", "shell", "editor", From 4344aa2ff1c3943ac6aea6c78e1a2e3342cd5b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 20:08:06 +0800 Subject: [PATCH 058/109] Top: adds option `showType: ` --- doc/json_schema.json | 32 ++++++- src/common/impl/commandoption.c | 7 +- src/common/impl/jsonconfig.c | 7 +- src/detection/top/top.c | 148 +++++++++++++++++++----------- src/detection/top/top.h | 4 +- src/detection/top/top_apple.c | 2 +- src/detection/top/top_bsd.c | 2 +- src/detection/top/top_gnu.c | 156 ++++++++++++++++---------------- src/detection/top/top_haiku.c | 2 +- src/detection/top/top_linux.c | 30 +++--- src/detection/top/top_nbsd.c | 2 +- src/detection/top/top_obsd.c | 2 +- src/detection/top/top_sunos.c | 17 ++-- src/detection/top/top_windows.c | 2 +- src/modules/top/option.h | 17 ++-- src/modules/top/top.c | 121 ++++++++++++++++++------- src/modules/top/top.h | 2 +- 17 files changed, 349 insertions(+), 204 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index a34d00fcf..e948d9285 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -4449,6 +4449,36 @@ ], "default": "cpu" }, + "showTypes": { + "description": "Specify which resource usages are detected and displayed.\nIf memory is enabled is enabled alone, only a single process snapshot is taken and `waitTime` sampling wait is skipped", + "default": [ + "cpu", + "memory", + "disk" + ], + "oneOf": [ + { + "type": "string", + "enum": [ + "cpu", + "memory", + "disk" + ] + }, + { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "cpu", + "memory", + "disk" + ] + } + } + ] + }, "processes": { "type": "integer", "description": "Number of top processes to print", @@ -4457,7 +4487,7 @@ }, "waitTime": { "type": "integer", - "description": "Wait time between process samples, in milliseconds", + "description": "Wait time between process samples, in milliseconds. Ignored when showTypes contains \"memory\" only", "minimum": 1, "default": 500 }, diff --git a/src/common/impl/commandoption.c b/src/common/impl/commandoption.c index d8922a48e..fbbcc18db 100644 --- a/src/common/impl/commandoption.c +++ b/src/common/impl/commandoption.c @@ -114,8 +114,11 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_TOP case 'T': case 't': - FF_IF_MODULE_MATCH(ffTopModuleInfo.name) - ffPrepareTopProcesses(); + FF_IF_MODULE_MATCH(ffTopModuleInfo.name) { + [[gnu::cleanup(ffDestroyTopOptions)]] FFTopOptions options; + ffInitTopOptions(&options); + ffPrepareTopProcesses(options.showTypes); + } break; #endif diff --git a/src/common/impl/jsonconfig.c b/src/common/impl/jsonconfig.c index 3d26e922e..a7597ca40 100644 --- a/src/common/impl/jsonconfig.c +++ b/src/common/impl/jsonconfig.c @@ -199,7 +199,12 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { case 't': case 'T': { if (ffStrEqualsIgnCase(type, ffTopModuleInfo.name)) { - ffPrepareTopProcesses(); + [[gnu::cleanup(ffDestroyTopOptions)]] FFTopOptions options; + ffInitTopOptions(&options); + if (module) { + ffTopModuleInfo.parseJsonObject(&options, module); + } + ffPrepareTopProcesses(options.showTypes); } break; } diff --git a/src/detection/top/top.c b/src/detection/top/top.c index 659b47f0e..5c1b8b645 100644 --- a/src/detection/top/top.c +++ b/src/detection/top/top.c @@ -4,15 +4,29 @@ static FFlist first; static double startTick; +static FFTopTypes preparedShowTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; -void ffPrepareTopProcesses(void) { - if (startTick != 0) { +void ffPrepareTopProcesses(FFTopTypes showTypes) { + if ((showTypes & (FF_TOP_TYPE_CPU | FF_TOP_TYPE_DISK)) == 0) { + return; // Memory usage is instantaneous; no baseline snapshot is needed + } + + if (startTick != 0 && preparedShowTypes == showTypes) { return; // Already prepared } + if (startTick != 0) { + // The set of requested types changed; discard the stale baseline + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, first) { + ffStrbufDestroy(&item->name); + } + ffListDestroy(&first); + } + ffListInit(&first); startTick = ffTimeGetTick(); - ffTopGetProcessSnapshot(&first); + preparedShowTypes = showTypes; + ffTopGetProcessSnapshot(&first, showTypes); } // clang-format off @@ -47,57 +61,92 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { return nullptr; } - if (startTick == 0) { - ffPrepareTopProcesses(); - } + // Memory usage is instantaneous; when neither CPU time nor disk IO counters + // are requested, a single snapshot suffices and no sampling wait is needed. + const bool sampleOnce = (options->showTypes & (FF_TOP_TYPE_CPU | FF_TOP_TYPE_DISK)) == 0; - double elapsedTime = ffTimeGetTick() - startTick; - if (elapsedTime < (double) options->waitTime) { - ffTimeSleep(options->waitTime - (uint32_t) elapsedTime); - } - - if (first.length == 0) { - return "No processes found"; - } - - FF_LIST_AUTO_DESTROY second = ffListCreate(); - const char* error = ffTopGetProcessSnapshot(&second); - const double elapsed = ffTimeGetTick() - startTick; - - if (error || elapsed <= 0) { - FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { - ffStrbufDestroy(&item->name); - } - return error ?: "Invalid process sampling interval"; - } - - ffListInitA(result, sizeof(FFTopProcessResult), first.length < options->nProcesses ? first.length : options->nProcesses); - FF_LIST_FOR_EACH (FFTopProcessSnapshot, oldItem, first) { - FFTopProcessSnapshot* newItem = nullptr; - FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { - if (item->pid == oldItem->pid) { - newItem = item; - break; + if (sampleOnce) { + FF_LIST_AUTO_DESTROY snapshots = ffListCreate(); + const char* error = ffTopGetProcessSnapshot(&snapshots, options->showTypes); + if (error) { + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, snapshots) { + ffStrbufDestroy(&item->name); } + return error; } - if (!newItem || newItem->startTime != oldItem->startTime || newItem->cpuTime < oldItem->cpuTime || newItem->bytesRead < oldItem->bytesRead || newItem->bytesWritten < oldItem->bytesWritten) { - ffStrbufDestroy(&oldItem->name); - continue; + if (snapshots.length == 0) { + return "No processes found"; } - FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); - item->pid = newItem->pid; - item->memBytes = newItem->memBytes; - item->bytesRead = (newItem->bytesRead - oldItem->bytesRead) * 1000u / (uint64_t) elapsed; - item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; - item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; - item->startTime = newItem->startTime; - ffStrbufInitMove(&item->name, &oldItem->name); + FF_LIST_FOR_EACH (FFTopProcessSnapshot, snap, snapshots) { + FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); + item->pid = snap->pid; + item->memBytes = snap->memBytes; + item->bytesRead = 0; + item->bytesWritten = 0; + item->cpuPercent = 0; + item->startTime = snap->startTime; + ffStrbufInitMove(&item->name, &snap->name); + } + } else { + if (startTick == 0 || preparedShowTypes != options->showTypes) { + ffPrepareTopProcesses(options->showTypes); + } + + double elapsedTime = ffTimeGetTick() - startTick; + if (elapsedTime < (double) options->waitTime) { + ffTimeSleep(options->waitTime - (uint32_t) elapsedTime); + } + + if (first.length == 0) { + return "No processes found"; + } + + ffListReserve(result, sizeof(FFTopProcessResult), first.length < options->nProcesses ? first.length : options->nProcesses); + + FF_LIST_AUTO_DESTROY second = ffListCreateA(sizeof(FFTopProcessSnapshot), first.length); + const char* error = ffTopGetProcessSnapshot(&second, options->showTypes); + const double elapsed = ffTimeGetTick() - startTick; + + if (error || elapsed <= 0) { + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + ffStrbufDestroy(&item->name); + } + return error ?: "Invalid process sampling interval"; + } + + FF_LIST_FOR_EACH (FFTopProcessSnapshot, oldItem, first) { + FFTopProcessSnapshot* newItem = nullptr; + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + if (item->pid == oldItem->pid) { + newItem = item; + break; + } + } + if (!newItem || newItem->startTime != oldItem->startTime || newItem->cpuTime < oldItem->cpuTime || newItem->bytesRead < oldItem->bytesRead || newItem->bytesWritten < oldItem->bytesWritten) { + ffStrbufDestroy(&oldItem->name); + continue; + } + + FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); + item->pid = newItem->pid; + item->memBytes = newItem->memBytes; + item->bytesRead = (newItem->bytesRead - oldItem->bytesRead) * 1000u / (uint64_t) elapsed; + item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; + item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; + item->startTime = newItem->startTime; + ffStrbufInitMove(&item->name, &oldItem->name); + } + + // Reuse `second` as the baseline of the next call + ffListDestroy(&first); + ffListInitMove(&first, &second); + startTick = ffTimeGetTick(); } - const void* compare = options->sort == FF_TOP_SORT_DISK_WRITE ? (void*) compareDiskWriteResults - : options->sort == FF_TOP_SORT_DISK_READ ? (void*) compareDiskReadResults - : options->sort == FF_TOP_SORT_MEMORY ? (void*) compareMemoryResults + const void* compare = options->sort == FF_TOP_TYPE_DISK_WRITE ? (void*) compareDiskWriteResults + : options->sort == FF_TOP_TYPE_DISK_READ ? (void*) compareDiskReadResults + : options->sort == FF_TOP_TYPE_MEMORY ? (void*) compareMemoryResults : (void*) compareCpuResults; ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); if (result->length > options->nProcesses) { @@ -108,10 +157,5 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { result->length = options->nProcesses; } - // Reuse `second` as the baseline of the next call - ffListDestroy(&first); - ffListInitMove(&first, &second); - startTick = ffTimeGetTick(); - return nullptr; } diff --git a/src/detection/top/top.h b/src/detection/top/top.h index b732a1fd6..de1289b4a 100644 --- a/src/detection/top/top.h +++ b/src/detection/top/top.h @@ -5,11 +5,11 @@ typedef struct FFTopProcessResult { FFstrbuf name; - uint64_t startTime; double cpuPercent; uint64_t memBytes; uint64_t bytesRead; uint64_t bytesWritten; + uint64_t startTime; uint32_t pid; } FFTopProcessResult; @@ -24,4 +24,4 @@ typedef struct FFTopProcessSnapshot { } FFTopProcessSnapshot; const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result); -const char* ffTopGetProcessSnapshot(FFlist* snapshots); +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes); diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index 0fdcb00be..fc8f5c998 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c index 87a67bba2..620b234b1 100644 --- a/src/detection/top/top_bsd.c +++ b/src/detection/top/top_bsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; size_t length; diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 3545ddac0..9bbe37aff 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -1,78 +1,78 @@ -#include "top.h" - -#include -#include -#include - -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { - struct ps_context* context = nullptr; - if (ps_context_create(getproc(), &context) != 0) { - return "ps_context_create(getproc()) failed"; - } - - const char* error = nullptr; - struct proc_stat_list* list = nullptr; - if (proc_stat_list_create(context, &list) != 0) { - error = "proc_stat_list_create() failed"; - goto done; - } - - if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { - error = "proc_stat_list_add_all() failed"; - goto done; - } - - // Flags that cannot be fetched for some process are simply left unset; - // each field must be checked before use. - if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { - error = "proc_stat_list_set_flags() failed"; - goto done; - } - - for (unsigned i = 0; i < list->num_procs; ++i) { - struct proc_stat* stat = list->proc_stats[i]; - - if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) { - continue; - } - if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) { - continue; - } - - FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); - - // There is no kernel-side comm on the Hurd; use the first argument. - ffStrbufInit(&item->name); - if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) { - size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat)); - ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat)); - } - if (item->name.length == 0) { - ffStrbufAppendS(&item->name, "(unknown)"); - } - - item->pid = (uint32_t) proc_stat_pid(stat); - - if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { - const task_basic_info_t info = proc_stat_task_basic_info(stat); - item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + - (uint64_t) info->user_time.microseconds / 1000 + - (uint64_t) info->system_time.seconds * 1000 + - (uint64_t) info->system_time.microseconds / 1000; - item->memBytes = (uint64_t) info->resident_size; - } - - // Neither process start times nor storage io counters are exposed by - // the Hurd; leave them zeroed. - item->startTime = 0; - item->bytesRead = 0; - item->bytesWritten = 0; - } - -done: - if (list) { - proc_stat_list_free(list); - } - ps_context_free(context); - return error; -} +#include "top.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { + struct ps_context* context = nullptr; + if (ps_context_create(getproc(), &context) != 0) { + return "ps_context_create(getproc()) failed"; + } + + const char* error = nullptr; + struct proc_stat_list* list = nullptr; + if (proc_stat_list_create(context, &list) != 0) { + error = "proc_stat_list_create() failed"; + goto done; + } + + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + error = "proc_stat_list_add_all() failed"; + goto done; + } + + // Flags that cannot be fetched for some process are simply left unset; + // each field must be checked before use. + if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { + error = "proc_stat_list_set_flags() failed"; + goto done; + } + + for (unsigned i = 0; i < list->num_procs; ++i) { + struct proc_stat* stat = list->proc_stats[i]; + + if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) { + continue; + } + if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + // There is no kernel-side comm on the Hurd; use the first argument. + ffStrbufInit(&item->name); + if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) { + size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat)); + ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat)); + } + if (item->name.length == 0) { + ffStrbufAppendS(&item->name, "(unknown)"); + } + + item->pid = (uint32_t) proc_stat_pid(stat); + + if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { + const task_basic_info_t info = proc_stat_task_basic_info(stat); + item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + + (uint64_t) info->user_time.microseconds / 1000 + + (uint64_t) info->system_time.seconds * 1000 + + (uint64_t) info->system_time.microseconds / 1000; + item->memBytes = (uint64_t) info->resident_size; + } + + // Neither process start times nor storage io counters are exposed by + // the Hurd; leave them zeroed. + item->startTime = 0; + item->bytesRead = 0; + item->bytesWritten = 0; + } + +done: + if (list) { + proc_stat_list_free(list); + } + ps_context_free(context); + return error; +} diff --git a/src/detection/top/top_haiku.c b/src/detection/top/top_haiku.c index 39efdb2b0..78310737a 100644 --- a/src/detection/top/top_haiku.c +++ b/src/detection/top/top_haiku.c @@ -3,7 +3,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int32 cookie = 0; team_info team; while (get_next_team_info(&cookie, &team) == B_OK) { diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 1c78c5e2b..28349a17d 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -55,7 +55,7 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r return true; } -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { const long ticks = sysconf(_SC_CLK_TCK); const long pageSize = instance.state.platform.sysinfo.pageSize; FF_DEBUG("Scanning /proc: clk_tck=%ld, pageSize=%ld", ticks, pageSize); @@ -98,20 +98,24 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { } statBuffer[statLength] = '\0'; - ssize_t statmLength; - if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { - FF_DEBUG("Failed to read /proc/%s/statm: %s", entry->d_name, strerror(errno)); - continue; + ssize_t statmLength = 0; + if (showTypes & FF_TOP_TYPE_MEMORY) { + if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/statm: %s", entry->d_name, strerror(errno)); + statmLength = 0; + } + statmBuffer[statmLength] = '\0'; } - statmBuffer[statmLength] = '\0'; char ioBuffer[512]; - ssize_t ioLength; - if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { - FF_DEBUG("Failed to read /proc/%s/io: %s", entry->d_name, strerror(errno)); - ioLength = 0; + ssize_t ioLength = 0; + if (showTypes & FF_TOP_TYPE_DISK) { + if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/io: %s", entry->d_name, strerror(errno)); + ioLength = 0; + } + ioBuffer[ioLength] = '\0'; } - ioBuffer[ioLength] = '\0'; auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInit(&snapshot->name); @@ -121,8 +125,8 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { continue; } - uint64_t rssPages; - if (__builtin_expect(sscanf(statmBuffer, "%*u %" SCNu64, &rssPages) != 1, false)) { + uint64_t rssPages = 0; + if (__builtin_expect((showTypes & FF_TOP_TYPE_MEMORY) && sscanf(statmBuffer, "%*u %" SCNu64, &rssPages) != 1, false)) { FF_DEBUG("Failed to parse statm of /proc/%lu", pid); ffStrbufDestroy(&snapshot->name); --snapshots->length; diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c index 3fee77049..277354ed3 100644 --- a/src/detection/top/top_nbsd.c +++ b/src/detection/top/top_nbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length; diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c index 99d7b0a8f..f7519bd00 100644 --- a/src/detection/top/top_obsd.c +++ b/src/detection/top/top_obsd.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); if (!kd) { return "kvm_open() failed"; diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c index b00ce50ce..f7e6a5f68 100644 --- a/src/detection/top/top_sunos.c +++ b/src/detection/top/top_sunos.c @@ -7,7 +7,7 @@ #include #include // DEV_BSIZE -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/proc"); if (!dirp) { return "opendir(\"/proc\") failed"; @@ -52,13 +52,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { item->startTime = (uint64_t) psinfo.pr_start.tv_sec * 1000 + (uint64_t) psinfo.pr_start.tv_nsec / 1000000; - prusage_t usage; - if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { - item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE; - item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE; - } else { - item->bytesRead = 0; - item->bytesWritten = 0; + item->bytesRead = 0; + item->bytesWritten = 0; + if (showTypes & FF_TOP_TYPE_DISK) { + prusage_t usage; + if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { + item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE; + item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE; + } } } diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index b27ad962e..59a5ab98d 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -7,7 +7,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; // Multiple attempts in case processes change while diff --git a/src/modules/top/option.h b/src/modules/top/option.h index 3b58118a2..82a138273 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -3,16 +3,19 @@ #include "common/option.h" #include "common/percent.h" -typedef enum FFTopSortType { - FF_TOP_SORT_CPU = 0, - FF_TOP_SORT_MEMORY, - FF_TOP_SORT_DISK_READ, - FF_TOP_SORT_DISK_WRITE, -} FFTopSortType; +typedef enum FFTopTypes: uint8_t { + FF_TOP_TYPE_CPU = 1 << 0, + FF_TOP_TYPE_MEMORY = 1 << 1, + FF_TOP_TYPE_DISK_READ = 1 << 2, + FF_TOP_TYPE_DISK_WRITE = 1 << 3, + + FF_TOP_TYPE_DISK = FF_TOP_TYPE_DISK_READ | FF_TOP_TYPE_DISK_WRITE, +} FFTopTypes; typedef struct FFTopOptions { FFModuleArgs moduleArgs; - FFTopSortType sort; + FFTopTypes sort; + FFTopTypes showTypes; // bitfields uint32_t nProcesses; uint32_t waitTime; FFPercentageModuleConfig percent; diff --git a/src/modules/top/top.c b/src/modules/top/top.c index b36a3a1cc..60ecda8a0 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -11,19 +11,23 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); - ffStrbufAppendF(&output, "%s (%u) - ", process->name.chars, process->pid); - if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { - ffStrbufAppendS(&output, "CPU "); + ffStrbufAppendF(&output, "%s (%u)", process->name.chars, process->pid); + if ((options->showTypes & FF_TOP_TYPE_CPU) && (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)) { + ffStrbufAppendS(&output, " - CPU "); ffPercentAppendNum(&output, process->cpuPercent, options->percent, false, &options->moduleArgs); } if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { - ffStrbufAppendS(&output, " - MEM "); - ffSizeAppendNum(process->memBytes, &output); - ffStrbufAppendS(&output, " - DSK "); - ffSizeAppendNum(process->bytesRead, &output); - ffStrbufAppendS(&output, "/s / "); - ffSizeAppendNum(process->bytesWritten, &output); - ffStrbufAppendS(&output, "/s"); + if (options->showTypes & FF_TOP_TYPE_MEMORY) { + ffStrbufAppendS(&output, " - MEM "); + ffSizeAppendNum(process->memBytes, &output); + } + if (options->showTypes & FF_TOP_TYPE_DISK) { + ffStrbufAppendS(&output, " - DSK "); + ffSizeAppendNum(process->bytesRead, &output); + ffStrbufAppendS(&output, "/s / "); + ffSizeAppendNum(process->bytesWritten, &output); + ffStrbufAppendS(&output, "/s"); + } } ffStrbufPutTo(&output, stdout); } else { @@ -92,16 +96,54 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "sort")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ - { "cpu", FF_TOP_SORT_CPU }, - { "memory", FF_TOP_SORT_MEMORY }, - { "disk-read", FF_TOP_SORT_DISK_READ }, - { "disk-write", FF_TOP_SORT_DISK_WRITE }, + { "cpu", FF_TOP_TYPE_CPU }, + { "memory", FF_TOP_TYPE_MEMORY }, + { "disk-read", FF_TOP_TYPE_DISK_READ }, + { "disk-write", FF_TOP_TYPE_DISK_WRITE }, {}, }); if (error) { ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { - options->sort = (FFTopSortType) value; + options->sort = (FFTopTypes) value; + } + continue; + } else if (unsafe_yyjson_equals_str(key, "showTypes")) { + if (yyjson_is_arr(val)) { + options->showTypes = 0; + yyjson_val* item; + size_t aidx, amax; + yyjson_arr_foreach (val, aidx, amax, item) { + int value; + const char* error = ffJsonConfigParseEnum(item, &value, (FFKeyValuePair[]){ + { "cpu", FF_TOP_TYPE_CPU }, + { "memory", FF_TOP_TYPE_MEMORY }, + { "disk", FF_TOP_TYPE_DISK }, + {}, + }); + if (error == nullptr) { + options->showTypes |= (FFTopTypes) value; + } + if (error) { + options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + break; + } + } + } else { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ + { "cpu", FF_TOP_TYPE_CPU }, + { "memory", FF_TOP_TYPE_MEMORY }, + { "disk", FF_TOP_TYPE_DISK }, + {}, + }); + if (error == nullptr) { + options->showTypes = (FFTopTypes) value; + } + if (error) { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + } } continue; } else if (unsafe_yyjson_equals_str(key, "processes")) { @@ -121,19 +163,25 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); yyjson_mut_obj_add_str(doc, module, "type", "top"); - switch (options->sort) { - case FF_TOP_SORT_CPU: - yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); - break; - case FF_TOP_SORT_MEMORY: - yyjson_mut_obj_add_str(doc, module, "sort", "memory"); - break; - case FF_TOP_SORT_DISK_READ: - yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); - break; - case FF_TOP_SORT_DISK_WRITE: - yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); - break; + yyjson_mut_val* showTypes = yyjson_mut_arr(doc); + if (options->showTypes & FF_TOP_TYPE_CPU) { + yyjson_mut_arr_add_str(doc, showTypes, "cpu"); + } + if (options->showTypes & FF_TOP_TYPE_MEMORY) { + yyjson_mut_arr_add_str(doc, showTypes, "memory"); + } + if (options->showTypes & FF_TOP_TYPE_DISK) { + yyjson_mut_arr_add_str(doc, showTypes, "disk"); + } + yyjson_mut_obj_add_val(doc, module, "showTypes", showTypes); + if (options->sort == FF_TOP_TYPE_CPU) { + yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); + } else if (options->sort == FF_TOP_TYPE_MEMORY) { + yyjson_mut_obj_add_str(doc, module, "sort", "memory"); + } else if (options->sort == FF_TOP_TYPE_DISK_READ) { + yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); + } else if (options->sort == FF_TOP_TYPE_DISK_WRITE) { + yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); } yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); @@ -153,10 +201,16 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_val* item = yyjson_mut_arr_add_obj(doc, array); yyjson_mut_obj_add_strbuf(doc, item, "name", &process->name); yyjson_mut_obj_add_uint(doc, item, "pid", process->pid); - yyjson_mut_obj_add_real(doc, item, "cpuPercent", process->cpuPercent); - yyjson_mut_obj_add_uint(doc, item, "mem", process->memBytes); - yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); - yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); + if (options->showTypes & FF_TOP_TYPE_CPU) { + yyjson_mut_obj_add_real(doc, item, "cpuPercent", process->cpuPercent); + } + if (options->showTypes & FF_TOP_TYPE_MEMORY) { + yyjson_mut_obj_add_uint(doc, item, "mem", process->memBytes); + } + if (options->showTypes & FF_TOP_TYPE_DISK) { + yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); + yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); + } yyjson_mut_obj_add_uint(doc, item, "startTime", process->startTime); } @@ -168,7 +222,8 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ void ffInitTopOptions(FFTopOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); - options->sort = FF_TOP_SORT_CPU; + options->sort = FF_TOP_TYPE_CPU; + options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; options->nProcesses = 5; options->waitTime = 500; options->compact = false; diff --git a/src/modules/top/top.h b/src/modules/top/top.h index 144130fd6..48c13d6df 100644 --- a/src/modules/top/top.h +++ b/src/modules/top/top.h @@ -2,7 +2,7 @@ #include "option.h" -void ffPrepareTopProcesses(void); +void ffPrepareTopProcesses(FFTopTypes showTypes); bool ffPrintTop(FFTopOptions* options); void ffInitTopOptions(FFTopOptions* options); From 71728247abd2aa5ee1dbb63681d18a76253e0c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 23:24:31 +0800 Subject: [PATCH 059/109] Common (Sysctl): handle varying data lengths in integer retrieval functions --- src/common/impl/sysctl.c | 56 ++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/common/impl/sysctl.c b/src/common/impl/sysctl.c index e17b5c348..122a79091 100644 --- a/src/common/impl/sysctl.c +++ b/src/common/impl/sysctl.c @@ -22,21 +22,41 @@ const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result) { } int ffSysctlGetInt(int mib1, int mib2, int defaultValue) { - int result; + alignas(int) uint8_t result[sizeof(int)]; size_t neededLength = sizeof(result); if (sysctl((int[]) { mib1, mib2 }, 2, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue) { - int64_t result; + alignas(int64_t) uint8_t result[sizeof(int64_t)]; size_t neededLength = sizeof(result); if (sysctl((int[]) { mib1, mib2 }, 2, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int64_t): + return *(int64_t*)result; + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } #else const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { @@ -59,21 +79,41 @@ const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { } int ffSysctlGetInt(const char* propName, int defaultValue) { - int result; + alignas(int) uint8_t result[sizeof(int)]; size_t neededLength = sizeof(result); if (sysctlbyname(propName, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) { - int64_t result; + alignas(int64_t) uint8_t result[sizeof(int64_t)]; size_t neededLength = sizeof(result); if (sysctlbyname(propName, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int64_t): + return *(int64_t*)result; + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } #endif // OpenBSD From 6c19a8b4ecb561ce7e863bd545286e579f89e595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 23:27:24 +0800 Subject: [PATCH 060/109] Top (DragonFly): fixes building --- src/detection/top/top_dbsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 872ba97f8..1a9bbb888 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; From 1b1df2e731d5f59a635a1507dac421f3ab960e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 23:27:36 +0800 Subject: [PATCH 061/109] Common (Settings): tidy --- src/common/impl/settings.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/common/impl/settings.c b/src/common/impl/settings.c index 0f00054df..11dbac670 100644 --- a/src/common/impl/settings.c +++ b/src/common/impl/settings.c @@ -450,12 +450,10 @@ bool ffSettingsGetSQLite3String(const char* dbPath, const char* query, FFstrbuf* return true; } #else // FF_HAVE_SQLITE3 -int ffSettingsGetSQLite3Int(const char* dbPath, const char* query) { - FF_UNUSED(dbPath, query) +int ffSettingsGetSQLite3Int(const char*, const char*) { return 0; } -bool ffSettingsGetSQLite3String(const char* dbPath, const char* query, FFstrbuf* result) { - FF_UNUSED(dbPath, query, result) +bool ffSettingsGetSQLite3String(const char*, const char*, FFstrbuf*) { return false; } #endif // FF_HAVE_SQLITE3 From 3b76ade662f34f70074c45601ac1ac3c13950006 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 08:50:08 +0800 Subject: [PATCH 062/109] Shell: fixes the fast path of ash version detection --- src/detection/terminalshell/terminalshell.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index fa323aa9e..4eccf6d49 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -194,6 +194,9 @@ static bool extractBusyboxVersion(const char* line, uint32_t len, void* userdata static bool getShellVersionAsh(FFstrbuf* exe, FFstrbuf* version) { ffBinaryExtractStrings(exe->chars, extractBusyboxVersion, version, (uint32_t) strlen("BusyBox v0.0.0")); + if (version->length > 0) { + return true; + } const char* error = ffStrbufEndsWithS(exe, "busybox") ? ffProcessAppendStdErr(version, (char* const[]) { exe->chars, "ash", "--help", nullptr }) From 9670b585fbc0498b13a14d1466d2e27aac3cfa4d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 10:50:16 +0800 Subject: [PATCH 063/109] LM: detects LM from processes list if systemd is not available 2. removes type field 3. small optimizations --- CMakeLists.txt | 4 +- src/detection/lm/lm.h | 1 - src/detection/lm/lm_linux.c | 278 +++++++++++++++++++++++++++++++++--- src/modules/lm/lm.c | 10 -- 4 files changed, 260 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f4605509..33e72853b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -978,7 +978,7 @@ elseif(OpenBSD) src/detection/gpu/gpu_bsddrm.c src/detection/gtk_qt/gtk.c src/detection/host/host_obsd.c - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c src/detection/keyboard/keyboard_nosupport.c @@ -1227,7 +1227,7 @@ elseif(SunOS) src/detection/initsystem/initsystem_linux.c src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_nosupport.c - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_linux.c src/detection/loadavg/loadavg_sunos.c src/detection/locale/locale_linux.c src/detection/localip/localip_linux.c diff --git a/src/detection/lm/lm.h b/src/detection/lm/lm.h index d30229a79..8bedf8e5c 100644 --- a/src/detection/lm/lm.h +++ b/src/detection/lm/lm.h @@ -5,7 +5,6 @@ typedef struct FFLMResult { FFstrbuf service; - FFstrbuf type; FFstrbuf version; } FFLMResult; diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 1623c7277..d208a2641 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -1,18 +1,35 @@ #include "lm.h" +#include "common/io.h" +#include "common/mallocHelper.h" #include "common/properties.h" -#include "common/dbus.h" #include "common/processing.h" +#include "common/strutil.h" #include "detection/displayserver/displayserver.h" #include +#if __FreeBSD__ + #include + #include + #include +#elif __OpenBSD__ + #include + #include + #include +#elif __sun + #include +#elif __NetBSD__ + #include + #include +#endif + #define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" #define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" static const char* getGdmVersion(FFstrbuf* version) { - const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm", "--version", nullptr }); + const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", nullptr }); if (error || version->length == 0) { - error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", nullptr }); + error = ffProcessAppendStdOut(version, (char* const[]) { "gdm", "--version", nullptr }); if (error || version->length == 0) { return "Failed to get GDM version"; } @@ -112,34 +129,264 @@ static const char* getLightdmVersion(FFstrbuf* version) { return nullptr; } -const char* ffDetectLM(FFLMResult* result) { +#if __linux__ && !__ANDROID__ +static const char* detectBySystemd(FFLMResult* result) { FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY sessionId = ffStrbufCreateS(getenv("XDG_SESSION_ID")); if (sessionId.length == 0) { // On some incorrectly configured systems, $XDG_SESSION_ID is not set. Try finding it ourself // WARNING: This is private data. Do not parse - ffStrbufSetF(&path, FF_SYSTEMD_USERS_PATH "%d", instance.state.platform.uid); + ffStrbufAppendS(&path, FF_SYSTEMD_USERS_PATH); + ffStrbufAppendUInt(&path, instance.state.platform.uid); // This is actually buggy, and assumes current user is using DE // `sd_pid_get_session` can be a better option, but we need to find a pid to use - if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]) { + if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]){ { "DISPLAY=", &sessionId }, })) { return "Failed to get $XDG_SESSION_ID"; } } - ffStrbufSetS(&path, FF_SYSTEMD_SESSIONS_PATH); + ffStrbufClear(&path); + ffStrbufAppendS(&path, FF_SYSTEMD_SESSIONS_PATH); ffStrbufAppend(&path, &sessionId); // WARNING: This is private data. Do not parse - if (!ffParsePropFileValues(path.chars, 2, (FFpropquery[]) { - { "SERVICE=", &result->service }, - { "TYPE=", &result->type }, - })) { + if (!ffParsePropFile(path.chars, "SERVICE=", &result->service)) { return "Failed to parse " FF_SYSTEMD_SESSIONS_PATH "$XDG_SESSION_ID"; } + return nullptr; +} +#endif + +static const char* testLms(const char* psName) { + static const char* A[] = { + "atrium", + }; + static const char* C[] = { + "cdm", + }; + static const char* E[] = { + "entrance", + }; + static const char* G[] = { + "gdm", + "gdm3", + "greetd", + }; + static const char* L[] = { + "lemurs", + "lightdm", + "lxdm", + "ly", + }; + static const char* P[] = { + "plasmalogin", + }; + static const char* S[] = { + "sddm", + "slim", + }; + static const char* T[] = { + "tbsm", + }; + static const char* X[] = { + "xdm", + }; + + switch (psName[0]) { + #define PS_CASE(letter, array) \ + case letter: \ + for (uint32_t i = 0; i < ARRAY_SIZE(array); ++i) { \ + if (ffStrEqualsIgnCase(psName, array[i])) { \ + return array[i]; \ + } \ + } \ + break; + PS_CASE('a', A) + PS_CASE('c', C) + PS_CASE('e', E) + PS_CASE('g', G) + PS_CASE('l', L) + PS_CASE('p', P) + PS_CASE('s', S) + PS_CASE('t', T) + PS_CASE('x', X) + } + return nullptr; +} + +const char* detectByProcesses(FFLMResult* result) { +#if __FreeBSD__ + #ifdef __DragonFly__ + #define ki_comm kp_comm + #endif + + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, 0 }; + size_t length = 0; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, nullptr) failed"; + } + + FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed"; + } + + length /= sizeof(*procs); + + for (struct kinfo_proc* proc = procs; proc < procs + length; ++proc) { + const char* lm = testLms(proc->ki_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; + } + } +#elif __OpenBSD__ + kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + int count = 0; + const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, 0, sizeof(*proc), &count); + if (proc) { + for (int i = 0; i < count; ++i) { + const char* lm = testLms(proc[i].p_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; + } + } + } + kvm_close(kd); +#elif __sun + FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); + if (procdir == nullptr) { + return "opendir(\"/proc\") failed"; + } + + FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); + ffStrbufAppendS(&procPath, "/proc/"); + + uint32_t procPathLength = procPath.length; + + struct dirent* dirent; + while ((dirent = readdir(procdir)) != nullptr) { + if (!ffCharIsDigit(dirent->d_name[0])) { + continue; + } + + ffStrbufAppendS(&procPath, dirent->d_name); + ffStrbufAppendS(&procPath, "/psinfo"); + psinfo_t proc; + if (ffReadFileData(procPath.chars, sizeof(proc), &proc) == sizeof(proc)) { + ffStrbufSubstrBefore(&procPath, procPathLength); + + if (proc.pr_uid != 0) { + continue; + } + + const char* lm = testLms(proc.pr_fname); + if (lm) { + ffStrbufSetS(&result->service, lm); + break; + } + } + } +#elif __linux__ || __GNU__ + FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); + if (procdir == nullptr) { + return "opendir(\"/proc\") failed"; + } + + FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); + int procfd = dirfd(procdir); + + struct dirent* dirent; + while ((dirent = readdir(procdir)) != nullptr) { + // Match only folders starting with a number (the pid folders) + if (dirent->d_type != DT_DIR || !ffCharIsDigit(dirent->d_name[0])) { + continue; + } + + ffStrbufSetS(&procPath, dirent->d_name); + uint32_t procFolderPathLength = procPath.length; + + // Don't check for processes not owned by root (login managers run as root). + char loginuid[32]; + ffStrbufAppendS(&procPath, "/loginuid"); + ssize_t bytesRead = ffReadFileDataRelative(procfd, procPath.chars, sizeof(loginuid) - 1, loginuid); + if (bytesRead <= 0) { + continue; + } + loginuid[bytesRead] = '\0'; + + if (strtol(loginuid, nullptr, 10) != (long) (uint32_t) -1 /* no loginuid */) { + continue; + } + + ffStrbufSubstrBefore(&procPath, procFolderPathLength); + + ffStrbufAppendS(&procPath, "/comm"); + char comm[256]; + bytesRead = ffReadFileDataRelative(procfd, procPath.chars, sizeof(comm) - 1, comm); + if (bytesRead <= 0) { + continue; + } + if (comm[bytesRead - 1] == '\n') { + --bytesRead; + } + comm[bytesRead] = '\0'; + + const char* lm = testLms(comm); + if (lm) { + ffStrbufSetS(&result->service, lm); + break; + } + } +#elif __NetBSD__ + int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_UID, 0, sizeof(struct kinfo_proc2), INT_MAX }; + + size_t size = 0; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &size, nullptr, 0) != 0) { + return "sysctl(KERN_PROC_UID, nullptr) failed"; + } + + FF_AUTO_FREE struct kinfo_proc2* procs = malloc(size); + + if (sysctl(request, ARRAY_SIZE(request), procs, &size, nullptr, 0) != 0) { + return "sysctl(KERN_PROC_UID, procs) failed"; + } + + for (struct kinfo_proc2* proc = procs; proc < procs + (size / sizeof(struct kinfo_proc2)); proc++) { + const char* lm = testLms(proc->p_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; + } + } +#endif + + if (result->service.length == 0) { + return "Failed to detect login manager by processes"; + } + + return nullptr; +} + +const char* ffDetectLM(FFLMResult* result) { + const char* error = ""; +#if __linux__ && !__ANDROID__ + error = detectBySystemd(result); +#endif + + if (error != nullptr) { + error = detectByProcesses(result); + } + + if (error != nullptr) { + return error; + } if (instance.config.general.detectVersion) { if (ffStrbufStartsWithS(&result->service, "gdm")) { @@ -155,14 +402,5 @@ const char* ffDetectLM(FFLMResult* result) { } } - // Correct char cases - if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_WAYLAND)) { - ffStrbufSetS(&result->type, FF_WM_PROTOCOL_WAYLAND); - } else if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_X11)) { - ffStrbufSetS(&result->type, FF_WM_PROTOCOL_X11); - } else if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_TTY)) { - ffStrbufSetS(&result->type, FF_WM_PROTOCOL_TTY); - } - return nullptr; } diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index ca9debe11..2ce541eed 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -8,7 +8,6 @@ bool ffPrintLM(FFLMOptions* options) { bool success = false; FFLMResult result; ffStrbufInit(&result.service); - ffStrbufInit(&result.type); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -28,14 +27,10 @@ bool ffPrintLM(FFLMOptions* options) { if (result.version.length) { printf(" %s", result.version.chars); } - if (result.type.length) { - printf(" (%s)", result.type.chars); - } putchar('\n'); } else { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.service, "service"), - FF_ARG(result.type, "type"), FF_ARG(result.version, "version"), })); } @@ -43,7 +38,6 @@ bool ffPrintLM(FFLMOptions* options) { exit: ffStrbufDestroy(&result.service); - ffStrbufDestroy(&result.type); ffStrbufDestroy(&result.version); return success; @@ -69,7 +63,6 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do bool success = false; FFLMResult result; ffStrbufInit(&result.service); - ffStrbufInit(&result.type); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -85,13 +78,11 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "service", &result.service); - yyjson_mut_obj_add_strbuf(doc, obj, "type", &result.type); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); success = true; exit: ffStrbufDestroy(&result.service); - ffStrbufDestroy(&result.type); ffStrbufDestroy(&result.version); return success; @@ -138,7 +129,6 @@ FFModuleBaseInfo ffLMModuleInfo = { .generateJsonConfig = (void*) ffGenerateLMJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { { "LM service", "service" }, - { "LM type", "type" }, { "LM version", "version" }, })), .defaultOrder = 20, From 8b162e89de39a78609bbc8ebb4f5a5299f50b69e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 14:14:24 +0800 Subject: [PATCH 064/109] WMDE: improves performance --- src/detection/displayserver/linux/wmde.c | 55 +++++++++++++++--------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 8044c4a95..6984d1d0c 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -7,6 +7,7 @@ #include #include #include +#include #if __FreeBSD__ #include @@ -376,48 +377,60 @@ static const char* getFromProcesses(FFDisplayServerResult* result) { } FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); - ffStrbufAppendS(&procPath, "/proc/"); - - uint32_t procPathLength = procPath.length; - - FF_STRBUF_AUTO_DESTROY loginuid = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY processName = ffStrbufCreateA(256); // Some processes have large command lines (looking at you chrome) + int procfd = dirfd(procdir); struct dirent* dirent; while ((dirent = readdir(procdir)) != nullptr) { // Match only folders starting with a number (the pid folders) - if (dirent->d_type != DT_DIR || !ffCharIsDigit(dirent->d_name[0])) { + if ((dirent->d_type != DT_DIR && dirent->d_type != DT_UNKNOWN) || !ffCharIsDigit(dirent->d_name[0])) { continue; } - ffStrbufAppendS(&procPath, dirent->d_name); + ffStrbufSetS(&procPath, dirent->d_name); uint32_t procFolderPathLength = procPath.length; // Don't check for processes not owned by the current user. + char loginuid[32]; ffStrbufAppendS(&procPath, "/loginuid"); - ffReadFileBuffer(procPath.chars, &loginuid); - if (ffStrbufToUInt(&loginuid, (uint64_t) -1) != userId) { - ffStrbufSubstrBefore(&procPath, procPathLength); + ssize_t bytesRead = ffReadFileDataRelative(procfd, procPath.chars, sizeof(loginuid) - 1, loginuid); + if (bytesRead <= 0) { + continue; + } + loginuid[bytesRead] = '\0'; + if (strtol(loginuid, nullptr, 10) != (long) userId) { continue; } ffStrbufSubstrBefore(&procPath, procFolderPathLength); - // We check the cmdline for the process name, because it is not trimmed. - ffStrbufAppendS(&procPath, "/cmdline"); - ffReadFileBuffer(procPath.chars, &processName); - ffStrbufTrimRightSpace(&processName); - ffStrbufSubstrBeforeFirstC(&processName, '\0'); // Trim the arguments - ffStrbufSubstrAfterLastC(&processName, '/'); - - ffStrbufSubstrBefore(&procPath, procPathLength); + // We check the realpath for the process name + ffStrbufAppendS(&procPath, "/exe"); + char exePath[PATH_MAX]; + ssize_t exePathLength = readlinkat(procfd, procPath.chars, exePath, sizeof(exePath) - 1); + const char* processName; + if (exePathLength >= 0) { + exePath[exePathLength] = '\0'; + processName = basename(exePath); + } else { + ffStrbufSubstrBefore(&procPath, procFolderPathLength); + ffStrbufAppendS(&procPath, "/comm"); + exePathLength = ffReadFileDataRelative(procfd, procPath.chars, sizeof(exePath) - 1, exePath); + if (exePathLength <= 0) { + continue; + } + if (exePath[exePathLength - 1] == '\n') { + --exePathLength; + } + exePath[exePathLength] = '\0'; + processName = exePath; + } if (result->dePrettyName.length == 0) { - applyPrettyNameIfDE(result, processName.chars); + applyPrettyNameIfDE(result, processName); } if (result->wmPrettyName.length == 0) { - applyNameIfWM(result, processName.chars); + applyNameIfWM(result, processName); } if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) { From fb309134b5bcc6349f53eca3d404afda1bd44b60 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 14:43:16 +0800 Subject: [PATCH 065/109] LM (Linux): queries systemd session info via dbus --- src/detection/lm/lm_linux.c | 50 +++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index d208a2641..0bdab580a 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -4,7 +4,10 @@ #include "common/properties.h" #include "common/processing.h" #include "common/strutil.h" -#include "detection/displayserver/displayserver.h" + +#ifdef FF_HAVE_DBUS + #include "common/dbus.h" +#endif #include @@ -23,9 +26,6 @@ #include #endif -#define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" -#define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" - static const char* getGdmVersion(FFstrbuf* version) { const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", nullptr }); if (error || version->length == 0) { @@ -130,7 +130,33 @@ static const char* getLightdmVersion(FFstrbuf* version) { } #if __linux__ && !__ANDROID__ -static const char* detectBySystemd(FFLMResult* result) { +#ifdef FF_HAVE_DBUS +static const char* detectBySystemdDbus(FFLMResult* result) { + // This is the standard way to query the systemd session service name, + // and requires no $XDG_SESSION_ID being available + FF_DBUS_AUTO_DESTROY_DATA FFDBusData dbus = {}; + if (ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus) != nullptr) { + return "Failed to load system DBus"; + } + + if (!ffDBusGetPropertyString( + &dbus, + "org.freedesktop.login1", + "/org/freedesktop/login1/session/auto", + "org.freedesktop.login1.Session", + "Service", + &result->service)) { + return "Failed to get systemd session Service property"; + } + + return nullptr; +} +#endif + +#define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" +#define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" + +static const char* detectBySystemdPrivate(FFLMResult* result) { FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY sessionId = ffStrbufCreateS(getenv("XDG_SESSION_ID")); @@ -142,9 +168,7 @@ static const char* detectBySystemd(FFLMResult* result) { // This is actually buggy, and assumes current user is using DE // `sd_pid_get_session` can be a better option, but we need to find a pid to use - if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]){ - { "DISPLAY=", &sessionId }, - })) { + if (!ffParsePropFile(path.chars, "DISPLAY=", &sessionId)) { return "Failed to get $XDG_SESSION_ID"; } } @@ -157,6 +181,7 @@ static const char* detectBySystemd(FFLMResult* result) { if (!ffParsePropFile(path.chars, "SERVICE=", &result->service)) { return "Failed to parse " FF_SYSTEMD_SESSIONS_PATH "$XDG_SESSION_ID"; } + return nullptr; } #endif @@ -376,8 +401,13 @@ const char* detectByProcesses(FFLMResult* result) { const char* ffDetectLM(FFLMResult* result) { const char* error = ""; -#if __linux__ && !__ANDROID__ - error = detectBySystemd(result); +#if __linux__ + #ifdef FF_HAVE_DBUS + error = detectBySystemdDbus(result); + #endif + if (error != nullptr) { + error = detectBySystemdPrivate(result); + } #endif if (error != nullptr) { From 203cd7cbcfdc04feacb16e6f7a2423deeadb6aae Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 15:19:57 +0800 Subject: [PATCH 066/109] LM (Linux): adds pretty name --- src/detection/lm/lm.h | 1 + src/detection/lm/lm_linux.c | 62 +++++++++++++++++++++++++++++++++++++ src/modules/lm/lm.c | 11 +++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/detection/lm/lm.h b/src/detection/lm/lm.h index 8bedf8e5c..d2c3299f6 100644 --- a/src/detection/lm/lm.h +++ b/src/detection/lm/lm.h @@ -5,6 +5,7 @@ typedef struct FFLMResult { FFstrbuf service; + FFstrbuf prettyName; FFstrbuf version; } FFLMResult; diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 0bdab580a..8e197b31f 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -418,6 +418,68 @@ const char* ffDetectLM(FFLMResult* result) { return error; } + switch (result->service.chars[0]) { + case 'a': + if (ffStrEqualsIgnCase(result->service.chars, "atrium")) { + ffStrbufSetStatic(&result->prettyName, "Atrium"); + } + break; + case 'c': + if (ffStrEqualsIgnCase(result->service.chars, "cdm")) { + ffStrbufSetStatic(&result->prettyName, "CDM"); + } + break; + case 'e': + if (ffStrEqualsIgnCase(result->service.chars, "entrance")) { + ffStrbufSetStatic(&result->prettyName, "Entrance"); + } + break; + case 'g': + if (ffStrbufStartsWithIgnCaseS(&result->service, "gdm")) { + ffStrbufSetStatic(&result->prettyName, "GDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "greetd")) { + ffStrbufSetStatic(&result->prettyName, "greetd"); + } + break; + case 'l': + if (ffStrEqualsIgnCase(result->service.chars, "lemurs")) { + ffStrbufSetStatic(&result->prettyName, "Lemurs"); + } else if (ffStrEqualsIgnCase(result->service.chars, "lightdm")) { + ffStrbufSetStatic(&result->prettyName, "LightDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "lxdm")) { + ffStrbufSetStatic(&result->prettyName, "LXDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "ly")) { + ffStrbufSetStatic(&result->prettyName, "Ly"); + } + break; + case 'p': + if (ffStrEqualsIgnCase(result->service.chars, "plasmalogin")) { + ffStrbufSetStatic(&result->prettyName, "Plasma Login"); + } + break; + case 's': + if (ffStrEqualsIgnCase(result->service.chars, "sddm")) { + ffStrbufSetStatic(&result->prettyName, "SDDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "slim")) { + ffStrbufSetStatic(&result->prettyName, "SLiM"); + } + break; + case 't': + if (ffStrEqualsIgnCase(result->service.chars, "tbsm")) { + ffStrbufSetStatic(&result->prettyName, "TBSM"); + } + break; + case 'x': + if (ffStrEqualsIgnCase(result->service.chars, "xdm")) { + ffStrbufSetStatic(&result->prettyName, "XDM"); + } + break; + } + + if (result->prettyName.length == 0) { + ffStrbufSet(&result->prettyName, &result->service); + } + if (instance.config.general.detectVersion) { if (ffStrbufStartsWithS(&result->service, "gdm")) { getGdmVersion(&result->version); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 2ce541eed..ece31fb0e 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -8,6 +8,7 @@ bool ffPrintLM(FFLMOptions* options) { bool success = false; FFLMResult result; ffStrbufInit(&result.service); + ffStrbufInit(&result.prettyName); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -23,7 +24,7 @@ bool ffPrintLM(FFLMOptions* options) { if (options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufWriteTo(&result.service, stdout); + ffStrbufWriteTo(&result.prettyName, stdout); if (result.version.length) { printf(" %s", result.version.chars); } @@ -31,6 +32,7 @@ bool ffPrintLM(FFLMOptions* options) { } else { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.service, "service"), + FF_ARG(result.prettyName, "pretty-name"), FF_ARG(result.version, "version"), })); } @@ -38,6 +40,7 @@ bool ffPrintLM(FFLMOptions* options) { exit: ffStrbufDestroy(&result.service); + ffStrbufDestroy(&result.prettyName); ffStrbufDestroy(&result.version); return success; @@ -63,6 +66,7 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do bool success = false; FFLMResult result; ffStrbufInit(&result.service); + ffStrbufInit(&result.prettyName); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -78,11 +82,13 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "service", &result.service); + yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result.prettyName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); success = true; exit: ffStrbufDestroy(&result.service); + ffStrbufDestroy(&result.prettyName); ffStrbufDestroy(&result.version); return success; @@ -128,7 +134,8 @@ FFModuleBaseInfo ffLMModuleInfo = { .generateJsonResult = (void*) ffGenerateLMJsonResult, .generateJsonConfig = (void*) ffGenerateLMJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - { "LM service", "service" }, + { "LM service / process name", "service" }, + { "LM pretty name", "pretty-name" }, { "LM version", "version" }, })), .defaultOrder = 20, From c5598d23619a72dbf62ad6ee0d35e3e652457340 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 15:21:04 +0800 Subject: [PATCH 067/109] LM (macOS): adds support --- CMakeLists.txt | 2 +- src/detection/lm/lm_apple.m | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/detection/lm/lm_apple.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 33e72853b..be5f4d764 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1050,7 +1050,7 @@ elseif(APPLE) src/detection/icons/icons_nosupport.c src/detection/initsystem/initsystem_linux.c src/detection/keyboard/keyboard_apple.c - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_apple.m src/detection/loadavg/loadavg_bsd.c src/detection/libc/libc_apple.c src/detection/locale/locale_linux.c diff --git a/src/detection/lm/lm_apple.m b/src/detection/lm/lm_apple.m new file mode 100644 index 000000000..d600058d4 --- /dev/null +++ b/src/detection/lm/lm_apple.m @@ -0,0 +1,18 @@ +#include "lm.h" + +#import + +const char* ffDetectLM(FFLMResult* result) { + ffStrbufSetStatic(&result->service, "loginwindow"); + ffStrbufSetStatic(&result->prettyName, "Login Window"); + + NSError* error; + NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:@"/System/Library/CoreServices/loginwindow.app/Contents/Info.plist" isDirectory:NO] + error:&error]; + + if (dict) { + ffStrbufSetS(&result->version, ((NSString*) dict[@"CFBundleShortVersionString"]).UTF8String); + } + + return nullptr; +} From 32757b0e43d952ab1b303b345cd950ac27823716 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 15:21:22 +0800 Subject: [PATCH 068/109] LM (Windows): adds support --- CMakeLists.txt | 2 +- src/detection/lm/lm_windows.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/detection/lm/lm_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index be5f4d764..9ba505650 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1144,7 +1144,7 @@ elseif(WIN32) src/detection/initsystem/initsystem_windows.c src/detection/keyboard/keyboard_windows.c src/detection/libc/libc_windows.cpp - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_windows.c src/detection/loadavg/loadavg_nosupport.c src/detection/locale/locale_windows.c src/detection/localip/localip_windows.c diff --git a/src/detection/lm/lm_windows.c b/src/detection/lm/lm_windows.c new file mode 100644 index 000000000..79cffba2b --- /dev/null +++ b/src/detection/lm/lm_windows.c @@ -0,0 +1,19 @@ +#include "lm.h" + +#include "common/windows/version.h" +#include "common/windows/nt.h" + +#include + +const char* ffDetectLM(FFLMResult* result) { + ffStrbufSetStatic(&result->service, "LogonUI"); + ffStrbufSetStatic(&result->prettyName, "Logon User Interface"); + + if (instance.config.general.detectVersion) { + wchar_t exePath[MAX_PATH]; + _snwprintf(exePath, ARRAY_SIZE(exePath), L"%ls\\system32\\%ls", (const wchar_t*) SharedUserData->NtSystemRoot, L"LogonUI.exe"); + ffGetFileVersion(exePath, nullptr, &result->version); + } + + return nullptr; +} From 2b42db58dadaf07115896d4eaa718d1294c954bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Aug 2026 17:35:33 +0800 Subject: [PATCH 069/109] LM (OpenBSD): adds support --- src/detection/lm/lm_linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 8e197b31f..8b34d86c0 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -219,6 +219,7 @@ static const char* testLms(const char* psName) { }; static const char* X[] = { "xdm", + "xenodm", }; switch (psName[0]) { @@ -472,6 +473,8 @@ const char* ffDetectLM(FFLMResult* result) { case 'x': if (ffStrEqualsIgnCase(result->service.chars, "xdm")) { ffStrbufSetStatic(&result->prettyName, "XDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "xenodm")) { + ffStrbufSetStatic(&result->prettyName, "Xenodm"); } break; } From c9ad429a1b01f835750991badce38f7478daf9b0 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 23:12:25 +0800 Subject: [PATCH 070/109] Global: introduces global macro `FF_PATH_PKG_BASE` to replace `_PATH_LOCALBASE` --- src/common/impl/FFPlatform_unix.c | 6 ++---- src/common/path.h | 16 ++++++++++++++++ src/detection/de/de_linux.c | 21 ++------------------- src/detection/gpu/gpu_pci.c | 17 +++-------------- src/detection/lm/lm_linux.c | 4 +++- src/detection/terminalshell/terminalshell.c | 13 ++----------- src/detection/wm/wm_linux.c | 5 ++--- 7 files changed, 30 insertions(+), 52 deletions(-) diff --git a/src/common/impl/FFPlatform_unix.c b/src/common/impl/FFPlatform_unix.c index ec2ef1699..e3ea77f51 100644 --- a/src/common/impl/FFPlatform_unix.c +++ b/src/common/impl/FFPlatform_unix.c @@ -3,7 +3,7 @@ #include "common/arrutil.h" #include "common/strutil.h" #include "common/io.h" -#include "fastfetch_config.h" +#include "common/path.h" #include #include @@ -238,9 +238,7 @@ static void getDataDirs(FFPlatform* platform) { ffPlatformPathAddHome(&platform->dataDirs, platform, ""); platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); -#ifdef _PATH_LOCALBASE - ffPlatformPathAddAbsolute(&platform->dataDirs, _PATH_LOCALBASE "/share/"); -#endif + ffPlatformPathAddAbsolute(&platform->dataDirs, FF_PATH_PKG_BASE "/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/"); } diff --git a/src/common/path.h b/src/common/path.h index 705b1c094..0d292d868 100644 --- a/src/common/path.h +++ b/src/common/path.h @@ -2,6 +2,7 @@ #include "common/FFstrbuf.h" #include "common/strutil.h" +#include "fastfetch_config.h" const char* ffFindExecutableInPath(const char* name, FFstrbuf* result); static inline bool ffIsAbsolutePath(const char* path) { @@ -19,3 +20,18 @@ char* realpath(const char* __restrict file_name, char* __restrict resolved_name ssize_t freadlink(void* hFile, char* buf, size_t bufsiz); ssize_t readlink(const char* path, char* buf, size_t bufsiz); #endif + +#ifdef __FreeBSD__ + #include + #ifdef _PATH_LOCALBASE + #define FF_PATH_PKG_BASE _PATH_LOCALBASE + #else + #define FF_PATH_PKG_BASE "/usr/local" + #endif +#elif __OpenBSD__ + #define FF_PATH_PKG_BASE "/usr/local" +#elif __NetBSD__ + #define FF_PATH_PKG_BASE "/usr/pkg" +#else + #define FF_PATH_PKG_BASE FASTFETCH_TARGET_DIR_USR +#endif \ No newline at end of file diff --git a/src/detection/de/de_linux.c b/src/detection/de/de_linux.c index e79c3f418..719d81fe8 100644 --- a/src/detection/de/de_linux.c +++ b/src/detection/de/de_linux.c @@ -11,29 +11,12 @@ #include "detection/displayserver/displayserver.h" #include -#ifdef __FreeBSD__ - #include - #ifndef _PATH_LOCALBASE - #define _PATH_LOCALBASE "/usr/local" - #endif -#elif __OpenBSD__ - #define _PATH_LOCALBASE "/usr/local" -#elif __NetBSD__ - #define _PATH_LOCALBASE "/usr/pkg" -#endif static void getKDE(FFstrbuf* result, [[maybe_unused]] FFDEOptions* options) { -#ifdef _PATH_LOCALBASE - ffParsePropFile(_PATH_LOCALBASE "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); + ffParsePropFile(FF_PATH_PKG_BASE "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); if (result->length == 0) { - ffParsePropFile(_PATH_LOCALBASE "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result); + ffParsePropFile(FF_PATH_PKG_BASE "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result); } -#else - ffParsePropFile(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); - if (result->length == 0) { - ffParsePropFile(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result); - } -#endif if (result->length == 0) { ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index c3772fd91..b1bd08836 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -1,21 +1,10 @@ #include "gpu.h" #include "common/io.h" +#include "common/path.h" #include "common/properties.h" #include "common/memrchr.h" #include "common/strutil.h" -#include -#ifdef __FreeBSD__ - #include - #ifndef _PATH_LOCALBASE - #define _PATH_LOCALBASE "/usr/local" - #endif -#elif __OpenBSD__ - #define _PATH_LOCALBASE "/usr/local" -#elif __NetBSD__ - #define _PATH_LOCALBASE "/usr/pkg" -#endif - #if FF_HAVE_EMBEDDED_PCIIDS #include "fastfetch_pciids.c.inc" #endif @@ -46,9 +35,9 @@ static const FFstrbuf* loadPciIds() { } } #elif __OpenBSD__ || __FreeBSD__ || __NetBSD__ - ffReadFileBuffer(_PATH_LOCALBASE "/share/hwdata/pci.ids", &pciids); + ffReadFileBuffer(FF_PATH_PKG_BASE "/share/hwdata/pci.ids", &pciids); if (pciids.length == 0) { - ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids); + ffReadFileBuffer(FF_PATH_PKG_BASE "/share/pciids/pci.ids", &pciids); } #elif __sun ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 8b34d86c0..e4f18c19e 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -54,6 +54,8 @@ static const char* getSshdVersion(FFstrbuf* version) { #ifdef FF_HAVE_ZLIB #include "common/library.h" + #include "common/path.h" + #include #include @@ -66,7 +68,7 @@ static const char* getSddmVersion(FFstrbuf* version) { FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose) - gzFile file = ffgzopen(FASTFETCH_TARGET_DIR_USR "/share/man/man1/sddm.1.gz", "rb"); + gzFile file = ffgzopen(FF_PATH_PKG_BASE "/share/man/man1/sddm.1.gz", "rb"); if (file == Z_NULL) { return "ffgzopen(\"/usr/share/man/man1/sddm.1.gz\", \"rb\") failed"; } diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 4eccf6d49..1844d5163 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -8,17 +8,8 @@ #include #include -#ifdef __FreeBSD__ - #include - #ifndef _PATH_LOCALBASE - #define _PATH_LOCALBASE "/usr/local" - #endif -#elif __OpenBSD__ - #define _PATH_LOCALBASE "/usr/local" -#elif __NetBSD__ - #define _PATH_LOCALBASE "/usr/pkg" -#elif _WIN32 +#if _WIN32 #include "common/windows/registry.h" #include "common/windows/version.h" #include @@ -663,7 +654,7 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) || ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) #else - ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) + ffReadFileData(FF_PATH_PKG_BASE "/share/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) #endif ) { // Starts from version 0.17.0 diff --git a/src/detection/wm/wm_linux.c b/src/detection/wm/wm_linux.c index 5e3fff085..a22a513fb 100644 --- a/src/detection/wm/wm_linux.c +++ b/src/detection/wm/wm_linux.c @@ -43,9 +43,8 @@ static const char* getHyprland(FFstrbuf* result) { FF_DEBUG("Detecting Hyprland version"); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - FF_DEBUG("Checking for " FASTFETCH_TARGET_DIR_USR "/include/hyprland/src/version.h" - " file"); - if (ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/include/hyprland/src/version.h", result)) { + FF_DEBUG("Checking for " FF_PATH_PKG_BASE "/include/hyprland/src/version.h file"); + if (ffReadFileBuffer(FF_PATH_PKG_BASE "/include/hyprland/src/version.h", result)) { FF_DEBUG("Found version.h file, extracting version"); if (ffStrbufSubstrAfterFirstS(result, "\n#define GIT_TAG ")) { ffStrbufSubstrAfterFirstC(result, '"'); From 04f26a29eb9614dc7c253528b55122a3d3f5d235 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 09:45:58 +0800 Subject: [PATCH 071/109] CI: enables bluetooth module on platforms other than macOS --- .github/workflows/build-macos-hosts.yml | 4 ++-- presets/ci.jsonc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-macos-hosts.yml b/.github/workflows/build-macos-hosts.yml index 66c1666b7..573165518 100644 --- a/.github/workflows/build-macos-hosts.yml +++ b/.github/workflows/build-macos-hosts.yml @@ -41,10 +41,10 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan --stat false + run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan --format json + run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json - name: run flashfetch run: time ./flashfetch diff --git a/presets/ci.jsonc b/presets/ci.jsonc index bbc03613f..5499e1294 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -95,8 +95,8 @@ "opengl", "opencl", "users", - // "bluetooth", // doesn't work on macOS because it requires bluetooth permissions - // "bluetoothradio", + "bluetooth", + "bluetoothradio", "sound", "camera", "gamepad", From 5936c1cef4d8aac668dfa7278ab8d4810af3e130 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 10:15:25 +0800 Subject: [PATCH 072/109] CI: adds benchmark job --- .github/workflows/benchmark-index.html | 405 ++++++++++++++++++++++ .github/workflows/build-benchmark.yml | 56 +++ .github/workflows/build-linux-hosts.yml | 32 +- .github/workflows/build-macos-hosts.yml | 32 +- .github/workflows/build-windows-hosts.yml | 32 +- .github/workflows/ci.yml | 11 + 6 files changed, 562 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/benchmark-index.html create mode 100644 .github/workflows/build-benchmark.yml diff --git a/.github/workflows/benchmark-index.html b/.github/workflows/benchmark-index.html new file mode 100644 index 000000000..a2b9e309a --- /dev/null +++ b/.github/workflows/benchmark-index.html @@ -0,0 +1,405 @@ + + + + + + Fastfetch · Benchmark + + + + + +
+
+

Fastfetch Benchmark

+ +
+

Performance history grouped by CPU family. Each chart contains all modules and total process time for one operating system and architecture. Module curves are available from the legend and hidden by default.

+ +
+ +
+ + + diff --git a/.github/workflows/build-benchmark.yml b/.github/workflows/build-benchmark.yml new file mode 100644 index 000000000..827d81c39 --- /dev/null +++ b/.github/workflows/build-benchmark.yml @@ -0,0 +1,56 @@ +name: Reusable Benchmark + +on: + workflow_call: + +permissions: + contents: write + +jobs: + benchmark: + runs-on: ubuntu-latest + concurrency: + group: benchmark + cancel-in-progress: false + steps: + - name: checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: download benchmark data + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: benchmark-* + path: benchmarks + + - name: merge benchmark data + run: jq -s 'add' benchmarks/*/benchmark.json > benchmark.json + + - name: save benchmark dashboard + run: cp .github/benchmark-index.html "$RUNNER_TEMP/benchmark-index.html" + + - name: store benchmark result + uses: benchmark-action/github-action-benchmark@52576c92bccf6ac60c8223ec7eb2565637cae9ba # v1.22.1 + with: + name: Fastfetch + tool: customSmallerIsBetter + output-file-path: benchmark.json + github-token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ github.sha }} + auto-push: true + summary-always: true + fail-on-alert: true + benchmark-data-dir-path: dev/bench + + - name: publish benchmark dashboard + run: | + git fetch origin gh-pages + git switch --force-create gh-pages FETCH_HEAD + mkdir -p dev/bench + cp "$RUNNER_TEMP/benchmark-index.html" dev/bench/index.html + git config user.name github-action-benchmark + git config user.email github@users.noreply.github.com + git add dev/bench/index.html + if ! git diff --cached --quiet; then + git commit -m "Update benchmark dashboard" + git push origin gh-pages + fi diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index 612e7165f..19aec15b0 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -43,7 +43,7 @@ jobs: run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - name: install required packages - run: sudo apt-get update && sudo apt-get install -y gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build + run: sudo apt-get update && sudo apt-get install -y gcc-13 jq libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build - name: install linuxbrew packages run: | @@ -73,7 +73,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "linux" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -105,3 +127,9 @@ jobs: with: name: fastfetch-linux-${{ inputs.arch }} path: ./fastfetch-*.* + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-linux-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/build-macos-hosts.yml b/.github/workflows/build-macos-hosts.yml index 573165518..d805bf70d 100644 --- a/.github/workflows/build-macos-hosts.yml +++ b/.github/workflows/build-macos-hosts.yml @@ -29,7 +29,7 @@ jobs: - name: install required packages run: | HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew update - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng jq - name: configure project run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . @@ -44,7 +44,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "macos" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -60,3 +82,9 @@ jobs: with: name: fastfetch-macos-${{ inputs.arch }} path: ./fastfetch-*.* + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-macos-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/build-windows-hosts.yml b/.github/workflows/build-windows-hosts.yml index 2ef399f97..2518c25d6 100644 --- a/.github/workflows/build-windows-hosts.yml +++ b/.github/workflows/build-windows-hosts.yml @@ -49,7 +49,7 @@ jobs: with: msystem: ${{ inputs.msystem }} update: true - install: git mingw-w64-clang-${{ inputs.msys-arch }}-7zip mingw-w64-clang-${{ inputs.msys-arch }}-cmake mingw-w64-clang-${{ inputs.msys-arch }}-clang mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-loader mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-headers mingw-w64-clang-${{ inputs.msys-arch }}-opencl-icd mingw-w64-clang-${{ inputs.msys-arch }}-opencl-headers mingw-w64-clang-${{ inputs.msys-arch }}-cppwinrt mingw-w64-clang-${{ inputs.msys-arch }}-imagemagick mingw-w64-clang-${{ inputs.msys-arch }}-chafa mingw-w64-clang-${{ inputs.msys-arch }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers + install: git mingw-w64-clang-${{ inputs.msys-arch }}-7zip mingw-w64-clang-${{ inputs.msys-arch }}-cmake mingw-w64-clang-${{ inputs.msys-arch }}-clang mingw-w64-clang-${{ inputs.msys-arch }}-jq mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-loader mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-headers mingw-w64-clang-${{ inputs.msys-arch }}-opencl-icd mingw-w64-clang-${{ inputs.msys-arch }}-opencl-headers mingw-w64-clang-${{ inputs.msys-arch }}-cppwinrt mingw-w64-clang-${{ inputs.msys-arch }}-imagemagick mingw-w64-clang-${{ inputs.msys-arch }}-chafa mingw-w64-clang-${{ inputs.msys-arch }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers - name: print msys version run: uname -a @@ -70,7 +70,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "windows" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -116,3 +138,9 @@ jobs: name: fastfetch-windows-${{ inputs.arch }} path: ./fastfetch-windows-${{ inputs.arch }}.* overwrite: true + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-windows-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0081e62d8..8f63fdc04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,6 +176,17 @@ jobs: secrets: SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }} + benchmark: + if: github.event_name == 'push' && github.ref == 'refs/heads/dev' && github.repository == 'fastfetch-cli/fastfetch' + name: Benchmark + needs: + - linux-hosts + - macos-hosts + - windows-hosts + permissions: + contents: write + uses: ./.github/workflows/build-benchmark.yml + release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch' name: Release From 1dc794fac04954f2717e4cee4b437ec544cd9f3a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 11:09:55 +0800 Subject: [PATCH 073/109] Doc: updates changelog [ci skip] --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed5407df9..577aafa8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Changes: * The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations. Features: +* Improved Login Manager (LM) module + * Added support on macOS, Windows and POSIX systems without systemd (by process list enumeration). + * Reports pretty name on Linux. +* Added Top module to print processes with the highest CPU, memory or disk I/O usage. (Top) * Added module key localization support. (General) * Added a new option `--key-language ` (`display.key.language: ""` in JSON config). When left empty, it defaults to the system locale. * See `fastfetch -h key-language` for all supported languages. @@ -15,9 +19,14 @@ Features: * Added terminal font size detection support on Termux. (TerminalFont, Android) * Improved GTK theme/icons/font detection on standalone WMs such as Hyprland, sway, niri and i3. (Theme, Linux) * Improved fish completion scripts to print enum descriptions. (Completion) +* Enabled Wayland support on Android. (DisplayServer, Android) +* Added DE detection support for ASUS Zenfone. (DE, Android) Bugfixes: * Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO) +* Fixed the fast path of ash version detection. (Shell) +* Fixed memory usage detection support on x86-32 FreeBSD (Memory, FreeBSD) + * Note: Although 32-bit systems are still supported, they are deprecated and barely tested. Users are encouraged to upgrade to 64-bit systems. * Some internal cleanups and optimizations. # 2.67.1 From 191c5f2ef5435be1fc43ae281fed0fb48a425882 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 14:29:17 +0800 Subject: [PATCH 074/109] Doc: updates README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 84ec8e975..b3e66cee8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Fastfetch +[![Benchmark](https://img.shields.io/badge/GitHub%20Pages-live-blue?logo=github)](https://fastfetch-cli.github.io/fastfetch/dev/bench) [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/fastfetch-cli/fastfetch/ci.yml)](https://github.com/fastfetch-cli/fastfetch/actions) [![GitHub license](https://img.shields.io/github/license/fastfetch-cli/fastfetch)](https://github.com/fastfetch-cli/fastfetch/blob/dev/LICENSE) [![GitHub contributors](https://img.shields.io/github/contributors/fastfetch-cli/fastfetch)](https://github.com/fastfetch-cli/fastfetch/graphs/contributors) From dcce4ccdb042b5199acf1c194602739c52587481 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 14:57:22 +0800 Subject: [PATCH 075/109] CI: moves `benchmark-index` to `/.github` as required by the script --- .github/{workflows => }/benchmark-index.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflows => }/benchmark-index.html (100%) diff --git a/.github/workflows/benchmark-index.html b/.github/benchmark-index.html similarity index 100% rename from .github/workflows/benchmark-index.html rename to .github/benchmark-index.html From d80fe3f0043538031c70b2c059973436bbeeb923 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 14:58:32 +0800 Subject: [PATCH 076/109] Logo (Builtin): adds macOS_old --- CHANGELOG.md | 3 +++ src/logo/ascii/m.inc | 13 +++++++++++++ src/logo/ascii/m/macos_old.txt | 17 +++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/logo/ascii/m/macos_old.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 577aafa8a..f6165db0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,9 @@ Bugfixes: * Note: Although 32-bit systems are still supported, they are deprecated and barely tested. Users are encouraged to upgrade to 64-bit systems. * Some internal cleanups and optimizations. +Logos: +* Added macOS_old + # 2.67.1 Bugfixes: diff --git a/src/logo/ascii/m.inc b/src/logo/ascii/m.inc index 68faf3b9d..68bc8cc0e 100644 --- a/src/logo/ascii/m.inc +++ b/src/logo/ascii/m.inc @@ -103,6 +103,19 @@ static const FFlogo M[] = { .colorTitle = FF_COLOR_FG_GREEN, }, #endif + #ifdef FASTFETCH_DATATEXT_LOGO_MACOS_OLD + // MacOS_old + { + .names = { "macOS_old" }, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_MACOS_OLD, + .colors = { + FF_COLOR_FG_CYAN, + FF_COLOR_FG_BLUE, + FF_COLOR_FG_DEFAULT, + }, + }, + #endif #ifdef FASTFETCH_DATATEXT_LOGO_MAINSAILOS // MainsailOS { diff --git a/src/logo/ascii/m/macos_old.txt b/src/logo/ascii/m/macos_old.txt new file mode 100644 index 000000000..c5cf0c70d --- /dev/null +++ b/src/logo/ascii/m/macos_old.txt @@ -0,0 +1,17 @@ + $3@@ + $3@@ +$2((((((((((((((((((((($3@@$1****************** +$2(((((((((((((((((((($3@@$1******************* +$2(((((((((($3%%$2((((((($3@@$1********$3@@$1********** +$2(((((((((($3%%$2(((((($3@@$1*********$3@@$1********** +$2((((((((((((((((($3@@$1********************** +$2(((((((((((((((($3@@$1*********************** +$2((((((((((((((($3@@$1************************ +$2(((((((((((((($3@@@@@@@@$1******************* +$2(((((((((((((((((((($3@@$1******************* +$2(((((((($3%%%%%%%%%%%@@@@@@@@@@@@@@$1******** +$2(((((((((((((((((((($3@@$1******************* +$2((((((((((((((((((((($3@@$1****************** + $3@@ + @@ + @@ \ No newline at end of file From d7de7c41ca113c3a68a6f60060084b896ea8de4b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 15:28:18 +0800 Subject: [PATCH 077/109] CI: disables fail on alert --- .github/workflows/build-benchmark.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-benchmark.yml b/.github/workflows/build-benchmark.yml index 827d81c39..ebead8bf3 100644 --- a/.github/workflows/build-benchmark.yml +++ b/.github/workflows/build-benchmark.yml @@ -38,7 +38,6 @@ jobs: ref: ${{ github.sha }} auto-push: true summary-always: true - fail-on-alert: true benchmark-data-dir-path: dev/bench - name: publish benchmark dashboard From 4d00dc6802f1a45a0f5c1fba55da3cd5db6410cc Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 09:48:39 +0800 Subject: [PATCH 078/109] Logo (Builtin): adds omarchy --- CHANGELOG.md | 1 + src/logo/ascii/o.inc | 25 +++++++++++++++++++++++++ src/logo/ascii/o/omarchy.txt | 15 +++++++++++++++ src/logo/ascii/o/omarchy2.txt | 10 ++++++++++ 4 files changed, 51 insertions(+) create mode 100644 src/logo/ascii/o/omarchy.txt create mode 100644 src/logo/ascii/o/omarchy2.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index f6165db0d..c1e174428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Bugfixes: Logos: * Added macOS_old +* Added Omarchy, Omarchy2 # 2.67.1 diff --git a/src/logo/ascii/o.inc b/src/logo/ascii/o.inc index b5b32a902..54b9282f0 100644 --- a/src/logo/ascii/o.inc +++ b/src/logo/ascii/o.inc @@ -37,6 +37,31 @@ static const FFlogo O[] = { }, }, #endif + #ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY + // Omarchy + { + .names = { "Omarchy" }, + .lines = FASTFETCH_DATATEXT_LOGO_OMARCHY, + .colors = { + FF_COLOR_FG_256 "149", + }, + .colorKeys = FF_COLOR_FG_256 "149", + .colorTitle = FF_COLOR_FG_256 "111", + }, + #endif + #ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY2 + // Omarchy2 + { + .names = { "Omarchy2" }, + .lines = FASTFETCH_DATATEXT_LOGO_OMARCHY2, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .colors = { + FF_COLOR_FG_256 "149", + }, + .colorKeys = FF_COLOR_FG_256 "149", + .colorTitle = FF_COLOR_FG_256 "111", + }, + #endif #ifdef FASTFETCH_DATATEXT_LOGO_OMNIOS // OmniOS { diff --git a/src/logo/ascii/o/omarchy.txt b/src/logo/ascii/o/omarchy.txt new file mode 100644 index 000000000..05998ae4d --- /dev/null +++ b/src/logo/ascii/o/omarchy.txt @@ -0,0 +1,15 @@ +██████████████████████████████████ +██ ██ ██ +██ █████████████ ████ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +███████ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ████████████████████████ ██ +██ ██ ██ +██████████████████ █████████████ \ No newline at end of file diff --git a/src/logo/ascii/o/omarchy2.txt b/src/logo/ascii/o/omarchy2.txt new file mode 100644 index 000000000..c06e6802c --- /dev/null +++ b/src/logo/ascii/o/omarchy2.txt @@ -0,0 +1,10 @@ + ▄▄▄ + ▄█████▄ ▄███████████▄ ▄███████ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ +███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ +███ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ +███ ███ ███ ███ ███ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███ +███ ███ ███ ███ ███ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███ +███ ███ ███ ███ ███ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███ +███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ▀█████▀ ▀█ ███ █▀ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀ + ███ █▀ \ No newline at end of file From 14cf6bfdc1137384adaa62884c64cce667c7b355 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 15:36:25 +0800 Subject: [PATCH 079/109] Top (macOS): adds comments --- src/detection/top/top_apple.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index fc8f5c998..3c8250526 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -46,6 +46,17 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInitS(&item->name, proc->kp_proc.p_comm); item->pid = (uint32_t) pid; + // Note: Do NOT use proc->kp_proc.p_pctcpu for CPU usage. p_pctcpu is a + // decaying average (fixpt_t with FSCALE=2048) updated roughly once per + // second by the kernel. It is heavily smoothed, lags short bursts, has + // low resolution, and its multicore scaling (>100%) is inconsistent + // across XNU versions. It also breaks the unified model where + // FFTopProcessSnapshot.cpuTime is cumulative time and top.c computes + // (new - old) / elapsed * 100 for all platforms. proc_pid_rusage with + // RUSAGE_INFO_V2 provides precise cumulative ri_user_time + + // ri_system_time in nanoseconds and is the modern recommended API on + // Darwin, consistent with Linux/BSD differential sampling and accurate + // for the short waitTime interval (e.g. 100ms). item->cpuTime = (rusage.ri_user_time + rusage.ri_system_time) / 1000000u; // ns -> ms item->memBytes = rusage.ri_resident_size; item->bytesRead = rusage.ri_diskio_bytesread; From 51b370a10576faedf0acccd88a5352999d0eac70 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 15:21:52 +0800 Subject: [PATCH 080/109] Processes: adds total thread count detection --- CMakeLists.txt | 4 +- src/detection/processes/processes.h | 8 ++- src/detection/processes/processes_apple.c | 21 ++++++++ src/detection/processes/processes_bsd.c | 28 +++++----- src/detection/processes/processes_gnu.c | 19 +++++-- src/detection/processes/processes_haiku.c | 5 +- src/detection/processes/processes_linux.c | 51 +++++++++++++++---- src/detection/processes/processes_nbsd.c | 27 ++++++++-- src/detection/processes/processes_nosupport.c | 2 +- src/detection/processes/processes_obsd.c | 25 ++++++--- src/detection/processes/processes_sunos.c | 38 ++++++++++++++ src/detection/processes/processes_windows.c | 15 ++++-- src/modules/processes/processes.c | 13 ++--- 13 files changed, 202 insertions(+), 54 deletions(-) create mode 100644 src/detection/processes/processes_apple.c create mode 100644 src/detection/processes/processes_sunos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ba505650..a07298098 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1065,7 +1065,7 @@ elseif(APPLE) src/detection/packages/packages_apple.c src/detection/packages/packages_nix.c src/detection/poweradapter/poweradapter_apple.c - src/detection/processes/processes_bsd.c + src/detection/processes/processes_apple.c src/detection/sound/sound_apple.c src/detection/swap/swap_apple.c src/detection/terminalfont/terminalfont_apple.m @@ -1240,7 +1240,7 @@ elseif(SunOS) src/detection/os/os_sunos.c src/detection/packages/packages_sunos.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_linux.c + src/detection/processes/processes_sunos.c src/detection/gtk_qt/qt.c src/detection/sound/sound_sunos.c src/detection/swap/swap_sunos.c diff --git a/src/detection/processes/processes.h b/src/detection/processes/processes.h index 69cf46381..f9dc380cb 100644 --- a/src/detection/processes/processes.h +++ b/src/detection/processes/processes.h @@ -2,4 +2,10 @@ #include "fastfetch.h" -const char* ffDetectProcesses(uint32_t* result); +typedef struct FFProcessesResult +{ + uint32_t processes; + uint32_t threads; +} FFProcessesResult; + +const char* ffDetectProcesses(FFProcessesResult* result); diff --git a/src/detection/processes/processes_apple.c b/src/detection/processes/processes_apple.c new file mode 100644 index 000000000..6866c64fe --- /dev/null +++ b/src/detection/processes/processes_apple.c @@ -0,0 +1,21 @@ +#include "processes.h" +#include "common/mallocHelper.h" + +#import + +const char* ffDetectProcesses(FFProcessesResult* result) { + FF_AUTO_FREE pid_t* pids = malloc(sizeof(pid_t) * 0x1000); + int count = proc_listallpids(pids, 0x1000); + int trdCount = 0; + for (int index = 0; index < count; ++index) { + struct proc_taskinfo taskInfo; + if (proc_pidinfo(pids[index], PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) { + continue; + } + trdCount += taskInfo.pti_threadnum; + } + + result->processes = (uint32_t) count; + result->threads = (uint32_t) trdCount; + return nullptr; +} diff --git a/src/detection/processes/processes_bsd.c b/src/detection/processes/processes_bsd.c index 4d16bc3af..8410e2901 100644 --- a/src/detection/processes/processes_bsd.c +++ b/src/detection/processes/processes_bsd.c @@ -1,23 +1,23 @@ #include "processes.h" #include -#ifdef __FreeBSD__ - #include - #include -#endif +#include +#include -#ifndef KERN_PROC_PROC - #define KERN_PROC_PROC KERN_PROC_ALL // Apple -#endif - -const char* ffDetectProcesses(uint32_t* result) { - int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; - size_t length; - - if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { +const char* ffDetectProcesses(FFProcessesResult* result) { + int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; + size_t procLength; + if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; } - *result = (uint32_t) (length / sizeof(struct kinfo_proc)); + int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t threadLength; + if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); + result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); return nullptr; } diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c index 7dc739d2b..73d287d5d 100644 --- a/src/detection/processes/processes_gnu.c +++ b/src/detection/processes/processes_gnu.c @@ -3,7 +3,7 @@ #include #include -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { struct ps_context* context = nullptr; if (ps_context_create(getproc(), &context) != 0) { return "ps_context_create(getproc()) failed"; @@ -16,15 +16,26 @@ const char* ffDetectProcesses(uint32_t* result) { goto done; } - // No flags are needed; we only count the processes. - if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + struct proc_stat **stats = nullptr; + unsigned int numProcs = 0; + if (proc_stat_list_add_all(list, &stats, &numProcs) != 0) { error = "proc_stat_list_add_all() failed"; goto done; } - *result = (uint32_t) list->num_procs; + uint32_t nthread = 0; + for (unsigned int i = 0; i < numProcs; i++) { + proc_stat_get_basic_info(stats[i]); + nthread += proc_stat_thread_count(stats[i]); + } + + result->processes = (uint32_t) numProcs; + result->threads = nthread; done: + if (stats) { + proc_stat_list_free_stats(stats, numProcs); + } if (list) { proc_stat_list_free(list); } diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c index 0d960ab39..8b0c1cd4b 100644 --- a/src/detection/processes/processes_haiku.c +++ b/src/detection/processes/processes_haiku.c @@ -2,13 +2,14 @@ #include -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { system_info info; if (get_system_info(&info) != B_OK) { return "Error getting system info"; } - *result = info.used_teams; + result->processes = info.used_teams; + result->threads = info.used_threads; return nullptr; } diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 78790c2eb..05048d55a 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -1,27 +1,60 @@ #include "processes.h" #include "common/io.h" +#include "common/memrchr.h" #include "common/strutil.h" -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (dir == nullptr) { return "opendir(\"/proc\") failed"; } - uint32_t num = 0; + uint32_t processes = 0; + uint32_t threads = 0; + + int procfd = dirfd(dir); struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { - if ( -#ifdef _DIRENT_HAVE_D_TYPE - (entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && -#endif - ffCharIsDigit(entry->d_name[0])) - ++num; + if ((entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && ffCharIsDigit(entry->d_name[0])) { + ++processes; + + char statPath[32]; + strcpy(ffStrCopy(statPath, entry->d_name, sizeof(statPath)), "/stat"); + + char statBuffer[256]; + ssize_t statLength = ffReadFileDataRelative(procfd, statPath, sizeof(statBuffer) - 1, statBuffer); + if (statLength < 0) { + continue; + } + statBuffer[statLength] = '\0'; + + const char* cursor = (const char*) memrchr(statBuffer, ')', (size_t) statLength); + if (!cursor) { + continue; + } + ++cursor; + + for (uint32_t field = 2 /*comm*/; field < 20 /*num_threads*/; ++field) { + while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { + ++cursor; + } + ++cursor; + if (__builtin_expect(*cursor == '\0', false)) { + break; + } + } + if (__builtin_expect(*cursor == '\0', false)) { + continue; + } + + threads += (uint32_t) strtoul(cursor, nullptr, 10); + } } - *result = num; + result->processes = processes; + result->threads = threads; return nullptr; } diff --git a/src/detection/processes/processes_nbsd.c b/src/detection/processes/processes_nbsd.c index c3e7d047f..8e89ab3a1 100644 --- a/src/detection/processes/processes_nbsd.c +++ b/src/detection/processes/processes_nbsd.c @@ -1,15 +1,34 @@ #include "processes.h" +#include "common/mallocHelper.h" #include -const char* ffDetectProcesses(uint32_t* result) { - int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), 0 }; +const char* ffDetectProcesses(FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length = 0; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed"; } - *result = (uint32_t) (length / sizeof(struct kinfo_proc2)); + FF_AUTO_FREE struct kinfo_proc2* procs = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, procs}) failed"; + } + + uint32_t procCount = (uint32_t) (length / sizeof(struct kinfo_proc2)); + result->processes = procCount; + + uint32_t threads = 0; + for (uint32_t i = 0; i < procCount; ++i) { + int lwpRequest[] = { CTL_KERN, KERN_LWP, procs[i].p_pid, sizeof(struct kinfo_lwp), 0 }; + size_t lwpLength = 0; + + if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) { + threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); + } + } + + result->threads = threads; return nullptr; } diff --git a/src/detection/processes/processes_nosupport.c b/src/detection/processes/processes_nosupport.c index 7da208ec4..e7218a5c2 100644 --- a/src/detection/processes/processes_nosupport.c +++ b/src/detection/processes/processes_nosupport.c @@ -1,5 +1,5 @@ #include "processes.h" -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses([[maybe_unused]] FFProcessesResult* result) { return "Not supported on this platform"; } diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index 5a5ba31f4..cb960ce57 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -2,14 +2,25 @@ #include #include -#include -const char* ffDetectProcesses(uint32_t* result) { - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - const void* ret = kvm_getprocs(kd, KERN_PROC_ALL, 0, 1, result); - kvm_close(kd); - if (!ret) { - return "kvm_getprocs() failed"; +const char* ffDetectProcesses(FFProcessesResult* result) { + int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0 }; + size_t procLength = 0; + + if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; } + + result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); + + int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), 0 }; + size_t threadLength = 0; + + if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS}) failed"; + } + + result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); + return nullptr; } diff --git a/src/detection/processes/processes_sunos.c b/src/detection/processes/processes_sunos.c new file mode 100644 index 000000000..ce0da325c --- /dev/null +++ b/src/detection/processes/processes_sunos.c @@ -0,0 +1,38 @@ +#include "processes.h" + +#include "common/io.h" +#include "common/strutil.h" + +#include + +const char* ffDetectProcesses(FFProcessesResult* result) { + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); + if (dir == nullptr) { + return "opendir(\"/proc\") failed"; + } + + uint32_t processes = 0; + uint32_t threads = 0; + + int procfd = dirfd(dir); + + struct dirent* entry; + while ((entry = readdir(dir)) != nullptr) { + if (ffCharIsDigit(entry->d_name[0])) { + ++processes; + + char psinfoPath[32]; + strcpy(ffStrCopy(psinfoPath, entry->d_name, sizeof(psinfoPath)), "/psinfo"); + + psinfo_t info; + if (ffReadFileDataRelative(procfd, psinfoPath, sizeof(info), &info) == (ssize_t) sizeof(info)) { + threads += info.pr_nlwp; + } + } + } + + result->processes = processes; + result->threads = threads; + + return nullptr; +} diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index 78ed840b4..cb617099e 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -4,7 +4,7 @@ #include #include -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; // Multiple attempts in case processes change while @@ -25,10 +25,17 @@ const char* ffDetectProcesses(uint32_t* result) { } } - *result = 1; // Init with 1 because we test for ptr->NextEntryOffset - for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - ++*result; + uint32_t processes = 0; + uint32_t threads = 0; + for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { + ++processes; + threads += ptr->NumberOfThreads; + if (ptr->NextEntryOffset == 0) { + break; + } } + result->processes = processes; + result->threads = threads; return nullptr; } diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 428120456..9bb68239c 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -5,8 +5,8 @@ #include "modules/processes/processes.h" bool ffPrintProcesses(FFProcessesOptions* options) { - uint32_t numProcesses = 0; - const char* error = ffDetectProcesses(&numProcesses); + FFProcessesResult result = {}; + const char* error = ffDetectProcesses(&result); if (error) { ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); @@ -16,9 +16,9 @@ bool ffPrintProcesses(FFProcessesOptions* options) { if (options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - printf("%u\n", numProcesses); + printf("%u (%u threads)\n", result.processes, result.threads); } else { - FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.processes, "result") })); } return true; @@ -41,7 +41,7 @@ void ffGenerateProcessesJsonConfig(FFProcessesOptions* options, yyjson_mut_doc* } bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - uint32_t result; + FFProcessesResult result = {}; const char* error = ffDetectProcesses(&result); if (error) { @@ -49,7 +49,8 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, return false; } - yyjson_mut_obj_add_uint(doc, module, "result", result); + yyjson_mut_obj_add_uint(doc, module, "processes", result.processes); + yyjson_mut_obj_add_uint(doc, module, "threads", result.threads); return true; } From 2c4caf8e0d74fa9f3e50de50c115b45e5d7c0f53 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 16:22:33 +0800 Subject: [PATCH 081/109] Top: removes realloc retries --- src/detection/top/top_apple.c | 26 +++++++++----------------- src/detection/top/top_bsd.c | 18 ++++-------------- src/detection/top/top_dbsd.c | 21 ++++++--------------- src/detection/top/top_nbsd.c | 21 ++++++--------------- 4 files changed, 25 insertions(+), 61 deletions(-) diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index 3c8250526..862431381 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -10,33 +10,25 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { size_t length; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc); - struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); for (uint32_t i = 0; i < count; ++i) { const struct kinfo_proc* proc = &processes[i]; - pid_t pid = proc->kp_proc.p_pid; - if (pid <= 0) { + if (proc->kp_proc.p_flag & P_SYSTEM) { continue; } + pid_t pid = proc->kp_proc.p_pid; struct rusage_info_v2 rusage; if (proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*) &rusage) != 0) { diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c index 620b234b1..6c0f62018 100644 --- a/src/detection/top/top_bsd.c +++ b/src/detection/top/top_bsd.c @@ -15,20 +15,10 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc); - struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; } uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 1a9bbb888..858cc616d 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -11,24 +11,15 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { size_t length; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc); - struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc); + + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; } uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c index 277354ed3..1bc8e6543 100644 --- a/src/detection/top/top_nbsd.c +++ b/src/detection/top/top_nbsd.c @@ -11,24 +11,15 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { size_t length; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed"; } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc2* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc2); - struct kinfo_proc2* newProcesses = (struct kinfo_proc2*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc2[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc2); + + FF_AUTO_FREE struct kinfo_proc2* processes = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, processes}) failed"; } uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc2)); From f169165599d4d97684e7d9bd2bb46351d10cd890 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 18:45:16 +0800 Subject: [PATCH 082/109] Top (Linux): improves performance of `stat` parsing --- src/detection/top/top_linux.c | 72 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 28349a17d..2436e3ce7 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -18,40 +18,49 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r } ffStrbufSetNS(&result->name, (uint32_t) (close - open - 1), open + 1); - const char* cursor = close + 2; // state, then fields 4.. - if (*cursor == '\0') { - FF_DEBUG("parseStat(%s): truncated after state field", result->name.chars); - return false; - } - ++cursor; - uint64_t values[19]; - for (uint32_t field = 4; field <= 22; ++field) { - while (*cursor == ' ') { - ++cursor; - } - if (*cursor == '\0') { - FF_DEBUG("parseStat(%s): truncated at field %u", result->name.chars, field); - return false; - } - char* end; - errno = 0; - unsigned long long value = strtoull(cursor, &end, 10); - if (end == cursor || errno == ERANGE) { - FF_DEBUG("parseStat(%s): invalid number at field %u", result->name.chars, field); - return false; - } - values[field - 4] = (uint64_t) value; - cursor = end; - } - - if (values[5] & PF_KTHREAD) { // values[5] is field 9 (flags) - FF_DEBUG("Skip kernel thread: %s", result->name.chars); + const char* cursor = close + 2; // skip ") " + if (__builtin_expect(cursor >= buffer + length, false)) { return false; } - result->cpuTime = values[11] + values[12]; // user + system - result->startTime = values[18]; + result->cpuTime = 0; + + char* p; + for (uint32_t field = 3; field <= 22 /*start time*/; ++field) { + switch (field) { + case 9: // flags + if ((strtoul(cursor, &p, 10) & PF_KTHREAD)) { + FF_DEBUG("parseStat: skipping kernel task %s", result->name.chars); + return false; + } + cursor = p; + break; + + case 14: // user + case 15: // system + result->cpuTime += (uint64_t) strtoull(cursor, &p, 10); + cursor = p; + break; + + case 22: // start time + result->startTime = (uint64_t) strtoull(cursor, &p, 10); + cursor = p; + break; + + default: + while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { + ++cursor; + } + break; + } + + ++cursor; + if (__builtin_expect(cursor >= buffer + length, false)) { + return false; + } + } + return true; } @@ -72,7 +81,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int procfd = dirfd(dir); struct dirent* entry; - char statBuffer[4096]; + char statBuffer[1024]; char statmBuffer[256]; while ((entry = readdir(dir))) { if (!entry->d_name[0] || !ffCharIsDigit(entry->d_name[0])) { @@ -119,6 +128,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInit(&snapshot->name); + if (!parseStat(statBuffer, (size_t) statLength, snapshot)) { ffStrbufDestroy(&snapshot->name); --snapshots->length; From 41da49f5797c0672681dc601260cd8a0e2384598 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 18:53:56 +0800 Subject: [PATCH 083/109] Top (SunOS / Hurd): skips kernel tasks --- src/detection/top/top_dbsd.c | 4 ++-- src/detection/top/top_gnu.c | 7 ++++++- src/detection/top/top_sunos.c | 12 +++++++++--- src/detection/top/top_windows.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 858cc616d..56a572e65 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -28,8 +28,8 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { for (uint32_t i = 0; i < count; ++i) { const struct kinfo_proc* proc = &processes[i]; - // Kernel threads are reported with P_SYSTEM flags and pid -1. - if ((proc->kp_flags & P_SYSTEM) || proc->kp_stat == SZOMB) { + // KERN_PROC_ALL won't return kernel threads + if (proc->kp_stat == SZOMB) { // Ignore zombie processes continue; } diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 9bbe37aff..670f7f077 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -39,6 +39,11 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { continue; } + uint32_t pid = (uint32_t) proc_stat_pid(stat); + if (pid == 2) { // Kernel Task + continue; + } + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); // There is no kernel-side comm on the Hurd; use the first argument. @@ -51,7 +56,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { ffStrbufAppendS(&item->name, "(unknown)"); } - item->pid = (uint32_t) proc_stat_pid(stat); + item->pid = pid; if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c index f7e6a5f68..7dc9c880c 100644 --- a/src/detection/top/top_sunos.c +++ b/src/detection/top/top_sunos.c @@ -26,15 +26,21 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { continue; } + pstatus_t status; + if (ffReadFileDataRelative(subfd, "status", sizeof(status), &status) != (ssize_t) sizeof(status) || + status.pr_flags & PR_ISSYS) { + continue; // The process may have exited, no permission or is a kernel process + } + // The data model of the returned structure depends on the data model of // the calling process, not of the observed process. psinfo_t psinfo; if (ffReadFileDataRelative(subfd, "psinfo", sizeof(psinfo), &psinfo) != (ssize_t) sizeof(psinfo)) { - continue; // The process may have exited + continue; } - // pr_nlwp is zero for system processes and zombies - if (psinfo.pr_nlwp == 0 || psinfo.pr_lwp.pr_sname == 'Z') { + // zombies + if (psinfo.pr_lwp.pr_sname == 'Z') { continue; } diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index 59a5ab98d..604096403 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -33,7 +33,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { if (pidValue <= UINT32_MAX && info->CreateTime.QuadPart > 0) { FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); item->pid = (uint32_t) pidValue; - item->startTime = info->CreateTime.QuadPart > 0 ? (uint64_t) info->CreateTime.QuadPart : 0; + item->startTime = (uint64_t) info->CreateTime.QuadPart; item->cpuTime = ((uint64_t) info->UserTime.QuadPart + (uint64_t) info->KernelTime.QuadPart) / 10000u; item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize; item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount; From 7fe08bddd04a7ae69f4236670b0e1a3af1d3b841 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 17:40:57 +0800 Subject: [PATCH 084/109] Processes: adds option `countKprocs` --- CMakeLists.txt | 3 +- doc/json_schema.json | 7 ++- src/detection/processes/processes.h | 3 +- src/detection/processes/processes_apple.c | 44 ++++++++++++----- src/detection/processes/processes_bsd.c | 32 +++++++++---- src/detection/processes/processes_dbsd.c | 38 +++++++++++++++ src/detection/processes/processes_gnu.c | 27 ++++++----- src/detection/processes/processes_haiku.c | 2 +- src/detection/processes/processes_linux.c | 53 +++++++++++++-------- src/detection/processes/processes_nbsd.c | 13 +++-- src/detection/processes/processes_obsd.c | 38 +++++++++------ src/detection/processes/processes_sunos.c | 28 ++++++----- src/detection/processes/processes_windows.c | 13 +++-- src/modules/processes/option.h | 2 + src/modules/processes/processes.c | 14 ++++-- 15 files changed, 216 insertions(+), 101 deletions(-) create mode 100644 src/detection/processes/processes_dbsd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a07298098..e18136630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -813,7 +813,6 @@ elseif(FreeBSD) src/detection/os/os_linux.c src/detection/packages/packages_bsd.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_bsd.c src/detection/gtk_qt/qt.c src/detection/sound/sound_bsd.c src/detection/swap/swap_bsd.c @@ -833,12 +832,14 @@ elseif(FreeBSD) if(DragonFly) list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_nosupport.c + src/detection/processes/processes_dbsd.c src/detection/top/top_dbsd.c src/detection/wifi/wifi_nosupport.c ) else() list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_bsd.c + src/detection/processes/processes_bsd.c src/detection/top/top_bsd.c src/detection/wifi/wifi_bsd.c ) diff --git a/doc/json_schema.json b/doc/json_schema.json index e948d9285..2768b13df 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -3984,7 +3984,12 @@ "properties": { "type": { "const": "processes", - "description": "Print the number of running processes" + "description": "Print the number of running processes and threads" + }, + "countKprocs": { + "description": "Whether to take kernel processes and threads into account", + "type": "boolean", + "default": false }, "key": { "$ref": "#/$defs/key" diff --git a/src/detection/processes/processes.h b/src/detection/processes/processes.h index f9dc380cb..fdc7ceedb 100644 --- a/src/detection/processes/processes.h +++ b/src/detection/processes/processes.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/processes/option.h" typedef struct FFProcessesResult { @@ -8,4 +9,4 @@ typedef struct FFProcessesResult uint32_t threads; } FFProcessesResult; -const char* ffDetectProcesses(FFProcessesResult* result); +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result); diff --git a/src/detection/processes/processes_apple.c b/src/detection/processes/processes_apple.c index 6866c64fe..8ed1472b2 100644 --- a/src/detection/processes/processes_apple.c +++ b/src/detection/processes/processes_apple.c @@ -1,21 +1,41 @@ #include "processes.h" #include "common/mallocHelper.h" +#include #import -const char* ffDetectProcesses(FFProcessesResult* result) { - FF_AUTO_FREE pid_t* pids = malloc(sizeof(pid_t) * 0x1000); - int count = proc_listallpids(pids, 0x1000); - int trdCount = 0; - for (int index = 0; index < count; ++index) { - struct proc_taskinfo taskInfo; - if (proc_pidinfo(pids[index], PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) { - continue; - } - trdCount += taskInfo.pti_threadnum; +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + if (!options->countKprocs && (proc->kp_proc.p_flag & P_SYSTEM)) { + continue; + } + result->processes++; + + pid_t pid = proc->kp_proc.p_pid; + struct proc_taskinfo taskInfo; + if (proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) { + continue; + } + result->threads += taskInfo.pti_threadnum; } - result->processes = (uint32_t) count; - result->threads = (uint32_t) trdCount; return nullptr; } diff --git a/src/detection/processes/processes_bsd.c b/src/detection/processes/processes_bsd.c index 8410e2901..32ee53736 100644 --- a/src/detection/processes/processes_bsd.c +++ b/src/detection/processes/processes_bsd.c @@ -1,23 +1,35 @@ #include "processes.h" +#include "common/mallocHelper.h" #include #include #include -const char* ffDetectProcesses(FFProcessesResult* result) { - int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; - size_t procLength; - if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; + size_t length; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; } - int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - size_t threadLength; - if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* procs = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &procs[i]; + + if (!options->countKprocs && (proc->ki_flag & P_KPROC)) { + continue; + } + + result->processes++; + result->threads += (uint32_t) proc->ki_numthreads; } - result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); - result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); return nullptr; } diff --git a/src/detection/processes/processes_dbsd.c b/src/detection/processes/processes_dbsd.c new file mode 100644 index 000000000..c0fa246de --- /dev/null +++ b/src/detection/processes/processes_dbsd.c @@ -0,0 +1,38 @@ +#include "processes.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | (options->countKprocs ? KERN_PROC_FLAG_LWKT : 0) }; + size_t length; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* procs = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &procs[i]; + + if (proc->kp_pid == -1) { + // Kernel thread, only returned when countKprocs is set via KERN_PROC_FLAG_LWKT + result->threads++; + continue; + } + + result->processes++; + result->threads += (uint32_t) proc->kp_nthreads; + } + + return nullptr; +} diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c index 73d287d5d..ba4351f5e 100644 --- a/src/detection/processes/processes_gnu.c +++ b/src/detection/processes/processes_gnu.c @@ -3,7 +3,7 @@ #include #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { struct ps_context* context = nullptr; if (ps_context_create(getproc(), &context) != 0) { return "ps_context_create(getproc()) failed"; @@ -16,26 +16,27 @@ const char* ffDetectProcesses(FFProcessesResult* result) { goto done; } - struct proc_stat **stats = nullptr; - unsigned int numProcs = 0; - if (proc_stat_list_add_all(list, &stats, &numProcs) != 0) { + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { error = "proc_stat_list_add_all() failed"; goto done; } - uint32_t nthread = 0; - for (unsigned int i = 0; i < numProcs; i++) { - proc_stat_get_basic_info(stats[i]); - nthread += proc_stat_thread_count(stats[i]); + proc_stat_list_set_flags(list, PSTAT_NUM_THREADS); + + for (uint32_t i = 0; i < list->num_procs; i++) { + struct proc_stat* stat = list->proc_stats[i]; + if (!options->countKprocs && proc_stat_pid(stat) == 2) { // Kernel Task + continue; + } + + if (proc_stat_has(stat, PSTAT_NUM_THREADS)) { + result->threads += proc_stat_num_threads(stat); + } } - result->processes = (uint32_t) numProcs; - result->threads = nthread; + result->processes = (uint32_t) list->num_procs; done: - if (stats) { - proc_stat_list_free_stats(stats, numProcs); - } if (list) { proc_stat_list_free(list); } diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c index 8b0c1cd4b..484a32119 100644 --- a/src/detection/processes/processes_haiku.c +++ b/src/detection/processes/processes_haiku.c @@ -2,7 +2,7 @@ #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions*, FFProcessesResult* result) { system_info info; if (get_system_info(&info) != B_OK) { return "Error getting system info"; diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 05048d55a..68f819481 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -4,26 +4,23 @@ #include "common/memrchr.h" #include "common/strutil.h" -const char* ffDetectProcesses(FFProcessesResult* result) { +#define PF_KTHREAD 0x00200000 // defined in kernel include/linux/sched.h + +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (dir == nullptr) { return "opendir(\"/proc\") failed"; } - uint32_t processes = 0; - uint32_t threads = 0; - int procfd = dirfd(dir); struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { if ((entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && ffCharIsDigit(entry->d_name[0])) { - ++processes; - char statPath[32]; strcpy(ffStrCopy(statPath, entry->d_name, sizeof(statPath)), "/stat"); - char statBuffer[256]; + char statBuffer[512]; ssize_t statLength = ffReadFileDataRelative(procfd, statPath, sizeof(statBuffer) - 1, statBuffer); if (statLength < 0) { continue; @@ -34,27 +31,43 @@ const char* ffDetectProcesses(FFProcessesResult* result) { if (!cursor) { continue; } - ++cursor; + cursor += 2; // skip ") " + if (__builtin_expect(cursor >= statBuffer + statLength, false)) { + goto skip_process; + } - for (uint32_t field = 2 /*comm*/; field < 20 /*num_threads*/; ++field) { - while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { - ++cursor; + char* p; + for (uint32_t field = 3; field <= 20 /*num_threads*/; ++field) { + switch (field) { + case 9: // flags + if ((strtoul(cursor, &p, 10) & PF_KTHREAD) && !options->countKprocs) { + goto skip_process; + } + cursor = p; + break; + + case 20: // num_threads + result->threads += (uint32_t) strtoul(cursor, &p, 10); + cursor = p; + break; + + default: + while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { + ++cursor; + } + break; } + ++cursor; - if (__builtin_expect(*cursor == '\0', false)) { - break; + if (__builtin_expect(cursor >= statBuffer + statLength, false)) { + goto skip_process; } } - if (__builtin_expect(*cursor == '\0', false)) { - continue; - } - threads += (uint32_t) strtoul(cursor, nullptr, 10); + ++result->processes; } + skip_process:; } - result->processes = processes; - result->threads = threads; - return nullptr; } diff --git a/src/detection/processes/processes_nbsd.c b/src/detection/processes/processes_nbsd.c index 8e89ab3a1..cb91db096 100644 --- a/src/detection/processes/processes_nbsd.c +++ b/src/detection/processes/processes_nbsd.c @@ -3,7 +3,7 @@ #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length = 0; @@ -17,18 +17,21 @@ const char* ffDetectProcesses(FFProcessesResult* result) { } uint32_t procCount = (uint32_t) (length / sizeof(struct kinfo_proc2)); - result->processes = procCount; - uint32_t threads = 0; for (uint32_t i = 0; i < procCount; ++i) { + const struct kinfo_proc2* proc = &procs[i]; + if (!options->countKprocs && (proc->p_flag & P_SYSTEM)) { + continue; + } + ++result->processes; + int lwpRequest[] = { CTL_KERN, KERN_LWP, procs[i].p_pid, sizeof(struct kinfo_lwp), 0 }; size_t lwpLength = 0; if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) { - threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); + result->threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); } } - result->threads = threads; return nullptr; } diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index cb960ce57..d0de8170d 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -1,26 +1,36 @@ #include "processes.h" +#include "common/mallocHelper.h" + #include #include +#include -const char* ffDetectProcesses(FFProcessesResult* result) { - int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0 }; - size_t procLength = 0; - - if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + if (!kd) { + return "kvm_open() failed"; } - result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); - - int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), 0 }; - size_t threadLength = 0; - - if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS}) failed"; + int count = 0; + // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads + const struct kinfo_proc* procs = kvm_getprocs(kd, + (options->countKprocs ? KERN_PROC_KTHREAD : KERN_PROC_ALL) | KERN_PROC_SHOW_THREADS, + 0, sizeof(struct kinfo_proc), &count); + if (!procs) { + kvm_close(kd); + return "kvm_getprocs() failed"; } - result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); + for (int i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &procs[i]; + ++result->threads; + if (proc->p_tid == -1) { + ++result->processes; + } + } + + kvm_close(kd); return nullptr; } diff --git a/src/detection/processes/processes_sunos.c b/src/detection/processes/processes_sunos.c index ce0da325c..a815390bb 100644 --- a/src/detection/processes/processes_sunos.c +++ b/src/detection/processes/processes_sunos.c @@ -5,34 +5,36 @@ #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (dir == nullptr) { return "opendir(\"/proc\") failed"; } - uint32_t processes = 0; - uint32_t threads = 0; - int procfd = dirfd(dir); struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { if (ffCharIsDigit(entry->d_name[0])) { - ++processes; - - char psinfoPath[32]; - strcpy(ffStrCopy(psinfoPath, entry->d_name, sizeof(psinfoPath)), "/psinfo"); + char path[32]; + char* pidEnd = ffStrCopy(path, entry->d_name, sizeof(path)); + if (!options->countKprocs) { + pstatus_t status; + strcpy(pidEnd, "/status"); + if (ffReadFileDataRelative(procfd, path, sizeof(status), &status) != (ssize_t) sizeof(status) || + status.pr_flags & PR_ISSYS) { + continue; // The process may have exited, no permission or is a kernel process + } + } + strcpy(pidEnd, "/psinfo"); psinfo_t info; - if (ffReadFileDataRelative(procfd, psinfoPath, sizeof(info), &info) == (ssize_t) sizeof(info)) { - threads += info.pr_nlwp; + if (ffReadFileDataRelative(procfd, path, sizeof(info), &info) == (ssize_t) sizeof(info)) { + ++result->processes; + result->threads += (uint32_t) info.pr_nlwp; } } } - result->processes = processes; - result->threads = threads; - return nullptr; } diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index cb617099e..7ccd13149 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -4,7 +4,7 @@ #include #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; // Multiple attempts in case processes change while @@ -25,17 +25,16 @@ const char* ffDetectProcesses(FFProcessesResult* result) { } } - uint32_t processes = 0; - uint32_t threads = 0; for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - ++processes; - threads += ptr->NumberOfThreads; + if (!options->countKprocs && ptr->CreateTime.QuadPart == 0) { + continue; + } + ++result->processes; + result->threads += ptr->NumberOfThreads; if (ptr->NextEntryOffset == 0) { break; } } - result->processes = processes; - result->threads = threads; return nullptr; } diff --git a/src/modules/processes/option.h b/src/modules/processes/option.h index 2ee25634d..9ef218135 100644 --- a/src/modules/processes/option.h +++ b/src/modules/processes/option.h @@ -4,6 +4,8 @@ typedef struct FFProcessesOptions { FFModuleArgs moduleArgs; + + bool countKprocs; } FFProcessesOptions; static_assert(sizeof(FFProcessesOptions) <= FF_OPTION_MAX_SIZE, "FFProcessesOptions size exceeds maximum allowed size"); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 9bb68239c..e0838a925 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -6,7 +6,7 @@ bool ffPrintProcesses(FFProcessesOptions* options) { FFProcessesResult result = {}; - const char* error = ffDetectProcesses(&result); + const char* error = ffDetectProcesses(options, &result); if (error) { ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); @@ -32,17 +32,23 @@ void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module) continue; } + if (unsafe_yyjson_equals_str(key, "countKprocs")) { + options->countKprocs = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateProcessesJsonConfig(FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "countKprocs", options->countKprocs); } bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFProcessesResult result = {}; - const char* error = ffDetectProcesses(&result); + const char* error = ffDetectProcesses(options, &result); if (error) { yyjson_mut_obj_add_str(doc, module, "error", error); @@ -57,6 +63,8 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, void ffInitProcessesOptions(FFProcessesOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->countKprocs = false; } void ffDestroyProcessesOptions(FFProcessesOptions* options) { @@ -65,7 +73,7 @@ void ffDestroyProcessesOptions(FFProcessesOptions* options) { FFModuleBaseInfo ffProcessesModuleInfo = { .name = "Processes", - .description = "Print number of running processes", + .description = "Print number of running processes and threads", .displayName = { .en = "Processes", .ar = "العمليات", From 1c9e52177522a90b93fd2423bfb0144e0b9897b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 29 Aug 2026 10:32:04 +0800 Subject: [PATCH 085/109] Top: disables `FF_TOP_TYPE_DISK` on Hurd and Haiku --- src/modules/top/top.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 60ecda8a0..60b5a614e 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -223,7 +223,11 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ void ffInitTopOptions(FFTopOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); options->sort = FF_TOP_TYPE_CPU; - options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; + options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY + #if !__GNU__ && !__HAIKU__ + | FF_TOP_TYPE_DISK + #endif + ; options->nProcesses = 5; options->waitTime = 500; options->compact = false; From af8a42270c641df4911cbe0aa2ebc497484cfbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 29 Aug 2026 10:29:39 +0800 Subject: [PATCH 086/109] Top (Hurd): reports `startTime`; uses `time_value64_t` --- src/detection/top/top_gnu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 670f7f077..0407124fb 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -60,16 +60,16 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); - item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + - (uint64_t) info->user_time.microseconds / 1000 + - (uint64_t) info->system_time.seconds * 1000 + - (uint64_t) info->system_time.microseconds / 1000; + item->cpuTime = (uint64_t) info->user_time64.seconds * 1000 + + (uint64_t) info->user_time64.nanoseconds / 1000000 + + (uint64_t) info->system_time64.seconds * 1000 + + (uint64_t) info->system_time64.nanoseconds / 1000000; item->memBytes = (uint64_t) info->resident_size; + item->startTime = (uint64_t) info->creation_time64.seconds * 1000 + + (uint64_t) info->creation_time64.nanoseconds / 1000000; } - // Neither process start times nor storage io counters are exposed by - // the Hurd; leave them zeroed. - item->startTime = 0; + // Storage io counters aren't exposed by kernel; leave them zeroed. item->bytesRead = 0; item->bytesWritten = 0; } From 3abcf4195ff506c0c0d7eb26b72f99c0217a8509 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 29 Aug 2026 12:14:09 +0800 Subject: [PATCH 087/109] Processes: corrects the structure of JSON result --- src/modules/processes/processes.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index e0838a925..d6220aa03 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -55,8 +55,9 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, return false; } - yyjson_mut_obj_add_uint(doc, module, "processes", result.processes); - yyjson_mut_obj_add_uint(doc, module, "threads", result.threads); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_uint(doc, obj, "processes", result.processes); + yyjson_mut_obj_add_uint(doc, obj, "threads", result.threads); return true; } From b04587e0cbfa2c1ad940f4bee754101b176d9a4b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 29 Aug 2026 13:03:49 +0800 Subject: [PATCH 088/109] Presets: moves `top` to the bottom of running modules [ci skip] --- presets/all.jsonc | 10 +++++----- presets/ci.jsonc | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/presets/all.jsonc b/presets/all.jsonc index fdb33ac2b..73901ca30 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -19,7 +19,6 @@ "uptime", "loadavg", "processes", - "top", "packages", "shell", "editor", @@ -100,16 +99,17 @@ "gamepad", "mouse", "keyboard", - { - "type": "weather", - "timeout": 1000 - }, + "top", "netio", "diskio", { "type": "physicaldisk", "temp": true }, + { + "type": "weather", + "timeout": 1000 + }, "tpm", "version", "break", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 5499e1294..c18994df0 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -21,7 +21,6 @@ "uptime", "loadavg", "processes", - "top", "packages", "shell", "editor", @@ -102,16 +101,17 @@ "gamepad", "mouse", "keyboard", - { - "type": "weather", - "timeout": 1000 - }, + "top", "netio", "diskio", { "type": "physicaldisk", "temp": true }, + { + "type": "weather", + "timeout": 1000 + }, "tpm", "version", "logo", From 753ddec3c573b5079adf90c556c67f185165f0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 29 Aug 2026 20:09:48 +0800 Subject: [PATCH 089/109] Memory (Windows): prefers `NQSI` --- src/common/windows/nt.h | 56 +++++++++++++++++++++++++++ src/detection/memory/memory_windows.c | 31 +++++++++------ 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index 4a61b8226..ceecbf9c8 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -11,6 +11,7 @@ enum { SystemFirmwareTableInformation = 76, SystemBootEnvironmentInformation = 90, SystemLogicalProcessorAndGroupInformation = 107, + SystemBasicPerformanceInformation = 123, SystemSecureBootInformation = 146, }; @@ -198,6 +199,13 @@ typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION { _Field_size_bytes_(TableBufferLength) UCHAR TableBuffer[]; } SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; +typedef struct _SYSTEM_BASIC_PERFORMANCE_INFORMATION { + SIZE_T AvailablePages; + SIZE_T CommittedPages; + SIZE_T CommitLimit; + SIZE_T PeakCommitment; +} SYSTEM_BASIC_PERFORMANCE_INFORMATION, *PSYSTEM_BASIC_PERFORMANCE_INFORMATION; + NTSYSAPI NTSTATUS NTAPI NtDelayExecution(_In_ BOOLEAN Alertable, _In_ PLARGE_INTEGER DelayInterval); /** @@ -599,6 +607,54 @@ typedef struct _KUSER_SHARED_DATA { }; }; + // + // Reserved padding field to preserve structure alignment and compatibility. + // + + ULONG DataFlagsPad[1]; + + // + // Depending on the processor, the code for fast system call will differ, + // Stub code is provided pointers below to access the appropriate code. + // + // N.B. The following field is only used on 32-bit systems. + // + + ULONGLONG TestRetInstruction; + + // + // Query-performance counter (QPC) frequency, in counts per second. + // + // N.B. This value represents the fixed frequency of the system's high-resolution + // performance counter. It is used by user-mode time routines to convert QPC + // ticks into elapsed time without requiring a system call. The frequency is + // constant for the lifetime of the system and reflects the hardware or + // virtualized timer source selected by the kernel. + // + + LONGLONG QpcFrequency; + + // + // On AMD64, this value is initialized to a nonzero value if the system + // operates with an altered view of the system service call mechanism. + // + + ULONG SystemCall; + + // + // Reserved field - do not use. Used to be UserCetAvailableEnvironments. + // + + ULONG Reserved2; + + // + // Full 64 bit version of the number of physical pages in the system. + // This can dynamically change as physical memory can be added or removed + // from a running system. + // + + ULONGLONG FullNumberOfPhysicalPages; + // ... more fields follow, but we don't need them } KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; diff --git a/src/detection/memory/memory_windows.c b/src/detection/memory/memory_windows.c index da689621d..c86189ae6 100644 --- a/src/detection/memory/memory_windows.c +++ b/src/detection/memory/memory_windows.c @@ -1,19 +1,26 @@ #include "memory.h" -#include +#include "common/windows/nt.h" const char* ffDetectMemory(FFMemoryResult* ram) { - MEMORYSTATUSEX statex = { - .dwLength = sizeof(statex), - }; - // GlobalMemoryStatusEx() internally uses - // NtQuerySystemInformation(SystemBasicPerformanceInformation) in Win 7, and - // NtQuerySystemInformation(SystemMemoryUsageInformation) in Win 10 - if (!GlobalMemoryStatusEx(&statex)) { - return "GlobalMemoryStatusEx() failed"; - } + // Note: GlobalMemoryStatusEx() internally uses SystemMemoryUsageInformation in Win 10 - ram->bytesTotal = statex.ullTotalPhys; - ram->bytesUsed = statex.ullTotalPhys - statex.ullAvailPhys; + SYSTEM_BASIC_PERFORMANCE_INFORMATION sbpi; + if (!NT_SUCCESS(NtQuerySystemInformation(SystemBasicPerformanceInformation, &sbpi, sizeof(sbpi), NULL))) + return "Failed to query memory information"; + + uint64_t phyPages = + #if _WIN64 + SharedUserData->FullNumberOfPhysicalPages; + if (__builtin_expect(phyPages == 0, false)) { // Not supported on Windows 8.1 + phyPages = SharedUserData->NumberOfPhysicalPages; // ULONG, maximum 16 TB + } + #else + SharedUserData->NumberOfPhysicalPages; + #endif + + uint64_t pageSize = instance.state.platform.sysinfo.pageSize; + ram->bytesTotal = phyPages * pageSize; + ram->bytesUsed = (phyPages - sbpi.AvailablePages) * pageSize; return nullptr; } From 4dba32aabb888e4cb58ba3383ca29a829ed7448e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 30 Aug 2026 19:03:54 +0800 Subject: [PATCH 090/109] WM (macOS): improves reliability of WM plugin detection --- src/common/impl/sysctl.c | 15 --------------- src/common/sysctl.h | 1 - src/detection/wm/wm_apple.m | 21 ++++++++++++++------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/common/impl/sysctl.c b/src/common/impl/sysctl.c index 122a79091..29d4a3afc 100644 --- a/src/common/impl/sysctl.c +++ b/src/common/impl/sysctl.c @@ -116,18 +116,3 @@ int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) { } } #endif // OpenBSD - -void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength) { - if (sysctl(request, requestLength, nullptr, resultLength, nullptr, 0) != 0) { - return nullptr; - } - - void* data = malloc(*resultLength); - - if (sysctl(request, requestLength, data, resultLength, nullptr, 0) != 0) { - free(data); - return nullptr; - } - - return data; -} diff --git a/src/common/sysctl.h b/src/common/sysctl.h index 7e59ec663..9d12df6fc 100644 --- a/src/common/sysctl.h +++ b/src/common/sysctl.h @@ -14,4 +14,3 @@ const char* ffSysctlGetString(const char* propName, FFstrbuf* result); [[nodiscard]] int ffSysctlGetInt(const char* propName, int defaultValue); [[nodiscard]] int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue); #endif -[[nodiscard]] void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength); diff --git a/src/detection/wm/wm_apple.m b/src/detection/wm/wm_apple.m index c4bc780a2..e02c089bb 100644 --- a/src/detection/wm/wm_apple.m +++ b/src/detection/wm/wm_apple.m @@ -11,16 +11,23 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - u_int requestLength = ARRAY_SIZE(request); + size_t length; - size_t length = 0; - FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length); - if (processes == nullptr) { - return "sysctl(CTL_KERN, KERN_PROC, KERN_PROC_ALL) failed"; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; } - assert(length % sizeof(struct kinfo_proc) == 0); - for (size_t i = 0; i < length / sizeof(struct kinfo_proc); i++) { + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + for (size_t i = 0; i < count; i++) { const struct kinfo_proc* proc = &processes[i]; if (proc->kp_eproc.e_ppid != 1) { continue; From 39024abae958ff0cef8a5bd7ab83740ba3e61148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 30 Aug 2026 19:41:18 +0800 Subject: [PATCH 091/109] Processes (Haiku): honors `options->countKprocs` --- src/detection/processes/processes_haiku.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c index 484a32119..feecc34e5 100644 --- a/src/detection/processes/processes_haiku.c +++ b/src/detection/processes/processes_haiku.c @@ -2,7 +2,7 @@ #include -const char* ffDetectProcesses(const FFProcessesOptions*, FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { system_info info; if (get_system_info(&info) != B_OK) { return "Error getting system info"; @@ -11,5 +11,13 @@ const char* ffDetectProcesses(const FFProcessesOptions*, FFProcessesResult* resu result->processes = info.used_teams; result->threads = info.used_threads; + if (!options->countKprocs) { + team_info ti; + if (get_team_info(B_SYSTEM_TEAM, &ti) == B_OK) { + result->processes--; + result->threads -= (uint32_t) ti.thread_count; + } + } + return nullptr; } From 5b1ad1008dff9d53596460bf05d37ba7bf78e9c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 18:07:08 +0000 Subject: [PATCH 092/109] CI: Bump the github-actions group with 3 updates Bumps the github-actions group with 3 updates: [uraimo/run-on-arch-action](https://github.com/uraimo/run-on-arch-action), [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action). Updates `uraimo/run-on-arch-action` from 3.1.0 to 3.2.0 - [Release notes](https://github.com/uraimo/run-on-arch-action/releases) - [Commits](https://github.com/uraimo/run-on-arch-action/compare/f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9...460cb8e6d9f726a588fc9b5e681c8a6cab09ae41) Updates `github/codeql-action/init` from 4.37.7 to 4.37.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28) Updates `github/codeql-action/analyze` from 4.37.7 to 4.37.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28) --- updated-dependencies: - dependency-name: uraimo/run-on-arch-action dependency-version: 3.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/init dependency-version: 4.37.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.37.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-linux-armv7l.yml | 2 +- .github/workflows/build-linux-hosts.yml | 4 ++-- .github/workflows/build-linux-vms.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-linux-armv7l.yml b/.github/workflows/build-linux-armv7l.yml index 981ab48c4..16d239c5d 100644 --- a/.github/workflows/build-linux-armv7l.yml +++ b/.github/workflows/build-linux-armv7l.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: run VM - uses: uraimo/run-on-arch-action@f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9 # v3.1.0 + uses: uraimo/run-on-arch-action@460cb8e6d9f726a588fc9b5e681c8a6cab09ae41 # v3.2.0 id: runcmd with: arch: armv7 diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index 19aec15b0..51fe44c27 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -52,7 +52,7 @@ jobs: - name: Initialize CodeQL if: inputs.arch == 'amd64' - uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 + uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: languages: c @@ -64,7 +64,7 @@ jobs: - name: perform CodeQL analysis if: inputs.arch == 'amd64' - uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 + uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 - name: list features run: ./fastfetch --list-features diff --git a/.github/workflows/build-linux-vms.yml b/.github/workflows/build-linux-vms.yml index e61a2c52c..73bfd9c66 100644 --- a/.github/workflows/build-linux-vms.yml +++ b/.github/workflows/build-linux-vms.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: run VM - uses: uraimo/run-on-arch-action@f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9 # v3.1.0 + uses: uraimo/run-on-arch-action@460cb8e6d9f726a588fc9b5e681c8a6cab09ae41 # v3.2.0 id: runcmd with: arch: ${{ inputs.arch }} From df992414242d579ef91b3dbb13cfd07fa489e0fa Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 13:11:00 +0800 Subject: [PATCH 093/109] L10n (gl): adds missing missing Galician translations --- src/modules/custom/custom.c | 1 + src/modules/terminalsize/terminalsize.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 79c3d02f8..13a1fed0e 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -44,6 +44,7 @@ FFModuleBaseInfo ffCustomModuleInfo = { .de = "Benutzerdefiniert", .es = "Personalizado", .fr = "Personnalisé", + .gl = "Personalizado", .he = "מותאם אישית", .id = "Kustom", .it = "Personalizzato", diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 12470cd7a..cfea3bd2b 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -83,6 +83,7 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .de = "Terminalgröße", .es = "Tamaño del terminal", .fr = "Taille du terminal", + .gl = "Tamaño do terminal", .he = "גודל טרמינל", .id = "Ukuran Terminal", .it = "Dimensioni terminale", From a33d6326f1b0bee58c9a35a2ee1ec225a0f7021a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 13:31:21 +0800 Subject: [PATCH 094/109] CMake: enables `CONFIGURE_DEPENDS` to `FF_MODULE_DIRS` globbing --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e18136630..0d526dbb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,7 @@ if(APPLE) option(ENABLE_APPLE_MEMSIZE_USABLE "Use usable memory size as total memory size in Memory module, to match other systems" OFF) endif() -file(GLOB FF_MODULE_DIRS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/modules" "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/*/") +file(GLOB FF_MODULE_DIRS CONFIGURE_DEPENDS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/modules" "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/*/") foreach(FF_MODULE_DIR ${FF_MODULE_DIRS}) if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/${FF_MODULE_DIR}") string(TOUPPER "${FF_MODULE_DIR}" FF_MODULE_UPPER) From d5214af189e45f800d8260f86938007002097fb8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 13:44:19 +0800 Subject: [PATCH 095/109] Global: fixes British spellings and typos found by AI --- CHANGELOG.md | 2 +- presets/examples/14.jsonc | 2 +- src/common/impl/genconfig.c | 2 +- src/common/impl/settings.c | 4 ++-- src/detection/displayserver/linux/xcb.c | 2 +- src/detection/gtk_qt/gtk.c | 2 +- src/fastfetch.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e174428..c8cde2812 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3314,7 +3314,7 @@ Features: * Enhance `--percent-type` to allow hiding other texts (#387) * Add Wifi module support for Linux * Detect scaled resolutions (Windows, macOS) -* Optimise font module printing (Windows) +* Optimize font module printing (Windows) * Detect pacman package count inside MSYS2 environment (Windows) * Add Wifi / Battery module support for Android * Disk name support for Linux diff --git a/presets/examples/14.jsonc b/presets/examples/14.jsonc index b20c54477..e85e7bfb4 100644 --- a/presets/examples/14.jsonc +++ b/presets/examples/14.jsonc @@ -12,7 +12,7 @@ }, "modules": [ { - // draw borders first to make colors of left and right border consistant + // draw borders first to make colors of left and right border consistent "key": " user", "type": "title", "format": "{user-name}", diff --git a/src/common/impl/genconfig.c b/src/common/impl/genconfig.c index fbc10d874..e81950816 100644 --- a/src/common/impl/genconfig.c +++ b/src/common/impl/genconfig.c @@ -996,7 +996,7 @@ bool ffGenConfigInteractive(FFdata* data) { success = true; } } else { - fputs("\nConfig generation cancelled.\n", stderr); + fputs("\nConfig generation canceled.\n", stderr); } ffListDestroy(&ui.items); diff --git a/src/common/impl/settings.c b/src/common/impl/settings.c index 11dbac670..dcbd8893e 100644 --- a/src/common/impl/settings.c +++ b/src/common/impl/settings.c @@ -507,8 +507,8 @@ typedef struct E_Config { Eina_List* font_defaults; } E_Config; // Must be the same name as the top level struct in e.cfg - #define FF_EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type) \ - (ffeet_eina_file_data_descriptor_class_set(clas, sizeof(*(clas)), #type, sizeof(type))) + #define FF_EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(klass, type) \ + (ffeet_eina_file_data_descriptor_class_set(klass, sizeof(*(klass)), #type, sizeof(type))) #define FF_EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct_type, member, type) \ do { \ struct_type ___ett; \ diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index f3c371137..32b20ab27 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -331,7 +331,7 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen) { } static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) { - // With all the initialisation done, start the detection + // With all the initialization done, start the detection if (xcbRandrHandleMonitors(data, screen)) { return; } diff --git a/src/detection/gtk_qt/gtk.c b/src/detection/gtk_qt/gtk.c index 1740630e1..7c9638dbd 100644 --- a/src/detection/gtk_qt/gtk.c +++ b/src/detection/gtk_qt/gtk.c @@ -111,7 +111,7 @@ static void detectGTKFromSettings(FFGTKResult* result) { } else { // Standalone WMs (Hyprland, sway, niri, i3, ...) report no DE and have no settings // daemon, but GTK apps on them still read org.gnome.desktop.interface. - // Read via DConf, not GSettings: GSettings synthesises the schema default for keys + // Read via DConf, not GSettings: GSettings synthesizes the schema default for keys // the user never set, DConf returns nothing. Runs last; applyGTKSettings() only // fills still-empty fields, so config files always win. themeName = ffSettingsGetDConf("/org/gnome/desktop/interface/gtk-theme", FF_VARIANT_TYPE_STRING).strValue; diff --git a/src/fastfetch.c b/src/fastfetch.c index b6c2ea201..3a936fb76 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -910,7 +910,7 @@ int main(int argc, char** argv) { ffStrbufSetS(&data.structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string } if (data.genConfigInteractive && !ffGenConfigInteractive(&data)) { - // User cancelled the interactive config generation + // User canceled the interactive config generation ffStrbufDestroy(&data.structure); ffStrbufDestroy(&data.structureDisabled); yyjson_doc_free(data.configDoc); From ef7f5aeac32d0173220c7466b35b6489eb40e6d8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 14:09:57 +0800 Subject: [PATCH 096/109] CPU (Android): adds pretty names of new SoCs --- src/detection/cpu/cpu_linux.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index e41aeabe8..904533e4d 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -214,9 +214,15 @@ static void detectQualcomm(FFCPUResult* cpu) { const char* name = nullptr; switch (code) { + case 8975: + name = "8 Elite Extreme Gen 6"; + break; + case 8950: + name = "8 Elite Gen 6"; + break; case 8845: name = "8 Gen 5"; - break; // ? + break; case 8850: name = "8 Elite Gen 5"; break; @@ -238,6 +244,9 @@ static void detectQualcomm(FFCPUResult* cpu) { case 8475: name = "8+ Gen 1"; break; + case 8425: + name = "8+ Gen 1 4G"; + break; case 8450: name = "8 Gen 1"; break; @@ -271,12 +280,18 @@ static void detectQualcomm(FFCPUResult* cpu) { case 6475: name = "6 Gen 3"; break; + case 6225: + name = "6s 4G Gen 2"; + break; case 6115: - name = "6s Gen 1"; + name = "6s 4G Gen 1"; break; case 6450: name = "6 Gen 1"; break; + case 4850: + name = "4 Gen 5"; + break; case 4635: name = "4s Gen 2"; break; @@ -305,6 +320,9 @@ static void detectMediaTek(FFCPUResult* cpu) { switch (code) // The SOC code of MTK Dimensity series is full of mess { + case 6995: + name = "9600"; + break; case 6993: name = "9500"; break; @@ -357,6 +375,9 @@ static void detectExynos(FFCPUResult* cpu) { const char* name = nullptr; switch (code) { + case 9975: + name = "2700"; + break; case 9965: name = "2600"; break; @@ -374,6 +395,9 @@ static void detectExynos(FFCPUResult* cpu) { name = "2100"; break; + case 8865: + name = "1680"; + break; case 8855: name = "1580"; break; From 42002a6240ce00756f2bfa03418fa6c08687f9be Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 14:26:50 +0800 Subject: [PATCH 097/109] CPU (Linux): supports more Snapdragon X SoCs --- CHANGELOG.md | 1 + src/detection/cpu/cpu_linux.c | 67 +++++++++++++++++++++++++++-------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8cde2812..a18be3800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Features: * Improved fish completion scripts to print enum descriptions. (Completion) * Enabled Wayland support on Android. (DisplayServer, Android) * Added DE detection support for ASUS Zenfone. (DE, Android) +* Added new ARM SoCs (CPU, Linux / Android) Bugfixes: * Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 904533e4d..589d0ac01 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -837,6 +837,46 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) { return nullptr; } +[[maybe_unused]] static bool detectSnapdragonX(FFstrbuf* name, const char* model) { + // SoC models are enumerated in the form of `x[e|p]`, e.g. `x1e80100`, + // which is marketed as `X1E-80-100`, where `e` stands for Elite and `p` for Plus. + // https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems_on_chips#Snapdragon_X_series + const char* prefix; + uint32_t prefixLen; + + if (ffStrStartsWith(model, "x1e")) { + prefix = "Qualcomm Snapdragon X Elite"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x1p")) { + prefix = "Qualcomm Snapdragon X Plus"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x2e")) { + // Only X2E-94-100 and X2E-96-100 are branded as Extreme + prefix = model[3] == '9' ? "Qualcomm Snapdragon X2 Elite Extreme" : "Qualcomm Snapdragon X2 Elite"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x2p")) { + prefix = "Qualcomm Snapdragon X2 Plus"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x1")) { + prefix = "Qualcomm Snapdragon X"; + prefixLen = 2; + } else { + return false; + } + + uint32_t length = (uint32_t) strlen(model); + bool splitCode = length - prefixLen == 5; + + ffStrbufSetF(name, "%s X", prefix); + for (uint32_t i = 1; i < length; ++i) { + if (i == prefixLen || (splitCode && i == length - 3)) { + ffStrbufAppendC(name, '-'); + } + ffStrbufAppendC(name, (char) toupper(model[i])); + } + return true; +} + [[maybe_unused]] static void parseIsa(FFstrbuf* cpuIsa) { // Always use the last part of the ISA string. Ref: #590 #1204 ffStrbufSubstrAfterLastC(cpuIsa, ' '); @@ -938,22 +978,19 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) { } #endif else if (ffStrEquals(vendor, "qcom")) { - // https://elixir.bootlin.com/linux/v6.11/source/arch/arm64/boot/dts/qcom - if (ffStrStartsWith(model, "x")) { - ffStrbufSetS(&cpu->name, "Qualcomm Snapdragon X Elite "); - for (const char* p = model + 1; *p; ++p) { - ffStrbufAppendC(&cpu->name, (char) toupper(*p)); + // https://elixir.bootlin.com/linux/latest/source/arch/arm64/boot/dts/qcom + if (!detectSnapdragonX(&cpu->name, model)) { + if (ffStrStartsWith(model, "sc")) { + const char* code = model + 2; + uint32_t deviceId = (uint32_t) strtoul(code, nullptr, 10); + ffStrbufSetStatic(&cpu->name, ffCPUQualcommCodeToName(deviceId)); + if (!cpu->name.length) { + ffStrbufAppendS(&cpu->name, "Qualcomm Snapdragon SC"); + ffStrbufAppendS(&cpu->name, code); + } + } else { + ffStrbufSetS(&cpu->name, model); } - } else if (ffStrStartsWith(model, "sc")) { - const char* code = model + 2; - uint32_t deviceId = (uint32_t) strtoul(code, nullptr, 10); - ffStrbufSetStatic(&cpu->name, ffCPUQualcommCodeToName(deviceId)); - if (!cpu->name.length) { - ffStrbufAppendS(&cpu->name, "Qualcomm Snapdragon SC"); - ffStrbufAppendS(&cpu->name, code); - } - } else { - ffStrbufSetS(&cpu->name, model); } ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); From 76b676814176a3bd0929e504302f9760623157ee Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 14:33:43 +0800 Subject: [PATCH 098/109] JsonSchema: regenerates `moduleFormat` --- doc/json_schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 2768b13df..b2f07370d 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -398,7 +398,7 @@ "type": "string" }, "lmFormat": { - "description": "Output format for the `LM` module. See Wiki for formatting syntax\n 1. {service}: LM service\n 2. {type}: LM type\n 3. {version}: LM version", + "description": "Output format for the `LM` module. See Wiki for formatting syntax\n 1. {service}: LM service / process name\n 2. {pretty-name}: LM pretty name\n 3. {version}: LM version", "type": "string" }, "loadavgFormat": { @@ -506,7 +506,7 @@ "type": "string" }, "topFormat": { - "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second\n 7. {disk-write}: Disk write bytes per second\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second (0 if unsupported)\n 7. {disk-write}: Disk write bytes per second (0 if unsupported)\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", "type": "string" }, "themeFormat": { From 9c791b2c127467278a28c241ba9fbd3ecd04ae06 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 15:24:48 +0800 Subject: [PATCH 099/109] Doc: adds `CONTRIBUTING.md` --- .gitignore | 2 + CONTRIBUTING.md | 724 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 726 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/.gitignore b/.gitignore index 1394fe931..9fe9c7bfb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ fastfetch.kdev4 *.user.* *.swp *.log +/*.zh.md +/.*-ai/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..0da08c892 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,724 @@ +# Contributing to fastfetch + +
+ + Note + + + This document is generated by AI, and mainly for AI use. It is not a substitute for human review, and may contain errors or omissions. Please verify any information before relying on it. +
+ +Thanks for your interest in fastfetch. This document covers building, architecture, how to add a module or a logo, code style, commit conventions, and the pull request workflow. + +fastfetch is a system information tool written in C23, supporting Linux, macOS, Windows, the BSDs, Solaris, Haiku and Android. The project is borderline obsessive about **startup time** and **optional dependencies** — many design decisions only make sense under that constraint, and this document keeps coming back to it. + +--- + +## Table of contents + +- [Contributor quick reference](#contributor-quick-reference) +- [Getting started](#getting-started) +- [Code map](#code-map) +- [Core architecture: modules vs. detection](#core-architecture-modules-vs-detection) +- [Module registration](#module-registration) +- [Walkthrough: adding a module](#walkthrough-adding-a-module) +- [Walkthrough: adding a logo](#walkthrough-adding-a-logo) +- [Platform conventions](#platform-conventions) +- [Code style](#code-style) +- [Commit messages](#commit-messages) +- [Changelog](#changelog) +- [Tests](#tests) +- [Pull requests](#pull-requests) +- [Gotchas](#gotchas) + +--- + +## Contributor quick reference + +| Task | Start here | Verify with | +|---|---|---| +| Build and run fastfetch | `run.sh`, `CMakeLists.txt` | `./run.sh` | +| Add a module | `src/modules//`, `src/detection//`, `src/modules/modules.c` | `cmake -B build && cmake --build build -j` | +| Add a platform implementation | `src/detection//_.c` | Build on the target platform or CI | +| Add an ASCII logo | `src/logo/ascii//.txt`, matching `.inc` | `./build/fastfetch --logo ` | +| Change formatting or JSON output | `src/modules//.c` | `./build/fastfetch -s --format json` | +| Change shared formatting or containers | `src/common/format.h`, `src/common/color.h`, `src/common/FFstrbuf.h` | Build and run the matching test | +| Run the test suite | `tests/`, `build/` | `cd build && ctest --output-on-failure` | + +For a normal code change, the shortest useful loop is: configure, build the `fastfetch` target, run the affected module, then run the tests. If you add a directory or a generated input, re-run `cmake -B build` so CMake refreshes its file globs. + +--- + +## Getting started + +### Building + +The quickest way is `run.sh` in the repository root — it creates `build/`, configures, compiles and runs the binary: + +```sh +./run.sh # build and run +./run.sh --format json # arguments are forwarded to fastfetch +``` + +Manual build: + +```sh +cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo +cmake --build build --target fastfetch -j$(nproc) +./build/fastfetch +``` + +The default build type is `RelWithDebInfo`. LTO is enabled whenever `ENABLE_LTO=ON` **and** `CMAKE_BUILD_TYPE != Debug` — so the default already has it, and only `Debug` builds lack it. This matters because LTO here is not merely an optimization: it is what strips the code of disabled modules. See [Gotchas](#gotchas). + +### Common build options + +| Option | Default | Notes | +|---|---|---| +| `CMAKE_BUILD_TYPE` | `RelWithDebInfo` | LTO is on for anything but `Debug` | +| `BUILD_TESTS` | `OFF` | Builds the unit tests in `tests/` | +| `BUILD_FLASHFETCH` | `ON` | Also builds the stripped-down `flashfetch` | +| `BINARY_LINK_TYPE` | `dlopen` | `dlopen` / `dynamic` / `static` | +| `ENABLE_ASAN` | `OFF` | Address Sanitizer | +| `ENABLE_LTO` | `ON` | Link-time optimization | +| `MODULE_DISABLE_` | `OFF` | Disable a module, e.g. `MODULE_DISABLE_GPU=ON` | +| `SET_TWEAK` | `ON` | Appends a tweak to the dev version; turned off for releases | + +`BINARY_LINK_TYPE=dlopen` (the default) is a deliberate design choice: optional dependencies (Vulkan, Wayland, DBus, ImageMagick, chafa, …) are loaded at runtime, so a missing library never prevents startup. When adding a third-party dependency, use the dlopen helpers in `common/library.h` — do not link it directly. + +For a minimal-dependency build, see `.github/workflows/build-no-features-test.yml`: + +```sh +cmake -DBUILD_TESTS=On -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_X11=OFF \ + -DENABLE_DBUS=OFF -DENABLE_ZLIB=OFF ... . +``` + +### Dependencies + +Required: CMake ≥ 3.21 and a C23 compiler (GCC, Clang or MSVC). Everything else is optional. + +Optional dependencies are auto-detected: libpci, libdrm, vulkan, wayland, xcb, xrandr, dbus, sqlite3, rpm, imagemagick{6,7}, chafa, zlib, egl, glx, opencl, freetype, pulse, ddcutil, elf, libzfs, and more. + +--- + +## Code map + +``` +src/ +├── fastfetch.c entry point: CLI parsing, module dispatch, main loop (36 KB) +├── flashfetch.c entry point for the stripped-down build +├── options/ global (non-module) config: general / display / logo +├── modules/ module layer — module formatting and output +├── detection/ detection layer — platform-specific data retrieval +├── common/ infrastructure: FFstrbuf, FFlist, formatting, printing, networking +├── logo/ 530 ASCII logos plus the image logo backends +└── 3rdparty/ yyjson, widecharwidth, display-library +``` + +Flow of control: + +``` +fastfetch.c → options/ (global configuration) + → modules/ (76 modules, formatting and output) + → detection/ (one platform implementation each, raw data) + → common/ (infrastructure) +``` + +The number of module directories and detection directories does not match, and that is expected. The following relationships are structural rather than a fixed inventory: + +- **13 modules have no detection directory** — they are either pure layout (`break`, `separator`, `colors`, `title`, `logo`) or reuse someone else's detection result (`display`, `monitor`, `kernel`, `shell`, `terminal`, `player`, `custom`, `datetime`). +- **4 detection directories serve modules with different names** — `displayserver` (→ `display`, `monitor`), `gtk_qt` (→ `theme`, `icons`, `font`, `cursor`), `terminalshell` (→ `terminal`, `shell`) and `libc`. + +So do not assume `modules//` always has a matching `detection//`. + +### Layer boundaries + +| Layer | Owns | Must not | +|---|---|---| +| `options/` | **Global** config (colors, logo, threading, timeouts) | hold per-module options | +| `modules/` | formatting, printing, JSON serialization | read `/proc`, call Win32 APIs, parse sysfs | +| `detection/` | cross-platform data retrieval, clean result structs | print anything, read display config | +| `common/` | general-purpose utilities, no business logic | depend on a specific module | + +The test is simple: **no file under `detection/` should contain `printf` or read `instance.config`.** Symmetrically, no file under `modules/` should contain `#ifdef __linux__`. + +--- + +## Core architecture: modules vs. detection + +This is the single most important convention in the codebase. Every feature is a fixed set of files — using CPU as the example: + +``` +modules/cpu/option.h module option struct +modules/cpu/cpu.c formatting and output +detection/cpu/cpu.h platform-independent interface +detection/cpu/cpu_linux.c ┐ +detection/cpu/cpu_apple.c │ +detection/cpu/cpu_windows.c ├─ platform implementations, one linked per build +detection/cpu/cpu_bsd.c │ +detection/cpu/cpu_nosupport.c ┘ +``` + +The interface is deliberately minimal — usually just two things: + +```c +typedef struct FFCPUResult { ... } FFCPUResult; // result struct +const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu); +``` + +The `const char*` return value is an **error string**; `nullptr` means success. This pattern is used throughout `detection/` — please keep it consistent. + +Helper functions are only exposed when they are genuinely shared between platform implementations (as in `cpu.h`: `ffCPUAppleCodeToName`, `ffCPUDetectByCpuid`). + +**The payoff:** adding a platform never touches `modules/`; fixing output formatting never touches `detection/`. + +--- + +## Module registration + +### The descriptor + +Every module exports one `FFModuleBaseInfo` (defined in `common/option.h:46`) — essentially a hand-written vtable: + +```c +typedef struct FFModuleBaseInfo { + const char* name; // lookup key, e.g. "cpu" + const char* description; // help text + FFModuleDisplayName displayName; // module name in 20 languages + + void (*initOptions)(void* options); + void (*destroyOptions)(void* options); + void (*parseJsonObject)(void* options, struct yyjson_val* module); + bool (*printModule)(void* options); + bool (*generateJsonResult)(void* options, yyjson_mut_doc*, yyjson_mut_val*); + void (*generateJsonConfig)(void* options, yyjson_mut_doc*, yyjson_mut_val*); + + FFModuleFormatArgList formatArgs; // format placeholder table + const uint8_t defaultOrder; // sort weight +} FFModuleBaseInfo; +``` + +The source comment openly admits this is UB — `void*` is not compatible with `FF*Options*`. It is a pragmatic compromise to get polymorphism in C. Don't try to "fix" it. + +### The registry: a first-letter hash bucket + +`src/modules/modules.c` defines 26 `static FFModuleBaseInfo*` arrays (`A[]` through `Z[]`), each terminated by `nullptr`, collected into `ffModuleInfos[26]`: + +```c +FFModuleBaseInfo** modules = ffModuleInfos[toupper(name[0]) - 'A']; // O(1) bucket lookup +for (; *modules; ++modules) { // linear scan in the bucket + if (ffStrEqualsIgnCase(name, (*modules)->name)) { ... } +} +``` + +The registry is small enough that a subtraction plus a few string comparisons is preferable to a general-purpose hash table. When adding a module, place its descriptor in the bucket matching the first letter of `.name`; keep the existing `nullptr` terminator at the end. + +### The calling convention: zero heap allocation + +Every dispatch site (`jsonconfig.c:98`, `commandoption.c:189`) follows the same pattern: + +```c +alignas(uint64_t) uint8_t optionBuf[FF_OPTION_MAX_SIZE]; // 256 bytes, on the stack +baseInfo->initOptions(optionBuf); +baseInfo->parseJsonObject(optionBuf, jsonVal); // JSONC path only +baseInfo->printModule(optionBuf); // or generateJsonResult +baseInfo->destroyOptions(optionBuf); +``` + +`FF_OPTION_MAX_SIZE = 1 << 8` (256 bytes). Every module's `option.h` must end with: + +```c +static_assert(sizeof(FFCPUOptions) <= FF_OPTION_MAX_SIZE, "FFCPUOptions size exceeds maximum allowed size"); +``` + +**Meaning: no module option struct may exceed 256 bytes.** Hard constraint, enforced at compile time. + +The three dispatch entry points: + +| Entry point | Location | Used for | +|---|---|---| +| `parseModuleJsonObject` | `common/impl/jsonconfig.c:90` | the `modules[]` array in a JSONC config | +| `parseStructureCommand` | `common/impl/commandoption.c:181` | the colon-separated structure string | +| `ffParseModuleOptions` | `common/impl/commandoption.c:13` | **deprecated** — see [Gotchas](#4-cli-module-options-are-removed) | + +### Build-time module discovery + +`CMakeLists.txt:131` globs `src/modules/*/` and generates a `MODULE_DISABLE_` option per directory: + +```cmake +file(GLOB FF_MODULE_DIRS RELATIVE "..." ".../src/modules/*/") +foreach(FF_MODULE_DIR ${FF_MODULE_DIRS}) + option(MODULE_DISABLE_${FF_MODULE_UPPER} "Disable module ${FF_MODULE_DIR}" OFF) +endforeach() +``` + +**Adding a module requires no CMake change.** The same trick generates the package manager switches (`:146` regex-scans `src/modules/packages/option.h` for `FF_PACKAGES_FLAG_*_BIT`). + +--- + +## Walkthrough: adding a module + +Adding a `Foo` module, step by step. + +### 1. Define the option struct + +`src/modules/foo/option.h`: + +```c +#pragma once + +#include "common/option.h" + +typedef struct FFFooOptions { + FFModuleArgs moduleArgs; // must be the first field + bool showBar; +} FFFooOptions; + +static_assert(sizeof(FFFooOptions) <= FF_OPTION_MAX_SIZE, "FFFooOptions size exceeds maximum allowed size"); +``` + +`FFModuleArgs` must come first. It provides `key`, `format`, `outputColor`, `keyColor`, `keyIcon` and `keyWidth`; because it is the first field, `ffJsonConfigParseModuleArgs()` can handle these generically and you get them **for free — no parsing code to write**. + +Note these fields can only be set through the JSON config; CLI module options have been removed (see [Gotchas](#4-cli-module-options-are-removed)). + +### 2. Implement detection + +`src/detection/foo/foo.h`: + +```c +#pragma once +#include "fastfetch.h" + +typedef struct FFFooResult { + FFstrbuf name; + uint32_t count; +} FFFooResult; + +const char* ffDetectFoo(const FFFooOptions* options, FFFooResult* result); +``` + +`src/detection/foo/foo_linux.c`: + +```c +#include "foo.h" + +const char* ffDetectFoo(const FFFooOptions* options, FFFooResult* result) { + // read /sys, /proc, sysfs, dbus, ... + return nullptr; // success; return an error string on failure +} +``` + +**Write one file per target platform, and a `foo_nosupport.c` fallback for the rest.** There are already 45 `*_nosupport.c` files doing exactly this. + +### 3. Implement the module + +`src/modules/foo/foo.c` — implement the six functions, then define the descriptor: + +```c +FFModuleBaseInfo ffFooModuleInfo = { + .name = "Foo", + .description = "Print foo information", + .displayName = { + .en = "Foo", .ar = "Foo", .cs = "Foo", .de = "Foo", .es = "Foo", + .fr = "Foo", .gl = "Foo", .he = "Foo", .id = "Foo", .it = "Foo", + .ja = "Foo", .ko = "Foo", .pl = "Foo", .pt = "Foo", .ru = "Foo", + .tr = "Foo", .uk = "Foo", .vi = "Foo", .zh_CN = "Foo", .zh_TW = "Foo", + }, + .initOptions = (void*) ffInitFooOptions, + .destroyOptions = (void*) ffDestroyFooOptions, + .parseJsonObject = (void*) ffParseFooJsonObject, + .printModule = (void*) ffPrintFoo, + .generateJsonResult = (void*) ffGenerateFooJsonResult, + .generateJsonConfig = (void*) ffGenerateFooJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + { "Name", "name" }, + { "Count", "count" }, + })), + .defaultOrder = 73, +}; +``` + +Points to note: + +- **`displayName`** is a literal block of all 20 language fields — there is no shortcut macro, so copy the layout from a neighboring module: **`en`, `ar`, `cs`, `de`, `es`, `fr`, `gl`, `he`, `id`, `it`, `ja`, `ko`, `pl`, `pt`, `ru`, `tr`, `uk`, `vi`, `zh_CN`, `zh_TW`**. + **Fill in all 20.** The struct is read by byte offset (see [Gotchas](#6-localization-uses-byte-offsets-not-enums)) and there is **no fallback** — a missing field means the key prints empty in that language. +- **`formatArgs`** must be exhaustive. It drives the placeholder list printed by `fastfetch -h foo-format`; **anything you omit is invisible and unusable to the user.** +- The `moduleFormat` section in `doc/json_schema.json` is generated by `fastfetch -h format-json`. Its metadata comes from `FFModuleBaseInfo::formatArgs`. To keep the schema and module descriptors consistent, do not edit the `moduleFormat` section in `doc/json_schema.json` by hand; update the module metadata and regenerate it instead. +- **`defaultOrder`**: use the current maximum plus 1. Search the existing descriptors for `.defaultOrder =` before choosing a value; do not copy a hard-coded value from this document. Leaving it out, or setting it to `0`, makes the module **disappear** from the interactive `--gen-config` picker. Only `logo`, `command` and `custom` do this deliberately, because they need user arguments or are invoked directly by the display layer. + +### 4. Register it + +- Add `#include "modules/foo/foo.h"` to `src/modules/modules.h` +- Insert into the `F[]` array in `src/modules/modules.c`: + +```c +#if !FF_MODULE_DISABLE_FOO + &ffFooModuleInfo, +#endif +``` + +`FF_MODULE_DISABLE_FOO` is generated by CMake — you do not define it yourself. + +### 5. Modules that need warm-up + +If your module needs a sampling interval (CPU usage) or a network round-trip (public IP, weather), also implement `ffPrepareFoo()` and register it in the switch inside `ffPrepareCommandOption()` in `common/impl/commandoption.c`, under the right first-letter `case`. Six modules do this today: CPUUsage, DiskIO, NetIO, PublicIP, Top and Weather. + +### 6. Verify + +```sh +cmake -B build && cmake --build build -j +./build/fastfetch -s foo --format json # JSON output +./build/fastfetch -h foo-format # list formatArgs placeholders +./build/fastfetch --gen-config # confirm it appears in the picker +``` + +Note the `-format` suffix on the help flag: `fastfetch -h foo` does not work, only `fastfetch -h foo-format`. + +--- + +## Walkthrough: adding a logo + +A new logo **must** have a corresponding "Logo Request" issue, linked from the PR with `Closes #1234`. Logo PRs without a linked issue are not accepted. + +### 1. Drop in the ASCII file + +``` +src/logo/ascii//.txt +``` + +For example `src/logo/ascii/o/omarchy.txt`. Directories are already split by first letter (`a/` … `z/`, plus `_/`). + +The file is plain ASCII art with `$1` … `$9` as color placeholders: + +``` + $3 ,-^-___ +$3 /\\\/// +$2refined.$1 /\\\\// +``` + +- `$1` … `$9` map to palette slots 1–9; at most 9 (`FASTFETCH_LOGO_MAX_COLORS = 9`) +- `$$` is a literal `$` +- Characters without a placeholder inherit the current color. Of the 530 existing logos, 239 use no placeholders at all (monochrome) and 291 do — **new logos should use placeholders**; monochrome is a legacy style +- Tabs are expanded to 4 spaces +- Colors can be overridden with `--logo-color-1` … `--logo-color-9` + +### 2. Register it in the `.inc` + +CMake turns each `.txt` into a `FASTFETCH_DATATEXT_LOGO_` macro (`CMakeLists.txt:418`), but **the registry itself is maintained by hand**. Edit `src/logo/ascii/.inc`: + +```c +#ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY +// Omarchy +{ + .names = { "omarchy", "Omarchy" }, + .lines = FASTFETCH_DATATEXT_LOGO_OMARCHY, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_WHITE, + FF_COLOR_FG_CYAN, + }, +}, +#endif +``` + +- `names` is matched case-insensitively. Do not add names that differ only by case, because they can never be distinguished. Every name is also shown by `--list-logos`, so use user-friendly spelling such as an initial capital where appropriate. +- For a new logo, use exactly one name unless there is a specific compatibility reason to add more. That name should first be the `ID` from `/etc/os-release`. If the ID cannot distinguish this logo from another logo for the same OS, use the `NAME` value instead. `logoGetBuiltinDetected` in `src/logo/logo.c` documents the detection order: `ID`, then `NAME`, then tokens from `ID_LIKE`, then the platform name fallback. Manual `logo-source` selection uses the name directly. +- `colors` is positional — entry 0 is `$1`, entry 1 is `$2`, and so on +- `colors[0]` also becomes the title color and `colors[1]` the key color, unless the user overrides them + +If the same OS has multiple logo variants, mark the variant explicitly with `.type`: + +```c +.type = FF_LOGO_LINE_TYPE_SMALL_BIT, +``` + +Use `FF_LOGO_LINE_TYPE_ALTER_BIT` for an alternate logo, `FF_LOGO_LINE_TYPE_SMALL_BIT` for a small logo, or combine the flags when both apply. This is also a lookup optimization: a logo marked `FF_LOGO_LINE_TYPE_SMALL_BIT` is considered only for `type = small`, while a logo marked `FF_LOGO_LINE_TYPE_ALTER_BIT` is never selected by automatic detection. Alternate logos are available only when explicitly requested through `--logo `. + +### 3. Verify + +```sh +./build/fastfetch --logo omarchy +./build/fastfetch --list-logos | grep -i omarchy +``` + +--- + +## Platform conventions + +The `detection/` layer picks its implementation by **filename suffix**; the choice is made at build time from `CMAKE_SYSTEM_NAME`: + +| Suffix | Platform | +|---|---| +| `_linux.c` | Linux | +| `_apple.c` / `_apple.m` | macOS / iOS (`.m` for Objective-C) | +| `_windows.c` / `_windows.cpp` | Windows (`.cpp` for WinRT / WMI) | +| `_bsd.c` | FreeBSD | +| `_nbsd.c` | NetBSD | +| `_obsd.c` | OpenBSD | +| `_sunos.c` | Solaris / illumos | +| `_haiku.c` / `.cpp` | Haiku | +| `_android.c` | Android (Termux) | +| `_gnu.c` | GNU/Hurd | +| `_nosupport.c` | Empty fallback | + +Current distribution of platform files in `detection/`: + +| Suffix | Files | Suffix | Files | +|---|---|---|---| +| `_linux` | 58 | `_obsd` | 16 | +| `_windows` | 47 | `_haiku` | 13 | +| `_apple` | 46 | `_android` | 12 | +| `_nosupport` | 45 | `_gnu` | 3 | +| `_bsd` | 29 | | | +| `_sunos` | 19 | | | +| `_nbsd` | 17 | | | + +(These are repository inventory figures, counting `.c`, `.m`, `.cpp`, and `.h`; they may change as platforms and modules are added.) + +**Don't pile `#ifdef __linux__` into one file.** When adding platform support, copy the closest existing implementation and change the suffix. + +`common/` uses the same idea: `common/impl/` contains `io_unix.c` / `io_windows.c`, `netif_linux.c` / `netif_apple.c` / `netif_bsd.c` and so on, with `common/apple/`, `common/windows/` and `common/haiku/` holding platform-specific helpers. + +When several platform suffixes could apply, use the most specific implementation supported by the build system (for example, `_nbsd.c` instead of the generic `_bsd.c` on NetBSD). Keep the generic file as the fallback for platforms that share its conventions. + +--- + +## Code style + +### Formatting + +The project uses clang-format with `BasedOnStyle: LLVM` plus these key overrides: + +```yaml +IndentWidth: 4 +UseTab: Never +ColumnLimit: 0 # never wrap +InsertBraces: true # braces even on single-statement ifs +PointerAlignment: Left # char* p, not char *p +SortIncludes: Never # include order is managed by hand +AlignAfterOpenBracket: DontAlign +BinPackParameters: false # all params on one line, or one per line +``` + +Before committing: + +```sh +clang-format -i src/modules/foo/*.c src/modules/foo/*.h +``` + +`src/3rdparty/**`, `build/**` and `src/logo/builtin.c` are listed in `.clang-format-ignore` — **do not reformat them.** + +`.editorconfig` adds LF line endings, 4-space indent, a final newline, and trailing whitespace trimmed (except in Markdown). + +### Naming + +| Kind | Convention | Example | +|---|---|---| +| Functions | `ff` + PascalCase | `ffDetectCPU`, `ffPrintCPU` | +| Types | `FF` + PascalCase | `FFCPUResult`, `FFModuleBaseInfo` | +| Variables / fields | camelCase | `coresPhysical`, `keyWidth` | +| Macros | SCREAMING_SNAKE_CASE | `FF_OPTION_MAX_SIZE` | +| Module options | `FFOptions` | `FFCPUOptions` | +| Detection results | `FFResult` | `FFCPUResult` | + +### Spelling + +CI runs codespell (`.codespellrc`). Known false positives live in `ignore-words-list` (`iterm`, `compiletime`, and various non-English distro words). Add new words there rather than changing the code. + +### Compiler warnings + +The build enables `-Wall -Wextra -Wconversion` plus several `-Werror`s: + +``` +-Werror=uninitialized -Werror=return-type -Werror=vla +-Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion +``` + +**`-Wconversion` is strict**: every implicit narrowing conversion needs an explicit cast. + +--- + +## Commit messages + +Format: + +``` +[ (Platform)]: +``` + +Scope is the module or subsystem name; Platform is optional. Use the third-person singular present tense, capitalize the first letter, no trailing period. + +Real examples from recent history: + +``` +Processes (Haiku): honors `options->countKprocs` +WM (macOS): improves reliability of WM plugin detection +Memory (Windows): prefers `NQSI` +Top (Linux): improves performance of `stat` parsing +Logo (Builtin): adds omarchy +Global: introduces global macro `FF_PATH_PKG_BASE` to replace `_PATH_LOCALBASE` +LM (OpenBSD): adds support +CI: disables fail on alert +Doc: updates README +Presets: moves `top` to the bottom of running modules [ci skip] +``` + +Common verbs: `adds`, `removes`, `fixes`, `improves`, `updates`, `corrects`, `prefers`, `honors`, `disables`, `enables`, `introduces`, `detects`, `reports`, `skips`, `uses`. + +Scopes in use: `Top`, `Processes`, `Memory`, `Logo (Builtin)`, `CI`, `Doc`, `Presets`, `Global`, plus individual module names. + +Documentation-only changes get a `[ci skip]` suffix. + +--- + +## Changelog + +User-visible changes go into `CHANGELOG.md`, under the topmost version heading: + +```markdown +# Unreleased + +Changes: +* The DE / WM / LM modules now reports the full name ... + +Features: +* Added Top module to print processes with the highest CPU, memory or disk I/O usage. (Top) +* Improved Wi-Fi module + * Added Wifi channel width detection, exposed via `{channel-width}` in custom format. + * Improved Wifi channel frequency accuracy on Windows, macOS. +* Added Battery detection support on SunOS. (Battery, SunOS) + +Bugfixes: +* Fixed I/O rate calculation precision in DiskIO and NetIO. (DiskIO / NetIO) +``` + +Rules: + +- Three sections: `Changes:` (behavior changes), `Features:`, `Bugfixes:` +- Past tense: `Added` / `Fixed` / `Improved` +- End each entry with its scope: `(Module, Platform)` or `(ModuleA / ModuleB)` +- Sub-bullets are indented 4 spaces + +--- + +## Tests + +Tests are standalone executables in `tests/` using a `VERIFY` macro that exits non-zero on failure: + +```c +#define VERIFY(expression) \ + if (!(expression)) testFailed(&strbuf, #expression, __LINE__) +``` + +Current tests: `strbuf.c`, `list.c`, `format.c`, `color.c`, `duration.c`, `strutil.c`. + +```sh +cmake -B build -DBUILD_TESTS=On +cmake --build build +cd build && ctest --output-on-failure +``` + +Coverage focuses on the core data structures and the formatting engine in `common/`. The `detection/` layer has no automated tests (it depends too heavily on a real system) and is instead covered by the CI matrix — 20 workflows under `.github/workflows/` spanning Linux (including musl, loong64, armv7l, i686), macOS, Windows, FreeBSD, NetBSD, OpenBSD, DragonFly, Solaris, OmniOS and Haiku, plus spellcheck and benchmark jobs. + +**If you touch `common/FFstrbuf.h`, `common/format.h` or `common/color.h`, please extend the matching test.** + +--- + +## Pull requests + +1. **Open an issue first** (feature request / bug report / logo request) so you don't waste effort. Templates are in `.github/ISSUE_TEMPLATE/`. +2. Branch off `dev` — **`dev` is the main development branch**, not `master`. +3. Follow the [commit message convention](#commit-messages). +4. Update `CHANGELOG.md` for user-visible changes. +5. Open the PR against `dev` and fill in `.github/pull_request_template.md`: + - Summary + - Related issue (**required for new logos**, otherwise the PR won't be accepted) + - Changes + - Screenshots (required for visual changes) + - Checklist: confirm you tested locally + +### Pre-submit checklist + +```sh +clang-format -i # format +codespell # spelling +cmake -B build -DBUILD_TESTS=On && cmake --build build -j +cd build && ctest --output-on-failure # tests +./build/fastfetch --format json # verify JSON output is well-formed +./build/fastfetch -c presets/all.jsonc --stat false # smoke-test every module +``` + +--- + +## Gotchas + +Things that are easy to get wrong when reading this codebase. Most of them follow from the "obsessively fast startup" goal. + +### 1. Option structs must not exceed 256 bytes + +`FF_OPTION_MAX_SIZE = 1 << 8`. Exceeding it is caught at compile time by `static_assert`. Don't try to raise the value — it determines the stack cost of every module invocation. + +### 2. `FF_MODULE_DISABLE_*` controls registration, not compilation + +```c +// verbatim from the top of modules/modules.c: +// FF_MODULE_DISABLE_ only controls if the module is registered, +// the module code itself is still compiled. +// We rely `LTO` to remove the unused code (only enabled in Release mode) +``` + +**Disabling modules in a Debug build does not shrink the binary.** LTO is enabled whenever `CMAKE_BUILD_TYPE != Debug`, and the default `RelWithDebInfo` already satisfies that — so measure size with `RelWithDebInfo` or `Release`, never with `Debug`. (The "Release mode" wording in the comment above is imprecise.) + +### 3. CMake globs don't trigger reconfiguration + +Both the module directories and the logo files are discovered by glob. CMake will not notice new files on its own — you need to re-run `cmake -B build` (or delete `build/CMakeCache.txt` and start over). This is the classic CMake footgun. + +### 4. CLI module options are removed + +Per-module command-line flags such as `--cpu-temp` are **no longer supported**. The only job of `ffParseModuleOptions` now is to translate the flag into a JSON key, then `exit(477)` with a pointer to the config file: + +``` +Error: Unsupported module option: --cpu-temp + Support of module options has been removed. Please add the flag to the JSON config instead. + Example (demonstration only): `{ "modules": [ { "type": "cpu", "temp": true } ] }` +``` + +**JSONC is the first-class configuration interface; the command line is not.** When adding module options, implement `parseJsonObject` only — do not add a CLI branch. + +### 5. `defaultOrder = 0` hides a module from `--gen-config` + +`collectModuleInfos` (`genconfig.c:186`) skips any module whose `defaultOrder` is `0`. C zero-initializes the field, so **omitting it is the same as setting it to 0**. Only `logo`, `command` and `custom` do this on purpose. + +`defaultOrder` affects only the ordering in the interactive `--gen-config` picker; it has no effect on runtime output order. + +### 6. Localization uses byte offsets, not enums + +`instance.config.display.keyLanguage` does not hold a language enum — it holds a **byte offset** such as `offsetof(FFModuleDisplayName, zh_CN)`. The macro `FF_MODULE_GET_DISPLAY_NAME` (`common/option.h:123`) does plain pointer arithmetic with it: + +```c +#define FF_MODULE_GET_DISPLAY_NAME(moduleName) \ + (*(const char**) ((uint8_t*) &ff ## moduleName ## ModuleInfo.displayName + instance.config.display.keyLanguage)) +``` + +Consequence: **the field order of `FFModuleDisplayName` must never change** — reordering silently scrambles every language. + +### 7. The `multithreading` switch barely does anything + +The global `multithreading` option currently takes effect in exactly one place: `common/impl/networking_linux.c:339`. Modules are still printed sequentially. Modules that need concurrency go through the `ffPrepare*` warm-up hooks instead, which start sampling or fire off requests before the print loop begins. + +### 8. Don't print or read config inside `detection/` + +The `detection/` layer must stay pure: read system state, fill a struct, return an error string. Any `printf` or any read of `instance.config` there is a design error. + +### 9. `src/logo/builtin.c` and `3rdparty/` are formatting-exempt + +The former is a large generated/hand-maintained data table, the latter is upstream code. Both are excluded via `.clang-format-ignore` — leave them alone. + +--- + +## Reference + +- Configuration guide: +- JSON schema: `doc/json_schema.json` +- Example presets: `presets/` (`all.jsonc`, `neofetch.jsonc`, `ci.jsonc`, …) +- Man page source: `doc/fastfetch.1.in` +- Code generation scripts: `scripts/` (`gen-pciids.py`, `gen-amdgpuids.py`, `gen-man.py`) From b9e4d04d6578acdcb31c64aeecbd26e265769a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 19:08:33 +0800 Subject: [PATCH 100/109] Global: addresses review comments generated by CI --- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- doc/json_schema.json | 4 ++-- src/common/impl/FFPlatform_unix.c | 2 ++ src/detection/processes/processes_gnu.c | 3 +-- src/detection/processes/processes_nosupport.c | 2 +- src/detection/terminalfont/terminalfont_android.c | 3 ++- src/detection/top/top_gnu.c | 3 +++ src/modules/diskio/diskio.c | 3 +++ src/modules/netio/netio.c | 3 +++ src/modules/top/top.c | 6 +++--- 11 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a18be3800..6e9021131 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# 2.68.0 Changes: * The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations. diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d526dbb7..995c2049d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.21.0) # C_STANDARD project(fastfetch - VERSION 2.67.1 + VERSION 2.68.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" diff --git a/doc/json_schema.json b/doc/json_schema.json index b2f07370d..1ec527f38 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -322,7 +322,7 @@ "type": "string" }, "cpuFormat": { - "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count", + "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count\n 13. {code-name}: CPU code name\n 14. {technology}: CPU technology", "type": "string" }, "cpucacheFormat": { @@ -506,7 +506,7 @@ "type": "string" }, "topFormat": { - "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second (0 if unsupported)\n 7. {disk-write}: Disk write bytes per second (0 if unsupported)\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {pid}: Process ID\n 3. {cpu}: CPU usage\n 4. {mem}: Memory usage (RSS) in bytes\n 5. {disk-read}: Disk read bytes per second (0 if unsupported)\n 6. {disk-write}: Disk write bytes per second (0 if unsupported)\n 7. {cpu-percentage}: CPU usage percentage\n 8. {mem-formatted}: Memory usage (RSS) formatted\n 9. {disk-read-formatted}: Disk read formatted\n 10. {disk-write-formatted}: Disk write formatted", "type": "string" }, "themeFormat": { diff --git a/src/common/impl/FFPlatform_unix.c b/src/common/impl/FFPlatform_unix.c index e3ea77f51..92f0e8634 100644 --- a/src/common/impl/FFPlatform_unix.c +++ b/src/common/impl/FFPlatform_unix.c @@ -238,7 +238,9 @@ static void getDataDirs(FFPlatform* platform) { ffPlatformPathAddHome(&platform->dataDirs, platform, ""); platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) ffPlatformPathAddAbsolute(&platform->dataDirs, FF_PATH_PKG_BASE "/share/"); +#endif ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/"); } diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c index ba4351f5e..53c9781c6 100644 --- a/src/detection/processes/processes_gnu.c +++ b/src/detection/processes/processes_gnu.c @@ -29,13 +29,12 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu continue; } + ++result->processes; if (proc_stat_has(stat, PSTAT_NUM_THREADS)) { result->threads += proc_stat_num_threads(stat); } } - result->processes = (uint32_t) list->num_procs; - done: if (list) { proc_stat_list_free(list); diff --git a/src/detection/processes/processes_nosupport.c b/src/detection/processes/processes_nosupport.c index e7218a5c2..04a5eafd8 100644 --- a/src/detection/processes/processes_nosupport.c +++ b/src/detection/processes/processes_nosupport.c @@ -1,5 +1,5 @@ #include "processes.h" -const char* ffDetectProcesses([[maybe_unused]] FFProcessesResult* result) { +const char* ffDetectProcesses([[maybe_unused]] const FFProcessesOptions* options, [[maybe_unused]] FFProcessesResult* result) { return "Not supported on this platform"; } diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 7ef0f5250..494dcee1f 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -16,7 +16,8 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) { FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); // SharedPreferences XML: 14, in px - if (ffParsePropFile(FF_TERMUX_PREF_PATH, "", &fontSize)) { + ffParsePropFile(FF_TERMUX_PREF_PATH, "", &fontSize); + if (fontSize.length > 0) { ffStrbufAppendS(&fontSize, "px"); } diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 0407124fb..37845a640 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -57,6 +57,9 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { } item->pid = pid; + item->cpuTime = 0; + item->memBytes = 0; + item->startTime = 0; if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 71f6970d8..61ed83001 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -111,6 +111,9 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); + if (options->waitTime == 0) { + options->waitTime = 1; + } continue; } diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 0729b444e..0ffe4f1d3 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -126,6 +126,9 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); + if (options->waitTime == 0) { + options->waitTime = 1; + } continue; } diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 60b5a614e..7087e38ed 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -43,7 +43,7 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total FF_STRBUF_AUTO_DESTROY diskWriteFormatted = ffStrbufCreate(); ffSizeAppendNum(process->bytesWritten, &diskWriteFormatted); ffStrbufAppendS(&diskWriteFormatted, "/s"); - FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), (uint8_t) index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_ARG(process->name, "name"), FF_ARG(process->pid, "pid"), FF_ARG(process->cpuPercent, "cpu"), @@ -73,11 +73,12 @@ bool ffPrintTop(FFTopOptions* options) { } else { ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { - ffStrbufWriteTo(&process->name, stdout); if ((void*) process != results.data) { putchar(' '); } + ffStrbufWriteTo(&process->name, stdout); } + putchar('\n'); } FF_LIST_FOR_EACH (FFTopProcessResult, item, results) { @@ -271,7 +272,6 @@ FFModuleBaseInfo ffTopModuleInfo = { .generateJsonConfig = (void*) ffGenerateTopJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){ { "Process name", "name" }, - { "Executable path", "path" }, { "Process ID", "pid" }, { "CPU usage", "cpu" }, { "Memory usage (RSS) in bytes", "mem" }, From 6eef800ea299a51aaebb9fbd8dc17e28c451ec5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 19:47:14 +0800 Subject: [PATCH 101/109] Top: supports sorting by `start-time` --- doc/json_schema.json | 7 ++++--- src/detection/top/top.c | 7 +++++++ src/modules/top/option.h | 1 + src/modules/top/top.c | 3 +++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 1ec527f38..3d43ca94e 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -4441,16 +4441,17 @@ "properties": { "type": { "const": "top", - "description": "Print processes with the highest CPU or memory usage" + "description": "Print processes with the highest CPU, memory, disk I/O usage or latest start time" }, "sort": { "type": "string", - "description": "Sort processes by CPU, memory or disk IO usage", + "description": "Sort processes by CPU, memory, disk IO usage or start time", "enum": [ "cpu", "memory", "disk-read", - "disk-write" + "disk-write", + "start-time" ], "default": "cpu" }, diff --git a/src/detection/top/top.c b/src/detection/top/top.c index 5c1b8b645..26b5b76db 100644 --- a/src/detection/top/top.c +++ b/src/detection/top/top.c @@ -53,6 +53,12 @@ static int compareDiskWriteResults(const FFTopProcessResult* a, const FFTopProce if (a->bytesWritten > b->bytesWritten) return -1; return (int) (a->pid - b->pid); } + +static int compareStartTimeResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->startTime < b->startTime) return 1; + if (a->startTime > b->startTime) return -1; + return (int) (a->pid - b->pid); +} // clang-format on const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { @@ -147,6 +153,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { const void* compare = options->sort == FF_TOP_TYPE_DISK_WRITE ? (void*) compareDiskWriteResults : options->sort == FF_TOP_TYPE_DISK_READ ? (void*) compareDiskReadResults : options->sort == FF_TOP_TYPE_MEMORY ? (void*) compareMemoryResults + : options->sort == FF_TOP_TYPE_START_TIME ? (void*) compareStartTimeResults : (void*) compareCpuResults; ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); if (result->length > options->nProcesses) { diff --git a/src/modules/top/option.h b/src/modules/top/option.h index 82a138273..0422d3a8a 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -8,6 +8,7 @@ typedef enum FFTopTypes: uint8_t { FF_TOP_TYPE_MEMORY = 1 << 1, FF_TOP_TYPE_DISK_READ = 1 << 2, FF_TOP_TYPE_DISK_WRITE = 1 << 3, + FF_TOP_TYPE_START_TIME = 1 << 4, FF_TOP_TYPE_DISK = FF_TOP_TYPE_DISK_READ | FF_TOP_TYPE_DISK_WRITE, } FFTopTypes; diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 7087e38ed..cc39c9977 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -101,6 +101,7 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { { "memory", FF_TOP_TYPE_MEMORY }, { "disk-read", FF_TOP_TYPE_DISK_READ }, { "disk-write", FF_TOP_TYPE_DISK_WRITE }, + { "start-time", FF_TOP_TYPE_START_TIME }, {}, }); if (error) { @@ -183,6 +184,8 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); } else if (options->sort == FF_TOP_TYPE_DISK_WRITE) { yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); + } else if (options->sort == FF_TOP_TYPE_START_TIME) { + yyjson_mut_obj_add_str(doc, module, "sort", "start-time"); } yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); From 4ff931c06fe44a950830d9ec20e75d2e86e17548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 20:27:22 +0800 Subject: [PATCH 102/109] Top: adds thread count detection --- doc/json_schema.json | 17 +++++++------ src/detection/top/top.c | 13 ++++++++-- src/detection/top/top.h | 2 ++ src/detection/top/top_apple.c | 9 ++++++- src/detection/top/top_bsd.c | 3 ++- src/detection/top/top_dbsd.c | 3 ++- src/detection/top/top_gnu.c | 11 +++++++-- src/detection/top/top_haiku.c | 3 ++- src/detection/top/top_linux.c | 10 ++++++-- src/detection/top/top_nbsd.c | 10 +++++++- src/detection/top/top_obsd.c | 19 ++++++++++++++- src/detection/top/top_sunos.c | 1 + src/detection/top/top_windows.c | 1 + src/modules/top/option.h | 1 + src/modules/top/top.c | 43 ++++++++++++++++++++++----------- 15 files changed, 113 insertions(+), 33 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 3d43ca94e..0aeba6de2 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -506,7 +506,7 @@ "type": "string" }, "topFormat": { - "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {pid}: Process ID\n 3. {cpu}: CPU usage\n 4. {mem}: Memory usage (RSS) in bytes\n 5. {disk-read}: Disk read bytes per second (0 if unsupported)\n 6. {disk-write}: Disk write bytes per second (0 if unsupported)\n 7. {cpu-percentage}: CPU usage percentage\n 8. {mem-formatted}: Memory usage (RSS) formatted\n 9. {disk-read-formatted}: Disk read formatted\n 10. {disk-write-formatted}: Disk write formatted", + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {pid}: Process ID\n 3. {cpu}: CPU usage\n 4. {mem}: Memory usage (RSS) in bytes\n 5. {disk-read}: Disk read bytes per second (0 if unsupported)\n 6. {disk-write}: Disk write bytes per second (0 if unsupported)\n 7. {threads}: Number of threads\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", "type": "string" }, "themeFormat": { @@ -4441,22 +4441,23 @@ "properties": { "type": { "const": "top", - "description": "Print processes with the highest CPU, memory, disk I/O usage or latest start time" + "description": "Print processes with the highest CPU, memory, disk I/O usage, latest start time or thread count" }, "sort": { "type": "string", - "description": "Sort processes by CPU, memory, disk IO usage or start time", + "description": "Sort processes by CPU, memory, disk IO usage, start time or thread count", "enum": [ "cpu", "memory", "disk-read", "disk-write", - "start-time" + "start-time", + "threads" ], "default": "cpu" }, "showTypes": { - "description": "Specify which resource usages are detected and displayed.\nIf memory is enabled is enabled alone, only a single process snapshot is taken and `waitTime` sampling wait is skipped", + "description": "Specify which resource usages are detected and displayed.\nIf memory or threads is enabled is enabled alone, only a single process snapshot is taken and `waitTime` sampling wait is skipped", "default": [ "cpu", "memory", @@ -4468,7 +4469,8 @@ "enum": [ "cpu", "memory", - "disk" + "disk", + "threads" ] }, { @@ -4479,7 +4481,8 @@ "enum": [ "cpu", "memory", - "disk" + "disk", + "threads" ] } } diff --git a/src/detection/top/top.c b/src/detection/top/top.c index 26b5b76db..dd4442a7e 100644 --- a/src/detection/top/top.c +++ b/src/detection/top/top.c @@ -59,6 +59,12 @@ static int compareStartTimeResults(const FFTopProcessResult* a, const FFTopProce if (a->startTime > b->startTime) return -1; return (int) (a->pid - b->pid); } + +static int compareThreadsResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->threads < b->threads) return 1; + if (a->threads > b->threads) return -1; + return (int) (a->pid - b->pid); +} // clang-format on const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { @@ -67,8 +73,8 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { return nullptr; } - // Memory usage is instantaneous; when neither CPU time nor disk IO counters - // are requested, a single snapshot suffices and no sampling wait is needed. + // Memory usage and thread count are instantaneous; when neither CPU time nor disk IO + // counters are requested, a single snapshot suffices and no sampling wait is needed. const bool sampleOnce = (options->showTypes & (FF_TOP_TYPE_CPU | FF_TOP_TYPE_DISK)) == 0; if (sampleOnce) { @@ -92,6 +98,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { item->bytesWritten = 0; item->cpuPercent = 0; item->startTime = snap->startTime; + item->threads = snap->threads; ffStrbufInitMove(&item->name, &snap->name); } } else { @@ -141,6 +148,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; item->startTime = newItem->startTime; + item->threads = newItem->threads; ffStrbufInitMove(&item->name, &oldItem->name); } @@ -154,6 +162,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { : options->sort == FF_TOP_TYPE_DISK_READ ? (void*) compareDiskReadResults : options->sort == FF_TOP_TYPE_MEMORY ? (void*) compareMemoryResults : options->sort == FF_TOP_TYPE_START_TIME ? (void*) compareStartTimeResults + : options->sort == FF_TOP_TYPE_THREADS ? (void*) compareThreadsResults : (void*) compareCpuResults; ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); if (result->length > options->nProcesses) { diff --git a/src/detection/top/top.h b/src/detection/top/top.h index de1289b4a..26f05d549 100644 --- a/src/detection/top/top.h +++ b/src/detection/top/top.h @@ -10,6 +10,7 @@ typedef struct FFTopProcessResult { uint64_t bytesRead; uint64_t bytesWritten; uint64_t startTime; + uint32_t threads; uint32_t pid; } FFTopProcessResult; @@ -20,6 +21,7 @@ typedef struct FFTopProcessSnapshot { uint64_t bytesRead; // Physical storage read uint64_t bytesWritten; // Physical storage written uint64_t startTime; // Differs between platforms + uint32_t threads; uint32_t pid; } FFTopProcessSnapshot; diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index 862431381..6a1692b0e 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; @@ -54,6 +54,13 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = rusage.ri_diskio_bytesread; item->bytesWritten = rusage.ri_diskio_byteswritten; item->startTime = rusage.ri_proc_start_abstime; + item->threads = 0; + if (showTypes & FF_TOP_TYPE_THREADS) { + struct proc_taskinfo taskInfo; + if (proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) == sizeof(taskInfo)) { + item->threads = (uint32_t) taskInfo.pti_threadnum; + } + } } return nullptr; diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c index 6c0f62018..108e5e97e 100644 --- a/src/detection/top/top_bsd.c +++ b/src/detection/top/top_bsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; size_t length; @@ -51,6 +51,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = (uint64_t) proc->ki_rusage.ru_inblock * DEV_BSIZE; item->bytesWritten = (uint64_t) proc->ki_rusage.ru_oublock * DEV_BSIZE; + item->threads = (uint32_t) proc->ki_numthreads; } return NULL; diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 56a572e65..9896b6f54 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; @@ -52,6 +52,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = (uint64_t) (proc->kp_ru.ru_inblock + proc->kp_lwp.kl_ru.ru_inblock) * DEV_BSIZE; item->bytesWritten = (uint64_t) (proc->kp_ru.ru_oublock + proc->kp_lwp.kl_ru.ru_oublock) * DEV_BSIZE; + item->threads = (uint32_t) proc->kp_nthreads; } return nullptr; diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 37845a640..9f9342216 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -4,7 +4,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { struct ps_context* context = nullptr; if (ps_context_create(getproc(), &context) != 0) { return "ps_context_create(getproc()) failed"; @@ -24,7 +24,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { // Flags that cannot be fetched for some process are simply left unset; // each field must be checked before use. - if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { + if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC | ((showTypes & FF_TOP_TYPE_THREADS) ? PSTAT_NUM_THREADS : 0)) != 0) { error = "proc_stat_list_set_flags() failed"; goto done; } @@ -60,6 +60,13 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->cpuTime = 0; item->memBytes = 0; item->startTime = 0; + item->threads = 0; + + if (showTypes & FF_TOP_TYPE_THREADS) { + if (proc_stat_has(stat, PSTAT_NUM_THREADS)) { + item->threads = (uint32_t) proc_stat_num_threads(stat); + } + } if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); diff --git a/src/detection/top/top_haiku.c b/src/detection/top/top_haiku.c index 78310737a..32f73d686 100644 --- a/src/detection/top/top_haiku.c +++ b/src/detection/top/top_haiku.c @@ -3,7 +3,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int32 cookie = 0; team_info team; while (get_next_team_info(&cookie, &team) == B_OK) { @@ -41,6 +41,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { // Storage io counters are not exposed by Haiku; leave them zeroed. item->bytesRead = 0; item->bytesWritten = 0; + item->threads = (uint32_t) team.thread_count; } return nullptr; diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 2436e3ce7..be71ab5a8 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -24,8 +24,6 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r return false; } - result->cpuTime = 0; - char* p; for (uint32_t field = 3; field <= 22 /*start time*/; ++field) { switch (field) { @@ -43,6 +41,11 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r cursor = p; break; + case 20: // number of threads + result->threads = (uint32_t) strtoul(cursor, &p, 10); + cursor = p; + break; + case 22: // start time result->startTime = (uint64_t) strtoull(cursor, &p, 10); cursor = p; @@ -128,6 +131,9 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInit(&snapshot->name); + snapshot->threads = 0; + snapshot->cpuTime = 0; + snapshot->startTime = 0; if (!parseStat(statBuffer, (size_t) statLength, snapshot)) { ffStrbufDestroy(&snapshot->name); diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c index 1bc8e6543..8c9c4968d 100644 --- a/src/detection/top/top_nbsd.c +++ b/src/detection/top/top_nbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length; @@ -50,6 +50,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + item->threads = 0; + if (showTypes & FF_TOP_TYPE_THREADS) { + int lwpRequest[] = { CTL_KERN, KERN_LWP, proc->p_pid, sizeof(struct kinfo_lwp), 0 }; + size_t lwpLength = 0; + if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) { + item->threads = (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); + } + } } return NULL; diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c index f7519bd00..365ecfe7f 100644 --- a/src/detection/top/top_obsd.c +++ b/src/detection/top/top_obsd.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); if (!kd) { return "kvm_open() failed"; @@ -37,6 +37,23 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->startTime = (uint64_t) proc->p_ustart_sec * 1000 + (uint64_t) proc->p_ustart_usec / 1000; item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + item->threads = 0; + } + + if (showTypes & FF_TOP_TYPE_THREADS) { + int threadCount = 0; + const struct kinfo_proc* threads = kvm_getprocs(kd, + KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &threadCount); + if (threads) { + for (uint32_t i = 0; i < snapshots->length; ++i) { + FFTopProcessSnapshot* item = FF_LIST_GET(FFTopProcessSnapshot, *snapshots, i); + for (int j = 0; j < threadCount; ++j) { + if (threads[j].p_pid == (pid_t) item->pid && threads[j].p_tid != -1) { + ++item->threads; + } + } + } + } } kvm_close(kd); diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c index 7dc9c880c..0054ae79a 100644 --- a/src/detection/top/top_sunos.c +++ b/src/detection/top/top_sunos.c @@ -60,6 +60,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { item->bytesRead = 0; item->bytesWritten = 0; + item->threads = (uint32_t) psinfo.pr_nlwp; if (showTypes & FF_TOP_TYPE_DISK) { prusage_t usage; if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index 604096403..2f1e5d66d 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -38,6 +38,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize; item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount; item->bytesWritten = (uint64_t) info->IoCounters.WriteTransferCount; + item->threads = info->NumberOfThreads; ffStrbufInitNWS(&item->name, info->ImageName.Length / sizeof(wchar_t), info->ImageName.Buffer); } if (info->NextEntryOffset == 0) { diff --git a/src/modules/top/option.h b/src/modules/top/option.h index 0422d3a8a..0c3ff406d 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -9,6 +9,7 @@ typedef enum FFTopTypes: uint8_t { FF_TOP_TYPE_DISK_READ = 1 << 2, FF_TOP_TYPE_DISK_WRITE = 1 << 3, FF_TOP_TYPE_START_TIME = 1 << 4, + FF_TOP_TYPE_THREADS = 1 << 5, FF_TOP_TYPE_DISK = FF_TOP_TYPE_DISK_READ | FF_TOP_TYPE_DISK_WRITE, } FFTopTypes; diff --git a/src/modules/top/top.c b/src/modules/top/top.c index cc39c9977..8ba755a83 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -28,6 +28,9 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffSizeAppendNum(process->bytesWritten, &output); ffStrbufAppendS(&output, "/s"); } + if (options->showTypes & FF_TOP_TYPE_THREADS) { + ffStrbufAppendF(&output, " - THR %u", process->threads); + } } ffStrbufPutTo(&output, stdout); } else { @@ -44,17 +47,18 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffSizeAppendNum(process->bytesWritten, &diskWriteFormatted); ffStrbufAppendS(&diskWriteFormatted, "/s"); FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ - FF_ARG(process->name, "name"), - FF_ARG(process->pid, "pid"), - FF_ARG(process->cpuPercent, "cpu"), - FF_ARG(process->memBytes, "mem"), - FF_ARG(process->bytesRead, "disk-read"), - FF_ARG(process->bytesWritten, "disk-write"), - FF_ARG(cpuFormatted, "cpu-percentage"), - FF_ARG(memFormatted, "mem-formatted"), - FF_ARG(diskReadFormatted, "disk-read-formatted"), - FF_ARG(diskWriteFormatted, "disk-write-formatted"), - })); + FF_ARG(process->name, "name"), + FF_ARG(process->pid, "pid"), + FF_ARG(process->cpuPercent, "cpu"), + FF_ARG(process->memBytes, "mem"), + FF_ARG(process->bytesRead, "disk-read"), + FF_ARG(process->bytesWritten, "disk-write"), + FF_ARG(process->threads, "threads"), + FF_ARG(cpuFormatted, "cpu-percentage"), + FF_ARG(memFormatted, "mem-formatted"), + FF_ARG(diskReadFormatted, "disk-read-formatted"), + FF_ARG(diskWriteFormatted, "disk-write-formatted"), + })); } } @@ -121,6 +125,7 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { { "cpu", FF_TOP_TYPE_CPU }, { "memory", FF_TOP_TYPE_MEMORY }, { "disk", FF_TOP_TYPE_DISK }, + { "threads", FF_TOP_TYPE_THREADS }, {}, }); if (error == nullptr) { @@ -138,6 +143,7 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { { "cpu", FF_TOP_TYPE_CPU }, { "memory", FF_TOP_TYPE_MEMORY }, { "disk", FF_TOP_TYPE_DISK }, + { "threads", FF_TOP_TYPE_THREADS }, {}, }); if (error == nullptr) { @@ -175,6 +181,9 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ if (options->showTypes & FF_TOP_TYPE_DISK) { yyjson_mut_arr_add_str(doc, showTypes, "disk"); } + if (options->showTypes & FF_TOP_TYPE_THREADS) { + yyjson_mut_arr_add_str(doc, showTypes, "threads"); + } yyjson_mut_obj_add_val(doc, module, "showTypes", showTypes); if (options->sort == FF_TOP_TYPE_CPU) { yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); @@ -186,6 +195,8 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); } else if (options->sort == FF_TOP_TYPE_START_TIME) { yyjson_mut_obj_add_str(doc, module, "sort", "start-time"); + } else if (options->sort == FF_TOP_TYPE_THREADS) { + yyjson_mut_obj_add_str(doc, module, "sort", "threads"); } yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); @@ -215,6 +226,9 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); } + if (options->showTypes & FF_TOP_TYPE_THREADS) { + yyjson_mut_obj_add_uint(doc, item, "threads", process->threads); + } yyjson_mut_obj_add_uint(doc, item, "startTime", process->startTime); } @@ -228,10 +242,10 @@ void ffInitTopOptions(FFTopOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); options->sort = FF_TOP_TYPE_CPU; options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY - #if !__GNU__ && !__HAIKU__ +#if !__GNU__ && !__HAIKU__ | FF_TOP_TYPE_DISK - #endif - ; +#endif + ; options->nProcesses = 5; options->waitTime = 500; options->compact = false; @@ -280,6 +294,7 @@ FFModuleBaseInfo ffTopModuleInfo = { { "Memory usage (RSS) in bytes", "mem" }, { "Disk read bytes per second (0 if unsupported)", "disk-read" }, { "Disk write bytes per second (0 if unsupported)", "disk-write" }, + { "Number of threads", "threads" }, { "CPU usage percentage", "cpu-percentage" }, { "Memory usage (RSS) formatted", "mem-formatted" }, { "Disk read formatted", "disk-read-formatted" }, From b5ffc32b804a91a9f2a1f31a44ebfbd2903b9f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 20:29:06 +0800 Subject: [PATCH 103/109] Top / Processes (Windows): improves detection of system / kernel processes detection --- src/detection/processes/processes_windows.c | 2 +- src/detection/top/top_windows.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index 7ccd13149..af09f6a91 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -26,7 +26,7 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - if (!options->countKprocs && ptr->CreateTime.QuadPart == 0) { + if (!options->countKprocs && (uintptr_t) ptr->InheritedFromUniqueProcessId > 0) { continue; } ++result->processes; diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index 2f1e5d66d..33a430af7 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -30,7 +30,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { for (SYSTEM_PROCESS_INFORMATION* info = pstart;; info = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) info + info->NextEntryOffset)) { uintptr_t pidValue = (uintptr_t) info->UniqueProcessId; - if (pidValue <= UINT32_MAX && info->CreateTime.QuadPart > 0) { + if (pidValue <= UINT32_MAX && (uintptr_t) info->InheritedFromUniqueProcessId > 0) { FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); item->pid = (uint32_t) pidValue; item->startTime = (uint64_t) info->CreateTime.QuadPart; From 43d01f26ea31485821075ba49932a1d649eb063b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 20:32:29 +0800 Subject: [PATCH 104/109] Top: handle unknown process names gracefully in output --- src/modules/top/top.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 8ba755a83..9edbc394d 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -11,7 +11,12 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); - ffStrbufAppendF(&output, "%s (%u)", process->name.chars, process->pid); + if (process->name.length == 0) { + ffStrbufAppendS(&output, ""); + } else { + ffStrbufAppend(&output, &process->name); + } + ffStrbufAppendF(&output, " (%u)", process->pid); if ((options->showTypes & FF_TOP_TYPE_CPU) && (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)) { ffStrbufAppendS(&output, " - CPU "); ffPercentAppendNum(&output, process->cpuPercent, options->percent, false, &options->moduleArgs); From b0ba084b5ef80c7ca87f6a60185295caec2d7514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 21:53:32 +0800 Subject: [PATCH 105/109] Global: address review comments v2 --- src/detection/processes/processes_obsd.c | 3 ++- src/detection/processes/processes_windows.c | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index d0de8170d..8c50065a0 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -13,7 +13,8 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } int count = 0; - // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads + // KERN_PROC_ALL returns all user-level processes + // KERN_PROC_KTHREAD returns all processes, including user-level processes (despite the name) const struct kinfo_proc* procs = kvm_getprocs(kd, (options->countKprocs ? KERN_PROC_KTHREAD : KERN_PROC_ALL) | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &count); diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index af09f6a91..0a2ba2f41 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -26,11 +26,10 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - if (!options->countKprocs && (uintptr_t) ptr->InheritedFromUniqueProcessId > 0) { - continue; + if (options->countKprocs || (uintptr_t) ptr->InheritedFromUniqueProcessId > 0) { + ++result->processes; + result->threads += ptr->NumberOfThreads; } - ++result->processes; - result->threads += ptr->NumberOfThreads; if (ptr->NextEntryOffset == 0) { break; } From 8ea4468eec60fb43dcb12a61afcc229e6103b2a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 1 Sep 2026 00:20:40 +0800 Subject: [PATCH 106/109] Common (Endian): adds new header --- src/common/endian.h | 17 +++++++++ src/common/impl/base64.c | 9 ++--- src/common/impl/smbios.c | 33 ++++++++--------- src/detection/battery/battery_windows.c | 20 +++++------ src/detection/chassis/chassis_linux.c | 3 +- src/detection/cpu/cpu_windows.c | 3 +- src/detection/cpucache/cpucache_shared.c | 13 ++++--- src/detection/host/host_windows.c | 10 +++++- .../physicalmemory/physicalmemory_linux.c | 36 +++++++++++-------- 9 files changed, 87 insertions(+), 57 deletions(-) create mode 100644 src/common/endian.h diff --git a/src/common/endian.h b/src/common/endian.h new file mode 100644 index 000000000..2410911ee --- /dev/null +++ b/src/common/endian.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#if __BIG_ENDIAN__ + #define FF_READ_LE(x) _Generic((x), \ + uint16_t: __builtin_bswap16(x), \ + uint32_t: __builtin_bswap32(x), \ + uint64_t: __builtin_bswap64(x)) + #define FF_READ_BE(x) (x) +#else + #define FF_READ_LE(x) (x) + #define FF_READ_BE(x) _Generic((x), \ + uint16_t: __builtin_bswap16(x), \ + uint32_t: __builtin_bswap32(x), \ + uint64_t: __builtin_bswap64(x)) +#endif diff --git a/src/common/impl/base64.c b/src/common/impl/base64.c index fa987c303..3d743691b 100644 --- a/src/common/impl/base64.c +++ b/src/common/impl/base64.c @@ -1,4 +1,5 @@ #include "common/base64.h" +#include "common/endian.h" // https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145 void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output) { @@ -7,12 +8,8 @@ void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* const char* ends = str + (size - size % 3); while (str != ends) { uint32_t n = *(uint32_t*) str; - #if !__BIG_ENDIAN__ - // The 3 input bytes must be laid out big-endian (str[0] in the most - // significant position). On little-endian hosts swap; on big-endian - // hosts the word is already in the right order. - n = __builtin_bswap32(n); - #endif + // The 3 input bytes must be laid out big-endian (str[0] in the most significant position). + n = FF_READ_BE(n); *out++ = chars[(n >> 26) & 63]; *out++ = chars[(n >> 20) & 63]; *out++ = chars[(n >> 14) & 63]; diff --git a/src/common/impl/smbios.c b/src/common/impl/smbios.c index fc7df14b3..9a54003bc 100644 --- a/src/common/impl/smbios.c +++ b/src/common/impl/smbios.c @@ -1,3 +1,4 @@ +#include "common/endian.h" #include "common/smbios.h" #include "common/io.h" #include "common/mallocHelper.h" @@ -81,9 +82,9 @@ static bool parseSmbiosTable(const uint8_t* data, uint32_t length) { break; } - if (header->Handle >= 0xFF00) { + if (FF_READ_LE(header->Handle) >= 0xFF00) { FF_DEBUG("Invalid SMBIOS structure handle 0x%04x at offset 0x%lx", - header->Handle, + FF_READ_LE(header->Handle), (unsigned long) ((const uint8_t*) header - data)); break; } @@ -103,25 +104,25 @@ static bool parseSmbiosTable(const uint8_t* data, uint32_t length) { smbiosTable[header->Type] = header; FF_DEBUG("Found SMBIOS structure type %u, handle 0x%04X, length %u", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); structureCount++; } else { FF_DEBUG("Duplicate SMBIOS structure type %u, handle 0x%04X, length %u", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); } } else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE) { FF_DEBUG("Reached SMBIOS end of type %u, handle 0x%04X, length %u", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); break; } else { FF_DEBUG("Found custom SMBIOS structure type %u, handle 0x%04X, length %u; ignoring", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); } } @@ -308,8 +309,8 @@ static bool fillTableBufferFallback(FFstrbuf* buffer) { sizeof(p->Smbios30)); return false; } - tableLength = p->Smbios30.StructureTableMaximumSize; - tableAddress = (off_t) p->Smbios30.StructureTableAddress; + tableLength = FF_READ_LE(p->Smbios30.StructureTableMaximumSize); + tableAddress = (off_t) FF_READ_LE(p->Smbios30.StructureTableAddress); FF_DEBUG("SMBIOS 3.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u.%u", tableLength, (unsigned long) tableAddress, @@ -325,8 +326,8 @@ static bool fillTableBufferFallback(FFstrbuf* buffer) { sizeof(p->Smbios20)); return false; } - tableLength = p->Smbios20.StructureTableLength; - tableAddress = (off_t) p->Smbios20.StructureTableAddress; + tableLength = FF_READ_LE(p->Smbios20.StructureTableLength); + tableAddress = (off_t) FF_READ_LE(p->Smbios20.StructureTableAddress); FF_DEBUG("SMBIOS 2.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u", tableLength, (unsigned long) tableAddress, @@ -369,9 +370,9 @@ static bool detectSmbiosTableLength(const uint8_t* data, uint32_t bufferLength, return false; } - if (header->Handle >= 0xFF00) { + if (FF_READ_LE(header->Handle) >= 0xFF00) { FF_DEBUG("Invalid SMBIOS structure handle 0x%04x at offset 0x%lx", - header->Handle, + FF_READ_LE(header->Handle), (unsigned long) (p - data)); return false; } @@ -614,8 +615,8 @@ static bool fillTableBufferPlatform(FFstrbuf* buffer) { sizeof(entryPoint.Smbios20)); return false; } - tableLength = entryPoint.Smbios20.StructureTableLength; - tableAddress = (off_t) entryPoint.Smbios20.StructureTableAddress; + tableLength = FF_READ_LE(entryPoint.Smbios20.StructureTableLength); + tableAddress = (off_t) FF_READ_LE(entryPoint.Smbios20.StructureTableAddress); FF_DEBUG("SMBIOS 2.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u", tableLength, (unsigned long) tableAddress, @@ -629,8 +630,8 @@ static bool fillTableBufferPlatform(FFstrbuf* buffer) { sizeof(entryPoint.Smbios30)); return false; } - tableLength = entryPoint.Smbios30.StructureTableMaximumSize; - tableAddress = (off_t) entryPoint.Smbios30.StructureTableAddress; + tableLength = FF_READ_LE(entryPoint.Smbios30.StructureTableMaximumSize); + tableAddress = (off_t) FF_READ_LE(entryPoint.Smbios30.StructureTableAddress); FF_DEBUG("SMBIOS 3.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u.%u", tableLength, (unsigned long) tableAddress, diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 720d5cbd3..cbede5d1e 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -1,6 +1,7 @@ #define INITGUID #include "battery.h" +#include "common/endian.h" #include "common/debug.h" #include "common/mallocHelper.h" @@ -127,29 +128,24 @@ static void detectStaticData(FFlist* entries, FFlist* results) { FFBatteryWmiEntry* entry = getBatteryEntry(entries, results, data->Tag); FF_DEBUG("chemistry: %.4s", (const char*) &data->Chemistry); -#if __BIG_ENDIAN__ - #define htobe32(x) (x) // Should not happen on Windows, but just in case -#else - #define htobe32(x) __builtin_bswap32(x) -#endif switch (data->Chemistry) { - case htobe32('PbAc'): + case FF_READ_BE((uint32_t) 'PbAc'): ffStrbufSetStatic(&entry->result->technology, "Lead Acid"); break; - case htobe32('LION'): - case htobe32('Li-I'): + case FF_READ_BE((uint32_t) 'LION'): + case FF_READ_BE((uint32_t) 'Li-I'): ffStrbufSetStatic(&entry->result->technology, "Lithium Ion"); break; - case htobe32('NiCd'): + case FF_READ_BE((uint32_t) 'NiCd'): ffStrbufSetStatic(&entry->result->technology, "Nickel Cadmium"); break; - case htobe32('NiMH'): + case FF_READ_BE((uint32_t) 'NiMH'): ffStrbufSetStatic(&entry->result->technology, "Nickel Metal Hydride"); break; - case htobe32('NiZn'): + case FF_READ_BE((uint32_t) 'NiZn'): ffStrbufSetStatic(&entry->result->technology, "Nickel Zinc"); break; - case htobe32('RAM\0'): + case FF_READ_BE((uint32_t) 'RAM\0'): ffStrbufSetStatic(&entry->result->technology, "Rechargeable Alkaline-Manganese"); break; default: diff --git a/src/detection/chassis/chassis_linux.c b/src/detection/chassis/chassis_linux.c index 686fc67be..e23f73463 100644 --- a/src/detection/chassis/chassis_linux.c +++ b/src/detection/chassis/chassis_linux.c @@ -1,4 +1,5 @@ #include "chassis.h" +#include "common/endian.h" #include "common/io.h" #include "common/smbios.h" @@ -21,7 +22,7 @@ const char* ffDetectChassis(FFChassisResult* result) { uint32_t chassisType = 0; if (ffReadFileData("/sys/firmware/devicetree/base/smbios/smbios/chassis/chassis-type", sizeof(chassisType), &chassisType)) // big endian { - chassisType = __builtin_bswap32(chassisType); + chassisType = FF_READ_BE(chassisType); const char* typeStr = ffChassisTypeToString(chassisType); if (typeStr) { ffStrbufSetStatic(&result->type, typeStr); diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 82b656e4f..8975775d0 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -1,4 +1,5 @@ #include "cpu.h" +#include "common/endian.h" #include "common/windows/registry.h" #include "common/windows/nt.h" #include "common/mallocHelper.h" @@ -205,7 +206,7 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) { } } - uint32_t speed = data->MaxSpeed; + uint32_t speed = FF_READ_LE(data->MaxSpeed); // Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2) { return "Possible invalid CPU max speed in SMBIOS data. See #800"; diff --git a/src/detection/cpucache/cpucache_shared.c b/src/detection/cpucache/cpucache_shared.c index 58419a963..f8888313a 100644 --- a/src/detection/cpucache/cpucache_shared.c +++ b/src/detection/cpucache/cpucache_shared.c @@ -1,4 +1,5 @@ #include "cpucache.h" +#include "common/endian.h" #include "common/smbios.h" #include "common/strutil.h" @@ -43,24 +44,26 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result) { continue; } - bool enabled = !!(data->CacheConfiguration & (1 << 7)); + uint16_t cacheConfiguration = FF_READ_LE(data->CacheConfiguration); + uint16_t installedSize = FF_READ_LE(data->InstalledSize); + bool enabled = !!(cacheConfiguration & (1 << 7)); if (!enabled) { continue; } - uint32_t size = data->InstalledSize; + uint32_t size = installedSize; if (size == 0) { continue; } - if (data->InstalledSize != 0xFFFF) { + if (installedSize != 0xFFFF) { size *= (size >> 15 ? 64 : 1) * 1024u; } else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2)) { - size = data->InstalledCacheSize2; + size = FF_READ_LE(data->InstalledCacheSize2); size *= (size >> 31 ? 64 : 1) * 1024u; } - uint32_t level = (data->CacheConfiguration & 0b111u) + 1; + uint32_t level = (cacheConfiguration & 0b111u) + 1; FFCPUCacheType type; switch (data->SystemCacheType) { diff --git a/src/detection/host/host_windows.c b/src/detection/host/host_windows.c index 13bf56e88..a39a3041e 100644 --- a/src/detection/host/host_windows.c +++ b/src/detection/host/host_windows.c @@ -1,4 +1,5 @@ #include "host.h" +#include "common/endian.h" #include "common/smbios.h" typedef struct [[gnu::packed]] FFSmbiosSystemInfo { @@ -52,7 +53,14 @@ const char* ffDetectHost(FFHostResult* host) { static_assert(offsetof(FFSmbiosSystemInfo, UUID) == 0x08, "FFSmbiosSystemInfo.UUID offset is wrong"); if (data->Header.Length > offsetof(FFSmbiosSystemInfo, UUID)) { - ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", data->UUID.TimeLow, data->UUID.TimeMid, data->UUID.TimeHighAndVersion, data->UUID.ClockSeqHiAndReserved, data->UUID.ClockSeqLow, data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]); + ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + FF_READ_LE(data->UUID.TimeLow), + FF_READ_LE(data->UUID.TimeMid), + FF_READ_LE(data->UUID.TimeHighAndVersion), + data->UUID.ClockSeqHiAndReserved, + data->UUID.ClockSeqLow, + data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], + data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]); } static_assert(offsetof(FFSmbiosSystemInfo, SKUNumber) == 0x19, "FFSmbiosSystemInfo.SKUNumber offset is wrong"); diff --git a/src/detection/physicalmemory/physicalmemory_linux.c b/src/detection/physicalmemory/physicalmemory_linux.c index fe248be0c..c3e3fae96 100644 --- a/src/detection/physicalmemory/physicalmemory_linux.c +++ b/src/detection/physicalmemory/physicalmemory_linux.c @@ -1,4 +1,5 @@ #include "physicalmemory.h" +#include "common/endian.h" #include "common/smbios.h" // 7.18 @@ -82,7 +83,8 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res } const char* strings = (const char*) data + data->Header.Length; - bool installed = data->Size != 0; + uint16_t size = FF_READ_LE(data->Size); + bool installed = size != 0; if (!installed && !options->showEmptySlots) { continue; @@ -101,19 +103,21 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res device->installed = installed; device->ecc = false; - if (installed && data->TotalWidth != 0xFFFF && data->DataWidth != 0xFFFF) { - device->ecc = data->TotalWidth > data->DataWidth; + uint16_t totalWidth = FF_READ_LE(data->TotalWidth); + uint16_t dataWidth = FF_READ_LE(data->DataWidth); + if (installed && totalWidth != 0xFFFF && dataWidth != 0xFFFF) { + device->ecc = totalWidth > dataWidth; } - if (installed && data->Size != 0xFFFF) { - if (data->Size == 0x7FFF) { - device->size = (data->ExtendedSize & ~(1ULL << 31)) * 1024ULL * 1024ULL; - } else if (data->Size & (1 << 15)) { + if (installed && size != 0xFFFF) { + if (size == 0x7FFF) { + device->size = (FF_READ_LE(data->ExtendedSize) & ~(1ULL << 31)) * 1024ULL * 1024ULL; + } else if (size & (1 << 15)) { // in kB - device->size = (data->Size & ~(1ULL << 15)) * 1024ULL; + device->size = (size & ~(1ULL << 15)) * 1024ULL; } else { // in MB - device->size = data->Size * 1024ULL * 1024ULL; + device->size = size * 1024ULL * 1024ULL; } } @@ -206,8 +210,9 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res if (installed && data->Header.Length > offsetof(FFSmbiosMemoryDevice, Speed)) // 2.3+ { - if (data->Speed) { - device->maxSpeed = data->Speed == 0xFFFF ? data->ExtendedSpeed : data->Speed; + uint16_t speed = FF_READ_LE(data->Speed); + if (speed) { + device->maxSpeed = speed == 0xFFFF ? FF_READ_LE(data->ExtendedSpeed) : speed; } ffStrbufSetStatic(&device->vendor, ffSmbiosLocateString(strings, data->Manufacturer)); @@ -223,10 +228,11 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res if (installed && data->Header.Length > offsetof(FFSmbiosMemoryDevice, ConfiguredMemorySpeed)) // 2.7+ { - if (data->ConfiguredMemorySpeed) { - device->runningSpeed = data->ConfiguredMemorySpeed == 0xFFFF - ? data->ExtendedConfiguredSpeed - : data->ConfiguredMemorySpeed; + uint16_t configuredSpeed = FF_READ_LE(data->ConfiguredMemorySpeed); + if (configuredSpeed) { + device->runningSpeed = configuredSpeed == 0xFFFF + ? FF_READ_LE(data->ExtendedConfiguredSpeed) + : configuredSpeed; } } } From 4863a173e4cc3dbff76e8d993be5d81d6664364a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 1 Sep 2026 00:34:55 +0800 Subject: [PATCH 107/109] Wifi (linux): enables netlink on big-endian platforms --- src/detection/wifi/wifi_linux.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 87e8e7378..8de3ec64b 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,4 +1,5 @@ #include "wifi.h" +#include "common/endian.h" #include "common/io.h" #include "common/debug.h" #include "common/strutil.h" @@ -11,12 +12,11 @@ #include #include -#if !__BIG_ENDIAN__ - #include - #include +#include +#include - // Silence warning of `NLA_HDRLEN` and `NLA_ALIGN` - #pragma GCC diagnostic ignored "-Wsign-conversion" +// Silence warning of `NLA_HDRLEN` and `NLA_ALIGN` +#pragma GCC diagnostic ignored "-Wsign-conversion" typedef struct FFWifiNlContext { int sockFd; @@ -459,7 +459,7 @@ static void ffWifiParseRsnIe(const uint8_t* ie, size_t len, FFWifiSecurityFlags* if (pos + 2 > len) { // pairwise cipher suite count field length return; } - uint16_t pairwiseCount = *(uint16_t*) (ie + pos); + uint16_t pairwiseCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2; // skip pairwise cipher suite count field size_t pairwiseLen = (size_t) pairwiseCount * 4; // each suite selector is 4 bytes @@ -471,7 +471,7 @@ static void ffWifiParseRsnIe(const uint8_t* ie, size_t len, FFWifiSecurityFlags* if (pos + 2 > len) { // AKM suite count field length return; } - uint16_t akmCount = *(uint16_t*) (ie + pos); + uint16_t akmCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2; // skip AKM suite count field for (uint16_t i = 0; i < akmCount && pos + 4 <= len; ++i, pos += 4) { // each AKM suite selector is 4 bytes @@ -528,13 +528,13 @@ static void ffWifiParseWpaVendorIe(const uint8_t* ie, size_t len, FFWifiSecurity if (pos + 2 > len) { // unicast cipher suite count field length return; } - uint16_t pairwiseCount = *(uint16_t*) (ie + pos); + uint16_t pairwiseCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2 + (size_t) pairwiseCount * 4; // count field(2) + N unicast suite selectors(4 each) if (pos + 2 > len) { // AKM suite count field length return; } - uint16_t akmCount = *(uint16_t*) (ie + pos); + uint16_t akmCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2; // skip AKM suite count field for (uint16_t i = 0; i < akmCount && pos + 4 <= len; ++i, pos += 4) { // each AKM suite selector is 4 bytes @@ -845,8 +845,6 @@ static const char* detectWithNetlink(FFWifiNlContext* ctx, FFWifiResult* item, u FF_DEBUG("Netlink wifi detection completed"); return nullptr; } -#endif - typedef struct FFWifiIcContext { int sockFd; } FFWifiIcContext; @@ -1049,9 +1047,7 @@ const char* ffDetectWifi(FFlist* result) { return "if_nameindex() failed"; } -#if !__BIG_ENDIAN__ FFWifiNlContext nl = { .sockFd = -1 }; -#endif FFWifiIcContext ic = { .sockFd = -1 }; FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); @@ -1090,9 +1086,7 @@ const char* ffDetectWifi(FFlist* result) { if (operstate == 'u') { ffStrbufSetStatic(&item->inf.status, "up"); -#if !__BIG_ENDIAN__ detectWithNetlink(&nl, item, i->if_index); -#endif detectWithIoctl(&ic, item, i->if_name); } else { ffStrbufSetStatic(&item->conn.status, "disconnected"); @@ -1116,11 +1110,9 @@ const char* ffDetectWifi(FFlist* result) { } if_freenameindex(infs); -#if !__BIG_ENDIAN__ if (nl.sockFd >= 0) { close(nl.sockFd); } -#endif if (ic.sockFd >= 0) { close(ic.sockFd); } From 3d107764fae5b79418d39320f05c1d80c379f94a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 1 Sep 2026 14:14:01 +0800 Subject: [PATCH 108/109] Wifi (Linux): fixes compatibility with old kernel headers --- src/detection/wifi/wifi_linux.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 8de3ec64b..c0a56ede4 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -308,19 +308,19 @@ static uint16_t ffWifiChannelWidthToMhz(uint32_t width) { return 80; case NL80211_CHAN_WIDTH_160: return 160; - case NL80211_CHAN_WIDTH_5: + case 6 /* NL80211_CHAN_WIDTH_5 */: return 5; - case NL80211_CHAN_WIDTH_10: + case 7 /* NL80211_CHAN_WIDTH_10 */: return 10; - case NL80211_CHAN_WIDTH_1: + case 8 /* NL80211_CHAN_WIDTH_1 */: return 1; - case NL80211_CHAN_WIDTH_2: + case 9 /* NL80211_CHAN_WIDTH_2 */: return 2; - case NL80211_CHAN_WIDTH_4: + case 10 /* NL80211_CHAN_WIDTH_4 */: return 4; - case NL80211_CHAN_WIDTH_8: + case 11 /* NL80211_CHAN_WIDTH_8 */: return 8; - case NL80211_CHAN_WIDTH_16: + case 12 /* NL80211_CHAN_WIDTH_16 */: return 16; case 13 /* NL80211_CHAN_WIDTH_320 */: return 320; From 0b1bc5b527b958aabc62be06d89795e6d4325849 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 09:26:22 +0800 Subject: [PATCH 109/109] CI: upgrades deps; reenables Haiku --- .github/workflows/build-dragonfly-amd64.yml | 2 +- .github/workflows/build-freebsd-amd64.yml | 2 +- .github/workflows/build-haiku-amd64.yml | 4 ++-- .github/workflows/build-netbsd-amd64.yml | 2 +- .github/workflows/build-omnios-amd64.yml | 2 +- .github/workflows/build-openbsd-amd64.yml | 2 +- .github/workflows/ci.yml | 3 +-- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-dragonfly-amd64.yml b/.github/workflows/build-dragonfly-amd64.yml index c3aec5d6e..f7e406f54 100644 --- a/.github/workflows/build-dragonfly-amd64.yml +++ b/.github/workflows/build-dragonfly-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: dragonflybsd version: '6.4.2' diff --git a/.github/workflows/build-freebsd-amd64.yml b/.github/workflows/build-freebsd-amd64.yml index 1cbbcae4c..1eb0c36c6 100644 --- a/.github/workflows/build-freebsd-amd64.yml +++ b/.github/workflows/build-freebsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: freebsd version: '15.1' diff --git a/.github/workflows/build-haiku-amd64.yml b/.github/workflows/build-haiku-amd64.yml index 41aa30680..c6642b9b1 100644 --- a/.github/workflows/build-haiku-amd64.yml +++ b/.github/workflows/build-haiku-amd64.yml @@ -18,10 +18,10 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: haiku - version: 'r1beta5' + version: 'r1beta6' shell: bash cpu_count: 4 diff --git a/.github/workflows/build-netbsd-amd64.yml b/.github/workflows/build-netbsd-amd64.yml index 87a8dc497..d55dbd0b5 100644 --- a/.github/workflows/build-netbsd-amd64.yml +++ b/.github/workflows/build-netbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: netbsd version: '10.1' diff --git a/.github/workflows/build-omnios-amd64.yml b/.github/workflows/build-omnios-amd64.yml index a72108088..f29c27dc4 100644 --- a/.github/workflows/build-omnios-amd64.yml +++ b/.github/workflows/build-omnios-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: omnios version: 'r151058' diff --git a/.github/workflows/build-openbsd-amd64.yml b/.github/workflows/build-openbsd-amd64.yml index 9db8c4cef..7f7bd2102 100644 --- a/.github/workflows/build-openbsd-amd64.yml +++ b/.github/workflows/build-openbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: openbsd version: '7.9' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f63fdc04..16f6ce34c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,7 +138,6 @@ jobs: uses: ./.github/workflows/build-dragonfly-amd64.yml haiku-amd64: - if: false # Disabled because the Haiku build is currently broken needs: no-features-test name: Haiku-amd64 permissions: @@ -204,7 +203,7 @@ jobs: - dragonfly-amd64 - solaris-amd64 - omnios-amd64 - # - haiku-amd64 + - haiku-amd64 - windows-hosts permissions: contents: write