mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
+99
-17
@@ -15,8 +15,12 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Ll]inux.*")
|
||||
set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
|
||||
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Bb][Ss][Dd].*")
|
||||
set(BSD TRUE CACHE BOOL "..." FORCE)
|
||||
elseif(NOT APPLE AND NOT ANDROID)
|
||||
message(FATAL_ERROR "Unsupported platform")
|
||||
elseif(NOT APPLE AND NOT ANDROID AND NOT MSYS)
|
||||
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
if(MSYS)
|
||||
enable_language(CXX)
|
||||
endif()
|
||||
|
||||
#####################
|
||||
@@ -26,7 +30,7 @@ endif()
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR MSYS" 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)
|
||||
@@ -45,8 +49,8 @@ cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENAB
|
||||
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" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR MSYS" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR MSYS" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
@@ -76,13 +80,21 @@ message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
|
||||
|
||||
if(MSYS)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti")
|
||||
endif()
|
||||
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
|
||||
endif()
|
||||
|
||||
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined")
|
||||
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
|
||||
if(NOT MSYS)
|
||||
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic")
|
||||
|
||||
@@ -190,7 +202,6 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/caching.c
|
||||
src/common/properties.c
|
||||
src/common/font.c
|
||||
src/common/processing.c
|
||||
src/common/format.c
|
||||
src/common/parsing.c
|
||||
src/common/settings.c
|
||||
@@ -201,15 +212,13 @@ set(LIBFASTFETCH_SRC
|
||||
src/logo/image/image.c
|
||||
src/logo/image/im7.c
|
||||
src/logo/image/im6.c
|
||||
src/detection/qt.c
|
||||
src/detection/gtk.c
|
||||
src/detection/terminalShell.c
|
||||
src/detection/vulkan.c
|
||||
src/detection/datetime.c
|
||||
src/detection/title.c
|
||||
src/detection/host/host.c
|
||||
src/detection/os/os.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuUsage/cpuUsage.c
|
||||
src/detection/gpu/gpu.c
|
||||
src/detection/memory/memory.c
|
||||
src/detection/font/font.c
|
||||
@@ -222,6 +231,8 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/separator.c
|
||||
src/modules/os.c
|
||||
src/modules/host.c
|
||||
src/modules/bios.c
|
||||
src/modules/board.c
|
||||
src/modules/kernel.c
|
||||
src/modules/uptime.c
|
||||
src/modules/processes.c
|
||||
@@ -260,6 +271,18 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/users.c
|
||||
)
|
||||
|
||||
if(LINUX OR APPLE OR ANDROID OR BSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/users/users_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/disk/disk.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/packages/packages_linux.c
|
||||
src/detection/kernel/kernel_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BSD OR APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/sysctl.c
|
||||
@@ -277,14 +300,19 @@ if(LINUX OR ANDROID OR BSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/cpuUsage/cpuUsage_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/poweradapter/poweradapter_linux.c
|
||||
src/detection/temps/temps_linux.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/processes/processes_linux.c
|
||||
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if(LINUX OR BSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/bios/bios_linux.c
|
||||
src/detection/board/board_linux.c
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
@@ -297,6 +325,42 @@ if(LINUX OR BSD)
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/qt.c
|
||||
src/detection/gtk.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MSYS)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/processing_linux.c
|
||||
src/detection/host/host_windows.cpp
|
||||
src/detection/bios/bios_windows.cpp
|
||||
src/detection/board/board_windows.cpp
|
||||
src/detection/cpu/cpu_windows.cpp
|
||||
src/detection/gpu/gpu_windows.cpp
|
||||
src/detection/battery/battery_windows.cpp
|
||||
src/detection/displayserver/displayserver_windows.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/opengl/opengl_windows.c
|
||||
src/detection/users/users_windows.cpp
|
||||
src/detection/os/os_windows.cpp
|
||||
src/detection/processes/processes_windows.cpp
|
||||
src/detection/disk/disk_windows.c
|
||||
src/detection/cpuUsage/cpuUsage_windows.c
|
||||
src/detection/cpuUsage/cpuUsage_nowait_windows.cpp
|
||||
src/detection/memory/memory_windows.cpp
|
||||
src/detection/font/font_windows.cpp
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/terminalshell/terminalshell_windows.cpp
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/packages/packages_linux.c
|
||||
src/detection/packages/packages_windows.c
|
||||
src/detection/kernel/kernel_windows.cpp
|
||||
src/detection/localip/localip_windows.c
|
||||
src/util/windows/wmi.cpp
|
||||
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/media/media_nosupport.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -319,6 +383,11 @@ if(APPLE)
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/temps/temps_apple.c
|
||||
src/detection/font/font_apple.m
|
||||
src/detection/opengl/opengl_apple.c
|
||||
src/detection/processes/processes_apple.c
|
||||
|
||||
src/detection/bios/bios_nosupport.c
|
||||
src/detection/board/board_nosupport.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -333,13 +402,16 @@ if(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/host/host_android.c
|
||||
src/detection/os/os_android.c
|
||||
src/detection/gpu/gpu_android.c
|
||||
src/detection/battery/battery_android.c
|
||||
src/detection/displayserver/displayserver_android.c
|
||||
src/detection/terminalfont/terminalfont_android.c
|
||||
src/detection/media/media_android.c
|
||||
src/detection/wmtheme/wmtheme_android.c
|
||||
src/detection/font/font_android.c
|
||||
|
||||
src/detection/bios/bios_nosupport.c
|
||||
src/detection/board/board_nosupport.c
|
||||
src/detection/displayserver/displayserver_nosupport.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/gpu/gpu_nosupport.c
|
||||
src/detection/font/font_nosupport.c
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -417,6 +489,16 @@ if(APPLE)
|
||||
PRIVATE "-framework Cocoa"
|
||||
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
|
||||
)
|
||||
elseif(MSYS)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "wbemuuid"
|
||||
PRIVATE "ole32"
|
||||
PRIVATE "oleaut32"
|
||||
PRIVATE "dwmapi"
|
||||
PRIVATE "opengl32"
|
||||
PRIVATE "gdi32"
|
||||
PRIVATE "iphlpapi"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Fastfetch
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, BSD and MacOS are supported.
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, BSD, MacOS and Windows on [MSYS2](https://www.msys2.org/) are supported.
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -44,7 +44,7 @@ The following libraries are used if present at runtime:
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
|
||||
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
|
||||
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( Windows, WSL ).
|
||||
* [`freetype`](https://www.freetype.org/): Needed for Termux font detection ( Android ).
|
||||
|
||||
## Support status
|
||||
@@ -52,12 +52,12 @@ All categories not listed here should work without needing a specific implementa
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
```
|
||||
|
||||
##### Logos
|
||||
```
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal, Debian, Devuan, Deepin, Endeavour, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Ubuntu, Void, Zorin
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal, Debian, Devuan, Deepin, Endeavour, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Ubuntu, Void, Windows 11, Windows 8, Windows, Zorin
|
||||
```
|
||||
* Most of the logos have a small variant. Access it by appending _small to the logo name.
|
||||
* Some logos have an old variant. Access it by appending _old to the logo name.
|
||||
@@ -67,12 +67,12 @@ AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal
|
||||
|
||||
##### Package managers
|
||||
```
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop
|
||||
```
|
||||
|
||||
##### WM themes
|
||||
```
|
||||
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS)
|
||||
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), DWM (Windows)
|
||||
```
|
||||
|
||||
##### DE versions
|
||||
@@ -82,7 +82,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
|
||||
|
||||
##### Terminal fonts
|
||||
```
|
||||
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux
|
||||
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux, mintty
|
||||
```
|
||||
|
||||
## Building
|
||||
@@ -97,6 +97,12 @@ cmake --build . --target fastfetch --target flashfetch
|
||||
|
||||
If pkg-config fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
|
||||
|
||||
### Building on Windows
|
||||
|
||||
Currently [MSYS2](https://www.msys2.org/) is required to build fastfetch. Running fastfetch requires msys2 runtime library (`msys-2.0.dll`) but not full MSYS2 environment.
|
||||
|
||||
Full native Windows executable is planned.
|
||||
|
||||
## Packaging
|
||||
|
||||
### Repositories
|
||||
|
||||
@@ -99,7 +99,10 @@ static bool printCachedValue(FFinstance* instance, const char* moduleName, const
|
||||
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
|
||||
|
||||
if(content.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&content);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t moduleCounter = 1;
|
||||
|
||||
|
||||
+5
-1
@@ -162,6 +162,8 @@ static void defaultConfig(FFinstance* instance)
|
||||
|
||||
initModuleArg(&instance->config.os);
|
||||
initModuleArg(&instance->config.host);
|
||||
initModuleArg(&instance->config.bios);
|
||||
initModuleArg(&instance->config.board);
|
||||
initModuleArg(&instance->config.kernel);
|
||||
initModuleArg(&instance->config.uptime);
|
||||
initModuleArg(&instance->config.processes);
|
||||
@@ -257,7 +259,7 @@ void ffInitInstance(FFinstance* instance)
|
||||
defaultConfig(instance);
|
||||
}
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
#if !defined(__ANDROID__) && !defined(_WIN32) && !defined(__MSYS__)
|
||||
|
||||
static void* connectDisplayServerThreadMain(void* instance)
|
||||
{
|
||||
@@ -416,6 +418,8 @@ static void destroyConfig(FFinstance* instance)
|
||||
|
||||
destroyModuleArg(&instance->config.os);
|
||||
destroyModuleArg(&instance->config.host);
|
||||
destroyModuleArg(&instance->config.bios);
|
||||
destroyModuleArg(&instance->config.board);
|
||||
destroyModuleArg(&instance->config.kernel);
|
||||
destroyModuleArg(&instance->config.uptime);
|
||||
destroyModuleArg(&instance->config.processes);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#ifndef FF_INCLUDED_common_io
|
||||
#define FF_INCLUDED_common_io
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <sys/types.h> //mode_t
|
||||
|
||||
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
static void* libraryLoad(const char* path, int maxVersion)
|
||||
{
|
||||
void* result = dlopen(path, FF_DLOPEN_FLAGS);
|
||||
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
|
||||
// libX.dll.1 never exists on Windows, while libX-1.dll may exist
|
||||
FF_UNUSED(maxVersion)
|
||||
|
||||
#else
|
||||
|
||||
if(result != NULL || maxVersion < 0)
|
||||
return result;
|
||||
|
||||
@@ -40,6 +48,9 @@ static void* libraryLoad(const char* path, int maxVersion)
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&pathbuf);
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
#define FF_LIBRARY_EXTENSION ".dll"
|
||||
#elif defined(__APPLE__)
|
||||
#define FF_LIBRARY_EXTENSION ".dylib"
|
||||
#else
|
||||
#define FF_LIBRARY_EXTENSION ".so"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places.
|
||||
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
{
|
||||
SECURITY_ATTRIBUTES saAttr = {
|
||||
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
||||
.lpSecurityDescriptor = NULL,
|
||||
.bInheritHandle = TRUE,
|
||||
};
|
||||
|
||||
HANDLE hChildStdoutRead, hChildStdoutWrite;
|
||||
if (!CreatePipe(&hChildStdoutRead, &hChildStdoutWrite, &saAttr, 0))
|
||||
return "CreatePipe() failed";
|
||||
|
||||
if (!SetHandleInformation(hChildStdoutRead, HANDLE_FLAG_INHERIT, 0))
|
||||
return "SetHandleInformation(hChildStdoutRead) failed";
|
||||
|
||||
PROCESS_INFORMATION piProcInfo = {0};
|
||||
STARTUPINFOA siStartInfo = {
|
||||
.cb = sizeof(siStartInfo),
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
.hStdOutput = hChildStdoutWrite,
|
||||
};
|
||||
|
||||
FFstrbuf cmdline;
|
||||
ffStrbufInit(&cmdline);
|
||||
for(char* const* parg = argv; *parg; ++parg)
|
||||
{
|
||||
if(cmdline.length > 0)
|
||||
ffStrbufAppendC(&cmdline, ' ');
|
||||
ffStrbufAppendF(&cmdline, "\"%s\"", * parg);
|
||||
}
|
||||
|
||||
BOOL success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo); // receives PROCESS_INFORMATION
|
||||
|
||||
CloseHandle(hChildStdoutWrite);
|
||||
if(!success)
|
||||
{
|
||||
CloseHandle(hChildStdoutRead);
|
||||
return "CreateProcessA() failed";
|
||||
}
|
||||
|
||||
char str[128];
|
||||
DWORD nRead;
|
||||
while(ReadFile(hChildStdoutRead, str, sizeof(str), &nRead, NULL) && nRead > 0)
|
||||
{
|
||||
ffStrbufAppendNS(buffer, nRead, str);
|
||||
if(nRead < sizeof(str))
|
||||
break;
|
||||
}
|
||||
|
||||
CloseHandle(hChildStdoutRead);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_time
|
||||
#define FF_INCLUDED_common_time
|
||||
|
||||
#include <stdint.h>
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
#include <synchapi.h>
|
||||
#include <sysinfoapi.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static inline uint64_t ffTimeGetTick() //In msec
|
||||
{
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
return GetTickCount64();
|
||||
#else
|
||||
struct timeval timeNow;
|
||||
gettimeofday(&timeNow, NULL);
|
||||
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void ffTimeSleep(uint32_t msec)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
SleepEx(msec, TRUE);
|
||||
#else
|
||||
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
# Whitespaces are trimmed at the beginning and the end.
|
||||
# Empty lines or lines starting with # are ignored.
|
||||
|
||||
# This file was shipped with $"FASTFETCH_PROJECT_VERSION$".
|
||||
# This file was shipped with $" FASTFETCH_PROJECT_VERSION $".
|
||||
# Use fastfetch --print-config-user > ~/.config/fastfetch/config.conf to overwrite this file with the current defaults
|
||||
|
||||
# Below some often usefull options are listed. Uncomment and modify them so they take affect.
|
||||
@@ -25,7 +25,7 @@
|
||||
# Must be a list of module names, separated by colons.
|
||||
# List available modules with "fastfetch --list-modules".
|
||||
# Get the default structure with "fastfetch --print-structure".
|
||||
#--structure $"FASTFETCH_DATATEXT_STRUCTURE$"
|
||||
#--structure $" FASTFETCH_DATATEXT_STRUCTURE $"
|
||||
|
||||
# Multithreading option:
|
||||
# Sets if fastfetch should use multiple threads to detect the values.
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ Module specific options:
|
||||
--title-fqdn <?value>: Sets if the title should use fully qualified domain name. Default is false.
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS informations
|
||||
--disk-folders <folders>: A colon separated list of folder paths for the disk output. Default is "/:/home"
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-removable <?value>: Sets if removable volume should be printed. Default is false
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
#include "battery.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_UNUSED(instance, results)
|
||||
return "Unimplemented";
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
extern "C" {
|
||||
#include "battery.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery", nullptr);
|
||||
|
||||
if(!pEnumerator)
|
||||
return "Query WMI service failed";
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
|
||||
{
|
||||
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffGetWmiObjString(pclsObj, L"SystemName", &battery->manufacturer);
|
||||
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffGetWmiObjString(pclsObj, L"Name", &battery->modelName);
|
||||
|
||||
uint64_t chemistry;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"Chemistry", &chemistry);
|
||||
switch(chemistry)
|
||||
{
|
||||
case 1: ffStrbufInitS(&battery->technology, "Other"); break;
|
||||
case 2: ffStrbufInitS(&battery->technology, "Unknown"); break;
|
||||
case 3: ffStrbufInitS(&battery->technology, "Lead Acid"); break;
|
||||
case 4: ffStrbufInitS(&battery->technology, "Nickel Cadmium"); break;
|
||||
case 5: ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); break;
|
||||
case 6: ffStrbufInitS(&battery->technology, "Lithium-ion"); break;
|
||||
case 7: ffStrbufInitS(&battery->technology, "Zinc air"); break;
|
||||
case 8: ffStrbufInitS(&battery->technology, "Lithium Polymer"); break;
|
||||
}
|
||||
|
||||
uint64_t capacity;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"EstimatedChargeRemaining", &capacity);
|
||||
ffStrbufInitF(&battery->capacity, "%d", (int)capacity);
|
||||
|
||||
uint64_t batteryStatus;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"BatteryStatus", &batteryStatus);
|
||||
switch(batteryStatus)
|
||||
{
|
||||
case 1: ffStrbufInitS(&battery->status, "Discharging"); break;
|
||||
case 2: ffStrbufInitS(&battery->status, "AC Connected"); break;
|
||||
case 3: ffStrbufInitS(&battery->status, "Fully Charged"); break;
|
||||
case 4: ffStrbufInitS(&battery->status, "Low"); break;
|
||||
case 5: ffStrbufInitS(&battery->status, "Critical"); break;
|
||||
case 6: ffStrbufInitS(&battery->status, "Charging"); break;
|
||||
case 7: ffStrbufInitS(&battery->status, "Charging and High"); break;
|
||||
case 8: ffStrbufInitS(&battery->status, "Charging and Low"); break;
|
||||
case 9: ffStrbufInitS(&battery->status, "Charging and Critical"); break;
|
||||
case 10: ffStrbufInitS(&battery->status, "Undefined"); break;
|
||||
case 11: ffStrbufInitS(&battery->status, "Partially Charged"); break;
|
||||
}
|
||||
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
}
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_bios_bios
|
||||
#define FF_INCLUDED_detection_bios_bios
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBiosResult
|
||||
{
|
||||
FFstrbuf biosDate;
|
||||
FFstrbuf biosRelease;
|
||||
FFstrbuf biosVendor;
|
||||
FFstrbuf biosVersion;
|
||||
FFstrbuf error;
|
||||
} FFBiosResult;
|
||||
|
||||
void ffDetectBios(FFBiosResult* bios);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "bios.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool hostValueSet(FFstrbuf* value)
|
||||
{
|
||||
return
|
||||
value->length > 0 &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||
;
|
||||
}
|
||||
|
||||
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||
{
|
||||
ffReadFileBuffer(devicesPath, buffer);
|
||||
if(hostValueSet(buffer))
|
||||
return;
|
||||
|
||||
ffReadFileBuffer(classPath, buffer);
|
||||
if(hostValueSet(buffer))
|
||||
return;
|
||||
|
||||
ffStrbufClear(buffer);
|
||||
}
|
||||
|
||||
void ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
ffStrbufInit(&bios->error);
|
||||
|
||||
ffStrbufInit(&bios->biosDate);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->biosDate);
|
||||
|
||||
ffStrbufInit(&bios->biosRelease);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->biosRelease);
|
||||
|
||||
ffStrbufInit(&bios->biosVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->biosVendor);
|
||||
|
||||
ffStrbufInit(&bios->biosVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->biosVersion);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "bios.h"
|
||||
|
||||
void ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
ffStrbufInitS(&bios->error, "Not supported on this platform");
|
||||
|
||||
ffStrbufInit(&bios->biosDate);
|
||||
ffStrbufInit(&bios->biosRelease);
|
||||
ffStrbufInit(&bios->biosVendor);
|
||||
ffStrbufInit(&bios->biosVersion);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
extern "C" {
|
||||
#include "bios.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C" void ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
ffStrbufInit(&bios->error);
|
||||
|
||||
ffStrbufInit(&bios->biosDate);
|
||||
ffStrbufInit(&bios->biosRelease);
|
||||
ffStrbufInit(&bios->biosVendor);
|
||||
ffStrbufInit(&bios->biosVersion);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, ReleaseDate, Version, Manufacturer FROM Win32_BIOS", &bios->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if(uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&bios->error, "No Wmi result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"Name", &bios->biosRelease);
|
||||
ffGetWmiObjString(pclsObj, L"ReleaseDate", &bios->biosDate);
|
||||
ffGetWmiObjString(pclsObj, L"Version", &bios->biosVersion);
|
||||
ffGetWmiObjString(pclsObj, L"Manufacturer", &bios->biosVendor);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_board_board
|
||||
#define FF_INCLUDED_detection_board_board
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBoardResult
|
||||
{
|
||||
FFstrbuf boardName;
|
||||
FFstrbuf boardVendor;
|
||||
FFstrbuf boardVersion;
|
||||
FFstrbuf error;
|
||||
} FFBoardResult;
|
||||
|
||||
void ffDetectBoard(FFBoardResult* result);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "board.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool hostValueSet(FFstrbuf* value)
|
||||
{
|
||||
return
|
||||
value->length > 0 &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||
;
|
||||
}
|
||||
|
||||
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||
{
|
||||
ffReadFileBuffer(devicesPath, buffer);
|
||||
if(hostValueSet(buffer))
|
||||
return;
|
||||
|
||||
ffReadFileBuffer(classPath, buffer);
|
||||
if(hostValueSet(buffer))
|
||||
return;
|
||||
|
||||
ffStrbufClear(buffer);
|
||||
}
|
||||
|
||||
void ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
ffStrbufInit(&board->error);
|
||||
|
||||
ffStrbufInit(&board->boardName);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->boardName);
|
||||
|
||||
ffStrbufInit(&board->boardVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->boardVendor);
|
||||
|
||||
ffStrbufInit(&board->boardVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->boardVersion);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "board.h"
|
||||
|
||||
void ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
ffStrbufInitS(&board->error, "Not supported on this platform");
|
||||
|
||||
ffStrbufInit(&board->boardName);
|
||||
ffStrbufInit(&board->boardVendor);
|
||||
ffStrbufInit(&board->boardVersion);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
extern "C" {
|
||||
#include "board.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C" void ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
ffStrbufInit(&board->error);
|
||||
|
||||
ffStrbufInit(&board->boardName);
|
||||
ffStrbufInit(&board->boardVendor);
|
||||
ffStrbufInit(&board->boardVersion);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Product, Version, Manufacturer FROM Win32_BaseBoard", &board->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if(uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&board->error, "No Wmi result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"Product", &board->boardName);
|
||||
ffGetWmiObjString(pclsObj, L"Manufacturer", &board->boardVendor);
|
||||
ffGetWmiObjString(pclsObj, L"Version", &board->boardVersion);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
extern "C" {
|
||||
#include "cpu.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C"
|
||||
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if(cached)
|
||||
return;
|
||||
|
||||
cpu->coresPhysical = cpu->coresLogical = cpu->coresOnline = 0;
|
||||
ffStrbufInit(&cpu->name);
|
||||
ffStrbufInit(&cpu->vendor);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3", nullptr);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"Name", &cpu->name);
|
||||
ffGetWmiObjString(pclsObj, L"Manufacturer", &cpu->vendor);
|
||||
|
||||
uint64_t value;
|
||||
|
||||
ffGetWmiObjUnsigned(pclsObj, L"NumberOfCores", &value);
|
||||
cpu->coresPhysical = (uint16_t)value;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"NumberOfLogicalProcessors", &value);
|
||||
cpu->coresLogical = (uint16_t)value;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"ThreadCount", &value);
|
||||
cpu->coresOnline = (uint16_t)value;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor
|
||||
cpu->frequencyMin = (double)value / 1000.0;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"MaxClockSpeed", &value);
|
||||
cpu->frequencyMax = (double)value / 1000.0;
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "fastfetch.h"
|
||||
#include "cpuUsage.h"
|
||||
|
||||
#if FF_DETECTION_CPUUSAGE_NOWAIT
|
||||
|
||||
const char* ffGetCpuUsageResultNoWait(double* result);
|
||||
|
||||
void ffPrepareCPUUsage() {}
|
||||
|
||||
const char* ffGetCpuUsageResult(double* result) {
|
||||
return ffGetCpuUsageResultNoWait(result);
|
||||
}
|
||||
|
||||
#else //FF_DETECTION_CPUUSAGE_NOWAIT
|
||||
|
||||
#include "common/time.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// We need to use uint64_t because sizeof(long) == 4 on Windows
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
|
||||
|
||||
static uint64_t inUseAll1, totalAll1, startTime;
|
||||
|
||||
void ffPrepareCPUUsage()
|
||||
{
|
||||
startTime = ffTimeGetTick();
|
||||
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
}
|
||||
|
||||
const char* ffGetCpuUsageResult(double* result)
|
||||
{
|
||||
const char* error = NULL;
|
||||
if(startTime == 0)
|
||||
{
|
||||
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
if(error)
|
||||
return error;
|
||||
ffTimeSleep(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t duration = ffTimeGetTick() - startTime;
|
||||
if(duration < 1000)
|
||||
ffTimeSleep(1000 - (uint32_t) duration);
|
||||
}
|
||||
|
||||
uint64_t inUseAll2, totalAll2;
|
||||
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif //FF_DETECTION_CPUUSAGE_NOWAIT
|
||||
@@ -3,6 +3,11 @@
|
||||
#ifndef FF_INCLUDED_detection_cpu_cpuUsage
|
||||
#define FF_INCLUDED_detection_cpu_cpuUsage
|
||||
|
||||
const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll);
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
// Disabled by default because the result does need some time to generate
|
||||
#define FF_DETECTION_CPUUSAGE_NOWAIT 0
|
||||
#endif
|
||||
|
||||
const char* ffGetCpuUsageResult(double* result);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <mach/processor_info.h>
|
||||
#include <mach/mach_host.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll)
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
{
|
||||
natural_t numCPUs = 0U;
|
||||
processor_info_array_t cpuInfo;
|
||||
@@ -21,8 +21,8 @@ const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll)
|
||||
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
|
||||
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
|
||||
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
|
||||
*inUseAll += inUse;
|
||||
*totalAll += total;
|
||||
*inUseAll += (uint64_t)inUse;
|
||||
*totalAll += (uint64_t)total;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
#include "cpuUsage.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll)
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
{
|
||||
long user, nice, system, idle, iowait, irq, softirq;
|
||||
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
|
||||
|
||||
FILE* procStat = fopen("/proc/stat", "r");
|
||||
if(procStat == NULL)
|
||||
return "fopen(\"""/proc/stat\", \"r\") == NULL";
|
||||
|
||||
if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
|
||||
if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
|
||||
{
|
||||
fclose(procStat);
|
||||
return "fscanf() failed";
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
extern "C" {
|
||||
#include "cpuUsage.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C" const char* ffGetCpuUsageResultNoWait(double* result)
|
||||
{
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT LoadPercentage FROM Win32_Processor", nullptr);
|
||||
if(!pEnumerator)
|
||||
return "Query WMI service failed";
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
pEnumerator->Release();
|
||||
return "No WMI result returned";
|
||||
}
|
||||
|
||||
ffGetWmiObjReal(pclsObj, L"LoadPercentage", result);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "fastfetch.h"
|
||||
#include "cpuUsage.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
|
||||
return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime);
|
||||
}
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
{
|
||||
FILETIME idleTime, kernelTime, userTime;
|
||||
if(GetSystemTimes(&idleTime, &kernelTime, &userTime) == 0)
|
||||
return "GetSystemTimes() failed";
|
||||
|
||||
*inUseAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
|
||||
*totalAll = *inUseAll + fileTimeToUint64(&idleTime);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "fastfetch.h"
|
||||
#include "disk.h"
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result)
|
||||
{
|
||||
ffStrbufInitS(&result->path, folderPath);
|
||||
result->used = result->total = 0;
|
||||
ffStrbufInit(&result->error);
|
||||
|
||||
struct statvfs newFs;
|
||||
|
||||
if(fs == NULL)
|
||||
{
|
||||
fs = &newFs;
|
||||
int ret = statvfs(folderPath, fs);
|
||||
if(ret != 0)
|
||||
{
|
||||
ffStrbufAppendF(&result->error, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
result->total = fs->f_blocks * fs->f_frsize;
|
||||
|
||||
if(result->total == 0)
|
||||
{
|
||||
ffStrbufAppendF(&result->error, "statvfs for %s returned size 0", folderPath);
|
||||
return;
|
||||
}
|
||||
|
||||
result->used = result->total - (fs->f_bavail * fs->f_frsize);
|
||||
result->files = (uint32_t) (fs->f_files - fs->f_ffree);
|
||||
result->removable = false; //To be set at other place
|
||||
}
|
||||
|
||||
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
|
||||
{
|
||||
ffStrbufTrim(&instance->config.diskFolders, ':');
|
||||
if(instance->config.diskFolders.length == 0)
|
||||
return false;
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < instance->config.diskFolders.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
|
||||
instance->config.diskFolders.chars[colonIndex] = '\0';
|
||||
|
||||
ffDetectDiskWithStatvfs(instance->config.diskFolders.chars + startIndex, NULL, (FFDiskResult*)ffListAdd(folders));
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5,6 +5,17 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFDiskResult
|
||||
{
|
||||
FFstrbuf path;
|
||||
uint64_t used;
|
||||
uint64_t total;
|
||||
uint32_t files;
|
||||
bool removable;
|
||||
FFstrbuf error;
|
||||
} FFDiskResult;
|
||||
|
||||
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders);
|
||||
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
|
||||
|
||||
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
|
||||
{
|
||||
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, nil];
|
||||
@@ -18,7 +20,9 @@ const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
|
||||
if(removable.boolValue && !instance->config.diskRemovable)
|
||||
continue;
|
||||
|
||||
ffStrbufInitS((FFstrbuf *)ffListAdd(folders), [url.relativePath cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
|
||||
ffDetectDiskWithStatvfs([url.relativePath cStringUsingEncoding:NSUTF8StringEncoding], NULL, folder);
|
||||
folder->removable = removable.boolValue;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
|
||||
|
||||
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
@@ -11,12 +13,12 @@ const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
|
||||
if(rootRet != 0)
|
||||
return "statvfs(\"/\") failed";
|
||||
|
||||
ffStrbufInitS((FFstrbuf *)ffListAdd(folders), FASTFETCH_TARGET_DIR_ROOT"/");
|
||||
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot, (FFDiskResult*)ffListAdd(folders));
|
||||
|
||||
struct statvfs fsHome;
|
||||
int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome);
|
||||
if(homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid))
|
||||
ffStrbufInitS((FFstrbuf *)ffListAdd(folders), FASTFETCH_TARGET_DIR_HOME);
|
||||
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome, (FFDiskResult*)ffListAdd(folders));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "disk.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
static void detectDrive(const char* folderPath, uint32_t pathLen, FFDiskResult* result)
|
||||
{
|
||||
ffStrbufInitNS(&result->path, pathLen, folderPath);
|
||||
result->removable = false; //To be set at other place
|
||||
result->files = 0; //Unsupported
|
||||
|
||||
//According to https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexa
|
||||
//GetDiskFreeSpaceExA does not have to specify the root directory on a disk. The function accepts any directory on a disk.
|
||||
uint64_t freeBytes;
|
||||
if(GetDiskFreeSpaceExA(folderPath, NULL, (PULARGE_INTEGER)&result->total, (PULARGE_INTEGER)&freeBytes)) {
|
||||
result->used = result->total - freeBytes;
|
||||
ffStrbufInit(&result->error);
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&result->error, "GetDiskFreeSpaceExA() failed");
|
||||
}
|
||||
|
||||
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
char buf[128]; // "C:\\\0D:\\\0"
|
||||
uint32_t length = GetLogicalDriveStringsA(sizeof(buf) / sizeof(*buf), buf);
|
||||
|
||||
for(size_t i = 0; i < length;)
|
||||
{
|
||||
const char* drive = buf + i;
|
||||
uint32_t driveLen = (uint32_t) strlen(drive);
|
||||
i += driveLen + 1;
|
||||
|
||||
bool removable = GetDriveTypeA(drive) == DRIVE_REMOVABLE;
|
||||
if(removable && !instance->config.diskRemovable)
|
||||
continue;
|
||||
|
||||
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
|
||||
detectDrive(drive, driveLen, folder);
|
||||
folder->removable = removable;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
|
||||
{
|
||||
ffStrbufTrim(&instance->config.diskFolders, ';');
|
||||
if(instance->config.diskFolders.length == 0)
|
||||
return false;
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < instance->config.diskFolders.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ';');
|
||||
instance->config.diskFolders.chars[colonIndex] = '\0';
|
||||
|
||||
detectDrive(instance->config.diskFolders.chars + startIndex, colonIndex - startIndex, (FFDiskResult*)ffListAdd(folders));
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "displayserver.h"
|
||||
#include "detection/os/os.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
#include <WinUser.h>
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
BOOL enabled;
|
||||
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled == TRUE)
|
||||
{
|
||||
ffStrbufInitS(&ds->wmProcessName, "dwm.exe");
|
||||
ffStrbufInitS(&ds->wmPrettyName, "Desktop Window Manager");
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufInitS(&ds->wmProcessName, "internal");
|
||||
ffStrbufInitS(&ds->wmPrettyName, "internal");
|
||||
}
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInit(&ds->resolutions, sizeof(FFResolutionResult));
|
||||
|
||||
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) };
|
||||
for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum)
|
||||
{
|
||||
if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) };
|
||||
if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0)
|
||||
continue;
|
||||
|
||||
ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency);
|
||||
}
|
||||
|
||||
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
|
||||
const FFOSResult* os = ffDetectOS(instance);
|
||||
if(ffStrbufCompS(&os->version, "11") == 0 || ffStrbufCompS(&os->version, "10") == 0)
|
||||
ffStrbufSetS(&ds->dePrettyName, "Fluent");
|
||||
else if(ffStrbufCompS(&os->version, "8") == 0 || ffStrbufStartsWithS(&os->version, "8."))
|
||||
ffStrbufSetS(&ds->dePrettyName, "Metro");
|
||||
else
|
||||
ffStrbufSetS(&ds->dePrettyName, "Aero");
|
||||
}
|
||||
@@ -12,9 +12,10 @@ typedef struct FFFontResult
|
||||
FFstrbuf error;
|
||||
|
||||
/**
|
||||
* Linux / BSD: QT, GTK2, GTK3, GTK4
|
||||
* MacOS: System, User, Monospace, Application
|
||||
* Other: Unset, Unset, Unset, Unset
|
||||
* Linux / BSD: QT, GTK2, GTK3, GTK4
|
||||
* MacOS: System, User, Monospace, Application
|
||||
* Windows: Desktop, Unset, Unset, Unset
|
||||
* Other: Unset, Unset, Unset, Unset
|
||||
*/
|
||||
FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS];
|
||||
} FFFontResult;
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
ffStrbufAppendS(&result->error, "Not implemented");
|
||||
ffStrbufAppendS(&result->error, "Not supported on this platform");
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
extern "C" {
|
||||
#include "font.h"
|
||||
#include "common/font.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
extern "C"
|
||||
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
{
|
||||
wchar_t query[256] = {};
|
||||
swprintf(query, 256, L"SELECT IconTitleFaceName, IconTitleSize FROM Win32_Desktop WHERE Name LIKE '%%\\\\%s'", instance->state.passwd->pw_name);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, &result->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if(uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&result->error, "No WMI result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf fontName;
|
||||
ffStrbufInit(&fontName);
|
||||
ffGetWmiObjString(pclsObj, L"IconTitleFaceName", &fontName);
|
||||
|
||||
uint64_t fontSize;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"IconTitleSize", &fontSize);
|
||||
|
||||
ffStrbufAppendF(&result->fonts[0], "%*s (%upt)", fontName.length, fontName.chars, (unsigned)fontSize);
|
||||
|
||||
ffStrbufDestroy(&fontName);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -3,5 +3,5 @@
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(gpus, instance);
|
||||
return "Unimplemented";
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
extern "C" {
|
||||
#include "gpu.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr);
|
||||
|
||||
if(!pEnumerator)
|
||||
return "Query WMI service failed";
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
|
||||
{
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffGetWmiObjString(pclsObj, L"AdapterCompatibility", &gpu->vendor);
|
||||
if(ffStrbufStartsWithS(&gpu->vendor, "Intel "))
|
||||
{
|
||||
//Intel returns "Intel Corporation", not sure about AMD
|
||||
ffStrbufSetS(&gpu->vendor, "Intel");
|
||||
}
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffGetWmiObjString(pclsObj, L"Name", &gpu->name);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffGetWmiObjString(pclsObj, L"DriverVersion", &gpu->driver);
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
}
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux"
|
||||
#define FF_HOST_PRODUCT_NAME_MSYS "Windows on MSYS"
|
||||
|
||||
typedef struct FFHostResult
|
||||
{
|
||||
@@ -13,17 +14,11 @@ typedef struct FFHostResult
|
||||
FFstrbuf productName;
|
||||
FFstrbuf productVersion;
|
||||
FFstrbuf productSku;
|
||||
FFstrbuf biosDate;
|
||||
FFstrbuf biosRelease;
|
||||
FFstrbuf biosVendor;
|
||||
FFstrbuf biosVersion;
|
||||
FFstrbuf boardName;
|
||||
FFstrbuf boardVendor;
|
||||
FFstrbuf boardVersion;
|
||||
FFstrbuf chassisType;
|
||||
FFstrbuf chassisVendor;
|
||||
FFstrbuf chassisVersion;
|
||||
FFstrbuf sysVendor;
|
||||
FFstrbuf error;
|
||||
} FFHostResult;
|
||||
|
||||
const FFHostResult* ffDetectHost();
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->error);
|
||||
|
||||
//Family
|
||||
|
||||
ffStrbufInit(&host->productFamily);
|
||||
@@ -32,13 +34,6 @@ void ffDetectHostImpl(FFHostResult* host)
|
||||
|
||||
ffStrbufInitA(&host->productVersion, 0);
|
||||
ffStrbufInitA(&host->productSku, 0);
|
||||
ffStrbufInitA(&host->biosDate, 0);
|
||||
ffStrbufInitA(&host->biosRelease, 0);
|
||||
ffStrbufInitA(&host->biosVendor, 0);
|
||||
ffStrbufInitA(&host->biosVersion, 0);
|
||||
ffStrbufInitA(&host->boardName, 0);
|
||||
ffStrbufInitA(&host->boardVendor, 0);
|
||||
ffStrbufInitA(&host->boardVersion, 0);
|
||||
ffStrbufInitA(&host->chassisType, 0);
|
||||
ffStrbufInitA(&host->chassisVendor, 0);
|
||||
ffStrbufInitA(&host->chassisVersion, 0);
|
||||
|
||||
@@ -112,19 +112,14 @@ static const char* getProductName(const FFstrbuf* hwModel)
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->error);
|
||||
|
||||
ffStrbufInit(&host->productName);
|
||||
ffStrbufInit(&host->productFamily);
|
||||
ffStrbufInit(&host->productVersion);
|
||||
ffStrbufInit(&host->productSku);
|
||||
|
||||
ffStrbufInitA(&host->sysVendor, 0);
|
||||
ffStrbufInitA(&host->productVersion, 0);
|
||||
ffStrbufInitA(&host->productSku, 0);
|
||||
ffStrbufInitA(&host->biosDate, 0);
|
||||
ffStrbufInitA(&host->biosRelease, 0);
|
||||
ffStrbufInitA(&host->biosVendor, 0);
|
||||
ffStrbufInitA(&host->biosVersion, 0);
|
||||
ffStrbufInitA(&host->boardName, 0);
|
||||
ffStrbufInitA(&host->boardVendor, 0);
|
||||
ffStrbufInitA(&host->boardVersion, 0);
|
||||
ffStrbufInitA(&host->chassisType, 0);
|
||||
ffStrbufInitA(&host->chassisVendor, 0);
|
||||
ffStrbufInitA(&host->chassisVersion, 0);
|
||||
|
||||
@@ -60,6 +60,8 @@ static void getHostProductName(FFstrbuf* name)
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->error);
|
||||
|
||||
ffStrbufInit(&host->productFamily);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
|
||||
|
||||
@@ -72,27 +74,6 @@ void ffDetectHostImpl(FFHostResult* host)
|
||||
ffStrbufInit(&host->productSku);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
|
||||
|
||||
ffStrbufInit(&host->biosDate);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &host->biosDate);
|
||||
|
||||
ffStrbufInit(&host->biosRelease);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &host->biosRelease);
|
||||
|
||||
ffStrbufInit(&host->biosVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &host->biosVendor);
|
||||
|
||||
ffStrbufInit(&host->biosVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &host->biosVersion);
|
||||
|
||||
ffStrbufInit(&host->boardName);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &host->boardName);
|
||||
|
||||
ffStrbufInit(&host->boardVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &host->boardVendor);
|
||||
|
||||
ffStrbufInit(&host->boardVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &host->boardVersion);
|
||||
|
||||
ffStrbufInit(&host->chassisType);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &host->chassisType);
|
||||
|
||||
@@ -109,10 +90,10 @@ void ffDetectHostImpl(FFHostResult* host)
|
||||
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
|
||||
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
|
||||
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(host->productFamily.length == 0 && host->productName.length == 0 && (
|
||||
getenv("WSLENV") != NULL ||
|
||||
getenv("WSL_DISTRO") != NULL ||
|
||||
getenv("WSL_INTEROP") != NULL
|
||||
)) ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
|
||||
if(host->productFamily.length == 0 && host->productName.length == 0)
|
||||
{
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
|
||||
ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
extern "C" {
|
||||
#include "host.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C" void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->error);
|
||||
|
||||
ffStrbufInit(&host->productName);
|
||||
ffStrbufInit(&host->productFamily);
|
||||
ffStrbufInit(&host->productVersion);
|
||||
ffStrbufInit(&host->productSku);
|
||||
ffStrbufInit(&host->sysVendor);
|
||||
ffStrbufInit(&host->chassisType);
|
||||
ffStrbufInit(&host->chassisVendor);
|
||||
ffStrbufInit(&host->chassisVersion);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Version, SKUNumber, Vendor FROM Win32_ComputerSystemProduct", &host->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if(uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&host->error, "No Wmi result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"Name", &host->productName);
|
||||
ffGetWmiObjString(pclsObj, L"Version", &host->productVersion);
|
||||
ffGetWmiObjString(pclsObj, L"SKUNumber", &host->productSku);
|
||||
ffGetWmiObjString(pclsObj, L"Vendor", &host->sysVendor);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_kernel_kernel
|
||||
#define FF_INCLUDED_detection_kernel_kernel
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFKernelResult
|
||||
{
|
||||
FFstrbuf sysname;
|
||||
FFstrbuf release;
|
||||
FFstrbuf version;
|
||||
FFstrbuf error;
|
||||
} FFKernelResult;
|
||||
|
||||
void ffDetectKernel(FFinstance* instance, FFKernelResult* result);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "kernel.h"
|
||||
|
||||
void ffDetectKernel(FFinstance* instance, FFKernelResult* result)
|
||||
{
|
||||
ffStrbufInit(&result->error);
|
||||
ffStrbufInitS(&result->sysname, instance->state.utsname.sysname);
|
||||
ffStrbufInitS(&result->release, instance->state.utsname.release);
|
||||
ffStrbufInitS(&result->version, instance->state.utsname.version);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
extern "C" {
|
||||
#include "kernel.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C" void ffDetectKernel(FFinstance* instance, FFKernelResult* kernel)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInit(&kernel->error);
|
||||
|
||||
ffStrbufInitS(&kernel->sysname, "Windows_NT");
|
||||
ffStrbufInit(&kernel->release);
|
||||
ffStrbufInit(&kernel->version);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Version FROM Win32_OperatingSystem", &kernel->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&kernel->error, "No WMI result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"Version", &kernel->release);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_localip_localip
|
||||
#define FF_INCLUDED_detection_localip_localip
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFLocalIpResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf addr;
|
||||
bool ipv6;
|
||||
} FFLocalIpResult;
|
||||
|
||||
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "localip.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/socket.h> // FreeBSD needs this for AF_INET
|
||||
#endif
|
||||
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, bool ipv6)
|
||||
{
|
||||
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
ffStrbufInitS(&ip->name, name);
|
||||
ffStrbufInitS(&ip->addr, addr);
|
||||
ip->ipv6 = ipv6;
|
||||
}
|
||||
|
||||
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
{
|
||||
struct ifaddrs* ifAddrStruct = NULL;
|
||||
if(getifaddrs(&ifAddrStruct) < 0)
|
||||
return "getifaddrs(&ifAddrStruct) failed";
|
||||
|
||||
for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
// loop back
|
||||
if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop)
|
||||
continue;
|
||||
|
||||
if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
// IPv4
|
||||
if (!instance->config.localIpShowIpV4)
|
||||
continue;
|
||||
|
||||
struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, false);
|
||||
}
|
||||
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
// IPv6
|
||||
if (!instance->config.localIpShowIpV6)
|
||||
continue;
|
||||
|
||||
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "localip.h"
|
||||
|
||||
static void addNewIp(FFlist* list, const wchar_t* name, const char* addr, bool ipv6)
|
||||
{
|
||||
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
|
||||
int len = (int)wcslen(name);
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, name, len, NULL, 0, NULL, NULL);
|
||||
ffStrbufInitA(&ip->name, (uint32_t)size_needed + 1);
|
||||
WideCharToMultiByte(CP_UTF8, 0, name, len, ip->name.chars, size_needed, NULL, NULL);
|
||||
ip->name.length = (uint32_t)size_needed;
|
||||
ip->name.chars[size_needed] = '\0';
|
||||
|
||||
ffStrbufInitS(&ip->addr, addr);
|
||||
ip->ipv6 = ipv6;
|
||||
}
|
||||
|
||||
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
{
|
||||
IP_ADAPTER_ADDRESSES* adapter_addresses = NULL;
|
||||
|
||||
// Start with a 16 KB buffer and resize if needed -
|
||||
// multiple attempts in case interfaces change while
|
||||
// we are in the middle of querying them.
|
||||
DWORD adapter_addresses_buffer_size = 16 * 1024;
|
||||
for (int attempts = 0; attempts != 3; ++attempts)
|
||||
{
|
||||
adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size);
|
||||
assert(adapter_addresses);
|
||||
|
||||
DWORD error = GetAdaptersAddresses(
|
||||
AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
adapter_addresses,
|
||||
&adapter_addresses_buffer_size);
|
||||
|
||||
if (error == ERROR_SUCCESS)
|
||||
break;
|
||||
else if (ERROR_BUFFER_OVERFLOW == error)
|
||||
continue;
|
||||
else
|
||||
return "GetAdaptersAddresses() failed";
|
||||
}
|
||||
|
||||
// Iterate through all of the adapters
|
||||
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
|
||||
{
|
||||
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK && !instance->config.localIpShowLoop)
|
||||
continue;
|
||||
|
||||
for (IP_ADAPTER_UNICAST_ADDRESS* ifa = adapter->FirstUnicastAddress; ifa; ifa = ifa->Next)
|
||||
{
|
||||
if (ifa->Address.lpSockaddr->sa_family == AF_INET)
|
||||
{
|
||||
// IPv4
|
||||
if (!instance->config.localIpShowIpV4)
|
||||
continue;
|
||||
|
||||
SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, adapter->FriendlyName, addressBuffer, false);
|
||||
}
|
||||
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
|
||||
{
|
||||
// IPv6
|
||||
if (!instance->config.localIpShowIpV6)
|
||||
continue;
|
||||
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, adapter->FriendlyName, addressBuffer, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(adapter_addresses);
|
||||
return NULL;
|
||||
}
|
||||
@@ -3,5 +3,5 @@
|
||||
void ffDetectMediaImpl(const FFinstance* instance, FFMediaResult* media)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
ffStrbufAppendS(&media->error, "Media not supported on Android");
|
||||
ffStrbufAppendS(&media->error, "Not supported on this platform");
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
extern "C" {
|
||||
#include "memory.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
void detectRam(FFMemoryStorage* ram)
|
||||
{
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem", &ram->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&ram->error, "No WMI result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
//KB
|
||||
ffGetWmiObjUnsigned(pclsObj, L"TotalVisibleMemorySize", &ram->bytesTotal);
|
||||
uint64_t bytesFree;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"FreePhysicalMemory", &bytesFree);
|
||||
ram->bytesUsed = ram->bytesTotal - bytesFree;
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
|
||||
ram->bytesTotal *= 1024;
|
||||
ram->bytesUsed *= 1024;
|
||||
}
|
||||
|
||||
void detectSwap(FFMemoryStorage* swap)
|
||||
{
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT AllocatedBaseSize, CurrentUsage FROM Win32_PageFileUsage", &swap->error);
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
ffStrbufInitS(&swap->error, "No WMI result returned");
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
//MB
|
||||
ffGetWmiObjUnsigned(pclsObj, L"AllocatedBaseSize", &swap->bytesTotal);
|
||||
ffGetWmiObjUnsigned(pclsObj, L"CurrentUsage", &swap->bytesUsed);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
|
||||
swap->bytesTotal *= 1024 * 1024;
|
||||
swap->bytesUsed *= 1024 * 1024;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void ffDetectMemoryImpl(FFMemoryResult* memory)
|
||||
{
|
||||
detectRam(&memory->ram);
|
||||
detectSwap(&memory->swap);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_opengl_opengl
|
||||
#define FF_INCLUDED_detection_opengl_opengl
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFOpenGLResult
|
||||
{
|
||||
FFstrbuf version;
|
||||
FFstrbuf renderer;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf slv;
|
||||
} FFOpenGLResult;
|
||||
|
||||
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "opengl.h"
|
||||
|
||||
#define GL_SILENCE_DEPRECATION
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/OpenGL.h> // This brings in CGL, not GL
|
||||
|
||||
static const char* glHandleResult(FFOpenGLResult* result)
|
||||
{
|
||||
ffStrbufAppendS(&result->version, (const char*) glGetString(GL_VERSION));
|
||||
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));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* cglHandleContext(FFOpenGLResult* result, CGLContextObj context)
|
||||
{
|
||||
if(CGLSetCurrentContext(context) != kCGLNoError)
|
||||
return "CGLSetCurrentContext() failed";
|
||||
|
||||
return glHandleResult(result);
|
||||
}
|
||||
|
||||
static const char* cglHandlePixelFormat(FFOpenGLResult* result, CGLPixelFormatObj pixelFormat)
|
||||
{
|
||||
CGLContextObj context;
|
||||
|
||||
if(CGLCreateContext(pixelFormat, NULL, &context) != kCGLNoError)
|
||||
return "CGLCreateContext() failed";
|
||||
|
||||
const char* error = cglHandleContext(result, context);
|
||||
CGLDestroyContext(context);
|
||||
return error;
|
||||
}
|
||||
|
||||
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
CGLPixelFormatObj pixelFormat;
|
||||
CGLPixelFormatAttribute attrs[] = {
|
||||
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
|
||||
kCGLPFAAccelerated,
|
||||
0
|
||||
};
|
||||
|
||||
GLint num;
|
||||
if (CGLChoosePixelFormat(attrs, &pixelFormat, &num) != kCGLNoError)
|
||||
return "CGLChoosePixelFormat() failed";
|
||||
|
||||
const char* error = cglHandlePixelFormat(result, pixelFormat);
|
||||
CGLDestroyPixelFormat(pixelFormat);
|
||||
return error;
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
#include "fastfetch.h"
|
||||
#include "opengl.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
|
||||
#define FF_HAVE_GL 1
|
||||
|
||||
#include "common/library.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#define FF_OPENGL_BUFFER_WIDTH 1
|
||||
#define FF_OPENGL_BUFFER_HEIGHT 1
|
||||
|
||||
typedef struct GLData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
} GLData;
|
||||
|
||||
static const char* glHandleResult(FFOpenGLResult* result, const GLData* data)
|
||||
{
|
||||
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));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_GL
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
#include <EGL/egl.h>
|
||||
|
||||
typedef struct EGLData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(eglGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(eglGetDisplay)
|
||||
FF_LIBRARY_SYMBOL(eglInitialize)
|
||||
FF_LIBRARY_SYMBOL(eglBindAPI)
|
||||
FF_LIBRARY_SYMBOL(eglGetConfigs)
|
||||
FF_LIBRARY_SYMBOL(eglCreatePbufferSurface)
|
||||
FF_LIBRARY_SYMBOL(eglCreateContext)
|
||||
FF_LIBRARY_SYMBOL(eglMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(eglDestroyContext)
|
||||
FF_LIBRARY_SYMBOL(eglDestroySurface)
|
||||
FF_LIBRARY_SYMBOL(eglTerminate)
|
||||
|
||||
EGLDisplay display;
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
} EGLData;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
|
||||
if(data->context == EGL_NO_CONTEXT)
|
||||
return "eglCreateContext returned EGL_NO_CONTEXT";
|
||||
|
||||
const char* error = eglHandleContext(result, data);
|
||||
data->ffeglDestroyContext(data->display, data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
if(data->ffeglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
|
||||
return "eglBindAPI returned EGL_FALSE";
|
||||
|
||||
EGLint eglConfigCount;
|
||||
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
|
||||
if(eglConfigCount == 0)
|
||||
return "eglGetConfigs returned 0 configs";
|
||||
|
||||
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
|
||||
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
|
||||
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
if(data->surface == EGL_NO_SURFACE)
|
||||
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
|
||||
|
||||
const char* error = eglHandleSurface(result, data);
|
||||
data->ffeglDestroySurface(data->display, data->surface);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffeglGetProcAddress("glGetString");
|
||||
if(!data->glData.ffglGetString)
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(data->display == EGL_NO_DISPLAY)
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
|
||||
EGLint major, minor;
|
||||
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
|
||||
return "eglInitialize returned EGL_FALSE";
|
||||
|
||||
const char* error = eglHandleDisplay(result, data);
|
||||
data->ffeglTerminate(data->display);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglPrint(FFinstance* instance, FFOpenGLResult* result)
|
||||
{
|
||||
EGLData eglData;
|
||||
|
||||
FF_LIBRARY_LOAD(egl, &instance->config.libEGL, "dlopen egl failed", "libEGL.so", 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglBindAPI);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetConfigs);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreatePbufferSurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroyContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
|
||||
|
||||
const char* error = eglHandleData(result, &eglData);
|
||||
dlclose(egl);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_EGL
|
||||
|
||||
#ifdef FF_HAVE_GLX
|
||||
#include <GL/glx.h>
|
||||
|
||||
typedef struct GLXData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(glXGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(XOpenDisplay)
|
||||
FF_LIBRARY_SYMBOL(glXChooseVisual)
|
||||
FF_LIBRARY_SYMBOL(XCreatePixmap);
|
||||
FF_LIBRARY_SYMBOL(glXCreateGLXPixmap)
|
||||
FF_LIBRARY_SYMBOL(glXCreateContext)
|
||||
FF_LIBRARY_SYMBOL(glXMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(glXDestroyContext)
|
||||
FF_LIBRARY_SYMBOL(glXDestroyGLXPixmap)
|
||||
FF_LIBRARY_SYMBOL(XFreePixmap)
|
||||
FF_LIBRARY_SYMBOL(XCloseDisplay)
|
||||
|
||||
Display* display;
|
||||
XVisualInfo* visualInfo;
|
||||
Pixmap pixmap;
|
||||
GLXPixmap glxPixmap;
|
||||
GLXContext context;
|
||||
} GLXData;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static const char* glxHandleGLXPixmap(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
data->context = data->ffglXCreateContext(data->display, data->visualInfo, NULL, True);
|
||||
if(data->context == NULL)
|
||||
return "glXCreateContext returned NULL";
|
||||
|
||||
const char* error = glxHandleContext(result, data);
|
||||
data->ffglXDestroyContext(data->display, data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxHandlePixmap(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
data->glxPixmap = data->ffglXCreateGLXPixmap(data->display, data->visualInfo, data->pixmap);
|
||||
if(data->glxPixmap == None)
|
||||
return "glXCreateGLXPixmap returned None";
|
||||
|
||||
const char* error = glxHandleGLXPixmap(result, data);
|
||||
data->ffglXDestroyGLXPixmap(data->display, data->glxPixmap);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxHandleVisualInfo(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
data->pixmap = data->ffXCreatePixmap(data->display, DefaultRootWindow(data->display), FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, (unsigned int) data->visualInfo->depth);
|
||||
if(data->pixmap == None)
|
||||
return "XCreatePixmap returned None";
|
||||
|
||||
const char* error = glxHandlePixmap(result, data);
|
||||
data->ffXFreePixmap(data->display, data->pixmap);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxHandleDisplay(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
data->visualInfo = data->ffglXChooseVisual(data->display, DefaultScreen(data->display), (int[]){None});
|
||||
if(data->visualInfo == NULL)
|
||||
return "glXChooseVisual returned NULL";
|
||||
|
||||
return glxHandleVisualInfo(result, data);
|
||||
}
|
||||
|
||||
static const char* glxHandleData(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
|
||||
if(data->glData.ffglGetString == NULL)
|
||||
return "glXGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffXOpenDisplay(NULL);
|
||||
if(data->display == NULL)
|
||||
return "XOpenDisplay returned NULL";
|
||||
|
||||
const char* error = glxHandleDisplay(result, data);
|
||||
data->ffXCloseDisplay(data->display);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxPrint(FFinstance* instance, FFOpenGLResult* result)
|
||||
{
|
||||
GLXData data;
|
||||
|
||||
FF_LIBRARY_LOAD(glx, &instance->config.libGLX, "dlopen glx failed", "libGLX.so", 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXChooseVisual);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCreatePixmap);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXCreateGLXPixmap);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXDestroyContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXDestroyGLXPixmap);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFreePixmap);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCloseDisplay);
|
||||
|
||||
const char* error = glxHandleData(result, &data);
|
||||
dlclose(glx);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_GLX
|
||||
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
#include <GL/osmesa.h>
|
||||
|
||||
typedef struct OSMesaData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(OSMesaGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(OSMesaCreateContext)
|
||||
FF_LIBRARY_SYMBOL(OSMesaMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(OSMesaDestroyContext)
|
||||
|
||||
OSMesaContext context;
|
||||
} OSMesaData;
|
||||
|
||||
static const char* osMesaHandleContext(FFOpenGLResult* result, OSMesaData* data)
|
||||
{
|
||||
unsigned char buffer[FF_OPENGL_BUFFER_WIDTH * FF_OPENGL_BUFFER_HEIGHT * sizeof(uint32_t)]; // 4 bytes per pixel (RGBA)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static const char* osMesaHandleData(FFOpenGLResult* result, OSMesaData* data)
|
||||
{
|
||||
//The case to void* is required here, because OSMESAproc can't be cast to (__typeof__(data->glData.ffglGetString)) without a warning, even though it is the actual type.
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) (void*) data->ffOSMesaGetProcAddress("glGetString");
|
||||
if(data->glData.ffglGetString == NULL)
|
||||
return "OSMesaGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->context = data->ffOSMesaCreateContext(OSMESA_RGBA, NULL);
|
||||
if(data->context == NULL)
|
||||
return "OSMesaCreateContext returned NULL";
|
||||
|
||||
const char* error = osMesaHandleContext(result, data);
|
||||
data->ffOSMesaDestroyContext(data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* osMesaPrint(FFinstance* instance, FFOpenGLResult* result)
|
||||
{
|
||||
OSMesaData data;
|
||||
|
||||
FF_LIBRARY_LOAD(osmesa, &instance->config.libOSMesa, "dlopen osmesa failed", "libOSMesa.so", 8);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaDestroyContext);
|
||||
|
||||
const char* error = osMesaHandleData(result, &data);
|
||||
dlclose(osmesa);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_OSMESA
|
||||
|
||||
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result)
|
||||
{
|
||||
#if FF_HAVE_GL
|
||||
|
||||
if(instance->config.glType == FF_GL_TYPE_GLX)
|
||||
{
|
||||
#ifdef FF_HAVE_GLX
|
||||
return glxPrint(instance, result);
|
||||
#else
|
||||
return "fastfetch was compiled without glx support";
|
||||
#endif
|
||||
}
|
||||
|
||||
if(instance->config.glType == FF_GL_TYPE_EGL)
|
||||
{
|
||||
#ifdef FF_HAVE_EGL
|
||||
return eglPrint(instance, result);
|
||||
#else
|
||||
return "fastfetch was compiled without egl support";
|
||||
#endif
|
||||
}
|
||||
|
||||
if(instance->config.glType == FF_GL_TYPE_OSMESA)
|
||||
{
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
return osMesaPrint(instance, result);
|
||||
#else
|
||||
return "fastfetch was compiled without osmesa support";
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* error = ""; // not NULL dummy value
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
error = eglPrint(instance, result);
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_GLX
|
||||
if(error != NULL)
|
||||
error = glxPrint(instance, result);
|
||||
#endif
|
||||
|
||||
//We don't use osmesa in auto mode here, because it is a software implementation,
|
||||
//that doesn't reflect the opengl supported by the hardware
|
||||
|
||||
return error;
|
||||
|
||||
#else
|
||||
|
||||
FF_UNUSED(instance, result);
|
||||
return "Fastfetch was built without gl support.";
|
||||
|
||||
#endif //FF_HAVE_GL
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "opengl.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
#include <GL/gl.h>
|
||||
#ifndef GL_SHADING_LANGUAGE_VERSION // For WGL
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#endif
|
||||
|
||||
static const char* glHandleResult(FFOpenGLResult* result)
|
||||
{
|
||||
ffStrbufAppendS(&result->version, (const char*) glGetString(GL_VERSION));
|
||||
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));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* wglHandleContext(FFOpenGLResult* result, HDC hdc, HGLRC context)
|
||||
{
|
||||
if(wglMakeCurrent(hdc, context) == FALSE)
|
||||
return "wglMakeCurrent() failed";
|
||||
return glHandleResult(result);
|
||||
}
|
||||
|
||||
const char* wglHandlePixelFormat(FFOpenGLResult* result, HWND hWnd)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
1,
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
|
||||
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
|
||||
32, // Colordepth of the framebuffer.
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
24, // Number of bits for the depthbuffer
|
||||
8, // Number of bits for the stencilbuffer
|
||||
0, // Number of Aux buffers in the framebuffer.
|
||||
PFD_MAIN_PLANE,
|
||||
0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
HDC hdc = GetDC(hWnd);
|
||||
|
||||
if(SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd) == FALSE)
|
||||
return "SetPixelFormat() failed";
|
||||
|
||||
HGLRC context = wglCreateContext(hdc);
|
||||
if(context == NULL)
|
||||
return "wglCreateContext() failed";
|
||||
|
||||
const char* error = wglHandleContext(result, hdc, context);
|
||||
wglDeleteContext(context);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
typedef struct WGLData
|
||||
{
|
||||
FFOpenGLResult* result;
|
||||
const char* error;
|
||||
} WGLData;
|
||||
|
||||
LRESULT CALLBACK wglHandleWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(message)
|
||||
{
|
||||
case WM_CREATE: {
|
||||
WGLData* wglData = (WGLData*)((CREATESTRUCT*)lParam)->lpCreateParams;
|
||||
wglData->error = wglHandlePixelFormat(wglData->result, hWnd);
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
MSG msg = {0};
|
||||
WNDCLASSW wc = {
|
||||
.lpfnWndProc = wglHandleWndProc,
|
||||
.hInstance = NULL,
|
||||
.hbrBackground = (HBRUSH)COLOR_BACKGROUND,
|
||||
.lpszClassName = L"ogl_version_check",
|
||||
.style = CS_OWNDC,
|
||||
};
|
||||
if(!RegisterClassW(&wc))
|
||||
return "RegisterClassW() failed";
|
||||
|
||||
WGLData data = { .result = result };
|
||||
HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, 1, 1, NULL, NULL, NULL, &data);
|
||||
|
||||
while(GetMessageW(&msg, hWnd, 0, 0) > 0)
|
||||
DispatchMessage(&msg);
|
||||
|
||||
return data.error;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
extern "C" {
|
||||
#include "os.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C"
|
||||
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
{
|
||||
ffStrbufInit(&os->name);
|
||||
ffStrbufInit(&os->prettyName);
|
||||
ffStrbufInit(&os->id);
|
||||
ffStrbufInit(&os->idLike);
|
||||
ffStrbufInit(&os->variant);
|
||||
ffStrbufInit(&os->variantID);
|
||||
ffStrbufInit(&os->version);
|
||||
ffStrbufInit(&os->versionID);
|
||||
ffStrbufInit(&os->codename);
|
||||
ffStrbufInit(&os->buildID);
|
||||
ffStrbufInit(&os->systemName);
|
||||
ffStrbufInit(&os->architecture);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Caption, Version, BuildNumber, OSArchitecture FROM Win32_OperatingSystem", nullptr);
|
||||
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
pEnumerator->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"Caption", &os->variant); // Microsoft Windows 11 家庭中文版
|
||||
if(ffStrbufStartsWithS(&os->variant, "Microsoft Windows "))
|
||||
{
|
||||
ffStrbufAppendS(&os->name, "Microsoft Windows");
|
||||
ffStrbufAppendS(&os->prettyName, "Windows");
|
||||
|
||||
ffStrbufSubstrAfter(&os->variant, strlen("Microsoft Windows ") - 1); // 11 家庭中文版
|
||||
uint32_t index = ffStrbufFirstIndexC(&os->variant, ' ');
|
||||
ffStrbufAppendNS(&os->version, index, os->variant.chars);
|
||||
ffStrbufSubstrAfter(&os->variant, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown Windows name, please report this
|
||||
ffStrbufAppend(&os->name, &os->variant);
|
||||
ffStrbufClear(&os->variant);
|
||||
}
|
||||
|
||||
if(getenv("MSYSTEM"))
|
||||
ffStrbufAppendS(&os->id, "MSYS2");
|
||||
else
|
||||
ffStrbufAppendF(&os->id, "Windows %*s", os->version.length, os->version.chars);
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"BuildNumber", &os->buildID);
|
||||
ffGetWmiObjString(pclsObj, L"OSArchitecture", &os->architecture);
|
||||
|
||||
#ifdef __MSYS__
|
||||
ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
|
||||
#else
|
||||
ffStrbufSetS(&os->systemName, "Windows");
|
||||
#endif
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_packages_packages
|
||||
#define FF_INCLUDED_detection_packages_packages
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFPackageCounts
|
||||
{
|
||||
uint32_t pacman;
|
||||
uint32_t dpkg;
|
||||
uint32_t rpm;
|
||||
uint32_t emerge;
|
||||
uint32_t xbps;
|
||||
uint32_t nixSystem;
|
||||
uint32_t nixDefault;
|
||||
uint32_t apk;
|
||||
uint32_t pkg;
|
||||
uint32_t flatpak;
|
||||
uint32_t snap;
|
||||
uint32_t brew;
|
||||
uint32_t port;
|
||||
uint32_t scoop;
|
||||
|
||||
FFstrbuf pacmanBranch;
|
||||
|
||||
uint32_t nixUser;
|
||||
} FFPackageCounts;
|
||||
|
||||
void ffDetectPackages(FFinstance* instance, FFPackageCounts* counts);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,448 @@
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/os/os.h"
|
||||
|
||||
#include "packages.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static uint32_t getNumElements(const char* dirname, unsigned char type)
|
||||
{
|
||||
DIR* dirp = opendir(dirname);
|
||||
if(dirp == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t num_elements = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while((entry = readdir(dirp)) != NULL) {
|
||||
if(entry->d_type == type)
|
||||
++num_elements;
|
||||
}
|
||||
|
||||
if(type == DT_DIR)
|
||||
num_elements -= 2; // accounting for . and ..
|
||||
|
||||
closedir(dirp);
|
||||
|
||||
return num_elements;
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
static uint32_t getNumStrings(const char* filename, const char* needle)
|
||||
{
|
||||
FILE* file = fopen(filename, "r");
|
||||
if(file == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t count = 0;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while(getline(&line, &len, file) != EOF)
|
||||
{
|
||||
if(strstr(line, needle) != NULL)
|
||||
++count;
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
|
||||
static uint32_t countFilesRecursive(FFstrbuf* baseDirPath, const char* filename)
|
||||
{
|
||||
uint32_t baseDirPathLength = baseDirPath->length;
|
||||
|
||||
ffStrbufAppendC(baseDirPath, '/');
|
||||
ffStrbufAppendS(baseDirPath, filename);
|
||||
bool exists = ffFileExists(baseDirPath->chars, S_IFREG);
|
||||
ffStrbufSubstrBefore(baseDirPath, baseDirPathLength);
|
||||
if(exists)
|
||||
return 1;
|
||||
|
||||
DIR* dirp = opendir(baseDirPath->chars);
|
||||
if(dirp == NULL)
|
||||
return 0;
|
||||
|
||||
ffStrbufAppendC(baseDirPath, '/');
|
||||
baseDirPathLength = baseDirPath->length;
|
||||
|
||||
uint32_t sum = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while((entry = readdir(dirp)) != NULL) {
|
||||
// According to the PMS, neither category nor package name can begin with '.', so no need to check for . or .. specifically
|
||||
if(entry->d_type != DT_DIR || entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(baseDirPath, entry->d_name);
|
||||
sum += countFilesRecursive(baseDirPath, filename);
|
||||
ffStrbufSubstrBefore(baseDirPath, baseDirPathLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t getNixPackages(char* path)
|
||||
{
|
||||
//Nix detection is kinda slow, so we only do it if the dir exists
|
||||
if(!ffFileExists(path, S_IFDIR))
|
||||
return 0;
|
||||
|
||||
FFstrbuf output;
|
||||
ffStrbufInitA(&output, 128);
|
||||
|
||||
//https://github.com/LinusDierheimer/fastfetch/issues/195#issuecomment-1191748222
|
||||
FFstrbuf command;
|
||||
ffStrbufInitA(&command, 255);
|
||||
ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq");
|
||||
|
||||
ffProcessAppendStdOut(&output, (char* const[]) {
|
||||
"sh",
|
||||
"-c",
|
||||
command.chars,
|
||||
NULL
|
||||
});
|
||||
|
||||
//Each package is a new line in the output. If at least one line is found, add 1 for the last line.
|
||||
uint32_t result = ffStrbufCountC(&output, '\n');
|
||||
if(result > 0)
|
||||
result++;
|
||||
|
||||
ffStrbufDestroy(&output);
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t getXBPS(FFstrbuf* baseDir)
|
||||
{
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type != DT_REG || strncasecmp(entry->d_name, "pkgdb-", 6) != 0)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
result = getNumStrings(baseDir->chars, "<string>installed</string>");
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // !__ANDROID__
|
||||
|
||||
#else // !__APPLE__
|
||||
|
||||
static uint32_t countBrewPackages(FFstrbuf* baseDir)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
ffStrbufAppendS(baseDir, "/Caskroom");
|
||||
result += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
ffStrbufAppendS(baseDir, "/Cellar");
|
||||
result += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t getBrewPackages(FFstrbuf* baseDir)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
const char* prefix = getenv("HOMEBREW_PREFIX");
|
||||
bool prefixSet = ffStrSet(prefix);
|
||||
|
||||
if(prefixSet)
|
||||
{
|
||||
ffStrbufAppendS(baseDir, prefix);
|
||||
result += countBrewPackages(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(baseDir, "/opt/homebrew");
|
||||
if(!prefixSet || strcasecmp(baseDir->chars, prefix) != 0)
|
||||
result += countBrewPackages(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
ffStrbufAppendS(baseDir, "/usr/local");
|
||||
if(!prefixSet || strcasecmp(baseDir->chars, prefix) != 0)
|
||||
result += countBrewPackages(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t countMacPortsPackages(FFstrbuf* baseDir)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
ffStrbufAppendS(baseDir, "/var/macports/software");
|
||||
result += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t getMacPortsPackages(FFstrbuf* baseDir)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
const char* prefix = getenv("MACPORTS_PREFIX");
|
||||
bool prefixSet = ffStrSet(prefix);
|
||||
|
||||
if(prefixSet)
|
||||
{
|
||||
ffStrbufAppendS(baseDir, prefix);
|
||||
result += countMacPortsPackages(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(baseDir, "/opt/local");
|
||||
if(!prefixSet || strcasecmp(baseDir->chars, prefix) != 0)
|
||||
result += countMacPortsPackages(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
#ifdef FF_HAVE_RPM
|
||||
#include "common/library.h"
|
||||
#include <rpm/rpmlib.h>
|
||||
#include <rpm/rpmts.h>
|
||||
#include <rpm/rpmdb.h>
|
||||
#include <rpm/rpmlog.h>
|
||||
|
||||
static uint32_t getRpmFromLibrpm(const FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(rpm, &instance->config.librpm, 0, "librpm.so", 12)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
|
||||
|
||||
// Don't print any error messages
|
||||
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
|
||||
|
||||
if(ffrpmReadConfigFiles(NULL, NULL) != 0)
|
||||
{
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpmts ts = ffrpmtsCreate();
|
||||
if(ts == NULL)
|
||||
{
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0);
|
||||
if(mi == NULL)
|
||||
{
|
||||
ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = ffrpmdbGetIteratorCount(mi);
|
||||
|
||||
ffrpmdbFreeIterator(mi);
|
||||
ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
|
||||
return count > 0 ? (uint32_t) count : 0;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_RPM
|
||||
|
||||
static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, FFPackageCounts* packageCounts)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(__ANDROID__)
|
||||
FF_UNUSED(instance);
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__ //Linux desktop and Android
|
||||
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
//pacman
|
||||
ffStrbufAppendS(baseDir, "/var/lib/pacman/local");
|
||||
packageCounts->pacman += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//dpkg
|
||||
ffStrbufAppendS(baseDir, "/var/lib/dpkg/status");
|
||||
packageCounts->dpkg += getNumStrings(baseDir->chars, "Status: ");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
#ifndef __ANDROID__ //Linux Desktop
|
||||
|
||||
//rpm
|
||||
ffStrbufAppendS(baseDir, "/var/lib/rpm/rmpdb.sqlite");
|
||||
packageCounts->rpm += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(blob) FROM Packages");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//emerge
|
||||
ffStrbufAppendS(baseDir, "/var/db/pkg");
|
||||
packageCounts->emerge += countFilesRecursive(baseDir, "SIZE");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//xps
|
||||
ffStrbufAppendS(baseDir, "/var/db/xbps");
|
||||
packageCounts->xbps += getXBPS(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//nix system
|
||||
ffStrbufAppendS(baseDir, "/run/current-system");
|
||||
packageCounts->nixSystem += getNixPackages(baseDir->chars);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//nix default
|
||||
ffStrbufAppendS(baseDir, "/nix/var/nix/profiles/default");
|
||||
packageCounts->nixDefault += getNixPackages(baseDir->chars);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//apk
|
||||
ffStrbufAppendS(baseDir, "/lib/apk/db/installed");
|
||||
packageCounts->apk += getNumStrings(baseDir->chars, "C:Q");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//flatpak
|
||||
ffStrbufAppendS(baseDir, "/var/lib/flatpak/app");
|
||||
packageCounts->flatpak += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//snap
|
||||
ffStrbufAppendS(baseDir, "/snap");
|
||||
uint32_t snap = getNumElements(baseDir->chars, DT_DIR);
|
||||
if(snap > 0)
|
||||
packageCounts->snap += (snap - 1); //Accounting for the /snap/bin folder
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//pacman branch
|
||||
ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC"/pacman-mirrors.conf");
|
||||
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
|
||||
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
#endif // !__ANDROID__
|
||||
|
||||
#else // !__APPLE__
|
||||
|
||||
//brew
|
||||
packageCounts->brew += getBrewPackages(baseDir);
|
||||
packageCounts->port += getMacPortsPackages(baseDir);
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
ffStrbufAppendS(baseDir, "/var/db/pkg/local.sqlite");
|
||||
packageCounts->pkg += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(id) FROM packages");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
#endif // __FreeBSD__
|
||||
}
|
||||
|
||||
static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDir, FFPackageCounts* packageCounts)
|
||||
{
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
ffStrbufAppendS(baseDir, "/bedrock/strata");
|
||||
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
{
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
getPackageCounts(instance, baseDir, packageCounts);
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
baseDirLength = baseDir->length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
getPackageCounts(instance, baseDir, packageCounts);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef __MSYS__
|
||||
ffDetectPackagesPosix
|
||||
#else
|
||||
ffDetectPackages
|
||||
#endif
|
||||
(FFinstance* instance, FFPackageCounts* counts)
|
||||
{
|
||||
FFstrbuf baseDir;
|
||||
ffStrbufInitA(&baseDir, 512);
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&ffDetectOS(instance)->id, "bedrock") == 0)
|
||||
getPackageCountsBedrock(instance, &baseDir, counts);
|
||||
else
|
||||
getPackageCounts(instance, &baseDir, counts);
|
||||
|
||||
// If SQL failed, we can still try with librpm.
|
||||
// This is needed on openSUSE, which seems to use a proprietary database file
|
||||
// This method doesn't work on bedrock, so we do it here.
|
||||
#ifdef FF_HAVE_RPM
|
||||
if(counts->rpm == 0)
|
||||
counts->rpm = getRpmFromLibrpm(instance);
|
||||
#endif
|
||||
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
//nix user
|
||||
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
|
||||
ffStrbufAppendS(&baseDir, "/.nix-profile");
|
||||
counts->nixUser = getNixPackages(baseDir.chars);
|
||||
#endif
|
||||
|
||||
ffStrbufDestroy(&baseDir);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "packages.h"
|
||||
|
||||
#include <handleapi.h>
|
||||
#include <fileapi.h>
|
||||
|
||||
static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
WIN32_FIND_DATAA wfd;
|
||||
HANDLE hFind = FindFirstFileA(searchPath, &wfd);
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do // Managed to locate and create an handle to that folder.
|
||||
{
|
||||
if(wfd.dwFileAttributes & type)
|
||||
counter++;
|
||||
} while (FindNextFileA(hFind, &wfd) == TRUE);
|
||||
FindClose(hFind);
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
#ifdef __MSYS__
|
||||
void ffDetectPackagesPosix(const FFinstance* instance, FFPackageCounts* counts);
|
||||
#endif
|
||||
|
||||
void ffDetectPackages(FFinstance* instance, FFPackageCounts* counts)
|
||||
{
|
||||
#ifdef __MSYS__
|
||||
//We have pacman and maybe others in MSYS, but not package managers for Windows
|
||||
if(getenv("MSYSTEM"))
|
||||
return ffDetectPackagesPosix(instance, counts);
|
||||
#endif
|
||||
|
||||
FFstrbuf scoopPath;
|
||||
ffStrbufInitF(&scoopPath, "%s/scoop/apps/*", getenv("USERPROFILE"));
|
||||
counts->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY) - 3; // . .. scoop
|
||||
ffStrbufDestroy(&scoopPath);
|
||||
}
|
||||
+1
-1
@@ -3,5 +3,5 @@
|
||||
const char* ffDetectPowerAdapterImpl(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_UNUSED(instance, results);
|
||||
return "Unimplemented";
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_processes_processes
|
||||
#define FF_INCLUDED_detection_processes_processes
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "processes.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
|
||||
size_t length;
|
||||
|
||||
if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0)
|
||||
{
|
||||
ffStrbufAppend(error, "sysctl() failed");
|
||||
return 0;
|
||||
}
|
||||
return (uint32_t)(length / sizeof(struct kinfo_proc));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "processes.h"
|
||||
|
||||
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error)
|
||||
{
|
||||
#if FF_HAVE_SYSINFO_H
|
||||
FF_UNUSED(error);
|
||||
return (uint32_t) instance->state.sysinfo.procs;
|
||||
#else
|
||||
ffStrbufAppendS(error, "Unimplemented");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
extern "C" {
|
||||
#include "processes.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT NumberOfProcesses FROM Win32_OperatingSystem", error);
|
||||
|
||||
if(!pEnumerator)
|
||||
return 0;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
ffStrbufAppendS(error, "No Wmi result returned");
|
||||
pEnumerator->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t result = 0;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"NumberOfProcesses", &result);
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
return (uint32_t)result;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "common/properties.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/internal.h"
|
||||
#include "detection/terminalshell.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
|
||||
static void detectAlacritty(const FFinstance* instance, FFTerminalFontResult* terminalFont) {
|
||||
FFstrbuf fontName;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "terminalfont.h"
|
||||
#include "detection/terminalshell.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "terminalfont.h"
|
||||
#include "common/font.h"
|
||||
#include "detection/terminalshell.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "util/apple/osascript.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "common/settings.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/terminalshell.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
static const char* getSystemMonospaceFont(const FFinstance* instance)
|
||||
@@ -189,7 +189,7 @@ static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* conten
|
||||
{
|
||||
CJSONData cjsonData;
|
||||
|
||||
FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson failed", "libcjson"FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive)
|
||||
@@ -292,12 +292,17 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFon
|
||||
FFstrbuf name;
|
||||
ffStrbufInit(&name);
|
||||
int size = -1;
|
||||
detectFromWTImpl(instance, &json, &name, &size);
|
||||
error = detectFromWTImpl(instance, &json, &name, &size);
|
||||
ffStrbufDestroy(&json);
|
||||
|
||||
char sizeStr[16];
|
||||
snprintf(sizeStr, sizeof(sizeStr), "%d", size);
|
||||
ffFontInitValues(&terminalFont->font, name.chars, sizeStr);
|
||||
if(error)
|
||||
ffStrbufAppendS(&terminalFont->error, error);
|
||||
else
|
||||
{
|
||||
char sizeStr[16];
|
||||
snprintf(sizeStr, sizeof(sizeStr), "%d", size);
|
||||
ffFontInitValues(&terminalFont->font, name.chars, sizeStr);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&name);
|
||||
}
|
||||
@@ -312,6 +317,82 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFon
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
// TODO: move to a separate file
|
||||
|
||||
static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FFstrbuf fontName;
|
||||
ffStrbufInit(&fontName);
|
||||
|
||||
FFstrbuf fontSize;
|
||||
ffStrbufInit(&fontSize);
|
||||
|
||||
ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) {
|
||||
{"Font=", &fontName},
|
||||
{"FontHeight=", &fontSize}
|
||||
});
|
||||
if(fontName.length == 0)
|
||||
ffStrbufAppendS(&fontName, "Lucida Console");
|
||||
if(fontSize.length == 0)
|
||||
ffStrbufAppendC(&fontSize, '9');
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
|
||||
ffStrbufDestroy(&fontName);
|
||||
ffStrbufDestroy(&fontSize);
|
||||
}
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
//Current font of conhost doesn't seem to be detectable, we detect default font instead
|
||||
|
||||
HKEY hKey;
|
||||
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD bufSize;
|
||||
|
||||
wchar_t fontNameW[64];
|
||||
bufSize = sizeof(fontNameW);
|
||||
if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed");
|
||||
goto exit;
|
||||
}
|
||||
fontNameW[bufSize] = '\0';
|
||||
|
||||
char fontNameA[128];
|
||||
int fontNameALen = WideCharToMultiByte(CP_UTF8, 0, fontNameW, (int)(bufSize / 2), fontNameA, sizeof(fontNameA), NULL, NULL);
|
||||
fontNameA[fontNameALen] = '\0';
|
||||
|
||||
uint32_t fontSizeNum = 0;
|
||||
bufSize = sizeof(fontSizeNum);
|
||||
if(RegQueryValueExW(hKey, L"fontSize", NULL, NULL, (LPBYTE)&fontSizeNum, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
char fontSize[16];
|
||||
snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16));
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontNameA, fontSize);
|
||||
|
||||
exit:
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
#endif //defined(_WIN32) || defined(__MSYS__)
|
||||
|
||||
void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0)
|
||||
@@ -324,6 +405,14 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh
|
||||
detectFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", terminalFont);
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "gnome-terminal-") == 0)
|
||||
detectFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", terminalFont);
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0)
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 ||
|
||||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0)
|
||||
detectFromWindowsTeriminal(instance, terminalFont);
|
||||
|
||||
#if defined(_WIN32) || defined(__MSYS__)
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0)
|
||||
detectMintty(instance, terminalFont);
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0)
|
||||
detectConhost(instance, terminalFont);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@ typedef struct FFTerminalShellResult
|
||||
FFstrbuf shellProcessName;
|
||||
FFstrbuf shellExe;
|
||||
const char* shellExeName; //pointer to a char in shellExe
|
||||
FFstrbuf shellPrettyName;
|
||||
FFstrbuf shellVersion;
|
||||
|
||||
FFstrbuf terminalProcessName;
|
||||
FFstrbuf terminalExe;
|
||||
FFstrbuf terminalPrettyName;
|
||||
const char* terminalExeName; //pointer to a char in terminalExe
|
||||
|
||||
FFstrbuf userShellExe;
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/terminalshell.h"
|
||||
#include "detection/host/host.h"
|
||||
#include "common/io.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/processing.h"
|
||||
#include "terminalshell.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
@@ -12,6 +13,7 @@
|
||||
|
||||
static void setExeName(FFstrbuf* exe, const char** exeName)
|
||||
{
|
||||
assert(exe->length > 0);
|
||||
uint32_t lastSlashIndex = ffStrbufLastIndexC(exe, '/');
|
||||
if(lastSlashIndex < exe->length)
|
||||
*exeName = exe->chars + lastSlashIndex + 1;
|
||||
@@ -19,15 +21,20 @@ static void setExeName(FFstrbuf* exe, const char** exeName)
|
||||
|
||||
static void getProcessInformation(const char* pid, FFstrbuf* processName, FFstrbuf* exe, const char** exeName)
|
||||
{
|
||||
assert(processName->length > 0);
|
||||
|
||||
FFstrbuf cmdlineFilePath;
|
||||
ffStrbufInit(&cmdlineFilePath);
|
||||
ffStrbufAppendS(&cmdlineFilePath, "/proc/");
|
||||
ffStrbufAppendS(&cmdlineFilePath, pid);
|
||||
ffStrbufAppendS(&cmdlineFilePath, "/cmdline");
|
||||
|
||||
ffReadFileBuffer(cmdlineFilePath.chars, exe);
|
||||
ffStrbufSubstrBeforeFirstC(exe, '\0'); //Trim the arguments
|
||||
ffStrbufTrimLeft(exe, '-'); //Happens in TTY
|
||||
ffStrbufClear(exe);
|
||||
if(ffAppendFileBuffer(cmdlineFilePath.chars, exe))
|
||||
{
|
||||
ffStrbufSubstrBeforeFirstC(exe, '\0'); //Trim the arguments
|
||||
ffStrbufTrimLeft(exe, '-'); //Happens in TTY
|
||||
}
|
||||
|
||||
if(exe->length == 0)
|
||||
ffStrbufSet(exe, processName);
|
||||
@@ -93,16 +100,17 @@ static void getTerminalShell(FFTerminalShellResult* result, const char* pid)
|
||||
strcasecmp(name, "ksh") == 0 ||
|
||||
strcasecmp(name, "fish") == 0 ||
|
||||
strcasecmp(name, "dash") == 0 ||
|
||||
strcasecmp(name, "pwsh") == 0 ||
|
||||
strcasecmp(name, "git-shell") == 0
|
||||
) {
|
||||
ffStrbufAppendS(&result->shellProcessName, name);
|
||||
ffStrbufSetS(&result->shellProcessName, name); // prevent from `fishbash`
|
||||
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
|
||||
|
||||
getTerminalShell(result, ppid);
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&result->terminalProcessName, name);
|
||||
ffStrbufSetS(&result->terminalProcessName, name);
|
||||
getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName);
|
||||
}
|
||||
|
||||
@@ -149,17 +157,18 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
getenv("KONSOLE_VERSION") != NULL
|
||||
)) term = "konsole";
|
||||
|
||||
//MacOS
|
||||
//MacOS, mintty
|
||||
if(!ffStrSet(term))
|
||||
term = getenv("TERM_PROGRAM");
|
||||
|
||||
//We are in WSL but not in Windows Terminal
|
||||
if(!ffStrSet(term) && (
|
||||
getenv("WSLENV") != NULL ||
|
||||
getenv("WSL_DISTRO") != NULL ||
|
||||
getenv("WSL_INTEROP") != NULL
|
||||
))
|
||||
if(!ffStrSet(term))
|
||||
{
|
||||
const FFHostResult* host = ffDetectHost();
|
||||
if(ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_WSL) == 0 ||
|
||||
ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_MSYS) == 0) //TODO better WSL or MSYS detection
|
||||
term = "conhost";
|
||||
}
|
||||
|
||||
//Normal Terminal
|
||||
if(!ffStrSet(term))
|
||||
@@ -169,14 +178,19 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
if(!ffStrSet(term) || strcasecmp(term, "linux") == 0)
|
||||
term = ttyname(STDIN_FILENO);
|
||||
|
||||
ffStrbufSetS(&result->terminalProcessName, term);
|
||||
ffStrbufSetS(&result->terminalExe, term);
|
||||
setExeName(&result->terminalExe, &result->terminalExeName);
|
||||
if(ffStrSet(term))
|
||||
{
|
||||
ffStrbufSetS(&result->terminalProcessName, term);
|
||||
ffStrbufSetS(&result->terminalExe, term);
|
||||
setExeName(&result->terminalExe, &result->terminalExeName);
|
||||
}
|
||||
}
|
||||
|
||||
static void getUserShellFromEnv(FFTerminalShellResult* result)
|
||||
{
|
||||
ffStrbufAppendS(&result->userShellExe, getenv("SHELL"));
|
||||
if(result->userShellExe.length == 0)
|
||||
return;
|
||||
setExeName(&result->userShellExe, &result->userShellExeName);
|
||||
|
||||
//If shell detection via processes failed
|
||||
@@ -250,17 +264,24 @@ static void getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf*
|
||||
|
||||
static void getShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
|
||||
{
|
||||
ffStrbufClear(version);
|
||||
if(strcasecmp(exeName, "bash") == 0)
|
||||
getShellVersionBash(exe, version);
|
||||
else if(strcasecmp(exeName, "zsh") == 0)
|
||||
getShellVersionZsh(exe, version);
|
||||
else if(strcasecmp(exeName, "fish") == 0)
|
||||
else if(strcasecmp(exeName, "fish") == 0 || strcasecmp(exeName, "pwsh") == 0)
|
||||
getShellVersionFish(exe, version);
|
||||
else
|
||||
getShellVersionGeneric(exe, exeName, version);
|
||||
}
|
||||
|
||||
const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
|
||||
const FFTerminalShellResult*
|
||||
#if defined(__MSYS__) || defined(_WIN32)
|
||||
ffDetectTerminalShellPosix
|
||||
#else
|
||||
ffDetectTerminalShell
|
||||
#endif
|
||||
(const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
@@ -301,6 +322,14 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
|
||||
else
|
||||
ffStrbufSet(&result.userShellVersion, &result.shellVersion);
|
||||
|
||||
// https://github.com/LinusDierheimer/fastfetch/discussions/280#discussioncomment-3831734
|
||||
ffStrbufInitS(&result.shellPrettyName, result.shellExeName);
|
||||
|
||||
if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
|
||||
ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName);
|
||||
else
|
||||
ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
extern "C" {
|
||||
#include "terminalshell.h"
|
||||
#include "common/processing.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <processthreadsapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
struct ProcessInfo
|
||||
{
|
||||
uint32_t pid;
|
||||
FFstrbuf psName;
|
||||
};
|
||||
|
||||
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe)
|
||||
{
|
||||
wchar_t query[256] = {};
|
||||
swprintf(query, 256, L"SELECT Name, ParentProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId = %" PRIu32, pid);
|
||||
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, nullptr);
|
||||
if(!pEnumerator)
|
||||
return false;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
|
||||
{
|
||||
pEnumerator->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ppid)
|
||||
{
|
||||
uint64_t value;
|
||||
ffGetWmiObjUnsigned(pclsObj, L"ParentProcessId", &value);
|
||||
*ppid = (uint32_t) value;
|
||||
}
|
||||
|
||||
if(pname)
|
||||
ffGetWmiObjString(pclsObj, L"Name", pname);
|
||||
|
||||
if(exe)
|
||||
ffGetWmiObjString(pclsObj, L"ExecutablePath", exe);
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void getShellVersion(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
char* const argv[] = { exe->chars, (char*)"--version", NULL };
|
||||
ffProcessAppendStdOut(version, argv);
|
||||
ffStrbufTrimRight(version, '\n');
|
||||
ffStrbufSubstrAfterLastC(version, ' ');
|
||||
}
|
||||
|
||||
static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
{
|
||||
uint32_t ppid;
|
||||
|
||||
if(!getProcessInfo(pid, &ppid, &result->shellProcessName, &result->shellExe))
|
||||
return 0;
|
||||
result->shellExeName = result->shellExe.chars + ffStrbufLastIndexC(&result->shellExe, '\\') + 1;
|
||||
|
||||
ffStrbufSet(&result->shellPrettyName, &result->shellProcessName);
|
||||
if(ffStrbufEndsWithIgnCaseS(&result->shellPrettyName, ".exe"))
|
||||
ffStrbufSubstrBefore(&result->shellPrettyName, result->shellPrettyName.length - 4);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&result->shellPrettyName, "pwsh") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->shellPrettyName, "PowerShell");
|
||||
getShellVersion(&result->shellExe, &result->shellVersion);
|
||||
}
|
||||
else if(ffStrbufIgnCaseCompS(&result->shellPrettyName, "powershell") == 0)
|
||||
ffStrbufSetS(&result->shellPrettyName, "Windows PowerShell");
|
||||
else if(ffStrbufIgnCaseCompS(&result->shellPrettyName, "cmd") == 0)
|
||||
ffStrbufSetS(&result->shellPrettyName, "Command Prompt");
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
{
|
||||
uint32_t ppid;
|
||||
|
||||
if(!getProcessInfo(pid, &ppid, &result->terminalProcessName, &result->terminalExe))
|
||||
return 0;
|
||||
result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\');
|
||||
|
||||
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
|
||||
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
|
||||
ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&result->terminalPrettyName, "WindowsTerminal") == 0)
|
||||
ffStrbufSetS(&result->terminalPrettyName, "Windows Terminal");
|
||||
else if(ffStrbufIgnCaseCompS(&result->terminalPrettyName, "conhost") == 0)
|
||||
ffStrbufSetS(&result->terminalPrettyName, "Console Window Host");
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
#ifdef __MSYS__
|
||||
extern "C"
|
||||
const FFTerminalShellResult* ffDetectTerminalShellPosix(const FFinstance* instance);
|
||||
#endif
|
||||
|
||||
const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
|
||||
{
|
||||
#ifdef __MSYS__
|
||||
// This is hacky.
|
||||
// When running inside of MSYS2, the real Windows parent process doesn't exist and we must find it in Linux way ( /proc/self/xxx )
|
||||
// When running outside of MSYS2, /proc/self/xxx doesn't exist and we must find it in Windows way
|
||||
if(getenv("MSYSTEM"))
|
||||
return ffDetectTerminalShellPosix(instance);
|
||||
#endif
|
||||
|
||||
static FFTerminalShellResult result;
|
||||
static bool init = false;
|
||||
if(init)
|
||||
return &result;
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.shellProcessName);
|
||||
ffStrbufInitA(&result.shellExe, 128);
|
||||
result.shellExeName = result.shellExe.chars;
|
||||
ffStrbufInit(&result.shellPrettyName);
|
||||
ffStrbufInit(&result.shellVersion);
|
||||
|
||||
ffStrbufInit(&result.terminalProcessName);
|
||||
ffStrbufInitA(&result.terminalExe, 128);
|
||||
result.terminalExeName = result.terminalExe.chars;
|
||||
ffStrbufInit(&result.terminalPrettyName);
|
||||
|
||||
ffStrbufInit(&result.userShellExe);
|
||||
result.userShellExeName = result.userShellExe.chars;
|
||||
ffStrbufInit(&result.userShellVersion);
|
||||
|
||||
uint32_t ppid = GetCurrentProcessId();
|
||||
if(!getProcessInfo(ppid, &ppid, nullptr, nullptr))
|
||||
return &result;
|
||||
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
if(ppid == 0)
|
||||
return &result;
|
||||
|
||||
// TODO: handle nested shells
|
||||
// TODO: handle running without shells ( dblclick exe in Windows Explorer )
|
||||
|
||||
ppid = getTerminalInfo(&result, ppid);
|
||||
if(ppid == 0)
|
||||
return &result;
|
||||
|
||||
return &result;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_users_users
|
||||
#define FF_INCLUDED_detection_users_users
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffDetectUsers(FFlist* users /* List of FFstrbuf */, FFstrbuf* error);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "fastfetch.h"
|
||||
#include "users.h"
|
||||
|
||||
#if FF_HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#else
|
||||
//for Android compatibility
|
||||
#include <utmp.h>
|
||||
#define utmpx utmp
|
||||
#define setutxent setutent
|
||||
#define getutxent getutent
|
||||
#endif
|
||||
|
||||
void ffDetectUsers(FFlist* users, FFstrbuf* error)
|
||||
{
|
||||
struct utmpx* n = NULL;
|
||||
setutxent();
|
||||
|
||||
next:
|
||||
while((n = getutxent()))
|
||||
{
|
||||
if(n->ut_type != USER_PROCESS)
|
||||
continue;
|
||||
|
||||
for(uint32_t i = 0; i < users->length; ++i)
|
||||
{
|
||||
if(ffStrbufCompS((FFstrbuf*)ffListGet(users, i), n->ut_user) == 0)
|
||||
goto next;
|
||||
}
|
||||
|
||||
ffStrbufInitS((FFstrbuf*)ffListAdd(users), n->ut_user);
|
||||
}
|
||||
|
||||
if(users->length == 0)
|
||||
ffStrbufAppendS(error, "Unable to detect users");
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
extern "C" {
|
||||
#include "users.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
void ffDetectUsers(FFlist* users, FFstrbuf* error)
|
||||
{
|
||||
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Antecedent FROM Win32_LoggedOnUser", error);
|
||||
|
||||
if(!pEnumerator)
|
||||
return;
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
next:
|
||||
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
|
||||
{
|
||||
FFstrbuf antecedent;
|
||||
ffStrbufInit(&antecedent);
|
||||
ffGetWmiObjString(pclsObj, L"Antecedent", &antecedent); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME"
|
||||
ffStrbufTrimRight(&antecedent, '"'); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME
|
||||
ffStrbufSubstrAfterFirstC(&antecedent, '"'); // DOMAIN",Name="NAME
|
||||
uint32_t index = ffStrbufFirstIndexC(&antecedent, '"');
|
||||
ffStrbufRemoveSubstr(&antecedent, index, ffStrbufLastIndexC(&antecedent, '"')); // DOMAIN"NAME
|
||||
antecedent.chars[index] = '\\';
|
||||
|
||||
for(uint32_t i = 0; i < users->length; ++i)
|
||||
{
|
||||
if(ffStrbufComp((FFstrbuf*)ffListGet(users, i), &antecedent) == 0)
|
||||
goto next;
|
||||
}
|
||||
|
||||
*(FFstrbuf*)ffListAdd(users) = antecedent;
|
||||
}
|
||||
|
||||
if(users->length == 0)
|
||||
ffStrbufAppendS(error, "Unable to detect users");
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
}
|
||||
@@ -35,7 +35,7 @@ static void applyDriverName(VkPhysicalDeviceDriverProperties* properties, FFstrb
|
||||
|
||||
static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed", "libvulkan"FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed", "libvulkan"FF_LIBRARY_EXTENSION, 2, "vulkan-1"FF_LIBRARY_EXTENSION, -1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkCreateInstance)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkDestroyInstance)
|
||||
|
||||
@@ -224,6 +224,6 @@ bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
|
||||
return detectOpenbox(instance, &wm->dePrettyName, themeOrError);
|
||||
|
||||
ffStrbufAppendS(themeOrError, "Unknown WM: ");
|
||||
ffStrbufAppend(themeOrError, &wm->dePrettyName);
|
||||
ffStrbufAppend(themeOrError, &wm->wmPrettyName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
ffStrbufAppendS(themeOrError, "WM theme detection is not supported on Android");
|
||||
ffStrbufAppendS(themeOrError, "Not supported on this platform");
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "fastfetch.h"
|
||||
#include "wmtheme.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
HKEY hKey;
|
||||
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegOpenKeyExW() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
int SystemUsesLightTheme = 1;
|
||||
DWORD bufSize = sizeof(SystemUsesLightTheme);
|
||||
|
||||
if(RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&SystemUsesLightTheme, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegOpenKeyExW(SystemUsesLightTheme) failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
int AppsUsesLightTheme = 1;
|
||||
bufSize = sizeof(AppsUsesLightTheme);
|
||||
if(RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&AppsUsesLightTheme, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegOpenKeyExW(AppsUseLightTheme) failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark");
|
||||
|
||||
exit:
|
||||
RegCloseKey(hKey);
|
||||
return result;
|
||||
}
|
||||
+30
-9
@@ -71,24 +71,34 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "host-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("host", "{2} {3}", 15,
|
||||
constructAndPrintCommandHelpFormat("host", "{2} {3}", 8,
|
||||
"product family",
|
||||
"product name",
|
||||
"product version",
|
||||
"product sku",
|
||||
"bios date",
|
||||
"bios release",
|
||||
"bios vendor",
|
||||
"bios version",
|
||||
"board name",
|
||||
"board vendor",
|
||||
"board version",
|
||||
"chassis type",
|
||||
"chassis vendor",
|
||||
"chassis version",
|
||||
"sys vendor"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "bios-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("bios", "{2} {3}", 4,
|
||||
"bios date",
|
||||
"bios release",
|
||||
"bios vendor",
|
||||
"bios version"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "board-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("board", "{2} {3}", 3,
|
||||
"board name",
|
||||
"board vendor",
|
||||
"board version"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "kernel-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("kernel", "{2}", 3,
|
||||
@@ -114,7 +124,7 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "packages-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (pkg), {13} (flatpak), {14} (snap), {15} (brew), {16} (port)", 16,
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (pkg), {13} (flatpak), {14} (snap), {15} (brew), {16} (port), {17} (scoop)", 17,
|
||||
"Number of all packages",
|
||||
"Number of pacman packages",
|
||||
"Pacman branch on manjaro",
|
||||
@@ -131,6 +141,7 @@ static inline void printCommandHelp(const char* command)
|
||||
"Number of snap packages",
|
||||
"Number of brew packages",
|
||||
"Number of macports packages"
|
||||
"Number of scoop packages"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "shell-format") == 0)
|
||||
@@ -978,6 +989,12 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.host.outputFormat);
|
||||
else if(strcasecmp(key, "--host-error") == 0)
|
||||
optionParseString(key, value, &instance->config.host.errorFormat);
|
||||
else if(strcasecmp(key, "--bios-key") == 0)
|
||||
optionParseString(key, value, &instance->config.bios.key);
|
||||
else if(strcasecmp(key, "--bios-format") == 0)
|
||||
optionParseString(key, value, &instance->config.bios.outputFormat);
|
||||
else if(strcasecmp(key, "--bios-error") == 0)
|
||||
optionParseString(key, value, &instance->config.bios.errorFormat);
|
||||
else if(strcasecmp(key, "--kernel-key") == 0)
|
||||
optionParseString(key, value, &instance->config.kernel.key);
|
||||
else if(strcasecmp(key, "--kernel-format") == 0)
|
||||
@@ -1367,6 +1384,10 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
|
||||
ffPrintOS(instance);
|
||||
else if(strcasecmp(line, "host") == 0)
|
||||
ffPrintHost(instance);
|
||||
else if(strcasecmp(line, "bios") == 0)
|
||||
ffPrintBios(instance);
|
||||
else if(strcasecmp(line, "board") == 0)
|
||||
ffPrintBoard(instance);
|
||||
else if(strcasecmp(line, "kernel") == 0)
|
||||
ffPrintKernel(instance);
|
||||
else if(strcasecmp(line, "uptime") == 0)
|
||||
|
||||
@@ -94,6 +94,8 @@ typedef struct FFconfig
|
||||
|
||||
FFModuleArgs os;
|
||||
FFModuleArgs host;
|
||||
FFModuleArgs bios;
|
||||
FFModuleArgs board;
|
||||
FFModuleArgs kernel;
|
||||
FFModuleArgs uptime;
|
||||
FFModuleArgs processes;
|
||||
@@ -249,6 +251,8 @@ void ffPrintTitle(FFinstance* instance);
|
||||
void ffPrintSeparator(FFinstance* instance);
|
||||
void ffPrintOS(FFinstance* instance);
|
||||
void ffPrintHost(FFinstance* instance);
|
||||
void ffPrintBios(FFinstance* instance);
|
||||
void ffPrintBoard(FFinstance* instance);
|
||||
void ffPrintKernel(FFinstance* instance);
|
||||
void ffPrintUptime(FFinstance* instance);
|
||||
void ffPrintProcesses(FFinstance* instance);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#define FASTFETCH_TARGET_DIR_INSTALL_SYSCONF "@CMAKE_INSTALL_SYSCONFDIR@"
|
||||
|
||||
#define FASTFETCH_DATATEXT_STRUCTURE "@DATATEXT_STRUCTURE@"
|
||||
#define FASTFETCH_DATATEXT_CONFIG_SYSTEM "@DATATEXT_CONFIG_SYSTEM@" //Requires FASTFETCH_PROJECT_VERSION to be set
|
||||
#define FASTFETCH_DATATEXT_CONFIG_SYSTEM "@DATATEXT_CONFIG_SYSTEM@"
|
||||
#define FASTFETCH_DATATEXT_CONFIG_USER "@DATATEXT_CONFIG_USER@" //Requires FASTFETCH_PROJECT_VERSION and FASTFETCH_DATATEXT_STRUCTURE to be set
|
||||
#define FASTFETCH_DATATEXT_MODULES "@DATATEXT_MODULES@"
|
||||
#define FASTFETCH_DATATEXT_HELP "@DATATEXT_HELP@"
|
||||
|
||||
@@ -22,6 +22,8 @@ int main(int argc, char** argv)
|
||||
ffPrintSeparator(&instance);
|
||||
ffPrintOS(&instance);
|
||||
ffPrintHost(&instance);
|
||||
//ffPrintBios(&instance);
|
||||
//ffPrintBoard(&instance);
|
||||
ffPrintKernel(&instance);
|
||||
ffPrintUptime(&instance);
|
||||
//ffPrintProcesses(&instance);
|
||||
|
||||
@@ -1277,6 +1277,102 @@ static const FFlogo* getLogoMsys2()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoWindows11()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("Windows 11")
|
||||
FF_LOGO_LINES(
|
||||
"$1\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################\n"
|
||||
"################ ################"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"34" //blue
|
||||
)
|
||||
FF_LOGO_COLOR_KEYS("34"); //blue
|
||||
FF_LOGO_COLOR_TITLE("36"); //cyan
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoWindows8()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("Windows 8", "Windows 8.1", "Windows 10")
|
||||
FF_LOGO_LINES(
|
||||
"$1 ..,\n"
|
||||
" ....,,:;+ccllll\n"
|
||||
" ...,,+:; cllllllllllllllllll\n"
|
||||
",cclllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"llllllllllllll lllllllllllllllllll\n"
|
||||
"`'ccllllllllll lllllllllllllllllll\n"
|
||||
" `' \\*:: :ccllllllllllllllll\n"
|
||||
" ````''*::cll\n"
|
||||
" ``"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"36" //cyan
|
||||
)
|
||||
FF_LOGO_COLOR_KEYS("36"); //cyan
|
||||
FF_LOGO_COLOR_TITLE("37"); //white
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoWindows()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("Windows")
|
||||
FF_LOGO_LINES(
|
||||
"$1 ,.=:!!t3Z3z.,\n"
|
||||
" :tt:::tt333EE3\n"
|
||||
"$1 Et:::ztt33EEEL$2 @Ee., ..,\n"
|
||||
"$1 ;tt:::tt333EE7$2 ;EEEEEEttttt33#\n"
|
||||
"$1 :Et:::zt333EEQ.$2 $EEEEEttttt33QL\n"
|
||||
"$1 it::::tt333EEF$2 @EEEEEEttttt33F\n"
|
||||
"$1 ;3=*^```\"*4EEV$2 :EEEEEEttttt33@.\n"
|
||||
"$3 ,.=::::!t=., $1`$2 @EEEEEEtttz33QF\n"
|
||||
"$3 ;::::::::zt33)$2 \"4EEEtttji3P*\n"
|
||||
"$3 :t::::::::tt33.$4:Z3z..$2 ``$4 ,..g.\n"
|
||||
"$3 i::::::::zt33F$4 AEEEtttt::::ztF\n"
|
||||
"$3 ;:::::::::t33V$4 ;EEEttttt::::t3\n"
|
||||
"$3 E::::::::zt33L$4 @EEEtttt::::z3F\n"
|
||||
"$3{3=*^```\"*4E3)$4 ;EEEtttt:::::tZ`\n"
|
||||
"$3 `$4 :EEEEtttt::::z7\n"
|
||||
" \"VEzjt:;;z>*`"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"31", //red
|
||||
"32", //green
|
||||
"34", //blue
|
||||
"33" //yellow
|
||||
)
|
||||
FF_LOGO_COLOR_KEYS("34"); //blue
|
||||
FF_LOGO_COLOR_TITLE("32"); //green
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoNixOS()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -2016,6 +2112,9 @@ GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
getLogoMintSmall,
|
||||
getLogoMintOld,
|
||||
getLogoMsys2,
|
||||
getLogoWindows11,
|
||||
getLogoWindows8,
|
||||
getLogoWindows,
|
||||
getLogoNixOS,
|
||||
getLogoNixOsOld,
|
||||
getLogoNixOsSmall,
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#include "common/io.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/os/os.h"
|
||||
#include "detection/terminalshell.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
#include "detection/bios/bios.h"
|
||||
|
||||
#define FF_BIOS_MODULE_NAME "Bios"
|
||||
#define FF_BIOS_NUM_FORMAT_ARGS 4
|
||||
|
||||
void ffPrintBios(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_BIOS_MODULE_NAME, &instance->config.bios, FF_BIOS_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FFBiosResult result;
|
||||
ffDetectBios(&result);
|
||||
|
||||
if(result.error.length > 0)
|
||||
{
|
||||
ffPrintError(instance, FF_BIOS_MODULE_NAME, 0, &instance->config.bios, "%*s", result.error.length, result.error.chars);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(result.biosRelease.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_BIOS_MODULE_NAME, 0, &instance->config.bios, "bios_release is not set.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ffPrintAndWriteToCache(instance, FF_BIOS_MODULE_NAME, &instance->config.bios, &result.biosRelease, FF_BIOS_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosDate},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosRelease},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosVersion},
|
||||
});
|
||||
|
||||
exit:
|
||||
ffStrbufDestroy(&result.biosDate);
|
||||
ffStrbufDestroy(&result.biosRelease);
|
||||
ffStrbufDestroy(&result.biosVendor);
|
||||
ffStrbufDestroy(&result.biosVersion);
|
||||
ffStrbufDestroy(&result.error);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
#include "detection/board/board.h"
|
||||
|
||||
#define FF_BOARD_MODULE_NAME "Board"
|
||||
#define FF_BOARD_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintBoard(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_BOARD_MODULE_NAME, &instance->config.board, FF_BOARD_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FFBoardResult result;
|
||||
ffDetectBoard(&result);
|
||||
|
||||
if(result.error.length > 0)
|
||||
{
|
||||
ffPrintError(instance, FF_BOARD_MODULE_NAME, 0, &instance->config.board, "%*s", result.error.length, result.error.chars);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(result.boardName.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_BOARD_MODULE_NAME, 0, &instance->config.board, "board_name is not set.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ffPrintAndWriteToCache(instance, FF_BOARD_MODULE_NAME, &instance->config.board, &result.boardName, FF_BOARD_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.boardName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.boardVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.boardVersion},
|
||||
});
|
||||
|
||||
exit:
|
||||
ffStrbufDestroy(&result.boardName);
|
||||
ffStrbufDestroy(&result.boardVendor);
|
||||
ffStrbufDestroy(&result.boardVersion);
|
||||
ffStrbufDestroy(&result.error);
|
||||
}
|
||||
+2
-37
@@ -1,56 +1,21 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/cpuUsage/cpuUsage.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#define FF_CPU_USAGE_MODULE_NAME "CPU Usage"
|
||||
#define FF_CPU_USAGE_NUM_FORMAT_ARGS 1
|
||||
|
||||
time_t getTimeInMs()
|
||||
{
|
||||
struct timeval timeNow;
|
||||
gettimeofday(&timeNow, NULL);
|
||||
return (timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000);
|
||||
}
|
||||
|
||||
static long inUseAll1, totalAll1, startTime;
|
||||
|
||||
void ffPrepareCPUUsage()
|
||||
{
|
||||
startTime = getTimeInMs();
|
||||
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
}
|
||||
|
||||
void ffPrintCPUUsage(FFinstance* instance)
|
||||
{
|
||||
const char* error = NULL;
|
||||
if(startTime == 0)
|
||||
{
|
||||
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
if(error)
|
||||
goto error;
|
||||
nanosleep(&(struct timespec){ 1, 0 }, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t duration = getTimeInMs() - startTime;
|
||||
if(duration < 1000)
|
||||
nanosleep(&(struct timespec){ 0, (1000 - duration) * 1000000L }, NULL);
|
||||
}
|
||||
|
||||
long inUseAll2, totalAll2;
|
||||
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
|
||||
double cpuPercent = 0.0/0.0;
|
||||
const char* error = ffGetCpuUsageResult(&cpuPercent);
|
||||
|
||||
if(error)
|
||||
{
|
||||
error:
|
||||
ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "%s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
double cpuPercent = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||
|
||||
if(instance->config.cpuUsage.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsage.key);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define FF_CURSOR_MODULE_NAME "Cursor"
|
||||
#define FF_CURSOR_NUM_FORMAT_ARGS 2
|
||||
|
||||
#if !(defined(__ANDROID__) || defined(__APPLE__))
|
||||
#if !(defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) || defined(__MSYS__))
|
||||
|
||||
static void printCursor(FFinstance* instance, FFstrbuf* cursorTheme, const FFstrbuf* cursorSize)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ static bool printCursorFromEnv(FFinstance* instance)
|
||||
|
||||
void ffPrintCursor(FFinstance* instance)
|
||||
{
|
||||
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||
#if defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) || defined(__MSYS__)
|
||||
|
||||
FF_UNUSED(instance);
|
||||
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor detection is not supported");
|
||||
|
||||
+32
-67
@@ -8,111 +8,76 @@
|
||||
#define FF_DISK_MODULE_NAME "Disk"
|
||||
#define FF_DISK_NUM_FORMAT_ARGS 4
|
||||
|
||||
static void createKey(FFinstance* instance, const char* folderPath, FFstrbuf* key)
|
||||
static void printFolder(FFinstance* instance, FFDiskResult* folder)
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
|
||||
if(instance->config.disk.key.length == 0)
|
||||
{
|
||||
ffStrbufAppendS(key, FF_DISK_MODULE_NAME);
|
||||
if(folderPath != NULL)
|
||||
ffStrbufAppendF(key, " (%s)", folderPath);
|
||||
ffStrbufAppendF(&key, "%s (%*s)", FF_DISK_MODULE_NAME, folder->path.length, folder->path.chars);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffParseFormatString(key, &instance->config.disk.key, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, folderPath}
|
||||
ffParseFormatString(&key, &instance->config.disk.key, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &folder->path}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void printStatvfs(FFinstance* instance, const FFstrbuf* key, const char* folderPath, struct statvfs* fs)
|
||||
{
|
||||
uint64_t total = fs->f_blocks * fs->f_frsize;
|
||||
|
||||
if(total == 0)
|
||||
{
|
||||
ffPrintErrorString(instance, key->chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs for %s returned size 0", folderPath);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t used = total - (fs->f_bavail * fs->f_frsize);
|
||||
uint32_t files = (uint32_t) (fs->f_files - fs->f_ffree);
|
||||
uint8_t percentage = (uint8_t) ((used / (long double) total) * 100.0);
|
||||
uint8_t percentage = (uint8_t) ((folder->used / (long double) folder->total) * 100.0);
|
||||
|
||||
FFstrbuf usedPretty;
|
||||
ffStrbufInit(&usedPretty);
|
||||
ffParseSize(used, instance->config.binaryPrefixType, &usedPretty);
|
||||
ffParseSize(folder->used, instance->config.binaryPrefixType, &usedPretty);
|
||||
|
||||
FFstrbuf totalPretty;
|
||||
ffStrbufInit(&totalPretty);
|
||||
ffParseSize(total, instance->config.binaryPrefixType, &totalPretty);
|
||||
ffParseSize(folder->total, instance->config.binaryPrefixType, &totalPretty);
|
||||
|
||||
if(instance->config.disk.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, key->chars, 0, NULL);
|
||||
printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, percentage);
|
||||
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
|
||||
printf("%s / %s (%u%%)%s\n", usedPretty.chars, totalPretty.chars, percentage, folder->removable ? " [Removable]" : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, key->chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &percentage},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &files},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &folder->files},
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&key);
|
||||
ffStrbufDestroy(&totalPretty);
|
||||
ffStrbufDestroy(&usedPretty);
|
||||
}
|
||||
|
||||
static void printFolder(FFinstance* instance, const char* folderPath)
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
createKey(instance, folderPath, &key);
|
||||
|
||||
struct statvfs fs;
|
||||
int ret = statvfs(folderPath, &fs);
|
||||
if(ret != 0)
|
||||
{
|
||||
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
|
||||
ffStrbufDestroy(&key);
|
||||
return;
|
||||
}
|
||||
|
||||
printStatvfs(instance, &key, folderPath, &fs);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
|
||||
void ffPrintDisk(FFinstance* instance)
|
||||
{
|
||||
ffStrbufTrim(&instance->config.diskFolders, ':');
|
||||
FFlist folders;
|
||||
ffListInit(&folders, sizeof(FFDiskResult));
|
||||
|
||||
if(instance->config.diskFolders.length == 0)
|
||||
const char* error = NULL;
|
||||
|
||||
if(!ffDiskDetectDiskFolders(instance, &folders))
|
||||
error = ffDiskAutodetectFolders(instance, &folders);
|
||||
|
||||
if(error)
|
||||
{
|
||||
ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", error);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFlist folders;
|
||||
ffListInit(&folders, sizeof(FFstrbuf));
|
||||
const char* error = ffDiskAutodetectFolders(instance, &folders);
|
||||
if(error)
|
||||
ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", error);
|
||||
for(uint32_t i = 0; i < folders.length; ++i)
|
||||
{
|
||||
FFstrbuf* folder = (FFstrbuf*)ffListGet(&folders, i);
|
||||
printFolder(instance, folder->chars);
|
||||
ffStrbufDestroy(folder);
|
||||
FFDiskResult* folder = (FFDiskResult*)ffListGet(&folders, i);
|
||||
printFolder(instance, folder);
|
||||
ffStrbufDestroy(&folder->path);
|
||||
ffStrbufDestroy(&folder->error);
|
||||
}
|
||||
ffListDestroy(&folders);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < instance->config.diskFolders.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
|
||||
instance->config.diskFolders.chars[colonIndex] = '\0';
|
||||
|
||||
printFolder(instance, instance->config.diskFolders.chars + startIndex);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
ffListDestroy(&folders);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,16 @@ static void printFont(const FFFontResult* font)
|
||||
printf("%s [User]", font->fonts[1].chars);
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) || defined(__MSYS__)
|
||||
|
||||
static void printFont(const FFFontResult* font)
|
||||
{
|
||||
if(font->fonts[0].length > 0)
|
||||
{
|
||||
printf("%s [Desktop]", font->fonts[0].chars);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void printFont(const FFFontResult* font)
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
|
||||
FFstrbuf output;
|
||||
ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length);
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
if(gpu->vendor.length > 0 && !ffStrbufStartsWith(&gpu->name, &gpu->vendor))
|
||||
{
|
||||
ffStrbufAppend(&output, &gpu->vendor);
|
||||
ffStrbufAppendC(&output, ' ');
|
||||
|
||||
+7
-8
@@ -4,7 +4,7 @@
|
||||
#include "detection/host/host.h"
|
||||
|
||||
#define FF_HOST_MODULE_NAME "Host"
|
||||
#define FF_HOST_NUM_FORMAT_ARGS 15
|
||||
#define FF_HOST_NUM_FORMAT_ARGS 8
|
||||
|
||||
void ffPrintHost(FFinstance* instance)
|
||||
{
|
||||
@@ -13,6 +13,12 @@ void ffPrintHost(FFinstance* instance)
|
||||
|
||||
const FFHostResult* host = ffDetectHost();
|
||||
|
||||
if(host->error.length > 0)
|
||||
{
|
||||
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "%*s", host->error.length, host->error.chars);
|
||||
return;
|
||||
}
|
||||
|
||||
if(host->productFamily.length == 0 && host->productName.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "neither product_family nor product_name is set by O.E.M.");
|
||||
@@ -38,13 +44,6 @@ void ffPrintHost(FFinstance* instance)
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productSku},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosDate},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosRelease},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisType},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVersion},
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
void ffPrintIcons(FFinstance* instance)
|
||||
{
|
||||
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||
#if defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) || defined(__MSYS__)
|
||||
|
||||
FF_UNUSED(instance);
|
||||
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons detection is not supported");
|
||||
|
||||
+20
-4
@@ -1,22 +1,38 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/kernel/kernel.h"
|
||||
|
||||
#define FF_KERNEL_MODULE_NAME "Kernel"
|
||||
#define FF_KERNEL_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintKernel(FFinstance* instance)
|
||||
{
|
||||
FFKernelResult result;
|
||||
ffDetectKernel(instance, &result);
|
||||
|
||||
if(result.error.length > 0)
|
||||
{
|
||||
ffPrintError(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel, "%*s", result.error.length, result.error.chars);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(instance->config.kernel.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel.key);
|
||||
puts(instance->state.utsname.release);
|
||||
ffStrbufPutTo(&result.release, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel, FF_KERNEL_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.sysname},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.release},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.version}
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.sysname},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.release},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.version}
|
||||
});
|
||||
}
|
||||
|
||||
exit:
|
||||
ffStrbufDestroy(&result.error);
|
||||
ffStrbufDestroy(&result.sysname);
|
||||
ffStrbufDestroy(&result.release);
|
||||
ffStrbufDestroy(&result.version);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "common/properties.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
+50
-74
@@ -1,90 +1,66 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/localip/localip.h"
|
||||
|
||||
#define FF_LOCALIP_MODULE_NAME "Local IP"
|
||||
#define FF_LOCALIP_NUM_FORMAT_ARGS 1
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/socket.h> // FreeBSD needs this for AF_INET
|
||||
#endif
|
||||
|
||||
static void printValue(FFinstance* instance, const char* ifaName, const char* addressBuffer)
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
|
||||
if (instance->config.localIP.key.length == 0)
|
||||
{
|
||||
ffStrbufAppendF(&key, FF_LOCALIP_MODULE_NAME " (%s)", ifaName);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, ifaName}
|
||||
});
|
||||
}
|
||||
|
||||
if (instance->config.localIP.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
|
||||
puts(addressBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, addressBuffer}
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
#define FF_LOCALIP_NUM_FORMAT_ARGS 2
|
||||
|
||||
void ffPrintLocalIp(FFinstance* instance)
|
||||
{
|
||||
struct ifaddrs* ifAddrStruct = NULL;
|
||||
int ret = getifaddrs(&ifAddrStruct);
|
||||
if (ret < 0) {
|
||||
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "getifaddrs(&ifAddrStruct) < 0 (%i)", ret);
|
||||
return;
|
||||
FFlist results;
|
||||
ffListInit(&results, sizeof(FFLocalIpResult));
|
||||
|
||||
const char* error = ffDetectLocalIps(instance, &results);
|
||||
|
||||
if(error)
|
||||
{
|
||||
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "%s", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (struct ifaddrs* ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
if(results.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "Failed to detect any IPs");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// loop back
|
||||
if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop)
|
||||
continue;
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
|
||||
if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
|
||||
continue;
|
||||
for(uint32_t i = 0; i < results.length; ++i)
|
||||
{
|
||||
FFLocalIpResult* ip = (FFLocalIpResult*) ffListGet(&results, i);
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
|
||||
// is a valid IP4 Address
|
||||
if (!instance->config.localIpShowIpV4)
|
||||
continue;
|
||||
|
||||
void* tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
||||
printValue(instance, ifa->ifa_name, addressBuffer);
|
||||
} else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
|
||||
// is a valid IP6 Address
|
||||
if (!instance->config.localIpShowIpV6)
|
||||
continue;
|
||||
|
||||
void* tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
printValue(instance, ifa->ifa_name, addressBuffer);
|
||||
if(instance->config.localIP.key.length == 0)
|
||||
{
|
||||
ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->name}
|
||||
});
|
||||
}
|
||||
|
||||
if(instance->config.localIP.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
|
||||
ffStrbufPutTo(&ip->addr, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->addr},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, ip->ipv6 ? "IPv6" : "IPv4"}
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&ip->name);
|
||||
ffStrbufDestroy(&ip->addr);
|
||||
}
|
||||
|
||||
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
|
||||
ffStrbufDestroy(&key);
|
||||
|
||||
exit:
|
||||
ffListDestroy(&results);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ static const char* printOpenCL(FFinstance* instance)
|
||||
{
|
||||
OpenCLData data;
|
||||
|
||||
FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL.so failed", "libOpenCL.so", 1);
|
||||
FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", "libOpenCL"FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user