mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 630d876e2d | |||
| 1938be86ff | |||
| 0980d5f0ad | |||
| d8c1b3b61b | |||
| 969523ae8a | |||
| 5d960ec744 | |||
| 3b36b8ca57 | |||
| 05f14764e6 | |||
| 3a180b24e3 | |||
| 02ab58e001 | |||
| fd158b41e1 | |||
| 89e0ede12f | |||
| 4d7b2410ef | |||
| c1f6a2f755 | |||
| 9c455c3b0f | |||
| d4ea9dfd21 | |||
| 08071e6e7e | |||
| ec87174f30 | |||
| 835e5b51c9 | |||
| 07c5ef255e | |||
| 476b55c17d | |||
| 4a53cfa312 | |||
| 50ea515476 | |||
| cbd9f72bc8 | |||
| 29eaa35f4c | |||
| 97c89c39d3 |
+26
-4
@@ -1,12 +1,34 @@
|
||||
# 2.42.0
|
||||
|
||||
Changes:
|
||||
* Normalize the module name `Bios` to `BIOS` (#1721)
|
||||
* No configuration file changes are required because fastfetch parses module names case-insensitively.
|
||||
|
||||
Bugfixes:
|
||||
* Disable disk type detection for virtual disks (PhysicalDisk, Linux, #1669)
|
||||
* Fix incorrect CPU temperature reporting (CPU, OpenBSD)
|
||||
* Fix setting `logo.chafa.symbols` in JSON configuration (Logo, #1709)
|
||||
* Fix non-normalized time display (Uptime, #1720)
|
||||
* Miscellaneous minor fixes
|
||||
|
||||
Features:
|
||||
* Add CPU temperature detection support (CPU, SunOS)
|
||||
* Improve CPU frequency detection (CPU, NetBSD)
|
||||
* Add Wi-Fi detection support (Wifi, NetBSD)
|
||||
* Add Webcam detection support (Camera, OpenBSD)
|
||||
* Requires root privileges
|
||||
|
||||
Logos:
|
||||
* Remove GoralixOS logo (#1699)
|
||||
* Add Aurora logo (#1700)
|
||||
* Add Codex Linux logo (#1701)
|
||||
|
||||
# 2.41.0
|
||||
|
||||
Changes:
|
||||
* Due to [the deprecation](https://github.com/actions/runner-images/issues/11101), Linux x86_64 binaries are now built with Ubuntu 22.04 (Glibc 2.35, Debian 12)
|
||||
* You can always build fastfetch yourself on your own. Please don't report bugs related to this change.
|
||||
|
||||
Bugfixes:
|
||||
* Don't detect disk type for virtual disks (PhysicalDisk, Linux, #1669)
|
||||
|
||||
Features:
|
||||
* Support physical core count detection on non-x86 platforms (CPU, Linux / FreeBSD)
|
||||
* Support CPU frequency detection on PPC64 (CPU, FreeBSD)
|
||||
@@ -881,7 +903,7 @@ Bugfixes:
|
||||
* Fix some presets
|
||||
* Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux)
|
||||
* Remove debug output (#1097, Windows)
|
||||
* Fix command line option `--gpu-hide-type` doesn't work (#1098, GPU)
|
||||
* Fix flag `--gpu-hide-type` doesn't work (#1098, GPU)
|
||||
* Fix wrong date on Raspbian 10 (#1108, DateTime, Linux)
|
||||
* Use `brightness` instead of `actuall_brightness` when detecting current brightness level (Brightness, Linux)
|
||||
* Ref: https://bugzilla.kernel.org/show_bug.cgi?id=203905
|
||||
|
||||
+19
-3
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.41.0
|
||||
VERSION 2.42.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -797,7 +797,7 @@ elseif(NetBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wifi/wifi_nbsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
@@ -879,7 +879,7 @@ elseif(OpenBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_obsd.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nbsd.c
|
||||
src/detection/wifi/wifi_obsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
@@ -1834,10 +1834,26 @@ if (BUILD_TESTS)
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(fastfetch-test-color
|
||||
tests/color.c
|
||||
)
|
||||
target_link_libraries(fastfetch-test-color
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(fastfetch-test-duration
|
||||
tests/duration.c
|
||||
)
|
||||
target_link_libraries(fastfetch-test-duration
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
|
||||
add_test(NAME test-list COMMAND fastfetch-test-list)
|
||||
add_test(NAME test-format COMMAND fastfetch-test-format)
|
||||
add_test(NAME test-color COMMAND fastfetch-test-color)
|
||||
add_test(NAME test-duration COMMAND fastfetch-test-duration)
|
||||
endif()
|
||||
|
||||
##################
|
||||
|
||||
Vendored
+18
@@ -1,3 +1,21 @@
|
||||
fastfetch (2.41.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.41.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 16 Apr 2025 13:42:58 +0800
|
||||
|
||||
fastfetch (2.40.4) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.4
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 10 Apr 2025 15:38:21 +0800
|
||||
|
||||
fastfetch (2.40.3) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.3
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 07 Apr 2025 09:29:27 +0800
|
||||
|
||||
fastfetch (2.40.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.0
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.40.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.41.0_source.buildinfo universe/utils optional
|
||||
|
||||
@@ -177,6 +177,7 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
if (ffCharIsEnglishAlphabet(value[0]))
|
||||
{
|
||||
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
|
||||
else FF_APPEND_COLOR_CODE_COND(bold_, FF_COLOR_MODE_BOLD)
|
||||
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
|
||||
else FF_APPEND_COLOR_CODE_COND(dim_, FF_COLOR_MODE_DIM)
|
||||
else FF_APPEND_COLOR_CODE_COND(italic_, FF_COLOR_MODE_ITALIC)
|
||||
@@ -212,6 +213,35 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
exit(479);
|
||||
}
|
||||
}
|
||||
else if (value[0] == '#')
|
||||
{
|
||||
// RGB color
|
||||
++value;
|
||||
char* pend = NULL;
|
||||
uint32_t rgb = (uint32_t) strtoul(value, &pend, 16);
|
||||
if (pend == value) {
|
||||
fprintf(stderr, "Error: invalid RGB color code found: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
if (pend - value > 6) {
|
||||
fprintf(stderr, "Error: RGB color code too long: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
else if (pend - value == 3) {
|
||||
rgb = ((rgb & 0xF00) >> 8) * 0x110000 +
|
||||
((rgb & 0x0F0) >> 4) * 0x001100 +
|
||||
((rgb & 0x00F) >> 0) * 0x000011;
|
||||
}
|
||||
else if (pend - value != 6) {
|
||||
fprintf(stderr, "Error: invalid RGB color code length: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
|
||||
uint32_t r = rgb >> 16, g = (rgb >> 8) & 0xFF, b = rgb & 0xFF;
|
||||
ffStrbufAppendF(buffer, FF_COLOR_FG_RGB "%u;%u;%u", r, g, b);
|
||||
value = pend;
|
||||
continue;
|
||||
}
|
||||
ffStrbufAppendC(buffer, *value);
|
||||
++value;
|
||||
|
||||
|
||||
+15
-8
@@ -190,19 +190,26 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
}
|
||||
}
|
||||
|
||||
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result)
|
||||
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result)
|
||||
{
|
||||
if(days == 0 && hours == 0 && minutes == 0)
|
||||
if(totalSeconds < 60)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u seconds", seconds);
|
||||
ffStrbufAppendF(result, "%u second", (unsigned) totalSeconds);
|
||||
if (totalSeconds != 1)
|
||||
ffStrbufAppendC(result, 's');
|
||||
return;
|
||||
}
|
||||
|
||||
if(seconds >= 30)
|
||||
{
|
||||
minutes++;
|
||||
seconds = 0;
|
||||
}
|
||||
uint32_t seconds = totalSeconds % 60;
|
||||
totalSeconds /= 60;
|
||||
if (seconds >= 30)
|
||||
totalSeconds++;
|
||||
|
||||
uint32_t minutes = totalSeconds % 60;
|
||||
totalSeconds /= 60;
|
||||
uint32_t hours = totalSeconds % 24;
|
||||
totalSeconds /= 24;
|
||||
uint32_t days = (uint32_t) totalSeconds;
|
||||
|
||||
if(days > 0)
|
||||
{
|
||||
|
||||
@@ -27,4 +27,4 @@ int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFstrbuf* result);
|
||||
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result);
|
||||
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result);
|
||||
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result);
|
||||
|
||||
@@ -100,7 +100,7 @@ void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleAr
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
if(!instance.config.display.showErrors)
|
||||
return;
|
||||
@@ -110,7 +110,10 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
vprintf(message, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
@@ -118,14 +121,6 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
printError(moduleName, moduleIndex, moduleArgs, printType, message, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
void ffPrintColor(const FFstrbuf* colorValue)
|
||||
{
|
||||
//If the color is not set, this would reset in \033[m, which resets everything.
|
||||
|
||||
@@ -232,7 +232,7 @@ static uint32_t connectedDevices(void)
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
int32_t connectedCount = -1;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#if FF_HAVE_LINUX_VIDEODEV2
|
||||
#include <linux/videodev2.h>
|
||||
#elif __has_include(<sys/videoio.h>) // OpenBSD
|
||||
#include <sys/videoio.h>
|
||||
#define FF_HAVE_LINUX_VIDEODEV2 1
|
||||
#endif
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
@@ -19,7 +22,13 @@ const char* ffDetectCamera(FFlist* result)
|
||||
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
break;
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
break;
|
||||
if (errno == ENXIO)
|
||||
continue;
|
||||
return "Failed to open /dev/videoN";
|
||||
}
|
||||
|
||||
struct v4l2_capability cap = {};
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
|
||||
@@ -67,6 +67,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
|
||||
if (freq == 0) freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
|
||||
if (freq == 0) freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
|
||||
if (freq > cpu->frequencyBase) cpu->frequencyBase = freq;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -1,10 +1,53 @@
|
||||
#include "cpu.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/sensors.h>
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
static const char* detectCPUTemp(FFCPUResult* cpu)
|
||||
{
|
||||
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
|
||||
|
||||
for (mib[2] = 0; mib[2] < 1024; mib[2]++)
|
||||
{
|
||||
struct sensordev sensordev;
|
||||
size_t sdlen = sizeof(struct sensordev);
|
||||
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
break;
|
||||
if (errno == ENXIO)
|
||||
continue;
|
||||
return "sysctl(sensordev) failed";
|
||||
}
|
||||
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
|
||||
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
|
||||
{
|
||||
struct sensor sensor;
|
||||
size_t slen = sizeof(struct sensor);
|
||||
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return "sysctl(sensor) failed";
|
||||
continue;
|
||||
}
|
||||
if (sensor.flags & SENSOR_FINVALID)
|
||||
continue;
|
||||
|
||||
cpu->temperature = (double)(sensor.value - 273150000) / 1E6;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return "No sensor for CPU temp found";
|
||||
}
|
||||
|
||||
const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name))
|
||||
return "sysctl(hw.model) failed";
|
||||
@@ -19,13 +62,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
if (options->temp)
|
||||
{
|
||||
struct sensor sensors;
|
||||
size_t size = sizeof(sensors);
|
||||
if (sysctl((int[]) {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0}, 5, &sensors, &size, NULL, 0) == 0)
|
||||
cpu->temperature = (double) (sensors.value - 273150000) / 1E6;
|
||||
}
|
||||
if (options->temp) detectCPUTemp(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,59 @@
|
||||
#include "cpu.h"
|
||||
#include "common/processing.h"
|
||||
#include <kstat.h>
|
||||
|
||||
static const char* detectCPUTempByKstat(kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
{
|
||||
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
|
||||
|
||||
for (int i = 0; possibleModules[i] != NULL; i++) {
|
||||
kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL);
|
||||
if (ks && kstat_read(kc, ks, NULL) >= 0) {
|
||||
kstat_named_t* kn = kstat_data_lookup(ks, "temperature");
|
||||
if (kn) {
|
||||
switch (kn->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
cpu->temperature = (float)kn->value.i32;
|
||||
return NULL;
|
||||
case KSTAT_DATA_UINT32:
|
||||
cpu->temperature = (float)kn->value.ui32;
|
||||
return NULL;
|
||||
case KSTAT_DATA_FLOAT:
|
||||
cpu->temperature = kn->value.f;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "Failed to find CPU temperature using kstat";
|
||||
}
|
||||
|
||||
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
"ipmitool",
|
||||
"-c",
|
||||
"sdr",
|
||||
"list",
|
||||
NULL
|
||||
});
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &buffer))
|
||||
{
|
||||
if (sscanf(line, "CPU%*d Temp,%lf,degrees C,ok", &cpu->temperature) == 1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "ipmitool sdr list failed to find CPU temperature";
|
||||
}
|
||||
|
||||
static inline void kstatFreeWrap(kstat_ctl_t** pkc)
|
||||
{
|
||||
assert(pkc);
|
||||
@@ -8,7 +61,7 @@ static inline void kstatFreeWrap(kstat_ctl_t** pkc)
|
||||
kstat_close(*pkc);
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
__attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open();
|
||||
if (!kc)
|
||||
@@ -43,5 +96,11 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
|
||||
if (kn) cpu->coresLogical = cpu->coresPhysical = cpu->coresOnline = (uint16_t) kn->value.ui32;
|
||||
}
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (detectCPUTempByKstat(kc, cpu) != NULL)
|
||||
detectCPUTempByIpmiTool(cpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,10 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
|
||||
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
|
||||
ffStrbufSetStatic(&device->interconnect, "NVMe");
|
||||
else if (strstr(pathSysDeviceReal, "/virtio") != NULL)
|
||||
{
|
||||
ffStrbufSetStatic(&device->interconnect, "Virtual");
|
||||
isVirtual = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
|
||||
|
||||
@@ -17,6 +17,7 @@ const char* ffDetectWifi(FFlist* result)
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0) {
|
||||
if_freenameindex(infs);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
@@ -82,22 +83,23 @@ const char* ffDetectWifi(FFlist* result)
|
||||
item->conn.channel = curchan.ic_ieee;
|
||||
item->conn.frequency = curchan.ic_freq;
|
||||
|
||||
if (IEEE80211_IS_CHAN_FHSS(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
|
||||
if (IEEE80211_IS_CHAN_A(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
if (IEEE80211_IS_CHAN_B(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
if (IEEE80211_IS_CHAN_ANYG(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
if (IEEE80211_IS_CHAN_HT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
if (IEEE80211_IS_CHAN_VHT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
#ifdef IEEE80211_IS_CHAN_HE // for future use
|
||||
if (IEEE80211_IS_CHAN_HE(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
else
|
||||
#endif
|
||||
if (IEEE80211_IS_CHAN_VHT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
else if (IEEE80211_IS_CHAN_HT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
else if (IEEE80211_IS_CHAN_ANYG(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
else if (IEEE80211_IS_CHAN_B(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
else if (IEEE80211_IS_CHAN_A(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
else if (IEEE80211_IS_CHAN_FHSS(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
|
||||
}
|
||||
|
||||
union {
|
||||
|
||||
+107
-49
@@ -2,12 +2,21 @@
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define COMPAT_FREEBSD_NET80211 1
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net80211/ieee80211.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// ieee80211 header of NetBSD is full of mess. Add compatibility macros from FreeBSD
|
||||
#undef IEEE80211_IS_CHAN_ANYG
|
||||
#define IEEE80211_IS_CHAN_ANYG(x) (IEEE80211_IS_CHAN_PUREG(x) || IEEE80211_IS_CHAN_G(x))
|
||||
#undef IEEE80211_IS_CHAN_HT
|
||||
#define IEEE80211_IS_CHAN_HT(x) (((x)->ic_flags & IEEE80211_CHAN_HT) != 0)
|
||||
#undef IEEE80211_IS_CHAN_VHT
|
||||
#define IEEE80211_IS_CHAN_VHT(x) (((x)->ic_flags & IEEE80211_CHAN_VHT) != 0)
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
@@ -18,6 +27,7 @@ const char* ffDetectWifi(FFlist* result)
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0) {
|
||||
if_freenameindex(infs);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
@@ -41,67 +51,115 @@ const char* ffDetectWifi(FFlist* result)
|
||||
item->conn.channel = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
struct ieee80211_nodereq nr = {};
|
||||
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
|
||||
char ssid[IEEE80211_NWID_LEN + 1] = {};
|
||||
struct ieee80211req ireq = {};
|
||||
strlcpy(ireq.i_name, i->if_name, sizeof(ireq.i_name));
|
||||
ireq.i_type = IEEE80211_IOC_SSID;
|
||||
ireq.i_data = ssid;
|
||||
ireq.i_len = sizeof(ssid) - 1;
|
||||
|
||||
struct ifreq ifr = {};
|
||||
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
ffStrbufSetStatic(&item->inf.status, "Unknown");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
|
||||
}
|
||||
|
||||
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
if (ioctl(sock, SIOCG80211, &ireq) < 0 || ireq.i_len == 0) {
|
||||
struct ifreq ifr;
|
||||
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
ffStrbufSetStatic(&item->inf.status, "Unknown");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
|
||||
}
|
||||
ffStrbufAppendS(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nr.nr_nwid_len > 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*)nr.nr_nwid);
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
ffStrbufSetStatic(&item->inf.status, "Up");
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, ireq.i_len, ssid);
|
||||
|
||||
uint8_t bssid[IEEE80211_ADDR_LEN] = {};
|
||||
ireq.i_type = IEEE80211_IOC_BSSID;
|
||||
ireq.i_data = bssid;
|
||||
ireq.i_len = sizeof(bssid);
|
||||
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
||||
}
|
||||
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2],
|
||||
nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]);
|
||||
struct ieee80211_channel curchan = {};
|
||||
ireq.i_type = IEEE80211_IOC_CHANNEL;
|
||||
ireq.i_data = &curchan;
|
||||
ireq.i_len = sizeof(curchan);
|
||||
|
||||
item->conn.channel = nr.nr_channel;
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
// item->conn.channel = curchan.ic_ieee; // No ic_ieee in NetBSD
|
||||
item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq);
|
||||
item->conn.frequency = curchan.ic_freq;
|
||||
|
||||
if (nr.nr_max_rssi) {
|
||||
item->conn.signalQuality = ((float)nr.nr_rssi / nr.nr_max_rssi) * 100.0;
|
||||
#ifdef IEEE80211_IS_CHAN_HE // for future use
|
||||
if (IEEE80211_IS_CHAN_HE(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
else
|
||||
#endif
|
||||
if (IEEE80211_IS_CHAN_VHT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
else if (IEEE80211_IS_CHAN_HT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
else if (IEEE80211_IS_CHAN_ANYG(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
else if (IEEE80211_IS_CHAN_B(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
else if (IEEE80211_IS_CHAN_A(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
else if (IEEE80211_IS_CHAN_FHSS(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
|
||||
}
|
||||
|
||||
if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
} else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
union {
|
||||
struct ieee80211req_sta_req req;
|
||||
uint8_t buf[1024];
|
||||
} stareq = {};
|
||||
memcpy(stareq.req.is_u.macaddr, bssid, sizeof(bssid));
|
||||
ireq.i_type = IEEE80211_IOC_STA_INFO;
|
||||
ireq.i_data = &stareq;
|
||||
ireq.i_len = sizeof(stareq);
|
||||
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
struct ieee80211req_sta_info* sta = stareq.req.info;
|
||||
if (sta->isi_len != 0) {
|
||||
int8_t rssi = (int8_t) sta->isi_rssi; // Strangely, `sta->isi_rssi` is unsigned
|
||||
item->conn.signalQuality = (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2);
|
||||
|
||||
if (sta->isi_txrate) {
|
||||
item->conn.txRate = (double)sta->isi_txrate / 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ieee80211_wpaparams wpa = {};
|
||||
strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) {
|
||||
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2)
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA2");
|
||||
else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1)
|
||||
ireq.i_type = IEEE80211_IOC_AUTHMODE;
|
||||
ireq.i_data = NULL;
|
||||
ireq.i_len = 0;
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
switch (ireq.i_val) {
|
||||
case IEEE80211_AUTH_NONE:
|
||||
ffStrbufSetStatic(&item->conn.security, "Insecure");
|
||||
break;
|
||||
case IEEE80211_AUTH_OPEN:
|
||||
ffStrbufSetStatic(&item->conn.security, "Open");
|
||||
break;
|
||||
case IEEE80211_AUTH_SHARED:
|
||||
ffStrbufSetStatic(&item->conn.security, "Shared");
|
||||
break;
|
||||
case IEEE80211_AUTH_8021X:
|
||||
ffStrbufSetStatic(&item->conn.security, "8021X");
|
||||
break;
|
||||
case IEEE80211_AUTH_AUTO:
|
||||
ffStrbufSetStatic(&item->conn.security, "Auto");
|
||||
break;
|
||||
case IEEE80211_AUTH_WPA:
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
} else {
|
||||
struct ieee80211_nwkey nwkey = {};
|
||||
strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) {
|
||||
if (nwkey.i_wepon)
|
||||
ffStrbufSetStatic(&item->conn.security, "WEP");
|
||||
else
|
||||
ffStrbufSetStatic(&item->conn.security, "Open");
|
||||
break;
|
||||
default:
|
||||
ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "wifi.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net80211/ieee80211.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
struct if_nameindex* infs = if_nameindex();
|
||||
if(!infs) {
|
||||
return "if_nameindex() failed";
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0) {
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
|
||||
{
|
||||
if (!ffStrStartsWith(i->if_name, "iwm")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&item->inf.description, i->if_name);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
ffStrbufInit(&item->conn.status);
|
||||
ffStrbufInit(&item->conn.ssid);
|
||||
ffStrbufInit(&item->conn.bssid);
|
||||
ffStrbufInit(&item->conn.protocol);
|
||||
ffStrbufInit(&item->conn.security);
|
||||
item->conn.signalQuality = 0.0/0.0;
|
||||
item->conn.rxRate = 0.0/0.0;
|
||||
item->conn.txRate = 0.0/0.0;
|
||||
item->conn.channel = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
struct ieee80211_nodereq nr = {};
|
||||
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
|
||||
|
||||
struct ifreq ifr = {};
|
||||
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
ffStrbufSetStatic(&item->inf.status, "Unknown");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
|
||||
}
|
||||
|
||||
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nr.nr_nwid_len > 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*)nr.nr_nwid);
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2],
|
||||
nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]);
|
||||
|
||||
item->conn.channel = nr.nr_channel;
|
||||
|
||||
if (nr.nr_max_rssi) {
|
||||
item->conn.signalQuality = ((float)nr.nr_rssi / nr.nr_max_rssi) * 100.0;
|
||||
}
|
||||
|
||||
if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
} else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
}
|
||||
|
||||
struct ieee80211_wpaparams wpa = {};
|
||||
strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) {
|
||||
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2)
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA2");
|
||||
else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1)
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
} else {
|
||||
struct ieee80211_nwkey nwkey = {};
|
||||
strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) {
|
||||
if (nwkey.i_wepon)
|
||||
ffStrbufSetStatic(&item->conn.security, "WEP");
|
||||
else
|
||||
ffStrbufSetStatic(&item->conn.security, "Open");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if_freenameindex(infs);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
+++++++++
|
||||
+++++$4+$1++++++$4+$1++
|
||||
++++++$4+$1+++ +++++++++++
|
||||
+++++++++++ $2+$1 +++++$4+$1+++++
|
||||
++++++$4+$1++++ $4+++$1 +++++++++++
|
||||
++++++++++$4 + +++++ ++ $2+++++$4+$2++++
|
||||
+++$4+$1++++$4 + + + +++++++ + + $2+++++$4+$2++
|
||||
++++++$4 $2+$4 +++ +++++++++ +++ $2++++++++
|
||||
+++$4+$1++$4 + +++++ +++++ +
|
||||
++++++$4 $2+$4 +++++ +++++ +++++
|
||||
++$4+$2+++$4 + +++++ ++++++ ++++++++++
|
||||
++++++$4 +++++ +++++ + +++++++++++++++++++
|
||||
++++++$4 + +++++ + +++++++++++++++
|
||||
+++$4++$2+$4 ++++++ +++++++++++++
|
||||
++++++$4 + ++++++ +++++++++++++ $2+++ $4++
|
||||
++++++$4 ++++++++++++++++ $2++$4+$2+ $4++ $1+
|
||||
++++++$4 ++++++++++++++ $3+ $2++++
|
||||
++++++$4 +++++++++++ + $4+ $3++++++
|
||||
++$4+$3+++$4 ++++++++++ +++ $3+++++++++++++
|
||||
+++++ $4+++++++++ + $3+++++++++++++
|
||||
+++ $4++++++++ $2++$4 + $3++++++++++++++ ++++
|
||||
++ $4++++++++ $3+ ++++++++++++++ +++++++
|
||||
$4++++++ $2+ $3+++++++++++++ +++++++$2++
|
||||
$4++++ $3+++++++++++++ ++++++$2+++
|
||||
+++++++++++ ++++++$2+++
|
||||
+++++ ++++++$2+++
|
||||
++++++$2++
|
||||
+++++
|
||||
@@ -0,0 +1,12 @@
|
||||
^"^"^". `"^"""`
|
||||
";;;;;:. `;;;;;;.
|
||||
^;":;:;: .;,,;:;:
|
||||
.'`",, '":::. ^;'';;;;, .:: ,;;;:
|
||||
';;;;:":::::' ^;` `;;;;" ::. ,;;;:
|
||||
";:;:. ^;` ^;;;;^ ,;. ,;;;:
|
||||
";;;: ^;` ";;;;^ ";' ,;;;:
|
||||
";;;: ^;` ,;;;;`^;` ,;;;:
|
||||
";;;: ^;` ,;;;;;^ ,;;;:
|
||||
";:;: ^;` .:;:;" ,;:;:
|
||||
,;;;;. ";" .:;, :;;;;.
|
||||
."""""` ^"^ '" ."""""`
|
||||
@@ -1,11 +0,0 @@
|
||||
.7J~
|
||||
~G@^ .^.
|
||||
:5&&&&##B?. !B&G7
|
||||
7B##&&B##BBP~ ^P&@&##P~
|
||||
$2^YGP5PBPPP5YY55?: .7GGGB#BPPP7.
|
||||
.?PPPPPPPPPP55YYY5Y!.^YPPPPPP5YYY5J~
|
||||
!PPPPPPPPPPPPPP5YYYY5JY5PPPPPPP55YY55?:
|
||||
^YPPPPPPPPPPPPPPPPYYYYYYYYY5PPPPPPP5YYY5Y!.
|
||||
.7PPPPPPPPPPPPPPPPPP5YYYYYYYYY55PPPPP5YYYYY5J~
|
||||
!5GPPPPPPPPPPPPPPPPPPPP55555555YY5PPPPPP5555555?:
|
||||
7777777777777777777777777!!!!!!!!!77777777!!!!!7!:
|
||||
+14
-6
@@ -1,6 +1,14 @@
|
||||
${c2}TTTTTTTTTT
|
||||
tt ${c1}222${c2}
|
||||
tt ${c1}2 2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}22222${c2}
|
||||
$3//$2
|
||||
$3//$2
|
||||
$1TTTTTTTTTTTTTTT$2 $3//$2 $1..::$2 $4:-:.$2
|
||||
$4ttt$2 $3//$2 $1.::.$2 $4.:-:$2
|
||||
$4ttt$2 $3//$2 $1.:.$2 $4--$2
|
||||
$4ttt$2 $3//$2 $4:-:$2
|
||||
$4ttt$2 $3//$2 $4.:-:$2
|
||||
$4ttt$2 $3//$2 $4:-:.$2
|
||||
$4ttt$2 $3//$2 $4.--.$2
|
||||
$4ttt$2 $3//$2 $4.:-:$2
|
||||
$4ttt$2 $3//$2 $4...$2
|
||||
$4ttt$2 $3//$2
|
||||
$3//$2 $3.:::::::::::.$2
|
||||
$3//$2
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
${c2}TTTTTTTTTT
|
||||
tt ${c1}222${c2}
|
||||
tt ${c1}2 2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}22222${c2}
|
||||
+32
-10
@@ -663,6 +663,17 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_YELLOW,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Aurora
|
||||
{
|
||||
.names = {"Aurora"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_AURORA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// Azos
|
||||
{
|
||||
.names = {"Azos"},
|
||||
@@ -1124,6 +1135,14 @@ static const FFlogo C[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Codex Linux (reMarkable OS)
|
||||
{
|
||||
.names = {"Codex Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_CODEX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE
|
||||
},
|
||||
},
|
||||
// Condres
|
||||
{
|
||||
.names = {"Condres"},
|
||||
@@ -2018,15 +2037,6 @@ static const FFlogo G[] = {
|
||||
.colorKeys = FF_COLOR_FG_MAGENTA,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// GoralixOS
|
||||
{
|
||||
.names = {"GoralixOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_GORALIXOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
},
|
||||
},
|
||||
// GrapheneOS
|
||||
{
|
||||
.names = {"GrapheneOS"},
|
||||
@@ -4590,8 +4600,20 @@ static const FFlogo S[] = {
|
||||
static const FFlogo T[] = {
|
||||
// T2
|
||||
{
|
||||
.names = {"T2"},
|
||||
.names = {"T2", "T2 SDE", "T2/Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_T2,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
},
|
||||
// T2Small
|
||||
{
|
||||
.names = {"T2_small", "T2 SDE_small", "T2/Linux_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_T2_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_BLUE,
|
||||
|
||||
@@ -27,17 +27,6 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
uint32_t timeRemaining = result->timeRemaining < 0 ? 0 : (uint32_t) result->timeRemaining;
|
||||
|
||||
uint32_t seconds = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t minutes = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t hours = timeRemaining % 24;
|
||||
timeRemaining /= 24;
|
||||
uint32_t days = timeRemaining;
|
||||
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
@@ -70,7 +59,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
if(str.length > 0)
|
||||
ffStrbufAppendS(&str, " (");
|
||||
|
||||
ffParseDuration(days, hours, minutes, seconds, &str);
|
||||
ffParseDuration((uint32_t) result->timeRemaining, &str);
|
||||
ffStrbufAppendS(&str, " remaining)");
|
||||
}
|
||||
}
|
||||
@@ -95,6 +84,15 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t timeRemaining = result->timeRemaining < 0 ? 0 : (uint32_t) result->timeRemaining;
|
||||
uint32_t seconds = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t minutes = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t hours = timeRemaining % 24;
|
||||
timeRemaining /= 24;
|
||||
uint32_t days = timeRemaining;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY capacityNum = ffStrbufCreate();
|
||||
if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
|
||||
ffPercentAppendNum(&capacityNum, result->capacity, options->percent, false, &options->moduleArgs);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_BIOS_MODULE_NAME "Bios"
|
||||
#define FF_BIOS_MODULE_NAME "BIOS"
|
||||
|
||||
void ffPrintBios(FFBiosOptions* options);
|
||||
void ffInitBiosOptions(FFBiosOptions* options);
|
||||
|
||||
@@ -220,7 +220,7 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
yyjson_mut_obj_add_uint(doc, frequency, "max", cpu.frequencyMax);
|
||||
|
||||
yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes");
|
||||
for (uint32_t i = 0; i < sizeof (cpu.coreTypes) / sizeof (cpu.coreTypes[0]) && cpu.coreTypes[i].count > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(cpu.coreTypes) && cpu.coreTypes[i].count > 0; i++)
|
||||
{
|
||||
yyjson_mut_val* core = yyjson_mut_arr_add_obj(doc, coreTypes);
|
||||
yyjson_mut_obj_add_uint(doc, core, "count", cpu.coreTypes[i].count);
|
||||
|
||||
@@ -12,7 +12,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
|
||||
char levelStr[4] = "L";
|
||||
for (uint32_t i = 0; i < sizeof (result->caches) / sizeof (result->caches[0]) && result->caches[i].length > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(result->caches) && result->caches[i].length > 0; i++)
|
||||
{
|
||||
ffStrbufClear(&key);
|
||||
levelStr[1] = (char) ('1' + i);
|
||||
@@ -72,7 +72,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
uint64_t sum = 0;
|
||||
for (uint32_t i = 0; i < sizeof (result->caches) / sizeof (result->caches[0]) && result->caches[i].length > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(result->caches) && result->caches[i].length > 0; i++)
|
||||
{
|
||||
if (buffer.length)
|
||||
ffStrbufAppendS(&buffer, ", ");
|
||||
@@ -199,7 +199,7 @@ void ffGenerateCPUCacheJsonResult(FF_MAYBE_UNUSED FFCPUCacheOptions* options, yy
|
||||
|
||||
yyjson_mut_val* caches = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
|
||||
for (uint32_t i = 0; i < sizeof (result.caches) / sizeof (result.caches[0]) && result.caches[i].length > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(result.caches) && result.caches[i].length > 0; i++)
|
||||
{
|
||||
yyjson_mut_val* level = yyjson_mut_obj_add_arr(doc, caches, &"l1\0l2\0l3\0l4\0"[i * 3]);
|
||||
FF_LIST_FOR_EACH(FFCPUCache, src, result.caches[i])
|
||||
|
||||
+12
-12
@@ -7,7 +7,7 @@
|
||||
|
||||
void ffPrintUptime(FFUptimeOptions* options)
|
||||
{
|
||||
FFUptimeResult result;
|
||||
FFUptimeResult result = {};
|
||||
|
||||
const char* error = ffDetectUptime(&result);
|
||||
|
||||
@@ -19,26 +19,26 @@ void ffPrintUptime(FFUptimeOptions* options)
|
||||
|
||||
uint64_t uptime = result.uptime;
|
||||
|
||||
uint32_t milliseconds = (uint32_t) (uptime % 1000);
|
||||
uptime /= 1000;
|
||||
uint32_t seconds = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t minutes = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t hours = (uint32_t) (uptime % 24);
|
||||
uptime /= 24;
|
||||
uint32_t days = (uint32_t) uptime;
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
ffParseDuration(days, hours, minutes, seconds, &buffer);
|
||||
ffParseDuration((uptime + 500) / 1000, &buffer);
|
||||
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t milliseconds = (uint32_t) (uptime % 1000);
|
||||
uptime /= 1000;
|
||||
uint32_t seconds = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t minutes = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t hours = (uint32_t) (uptime % 24);
|
||||
uptime /= 24;
|
||||
uint32_t days = (uint32_t) uptime;
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
|
||||
FF_FORMAT_ARG(days, "days"),
|
||||
FF_FORMAT_ARG(hours, "hours"),
|
||||
|
||||
+1
-1
@@ -401,7 +401,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
|
||||
|
||||
yyjson_val* symbols = yyjson_obj_get(val, "symbols");
|
||||
if (symbols)
|
||||
ffStrbufAppendS(&options->chafaSymbols, yyjson_get_str(symbols));
|
||||
ffStrbufSetS(&options->chafaSymbols, yyjson_get_str(symbols));
|
||||
|
||||
yyjson_val* canvasMode = yyjson_obj_get(val, "canvasMode");
|
||||
if (canvasMode)
|
||||
|
||||
@@ -49,6 +49,7 @@ void ffPlatformDestroy(FFPlatform* platform)
|
||||
ffStrbufDestroy(&platform->userName);
|
||||
ffStrbufDestroy(&platform->hostName);
|
||||
ffStrbufDestroy(&platform->userShell);
|
||||
ffStrbufDestroy(&platform->fullUserName);
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
ffStrbufDestroy(&info->architecture);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "common/format.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void verify(const char* color, const char* expected, int lineNo)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
|
||||
ffOptionParseColorNoClear(color, &result);
|
||||
if (!ffStrbufEqualS(&result, expected))
|
||||
{
|
||||
fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %s: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, color, expected, result.chars);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define VERIFY(color, expected) verify((color), (expected), __LINE__)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
instance.config.display.pipe = true;
|
||||
// Initialize dummy config colors for property tests
|
||||
ffStrbufInitS(&instance.config.display.colorKeys, "94"); // light_blue
|
||||
ffStrbufInitS(&instance.config.display.colorTitle, "95"); // light_magenta
|
||||
|
||||
{
|
||||
VERIFY("", "");
|
||||
VERIFY("1", "1");
|
||||
|
||||
VERIFY("red", "31");
|
||||
VERIFY("light_green", "92");
|
||||
VERIFY("default", "39");
|
||||
VERIFY("blue", "34");
|
||||
VERIFY("light_cyan", "96");
|
||||
|
||||
VERIFY("bold_red", "1;31");
|
||||
VERIFY("dim_light_yellow", "2;93");
|
||||
VERIFY("italic_underline_green", "3;4;32");
|
||||
VERIFY("reset_blue", "0;34"); // Reset followed by color
|
||||
|
||||
VERIFY("#ff0000", "38;2;255;0;0"); // RRGGBB
|
||||
VERIFY("#0f0", "38;2;0;255;0"); // RGB
|
||||
VERIFY("#123456", "38;2;18;52;86");
|
||||
VERIFY("#abc", "38;2;170;187;204");
|
||||
|
||||
VERIFY("bold_#ff00ff", "1;38;2;255;0;255");
|
||||
VERIFY("underline_#123", "4;38;2;17;34;51");
|
||||
|
||||
VERIFY("\e[32m", "32"); // Direct ANSI code
|
||||
VERIFY("\e[1;94m", "1;94"); // Direct ANSI code with mode
|
||||
|
||||
// Property colors (ensure dummy config colors are set)
|
||||
VERIFY("keys", "94");
|
||||
VERIFY("title", "95");
|
||||
VERIFY("bold_keys", "1;94");
|
||||
}
|
||||
|
||||
// Clean up dummy config colors
|
||||
ffStrbufDestroy(&instance.config.display.colorKeys);
|
||||
ffStrbufDestroy(&instance.config.display.colorTitle);
|
||||
|
||||
//Success
|
||||
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "common/parsing.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void verify(uint64_t totalSeconds, const char* expected, int lineNo)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
|
||||
ffParseDuration(totalSeconds, &result);
|
||||
if (!ffStrbufEqualS(&result, expected))
|
||||
{
|
||||
fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %llu: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, (unsigned long long) totalSeconds, expected, result.chars);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define VERIFY(color, expected) verify((color), (expected), __LINE__)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Test seconds less than 60
|
||||
VERIFY(0, "0 seconds");
|
||||
VERIFY(1, "1 second");
|
||||
VERIFY(2, "2 seconds");
|
||||
VERIFY(59, "59 seconds");
|
||||
|
||||
// Test minute rounding (when seconds >= 30)
|
||||
VERIFY(60, "1 min");
|
||||
VERIFY(60 + 29, "1 min");
|
||||
VERIFY(60 + 30, "2 mins");
|
||||
|
||||
// Test only minutes
|
||||
VERIFY(60 * 2 - 1, "2 mins");
|
||||
VERIFY(60 * 2, "2 mins");
|
||||
VERIFY(60 * 59 + 29, "59 mins");
|
||||
|
||||
// Test only hours (no minutes)
|
||||
VERIFY(60 * 59 + 30, "1 hour");
|
||||
VERIFY(60 * 60, "1 hour");
|
||||
VERIFY(2 * 60 * 60, "2 hours");
|
||||
VERIFY(23 * 60 * 60, "23 hours");
|
||||
|
||||
// Test combination of hours and minutes
|
||||
VERIFY(60 * 60 + 60, "1 hour, 1 min");
|
||||
VERIFY(60 * 60 + 60 * 2, "1 hour, 2 mins");
|
||||
VERIFY(60 * 60 * 2 + 60 + 29, "2 hours, 1 min");
|
||||
VERIFY(60 * 60 * 2 + 60 + 30, "2 hours, 2 mins");
|
||||
|
||||
// Test days
|
||||
VERIFY(60 * 60 * 24, "1 day");
|
||||
VERIFY(60 * 60 * 24 - 1, "1 day");
|
||||
VERIFY(60 * 60 * 24 * 2, "2 days");
|
||||
|
||||
// Test combination of days and hours
|
||||
VERIFY(60 * 60 * 24 + 60 * 60, "1 day, 1 hour");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 60, "2 days, 1 hour");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 60 * 2, "2 days, 2 hours");
|
||||
|
||||
// Test combination of days, hours, and minutes
|
||||
VERIFY(60 * 60 * 24 + 60 * 60 + 60, "1 day, 1 hour, 1 min");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 60 + 60 * 2, "2 days, 1 hour, 2 mins");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 2, "2 days, 2 mins");
|
||||
|
||||
// Test very large number of days
|
||||
VERIFY(60 * 60 * 24 * 100, "100 days(!)");
|
||||
VERIFY(60 * 60 * 24 * 200, "200 days(!)");
|
||||
|
||||
//Success
|
||||
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
Reference in New Issue
Block a user