diff --git a/CMakeLists.txt b/CMakeLists.txt index d59a68ecf..79e059926 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -302,6 +302,7 @@ endif() if(BSD OR APPLE) list(APPEND LIBFASTFETCH_SRC src/common/sysctl.c + src/detection/disk/disk_bsd.c src/detection/uptime/uptime_bsd.c src/detection/processes/processes_bsd.c ) @@ -310,6 +311,8 @@ endif() if(LINUX OR ANDROID) list(APPEND LIBFASTFETCH_SRC src/detection/cpu/cpu_linux.c + src/detection/cpuUsage/cpuUsage_linux.c + src/detection/disk/disk_linux.c src/detection/memory/memory_linux.c src/detection/processes/processes_linux.c src/detection/swap/swap_linux.c @@ -319,8 +322,6 @@ endif() if(LINUX OR ANDROID OR BSD) list(APPEND LIBFASTFETCH_SRC - src/detection/cpuUsage/cpuUsage_linux.c - src/detection/disk/disk_linux.c src/detection/temps/temps_linux.c src/detection/opengl/opengl_linux.c src/detection/packages/packages_linux.c @@ -331,12 +332,8 @@ 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 src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/wayland.c src/detection/displayserver/linux/xcb.c @@ -351,6 +348,15 @@ if(LINUX OR BSD) ) endif() +if(LINUX) + list(APPEND LIBFASTFETCH_SRC + src/detection/host/host_linux.c + src/detection/bios/bios_linux.c + src/detection/board/board_linux.c + src/detection/battery/battery_linux.c + ) +endif() + if(WIN32) list(APPEND LIBFASTFETCH_SRC src/common/processing_windows.c @@ -418,8 +424,14 @@ endif() if(BSD) list(APPEND LIBFASTFETCH_SRC src/detection/cpu/cpu_bsd.c + src/detection/cpuUsage/cpuUsage_bsd.c src/detection/memory/memory_bsd.c src/detection/swap/swap_bsd.c + src/detection/host/host_bsd.c + + src/detection/battery/battery_nosupport.c + src/detection/bios/bios_nosupport.c + src/detection/board/board_nosupport.c ) endif() diff --git a/README.md b/README.md index df0d96a52..52f99c321 100644 --- a/README.md +++ b/README.md @@ -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, MacOS and Windows 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, FreeBSD, MacOS and Windows are supported. @@ -26,7 +26,7 @@ Fastfetch dynamically loads needed libraries if they are available. On Linux, it The following libraries are used if present at runtime: -### Linux and BSD +### Linux and FreeBSD * [`libpci`](https://github.com/pciutils/pciutils): GPU output. * [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output. @@ -48,7 +48,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 ( Windows, WSL ). +* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ). ### macOS @@ -86,7 +86,7 @@ AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal ##### Package managers ``` -Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop +Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop, Chocolatey ``` ##### WM themes diff --git a/presets/all b/presets/all index a1706f3b1..f68223bb8 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors +--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors diff --git a/src/common/sysctl.c b/src/common/sysctl.c index 30e92383a..4f0f3b65c 100644 --- a/src/common/sysctl.c +++ b/src/common/sysctl.c @@ -2,11 +2,11 @@ #include -void ffSysctlGetString(const char* propName, FFstrbuf* result) +const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { size_t neededLength; if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator - return; + return "sysctlbyname() failed"; ffStrbufEnsureFree(result, (uint32_t) neededLength - 1); @@ -14,6 +14,8 @@ void ffSysctlGetString(const char* propName, FFstrbuf* result) result->length += (uint32_t) neededLength - 1; result->chars[result->length] = '\0'; + + return NULL; } int ffSysctlGetInt(const char* propName, int defaultValue) diff --git a/src/common/sysctl.h b/src/common/sysctl.h index 91e4ad8b6..562e625d5 100644 --- a/src/common/sysctl.h +++ b/src/common/sysctl.h @@ -4,12 +4,14 @@ #define FF_INCLUDED_common_sysctl #include "fastfetch.h" +#include "util/FFcheckmacros.h" + #include #include -void ffSysctlGetString(const char* propName, FFstrbuf* result); -int ffSysctlGetInt(const char* propName, int defaultValue); -int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue); -void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength); +const char* ffSysctlGetString(const char* propName, FFstrbuf* result); +FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue); +FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue); +FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength); #endif diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 46f60b4e6..6f71f1ef6 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -5,7 +5,17 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached) { FF_UNUSED(instance); - cpu->temperature = FF_CPU_TEMP_UNSET; + if (instance->config.cpuTemp) + { + FFstrbuf cpuTemp; + ffStrbufInit(&cpuTemp); + if(ffSysctlGetString("temperature", &cpuTemp)) + cpu->temperature = FF_CPU_TEMP_UNSET; + else + cpu->temperature = ffStrbufToDouble(&cpuTemp); + } + else + cpu->temperature = FF_CPU_TEMP_UNSET; if(cached) return; diff --git a/src/detection/cpuUsage/cpuUsage_bsd.c b/src/detection/cpuUsage/cpuUsage_bsd.c new file mode 100644 index 000000000..d96064fd4 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage_bsd.c @@ -0,0 +1,19 @@ +#include "cpuUsage.h" + +#include +#include +#include + +const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) +{ + // interrupt processing, user processes, system processing, lock spinning, and idling + uint64_t cpTime[5]; + size_t neededLength = sizeof(cpTime); + if(sysctlbyname("kern.cp_time", cpTime, &neededLength, NULL, 0) != 0) + return "sysctlbyname(kern.cp_time) failed"; + + *inUseAll = cpTime[0] + cpTime[1] + cpTime[2] + cpTime[3]; + *totalAll = *inUseAll + cpTime[4]; + + return NULL; +} diff --git a/src/detection/disk/disk_apple.m b/src/detection/disk/disk_apple.m index 42c2e6a26..b2f7cec08 100644 --- a/src/detection/disk/disk_apple.m +++ b/src/detection/disk/disk_apple.m @@ -1,61 +1,17 @@ #include "disk.h" -#include +#include #import -#import -void ffDetectDisksImpl(FFDiskResult* disks) +void detectFsInfo(struct statfs* fs, FFDisk* disk) { - NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, nil]; - NSArray *urls = [NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys:keys options:0]; + // FreeBSD doesn't support these flags + if(fs->f_flags & MNT_DONTBROWSE) + disk->type = FF_DISK_TYPE_HIDDEN; + else if(fs->f_flags & MNT_REMOVABLE) + disk->type = FF_DISK_TYPE_EXTERNAL; + else + disk->type = FF_DISK_TYPE_REGULAR; - if(urls == nil) - { - ffStrbufAppendS(&disks->error, "[NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys] failed"); - return; - } - - for (NSURL *url in urls) - { - FFDisk* disk = ffListAdd(&disks->disks); - - ffStrbufInitS(&disk->mountpoint, [url.relativePath cStringUsingEncoding:NSUTF8StringEncoding]); - - NSString* filesystem; - BOOL removable; - [NSWorkspace.sharedWorkspace getFileSystemInfoForPath:url.relativePath - isRemovable:&removable - isWritable:nil - isUnmountable:nil - description:nil - type:&filesystem - ]; - ffStrbufInitS(&disk->filesystem, [filesystem cStringUsingEncoding:NSUTF8StringEncoding]); - - NSError* error; - - NSNumber* isBrowsable; - if([url getResourceValue:&isBrowsable forKey:NSURLVolumeIsBrowsableKey error:&error] == YES && !isBrowsable.boolValue) - disk->type = FF_DISK_TYPE_HIDDEN; - else if(removable) - disk->type = FF_DISK_TYPE_EXTERNAL; - else - disk->type = FF_DISK_TYPE_REGULAR; - - NSString* volumeName; - if([url getResourceValue:&volumeName forKey:NSURLVolumeNameKey error:&error] == YES) - ffStrbufInitS(&disk->name, [volumeName cStringUsingEncoding:NSUTF8StringEncoding]); - else - ffStrbufInit(&disk->name); - - struct statvfs fs; - if(statvfs(disk->mountpoint.chars, &fs) != 0) - memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too - - disk->bytesTotal = fs.f_blocks * fs.f_frsize; - disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize); - - disk->filesTotal = (uint32_t) fs.f_files; - disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree); - } + ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String); } diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c new file mode 100644 index 000000000..0e14ef3f2 --- /dev/null +++ b/src/detection/disk/disk_bsd.c @@ -0,0 +1,56 @@ +#include "disk.h" + +#include + +#ifdef __FreeBSD__ +static void detectFsInfo(struct statfs* fs, FFDisk* disk) +{ + if( + ffStrbufStartsWithS(&disk->mountpoint, "/boot") || + ffStrbufStartsWithS(&disk->mountpoint, "/dev") || + ffStrbufStartsWithS(&disk->mountpoint, "/var") || + ffStrbufStartsWithS(&disk->mountpoint, "/tmp") || + ffStrbufStartsWithS(&disk->mountpoint, "/proc") || + ffStrbufStartsWithS(&disk->mountpoint, "/zroot") + ) + disk->type = FF_DISK_TYPE_HIDDEN; + else if((fs->f_flags & MNT_NOSUID) || !(fs->f_flags & MNT_LOCAL)) + disk->type = FF_DISK_TYPE_EXTERNAL; + else + disk->type = FF_DISK_TYPE_REGULAR; + + ffStrbufInit(&disk->name); +} +#else +void detectFsInfo(struct statfs* fs, FFDisk* disk); +#endif + +void ffDetectDisksImpl(FFDiskResult* disks) +{ + struct statfs* buf; + + int size = getmntinfo(&buf, MNT_WAIT); + if(size <= 0) + ffStrbufAppendS(&disks->error, "getmntinfo() failed"); + + for(struct statfs* fs = buf; fs < buf + size; ++fs) + { + FFDisk* disk = ffListAdd(&disks->disks); + + #ifdef __FreeBSD__ + // f_bavail and f_ffree are signed on FreeBSD... + if(fs->f_bavail < 0) fs->f_bavail = 0; + if(fs->f_ffree < 0) fs->f_ffree = 0; + #endif + + disk->bytesTotal = fs->f_blocks * fs->f_bsize; + disk->bytesUsed = disk->bytesTotal - ((uint64_t)fs->f_bavail * fs->f_bsize); + + disk->filesTotal = (uint32_t) fs->f_files; + disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs->f_ffree); + + ffStrbufInitS(&disk->mountpoint, fs->f_mntonname); + ffStrbufInitS(&disk->filesystem, fs->f_fstypename); + detectFsInfo(fs, disk); + } +} diff --git a/src/detection/host/host_bsd.c b/src/detection/host/host_bsd.c new file mode 100644 index 000000000..13a43acda --- /dev/null +++ b/src/detection/host/host_bsd.c @@ -0,0 +1,19 @@ +#include "host.h" +#include "common/sysctl.h" + +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); + + ffStrbufAppendS(&host->error, ffSysctlGetString("hw.fdt.model", &host->productName)); +} diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index f4141a6b2..a99c498e4 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -71,6 +71,17 @@ static void getShellVersionFish(FFstrbuf* exe, FFstrbuf* version) ffStrbufSubstrAfterLastC(version, ' '); } +static void getShellVersionTcsh(FFstrbuf* exe, FFstrbuf* version) +{ + ffProcessAppendStdOut(version, (char* const[]) { + exe->chars, + "--version", + NULL + }); // tcsh 6.24.01 (Astron) 2022-05-12 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec + ffStrbufSubstrAfterFirstC(version, ' '); // 6.24.01 (Astron) 2022-05-12 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec + ffStrbufSubstrBeforeFirstC(version, ' '); // 6.24.01 +} + static void getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version) { #ifdef _WIN32 @@ -128,6 +139,8 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) getShellVersionFish(exe, version); else if(strcasecmp(exeName, "pwsh") == 0) getShellVersionPwsh(exe, version); + else if(strcasecmp(exeName, "csh") == 0 || strcasecmp(exeName, "tcsh") == 0) + getShellVersionTcsh(exe, version); else if(strcasecmp(exeName, "nu") == 0) getShellVersionNu(exe, version); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 5040cede5..57867fdb6 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -153,6 +153,8 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) strcasecmp(name, "sh") == 0 || strcasecmp(name, "zsh") == 0 || strcasecmp(name, "ksh") == 0 || + strcasecmp(name, "csh") == 0 || + strcasecmp(name, "tcsh") == 0 || strcasecmp(name, "fish") == 0 || strcasecmp(name, "dash") == 0 || strcasecmp(name, "pwsh") == 0 || @@ -251,11 +253,15 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) } } -static void getUserShellFromEnv(FFTerminalShellResult* result) +static void getUserShellFromEnv(const FFinstance* instance, FFTerminalShellResult* result) { - ffStrbufAppendS(&result->userShellExe, getenv("SHELL")); + if(instance->state.passwd->pw_shell[0] != '\0') + ffStrbufAppendS(&result->userShellExe, instance->state.passwd->pw_shell); + else + ffStrbufAppendS(&result->userShellExe, getenv("SHELL")); if(result->userShellExe.length == 0) return; + setExeName(&result->userShellExe, &result->userShellExeName); //If shell detection via processes failed @@ -313,13 +319,21 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) } init = true; + #ifdef __APPLE__ + const uint32_t exePathLen = PROC_PIDPATHINFO_MAXSIZE; + #elif defined(MAXPATH) + const uint32_t exePathLen = MAXPATH; + #else + const uint32_t exePathLen = 260; + #endif + ffStrbufInit(&result.shellProcessName); - ffStrbufInitA(&result.shellExe, 128); + ffStrbufInitA(&result.shellExe, exePathLen); result.shellExeName = result.shellExe.chars; ffStrbufInit(&result.shellVersion); ffStrbufInit(&result.terminalProcessName); - ffStrbufInitA(&result.terminalExe, 128); + ffStrbufInitA(&result.terminalExe, exePathLen); result.terminalExeName = result.terminalExe.chars; ffStrbufInit(&result.userShellExe); @@ -329,7 +343,7 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) getTerminalShell(&result, getppid()); getTerminalFromEnv(&result); - getUserShellFromEnv(&result); + getUserShellFromEnv(instance, &result); getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion); if(strcasecmp(result.shellExeName, result.userShellExeName) != 0)