diff --git a/CMakeLists.txt b/CMakeLists.txt index 037e9dfd9..f3c96e9b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -256,6 +256,7 @@ endif() if(LINUX OR BSD) list(APPEND LIBFASTFETCH_SRC + src/detection/cpuUsage/cpuUsage_linux.c src/detection/host/host_linux.c src/detection/os/os_linux.c src/detection/gpu/gpu_linux.c @@ -272,6 +273,7 @@ endif() if(APPLE) list(APPEND LIBFASTFETCH_SRC + src/detection/cpuUsage/cpuUsage_apple.c src/util/apple/cf_helpers.c src/util/apple/osascript.m src/detection/host/host_apple.c @@ -295,6 +297,7 @@ endif() if(ANDROID) list(APPEND LIBFASTFETCH_SRC + src/detection/cpuUsage/cpuUsage_linux.c src/detection/host/host_android.c src/detection/os/os_android.c src/detection/gpu/gpu_android.c diff --git a/README.md b/README.md index a6fb617ed..761fd167d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts ##### WM themes ``` -KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE) +KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS) ``` ##### DE versions @@ -81,7 +81,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt ##### Terminal fonts ``` -Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, ITerm2, Apple Terminal, TTY +Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY ``` ## Building diff --git a/src/common/processing.c b/src/common/processing.c index d361a63af..d8bb4e0bd 100644 --- a/src/common/processing.c +++ b/src/common/processing.c @@ -6,16 +6,16 @@ #include #include -void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) +const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) { int pipes[2]; if(pipe(pipes) == -1) - return; + return "pipe() failed"; pid_t childPid = fork(); if(childPid == -1) - return; + return "fork() failed"; //Child if(childPid == 0) @@ -33,4 +33,6 @@ void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) waitpid(childPid, NULL, 0); ffAppendFDBuffer(pipes[0], buffer); close(pipes[0]); + + return NULL; } diff --git a/src/common/processing.h b/src/common/processing.h index 8bb67be85..51164b0e9 100644 --- a/src/common/processing.h +++ b/src/common/processing.h @@ -5,6 +5,6 @@ #include "util/FFstrbuf.h" -void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]); +const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]); #endif diff --git a/src/detection/cpuUsage/cpuUsage.h b/src/detection/cpuUsage/cpuUsage.h new file mode 100644 index 000000000..577d2a374 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_cpu_cpuUsage +#define FF_INCLUDED_detection_cpu_cpuUsage + +const char* ffGetCpuUsagePercent(double* result); + +#endif diff --git a/src/detection/cpuUsage/cpuUsage_apple.c b/src/detection/cpuUsage/cpuUsage_apple.c new file mode 100644 index 000000000..49f1d34c8 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage_apple.c @@ -0,0 +1,46 @@ +#include "fastfetch.h" +#include "cpuUsage.h" + +#include +#include +#include + +static const char* getCpuUsageInfo(long* inUseAll, long* totalAll) +{ + natural_t numCPUs = 0U; + processor_info_array_t cpuInfo; + mach_msg_type_number_t numCpuInfo; + + if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS) + return "host_processor_info() failed"; + if (numCPUs * CPU_STATE_MAX != numCpuInfo) + return "Unexpected host_processor_info() result"; + + for (natural_t i = 0U; i < numCPUs; ++i) { + integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER] + + 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; + } + return NULL; +} + +const char* ffGetCpuUsagePercent(double* result) +{ + long inUseAll1 = 0, totalAll1 = 0; + const char* error = getCpuUsageInfo(&inUseAll1, &totalAll1); + if(error) + return error; + + sleep(1); + + long inUseAll2 = 0, totalAll2 = 0; + error = getCpuUsageInfo(&inUseAll2, &totalAll2); + if(error) + return error; + + *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + return NULL; +} diff --git a/src/detection/cpuUsage/cpuUsage_linux.c b/src/detection/cpuUsage/cpuUsage_linux.c new file mode 100644 index 000000000..499759a82 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage_linux.c @@ -0,0 +1,46 @@ +#include "fastfetch.h" +#include "cpuUsage.h" + +#include +#include + +static const char* getCpuUsageInfo(FILE* procStat, long* inUseAll, long* totalAll) +{ + long user, nice, system, idle, iowait, irq, softirq; + + if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) + { + fclose(procStat); + return "fscanf() failed"; + } + *inUseAll = user + nice + system; + *totalAll = *inUseAll + idle + iowait + irq + softirq; + return NULL; +} + +const char* ffGetCpuUsagePercent(double* result) +{ + FILE* procStat = fopen("/proc/stat", "r"); + if(procStat == NULL) + return "fopen(\"""/proc/stat\", \"r\") == NULL"; + + const char* error = NULL; + long inUseAll1 = 0, totalAll1 = 0; + error = getCpuUsageInfo(procStat, &inUseAll1, &totalAll1); + if(error) + goto exit; + + sleep(1); + rewind(procStat); + + long inUseAll2 = 0, totalAll2 = 0; + error = getCpuUsageInfo(procStat, &inUseAll2, &totalAll2); + if(error) + goto exit; + + *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + +exit: + fclose(procStat); + return error; +} diff --git a/src/detection/memory/memory.c b/src/detection/memory/memory.c index 14b86cc39..f777554c3 100644 --- a/src/detection/memory/memory.c +++ b/src/detection/memory/memory.c @@ -5,7 +5,7 @@ void ffDetectMemoryImpl(FFMemoryResult* memory); static void calculatePercentage(FFMemoryStorage* storage) { - if(storage->error.length == 0) + if(storage->error.length != 0) return; if(storage->bytesTotal == 0) diff --git a/src/detection/os/os_apple.c b/src/detection/os/os_apple.c index acf7cdd6c..a18870c81 100644 --- a/src/detection/os/os_apple.c +++ b/src/detection/os/os_apple.c @@ -3,6 +3,7 @@ #include "common/sysctl.h" #include +#include typedef enum PListKey { @@ -12,7 +13,7 @@ typedef enum PListKey PLIST_KEY_OTHER } PListKey; -static void parseFile(FFOSResult* os) +static void parseSystemVersion(FFOSResult* os) { FILE* plist = fopen("/System/Library/CoreServices/SystemVersion.plist", "r"); if(plist == NULL) @@ -58,6 +59,33 @@ static void parseFile(FFOSResult* os) fclose(plist); } +void parseOSXSoftwareLicense(FFOSResult* os) +{ + FILE* rtf = fopen("/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf", "r"); + if(rtf == NULL) + return; + + char* line = NULL; + size_t len = 0; + const char* searchStr = "\\f0\\b SOFTWARE LICENSE AGREEMENT FOR macOS "; + const size_t searchLen = strlen(searchStr); + while(getline(&line, &len, rtf) != EOF) + { + if (strncmp(line, searchStr, searchLen) == 0) + { + ffStrbufAppendS(&os->codename, line + searchLen); + ffStrbufTrimRight(&os->codename, '\n'); + ffStrbufTrimRight(&os->codename, '\\'); + break; + } + } + + if(line != NULL) + free(line); + + fclose(rtf); +} + void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) { FF_UNUSED(instance); @@ -76,7 +104,7 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInitA(&os->variant, 0); ffStrbufInitA(&os->variantID, 0); - parseFile(os); + parseSystemVersion(os); if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS")) ffStrbufAppendS(&os->id, "macos"); @@ -84,9 +112,13 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) if(os->version.length == 0) ffSysctlGetString("kern.osproductversion", &os->version); - //TODO map version to pretty name + if(os->buildID.length == 0) + ffSysctlGetString("kern.osversion", &os->buildID); + ffStrbufAppend(&os->prettyName, &os->name); ffStrbufAppend(&os->versionID, &os->version); ffSysctlGetString("kern.ostype", &os->systemName); ffSysctlGetString("hw.machine", &os->architecture); + + parseOSXSoftwareLicense(os); } diff --git a/src/detection/terminalShell.c b/src/detection/terminalShell.c index 98766772b..fbd898f60 100644 --- a/src/detection/terminalShell.c +++ b/src/detection/terminalShell.c @@ -130,6 +130,13 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) getenv("WT_PROFILE_ID") != NULL )) term = "Windows Terminal"; + //Alacritty + if(!ffStrSet(term) && ( + getenv("ALACRITTY_SOCKET") != NULL || + getenv("ALACRITTY_LOG") != NULL || + getenv("ALACRITTY_WINDOW_ID") != NULL + )) term = "Alacritty"; + //Termux if(!ffStrSet(term) && ( getenv("TERMUX_VERSION") != NULL || diff --git a/src/modules/cpuUsage.c b/src/modules/cpuUsage.c index c4b56873d..fe655af99 100644 --- a/src/modules/cpuUsage.c +++ b/src/modules/cpuUsage.c @@ -1,35 +1,20 @@ #include "fastfetch.h" #include "common/printing.h" - -#include +#include "detection/cpuUsage/cpuUsage.h" #define FF_CPU_USAGE_MODULE_NAME "CPU Usage" #define FF_CPU_USAGE_NUM_FORMAT_ARGS 1 void ffPrintCPUUsage(FFinstance* instance) { - long user, nice, system, idle, iowait, irq, softirq; - FILE* procStat = fopen("/proc/stat", "r"); - if(procStat == NULL) + double cpuPercent = 0; + const char* error = ffGetCpuUsagePercent(&cpuPercent); + + if(error) { - ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "fopen(\"""/proc/stat\", \"r\") == NULL"); + ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "%s", error); return; } - if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) goto exit; - long workJiffies1 = user + nice + system; - long totalJiffies1 = workJiffies1 + idle + iowait + irq + softirq; - - sleep(1); - - rewind(procStat); - if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) goto exit; - long workJiffies2 = user + nice + system; - long totalJiffies2 = workJiffies2 + idle + iowait + irq + softirq; - - // https://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-using-c#answer-3017438 - long workOverPeriod = workJiffies2 - workJiffies1; - long totalOverPeriod = totalJiffies2 - totalJiffies1; - double cpuPercent = (double)workOverPeriod / (double)totalOverPeriod * 100; if(instance->config.cpuUsage.outputFormat.length == 0) { @@ -43,7 +28,4 @@ void ffPrintCPUUsage(FFinstance* instance) {FF_FORMAT_ARG_TYPE_DOUBLE, &cpuPercent} }); } - -exit: - fclose(procStat); } diff --git a/src/modules/locale.c b/src/modules/locale.c index 5b5b63269..444ed5a11 100644 --- a/src/modules/locale.c +++ b/src/modules/locale.c @@ -2,6 +2,8 @@ #include "common/properties.h" #include "common/printing.h" #include "common/caching.h" +#include "common/processing.h" +#include "common/parsing.h" #include @@ -21,6 +23,31 @@ static void getLocaleFromEnv(FFstrbuf* locale) ffStrbufAppendS(locale, getenv("LC_MESSAGES")); } +static void getLocaleFromCmd(FFstrbuf* locale) +{ + FFstrbuf buffer; + ffStrbufInitA(&buffer, 0); + char* args[] = { "locale", NULL }; + if(ffProcessAppendStdOut(&buffer, args) == NULL) + { + ffParsePropLines(buffer.chars, "LANG=\"", locale); + ffStrbufTrimRight(locale, '"'); + + if(locale->length == 0) + { + ffParsePropLines(buffer.chars, "LC_ALL=\"", locale); + ffStrbufTrimRight(locale, '"'); + + if(locale->length == 0) + { + ffParsePropLines(buffer.chars, "LC_MESSAGES=\"", locale); + ffStrbufTrimRight(locale, '"'); + } + } + } + ffStrbufDestroy(&buffer); +} + void ffPrintLocale(FFinstance* instance) { if(ffPrintFromCache(instance, FF_LOCALE_MODULE_NAME, &instance->config.locale, FF_LOCALE_NUM_FORMAT_ARGS)) @@ -44,6 +71,11 @@ void ffPrintLocale(FFinstance* instance) getLocaleFromEnv(&locale); } + if(locale.length == 0) + { + getLocaleFromCmd(&locale); + } + if(locale.length == 0) { ffPrintError(instance, FF_LOCALE_MODULE_NAME, 0, &instance->config.locale, "No locale found"); diff --git a/src/modules/memory.c b/src/modules/memory.c index 45cabec28..f3f2c17ee 100644 --- a/src/modules/memory.c +++ b/src/modules/memory.c @@ -27,7 +27,10 @@ static void printMemory(FFinstance* instance, const char* name, const FFModuleAr if(moduleArgs->outputFormat.length == 0) { ffPrintLogoAndKey(instance, name, 0, &moduleArgs->key); - printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, storage->percentage); + if (storage->bytesTotal == 0) + puts("Disabled"); + else + printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, storage->percentage); } else { diff --git a/src/modules/os.c b/src/modules/os.c index 39132c3a1..3d110f3a4 100644 --- a/src/modules/os.c +++ b/src/modules/os.c @@ -19,6 +19,14 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) else ffStrbufAppend(result, &os->systemName); + #ifdef __APPLE__ + if(os->codename.length > 0) + { + ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, &os->codename); + } + #endif + //Append version if it is missing if(os->versionID.length > 0 && ffStrbufFirstIndex(result, &os->versionID) == result->length) { diff --git a/src/modules/wmtheme.c b/src/modules/wmtheme.c index 8e422e672..ea78a68c3 100644 --- a/src/modules/wmtheme.c +++ b/src/modules/wmtheme.c @@ -259,14 +259,15 @@ static const char* quartzCompositorParsePlist(FFinstance* instance, const FFstrb ffplist_get_uint_val(pWmThemeColor, &wmThemeColor); switch (wmThemeColor) { - case (uint64_t)-1: ffStrbufAppendS(theme, " (Graphite)"); + case (uint64_t)-1: ffStrbufAppendS(theme, "Graphite"); break; case 0: ffStrbufAppendS(theme, "Red"); break; case 1: ffStrbufAppendS(theme, "Orange"); break; case 2: ffStrbufAppendS(theme, "Yellow"); break; case 3: ffStrbufAppendS(theme, "Green"); break; + case 4: ffStrbufAppendS(theme, "Blue"); break; case 5: ffStrbufAppendS(theme, "Purple"); break; case 6: ffStrbufAppendS(theme, "Pink"); break; - default: ffStrbufAppendS(theme, "Blue"); break; + default: ffStrbufAppendS(theme, "Multicolor"); break; } plist_t pWmTheme = ffplist_dict_get_item(root_node, "AppleInterfaceStyle");