diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 174b5e961..023af3321 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,6 +197,41 @@ jobs: name: fastfetch-linux-armv7 path: ./fastfetch-*.* + linux-riscv64: + name: Linux-riscv64 + runs-on: ubuntu-22.04 + permissions: + security-events: write + contents: read + steps: + - name: checkout repository + uses: actions/checkout@v4 + + - name: run VM + uses: uraimo/run-on-arch-action@v2 + id: runcmd + with: + arch: riscv64 + distro: ubuntu22.04 + githubToken: ${{ github.token }} + run: | + uname -a + apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + cmake --build . --target package --verbose -j4 + ./fastfetch --list-features + time ./fastfetch -c presets/ci.jsonc + time ./fastfetch -c presets/ci.jsonc --format json + time ./flashfetch + ldd fastfetch + ctest + + - name: upload artifacts + uses: actions/upload-artifact@v4 + with: + name: fastfetch-linux-riscv64 + path: ./fastfetch-*.* + musl-amd64: name: Musl-amd64 runs-on: ubuntu-latest @@ -333,6 +368,40 @@ jobs: name: fastfetch-macos-universal path: ./fastfetch-*.* + sunos-amd64: + runs-on: ubuntu-latest + name: SunOS-amd64 + steps: + - name: checkout repository + uses: actions/checkout@v4 + + - uses: actions/checkout@v4 + - name: run VM + uses: vmactions/omnios-vm@v1 + with: + usesh: true + prepare: | + uname -a + pkg update --accept + pkg install gcc13 cmake git pkg-config glib2 dbus sqlite-3 imagemagick + + run: | + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + cmake --build . --target package --verbose -j4 + ./fastfetch --list-features + time ./fastfetch + time ./fastfetch --format json + time ./flashfetch + ldd fastfetch + ctest + cpack + + - name: upload artifacts + uses: actions/upload-artifact@v4 + with: + name: fastfetch-sunos-amd64 + path: ./fastfetch-*.* + freebsd-amd64: name: FreeBSD-amd64 runs-on: ubuntu-latest @@ -425,7 +494,7 @@ jobs: with: msystem: CLANG64 update: true - install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd + install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-cppwinrt - name: print msys version run: uname -a @@ -544,11 +613,13 @@ jobs: - linux-amd64 - linux-aarch64 - linux-armv7 + - linux-riscv64 - musl-amd64 - musl-aarch64 - macos-universal - freebsd-amd64 - freebsd-aarch64 + - sunos-amd64 - windows-amd64 - windows-i686 permissions: diff --git a/CHANGELOG.md b/CHANGELOG.md index 32433bc54..1f5a55cee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ +# 2.16.0 + +This release added basic support for SunOS (Solaris, illumos). The binaries provided in the release lack a few useful features (such as Display detection). People who use SunOS should consider building fastfetch themselves. + +Changes: +* Fastfetch now prefers `/etc/os-release` over `/etc/lsb-release` when detecting distro info. + * This may break some distros (notably some debian based distros). File a bug with the content of `os-release` and `lsb-release` if it breaks your distro. + +Features: +* Support Media detection in Windows (Media / Player, Windows) + * Requires Windows 10 and later +* Add new option `--users-myself-only` to display current login user only (Users) +* Add code name of macOS Sequoia (OS, macOS) +* Add new module `DNS` to show active DNS servers (DNS) +* Add new option `--loadavg-compact`. Defaults to true (Loadavg) + * Use `--loadavg-compact false` to display load averages in different lines +* Detect MTU size (LocalIP) +* Support version detection of pluma, which is the default editor of OpenIndiana (Editor) +* Print used OGL library, eg EGL, GLX or OSMesa (OpenGL) + +Bugfixes: +* Report error if cache size is unavailable (CPUCache, Android) +* Trim white spaces in device name (Sound, Linux, #1005) +* Fix `display.bar.border{Left,Right}` doesn't work in JSON config files (Config) +* Fix invalid call to `realpath(3)` (Platform, Linux) +* Fix result calculation (CPUUsage, FreeBSD) + +Logos: +* Add Mauna +* Add Tuxdeo +* Add Manjaro ARM +* Add RedOS +* Add Arch3 + # 2.15.0 Changes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 83ea5cf24..599783cff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.15.0 + VERSION 2.16.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -18,6 +18,8 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") set(BSD TRUE CACHE BOOL "..." FORCE) +elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") + set(SunOS TRUE CACHE BOOL "..." FORCE) elseif(NOT APPLE AND NOT WIN32) message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}") endif() @@ -42,30 +44,30 @@ include(CheckIncludeFile) include(CMakeDependentOption) -cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) +cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID OR SunOS" OFF) cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD OR APPLE" OFF) +cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD OR APPLE OR SunOS" OFF) cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE OR SunOS" OFF) cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) -cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF) +cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR SunOS" OFF) cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) -cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF) +cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF) cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF) @@ -118,7 +120,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointe if(WIN32 OR ENABLE_DIRECTX_HEADERS) enable_language(CXX) set(CMAKE_CXX_STANDARD 17) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -fno-exceptions -fno-rtti") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") endif() if(WIN32) @@ -340,6 +342,7 @@ set(LIBFASTFETCH_SRC src/modules/de/de.c src/modules/disk/disk.c src/modules/diskio/diskio.c + src/modules/dns/dns.c src/modules/editor/editor.c src/modules/font/font.c src/modules/gpu/gpu.c @@ -417,6 +420,7 @@ if(LINUX) src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_linux.c src/detection/disk/disk_linux.c + src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_linux.c src/detection/physicalmemory/physicalmemory_linux.c src/detection/diskio/diskio_linux.c @@ -487,6 +491,7 @@ elseif(ANDROID) src/detection/cursor/cursor_nosupport.c src/detection/cpuusage/cpuusage_linux.c src/detection/disk/disk_linux.c + src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_linux.c src/detection/physicalmemory/physicalmemory_nosupport.c src/detection/diskio/diskio_linux.c @@ -548,6 +553,7 @@ elseif(BSD) src/detection/cpuusage/cpuusage_bsd.c src/detection/cursor/cursor_linux.c src/detection/disk/disk_bsd.c + src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_bsd.c src/detection/physicalmemory/physicalmemory_linux.c src/detection/diskio/diskio_bsd.c @@ -619,6 +625,7 @@ elseif(APPLE) src/detection/cpuusage/cpuusage_apple.c src/detection/cursor/cursor_apple.m src/detection/disk/disk_bsd.c + src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_apple.c src/detection/physicalmemory/physicalmemory_apple.m src/detection/diskio/diskio_apple.c @@ -684,6 +691,7 @@ elseif(WIN32) src/detection/physicaldisk/physicaldisk_windows.c src/detection/diskio/diskio_windows.c src/detection/displayserver/displayserver_windows.c + src/detection/dns/dns_windows.c src/detection/font/font_windows.c src/detection/gpu/gpu_windows.c src/detection/host/host_windows.c @@ -695,7 +703,7 @@ elseif(WIN32) src/detection/locale/locale_windows.c src/detection/localip/localip_windows.c src/detection/gamepad/gamepad_windows.c - src/detection/media/media_nosupport.c + src/detection/media/media_windows.c src/detection/memory/memory_windows.c src/detection/physicalmemory/physicalmemory_linux.c src/detection/monitor/monitor_windows.c @@ -727,6 +735,77 @@ elseif(WIN32) src/util/windows/wmi.cpp src/util/platform/FFPlatform_windows.c ) +elseif(SunOS) + list(APPEND LIBFASTFETCH_SRC + src/common/dbus.c + src/common/io/io_unix.c + src/common/netif/netif_bsd.c + src/common/networking_linux.c + src/common/processing_linux.c + src/detection/battery/battery_nosupport.c + src/detection/bios/bios_windows.c + src/detection/board/board_windows.c + src/detection/bootmgr/bootmgr_nosupport.c + src/detection/brightness/brightness_nosupport.c + src/detection/chassis/chassis_windows.c + src/detection/cpu/cpu_sunos.c + src/detection/cpucache/cpucache_nosupport.c + src/detection/cpuusage/cpuusage_sunos.c + src/detection/cursor/cursor_linux.c + src/detection/bluetooth/bluetooth_nosupport.c + src/detection/disk/disk_sunos.c + src/detection/dns/dns_linux.c + src/detection/physicaldisk/physicaldisk_nosupport.c + src/detection/physicalmemory/physicalmemory_linux.c + src/detection/diskio/diskio_sunos.c + src/detection/displayserver/linux/displayserver_linux.c + src/detection/displayserver/linux/drm.c + src/detection/displayserver/linux/wayland/wayland.c + src/detection/displayserver/linux/wayland/global-output.c + src/detection/displayserver/linux/wayland/zwlr-output.c + src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c + src/detection/displayserver/linux/wmde.c + src/detection/displayserver/linux/xcb.c + src/detection/displayserver/linux/xlib.c + src/detection/font/font_linux.c + src/detection/gpu/gpu_sunos.c + src/detection/gpu/gpu_pci.c + src/detection/gtk_qt/gtk.c + src/detection/host/host_windows.c + src/detection/icons/icons_linux.c + src/detection/initsystem/initsystem_linux.c + src/detection/libc/libc_nosupport.c + src/detection/lm/lm_nosupport.c + src/detection/loadavg/loadavg_sunos.c + src/detection/locale/locale_linux.c + src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c + src/detection/media/media_linux.c + src/detection/memory/memory_sunos.c + src/detection/monitor/monitor_nosupport.c + src/detection/netio/netio_sunos.c + src/detection/opengl/opengl_linux.c + 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/gtk_qt/qt.c + src/detection/sound/sound_linux.c + src/detection/swap/swap_sunos.c + src/detection/terminalfont/terminalfont_linux.c + src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c + src/detection/theme/theme_linux.c + 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/wm/wm_nosupport.c + src/detection/de/de_linux.c + src/detection/wmtheme/wmtheme_linux.c + src/detection/camera/camera_nosupport.c + src/util/platform/FFPlatform_unix.c + ) endif() if(ENABLE_DIRECTX_HEADERS) @@ -814,6 +893,8 @@ if(WIN32) target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1) elseif(APPLE) target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE) +elseif(SunOS) + target_compile_definitions(libfastfetch PUBLIC __EXTENSIONS__ _POSIX_C_SOURCE=1) endif() if(HAVE_STATX) @@ -1001,6 +1082,7 @@ if(LINUX) ) elseif(APPLE) target_link_libraries(libfastfetch + PRIVATE "resolv" PRIVATE "-framework AVFoundation" PRIVATE "-framework Cocoa" PRIVATE "-framework CoreFoundation" @@ -1042,6 +1124,13 @@ elseif(BSD) PRIVATE "usbhid" PRIVATE "geom" ) +elseif(SunOS) + target_link_libraries(libfastfetch + PRIVATE "m" + PRIVATE "socket" + PRIVATE "kstat" + PRIVATE "proc" + ) elseif(ANDROID) CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC) if(HAVE_LIBANDROID_WORDEXP_STATIC) @@ -1067,6 +1156,24 @@ target_link_libraries(libfastfetch PRIVATE ${CMAKE_DL_LIBS} ) +target_compile_options(libfastfetch PRIVATE + $<$:-fno-exceptions -fno-rtti>) + +if(WIN32) + set(CMAKE_CXX_STANDARD 20) + include(CheckIncludeFileCXX) + CHECK_INCLUDE_FILE_CXX("winrt/Windows.Foundation.h" HAVE_WINRT) + if(HAVE_WINRT) + add_library(ffwinrt SHARED src/detection/media/media_windows.dll.cpp) + target_link_libraries(ffwinrt PRIVATE "RuntimeObject") + target_compile_definitions(ffwinrt PRIVATE WIN32_LEAN_AND_MEAN=1 WINRT_LEAN_AND_MEAN=1) + target_link_options(ffwinrt + PRIVATE "-static" # stdc++, winpthread, gcc_s, etc. + ) + endif() + set(CMAKE_CXX_STANDARD 17) +endif() + ###################### # Executable targets # ###################### @@ -1105,12 +1212,9 @@ if(yyjson_FOUND) endif() if(WIN32) - set(TARGET_NAME fastfetch) target_sources(fastfetch PRIVATE src/util/windows/version.rc ) - - set(TARGET_NAME flashfetch) target_sources(flashfetch PRIVATE src/util/windows/version.rc ) diff --git a/debian/changelog b/debian/changelog index e8a82b8f3..bd89f89ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +fastfetch (2.15.0) jammy; urgency=medium + + * Update to 2.15.0 + + -- Carter Li Fri, 07 Jun 2024 13:52:43 +0800 + +fastfetch (2.14.0) jammy; urgency=medium + + * Update to 2.14.0 + + -- Carter Li Thu, 30 May 2024 14:27:54 +0800 + fastfetch (2.13.2) jammy; urgency=medium * Update to 2.13.2 diff --git a/debian/files b/debian/files index 0372bb94a..d6cc5ebae 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.13.2_source.buildinfo universe/utils optional +fastfetch_2.15.0_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index 3533c651f..cdcfd736f 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -705,6 +705,7 @@ "disk", "diskio", "de", + "dns", "editor", "font", "gamepad", @@ -903,10 +904,6 @@ "const": "uptime", "description": "Print how long system has been running" }, - { - "const": "users", - "description": "Print users currently logged in" - }, { "const": "version", "description": "Print Fastfetch version" @@ -1438,6 +1435,41 @@ } } }, + { + "title": "DNS", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "const": "dns", + "description": "Print DNS servers" + }, + "showType": { + "enum": [ + "ipv4", + "ipv6", + "both" + ], + "default": "both", + "description": "Specify the type of DNS servers should be detected" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + } + }, { "title": "Gamepad", "type": "object", @@ -1636,6 +1668,14 @@ "maximum": 9, "default": 2 }, + "compact": { + "type": "boolean", + "description": "Show values in one line", + "default": true + }, + "percent": { + "$ref": "#/$defs/percent" + }, "key": { "$ref": "#/$defs/key" }, @@ -1999,6 +2039,42 @@ } } }, + { + "title": "Users", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "const": "users", + "description": "Print users currently logged in" + }, + "compact": { + "type": "boolean", + "description": "Show all active users in one line", + "default": false + }, + "myselfOnly": { + "type": "boolean", + "description": "Show only the current user", + "default": false + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + } + }, { "title": "Weather", "type": "object", diff --git a/presets/examples/13.jsonc b/presets/examples/13.jsonc index 8b29ab4c1..84b115be5 100644 --- a/presets/examples/13.jsonc +++ b/presets/examples/13.jsonc @@ -1,3 +1,4 @@ +// Inspired by Catnap { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", "logo": { diff --git a/presets/examples/14.jsonc b/presets/examples/14.jsonc index 0b82ef322..3e7a9f192 100644 --- a/presets/examples/14.jsonc +++ b/presets/examples/14.jsonc @@ -1,3 +1,4 @@ +// Inspired by Catnap { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", "logo": { diff --git a/presets/examples/15.jsonc b/presets/examples/15.jsonc index 7ac90feb0..1c849cec8 100644 --- a/presets/examples/15.jsonc +++ b/presets/examples/15.jsonc @@ -1,3 +1,4 @@ +// Inspired by Catnap { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", "logo": { diff --git a/presets/examples/16.jsonc b/presets/examples/16.jsonc index 6809c3e81..b48635ef2 100644 --- a/presets/examples/16.jsonc +++ b/presets/examples/16.jsonc @@ -1,3 +1,4 @@ +// Inspired by Catnap { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", "logo": { diff --git a/presets/examples/19.jsonc b/presets/examples/19.jsonc new file mode 100644 index 000000000..2663ea159 --- /dev/null +++ b/presets/examples/19.jsonc @@ -0,0 +1,188 @@ +// _____ _____ _____ _____ _____ _____ _____ _____ _____ +// | __| _ | __|_ _| __| __|_ _| | | | +// | __| |__ | | | | __| __| | | | --| | +// |__| |__|__|_____| |_| |__| |_____| |_| |_____|__|__| +// +// By CarterLi - https://github.com/CarterLi +// Homepage - https://github.com/fastfetch-cli/fastfetch +// config.jsonc - ニリ @niri-san +// pokemon-colorscripts - https://gitlab.com/phoneybadger/pokemon-colorscripts +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "source": " _____ _____ _____ _____ _____ _____ _____ _____ _____\n| __| _ | __|_ _| __| __|_ _| | | |\n| __| |__ | | | | __| __| | | | --| |\n|__| |__|__|_____| |_| |__| |_____| |_| |_____|__|__|", + "type": "data", + "separate": true, + "padding": { + "right": 2 + } + }, + "display": { + "separator": " - " + }, + "modules": [ + { + "type": "custom", // HardwareInfo + "format": "• {#green}SYSTEM INFORMATION" + }, + { + "type": "host", + "key": "HOST", + "format": "{name}{?vendor} ({vendor}){?}", + "keyColor": "green" + }, + { + "type": "chassis", + "key": "COMPUTER TYPE", + "keyColor": "green" + }, + { + "type": "cpu", + "key": "CPU", + "keyColor": "green" + }, + { + "type": "gpu", + "key": "GPU", + "keyColor": "green" + }, + { + "type": "memory", + "key": "MEMORY USED", + "keyColor": "green" + }, + { + "type": "swap", + "key": "SWAP USED", + "keyColor": "green" + }, + { + "type": "disk", + "key": "DISK", + "folders": "/", + "keyColor": "green" + }, + { + "type": "custom", // SoftwareInfo + "format": "• {#red}SOFTWARE INFORMATION" + }, + { + "type": "os", + "key": "DISTRO", + "keyColor": "red" + }, + { + "type": "disk", + "folders": "/", // Use "/System/Volumes/VM" or something else on macOS + "format": "{create-time}", + "key": "INSTALLED DATE", + "keyColor": "red" + }, + { + "type": "kernel", + "key": "KERNEL", + "keyColor": "red" + }, + { + "type": "packages", + "key": "PACKAGES", + "keyColor": "red" + }, + { + "type": "uptime", + "key": "UPTIME", + "keyColor": "red" + }, + { + "type": "custom", // DisplayInfo + "format": "• {#blue}DISPLAY INFORMATION" + }, + { + "type": "de", + "key": "DESKTOP ENVIRONMENT", + "keyColor": "blue" + }, + { + "type": "lm", + "key": "LOGIN MANAGER", + "format": "{type}", + "keyColor": "blue" + }, + { + "type": "wm", + "key": "WM", + "keyColor": "blue" + }, + { + "type": "wmtheme", + "key": "WM THEME", + "keyColor": "blue" + }, + { + "type": "monitor", + "key": "MONITOR ({name})", + "keyColor": "blue" + }, + { + "type": "custom", // DesignInfo + "format": "• {#yellow}DESIGN INFORMATION" + }, + { + "type": "wallpaper", + "key": "WALLPAPER", + "keyColor": "yellow" + }, + { + "type": "theme", + "key": "KDE THEME", + "format": "{1}", + "keyColor": "yellow" + }, + { + "type": "icons", + "key": "ICON THEME", + "format": "{1}", + "keyColor": "yellow" + }, + { + "type": "font", + "key": "FONT", + "format": "{?1}{1} [QT]{?}{/1}Unknown", // Remove "[QT]" if not using Qt + "keyColor": "yellow" + }, + { + "type": "terminalfont", + "key": "TERMINAL FONT", + "keyColor": "yellow" + }, + { + "type": "cursor", + "key": "CURSOR", + "keyColor": "yellow" + }, + { + "type": "custom", // OtherInfo + "format": "• {#cyan}VARIOUS INFORMATION" + }, + { + "type": "media", + "key": "NOW PLAYING", + "format": "{?artist}{artist} - {?}{title}", + "keyColor": "cyan" + }, + { + "type": "weather", + "key": "WEATHER", + "timeout": 1000, + "keyColor": "cyan" + }, + { + "type": "version", + "key": "INFO", + "keyColor": "cyan" + }, + "break", + "colors", + "break" + ] +} diff --git a/presets/examples/20.jsonc b/presets/examples/20.jsonc new file mode 100644 index 000000000..231d50b62 --- /dev/null +++ b/presets/examples/20.jsonc @@ -0,0 +1,160 @@ +// Inspired by https://github.com/usgraphics/TR-100 +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": null, + "display": { + "pipe": true, + "keyWidth": 16, + "separator": "│ ", + "percent": { + "type": 6 + }, + "bar": { + "borderLeft": "", + "borderRight": "", + "charElapsed": "█", + "charTotal": "░", + "width": 40 + } + }, + "modules": [ + { + "type": "custom", + "format": "┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐" + }, + { + "type": "custom", + "format": "├┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┤" + }, + { + "type": "version", + "key": " ", + "format": "│ FASTFETCH v{version} │" + }, + { + "type": "custom", + "format": "│ TR-100 MACHINE REPORT │" + }, + { + "type": "custom", + "format": "├────────────┬──────────────────────────────────────────┤" + }, + { + "type": "os", + "key": "│ OS │\u001b[42C" + }, + { + "type": "kernel", + "key": "│ KERNEL │\u001b[42C" + }, + { + "type": "custom", + "format": "├────────────┼──────────────────────────────────────────┤" + }, + { + "type": "title", + "key": "│ HOSTNAME │\u001b[42C", + "format": "{host-name}" + }, + { + "type": "localip", + "key": "│ CLIENT IP │\u001b[42C", + "format": "{ipv4}" + }, + { + "type": "localip", + "key": "│ MAC ADDR │\u001b[42C", + "format": "{mac} ({ifname})", + "showIPv4": false, + "showMac": true + }, + { + "type": "dns", + "key": "│ DNS │\u001b[42C", + "showType": "ipv4" + }, + { + "type": "title", + "key": "│ USER │\u001b[42C", + "format": "{user-name}" + }, + { + "type": "host", + "key": "│ MACHINE │\u001b[42C", + "format": "{name}" + }, + { + "type": "custom", + "format": "├────────────┼──────────────────────────────────────────┤" + }, + { + "type": "cpu", + "key": "│ PROCESSOR │\u001b[42C", + "format": "{name}" + }, + { + "type": "cpu", + "key": "│ CORES │\u001b[42C", + "format": "{cores-physical} PHYSICAL CORES / {cores-logical} THREADS", + "showPeCoreCount": false + }, + { + "type": "cpu", + "key": "│ CPU FREQ │\u001b[42C", + "format": "{freq-max}{/freq-max}{freq-base}{/} GHz" + }, + { + "type": "loadavg", + "compact": false, + // {duration} is not fixed length, hack it + "key": "│ LOAD \u001b[s{duration}m\u001b[u\u001b[6C│\u001b[42C" + }, + { + "type": "custom", + "format": "├────────────┼──────────────────────────────────────────┤" + }, + { + "type": "memory", + "key": "│ MEMORY │\u001b[42C", + "format": "{used} / {total} [{percentage}]" + }, + { + "type": "memory", + "key": "│ USAGE │\u001b[42C", + "format": "" + }, + { + "type": "custom", + "format": "├────────────┼──────────────────────────────────────────┤" + }, + { + "type": "disk", + "key": "│ VOLUME │\u001b[42C", + "format": "{size-used} / {size-total} [{size-percentage}]", + "folders": "/" + }, + { + "type": "disk", + "key": "│ DISK USAGE │\u001b[42C", + "format": "" + }, + { + "type": "custom", + "format": "├────────────┼──────────────────────────────────────────┤" + }, + { + "type": "users", + "key": "│ LAST LOGIN │\u001b[42C", + "format": "{login-time}{?client-ip} ({client-ip})", + "myselfOnly": true + }, + { + "type": "uptime", + "key": "│ UPTIME │\u001b[42C" + }, + { + "type": "custom", + "format": "└────────────┴──────────────────────────────────────────┘" + } + ] + } diff --git a/presets/examples/21.jsonc b/presets/examples/21.jsonc new file mode 100644 index 000000000..69f867ef9 --- /dev/null +++ b/presets/examples/21.jsonc @@ -0,0 +1,43 @@ +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "type": "small" + }, + "modules": [ + { + "key": "██ Distro", + "keyColor": "38;5;210", + "type": "os" + }, + { + "key": "██ Kernel", + "keyColor": "38;5;84", + "type": "kernel" + }, + { + "key": "██ Shell", + "keyColor": "38;5;147", + "type": "shell" + }, + { + "key": "██ Packages", + "keyColor": "38;5;200", + "type": "packages" + }, + { + "key": "██ WM", + "keyColor": "38;5;44", + "type": "wm" + }, + { + "key": "██ CPU", + "keyColor": "38;5;75", + "type": "cpu" + }, + { + "key": "██ Memory", + "keyColor": "38;5;123", + "type": "memory" + } + ] +} diff --git a/presets/examples/22.jsonc b/presets/examples/22.jsonc new file mode 100644 index 000000000..5ccb863f4 --- /dev/null +++ b/presets/examples/22.jsonc @@ -0,0 +1,109 @@ +// Modified from: https://github.com/fastfetch-cli/fastfetch/pull/1025#issuecomment-2177566138 +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "source": "arch3", + "color": { + "1": "red", + "2": "yellow" + } + }, + "display": { + "color": { + "separator": "blue" + }, + "separator": " | " + }, + "modules": [ + { + "type": "kernel", + "key": " /\\rch Linux", + "keyColor": "magenta" + }, + { + "type": "custom", + "format": ">-----------<+>------------------------------------------<", + "outputColor": "separator" + }, + { + "type": "uptime", + "key": " Uptime ", + "keyColor": "green" + }, + { + "type": "shell", + "key": " Shell ", + "keyColor": "green" + }, + { + "type": "terminal", + "key": " Terminal ", + "keyColor": "green" + }, + { + "type": "terminalfont", + "key": " Font ", + "keyColor": "green" + }, + { + "type": "packages", + "key": " Packages ", + "keyColor": "green" + }, + { + "type": "localip", + "key": " Local IP ", + "keyColor": "green" + }, + { + "type": "custom", + "format": ">-----------<+>------------------------------------------<", + "outputColor": "separator" + }, + { + "type": "display", + "key": " Display ", + "keyColor": "cyan" + }, + { + "type": "cpu", + "key": " CPU ", + "keyColor": "cyan" + }, + { + "type": "gpu", + "key": " GPU ", + "keyColor": "cyan" + }, + { + "type": "memory", + "key": " RAM ", + "keyColor": "cyan" + }, + { + "type": "swap", + "key": " SWAP ", + "keyColor": "cyan" + }, + { + "type": "disk", + "key": " Disk ", + "keyColor": "cyan" + }, + { + "type": "battery", + "key": " Battery ", + "keyColor": "cyan" + }, + { + "type": "custom", + "format": ">-----------<+>------------------------------------------<", + "outputColor": "separator" + }, + "break", + { + "type": "colors", + "paddingLeft": 15 + } + ] +} diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index d204de1ea..501e23015 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -204,7 +204,11 @@ bool ffSuppressIO(bool suppress) void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indentation, const char* folderName, bool pretty) { - DIR* dir = opendir(folder->chars); + FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY); + if (dfd < 0) + return; + + DIR* dir = fdopendir(dfd); if(dir == NULL) return; @@ -221,7 +225,21 @@ void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indenta while((entry = readdir(dir)) != NULL) { - if(entry->d_type == DT_DIR) + bool isDir = false; +#ifdef _DIRENT_HAVE_D_TYPE + if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) + isDir = entry->d_type == DT_DIR; + else +#else + { + struct stat stbuf; + if (fstatat(dfd, entry->d_name, &stbuf, 0) < 0) + isDir = false; + else + isDir = S_ISDIR(stbuf.st_mode); + } +#endif + if (isDir) { if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) continue; diff --git a/src/common/modules.c b/src/common/modules.c index 9580ccb06..d7607aa3a 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -34,6 +34,7 @@ static FFModuleBaseInfo* D[] = { (void*) &instance.config.modules.display, (void*) &instance.config.modules.disk, (void*) &instance.config.modules.diskIo, + (void*) &instance.config.modules.dns, NULL, }; diff --git a/src/common/netif/netif_bsd.c b/src/common/netif/netif_bsd.c index f288d7d35..b01ef2040 100644 --- a/src/common/netif/netif_bsd.c +++ b/src/common/netif/netif_bsd.c @@ -18,6 +18,8 @@ # define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) #elif defined(__OpenBSD__) # define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__sun) +# define ROUNDUP(a) ROUNDUP2((a), _SS_ALIGNSIZE) #else # error unknown platform #endif @@ -31,9 +33,13 @@ get_rt_address(struct rt_msghdr *rtm, int desired) { if (rtm->rtm_addrs & (1 << i)) { - if ((1 <sa_len) + (char *)sa); +#endif } } return NULL; @@ -71,7 +77,9 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) }, .dst = { .sin_family = AF_INET, + #ifndef __sun .sin_len = sizeof(rtmsg.dst), + #endif }, }; diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index ac4ee2b9f..af3f4ebf5 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -18,8 +18,10 @@ #include #include #endif -#ifdef __APPLE__ +#if defined(__APPLE__) #include +#elif defined(__sun) + #include #endif enum { FF_PIPE_BUFSIZ = 8192 }; @@ -234,6 +236,29 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons ffStrbufSetS(exe, arg0); } + #elif defined(__sun) + + char filePath[PATH_MAX]; + snprintf(filePath, sizeof(filePath), "/proc/%d/psinfo", (int) pid); + psinfo_t proc; + if (ffReadFileData(filePath, sizeof(proc), &proc) == sizeof(proc)) + { + ffStrbufSetS(exe, proc.pr_psargs); + ffStrbufSubstrBeforeFirstC(exe, ' '); + } + + if (exePath) + { + snprintf(filePath, sizeof(filePath), "/proc/%d/path/a.out", (int) pid); + ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX); + ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1); + if (length > 0) // doesn't contain trailing NUL + { + exePath->chars[length] = '\0'; + exePath->length = (uint32_t) length; + } + } + #endif if(exe->length == 0) @@ -335,6 +360,19 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i *tty = -1; } + #elif defined(__sun) + char path[128]; + snprintf(path, sizeof(path), "/proc/%d/psinfo", (int) pid); + psinfo_t proc; + if (ffReadFileData(path, sizeof(proc), &proc) != sizeof(proc)) + return "ffReadFileData(psinfo) failed"; + + ffStrbufSetS(name, proc.pr_fname); + if (ppid) + *ppid = proc.pr_ppid; + if (tty) + *tty = (int) proc.pr_ttydev; + #else return "Unsupported platform"; diff --git a/src/data/help.json b/src/data/help.json index cbecc9032..4dcdae17b 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1287,6 +1287,15 @@ "default": 2 } }, + { + "long": "loadavg-compact", + "desc": "Show load average values in one line", + "arg": { + "type": "bool", + "optional": true, + "default": true + } + }, { "long": "localip-show-ipv4", "desc": "Show IPv4 addresses in local ip module", @@ -1367,6 +1376,19 @@ "default": false } }, + { + "long": "dns-show-type", + "desc": "Specify the type of DNS servers should be detected", + "arg": { + "type": "enum", + "enum": { + "ipv4": "Show IPv4 addresses only", + "ipv6": "Show IPv6 addresses only", + "both": "Show both IPv4 and IPv6 addresses" + }, + "default": "both" + } + }, { "long": "netio-name-prefix", "desc": "Show interfaces with given name prefix only", @@ -1450,6 +1472,24 @@ "default": false } }, + { + "long": "users-compact", + "desc": "Show all active users in one line", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, + { + "long": "users-myself-only", + "desc": "Show only current user", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "player-name", "desc": "The name of the player to use for module Media and Player", diff --git a/src/detection/bios/bios_nosupport.c b/src/detection/bios/bios_nosupport.c new file mode 100644 index 000000000..76abc7a12 --- /dev/null +++ b/src/detection/bios/bios_nosupport.c @@ -0,0 +1,6 @@ +#include "bios.h" + +const char* ffDetectBios(FFBiosResult* bios) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/bios/bios_windows.c b/src/detection/bios/bios_windows.c index d7a954074..adabbe2bb 100644 --- a/src/detection/bios/bios_windows.c +++ b/src/detection/bios/bios_windows.c @@ -1,5 +1,7 @@ #include "bios.h" #include "util/smbiosHelper.h" + +#ifdef _WIN32 #include "util/windows/registry.h" #include @@ -25,7 +27,7 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION }; }; } SYSTEM_BOOT_ENVIRONMENT_INFORMATION; - +#endif typedef struct FFSmbiosBios { @@ -74,6 +76,7 @@ const char* ffDetectBios(FFBiosResult* bios) if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease)) ffStrbufSetF(&bios->release, "%u.%u", data->SystemBiosMajorRelease, data->SystemBiosMinorRelease); + #ifdef _WIN32 // Same as GetFirmwareType, but support (?) Windows 7 // https://ntdoc.m417z.com/system_information_class SYSTEM_BOOT_ENVIRONMENT_INFORMATION sbei; @@ -86,6 +89,7 @@ const char* ffDetectBios(FFBiosResult* bios) default: break; } } + #endif return NULL; } diff --git a/src/detection/camera/camera_nosupport.c b/src/detection/camera/camera_nosupport.c new file mode 100644 index 000000000..383e4cec1 --- /dev/null +++ b/src/detection/camera/camera_nosupport.c @@ -0,0 +1,6 @@ +#include "camera.h" + +const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) +{ + return "Not support on this platform"; +} diff --git a/src/detection/cpu/cpu_nosupport.c b/src/detection/cpu/cpu_nosupport.c new file mode 100644 index 000000000..2a06915d2 --- /dev/null +++ b/src/detection/cpu/cpu_nosupport.c @@ -0,0 +1,6 @@ +#include "cpu.h" + +const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/cpu/cpu_sunos.c b/src/detection/cpu/cpu_sunos.c new file mode 100644 index 000000000..4d66c69ab --- /dev/null +++ b/src/detection/cpu/cpu_sunos.c @@ -0,0 +1,45 @@ +#include "cpu.h" +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) +{ + assert(pkc); + if (*pkc) + kstat_close(*pkc); +} + +const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu) +{ + __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); + if (!kc) + return "kstat_open() failed"; + + kstat_t* ks = kstat_lookup(kc, "cpu_info", -1, NULL); + if (!ks) + return "kstat_lookup() failed"; + + if (kstat_read(kc, ks, NULL) < 0) + return "kstat_read() failed"; + + { + kstat_named_t* kn = kstat_data_lookup(ks, "brand"); + ffStrbufSetNS(&cpu->name, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn)); + } + { + kstat_named_t* kn = kstat_data_lookup(ks, "vendor_id"); + ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn)); + } + { + kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz"); + cpu->frequencyBase = kn->value.ui32 / 1000.; + } + + ks = kstat_lookup(kc, "unix", -1, "system_misc"); + if (ks && kstat_read(kc, ks, NULL) >= 0) + { + kstat_named_t* kn = kstat_data_lookup(ks, "ncpus"); + cpu->coresLogical = cpu->coresPhysical = cpu->coresOnline = (uint16_t) kn->value.ui32; + } + + return NULL; +} diff --git a/src/detection/cpucache/cpucache_linux.c b/src/detection/cpucache/cpucache_linux.c index 30737fc69..11ec5cbd1 100644 --- a/src/detection/cpucache/cpucache_linux.c +++ b/src/detection/cpucache/cpucache_linux.c @@ -50,7 +50,7 @@ static const char* parseCpuCacheIndex(FFstrbuf* path, FFCPUCacheResult* result, // deduplicate shared caches ffStrbufAppendF(buffer, "_%u_%u_%u_%u\n", level, sizeKb, lineSize, cacheType); - if (ffStrbufContain(added, buffer)) return "cache already added"; + if (ffStrbufContain(added, buffer)) return NULL; ffStrbufAppend(added, buffer); ffCPUCacheAddItem(result, level, sizeKb * 1024, lineSize, cacheType); return NULL; @@ -71,7 +71,8 @@ static const char* parseCpuCache(FFstrbuf* path, FFCPUCacheResult* result, FFstr || !ffCharIsDigit(pathCacheEntry->d_name[strlen("index")])) continue; ffStrbufAppendS(path, pathCacheEntry->d_name); - parseCpuCacheIndex(path, result, buffer, added); + const char* error = parseCpuCacheIndex(path, result, buffer, added); + if (error) return error; ffStrbufSubstrBefore(path, baseLen); } @@ -97,7 +98,8 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result) !ffCharIsDigit(pathCpuEntry->d_name[strlen("cpu")])) continue; ffStrbufAppendS(&path, pathCpuEntry->d_name); - parseCpuCache(&path, result, &buffer, &added); + const char* error = parseCpuCache(&path, result, &buffer, &added); + if (error) return error; ffStrbufSubstrBefore(&path, baseLen); } return NULL; diff --git a/src/detection/cpucache/cpucache_nosupport.c b/src/detection/cpucache/cpucache_nosupport.c index 5d5291209..b405b9079 100644 --- a/src/detection/cpucache/cpucache_nosupport.c +++ b/src/detection/cpucache/cpucache_nosupport.c @@ -1,5 +1,4 @@ #include "cpucache.h" -#include "common/sysctl.h" const char* ffDetectCPUCache(FF_MAYBE_UNUSED FFCPUCacheResult* result) { diff --git a/src/detection/cpuusage/cpuusage_bsd.c b/src/detection/cpuusage/cpuusage_bsd.c index 87c6757a7..af513878f 100644 --- a/src/detection/cpuusage/cpuusage_bsd.c +++ b/src/detection/cpuusage/cpuusage_bsd.c @@ -23,12 +23,12 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { uint64_t* cpTime = cpTimes[i]; uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS]; - uint64_t total = cpTime[CP_INTR] + cpTime[CP_IDLE]; + uint64_t total = inUse + cpTime[CP_INTR] + cpTime[CP_IDLE]; FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); *info = (FFCpuUsageInfo) { - .inUseAll = (uint64_t)inUse, - .totalAll = (uint64_t)total, + .inUseAll = inUse, + .totalAll = total, }; } diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index 118353e2c..b91d6eeb1 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -36,8 +36,8 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes) FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); *info = (FFCpuUsageInfo) { - .inUseAll = (uint64_t)inUse, - .totalAll = (uint64_t)total, + .inUseAll = inUse, + .totalAll = total, }; } else diff --git a/src/detection/cpuusage/cpuusage_nosupport.c b/src/detection/cpuusage/cpuusage_nosupport.c new file mode 100644 index 000000000..72770e3be --- /dev/null +++ b/src/detection/cpuusage/cpuusage_nosupport.c @@ -0,0 +1,7 @@ +#include "fastfetch.h" +#include "detection/cpuusage/cpuusage.h" + +const char* ffGetCpuUsageInfo(FFlist* cpuTimes) +{ + return "Not support on this platform"; +} diff --git a/src/detection/cpuusage/cpuusage_sunos.c b/src/detection/cpuusage/cpuusage_sunos.c new file mode 100644 index 000000000..2e36adbfe --- /dev/null +++ b/src/detection/cpuusage/cpuusage_sunos.c @@ -0,0 +1,38 @@ +#include "fastfetch.h" +#include "detection/cpuusage/cpuusage.h" + +#include +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) +{ + assert(pkc); + if (*pkc) + kstat_close(*pkc); +} + +const char* ffGetCpuUsageInfo(FFlist* cpuTimes) +{ + __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); + if (!kc) + return "kstat_open() failed"; + + for (int i = 0;; ++i) + { + kstat_t* ks = kstat_lookup(kc, "cpu_stat", i, NULL); + + cpu_stat_t cs; + if (!ks || kstat_read(kc, ks, &cs) < 0) + break; + + uint64_t inUse = cs.cpu_sysinfo.cpu[CPU_USER] + cs.cpu_sysinfo.cpu[CPU_KERNEL]; + uint64_t total = inUse + cs.cpu_sysinfo.cpu[CPU_IDLE] + cs.cpu_sysinfo.cpu[CPU_WAIT]; + + FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); + *info = (FFCpuUsageInfo) { + .inUseAll = inUse, + .totalAll = total, + }; + } + return NULL; +} diff --git a/src/detection/cpuusage/cpuusage_windows.c b/src/detection/cpuusage/cpuusage_windows.c index cf513340e..21c582b13 100644 --- a/src/detection/cpuusage/cpuusage_windows.c +++ b/src/detection/cpuusage/cpuusage_windows.c @@ -31,8 +31,8 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes) FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); *info = (FFCpuUsageInfo) { - .inUseAll = (uint64_t)inUse, - .totalAll = (uint64_t)total, + .inUseAll = inUse, + .totalAll = total, }; } diff --git a/src/detection/disk/disk_nosupport.c b/src/detection/disk/disk_nosupport.c new file mode 100644 index 000000000..cd224572a --- /dev/null +++ b/src/detection/disk/disk_nosupport.c @@ -0,0 +1,6 @@ +#include "disk.h" + +const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/disk/disk_sunos.c b/src/detection/disk/disk_sunos.c new file mode 100644 index 000000000..91cde2333 --- /dev/null +++ b/src/detection/disk/disk_sunos.c @@ -0,0 +1,138 @@ +#include "disk.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +#include +#include +#include +#include +#include + +static bool isPhysicalDevice(const struct mnttab* device) +{ + //Always show the root path + if(ffStrEquals(device->mnt_mountp, "/")) + return true; + + if(ffStrEquals(device->mnt_special, "none")) + return false; + + //ZFS pool + if(ffStrEquals(device->mnt_fstype, "zfs")) + return true; + + //Pseudo filesystems don't have a device in /dev + if(!ffStrStartsWith(device->mnt_special, "/dev/")) + return false; + + struct stat deviceStat; + if(stat(device->mnt_special, &deviceStat) != 0) + return false; + + //Ignore all devices that are not block devices + if(!S_ISBLK(deviceStat.st_mode)) + return false; + + return true; +} + +static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) +{ + if(ffStrbufEqualS(¤tDisk->filesystem, "zfs")) + { + //ZFS subvolumes + uint32_t index = ffStrbufFirstIndexC(¤tDisk->mountFrom, '/'); + if (index == currentDisk->mountFrom.length) + return false; + + FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->mountFrom.chars); + for(uint32_t i = 0; i < disks->length - 1; i++) + { + const FFDisk* otherDevice = ffListGet(disks, i); + if(ffStrbufEqualS(&otherDevice->filesystem, "zfs") && ffStrbufStartsWith(&otherDevice->mountFrom, &zpoolName)) + return true; + } + + return false; + } + else + { + //Filter all disks which device was already found. This catches BTRFS subvolumes. + for(uint32_t i = 0; i < disks->length - 1; i++) + { + const FFDisk* otherDevice = ffListGet(disks, i); + + if(ffStrbufEqual(¤tDisk->mountFrom, &otherDevice->mountFrom)) + return true; + } + } + + return false; +} + +static void detectType(const FFlist* disks, FFDisk* currentDisk, struct mnttab* device) +{ + if(ffStrContains(device->mnt_mntopts, MNTOPT_NOBROWSE)) + currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; + else if(isSubvolume(disks, currentDisk)) + currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; + else + currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; +} + +static void detectStats(FFDisk* disk) +{ + struct statvfs fs; + if(statvfs(disk->mountpoint.chars, &fs) != 0) + memset(&fs, 0, sizeof(struct statvfs)); + + disk->bytesTotal = fs.f_blocks * fs.f_frsize; + disk->bytesFree = fs.f_bfree * fs.f_frsize; + disk->bytesAvailable = fs.f_bavail * fs.f_frsize; + disk->bytesUsed = 0; // To be filled in ./disk.c + + disk->filesTotal = (uint32_t) fs.f_files; + disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree); + + if(fs.f_flag & ST_RDONLY) + disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; + + ffStrbufSetS(&disk->name, fs.f_fstr); + + disk->createTime = 0; + struct stat deviceStat; + if(stat(disk->mountpoint.chars, &deviceStat) == 0) + disk->createTime = (uint64_t) deviceStat.st_ctim.tv_sec * 1000 + (uint64_t) deviceStat.st_ctim.tv_nsec / 1000000000; +} + +const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) +{ + FF_AUTO_CLOSE_FILE FILE* mountsFile = fopen(MNTTAB, "r"); + if(mountsFile == NULL) + return "fopen(\"" MNTTAB "\", \"r\") == NULL"; + + struct mnttab device; + + while (getmntent(mountsFile, &device) == 0) + { + if (__builtin_expect(options->folders.length, 0)) + { + if (!ffDiskMatchMountpoint(options, device.mnt_mountp)) + continue; + } + else if(!isPhysicalDevice(&device)) + continue; + + //We have a valid device, add it to the list + FFDisk* disk = ffListAdd(disks); + disk->type = FF_DISK_VOLUME_TYPE_NONE; + ffStrbufInitS(&disk->mountFrom, device.mnt_special); + ffStrbufInitS(&disk->mountpoint, device.mnt_mountp); + ffStrbufInitS(&disk->filesystem, device.mnt_fstype); + ffStrbufInit(&disk->name); + detectType(disks, disk, &device); + detectStats(disk); + } + + return NULL; +} diff --git a/src/detection/diskio/diskio_nosupport.c b/src/detection/diskio/diskio_nosupport.c new file mode 100644 index 000000000..2e165c0c5 --- /dev/null +++ b/src/detection/diskio/diskio_nosupport.c @@ -0,0 +1,6 @@ +#include "diskio.h" + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/diskio/diskio_sunos.c b/src/detection/diskio/diskio_sunos.c new file mode 100644 index 000000000..26a3350ff --- /dev/null +++ b/src/detection/diskio/diskio_sunos.c @@ -0,0 +1,39 @@ +#include "diskio.h" +#include "util/stringUtils.h" +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) +{ + assert(pkc); + if (*pkc) + kstat_close(*pkc); +} + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); + if (!kc) + return "kstat_open() failed"; + + for (kstat_t* ks = kc->kc_chain; ks; ks = ks->ks_next) + { + if (ks->ks_type != KSTAT_TYPE_IO || !ffStrEquals(ks->ks_class, "disk")) continue; + + if (options->namePrefix.length && strncmp(ks->ks_name, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + kstat_io_t kio; + if (kstat_read(kc, ks, &kio) < 0) + continue; + + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + ffStrbufInitS(&device->devPath, ks->ks_name); + device->bytesRead = kio.nread; + device->readCount = kio.reads; + device->bytesWritten = kio.nwritten; + device->writeCount = kio.writes; + ffStrbufInitS(&device->name, ks->ks_name); + } + + return NULL; +} diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 3a2ed89e0..eb8d09847 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -3,6 +3,7 @@ #include "util/edidHelper.h" #include "util/stringUtils.h" +#ifdef __linux__ #include static const char* drmParseSysfs(FFDisplayServerResult* result) @@ -85,6 +86,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) return NULL; } +#endif #ifdef FF_HAVE_DRM @@ -369,5 +371,7 @@ void ffdsConnectDrm(FFDisplayServerResult* result) } #endif + #ifdef __linux__ drmParseSysfs(result); + #endif } diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 10ea048d1..32a599e17 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -1,4 +1,5 @@ #include "displayserver_linux.h" +#include "common/io/io.h" #include "common/properties.h" #include "util/stringUtils.h" #include "util/mallocHelper.h" @@ -11,8 +12,8 @@ #include #include #include -#else - #include "common/io/io.h" +#elif defined(__sun) + #include #endif static const char* parseEnv(void) @@ -302,6 +303,42 @@ static const char* getFromProcesses(FFDisplayServerResult* result) if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) break; } +#elif defined(__sun) + FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); + if(procdir == NULL) + 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)) != NULL) + { + 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 != userId) + continue; + + if(result->dePrettyName.length == 0) + applyPrettyNameIfDE(result, proc.pr_fname); + + if(result->wmPrettyName.length == 0) + applyNameIfWM(result, proc.pr_fname); + + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) + break; + } + } #else FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if(procdir == NULL) diff --git a/src/detection/dns/dns.h b/src/detection/dns/dns.h new file mode 100644 index 000000000..ec25005c3 --- /dev/null +++ b/src/detection/dns/dns.h @@ -0,0 +1,5 @@ +#pragma once + +#include "fastfetch.h" + +const char* ffDetectDNS(FFDNSOptions* options, FFlist* results /* list of FFstrbuf */); diff --git a/src/detection/dns/dns_linux.c b/src/detection/dns/dns_linux.c new file mode 100644 index 000000000..84b2f9179 --- /dev/null +++ b/src/detection/dns/dns_linux.c @@ -0,0 +1,35 @@ +#include "detection/dns/dns.h" + +#include "common/io/io.h" +#include "util/mallocHelper.h" +#include "util/stringUtils.h" + +const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) +{ + FF_AUTO_CLOSE_FILE FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf", "r"); + if (!file) + return "fopen (" FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf) failed"; + + FF_AUTO_FREE char* line = NULL; + size_t len = 0; + + while (getline(&line, &len, file) != -1) + { + if (ffStrStartsWith(line, "nameserver")) + { + const char* nameserver = line + strlen("nameserver"); + while (*nameserver == ' ' || *nameserver == '\t') + nameserver++; + if (*nameserver == '\0') continue; + + if ((ffStrContainsC(nameserver, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) || + (ffStrContainsC(nameserver, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT))) + continue; + + FFstrbuf* item = (FFstrbuf*) ffListAdd(results); + ffStrbufInitS(item, nameserver); + ffStrbufTrimRightSpace(item); + } + } + return NULL; +} diff --git a/src/detection/dns/dns_windows.c b/src/detection/dns/dns_windows.c new file mode 100644 index 000000000..55cda9e4f --- /dev/null +++ b/src/detection/dns/dns_windows.c @@ -0,0 +1,67 @@ +#include "detection/dns/dns.h" +#include "common/netif/netif.h" +#include "util/mallocHelper.h" + +#include +#include + +const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) +{ + IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; + + // Multiple attempts in case interfaces change while + // we are in the middle of querying them. + DWORD adapter_addresses_buffer_size = 0; + for (int attempts = 0;; ++attempts) + { + if (adapter_addresses_buffer_size) + { + adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size); + assert(adapter_addresses); + } + + DWORD error = GetAdaptersAddresses( + options->showType & FF_DNS_TYPE_IPV4_BIT + ? options->showType & FF_DNS_TYPE_IPV6_BIT ? AF_UNSPEC : AF_INET + : AF_INET6, + GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_FRIENDLY_NAME, + NULL, + adapter_addresses, + &adapter_addresses_buffer_size); + + if (error == ERROR_SUCCESS) + break; + else if (ERROR_BUFFER_OVERFLOW == error && attempts < 4) + continue; + else + return "GetAdaptersAddresses() failed"; + } + + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + // Iterate through all of the adapters + for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) + { + if (adapter->IfIndex != defaultRouteIfIndex) continue; + if (adapter->OperStatus != IfOperStatusUp) continue; + + for (IP_ADAPTER_DNS_SERVER_ADDRESS_XP * ifa = adapter->FirstDnsServerAddress; ifa; ifa = ifa->Next) + { + FFstrbuf* item = (FFstrbuf*) ffListAdd(results); + if (ifa->Address.lpSockaddr->sa_family == AF_INET) + { + SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr; + ffStrbufInitA(item, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &ipv4->sin_addr, item->chars, item->allocated); + } + else if (ifa->Address.lpSockaddr->sa_family == AF_INET6) + { + SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr; + ffStrbufInitA(item, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &ipv6->sin6_addr, item->chars, item->allocated); + } + ffStrbufRecalculateLength(item); + } + break; + } + return NULL; +} diff --git a/src/detection/editor/editor.c b/src/detection/editor/editor.c index be6ee4a9c..c6a281c17 100644 --- a/src/detection/editor/editor.c +++ b/src/detection/editor/editor.c @@ -90,6 +90,7 @@ const char* ffDetectEditor(FFEditorResult* result) ffStrbufStartsWithS(&result->exe, "emacs-") || // emacs-29.3 ffStrbufEqualS(&result->exe, "hx") || ffStrbufEqualS(&result->exe, "code") || + ffStrbufEqualS(&result->exe, "pluma") || ffStrbufEqualS(&result->exe, "sublime_text") ) param = "--version"; else if ( diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 9558af0b5..281b43ae1 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -43,6 +43,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c new file mode 100644 index 000000000..c5522c8bb --- /dev/null +++ b/src/detection/gpu/gpu_sunos.c @@ -0,0 +1,83 @@ +#include "gpu.h" +#include "common/properties.h" +#include "common/io/io.h" +#include "common/processing.h" + +const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) +{ + // SunOS requires root permission to query PCI device list, except `/usr/bin/scanpci` + // Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci` + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) { + "scanpci", + "-v", + NULL, + }); + if (error) + return error; + + if (!ffStrbufStartsWithS(&buffer, "\npci domain 0x")) + return "Invalid scanpci result"; + + FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); + + // pci domain 0x354b bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e + // Device unknown + // CardVendor 0x0000 card 0x0000 (Card unknown) + // STATUS 0x0010 COMMAND 0x0007 + // CLASS 0x03 0x02 0x00 REVISION 0x00 + // BIST 0x00 HEADER 0x00 LATENCY 0x00 CACHE 0x00 + // MAX_LAT 0x00 MIN_GNT 0x00 INT_PIN 0x00 INT_LINE 0x00 + + for ( + const char* pclass = strstr(buffer.chars, "\n CLASS 0x03 "); + pclass; + pclass = strstr(pclass, "\n CLASS 0x03 ") + ) + { + // find the start of device entry + const char* pstart = memrchr(buffer.chars, '\n', (size_t) (pclass - buffer.chars)); + while (pstart[1] != 'p') + pstart = memrchr(buffer.chars, '\n', (size_t) (pstart - buffer.chars - 1)); + ++pstart; + + uint32_t pciDomain, pciBus, pciDev, pciFunc, vendorId, deviceId; + if (sscanf(pstart, "pci domain %x bus %x cardnum %x function %x: vendor %x device %x", + &pciDomain, &pciBus, &pciDev, &pciFunc, &vendorId, &deviceId) != 6) + return "PCI info not found, invalid scanpci result"; + + pclass += strlen("\n CLASS 0x03 "); + uint32_t subclass = (uint32_t) strtoul(pclass, NULL, 16); + pclass += strlen("0x02 0x00 REVISION "); + uint32_t revision = (uint32_t) strtoul(pclass, NULL, 16); + + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); + ffStrbufInit(&gpu->name); + ffStrbufInit(&gpu->driver); + ffStrbufInit(&gpu->platformApi); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (pciDev << 2) | pciFunc; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; + + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) + { + char query[32]; + snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); + ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); + } + + if (gpu->name.length == 0) + { + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); + ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + } + } + + return NULL; +} diff --git a/src/detection/host/host_nosupport.c b/src/detection/host/host_nosupport.c new file mode 100644 index 000000000..6f3934823 --- /dev/null +++ b/src/detection/host/host_nosupport.c @@ -0,0 +1,6 @@ +#include "host.h" + +const char* ffDetectHost(FFHostResult* host) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/libc/libc_nosupport.c b/src/detection/libc/libc_nosupport.c new file mode 100644 index 000000000..be1316cce --- /dev/null +++ b/src/detection/libc/libc_nosupport.c @@ -0,0 +1,8 @@ +#include "libc.h" + +const char* ffDetectLibc(FFLibcResult* result) +{ + result->name = "Unknown"; + result->version = NULL; + return NULL; +} diff --git a/src/detection/loadavg/loadavg_sunos.c b/src/detection/loadavg/loadavg_sunos.c new file mode 100644 index 000000000..6ae401032 --- /dev/null +++ b/src/detection/loadavg/loadavg_sunos.c @@ -0,0 +1,8 @@ +#include "detection/loadavg/loadavg.h" + +#include + +const char* ffDetectLoadavg(double result[3]) +{ + return getloadavg(result, 3) == 3 ? NULL : "getloadavg() failed"; +} diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index fe50575ad..4b4162604 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -8,6 +8,7 @@ typedef struct FFLocalIpResult FFstrbuf ipv4; FFstrbuf ipv6; FFstrbuf mac; + int32_t mtu; bool defaultRoute; } FFLocalIpResult; diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 9c23b987f..924f830fd 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -10,12 +10,16 @@ #include #include #include +#include #if defined(__FreeBSD__) || defined(__APPLE__) #include #else #include #endif +#ifdef __sun +#include +#endif static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, bool firstOnly) { @@ -35,6 +39,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); ip->defaultRoute = defaultRoute; + ip->mtu = -1; } switch (type) @@ -160,5 +165,26 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (ifAddrStruct) freeifaddrs(ifAddrStruct); + FF_AUTO_CLOSE_FD int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd > 0) + { + FF_LIST_FOR_EACH(FFLocalIpResult, iface, *results) + { + struct ifreq ifr; + strncpy(ifr.ifr_name, iface->name.chars, IFNAMSIZ - 1); + if (ioctl(sockfd, SIOCGIFMTU, &ifr) == 0) + iface->mtu = (int32_t) ifr.ifr_mtu; + + #ifdef __sun + if ((options->showType & FF_LOCALIP_TYPE_MAC_BIT) && ioctl(sockfd, SIOCGIFHWADDR, &ifr) == 0) + { + const uint8_t* ptr = (uint8_t*) ifr.ifr_addr.sa_data; // NOT ifr_enaddr + ffStrbufSetF(&iface->mac, "%02x:%02x:%02x:%02x:%02x:%02x", + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + } + #endif + } + } + return NULL; } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 0650ae54a..8ac766660 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -18,10 +18,11 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); ip->defaultRoute = defaultRoute; + ip->mtu = -1; } else { - ip = ffListGet(list, list->length - 1); + ip = FF_LIST_GET(FFLocalIpResult, *list, list->length - 1); } switch (type) @@ -147,6 +148,9 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (typesToAdd == 0) break; } } + + if (!newIp) + FF_LIST_GET(FFLocalIpResult, *results, results->length - 1)->mtu = (int32_t) adapter->Mtu; } return NULL; diff --git a/src/detection/media/media.c b/src/detection/media/media.c index c24d8a1c4..585ccc48e 100644 --- a/src/detection/media/media.c +++ b/src/detection/media/media.c @@ -20,6 +20,10 @@ const FFMediaResult* ffDetectMedia(void) if(result.song.length == 0 && result.error.length == 0) ffStrbufAppendS(&result.error, "No media found"); + ffStrbufTrimRightSpace(&result.song); + ffStrbufTrimRightSpace(&result.artist); + ffStrbufTrimRightSpace(&result.album); + ffStrbufTrimRightSpace(&result.player); } return &result; diff --git a/src/detection/media/media_apple.m b/src/detection/media/media_apple.m index 0edd70264..e17ab48e2 100644 --- a/src/detection/media/media_apple.m +++ b/src/detection/media/media_apple.m @@ -27,7 +27,7 @@ static const char* getMedia(FFMediaResult* result) dispatch_group_enter(group); MRMediaRemoteGetNowPlayingApplicationIsPlaying(queue, ^(BOOL playing) { - ffStrbufAppendS(&result->status, playing ? "Playing" : "Paused"); + ffStrbufSetStatic(&result->status, playing ? "Playing" : "Paused"); dispatch_group_leave(group); }); diff --git a/src/detection/media/media_windows.c b/src/detection/media/media_windows.c new file mode 100644 index 000000000..ed0ed97ce --- /dev/null +++ b/src/detection/media/media_windows.c @@ -0,0 +1,38 @@ +#include "common/library.h" +#include "util/windows/unicode.h" +#include "media.h" +#include "media_windows.dll.h" + +static const char* getMedia(FFMediaResult* media) +{ + FF_LIBRARY_LOAD(libffwinrt, NULL, "dlopen libffwinrt" FF_LIBRARY_EXTENSION " failed", "libffwinrt" FF_LIBRARY_EXTENSION, 0) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libffwinrt, ffWinrtDetectMedia) + libffwinrt = NULL; // Don't close libffwinrt or it may crash + + FFWinrtMediaResult result = {}; + + const char* error = ffffWinrtDetectMedia(&result); + if (error) + { + ffStrbufSetStatic(&media->error, error); + return NULL; + } + + ffStrbufSetWS(&media->playerId, result.playerId); + ffStrbufSet(&media->player, &media->playerId); + if (ffStrbufEndsWithIgnCaseS(&media->player, ".exe")) + ffStrbufSubstrBefore(&media->player, media->player.length - 4); + else + ffStrbufSubstrAfterFirstC(&media->player, '!'); // UWP ID + ffStrbufSetWS(&media->song, result.song); + ffStrbufSetWS(&media->artist, result.artist); + ffStrbufSetWS(&media->album, result.album); + ffStrbufSetStatic(&media->status, result.status); + return NULL; +} + +void ffDetectMediaImpl(FFMediaResult* media) +{ + const char* error = getMedia(media); + ffStrbufAppendS(&media->error, error); +} diff --git a/src/detection/media/media_windows.dll.cpp b/src/detection/media/media_windows.dll.cpp new file mode 100644 index 000000000..71c3226c4 --- /dev/null +++ b/src/detection/media/media_windows.dll.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +extern "C" +{ +#include "media_windows.dll.h" + +const char* ffWinrtDetectMedia(FFWinrtMediaResult* result) +{ + // C++/WinRT requires Windows 8.1+ and C++ runtime (std::string, exceptions and other stuff) + // Make it a separate dll in order not to break Windows 7 support + using namespace winrt::Windows::Media::Control; + + try + { + auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get(); + if (!manager) + return "winrt: GlobalSystemMediaTransportControlsSessionManager::RequestAsync() failed"; + + auto session = manager.GetCurrentSession(); + if (!session) + return "winrt: GetCurrentSession() failed"; + + auto mediaProps = session + .TryGetMediaPropertiesAsync() + .get(); + if (!mediaProps) + return "winrt: TryGetMediaPropertiesAsync() failed"; + + if (auto playbackInfo = session.GetPlaybackInfo()) + { + switch (playbackInfo.PlaybackStatus()) + { + #define FF_MEDIA_SET_STATUS(status_code) \ + case GlobalSystemMediaTransportControlsSessionPlaybackStatus::status_code: result->status = #status_code; break + FF_MEDIA_SET_STATUS(Closed); + FF_MEDIA_SET_STATUS(Opened); + FF_MEDIA_SET_STATUS(Changing); + FF_MEDIA_SET_STATUS(Stopped); + FF_MEDIA_SET_STATUS(Playing); + FF_MEDIA_SET_STATUS(Paused); + #undef FF_MEDIA_SET_STATUS + } + } + + ::wcsncpy(result->playerId, session.SourceAppUserModelId().data(), FF_MEDIA_WIN_RESULT_BUFLEN); + ::wcsncpy(result->song, mediaProps.Title().data(), FF_MEDIA_WIN_RESULT_BUFLEN); + ::wcsncpy(result->artist, mediaProps.Artist().data(), FF_MEDIA_WIN_RESULT_BUFLEN); + ::wcsncpy(result->album, mediaProps.AlbumTitle().data(), FF_MEDIA_WIN_RESULT_BUFLEN); + + return NULL; + } + catch (...) + { + return "A C++ exception is thrown"; + } +} + +} // extern "C" diff --git a/src/detection/media/media_windows.dll.h b/src/detection/media/media_windows.dll.h new file mode 100644 index 000000000..045976c2e --- /dev/null +++ b/src/detection/media/media_windows.dll.h @@ -0,0 +1,15 @@ +#pragma once + +#define FF_MEDIA_WIN_RESULT_BUFLEN 256 + +typedef struct FFWinrtMediaResult +{ + wchar_t playerId[FF_MEDIA_WIN_RESULT_BUFLEN]; + wchar_t song[FF_MEDIA_WIN_RESULT_BUFLEN]; + wchar_t artist[FF_MEDIA_WIN_RESULT_BUFLEN]; + wchar_t album[FF_MEDIA_WIN_RESULT_BUFLEN]; + const char* status; +} FFWinrtMediaResult; + +__attribute__((__dllexport__)) +const char* ffWinrtDetectMedia(FFWinrtMediaResult* result); diff --git a/src/detection/memory/memory_nosupport.c b/src/detection/memory/memory_nosupport.c new file mode 100644 index 000000000..76cd7f828 --- /dev/null +++ b/src/detection/memory/memory_nosupport.c @@ -0,0 +1,6 @@ +#include "memory.h" + +const char* ffDetectMemory(FFMemoryResult* ram) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/memory/memory_sunos.c b/src/detection/memory/memory_sunos.c new file mode 100644 index 000000000..9e9f0f11e --- /dev/null +++ b/src/detection/memory/memory_sunos.c @@ -0,0 +1,34 @@ +#include "memory.h" +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) +{ + assert(pkc); + if (*pkc) + kstat_close(*pkc); +} + +const char* ffDetectMemory(FFMemoryResult* ram) +{ + __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); + if (!kc) + return "kstat_open() failed"; + + kstat_t* ks = kstat_lookup(kc, "unix", -1, "system_pages"); + if (!ks) + return "kstat_lookup() failed"; + + if (kstat_read(kc, ks, NULL) < 0) + return "kstat_read() failed"; + + { + kstat_named_t* kn = kstat_data_lookup(ks, "pagestotal"); + ram->bytesTotal = kn->value.ui64 * instance.state.platform.pageSize; + } + { + kstat_named_t* kn = kstat_data_lookup(ks, "pagesfree"); + ram->bytesUsed = ram->bytesTotal - kn->value.ui64 * instance.state.platform.pageSize; + } + + return NULL; +} diff --git a/src/detection/netio/netio_nosupport.c b/src/detection/netio/netio_nosupport.c new file mode 100644 index 000000000..254f22860 --- /dev/null +++ b/src/detection/netio/netio_nosupport.c @@ -0,0 +1,6 @@ +#include "netio.h" + +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/netio/netio_sunos.c b/src/detection/netio/netio_sunos.c new file mode 100644 index 000000000..e87222e83 --- /dev/null +++ b/src/detection/netio/netio_sunos.c @@ -0,0 +1,62 @@ +#include "netio.h" +#include "common/netif/netif.h" +#include "util/stringUtils.h" +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) +{ + assert(pkc); + if (*pkc) + kstat_close(*pkc); +} + +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) +{ + __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); + if (!kc) + return "kstat_open() failed"; + + const char* defaultRoute = ffNetifGetDefaultRouteIfName(); + + for (kstat_t* ks = kc->kc_chain; ks; ks = ks->ks_next) + { + if (!ffStrEquals(ks->ks_class, "net") || !ffStrEquals(ks->ks_module, "link")) continue; + + if (options->namePrefix.length && strncmp(ks->ks_name, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + bool isDefaultRoute = ffStrEquals(ks->ks_name, defaultRoute); + if (options->defaultRouteOnly && !isDefaultRoute) + continue; + + if (kstat_read(kc, ks, NULL) < 0) + continue; + + FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); + + kstat_named_t* wbytes = (kstat_named_t*) kstat_data_lookup(ks, "obytes64"); + kstat_named_t* rbytes = (kstat_named_t*) kstat_data_lookup(ks, "rbytes64"); + kstat_named_t* wpkts = (kstat_named_t*) kstat_data_lookup(ks, "opackets64"); + kstat_named_t* rpkts = (kstat_named_t*) kstat_data_lookup(ks, "ipackets64"); + kstat_named_t* werrs = (kstat_named_t*) kstat_data_lookup(ks, "oerrors"); + kstat_named_t* rerrs = (kstat_named_t*) kstat_data_lookup(ks, "ierrors"); + + *counters = (FFNetIOResult) { + .name = ffStrbufCreateS(ks->ks_name), + .txBytes = wbytes->value.ui64, + .rxBytes = rbytes->value.ui64, + .txPackets = wpkts->value.ui64, + .rxPackets = rpkts->value.ui64, + .txErrors = werrs->value.ui64, + .rxErrors = rerrs->value.ui64, + .txDrops = 0, // unsupported + .rxDrops = 0, + .defaultRoute = isDefaultRoute, + }; + + if (options->defaultRouteOnly) + break; + } + + return NULL; +} diff --git a/src/detection/opengl/opengl.h b/src/detection/opengl/opengl.h index 3c878f97c..6614ea2f2 100644 --- a/src/detection/opengl/opengl.h +++ b/src/detection/opengl/opengl.h @@ -8,6 +8,7 @@ typedef struct FFOpenGLResult FFstrbuf renderer; FFstrbuf vendor; FFstrbuf slv; + const char* library; } FFOpenGLResult; const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result); diff --git a/src/detection/opengl/opengl_apple.c b/src/detection/opengl/opengl_apple.c index e7f3ad0e9..3a8e7ac5e 100644 --- a/src/detection/opengl/opengl_apple.c +++ b/src/detection/opengl/opengl_apple.c @@ -12,6 +12,7 @@ static const char* glHandleResult(FFOpenGLResult* result) ffStrbufAppendS(&result->renderer, (const char*) glGetString(GL_RENDERER)); ffStrbufAppendS(&result->vendor, (const char*) glGetString(GL_VENDOR)); ffStrbufAppendS(&result->slv, (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); + result->library = "CGL"; return NULL; } diff --git a/src/detection/opengl/opengl_linux.c b/src/detection/opengl/opengl_linux.c index 8ce29e7a2..bc957add7 100644 --- a/src/detection/opengl/opengl_linux.c +++ b/src/detection/opengl/opengl_linux.c @@ -18,12 +18,13 @@ typedef struct GLData FF_LIBRARY_SYMBOL(glGetString) } GLData; -static const char* glHandleResult(FFOpenGLResult* result, const GLData* data) +static const char* glHandleResult(FFOpenGLResult* result, const GLData* data, const char* library) { ffStrbufAppendS(&result->version, (const char*) data->ffglGetString(GL_VERSION)); ffStrbufAppendS(&result->renderer, (const char*) data->ffglGetString(GL_RENDERER)); ffStrbufAppendS(&result->vendor, (const char*) data->ffglGetString(GL_VENDOR)); ffStrbufAppendS(&result->slv, (const char*) data->ffglGetString(GL_SHADING_LANGUAGE_VERSION)); + result->library = library; return NULL; } @@ -61,7 +62,7 @@ static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data) if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE) return "eglMakeCurrent returned EGL_FALSE"; - return glHandleResult(result, &data->glData); + return glHandleResult(result, &data->glData, "EGL"); } static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data) @@ -173,7 +174,7 @@ static const char* glxHandleContext(FFOpenGLResult* result, GLXData* data) if(data->ffglXMakeCurrent(data->display, data->glxPixmap, data->context) != True) return "glXMakeCurrent returned False"; - return glHandleResult(result, &data->glData); + return glHandleResult(result, &data->glData, "GLX"); } static const char* glxHandleGLXPixmap(FFOpenGLResult* result, GLXData* data) @@ -259,7 +260,11 @@ static const char* glxPrint(FFOpenGLResult* result) #endif //FF_HAVE_GLX #ifdef FF_HAVE_OSMESA -#include +#if __has_include() + #include +#else + #include // for sunos +#endif typedef struct OSMesaData { @@ -280,7 +285,7 @@ static const char* osMesaHandleContext(FFOpenGLResult* result, OSMesaData* data) if(data->ffOSMesaMakeCurrent(data->context, buffer, GL_UNSIGNED_BYTE, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT) != GL_TRUE) return "OSMesaMakeCurrent returned GL_FALSE"; - return glHandleResult(result, &data->glData); + return glHandleResult(result, &data->glData, "OSMesa"); } static const char* osMesaHandleData(FFOpenGLResult* result, OSMesaData* data) diff --git a/src/detection/opengl/opengl_windows.c b/src/detection/opengl/opengl_windows.c index 91b79388f..e0b29fc8a 100644 --- a/src/detection/opengl/opengl_windows.c +++ b/src/detection/opengl/opengl_windows.c @@ -25,6 +25,7 @@ static const char* glHandleResult(WGLData* wglData) ffStrbufAppendS(&wglData->result->renderer, (const char*) wglData->ffglGetString(GL_RENDERER)); ffStrbufAppendS(&wglData->result->vendor, (const char*) wglData->ffglGetString(GL_VENDOR)); ffStrbufAppendS(&wglData->result->slv, (const char*) wglData->ffglGetString(GL_SHADING_LANGUAGE_VERSION)); + wglData->result->library = "WGL"; return NULL; } diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index d08aed435..f82d7a501 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -37,6 +37,7 @@ static bool detectOSCodeName(FFOSResult* os) switch (num) { + case 15: ffStrbufSetStatic(&os->codename, "Sequoia"); return true; case 14: ffStrbufSetStatic(&os->codename, "Sonoma"); return true; case 13: ffStrbufSetStatic(&os->codename, "Ventura"); return true; case 12: ffStrbufSetStatic(&os->codename, "Monterey"); return true; diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 1d3afe947..c37de8647 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -180,6 +180,28 @@ static bool detectDebianDerived(FFOSResult* result) ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars); return true; } + else + { + // Hack for MX Linux. See #847 + FF_STRBUF_AUTO_DESTROY lsbRelease = ffStrbufCreate(); + if (ffAppendFileBuffer("/etc/lsb-release", &lsbRelease) && ffStrbufContainS(&lsbRelease, "DISTRIB_ID=MX")) + { + ffStrbufSetS(&result->id, "mx"); + ffStrbufSetS(&result->idLike, "debian"); + ffStrbufSetS(&result->name, "MX"); + + ffStrbufClear(&result->version); + ffParsePropLines(lsbRelease.chars, "DISTRIB_RELEASE=", &result->version); + ffStrbufSet(&result->versionID, &result->version); + + ffStrbufClear(&result->codename); + ffParsePropLines(lsbRelease.chars, "DISTRIB_CODENAME=", &result->codename); + + ffStrbufClear(&result->prettyName); + ffParsePropLines(lsbRelease.chars, "DISTRIB_DESCRIPTION=", &result->prettyName); + return true; + } + } return false; } @@ -208,22 +230,9 @@ static void detectOS(FFOSResult* os) // Refer: https://gist.github.com/natefoo/814c5bf936922dad97ff - // Hack for MX Linux. See #847 - if(parseLsbRelease(FASTFETCH_TARGET_DIR_ETC "/lsb-release", os)) - { - if (ffStrbufEqualS(&os->id, "MX")) - { - ffStrbufSetStatic(&os->name, "MX"); - ffStrbufSetStatic(&os->idLike, "debian"); - return; - } - - // For archlinux - if (ffStrbufEqualS(&os->version, "rolling")) - ffStrbufClear(&os->version); - } - - if(parseOsRelease(FASTFETCH_TARGET_DIR_ETC "/os-release", os) && allRelevantValuesSet(os)) + if((parseOsRelease(FASTFETCH_TARGET_DIR_ETC "/os-release", os) || + parseLsbRelease(FASTFETCH_TARGET_DIR_ETC "/lsb-release", os)) && + allRelevantValuesSet(os)) return; parseOsRelease(FASTFETCH_TARGET_DIR_USR "/lib/os-release", os); diff --git a/src/detection/os/os_sunos.c b/src/detection/os/os_sunos.c new file mode 100644 index 000000000..46bf05b65 --- /dev/null +++ b/src/detection/os/os_sunos.c @@ -0,0 +1,17 @@ +#include "os.h" +#include "common/io/io.h" + +void ffDetectOSImpl(FFOSResult* os) +{ + if (!ffReadFileBuffer("/etc/release", &os->prettyName)) + return; + + ffStrbufSubstrBeforeFirstC(&os->prettyName, '\n'); + ffStrbufSubstrBeforeLastC(&os->prettyName, '('); + ffStrbufTrim(&os->prettyName, ' '); + + // OpenIndiana Hipster 2024.04 + uint32_t idx = ffStrbufFirstIndexC(&os->prettyName, ' '); + ffStrbufSetNS(&os->id, idx, os->prettyName.chars); + ffStrbufSetStatic(&os->idLike, "sunos"); +} diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index 8734f74c1..117be1ed0 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -90,4 +90,5 @@ void ffDetectOSImpl(FFOSResult* os) } ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars); + ffStrbufSetStatic(&os->idLike, "Windows"); } diff --git a/src/detection/packages/packages_nosupport.c b/src/detection/packages/packages_nosupport.c new file mode 100644 index 000000000..87f65a8eb --- /dev/null +++ b/src/detection/packages/packages_nosupport.c @@ -0,0 +1,5 @@ +#include "packages.h" + +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) +{ +} diff --git a/src/detection/packages/packages_sunos.c b/src/detection/packages/packages_sunos.c new file mode 100644 index 000000000..a295f9ae8 --- /dev/null +++ b/src/detection/packages/packages_sunos.c @@ -0,0 +1,15 @@ +#include "packages.h" + +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) +{ + if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) + { + yyjson_doc* doc = yyjson_read_file(FASTFETCH_TARGET_DIR_ROOT "/var/pkg/state/installed/catalog.attrs", YYJSON_READ_NOFLAG, NULL, NULL); + if (doc) + { + yyjson_val* packageCount = yyjson_obj_get(yyjson_doc_get_root(doc), "package-count"); + if (packageCount) + result->pkg = (uint32_t) yyjson_get_uint(packageCount); + } + } +} diff --git a/src/detection/physicaldisk/physicaldisk_nosupport.c b/src/detection/physicaldisk/physicaldisk_nosupport.c new file mode 100644 index 000000000..1ed823d9c --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk_nosupport.c @@ -0,0 +1,6 @@ +#include "physicaldisk.h" + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 25e3a84af..58fea6416 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -14,7 +14,11 @@ const char* ffDetectProcesses(uint32_t* result) struct dirent* entry; while ((entry = readdir(dir)) != NULL) { - if (entry->d_type == DT_DIR && ffCharIsDigit(entry->d_name[0])) + if ( + #ifdef _DIRENT_HAVE_D_TYPE + entry->d_type == DT_DIR && + #endif + ffCharIsDigit(entry->d_name[0])) ++num; } diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index f42ea3a79..906792cc7 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -13,7 +13,10 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo FFSoundDevice* device = ffListAdd(userdata); ffStrbufInitS(&device->identifier, i->name); + ffStrbufTrimRightSpace(&device->identifier); ffStrbufInitS(&device->name, i->description); + ffStrbufTrimRightSpace(&device->name); + ffStrbufTrimLeft(&device->name, ' '); device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM); device->active = i->active_port && i->active_port->available != PA_PORT_AVAILABLE_NO; device->main = false; diff --git a/src/detection/swap/swap_nosupport.c b/src/detection/swap/swap_nosupport.c new file mode 100644 index 000000000..98a11195f --- /dev/null +++ b/src/detection/swap/swap_nosupport.c @@ -0,0 +1,6 @@ +#include "swap.h" + +const char* ffDetectSwap(FFSwapResult* swap) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/swap/swap_sunos.c b/src/detection/swap/swap_sunos.c new file mode 100644 index 000000000..f564e9929 --- /dev/null +++ b/src/detection/swap/swap_sunos.c @@ -0,0 +1,33 @@ +#include "swap.h" +#include +#include +#include + +enum { FFMaxNSwap = 8 }; + +const char* ffDetectSwap(FFSwapResult* swap) +{ + char strings[FFMaxNSwap][PATH_MAX]; + uint8_t buffer[sizeof(swaptbl_t) + sizeof(swapent_t) * (FFMaxNSwap - 1)] = {}; + swaptbl_t* table = (swaptbl_t*) buffer; + table->swt_n = FFMaxNSwap; + for (int i = 0; i < FFMaxNSwap; ++i) + table->swt_ent[i].ste_path = strings[i]; + + int size = swapctl(SC_LIST, table); + if (size < 0) + return "swapctl() failed"; + + swap->bytesTotal = swap->bytesUsed = 0; + + for (int i = 0; i < size; ++i) + { + swap->bytesTotal += (uint64_t) table->swt_ent[i].ste_pages; + swap->bytesUsed += (uint64_t) table->swt_ent[i].ste_free; + } + swap->bytesUsed = swap->bytesTotal - swap->bytesUsed; + swap->bytesTotal *= instance.state.platform.pageSize; + swap->bytesUsed *= instance.state.platform.pageSize; + + return NULL; +} diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index a4fd97783..7766790c2 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -553,7 +553,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal")) return getTerminalVersionGnome(version); diff --git a/src/detection/terminalsize/terminalsize_linux.c b/src/detection/terminalsize/terminalsize_linux.c index b15939661..b5016045d 100644 --- a/src/detection/terminalsize/terminalsize_linux.c +++ b/src/detection/terminalsize/terminalsize_linux.c @@ -4,6 +4,10 @@ #include #include +#ifdef __sun + #include +#endif + bool ffDetectTerminalSize(FFTerminalSizeResult* result) { struct winsize winsize = {}; diff --git a/src/detection/uptime/uptime_sunos.c b/src/detection/uptime/uptime_sunos.c new file mode 100644 index 000000000..fe45b61c8 --- /dev/null +++ b/src/detection/uptime/uptime_sunos.c @@ -0,0 +1,21 @@ +#include "uptime.h" +#include "common/time.h" +#include + +const char* ffDetectUptime(FFUptimeResult* result) +{ + struct utmpx* ut; + + setutxent(); + while (NULL != (ut = getutxent())) + { + if (ut->ut_type == BOOT_TIME) + { + result->bootTime = (uint64_t) ut->ut_tv.tv_sec * 1000 + (uint64_t) ut->ut_tv.tv_usec / 1000000; + result->uptime = ffTimeGetNow() - result->bootTime; + break; + } + } + endutxent(); + return NULL; +} diff --git a/src/detection/users/users.h b/src/detection/users/users.h index 67be7f1fd..e29a1858d 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -11,4 +11,4 @@ typedef struct FFUserResult uint64_t loginTime; // ms } FFUserResult; -const char* ffDetectUsers(FFlist* users); +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users); diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index 695a6a724..86e69dbe4 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -15,15 +15,18 @@ #include #endif -const char* ffDetectUsers(FFlist* users) +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) { struct utmpx* n = NULL; setutxent(); next: - while((n = getutxent())) + while ((n = getutxent())) { - if(n->ut_type != USER_PROCESS) + if (n->ut_type != USER_PROCESS) + continue; + + if (options->myselfOnly && !ffStrbufEqualS(&instance.state.platform.userName, n->ut_user)) continue; FF_LIST_FOR_EACH(FFUserResult, user, *users) diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 115f7935d..b7bdf2721 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -10,23 +10,28 @@ static inline uint64_t to_ms(uint64_t ret) return ret / 10000ull; } -const char* ffDetectUsers(FFlist* users) +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) { WTS_SESSION_INFO_1W* sessionInfo; DWORD sessionCount; DWORD level = 1; - if(!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount)) + if (!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount)) return "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed"; for (DWORD i = 0; i < sessionCount; i++) { WTS_SESSION_INFO_1W* session = &sessionInfo[i]; - if(session->State != WTSActive) + if (session->State != WTSActive) + continue; + + FF_STRBUF_AUTO_DESTROY userName = ffStrbufCreateWS(session->pUserName); + + if (options->myselfOnly && !ffStrbufEqual(&instance.state.platform.userName, &userName)) continue; FFUserResult* user = (FFUserResult*) ffListAdd(users); - ffStrbufInitWS(&user->name, session->pUserName); + ffStrbufInitMove(&user->name, &userName); ffStrbufInitWS(&user->hostName, session->pHostName); ffStrbufInitWS(&user->sessionName, session->pSessionName); ffStrbufInit(&user->clientIp); diff --git a/src/detection/wifi/wifi_nosupport.c b/src/detection/wifi/wifi_nosupport.c new file mode 100644 index 000000000..ae1d62e09 --- /dev/null +++ b/src/detection/wifi/wifi_nosupport.c @@ -0,0 +1,6 @@ +#include "wifi.h" + +const char* ffDetectWifi(FFlist* result) +{ + return "Not support on this platform"; +} diff --git a/src/logo/ascii/arch3.txt b/src/logo/ascii/arch3.txt new file mode 100644 index 000000000..23973f1ab --- /dev/null +++ b/src/logo/ascii/arch3.txt @@ -0,0 +1,19 @@ + . + / \ + / \ + / \ + / \ + />, \ + / `*. \ + / ` \ + / \ + / \ +$2 / ,.-+-.. \ + / ,/' `\. \ + / .|' `|. _ \ + / :|. ,|; `+.\ + / .\: ;/, "<\ + / __,--+" "+--.__ \ + / _,+'" "'+._ \ + /,-' `-.\ +' ' diff --git a/src/logo/ascii/arch_small.txt b/src/logo/ascii/arch_small.txt index 3688e2471..22ae23a10 100644 --- a/src/logo/ascii/arch_small.txt +++ b/src/logo/ascii/arch_small.txt @@ -2,6 +2,6 @@ / \ / \ / \ - / ,, \ +$2 / ,, \ / | | \ -/_-'' ''-_\ \ No newline at end of file +/_-'' ''-_\ diff --git a/src/logo/ascii/mauna.txt b/src/logo/ascii/mauna.txt new file mode 100644 index 000000000..69af130c5 --- /dev/null +++ b/src/logo/ascii/mauna.txt @@ -0,0 +1,15 @@ + .. :-=++++=-: + .-+*+ -********* **= + =***= +******+ =---=+*. + +**** +****+ :-=++*++=-- + =****= **** :+***********+: + +****+ *** $2.-- $1+******- + =*****: *- $2:+=: $1=*****: +$2. $1+*****: : $2-+++ $1:****= +$2-+ $1:*****+ $2- ++++ $1:***- +$2-++=: $1=+****: $2:++ +++++ $1**+ +$2 +++++= $1-====-$2++++: +++++ $1*+ +$2 .=++++++++++++++: $2+++++= $1. +$2 .=+++++++++= :=+++++= + .:::--- -+++++++- + :-==++==-. diff --git a/src/logo/ascii/redos.txt b/src/logo/ascii/redos.txt new file mode 100644 index 000000000..68bfc1e0d --- /dev/null +++ b/src/logo/ascii/redos.txt @@ -0,0 +1,18 @@ +╭───────────────╮ ╭───────────────╮ +│###############│ │###############│ +│#+++++++++++++#│ │#+++++++++++++#│ +│#+++++++++++++#│ │#+++++++++++++#│ +│#+++++++++++++#│ │#+++++++++++++#│ +│#+++++++++++++#│ │#+++++++++++++#│ +│#+++++++++++++#│ │#+++++++++++++#│ +│###############│ │###############│ +╰───────────────╯ ╰───────────────╯ +╭───────────────╮ +│###############│ +│#+++++++++++++#│ +│#+++++++++++++#│ +│#+++++++++++++#│ +│#+++++++++++++#│ +│#+++++++++++++#│ +│###############│ +╰───────────────╯ diff --git a/src/logo/ascii/redos_small.txt b/src/logo/ascii/redos_small.txt new file mode 100644 index 000000000..96a9d8b9a --- /dev/null +++ b/src/logo/ascii/redos_small.txt @@ -0,0 +1,8 @@ +╭─────╮ ╭─────╮ +│ │ │ │ +│ │ │ │ +╰─────╯ ╰─────╯ +╭─────╮ +│ │ +│ │ +╰─────╯ diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 0c92a20c8..69d6d99e9 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -328,8 +328,6 @@ static const FFlogo A[] = { FF_COLOR_FG_CYAN, FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_CYAN, - .colorTitle = FF_COLOR_FG_CYAN, }, // Arch2 { @@ -340,8 +338,16 @@ static const FFlogo A[] = { FF_COLOR_FG_CYAN, FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_CYAN, - .colorTitle = FF_COLOR_FG_CYAN, + }, + // Arch3 + { + .names = {"arch3", "archlinux3", "arch-linux3"}, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_ARCH3, + .colors = { + FF_COLOR_FG_CYAN, + FF_COLOR_FG_CYAN, + }, }, // ArchSmall { @@ -350,9 +356,8 @@ static const FFlogo A[] = { .lines = FASTFETCH_DATATEXT_LOGO_ARCH_SMALL, .colors = { FF_COLOR_FG_CYAN, + FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_CYAN, - .colorTitle = FF_COLOR_FG_CYAN, }, // Archlabs { @@ -2576,7 +2581,7 @@ static const FFlogo M[] = { }, // Manjaro { - .names = {"manjaro", "manjaro-linux", "manjarolinux"}, + .names = {"manjaro", "manjaro-linux", "manjarolinux", "manjaro-arm"}, .lines = FASTFETCH_DATATEXT_LOGO_MANJARO, .colors = { FF_COLOR_FG_GREEN, @@ -2626,6 +2631,15 @@ static const FFlogo M[] = { .colorKeys = FF_COLOR_FG_CYAN, .colorTitle = FF_COLOR_FG_WHITE, }, + // Mauna + { + .names = {"Mauna"}, + .lines = FASTFETCH_DATATEXT_LOGO_MAUNA, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_CYAN, + }, + }, // Meowix { .names = {"Meowix"}, @@ -3608,6 +3622,31 @@ static const FFlogo R[] = { FF_COLOR_FG_WHITE, }, }, + // RedOS + { + .names = {"RedOS", "RED OS", "red-os", "redos"}, + .lines = FASTFETCH_DATATEXT_LOGO_REDOS, + .colors = + { + FF_COLOR_FG_RED, + FF_COLOR_FG_WHITE, + }, + .colorTitle = FF_COLOR_FG_RED, + .colorKeys = FF_COLOR_FG_RED, + }, + // RedOS small + { + .names = {"RedOS_small", "RED OS_small", "red-os_small", "redos_small"}, + .type = FF_LOGO_LINE_TYPE_SMALL_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_REDOS_SMALL, + .colors = + { + FF_COLOR_FG_RED, + FF_COLOR_FG_WHITE, + }, + .colorTitle = FF_COLOR_FG_RED, + .colorKeys = FF_COLOR_FG_RED, + }, // RedstarOS { .names = {"redstar", "redstar-os", "redstaros", "redstaros-linux", "redstar-os-linux"}, @@ -4102,7 +4141,7 @@ static const FFlogo T[] = { }, // TuxedoOS { - .names = {"Tuxedo OS"}, + .names = {"Tuxedo OS", "tuxedo"}, .lines = FASTFETCH_DATATEXT_LOGO_TUXEDO_OS, .colors = { FF_COLOR_FG_WHITE, diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 5f2da3db4..31b931e6a 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -26,7 +26,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption ffStrbufClear(&buffer); - uint64_t sum = 0; + uint32_t sum = 0; FF_LIST_FOR_EACH(FFCPUCache, src, result->caches[i]) { char typeStr = '?'; @@ -44,7 +44,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption ffParseSize(src->size, &buffer); ffStrbufAppendF(&buffer, " (%c)", typeStr); - sum += (uint64_t) src->size * src->num; + sum += src->size * src->num; } if(options->moduleArgs.outputFormat.length == 0) @@ -74,7 +74,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio ffStrbufAppendS(&buffer, ", "); uint32_t value = 0; FF_LIST_FOR_EACH(FFCPUCache, src, result->caches[i]) - value += (uint64_t) src->size * src->num; + value += src->size * src->num; ffParseSize(value, &buffer); ffStrbufAppendF(&buffer, " (L%u)", i + 1); sum += value; diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c new file mode 100644 index 000000000..e848539fe --- /dev/null +++ b/src/modules/dns/dns.c @@ -0,0 +1,194 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/dns/dns.h" +#include "modules/dns/dns.h" +#include "util/stringUtils.h" + +#define FF_DNS_NUM_FORMAT_ARGS 1 + +void ffPrintDNS(FFDNSOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFstrbuf)); + + const char* error = ffDetectDNS(options, &result); + + if (error) + { + ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if (result.length == 0) + { + ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "NO DNS servers detected"); + return; + } + + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + FF_LIST_FOR_EACH(FFstrbuf, item, result) + { + if (!ffStrbufContainC(item, '.')) continue; // IPv4 + if (buf.length) + ffStrbufAppendC(&buf, ' '); + ffStrbufAppend(&buf, item); + } + FF_LIST_FOR_EACH(FFstrbuf, item, result) + { + if (!ffStrbufContainC(item, ':')) continue; // IPv6 + if (buf.length) + ffStrbufAppendC(&buf, ' '); + ffStrbufAppend(&buf, item); + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_DNS_MODULE_NAME, 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, FF_DNS_NUM_FORMAT_ARGS, ((FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &buf, "result"}, + })); + } + + FF_LIST_FOR_EACH(FFstrbuf, item, result) + { + ffStrbufDestroy(item); + } +} + +bool ffParseDNSCommandOptions(FFDNSOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_DNS_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + if (ffStrEqualsIgnCase(subKey, "show-type")) + { + options->showType = (FFDNSShowType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "both", FF_DNS_TYPE_BOTH }, + { "ipv4", FF_DNS_TYPE_IPV4_BIT }, + { "ipv6", FF_DNS_TYPE_IPV6_BIT }, + {}, + }); + return true; + } + + return false; +} + +void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + if (ffStrEqualsIgnCase(key, "showType")) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "both", FF_DNS_TYPE_BOTH }, + { "ipv4", FF_DNS_TYPE_IPV4_BIT }, + { "ipv6", FF_DNS_TYPE_IPV6_BIT }, + {}, + }); + if (error) + ffPrintError(FF_DNS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", key, error); + else + options->showType = (FFDNSShowType) value; + continue; + } + + ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateDNSJsonConfig(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyDNSOptions))) FFDNSOptions defaultOptions; + ffInitDNSOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + + if (defaultOptions.showType != options->showType) + { + switch (options->showType) + { + case FF_DNS_TYPE_IPV4_BIT: + yyjson_mut_obj_add_str(doc, module, "showType", "ipv4"); + break; + case FF_DNS_TYPE_IPV6_BIT: + yyjson_mut_obj_add_str(doc, module, "showType", "ipv6"); + break; + case FF_DNS_TYPE_BOTH: + yyjson_mut_obj_add_str(doc, module, "showType", "both"); + break; + } + } +} + +void ffGenerateDNSJsonResult(FF_MAYBE_UNUSED FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFstrbuf)); + + const char* error = ffDetectDNS(options, &result); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + + FF_LIST_FOR_EACH(FFstrbuf, item, result) + { + yyjson_mut_arr_add_strbuf(doc, arr, item); + } + +exit: + FF_LIST_FOR_EACH(FFstrbuf, item, result) + { + ffStrbufDestroy(item); + } +} + +void ffPrintDNSHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_DNS_MODULE_NAME, "{1}", FF_DNS_NUM_FORMAT_ARGS, ((const char* []) { + "DNS result - result", + })); +} + +void ffInitDNSOptions(FFDNSOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_DNS_MODULE_NAME, + "Print configured DNS servers", + ffParseDNSCommandOptions, + ffParseDNSJsonObject, + ffPrintDNS, + ffGenerateDNSJsonResult, + ffPrintDNSHelpFormat, + ffGenerateDNSJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs); + + options->showType = FF_DNS_TYPE_BOTH; +} + +void ffDestroyDNSOptions(FFDNSOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/dns/dns.h b/src/modules/dns/dns.h new file mode 100644 index 000000000..a26504d59 --- /dev/null +++ b/src/modules/dns/dns.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_DNS_MODULE_NAME "DNS" + +void ffPrintDNS(FFDNSOptions* options); +void ffInitDNSOptions(FFDNSOptions* options); +void ffDestroyDNSOptions(FFDNSOptions* options); diff --git a/src/modules/dns/option.h b/src/modules/dns/option.h new file mode 100644 index 000000000..d261d7e06 --- /dev/null +++ b/src/modules/dns/option.h @@ -0,0 +1,19 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef enum FFDNSShowType { + FF_DNS_TYPE_IPV4_BIT = 1, + FF_DNS_TYPE_IPV6_BIT = 2, + FF_DNS_TYPE_BOTH = FF_DNS_TYPE_IPV4_BIT | FF_DNS_TYPE_IPV6_BIT, +} FFDNSShowType; + +typedef struct FFDNSOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; + + FFDNSShowType showType; +} FFDNSOptions; diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 09c1a5465..42df9c60c 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -1,6 +1,8 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "common/percent.h" #include "detection/loadavg/loadavg.h" +#include "detection/cpu/cpu.h" #include "modules/loadavg/loadavg.h" #include "util/stringUtils.h" @@ -19,8 +21,66 @@ void ffPrintLoadavg(FFLoadavgOptions* options) if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - printf("%.*f, %.*f, %.*f\n", options->ndigits, result[0], options->ndigits, result[1], options->ndigits, result[2]); + if (options->compact) + { + ffPrintLogoAndKey(FF_LOADAVG_MODULE_NAME, 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 = { + .temperature = FF_CPU_TEMP_UNSET, + .frequencyMin = 0.0/0.0, + .frequencyMax = 0.0/0.0, + .frequencyBase = 0.0/0.0, + .frequencyBiosLimit = 0.0/0.0, + .name = ffStrbufCreate(), + .vendor = ffStrbufCreate(), + }; + ffDetectCPU(&(FFCPUOptions) {}, &cpu); + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + for (uint32_t index = 0; index < 3; index++) + { + 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); + } + else + { + ffStrbufClear(&buffer); + FF_PARSE_FORMAT_STRING_CHECKED(&buffer, &options->moduleArgs.key, 2, ((FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index, "index"}, + {FF_FORMAT_ARG_TYPE_UINT, &duration, "duration"}, + })); + } + + ffPrintLogoAndKey(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + + ffStrbufClear(&buffer); + double percent = result[index] * 100 / cpu.coresOnline; + + if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&buffer, percent, options->percent, &options->moduleArgs); + + if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + { + if (buffer.length > 0) + ffStrbufAppendC(&buffer, ' '); + ffStrbufAppendF(&buffer, "%.*f", options->ndigits, result[index]); + } + + if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + { + if (buffer.length > 0) + ffStrbufAppendC(&buffer, ' '); + ffPercentAppendNum(&buffer, percent, options->percent, buffer.length > 0, &options->moduleArgs); + } + + ffStrbufPutTo(&buffer, stdout); + } + } } else { @@ -45,6 +105,15 @@ bool ffParseLoadavgCommandOptions(FFLoadavgOptions* options, const char* key, co return true; } + if (ffStrEqualsIgnCase(subKey, "compact")) + { + options->compact = ffOptionParseBoolean(value); + return true; + } + + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -67,6 +136,15 @@ void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "compact")) + { + options->compact = yyjson_get_bool(val); + continue; + } + + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); } } @@ -80,6 +158,11 @@ void ffGenerateLoadavgJsonConfig(FFLoadavgOptions* options, yyjson_mut_doc* doc, if (defaultOptions.ndigits != options->ndigits) yyjson_mut_obj_add_uint(doc, module, "ndigits", options->ndigits); + + if (defaultOptions.compact != options->compact) + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateLoadavgJsonResult(FF_MAYBE_UNUSED FFLoadavgOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -122,7 +205,9 @@ void ffInitLoadavgOptions(FFLoadavgOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs); + options->percent = (FFColorRangeConfig) { 50, 80 }; options->ndigits = 2; + options->compact = true; } void ffDestroyLoadavgOptions(FFLoadavgOptions* options) diff --git a/src/modules/loadavg/option.h b/src/modules/loadavg/option.h index bc8df7077..0bcce0037 100644 --- a/src/modules/loadavg/option.h +++ b/src/modules/loadavg/option.h @@ -9,5 +9,7 @@ typedef struct FFLoadavgOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + FFColorRangeConfig percent; uint8_t ndigits; + bool compact; } FFLoadavgOptions; diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 28aa7d4d3..54d21f204 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -5,7 +5,7 @@ #include "util/stringUtils.h" #define FF_LOCALIP_DISPLAY_NAME "Local IP" -#define FF_LOCALIP_NUM_FORMAT_ARGS 5 +#define FF_LOCALIP_NUM_FORMAT_ARGS 6 #pragma GCC diagnostic ignored "-Wsign-conversion" static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) @@ -116,6 +116,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &ip->mac, "mac"}, {FF_FORMAT_ARG_TYPE_STRBUF, &ip->name, "ifname"}, {FF_FORMAT_ARG_TYPE_BOOL, &ip->defaultRoute, "is-default-route"}, + {FF_FORMAT_ARG_TYPE_INT, &ip->mtu, "mtu"}, })); } ++index; @@ -373,6 +374,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs yyjson_mut_obj_add_strbuf(doc, obj, "ipv6", &ip->ipv6); yyjson_mut_obj_add_strbuf(doc, obj, "mac", &ip->mac); yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name); + yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu); } FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) @@ -391,7 +393,8 @@ void ffPrintLocalIpHelpFormat(void) "Local IPv6 address - ipv6", "Physical (MAC) address - mac", "Interface name - ifname", - "Is default route - is-default-route" + "Is default route - is-default-route", + "MTU size in bytes - mtu", })); } diff --git a/src/modules/modules.h b/src/modules/modules.h index 0e4587691..58ce1b98d 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -23,6 +23,7 @@ #include "modules/diskio/diskio.h" #include "modules/display/display.h" #include "modules/de/de.h" +#include "modules/dns/dns.h" #include "modules/editor/editor.h" #include "modules/font/font.h" #include "modules/gamepad/gamepad.h" diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 3f9e42211..f0f49662b 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -4,7 +4,7 @@ #include "modules/opengl/opengl.h" #include "util/stringUtils.h" -#define FF_OPENGL_NUM_FORMAT_ARGS 4 +#define FF_OPENGL_NUM_FORMAT_ARGS 5 void ffPrintOpenGL(FFOpenGLOptions* options) { @@ -13,6 +13,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options) ffStrbufInit(&result.renderer); ffStrbufInit(&result.vendor); ffStrbufInit(&result.slv); + result.library = "Unknown"; const char* error = ffDetectOpenGL(options, &result); if(error) @@ -33,6 +34,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &result.renderer, "renderer"}, {FF_FORMAT_ARG_TYPE_STRBUF, &result.vendor, "vendor"}, {FF_FORMAT_ARG_TYPE_STRBUF, &result.slv, "slv"}, + {FF_FORMAT_ARG_TYPE_STRING, result.library, "library"}, })); } @@ -150,6 +152,7 @@ void ffGenerateOpenGLJsonResult(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson yyjson_mut_obj_add_strbuf(doc, obj, "renderer", &result.renderer); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "slv", &result.slv); + yyjson_mut_obj_add_str(doc, obj, "library", result.library); } ffStrbufDestroy(&result.version); @@ -164,7 +167,8 @@ void ffPrintOpenGLHelpFormat(void) "version - version", "renderer - renderer", "vendor - vendor", - "shading language version - slv" + "shading language version - slv", + "ogl library used - library", })); } diff --git a/src/modules/opengl/option.h b/src/modules/opengl/option.h index dd151f3d3..ca60b7da3 100644 --- a/src/modules/opengl/option.h +++ b/src/modules/opengl/option.h @@ -4,7 +4,7 @@ #include "common/option.h" -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) typedef enum FFOpenGLLibrary { FF_OPENGL_LIBRARY_AUTO, @@ -19,7 +19,7 @@ typedef struct FFOpenGLOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) FFOpenGLLibrary library; #endif } FFOpenGLOptions; diff --git a/src/modules/options.h b/src/modules/options.h index 7c0ff7129..49bd8fe6b 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -23,6 +23,7 @@ #include "modules/disk/option.h" #include "modules/diskio/option.h" #include "modules/display/option.h" +#include "modules/dns/option.h" #include "modules/editor/option.h" #include "modules/font/option.h" #include "modules/host/option.h" diff --git a/src/modules/os/os.c b/src/modules/os/os.c index b447a1821..5a6123f1d 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -11,7 +11,6 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) { - // asm ("int3"); //Create the basic output if(os->name.length > 0) ffStrbufAppend(result, &os->name); diff --git a/src/modules/player/player.c b/src/modules/player/player.c index df6c8a534..4e97da8ae 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -19,21 +19,30 @@ void ffPrintPlayer(FFPlayerOptions* options) return; } + if (media->player.length == 0) + { + ffPrintError(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No media player detected"); + return; + } + FF_STRBUF_AUTO_DESTROY playerPretty = ffStrbufCreate(); - //If we are on a website, prepend the website name - if( - ffStrbufIgnCaseCompS(&media->playerId, "spotify") == 0 || - ffStrbufIgnCaseCompS(&media->playerId, "vlc") == 0 - ) {} // do noting, surely not a website, even if the url is set - else if(ffStrbufStartsWithS(&media->url, "https://www.")) - ffStrbufAppendS(&playerPretty, media->url.chars + 12); - else if(ffStrbufStartsWithS(&media->url, "http://www.")) - ffStrbufAppendS(&playerPretty, media->url.chars + 11); - else if(ffStrbufStartsWithS(&media->url, "https://")) - ffStrbufAppendS(&playerPretty, media->url.chars + 8); - else if(ffStrbufStartsWithS(&media->url, "http://")) - ffStrbufAppendS(&playerPretty, media->url.chars + 7); + if (media->url.length > 0) + { + //If we are on a website, prepend the website name + if( + ffStrbufIgnCaseEqualS(&media->playerId, "spotify") || + ffStrbufIgnCaseEqualS(&media->playerId, "vlc") + ) {} // do noting, surely not a website, even if the url is set + else if(ffStrbufStartsWithS(&media->url, "https://www.")) + ffStrbufAppendS(&playerPretty, media->url.chars + 12); + else if(ffStrbufStartsWithS(&media->url, "http://www.")) + ffStrbufAppendS(&playerPretty, media->url.chars + 11); + else if(ffStrbufStartsWithS(&media->url, "https://")) + ffStrbufAppendS(&playerPretty, media->url.chars + 8); + else if(ffStrbufStartsWithS(&media->url, "http://")) + ffStrbufAppendS(&playerPretty, media->url.chars + 7); + } //If we found a website name, make it more pretty if(playerPretty.length > 0) @@ -68,7 +77,7 @@ void ffPrintPlayer(FFPlayerOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &playerPretty, "player"}, {FF_FORMAT_ARG_TYPE_STRBUF, &media->player, "name"}, {FF_FORMAT_ARG_TYPE_STRBUF, &media->playerId, "id"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &media->url, "url"} + {FF_FORMAT_ARG_TYPE_STRBUF, &media->url, "url"}, })); } } diff --git a/src/modules/users/option.h b/src/modules/users/option.h index 6883e8dd0..af194fea2 100644 --- a/src/modules/users/option.h +++ b/src/modules/users/option.h @@ -10,4 +10,5 @@ typedef struct FFUsersOptions FFModuleArgs moduleArgs; bool compact; + bool myselfOnly; } FFUsersOptions; diff --git a/src/modules/users/users.c b/src/modules/users/users.c index 3e81d7a24..e7ddec980 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -13,7 +13,7 @@ void ffPrintUsers(FFUsersOptions* options) { FF_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFUserResult)); - const char* error = ffDetectUsers(&users); + const char* error = ffDetectUsers(options, &users); if(error) { @@ -94,12 +94,18 @@ bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; - if(ffStrEqualsIgnCase(subKey, "compact")) + if (ffStrEqualsIgnCase(subKey, "compact")) { options->compact = ffOptionParseBoolean(value); return true; } + if (ffStrEqualsIgnCase(subKey, "myself-only")) + { + options->myselfOnly = ffOptionParseBoolean(value); + return true; + } + return false; } @@ -110,7 +116,7 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) yyjson_obj_foreach(module, idx, max, key_, val) { const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type")) + if (ffStrEqualsIgnCase(key, "type")) continue; if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) @@ -122,6 +128,12 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "myselfOnly")) + { + options->myselfOnly = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); } } @@ -135,13 +147,16 @@ void ffGenerateUsersJsonConfig(FFUsersOptions* options, yyjson_mut_doc* doc, yyj if (options->compact != defaultOptions.compact) yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); + + if (options->myselfOnly != defaultOptions.myselfOnly) + yyjson_mut_obj_add_bool(doc, module, "myselfOnly", options->myselfOnly); } -void ffGenerateUsersJsonResult(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateUsersJsonResult(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFUserResult)); - const char* error = ffDetectUsers(&results); + const char* error = ffDetectUsers(options, &results); if(error) { @@ -200,6 +215,7 @@ void ffInitUsersOptions(FFUsersOptions* options) ffOptionInitModuleArg(&options->moduleArgs); options->compact = false; + options->myselfOnly = false; } void ffDestroyUsersOptions(FFUsersOptions* options) diff --git a/src/options/display.c b/src/options/display.c index 65e9e4c65..b50488c9e 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -180,11 +180,11 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va if (charTotal) ffStrbufSetS(&options->barCharTotal, charTotal); - yyjson_val* borderLeft = yyjson_obj_get(val, "border-left"); + yyjson_val* borderLeft = yyjson_obj_get(val, "borderLeft"); if (borderLeft) ffStrbufSetS(&options->barBorderLeft, yyjson_get_str(borderLeft)); - yyjson_val* borderRight = yyjson_obj_get(val, "border-right"); + yyjson_val* borderRight = yyjson_obj_get(val, "borderRight"); if (borderRight) ffStrbufSetS(&options->barBorderRight, yyjson_get_str(borderRight)); diff --git a/src/options/general.c b/src/options/general.c index f27dce3e5..2b87d7929 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -22,7 +22,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va else if (ffStrEqualsIgnCase(key, "processingTimeout")) options->processingTimeout = (int32_t) yyjson_get_int(val); - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) else if (ffStrEqualsIgnCase(key, "escapeBedrock")) options->escapeBedrock = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "playerName")) @@ -72,7 +72,7 @@ bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key else if(ffStrEqualsIgnCase(key, "--processing-timeout")) options->processingTimeout = ffOptionParseInt32(key, value); - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) else if(ffStrEqualsIgnCase(key, "--escape-bedrock")) options->escapeBedrock = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "--player-name")) diff --git a/src/options/general.h b/src/options/general.h index 0ab8ee5a7..b388f3f43 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -15,7 +15,7 @@ typedef struct FFOptionsGeneral int32_t processingTimeout; // Module options that cannot be put in module option structure - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) FFstrbuf playerName; bool escapeBedrock; FFDsForceDrmType dsForceDrm; diff --git a/src/options/library.c b/src/options/library.c index 0a29f202b..36aa4033b 100644 --- a/src/options/library.c +++ b/src/options/library.c @@ -28,9 +28,12 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va else if (ffStrEqualsIgnCase(key, "z")) ffStrbufSetS(&options->libZ, yyjson_get_str(val)); -#if defined(__linux__) || defined(__FreeBSD__) +#ifdef __ANDROID__ else if (ffStrEqualsIgnCase(key, "freetype")) ffStrbufSetS(&options->libfreetype, yyjson_get_str(val)); +#endif + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) else if (ffStrEqualsIgnCase(key, "wayland")) ffStrbufSetS(&options->libWayland, yyjson_get_str(val)); else if (ffStrEqualsIgnCase(key, "xcbRandr")) @@ -92,9 +95,12 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key else if(ffStrEqualsIgnCase(subkey, "z")) ffOptionParseString(key, value, &options->libZ); -#if defined(__linux__) || defined(__FreeBSD__) +#ifdef __ANDROID__ else if(ffStrEqualsIgnCase(subkey, "freetype")) ffOptionParseString(key, value, &options->libfreetype); +#endif + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) else if(ffStrEqualsIgnCase(subkey, "wayland")) ffOptionParseString(key, value, &options->libWayland); else if(ffStrEqualsIgnCase(subkey, "xcbRandr")) diff --git a/src/options/library.h b/src/options/library.h index f7e3f16a3..cc65302b5 100644 --- a/src/options/library.h +++ b/src/options/library.h @@ -11,7 +11,11 @@ typedef struct FFOptionsLibrary FFstrbuf libChafa; FFstrbuf libZ; -#if defined(__linux__) || defined(__FreeBSD__) +#ifdef __ANDROID__ + FFstrbuf libfreetype; +#endif + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) FFstrbuf libWayland; FFstrbuf libXcbRandr; FFstrbuf libXcb; @@ -25,7 +29,6 @@ typedef struct FFOptionsLibrary FFstrbuf libEGL; FFstrbuf libGLX; FFstrbuf libOSMesa; - FFstrbuf libfreetype; FFstrbuf libPulse; FFstrbuf libnm; FFstrbuf libDdcutil; diff --git a/src/options/modules.c b/src/options/modules.c index 095449a8e..7d80b2d86 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -24,6 +24,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitDiskOptions(&options->disk); ffInitDiskIOOptions(&options->diskIo); ffInitDisplayOptions(&options->display); + ffInitDNSOptions(&options->dns); ffInitEditorOptions(&options->editor); ffInitFontOptions(&options->font); ffInitGPUOptions(&options->gpu); @@ -94,6 +95,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyDiskOptions(&options->disk); ffDestroyDiskIOOptions(&options->diskIo); ffDestroyDisplayOptions(&options->display); + ffDestroyDNSOptions(&options->dns); ffDestroyEditorOptions(&options->editor); ffDestroyFontOptions(&options->font); ffDestroyGPUOptions(&options->gpu); diff --git a/src/options/modules.h b/src/options/modules.h index c8f46b892..fdfae5e47 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -25,6 +25,7 @@ typedef struct FFOptionsModules FFDiskOptions disk; FFDiskIOOptions diskIo; FFDisplayOptions display; + FFDNSOptions dns; FFEditorOptions editor; FFFontOptions font; FFGPUOptions gpu; diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index b57bb499d..4ba4d2a5f 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -34,11 +34,14 @@ static void getExePath(FFPlatform* platform) exePathLen = 0; else exePathLen--; // remove terminating NUL + #else + ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1); + exePath[exePathLen] = '\0'; #endif if (exePathLen > 0) { ffStrbufEnsureFree(&platform->exePath, PATH_MAX); - if (realpath(platform->exePath.chars, exePath)) + if (realpath(exePath, platform->exePath.chars)) ffStrbufRecalculateLength(&platform->exePath); else ffStrbufSetNS(&platform->exePath, (uint32_t) exePathLen, exePath); @@ -181,7 +184,7 @@ void ffPlatformInitImpl(FFPlatform* platform) struct passwd* pwd = getpwuid(getuid()); struct utsname uts; - if(uname(&uts) != 0) + if(uname(&uts) < 0) memset(&uts, 0, sizeof(uts)); getExePath(platform); diff --git a/src/util/smbiosHelper.c b/src/util/smbiosHelper.c index 9c7d84267..8ce226fa0 100644 --- a/src/util/smbiosHelper.c +++ b/src/util/smbiosHelper.c @@ -48,16 +48,19 @@ const FFSmbiosHeader* ffSmbiosNextEntry(const FFSmbiosHeader* header) return (const FFSmbiosHeader*) (p + 1); } -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) #include #include #include +#include #ifdef __linux__ #include "common/properties.h" -#else +#elif defined(__FreeBSD__) #include "common/settings.h" #define loff_t off_t // FreeBSD doesn't have loff_t +#elif defined(__sun) + #define loff_t off_t #endif bool ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) @@ -134,11 +137,12 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() if (!ffAppendFileBuffer("/sys/firmware/dmi/tables/DMI", &buffer)) #endif { + #ifndef __sun FF_STRBUF_AUTO_DESTROY strEntryAddress = ffStrbufCreate(); #ifdef __FreeBSD__ if (!ffSettingsGetFreeBSDKenv("hint.smbios.0.mem", &strEntryAddress)) return NULL; - #else + #elif defined(__linux__) { FF_STRBUF_AUTO_DESTROY systab = ffStrbufCreate(); if (!ffAppendFileBuffer("/sys/firmware/efi/systab", &systab)) @@ -165,6 +169,13 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() memcpy(&entryPoint, p, sizeof(entryPoint)); munmap(p, sizeof(entryPoint)); } + #else + FF_AUTO_CLOSE_FD int fd = open("/dev/smbios", O_RDONLY); + if (fd < 0) return NULL; + + FFSmbiosEntryPoint entryPoint; + if (!ffReadFDData(fd, sizeof(entryPoint), &entryPoint)) return NULL; + #endif uint32_t tableLength = 0; loff_t tableAddress = 0;