Version", &result->deVersion);
+ ffParsePropFileData(instance, "gtk-doc/html/libxfce4ui/index.html", "
Version", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
@@ -214,12 +210,12 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, "LXQt");
- ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
+ ffParsePropFileData(instance, "gconfig/lxqt.pc", "Version:", &result->deVersion);
if(result->deVersion.length == 0)
- ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
+ ffParsePropFileData(instance, "cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
if(result->deVersion.length == 0)
- ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
+ ffParsePropFileData(instance, "cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
@@ -243,6 +239,13 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
ffStrbufDestroy(&wmProcessNameBuffer);
}
+static void getBudgie(const FFinstance* instance, FFDisplayServerResult* result)
+{
+ ffStrbufSetS(&result->dePrettyName, "Budgie");
+ ffStrbufSetS(&result->deProcessName, "budgie-desktop");
+ ffParsePropFileData(instance, "budgie/budgie-version.xml", "", &result->deVersion);
+}
+
static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
@@ -253,19 +256,19 @@ static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResul
strcasecmp(name, "plasma") == 0 ||
strcasecmp(name, "plasmashell") == 0 ||
strcasecmp(name, "plasmawayland") == 0
- ) getKDE(result);
+ ) getKDE(instance, result);
else if(
strcasecmp(name, "Gnome") == 0 ||
strcasecmp(name, "ubuntu:GNOME") == 0 ||
strcasecmp(name, "ubuntu") == 0 ||
strcasecmp(name, "gnome-shell") == 0
- ) getGnome(result);
+ ) getGnome(instance, result);
else if(
strcasecmp(name, "X-Cinnamon") == 0 ||
strcasecmp(name, "Cinnamon") == 0
- ) getCinnamon(result);
+ ) getCinnamon(instance, result);
else if(
strcasecmp(name, "XFCE") == 0 ||
@@ -286,6 +289,13 @@ static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResul
strcasecmp(name, "X-LXQT") == 0 ||
strcasecmp(name, "lxqt-session") == 0
) getLXQt(instance, result);
+
+ else if(
+ strcasecmp(name, "Budgie") == 0 ||
+ strcasecmp(name, "X-Budgie") == 0 ||
+ strcasecmp(name, "budgie-desktop") == 0 ||
+ strcasecmp(name, "Budgie:GNOME") == 0
+ ) getBudgie(instance, result);
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c
index 692be7808..99a960894 100644
--- a/src/detection/displayserver/linux/xcb.c
+++ b/src/detection/displayserver/linux/xcb.c
@@ -115,10 +115,12 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
while(iterator.rem > 0)
{
- ffdsAppendResolution(
+ ffdsAppendDisplay(
result,
(uint32_t) iterator.data->width_in_pixels,
(uint32_t) iterator.data->height_in_pixels,
+ 0,
+ 0,
0
);
ffxcb_screen_next(&iterator);
@@ -180,17 +182,19 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo
modeInfo->dot_clock / (uint32_t) (modeInfo->htotal * modeInfo->vtotal)
));
- return ffdsAppendResolution(
+ return ffdsAppendDisplay(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
- refreshRate == 0 ? data->defaultRefreshRate : refreshRate
+ refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
+ 0,
+ 0
);
}
static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode)
{
- //We do the check here, because we want the best fallback resolution if this call failed
+ //We do the check here, because we want the best fallback display if this call failed
if(data->screenResources == NULL)
return false;
@@ -215,11 +219,13 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
return false;
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
- res = res ? true : ffdsAppendResolution(
+ res = res ? true : ffdsAppendDisplay(
data->result,
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
- data->defaultRefreshRate
+ data->defaultRefreshRate,
+ 0,
+ 0
);
free(crtcInfoReply);
@@ -258,11 +264,13 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
data->ffxcb_randr_output_next(&outputIterator);
};
- return foundOutput ? true : ffdsAppendResolution(
+ return foundOutput ? true : ffdsAppendDisplay(
data->result,
(uint32_t) monitor->width,
(uint32_t) monitor->height,
- data->defaultRefreshRate
+ data->defaultRefreshRate,
+ 0,
+ 0
);
}
@@ -316,11 +324,13 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
return;
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
- ffdsAppendResolution(
+ ffdsAppendDisplay(
data->result,
(uint32_t) screen->width_in_pixels,
(uint32_t) screen->height_in_pixels,
- data->defaultRefreshRate
+ data->defaultRefreshRate,
+ 0,
+ 0
);
}
diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c
index 108de5946..12f87587c 100644
--- a/src/detection/displayserver/linux/xlib.c
+++ b/src/detection/displayserver/linux/xlib.c
@@ -79,10 +79,12 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
for(int i = 0; i < ScreenCount(display); i++)
{
Screen* screen = ScreenOfDisplay(display, i);
- ffdsAppendResolution(
+ ffdsAppendDisplay(
result,
(uint32_t) screen->width,
(uint32_t) screen->height,
+ 0,
+ 0,
0
);
}
@@ -138,11 +140,13 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)
));
- return ffdsAppendResolution(
+ return ffdsAppendDisplay(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
- refreshRate == 0 ? data->defaultRefreshRate : refreshRate
+ refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
+ 0,
+ 0
);
}
@@ -158,7 +162,7 @@ static bool xrandrHandleMode(XrandrData* data, RRMode mode)
static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
{
- //We do the check here, because we want the best fallback resolution if this call failed
+ //We do the check here, because we want the best fallback display if this call failed
if(data->screenResources == NULL)
return false;
@@ -167,11 +171,13 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
return false;
bool res = xrandrHandleMode(data, crtcInfo->mode);
- res = res ? true : ffdsAppendResolution(
+ res = res ? true : ffdsAppendDisplay(
data->result,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
- data->defaultRefreshRate
+ data->defaultRefreshRate,
+ 0,
+ 0
);
data->ffXRRFreeCrtcInfo(crtcInfo);
@@ -201,11 +207,13 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
foundOutput = true;
}
- return foundOutput ? true : ffdsAppendResolution(
+ return foundOutput ? true : ffdsAppendDisplay(
data->result,
(uint32_t) monitorInfo->width,
(uint32_t) monitorInfo->height,
- data->defaultRefreshRate
+ data->defaultRefreshRate,
+ 0,
+ 0
);
}
@@ -253,11 +261,13 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
return;
//Fallback to screen
- ffdsAppendResolution(
+ ffdsAppendDisplay(
data->result,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
- data->defaultRefreshRate
+ data->defaultRefreshRate,
+ 0,
+ 0
);
}
diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h
index 16bd2ff53..e14feb9d8 100644
--- a/src/detection/gpu/gpu.h
+++ b/src/detection/gpu/gpu.h
@@ -8,12 +8,21 @@
#define FF_GPU_TEMP_UNSET (0/0.0)
#define FF_GPU_CORE_COUNT_UNSET -1
+#define FF_GPU_VENDOR_NAME_APPLE "Apple"
#define FF_GPU_VENDOR_NAME_AMD "AMD"
#define FF_GPU_VENDOR_NAME_INTEL "Intel"
#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA"
+typedef enum FFGpuType
+{
+ FF_GPU_TYPE_INTEGRATED,
+ FF_GPU_TYPE_DISCRETE,
+ FF_GPU_TYPE_UNKNOWN
+} FFGpuType;
+
typedef struct FFGPUResult
{
+ FFGpuType type;
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c
index 52292d83e..413e65746 100644
--- a/src/detection/gpu/gpu_apple.c
+++ b/src/detection/gpu/gpu_apple.c
@@ -5,6 +5,7 @@
#include "util/apple/cf_helpers.h"
#include
+#include
static double detectGpuTemp(const FFstrbuf* gpuName)
{
@@ -59,7 +60,33 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
FFGPUResult* gpu = ffListAdd(gpus);
- ffStrbufInitA(&gpu->vendor, 0);
+ gpu->type = FF_GPU_TYPE_UNKNOWN;
+
+ ffStrbufInit(&gpu->vendor);
+ int vendorId;
+ if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId))
+ {
+ if(vendorId == 0x106b)
+ {
+ ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
+ gpu->type = FF_GPU_TYPE_INTEGRATED;
+ }
+ else if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2))
+ {
+ ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
+ gpu->type = FF_GPU_TYPE_DISCRETE; // Apple never used AMD CPUs
+ }
+ else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3))
+ {
+ ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
+ gpu->type = FF_GPU_TYPE_INTEGRATED;
+ }
+ else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3))
+ {
+ ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
+ gpu->type = FF_GPU_TYPE_DISCRETE;
+ }
+ }
ffStrbufInit(&gpu->driver);
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c
index 50580a898..d34807df9 100644
--- a/src/detection/gpu/gpu_linux.c
+++ b/src/detection/gpu/gpu_linux.c
@@ -58,10 +58,10 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
}
-static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
+static void drmDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
u8 revId;
- bool revIdSet = false;;
+ bool revIdSet = false;
#if PCI_LIB_VERSION >= 0x030800
revIdSet = pci->ffpci_fill_info(device, PCI_FILL_CLASS_EXT) & PCI_FILL_CLASS_EXT;
@@ -82,7 +82,7 @@ static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufInit(&query);
ffStrbufAppendF(&query, "%X, %X,", device->device_id, revId);
- ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->name);
+ ffParsePropFileData(instance, "libdrm/amdgpu.ids", query.chars, &gpu->name);
ffStrbufDestroy(&query);
@@ -94,11 +94,11 @@ static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufRemoveStringsA(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
}
-static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
+static void pciDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(ffStrbufCompS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD) == 0)
{
- drmDetectDeviceName(gpu, pci, device);
+ drmDetectDeviceName(instance, gpu, pci, device);
if(gpu->name.length > 0)
return;
}
@@ -146,20 +146,16 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufDestroy(&path);
}
-static void pciDetectTemperatur(const FFinstance* instance, FFGPUResult* gpu, struct pci_dev* device)
+static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
{
- const FFTempsResult* tempsResult = ffDetectTemps(instance);
+ const FFTempsResult* tempsResult = ffDetectTemps();
for(uint32_t i = 0; i < tempsResult->values.length; i++)
{
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
- uint32_t tempClass;
- if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1)
- continue;
-
//The kernel exposes the device class multiplied by 256 for some reason
- if(tempClass == device->device_class * 256)
+ if(tempValue->deviceClass == device->device_class * 256)
{
gpu->temperature = tempValue->value;
return;
@@ -167,6 +163,38 @@ static void pciDetectTemperatur(const FFinstance* instance, FFGPUResult* gpu, st
}
}
+static void detectType(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* device)
+{
+ //There is no straightforward way to detect the type of a GPU.
+ //The approach taken here is to look at the memory sizes of the device.
+ //Since integrated GPUs usually use the system ram, they don't have expansive ROMs
+ //and their memory sizes are usually smaller than 1GB.
+
+ if(!(pci->ffpci_fill_info(device, PCI_FILL_SIZES) & PCI_FILL_SIZES))
+ {
+ gpu->type = FF_GPU_TYPE_UNKNOWN;
+ return;
+ }
+
+ if(device->rom_size > 0)
+ {
+ gpu->type = FF_GPU_TYPE_DISCRETE;
+ return;
+ }
+
+ uint32_t numSizes = sizeof(device->size) / sizeof(device->size[0]);
+ for(uint32_t i = 0; i < numSizes; i++)
+ {
+ if(device->size[i] >= 1024 * 1024 * 1024) //1GB
+ {
+ gpu->type = FF_GPU_TYPE_DISCRETE;
+ return;
+ }
+ }
+
+ gpu->type = FF_GPU_TYPE_INTEGRATED;
+}
+
static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData* pci, struct pci_dev* device)
{
pci->ffpci_fill_info(device, PCI_FILL_CLASS);
@@ -175,7 +203,9 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
if(
+ //https://pci-ids.ucw.cz/read/PD/03
strcasecmp("VGA compatible controller", class) != 0 &&
+ strcasecmp("XGA compatible controller", class) != 0 &&
strcasecmp("3D controller", class) != 0 &&
strcasecmp("Display controller", class) != 0
) return;
@@ -188,16 +218,18 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
pciDetectVendorName(gpu, pci, device);
ffStrbufInit(&gpu->name);
- pciDetectDeviceName(gpu, pci, device);
+ pciDetectDeviceName(instance, gpu, pci, device);
ffStrbufInit(&gpu->driver);
pciDetectDriverName(gpu, pci, device);
+ detectType(gpu, pci, device);
+
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
if(instance->config.gpuTemp)
- pciDetectTemperatur(instance, gpu, device);
+ pciDetectTemperatur(gpu, device);
}
static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp
index f5d0f4946..07b711205 100644
--- a/src/detection/gpu/gpu_windows.cpp
+++ b/src/detection/gpu/gpu_windows.cpp
@@ -40,6 +40,8 @@ static const char* detectWithDxgi(FFlist* gpus)
ffStrbufInit(&gpu->driver);
+ gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
+
adapter->Release();
gpu->temperature = FF_GPU_TEMP_UNSET;
@@ -65,6 +67,8 @@ static const char* detectWithWmi(FFlist* gpus)
{
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
+ gpu->type = FF_GPU_TYPE_UNKNOWN;
+
ffStrbufInit(&gpu->vendor);
record.getString(L"AdapterCompatibility", &gpu->vendor);
if(ffStrbufStartsWithS(&gpu->vendor, "Intel "))
diff --git a/src/detection/gtk.c b/src/detection/gtk.c
index ad24c9c4e..1db344edd 100644
--- a/src/detection/gtk.c
+++ b/src/detection/gtk.c
@@ -80,8 +80,11 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
cursorTheme = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
cursorSize = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
}
- else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0)
- {
+ else if(
+ ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 ||
+ ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 ||
+ ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0
+ ) {
themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
@@ -145,7 +148,7 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
static void detectGTK(const FFinstance* instance, const char* version, FFGTKResult* result)
{
- //Mate, Cinnamon and Gnome use dconf to save theme config
+ //Mate, Cinnamon, Gnome, Unity, Budgie use dconf to save theme config
//On other DEs, this will do nothing
detectGTKFromSettings(instance, result);
if(allPropertiesSet(result))
@@ -155,9 +158,9 @@ static void detectGTK(const FFinstance* instance, const char* version, FFGTKResu
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
- for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
+ FF_LIST_FOR_EACH(FFstrbuf, configDir, instance->state.platform.configDirs)
{
- ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
+ ffStrbufSet(&baseDir, configDir);
detectGTKFromConfigDir(&baseDir, version, result);
if(allPropertiesSet(result))
break;
diff --git a/src/detection/os/os.h b/src/detection/os/os.h
index 688d6f63b..80fb6b2af 100644
--- a/src/detection/os/os.h
+++ b/src/detection/os/os.h
@@ -17,8 +17,6 @@ typedef struct FFOSResult
FFstrbuf versionID;
FFstrbuf codename;
FFstrbuf buildID;
- FFstrbuf systemName;
- FFstrbuf architecture;
} FFOSResult;
const FFOSResult* ffDetectOS(const FFinstance* instance);
diff --git a/src/detection/os/os_android.c b/src/detection/os/os_android.c
index eb4bf97d5..890486ab7 100644
--- a/src/detection/os/os_android.c
+++ b/src/detection/os/os_android.c
@@ -23,10 +23,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
ffStrbufInit(&os->buildID);
ffSettingsGetAndroidProperty("ro.build.id", &os->buildID);
- ffStrbufInitS(&os->systemName, instance->state.utsname.sysname);
-
- ffStrbufInitS(&os->architecture, instance->state.utsname.machine);
-
ffStrbufInit(&os->idLike);
ffStrbufInit(&os->variant);
ffStrbufInit(&os->variantID);
diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m
index d6a410506..8f8174387 100644
--- a/src/detection/os/os_apple.m
+++ b/src/detection/os/os_apple.m
@@ -61,8 +61,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
ffStrbufInit(&os->id);
ffStrbufInit(&os->prettyName);
ffStrbufInit(&os->versionID);
- ffStrbufInit(&os->systemName);
- ffStrbufInit(&os->architecture);
ffStrbufInitA(&os->codename, 0);
ffStrbufInitA(&os->idLike, 0);
@@ -82,8 +80,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
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/os/os_linux.c b/src/detection/os/os_linux.c
index 73c513922..45a0f5cec 100644
--- a/src/detection/os/os_linux.c
+++ b/src/detection/os/os_linux.c
@@ -138,11 +138,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
ffStrbufInit(&os->versionID);
ffStrbufInit(&os->codename);
ffStrbufInit(&os->buildID);
- ffStrbufInit(&os->systemName);
- ffStrbufInit(&os->architecture);
-
- ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
- ffStrbufSetS(&os->architecture, instance->state.utsname.machine);
detectOS(os, instance);
diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp
index fdda72c89..7b4c6ea2f 100644
--- a/src/detection/os/os_windows.cpp
+++ b/src/detection/os/os_windows.cpp
@@ -46,6 +46,8 @@ static const char* getOsNameByWinbrand(FFstrbuf* osName)
extern "C"
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
{
+ FF_UNUSED(instance);
+
ffStrbufInit(&os->name);
ffStrbufInit(&os->prettyName);
ffStrbufInit(&os->id);
@@ -56,8 +58,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
ffStrbufInit(&os->versionID);
ffStrbufInit(&os->codename);
ffStrbufInit(&os->buildID);
- ffStrbufInit(&os->systemName);
- ffStrbufInit(&os->architecture);
if(getOsNameByWinbrand(&os->variant) && getOsNameByWmi(&os->variant))
return;
@@ -106,7 +106,4 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
}
ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars);
-
- ffStrbufSetS(&os->architecture, instance->state.utsname.machine);
- ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
}
diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c
index f4b363d54..ace7d637e 100644
--- a/src/detection/packages/packages_linux.c
+++ b/src/detection/packages/packages_linux.c
@@ -140,7 +140,7 @@ static uint32_t getNixPackagesImpl(char* path)
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");
+ 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 | wc -l");
ffProcessAppendStdOut(&output, (char* const[]) {
"sh",
@@ -149,13 +149,12 @@ static uint32_t getNixPackagesImpl(char* path)
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++;
+ int result = (int) strtol(output.chars, NULL, 10);
+ ffStrbufDestroy(&command);
ffStrbufDestroy(&output);
- return result;
+
+ return (uint32_t) result;
}
static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
@@ -272,7 +271,7 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, FFPa
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR);
packageCounts->pkg += getSQLite3Int(instance, baseDir, "/var/db/pkg/local.sqlite", "SELECT count(id) FROM packages");
- packageCounts->rpm += getSQLite3Int(instance, baseDir, "/var/lib/rpm/rmpdb.sqlite", "SELECT count(blob) FROM Packages");
+ packageCounts->rpm += getSQLite3Int(instance, baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(blob) FROM Packages");
packageCounts->snap += getSnap(baseDir);
packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps");
}
@@ -309,6 +308,8 @@ static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDi
{
if(entry->d_type != DT_DIR)
continue;
+ if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+ continue;
ffStrbufAppendS(baseDir, entry->d_name);
getPackageCounts(instance, baseDir, packageCounts);
@@ -338,7 +339,7 @@ void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result)
result->rpm = getRpmFromLibrpm(instance);
#endif
- ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
+ ffStrbufSet(&baseDir, &instance->state.platform.homeDir);
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
ffStrbufDestroy(&baseDir);
diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c
index 93739e9bf..afd016c6d 100644
--- a/src/detection/packages/packages_windows.c
+++ b/src/detection/packages/packages_windows.c
@@ -17,10 +17,10 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix *
counter++;
} while (FindNextFileA(hFind, &wfd));
FindClose(hFind);
- }
- if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2)
- counter -= 2; // accounting for . and ..
+ if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2)
+ counter -= 2; // accounting for . and ..
+ }
return counter;
}
@@ -28,17 +28,15 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix *
static void detectScoop(const FFinstance* instance, FFPackagesResult* result)
{
char scoopPath[MAX_PATH + 3];
- strcpy(scoopPath, instance->state.passwd->pw_dir);
+ strcpy(scoopPath, instance->state.platform.homeDir.chars);
strncat(scoopPath, "/scoop/apps/*", sizeof(scoopPath) - 1 - strlen(scoopPath));
result->scoop = getNumElements(scoopPath, FILE_ATTRIBUTE_DIRECTORY);
if(result->scoop > 0)
result->scoop--; // scoop
}
-static void detectChoco(const FFinstance* instance, FFPackagesResult* result)
+static void detectChoco(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result)
{
- FF_UNUSED(instance);
-
const char* chocoInstall = getenv("ChocolateyInstall");
if(!chocoInstall || chocoInstall[0] == '\0')
return;
@@ -51,8 +49,22 @@ static void detectChoco(const FFinstance* instance, FFPackagesResult* result)
result->choco--; // choco
}
+static void detectPacman(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result)
+{
+ const char* msystemPrefix = getenv("MSYSTEM_PREFIX");
+ if(!msystemPrefix)
+ return;
+
+ // MSYS2
+ char pacmanPath[MAX_PATH + 3];
+ strcpy(pacmanPath, msystemPrefix);
+ strncat(pacmanPath, "/../var/lib/pacman/local/*", sizeof(pacmanPath) - 1 - strlen(pacmanPath));
+ result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY);
+}
+
void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result)
{
detectScoop(instance, result);
detectChoco(instance, result);
+ detectPacman(instance, result);
}
diff --git a/src/detection/qt.c b/src/detection/qt.c
index 6a7794c8e..5ac1d943e 100644
--- a/src/detection/qt.c
+++ b/src/detection/qt.c
@@ -88,9 +88,9 @@ static void detectPlasma(const FFinstance* instance, FFQtResult* result)
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
- for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
+ FF_LIST_FOR_EACH(FFstrbuf, configDir, instance->state.platform.configDirs)
{
- ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
+ ffStrbufSet(&baseDir, configDir);
ffStrbufAppendS(&baseDir, "kdeglobals");
if(detectPlasmaFromFile(baseDir.chars, result))
diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c
index cb342a9f8..913e6f037 100644
--- a/src/detection/temps/temps_linux.c
+++ b/src/detection/temps/temps_linux.c
@@ -8,18 +8,19 @@
static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value)
{
+ //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
uint32_t dirLength = dir->length;
- FFstrbuf valueBuffer;
+ FF_STRBUF_AUTO_DESTROY valueBuffer;
ffStrbufInit(&valueBuffer);
ffStrbufAppendS(dir, "temp1_input");
- ffReadFileBuffer(dir->chars, &valueBuffer);
+ if(!ffReadFileBuffer(dir->chars, &valueBuffer))
+ return false;
+
ffStrbufSubstrBefore(dir, dirLength);
- value->value = ffStrbufToDouble(&valueBuffer);
-
- ffStrbufDestroy(&valueBuffer);
+ value->value = ffStrbufToDouble(&valueBuffer) / 1000; // valueBuffer is millidegree Celsius
if(value->value != value->value)
return false;
@@ -29,13 +30,19 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value)
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufAppendS(dir, "device/class");
- ffReadFileBuffer(dir->chars, &value->deviceClass);
- ffStrbufSubstrBefore(dir, dirLength);
+ if(!ffReadFileBuffer(dir->chars, &valueBuffer))
+ {
+ ffStrbufSubstrBefore(dir, dirLength);
+ ffStrbufAppendS(dir, "device/device/class");
+ ffReadFileBuffer(dir->chars, &valueBuffer);
+ }
+ if(valueBuffer.length)
+ value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16);
- return value->name.length > 0 || value->deviceClass.length > 0;
+ return value->name.length > 0 || value->deviceClass > 0;
}
-const FFTempsResult* ffDetectTemps(const FFinstance* instance)
+const FFTempsResult* ffDetectTemps()
{
static FFTempsResult result;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
@@ -49,13 +56,6 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance)
}
init = true;
- if(!instance->config.allowSlowOperations)
- {
- ffListInitA(&result.values, sizeof(FFTempValue), 0);
- ffThreadMutexUnlock(&mutex);
- return &result;
- }
-
ffListInitA(&result.values, sizeof(FFTempValue), 16);
FFstrbuf baseDir;
@@ -83,11 +83,10 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance)
FFTempValue* temp = ffListAdd(&result.values);
ffStrbufInit(&temp->name);
- ffStrbufInit(&temp->deviceClass);
+ temp->deviceClass = 0;
if(!parseHwmonDir(&baseDir, temp))
{
ffStrbufDestroy(&temp->name);
- ffStrbufDestroy(&temp->deviceClass);
--result.values.length;
}
diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h
index 6bece23ed..569bd0401 100644
--- a/src/detection/temps/temps_linux.h
+++ b/src/detection/temps/temps_linux.h
@@ -8,7 +8,7 @@
typedef struct FFTempValue
{
FFstrbuf name;
- FFstrbuf deviceClass;
+ uint32_t deviceClass;
double value;
} FFTempValue;
@@ -17,6 +17,6 @@ typedef struct FFTempsResult
FFlist values; //List of FFTempValue
} FFTempsResult;
-const FFTempsResult* ffDetectTemps(const FFinstance* instance);
+const FFTempsResult* ffDetectTemps();
#endif
diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c
index 5716b720d..41ff5428b 100644
--- a/src/detection/terminalfont/terminalfont.c
+++ b/src/detection/terminalfont/terminalfont.c
@@ -37,7 +37,7 @@ static void detectAlacritty(const FFinstance* instance, FFTerminalFontResult* te
ffStrbufDestroy(&fontSize);
}
-static void detectTTY(FFTerminalFontResult* terminalFont)
+FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont)
{
FFstrbuf fontName;
ffStrbufInit(&fontName);
@@ -291,7 +291,7 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbu
#endif
#endif //defined(_WIN32) || defined(__linux__)
-static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result)
+FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result)
{
FFstrbuf fontName;
ffStrbufInit(&fontName);
@@ -320,21 +320,54 @@ static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result
return true;
}
+static bool detectWezterm(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminalFontResult* result)
+{
+ FF_STRBUF_AUTO_DESTROY fontName;
+ ffStrbufInit(&fontName);
+
+ ffStrbufSetS(&result->error, ffProcessAppendStdOut(&fontName, (char* const[]){
+ "wezterm",
+ "ls-fonts",
+ "--text",
+ "a",
+ NULL
+ }));
+ if(result->error.length)
+ return false;
+
+ //LeftToRight
+ // 0 a \u{61} x_adv=7 cells=1 glyph=a,180 wezterm.font("JetBrains Mono", {weight="Regular", stretch="Normal", style="Normal"})
+ // , BuiltIn
+ ffStrbufSubstrAfterFirstC(&fontName, '"');
+ ffStrbufSubstrBeforeFirstC(&fontName, '"');
+
+ if(!fontName.length)
+ return false;
+
+ ffFontInitCopy(&result->font, fontName.chars);
+ return true;
+}
+
void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont);
static bool detectTerminalFontCommon(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
{
- if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "alacritty") == 0)
+ if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "alacritty"))
detectAlacritty(instance, terminalFont);
- else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0)
+ else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui"))
+ detectWezterm(instance, terminalFont);
+
+ #ifndef _WIN32
+ else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kitty"))
detectKitty(instance, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty"))
detectTTY(terminalFont);
+ #endif
#if defined(_WIN32) || defined(__linux__)
//Used by both Linux (WSL) and Windows
- else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 ||
- ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0)
+ else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "Windows Terminal") ||
+ ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "WindowsTerminal.exe"))
detectFromWindowsTeriminal(instance, &terminalShell->terminalExe, terminalFont);
#endif
diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m
index 1ee387aa2..71ecc8b22 100644
--- a/src/detection/terminalfont/terminalfont_apple.m
+++ b/src/detection/terminalfont/terminalfont_apple.m
@@ -17,7 +17,7 @@ static void detectIterm2(const FFinstance* instance, FFTerminalFontResult* termi
}
NSError* error;
- NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.googlecode.iterm2.plist", instance->state.passwd->pw_dir];
+ NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.googlecode.iterm2.plist", instance->state.platform.homeDir.chars];
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
error:&error];
if(error)
@@ -62,7 +62,7 @@ static void detectAppleTerminal(FFTerminalFontResult* terminalFont)
static void detectWarpTerminal(const FFinstance* instance, FFTerminalFontResult* terminalFont)
{
NSError* error;
- NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance->state.passwd->pw_dir];
+ NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance->state.platform.homeDir.chars];
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
error:&error];
if(error)
diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c
index 54ea3a328..1d06d09c1 100644
--- a/src/detection/terminalfont/terminalfont_linux.c
+++ b/src/detection/terminalfont/terminalfont_linux.c
@@ -88,15 +88,15 @@ static void detectKonsole(const FFinstance* instance, FFTerminalFontResult* term
}
FFstrbuf profilePath;
- ffStrbufInitA(&profilePath, 64);
- ffStrbufAppendS(&profilePath, ".local/share/konsole/");
+ ffStrbufInitA(&profilePath, 32);
+ ffStrbufAppendS(&profilePath, "konsole/");
ffStrbufAppend(&profilePath, &profile);
ffStrbufDestroy(&profile);
FFstrbuf fontName;
ffStrbufInit(&fontName);
- ffParsePropFileHome(instance, profilePath.chars, "Font =", &fontName);
+ ffParsePropFileData(instance, profilePath.chars, "Font =", &fontName);
if(fontName.length == 0)
ffStrbufAppendF(&terminalFont->error, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath.chars);
@@ -149,7 +149,9 @@ static void detectDeepinTerminal(const FFinstance* instance, FFTerminalFontResul
ffStrbufInit(&fontSize);
FFstrbuf profile;
- ffStrbufInitF(&profile, "%s/.config/deepin/deepin-terminal/config.conf", instance->state.passwd->pw_dir);
+ ffStrbufInit(&profile);
+ ffStrbufAppend(&profile, &instance->state.platform.homeDir);
+ ffStrbufAppendS(&profile, ".config/deepin/deepin-terminal/config.conf"); //TODO: Use config dirs
FILE* file = fopen(profile.chars, "r");
if(file)
diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c
index ea41f018e..060108290 100644
--- a/src/detection/terminalfont/terminalfont_windows.c
+++ b/src/detection/terminalfont/terminalfont_windows.c
@@ -14,10 +14,14 @@ static void detectMintty(const FFinstance* instance, FFTerminalFontResult* termi
FF_STRBUF_AUTO_DESTROY fontSize;
ffStrbufInit(&fontSize);
- ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) {
+ if(!ffParsePropFileConfigValues(instance, "mintty/config", 2, (FFpropquery[]) {
{"Font=", &fontName},
{"FontHeight=", &fontSize}
- });
+ }))
+ ffParsePropFileConfigValues(instance, ".minttyrc", 2, (FFpropquery[]) {
+ {"Font=", &fontName},
+ {"FontHeight=", &fontSize}
+ });
if(fontName.length == 0)
ffStrbufAppendS(&fontName, "Lucida Console");
if(fontSize.length == 0)
diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c
index a99c498e4..aa9d221f3 100644
--- a/src/detection/terminalshell/terminalshell.c
+++ b/src/detection/terminalshell/terminalshell.c
@@ -1,5 +1,7 @@
#include "fastfetch.h"
+#include "common/io.h"
#include "common/processing.h"
+#include "common/properties.h"
#ifdef _WIN32
@@ -36,122 +38,252 @@ static bool getFileVersion(const char* exePath, FFstrbuf* version)
#endif
-static void getShellVersionBash(FFstrbuf* exe, FFstrbuf* version)
+static bool getExeVersionRaw(FFstrbuf* exe, FFstrbuf* version)
{
- ffProcessAppendStdOut(version, (char* const[]) {
+ return ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"--version",
NULL
- }); // GNU bash, version 5.1.16(1)-release (x86_64-pc-msys)\nCopyright...
+ }) == NULL;
+}
+
+static bool getExeVersionGeneral(FFstrbuf* exe, FFstrbuf* version)
+{
+ if(!getExeVersionRaw(exe, version))
+ return false;
+
+ ffStrbufSubstrAfterFirstC(version, ' ');
+ ffStrbufSubstrBeforeFirstC(version, ' ');
+ return true;
+}
+
+static bool getShellVersionBash(FFstrbuf* exe, FFstrbuf* version)
+{
+ if(!getExeVersionRaw(exe, version))
+ return false;
+
+ // GNU bash, version 5.1.16(1)-release (x86_64-pc-msys)\nCopyright...
ffStrbufSubstrBeforeFirstC(version, '\n'); // GNU bash, version 5.1.16(1)-release (x86_64-pc-msys)
ffStrbufSubstrBeforeLastC(version, ' '); // GNU bash, version 5.1.16(1)-release
ffStrbufSubstrAfterLastC(version, ' '); // 5.1.16(1)-release
ffStrbufSubstrBeforeFirstC(version, '('); // 5.1.16
+ return true;
}
-static void getShellVersionZsh(FFstrbuf* exe, FFstrbuf* version)
+static bool getShellVersionFish(FFstrbuf* exe, FFstrbuf* version)
{
- ffProcessAppendStdOut(version, (char* const[]) {
- exe->chars,
- "--version",
- NULL
- });
- ffStrbufSubstrBeforeLastC(version, ' ');
- ffStrbufSubstrAfterFirstC(version, ' ');
-}
+ if(!getExeVersionRaw(exe, version))
+ return false;
-static void getShellVersionFish(FFstrbuf* exe, FFstrbuf* version)
-{
- ffProcessAppendStdOut(version, (char* const[]) {
- exe->chars,
- "--version",
- NULL
- });
+ //fish, version 3.6.0
ffStrbufTrimRight(version, '\n');
ffStrbufSubstrAfterLastC(version, ' ');
+ return true;
}
-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)
+static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
{
#ifdef _WIN32
if(getFileVersion(exe->chars, version))
- return;
+ {
+ ffStrbufSubstrBeforeLastC(version, '.');
+ return true;
+ }
#endif
- ffProcessAppendStdOut(version, (char* const[]) {
- exe->chars,
- "--version",
- NULL
- });
+ if(!getExeVersionRaw(exe, version))
+ return false;
+
ffStrbufTrimRight(version, '\n');
ffStrbufSubstrAfterLastC(version, ' ');
+ return true;
}
#ifdef _WIN32
-static void getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
+static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
{
- ffProcessAppendStdOut(version, (char* const[]) {
+ if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-NoLogo",
"-NoProfile",
"-Command",
"$PSVersionTable.PSVersion.ToString()",
NULL
- });
+ })) return false;
+
ffStrbufTrimRight(version, '\n');
ffStrbufSubstrAfterLastC(version, ' ');
+ return true;
}
-static void getShellVersionCmd(FFstrbuf* exe, FFstrbuf* version)
+static bool getShellVersionCmd(FFstrbuf* exe, FFstrbuf* version)
{
- getFileVersion(exe->chars, version);
+ return getFileVersion(exe->chars, version);
}
#endif
-static void getShellVersionNu(FFstrbuf* exe, FFstrbuf* version)
-{
- ffProcessAppendStdOut(version, (char* const[]) {
- exe->chars,
- "--version",
- NULL
- });
-}
-
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
{
- bool ok = true;
if(strcasecmp(exeName, "bash") == 0 || strcasecmp(exeName, "sh") == 0)
- getShellVersionBash(exe, version);
- else if(strcasecmp(exeName, "zsh") == 0)
- getShellVersionZsh(exe, version);
- else if(strcasecmp(exeName, "fish") == 0)
- 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);
+ return getShellVersionBash(exe, version);
+ if(strcasecmp(exeName, "zsh") == 0)
+ return getExeVersionGeneral(exe, version); //zsh 5.9 (arm-apple-darwin21.3.0)
+ if(strcasecmp(exeName, "fish") == 0)
+ return getShellVersionFish(exe, version);
+ if(strcasecmp(exeName, "pwsh") == 0)
+ return getShellVersionPwsh(exe, version);
+ if(strcasecmp(exeName, "csh") == 0 || strcasecmp(exeName, "tcsh") == 0)
+ return getExeVersionGeneral(exe, version); //tcsh 6.24.07 (Astron) 2022-12-21 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec
+ if(strcasecmp(exeName, "nu") == 0)
+ return getExeVersionRaw(exe, version); //0.73.0
#ifdef _WIN32
- else if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0)
- getShellVersionWinPowerShell(exe, version);
- else if(strcasecmp(exeName, "cmd") == 0)
- getShellVersionCmd(exe, version);
+ if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0)
+ return getShellVersionWinPowerShell(exe, version);
+ if(strcasecmp(exeName, "cmd") == 0)
+ return getShellVersionCmd(exe, version);
#endif
- else
- ok = false;
- return ok;
+ return false;
+}
+
+FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version)
+{
+ ffStrbufSetS(version, getenv("TERMUX_VERSION"));
+ return version->length > 0;
+}
+
+FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version)
+{
+ if(ffProcessAppendStdOut(version, (char* const[]){
+ "gnome-terminal",
+ "--version",
+ NULL
+ })) return false;
+
+ //# GNOME Terminal 3.46.7 using VTE 0.70.2 +BIDI +GNUTLS +ICU +SYSTEMD
+ ffStrbufSubstrAfterFirstS(version, "Terminal ");
+ ffStrbufSubstrBeforeFirstC(version, ' ');
+ return true;
+}
+
+FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* version)
+{
+ const char* konsoleVersion = getenv("KONSOLE_VERSION");
+ if(konsoleVersion)
+ {
+ //221201
+ long major = strtol(konsoleVersion, NULL, 10);
+ if (major >= 0)
+ {
+ long patch = major % 100;
+ major /= 100;
+ long minor = major % 100;
+ major /= 100;
+ ffStrbufSetF(version, "%ld.%ld.%ld", major, minor, patch);
+ return true;
+ }
+ }
+
+ return getExeVersionGeneral(exe, version);
+}
+
+#ifdef _WIN32
+
+static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
+{
+ FF_STRBUF_AUTO_DESTROY buildInfoPath;
+ ffStrbufInitNS(&buildInfoPath, ffStrbufLastIndexC(exe, '\\') + 1, exe->chars);
+ ffStrbufAppendS(&buildInfoPath, "BuildInfo.xml");
+
+ if(ffParsePropFile(buildInfoPath.chars, "StoreVersion=\"", version))
+ {
+ ffStrbufTrimRight(version, '"');
+ return true;
+ }
+
+ return getFileVersion(exe->chars, version);
+}
+
+static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
+{
+ ffStrbufSetS(version, getenv("ConEmuBuild"));
+
+ if(version->length)
+ return true;
+
+ return getFileVersion(exe->chars, version);
+}
+
+#endif
+
+bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
+{
+ #ifdef __ANDROID__
+
+ if(ffStrbufEqualS(processName, "Termux"))
+ return getTerminalVersionTermux(version);
+
+ #endif
+
+ #if defined(__linux__) || defined(__FreeBSD__)
+
+ if(ffStrbufIgnCaseEqualS(processName, "gnome-terminal-"))
+ return getTerminalVersionGnome(version);
+
+ if(ffStrbufIgnCaseEqualS(processName, "konsole"))
+ return getTerminalVersionKonsole(exe, version);
+
+ if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal"))
+ return getExeVersionGeneral(exe, version);//xfce4-terminal 1.0.4 (Xfce 4.18)...
+
+ if(ffStrbufIgnCaseEqualS(processName, "deepin-terminal"))
+ return getExeVersionGeneral(exe, version);//deepin-terminal 5.4.36
+
+ #endif
+
+ #ifdef _WIN32
+
+ if(ffStrbufIgnCaseEqualS(processName, "WindowsTerminal.exe"))
+ return getTerminalVersionWindowsTerminal(exe, version);
+
+ if(ffStrbufStartsWithIgnCaseS(processName, "ConEmuC"))
+ return getTerminalVersionConEmu(exe, version);
+
+ #endif
+
+ #ifndef _WIN32
+
+ if(ffStrbufIgnCaseEqualS(processName, "kitty"))
+ return getExeVersionGeneral(exe, version); //kitty 0.21.2 created by Kovid Goyal
+
+ #endif
+
+ if(ffStrbufStartsWithIgnCaseS(processName, "alacritty"))
+ return getExeVersionGeneral(exe, version);
+
+ const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION");
+ if(termProgramVersion)
+ {
+ const char* termProgram = getenv("TERM_PROGRAM");
+ if(termProgram)
+ {
+ if(ffStrbufStartsWithIgnCaseS(processName, termProgram) || // processName ends with `.exe` on Windows
+ (strcmp(termProgram, "vscode") == 0 && ffStrbufStartsWithIgnCaseS(processName, "code"))
+ ) {
+ ffStrbufSetS(version, termProgramVersion);
+ return true;
+ }
+ }
+ }
+
+ #ifdef _WIN32
+
+ return getFileVersion(exe->chars, version);
+
+ #else
+
+ return false;
+
+ #endif
}
diff --git a/src/detection/terminalshell/terminalshell.h b/src/detection/terminalshell/terminalshell.h
index 8783e3410..a2a1f4200 100644
--- a/src/detection/terminalshell/terminalshell.h
+++ b/src/detection/terminalshell/terminalshell.h
@@ -17,6 +17,7 @@ typedef struct FFTerminalShellResult
FFstrbuf terminalExe;
FFstrbuf terminalPrettyName;
const char* terminalExeName; //pointer to a char in terminalExe
+ FFstrbuf terminalVersion;
FFstrbuf userShellExe;
const char* userShellExeName; //pointer to a char in userShellExe
diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c
index 80c0d93d1..1f30866c2 100644
--- a/src/detection/terminalshell/terminalshell_linux.c
+++ b/src/detection/terminalshell/terminalshell_linux.c
@@ -261,10 +261,7 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
static void getUserShellFromEnv(const FFinstance* instance, FFTerminalShellResult* result)
{
- if(instance->state.passwd->pw_shell[0] != '\0')
- ffStrbufAppendS(&result->userShellExe, instance->state.passwd->pw_shell);
- else
- ffStrbufAppendS(&result->userShellExe, getenv("SHELL"));
+ ffStrbufSet(&result->userShellExe, &instance->state.platform.userShell);
if(result->userShellExe.length == 0)
return;
@@ -310,6 +307,8 @@ static void getShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* versio
getShellVersionGeneric(exe, exeName, version);
}
+bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
+
const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
{
FF_UNUSED(instance);
@@ -350,12 +349,17 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
getTerminalFromEnv(&result);
getUserShellFromEnv(instance, &result);
- getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion);
- if(strcasecmp(result.shellExeName, result.userShellExeName) != 0)
- getShellVersion(&result.userShellExe, result.userShellExeName, &result.userShellVersion);
- else
- ffStrbufSet(&result.userShellVersion, &result.shellVersion);
+ ffStrbufClear(&result.shellVersion);
+ if(instance->config.shellVersion)
+ {
+ getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion);
+
+ if(strcasecmp(result.shellExeName, result.userShellExeName) != 0)
+ getShellVersion(&result.userShellExe, result.userShellExeName, &result.userShellVersion);
+ else
+ ffStrbufSet(&result.userShellVersion, &result.shellVersion);
+ }
if(ffStrbufEqualS(&result.shellProcessName, "pwsh"))
ffStrbufInitS(&result.shellPrettyName, "PowerShell");
@@ -373,11 +377,18 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
ffStrbufInitS(&result.terminalPrettyName, "Apple Terminal");
else if(ffStrbufEqualS(&result.terminalProcessName, "WarpTerminal"))
ffStrbufInitS(&result.terminalPrettyName, "Warp");
+ else if(ffStrbufEqualS(&result.terminalProcessName, "wezterm-gui"))
+ ffStrbufInitS(&result.terminalPrettyName, "WezTerm");
else 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);
+ ffStrbufInit(&result.terminalVersion);
+
+ if(instance->config.terminalVersion)
+ fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
+
ffThreadMutexUnlock(&mutex);
return &result;
}
diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp
index cb2da1ca4..b800228fa 100644
--- a/src/detection/terminalshell/terminalshell_windows.cpp
+++ b/src/detection/terminalshell/terminalshell_windows.cpp
@@ -99,7 +99,7 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
extern "C" bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
-static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
+static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* result, uint32_t pid)
{
uint32_t ppid;
@@ -128,11 +128,12 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
ffStrbufClear(&result->shellPrettyName);
ffStrbufClear(&result->shellExe);
result->shellExeName = nullptr;
- return getShellInfo(result, ppid);
+ return getShellInfo(instance, result, ppid);
}
ffStrbufClear(&result->shellVersion);
- fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion);
+ if(instance->config.shellVersion)
+ fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion);
if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "pwsh"))
ffStrbufSetS(&result->shellPrettyName, "PowerShell");
@@ -175,7 +176,7 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
return ppid;
}
-static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
+static uint32_t getTerminalInfo(const FFinstance* instance, FFTerminalShellResult* result, uint32_t pid)
{
uint32_t ppid;
@@ -201,7 +202,7 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
ffStrbufClear(&result->terminalPrettyName);
ffStrbufClear(&result->terminalExe);
result->terminalExeName = "";
- return getTerminalInfo(result, ppid);
+ return getTerminalInfo(instance, result, ppid);
}
if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "WindowsTerminal"))
@@ -217,6 +218,8 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
ffStrbufSetS(&result->terminalPrettyName, "Windows Explorer");
else if(ffStrbufStartsWithIgnCaseS(&result->terminalPrettyName, "ConEmuC"))
ffStrbufSetS(&result->terminalPrettyName, "ConEmu");
+ else if(ffStrbufEqualS(&result->terminalPrettyName, "wezterm-gui"))
+ ffStrbufInitS(&result->terminalPrettyName, "WezTerm");
return ppid;
}
@@ -263,6 +266,8 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
}
}
+extern "C" bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
+
const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
{
FF_UNUSED(instance);
@@ -297,11 +302,15 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
if(!getProcessInfo(0, &ppid, nullptr, nullptr, nullptr))
goto exit;
- ppid = getShellInfo(&result, ppid);
- getTerminalInfo(&result, ppid);
+ ppid = getShellInfo(instance, &result, ppid);
+ getTerminalInfo(instance, &result, ppid);
if(result.terminalProcessName.length == 0)
getTerminalFromEnv(&result);
+ ffStrbufInit(&result.terminalVersion);
+ if(instance->config.terminalVersion)
+ fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
+
exit:
ffThreadMutexUnlock(&mutex);
return &result;
diff --git a/src/detection/title.c b/src/detection/title.c
deleted file mode 100644
index df9367ba0..000000000
--- a/src/detection/title.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "fastfetch.h"
-#include "detection/title.h"
-#include "common/thread.h"
-
-#include
-#include
-
-#ifndef HOST_NAME_MAX
- #define HOST_NAME_MAX 64
-#endif
-
-#ifdef __linux__
-#include
-
-static void detectFQDN(FFTitleResult* title)
-{
- struct addrinfo hints = {0};
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_CANONNAME;
-
- struct addrinfo* info = NULL;
-
- if(getaddrinfo(title->hostname.chars, "80", &hints, &info) == 0)
- {
- struct addrinfo* current = info;
- while(title->fqdn.length == 0 && current != NULL)
- {
- ffStrbufAppendS(&title->fqdn, current->ai_canonname);
- current = current->ai_next;
- }
-
- freeaddrinfo(info);
- }
-}
-#endif
-
-const FFTitleResult* ffDetectTitle(const FFinstance* instance)
-{
- static FFTitleResult result;
-
- static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
- static bool init = false;
- ffThreadMutexLock(&mutex);
- if(init)
- {
- ffThreadMutexUnlock(&mutex);
- return &result;
- }
- init = true;
-
- ffStrbufInit(&result.userName);
- ffStrbufAppendS(&result.userName, instance->state.passwd->pw_name);
-
- ffStrbufInitA(&result.hostname, HOST_NAME_MAX);
- ffStrbufAppendS(&result.hostname, instance->state.utsname.nodename);
-
- ffStrbufInitA(&result.fqdn, HOST_NAME_MAX);
- #ifdef __linux__
- detectFQDN(&result);
- #endif
- if(result.fqdn.length == 0)
- ffStrbufAppend(&result.fqdn, &result.hostname);
-
- ffThreadMutexUnlock(&mutex);
- return &result;
-}
diff --git a/src/detection/title.h b/src/detection/title.h
deleted file mode 100644
index 9dc31d312..000000000
--- a/src/detection/title.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#ifndef FF_INCLUDED_detection_title
-#define FF_INCLUDED_detection_title
-
-#include "fastfetch.h"
-
-typedef struct FFTitleResult
-{
- FFstrbuf userName;
- FFstrbuf hostname;
- FFstrbuf fqdn; //Fully qualified domain name
-} FFTitleResult;
-
-const FFTitleResult* ffDetectTitle(const FFinstance* instance);
-
-#endif
diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c
index 7ed1c70fa..5c78cfdd7 100644
--- a/src/detection/users/users_windows.c
+++ b/src/detection/users/users_windows.c
@@ -2,7 +2,6 @@
#include "util/windows/unicode.h"
#include
-#include "wtsapi32_extend.h"
void ffDetectUsers(FFlist* users, FFstrbuf* error)
{
diff --git a/src/detection/users/wtsapi32_extend.h b/src/detection/users/wtsapi32_extend.h
deleted file mode 100644
index 5c89beb2f..000000000
--- a/src/detection/users/wtsapi32_extend.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-//at the time of writing, of MinGW doesn't have the definition of WTSEnumerateSessionsExW and friends
-
-#if (_WIN32_WINNT >= 0x0601)
-
-typedef struct _WTS_SESSION_INFO_1A {
- DWORD ExecEnvId;
- WTS_CONNECTSTATE_CLASS State;
- DWORD SessionId;
- LPSTR pSessionName;
- LPSTR pHostName;
- LPSTR pUserName;
- LPSTR pDomainName;
- LPSTR pFarmName;
-} WTS_SESSION_INFO_1A, *PWTS_SESSION_INFO_1A;
-
-typedef struct _WTS_SESSION_INFO_1W {
- DWORD ExecEnvId;
- WTS_CONNECTSTATE_CLASS State;
- DWORD SessionId;
- LPWSTR pSessionName;
- LPWSTR pHostName;
- LPWSTR pUserName;
- LPWSTR pDomainName;
- LPWSTR pFarmName;
-} WTS_SESSION_INFO_1W, * PWTS_SESSION_INFO_1W;
-
-#define WTS_SESSION_INFO_1 __MINGW_NAME_AW(WTS_SESSION_INFO_1)
-#define PWTS_SESSION_INFO_1 __MINGW_NAME_AW(PWTS_SESSION_INFO_1)
-
-WINBOOL WINAPI WTSEnumerateSessionsExA(HANDLE hServer,DWORD* pLevel,DWORD Filter,PWTS_SESSION_INFO_1A* ppSessionInfo,DWORD* pCount);
-WINBOOL WINAPI WTSEnumerateSessionsExW(HANDLE hServer,DWORD* pLevel,DWORD Filter,PWTS_SESSION_INFO_1W* ppSessionInfo,DWORD* pCount);
-#define WTSEnumerateSessionsEx __MINGW_NAME_AW(WTSEnumerateSessionsEx)
-
-typedef enum _WTS_TYPE_CLASS {
- WTSTypeProcessInfoLevel0,
- WTSTypeProcessInfoLevel1,
- WTSTypeSessionInfoLevel1
-} WTS_TYPE_CLASS;
-BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass,PVOID pMemory,ULONG NumberOfEntries);
-BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass,PVOID pMemory,ULONG NumberOfEntries);
-#define WTSFreeMemoryEx __MINGW_NAME_AW(WTSFreeMemoryEx)
-
-#endif /*(_WIN32_WINNT >= 0x0601)*/
diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c
index 4119280a7..dbda127bb 100644
--- a/src/detection/vulkan.c
+++ b/src/detection/vulkan.c
@@ -190,6 +190,11 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
ffStrbufInit(&gpu->name);
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
+ if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
+ gpu->type = FF_GPU_TYPE_INTEGRATED;
+ else
+ gpu->type = FF_GPU_TYPE_DISCRETE;
+
//No way to detect those using vulkan
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->driver);
diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h
index 375299a76..fae5c46ce 100644
--- a/src/detection/wifi/wifi.h
+++ b/src/detection/wifi/wifi.h
@@ -16,24 +16,17 @@ struct FFWifiConnection
FFstrbuf status;
FFstrbuf ssid;
FFstrbuf macAddress;
- FFstrbuf phyType;
+ FFstrbuf protocol;
+ FFstrbuf security;
double signalQuality; // Percentage
double rxRate;
double txRate;
};
-struct FFWifiSecurity
-{
- bool enabled;
- bool oneXEnabled;
- FFstrbuf algorithm;
-};
-
typedef struct FFWifiResult
{
struct FFWifiInterface inf;
struct FFWifiConnection conn;
- struct FFWifiSecurity security;
} FFWifiResult;
const char* ffDetectWifi(const FFinstance* instance, FFlist* result /*list of FFWifiItem*/);
diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c
new file mode 100644
index 000000000..af1012fe7
--- /dev/null
+++ b/src/detection/wifi/wifi_android.c
@@ -0,0 +1,62 @@
+#include "wifi.h"
+
+#include "common/processing.h"
+#include "common/properties.h"
+
+const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result)
+{
+ FF_STRBUF_AUTO_DESTROY buffer;
+ ffStrbufInit(&buffer);
+
+ if(ffProcessAppendStdOut(&buffer, (char* const[]){
+ FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api",
+ "WifiConnectionInfo"
+ }))
+ return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " WifiConnectionInfo` failed";
+
+ FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
+ ffStrbufInit(&item->inf.description);
+ ffStrbufInit(&item->inf.status);
+ ffStrbufInit(&item->conn.status);
+ ffStrbufInit(&item->conn.ssid);
+ ffStrbufInit(&item->conn.macAddress);
+ 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;
+
+ if(!ffParsePropLines(buffer.chars, "\"supplicant_state\": ", &item->inf.status))
+ ffStrbufAppendS(&item->inf.status, "Unknown");
+
+ {
+ ffStrbufTrimRight(&item->inf.status, ',');
+ ffStrbufTrim(&item->inf.status, '"');
+ if(!ffStrbufEqualS(&item->inf.status, "COMPLETED"))
+ return NULL;
+ }
+
+ if(ffParsePropLines(buffer.chars, "\"rssi\": ", &item->inf.description))
+ {
+ double rssi = ffStrbufToDouble(&item->inf.description);
+ item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2;
+ ffStrbufClear(&item->inf.description);
+ }
+
+ if(ffParsePropLines(buffer.chars, "\"network_id\": ", &item->inf.description))
+ ffStrbufTrimRight(&item->inf.description, ',');
+
+ if(ffParsePropLines(buffer.chars, "\"bssid\": ", &item->conn.macAddress))
+ {
+ ffStrbufTrimRight(&item->conn.macAddress, ',');
+ ffStrbufTrim(&item->conn.macAddress, '"');
+ }
+
+ if(ffParsePropLines(buffer.chars, "\"ssid\": ", &item->conn.ssid))
+ {
+ ffStrbufTrimRight(&item->conn.ssid, ',');
+ ffStrbufTrim(&item->conn.ssid, '"');
+ }
+
+ return NULL;
+}
diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m
index 4f09ae1a7..a83f79485 100644
--- a/src/detection/wifi/wifi_apple.m
+++ b/src/detection/wifi/wifi_apple.m
@@ -10,9 +10,6 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result)
if(!interfaces)
return "CWWiFiClient.sharedWiFiClient.interfaces is nil";
- if(interfaces.count == 0)
- return "No wifi interfaces found";
-
for(CWInterface* inf in interfaces)
{
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
@@ -21,13 +18,11 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result)
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
- ffStrbufInit(&item->conn.phyType);
+ 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->security.enabled = false;
- item->security.oneXEnabled = false;
- ffStrbufInit(&item->security.algorithm);
ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String);
ffStrbufAppendS(&item->inf.status, inf.powerOn ? "Power On" : "Power Off");
@@ -43,88 +38,88 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result)
switch(inf.activePHYMode)
{
case kCWPHYModeNone:
- ffStrbufAppendS(&item->conn.phyType, "none");
+ ffStrbufAppendS(&item->conn.protocol, "none");
break;
case kCWPHYMode11a:
- ffStrbufAppendS(&item->conn.phyType, "802.11a");
+ ffStrbufAppendS(&item->conn.protocol, "802.11a");
break;
case kCWPHYMode11b:
- ffStrbufAppendS(&item->conn.phyType, "802.11b");
+ ffStrbufAppendS(&item->conn.protocol, "802.11b");
break;
case kCWPHYMode11g:
- ffStrbufAppendS(&item->conn.phyType, "802.11g");
+ ffStrbufAppendS(&item->conn.protocol, "802.11g");
break;
case kCWPHYMode11n:
- ffStrbufAppendS(&item->conn.phyType, "802.11n (Wi-Fi 4)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11n (Wi-Fi 4)");
break;
case kCWPHYMode11ac:
- ffStrbufAppendS(&item->conn.phyType, "802.11ac (Wi-Fi 5)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
break;
case 6 /*kCWPHYMode11ax*/:
- ffStrbufAppendS(&item->conn.phyType, "802.11ax (Wi-Fi 6)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
break;
case 7 /*kCWPHYMode11be?*/:
- ffStrbufAppendS(&item->conn.phyType, "802.11be (Wi-Fi 7)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11be (Wi-Fi 7)");
break;
default:
- ffStrbufAppendF(&item->conn.phyType, "Unknown (%ld)", inf.activePHYMode);
+ ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode);
break;
}
item->conn.signalQuality = inf.rssiValue >= -50 ? 100 : inf.rssiValue <= -100 ? 0 : (inf.rssiValue + 100) * 2;
item->conn.txRate = inf.transmitRate;
- item->security.enabled = inf.security != kCWSecurityNone;
+
switch(inf.security)
{
case kCWSecurityNone:
- ffStrbufAppendS(&item->security.algorithm, "None");
+ ffStrbufAppendS(&item->conn.security, "Insecure");
break;
case kCWSecurityWEP:
- ffStrbufAppendS(&item->security.algorithm, "WEP");
+ ffStrbufAppendS(&item->conn.security, "WEP");
break;
case kCWSecurityWPAPersonal:
- ffStrbufAppendS(&item->security.algorithm, "WPA Personal");
+ ffStrbufAppendS(&item->conn.security, "WPA Personal");
break;
case kCWSecurityWPAPersonalMixed:
- ffStrbufAppendS(&item->security.algorithm, "WPA Persional Mixed");
+ ffStrbufAppendS(&item->conn.security, "WPA Persional Mixed");
break;
case kCWSecurityWPA2Personal:
- ffStrbufAppendS(&item->security.algorithm, "WPA2 Personal");
+ ffStrbufAppendS(&item->conn.security, "WPA2 Personal");
break;
case kCWSecurityPersonal:
- ffStrbufAppendS(&item->security.algorithm, "Personal");
+ ffStrbufAppendS(&item->conn.security, "Personal");
break;
case kCWSecurityDynamicWEP:
- ffStrbufAppendS(&item->security.algorithm, "Dynamic WEP");
+ ffStrbufAppendS(&item->conn.security, "Dynamic WEP");
break;
case kCWSecurityWPAEnterprise:
- ffStrbufAppendS(&item->security.algorithm, "WPA Enterprise");
+ ffStrbufAppendS(&item->conn.security, "WPA Enterprise");
break;
case kCWSecurityWPAEnterpriseMixed:
- ffStrbufAppendS(&item->security.algorithm, "WPA Enterprise Mixed");
+ ffStrbufAppendS(&item->conn.security, "WPA Enterprise Mixed");
break;
case kCWSecurityWPA2Enterprise:
- ffStrbufAppendS(&item->security.algorithm, "WPA2 Enterprise");
+ ffStrbufAppendS(&item->conn.security, "WPA2 Enterprise");
break;
case kCWSecurityEnterprise:
- ffStrbufAppendS(&item->security.algorithm, "Enterprise");
+ ffStrbufAppendS(&item->conn.security, "Enterprise");
break;
case kCWSecurityWPA3Personal:
- ffStrbufAppendS(&item->security.algorithm, "WPA3 Personal");
+ ffStrbufAppendS(&item->conn.security, "WPA3 Personal");
break;
case kCWSecurityWPA3Enterprise:
- ffStrbufAppendS(&item->security.algorithm, "WPA3 Enterprise");
+ ffStrbufAppendS(&item->conn.security, "WPA3 Enterprise");
break;
case kCWSecurityWPA3Transition:
- ffStrbufAppendS(&item->security.algorithm, "WPA3 Transition");
+ ffStrbufAppendS(&item->conn.security, "WPA3 Transition");
break;
case 14 /*kCWSecurityOWE*/:
- ffStrbufAppendS(&item->security.algorithm, "OWE");
+ ffStrbufAppendS(&item->conn.security, "OWE");
break;
case 15 /*kCWSecurityOWETransition*/:
- ffStrbufAppendS(&item->security.algorithm, "OWE Transition");
+ ffStrbufAppendS(&item->conn.security, "OWE Transition");
break;
default:
- ffStrbufAppendF(&item->security.algorithm, "Unknown (%ld)", inf.security);
+ ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security);
break;
}
}
diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c
index 985ba6f74..a8f70620d 100644
--- a/src/detection/wifi/wifi_linux.c
+++ b/src/detection/wifi/wifi_linux.c
@@ -1,20 +1,214 @@
#include "wifi.h"
-#include "common/io.h"
-#include
-#include
+#include
+#include
-static const char* detectInf(uint32_t ifIndex, FFWifiResult* wifi)
+#ifdef FF_HAVE_LIBNM
+
+#include "common/processing.h"
+#include "common/properties.h"
+#include "common/library.h"
+
+#include
+#define NM_NO_INCLUDE_EXTRA_HEADERS 1
+#include
+
+static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* result)
{
- //TODO: play with netlink
- FF_UNUSED(ifIndex, wifi);
- return "Unimplemented";
+ FF_LIBRARY_LOAD(nm, &instance->config.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_new);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_get_devices);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_iface);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_state);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_type);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_active_access_point);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_ssid);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_utils_ssid_to_utf8);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_bssid);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_strength);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_max_bitrate);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_flags);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_wpa_flags);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_rsn_flags);
+
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_type_check_instance_is_a);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_size);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_data);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_free);
+ FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_object_unref);
+
+ NMClient* client = ffnm_client_new(NULL, NULL);
+ if(!client)
+ {
+ dlclose(nm);
+ return "Could not create NMClient";
+ }
+
+ /* Get all devices managed by NetworkManager */
+ const GPtrArray* devices = ffnm_client_get_devices(client);
+
+ /* Go through the array and process Wi-Fi devices */
+ for (guint i = 0; i < devices->len; i++)
+ {
+ NMDevice *device = g_ptr_array_index(devices, i);
+ if (!({
+ GTypeInstance *__inst = (GTypeInstance*) device; GType __t = ffnm_device_wifi_get_type(); gboolean __r;
+ if (!__inst)
+ __r = FALSE;
+ else if (__inst->g_class && __inst->g_class->g_type == __t)
+ __r = TRUE;
+ else
+ __r = ffg_type_check_instance_is_a (__inst, __t);
+ __r;
+ }) //NM_IS_DEVICE_WIFI(device)
+ )
+ continue;
+
+ FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
+ ffStrbufInit(&item->inf.description);
+ ffStrbufInit(&item->inf.status);
+ ffStrbufInit(&item->conn.status);
+ ffStrbufInit(&item->conn.ssid);
+ ffStrbufInit(&item->conn.macAddress);
+ 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;
+
+ ffStrbufAppendS(&item->inf.description, ffnm_device_get_iface(device));
+ NMDeviceState state = ffnm_device_get_state(device);
+ switch(state)
+ {
+ case NM_DEVICE_STATE_UNKNOWN:
+ ffStrbufAppendS(&item->inf.status, "Unknown");
+ break;
+ case NM_DEVICE_STATE_UNMANAGED:
+ ffStrbufAppendS(&item->inf.status, "Unmanaged");
+ break;
+ case NM_DEVICE_STATE_UNAVAILABLE:
+ ffStrbufAppendS(&item->inf.status, "Unavailable");
+ break;
+ case NM_DEVICE_STATE_DISCONNECTED:
+ ffStrbufAppendS(&item->inf.status, "Disconnected");
+ break;
+ case NM_DEVICE_STATE_PREPARE:
+ ffStrbufAppendS(&item->inf.status, "Prepare");
+ break;
+ case NM_DEVICE_STATE_CONFIG:
+ ffStrbufAppendS(&item->inf.status, "Config");
+ break;
+ case NM_DEVICE_STATE_NEED_AUTH:
+ ffStrbufAppendS(&item->inf.status, "Need auth");
+ break;
+ case NM_DEVICE_STATE_IP_CONFIG:
+ ffStrbufAppendS(&item->inf.status, "IP config");
+ break;
+ case NM_DEVICE_STATE_IP_CHECK:
+ ffStrbufAppendS(&item->inf.status, "IP check");
+ break;
+ case NM_DEVICE_STATE_SECONDARIES:
+ ffStrbufAppendS(&item->inf.status, "Secondaries");
+ break;
+ case NM_DEVICE_STATE_ACTIVATED:
+ ffStrbufAppendS(&item->inf.status, "Activated");
+ break;
+ case NM_DEVICE_STATE_DEACTIVATING:
+ ffStrbufAppendS(&item->inf.status, "Deactivating");
+ break;
+ case NM_DEVICE_STATE_FAILED:
+ ffStrbufAppendS(&item->inf.status, "Failed");
+ break;
+ }
+ if(state != NM_DEVICE_STATE_ACTIVATED)
+ continue;
+
+ NMAccessPoint* ap = ffnm_device_wifi_get_active_access_point((NMDeviceWifi *) device);
+ if (!ap)
+ continue;
+
+ GBytes* activeSsid = ffnm_access_point_get_ssid(ap);
+ if (activeSsid)
+ {
+ char* ssid = ffnm_utils_ssid_to_utf8(ffg_bytes_get_data(activeSsid, NULL), ffg_bytes_get_size(activeSsid));
+ ffStrbufAppendS(&item->conn.ssid, ssid);
+ ffg_free(ssid);
+ }
+
+ ffStrbufAppendS(&item->conn.macAddress, ffnm_access_point_get_bssid(ap));
+ item->conn.signalQuality = ffnm_access_point_get_strength(ap);
+ item->conn.rxRate = ffnm_access_point_get_max_bitrate(ap);
+
+ if(instance->config.allowSlowOperations)
+ {
+ FF_STRBUF_AUTO_DESTROY output;
+ ffStrbufInit(&output);
+ if(!ffProcessAppendStdOut(&output, (char* const[]){
+ "iw",
+ "dev",
+ item->inf.description.chars,
+ "link",
+ NULL
+ }) && ffParsePropLines(output.chars, "tx bitrate: ", &item->conn.protocol))
+ {
+ if(ffStrbufContainS(&item->conn.protocol, " HE-MCS "))
+ ffStrbufSetS(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
+ else if(ffStrbufContainS(&item->conn.protocol, " VHT-MCS "))
+ ffStrbufSetS(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
+ else if(ffStrbufContainS(&item->conn.protocol, " MCS "))
+ ffStrbufSetS(&item->conn.protocol, "802.11n (Wi-Fi 4)");
+ else
+ ffStrbufSetS(&item->conn.protocol, "802.11a/b/g");
+ }
+ }
+
+ NM80211ApFlags flags = ffnm_access_point_get_flags(ap);
+ NM80211ApSecurityFlags wpaFlags = ffnm_access_point_get_wpa_flags(ap);
+ NM80211ApSecurityFlags rsnFlags = ffnm_access_point_get_rsn_flags(ap);
+
+ if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE)
+ && (rsnFlags == NM_802_11_AP_SEC_NONE))
+ ffStrbufAppendS(&item->conn.security, "WEP ");
+ if (wpaFlags != NM_802_11_AP_SEC_NONE)
+ ffStrbufAppendS(&item->conn.security, "WPA ");
+ if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
+ || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
+ ffStrbufAppendS(&item->conn.security, "WPA2 ");
+ }
+ if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) {
+ ffStrbufAppendS(&item->conn.security, "WPA3 ");
+ }
+ if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE)
+ || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) {
+ ffStrbufAppendS(&item->conn.security, "OWE ");
+ }
+ if ((wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+ || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
+ ffStrbufAppendS(&item->conn.security, "802.1X ");
+ }
+ if (!item->conn.security.length)
+ ffStrbufAppendS(&item->conn.security, "Insecure");
+ else
+ ffStrbufTrimRight(&item->conn.security, ' ');
+ }
+
+ ffg_object_unref(client);
+ dlclose(nm);
+
+ return NULL;
}
-const char* ffDetectWifi(const FFinstance* instance, FFlist* result)
-{
- FF_UNUSED(instance);
+#endif
+#include "common/io.h"
+
+#include
+#include
+#include
+#include
+
+static const char* detectWifiWithIoctls(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result)
+{
struct if_nameindex* infs = if_nameindex();
if(!infs)
return "if_nameindex() failed";
@@ -34,28 +228,93 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result)
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
- ffStrbufInit(&item->conn.phyType);
+ 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->security.enabled = false;
- item->security.oneXEnabled = false;
- ffStrbufInit(&item->security.algorithm);
ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name);
if(!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up"))
continue;
- ffStrbufSetF(&path, "/sys/class/net/%s/address", i->if_name);
- ffAppendFileBuffer(path.chars, &item->conn.macAddress);
+ int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if(sock < 0)
+ continue;
- detectInf(i->if_index, item);
+ struct iwreq iwr;
+ strncpy(iwr.ifr_name, i->if_name, IFNAMSIZ);
+ ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE);
+ iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars;
+ iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ iwr.u.essid.flags = 0;
+ if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0)
+ ffStrbufRecalculateLength(&item->conn.ssid);
+
+ if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0)
+ {
+ if(strncasecmp(iwr.u.name, "IEEE ", 5) == 0)
+ ffStrbufSetS(&item->conn.protocol, iwr.u.name + 5);
+ else
+ ffStrbufSetS(&item->conn.protocol, iwr.u.name);
+ }
+
+ if(ioctl(sock, SIOCGIWAP, &iwr) >= 0)
+ {
+ for(int i = 0; i < 6; ++i)
+ ffStrbufAppendF(&item->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]);
+ ffStrbufTrimRight(&item->conn.macAddress, '-');
+ }
+
+ //FIXME: doesn't work
+ if(ioctl(sock, SIOCGIWSPY, &iwr) >= 0)
+ item->conn.signalQuality = iwr.u.qual.level;
+
+ //FIXME: doesn't work
+ struct iw_encode_ext iwe;
+ iwr.u.data.pointer = &iwe;
+ iwr.u.data.length = sizeof(iwe);
+ iwr.u.data.flags = 0;
+ if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0)
+ {
+ struct iw_encode_ext* iwe = iwr.u.data.pointer;
+ switch(iwe->alg)
+ {
+ case IW_ENCODE_ALG_WEP:
+ ffStrbufAppendS(&item->conn.security, "WEP");
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ ffStrbufAppendS(&item->conn.security, "TKIP");
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ ffStrbufAppendS(&item->conn.security, "CCMP");
+ break;
+ case IW_ENCODE_ALG_PMK:
+ ffStrbufAppendS(&item->conn.security, "PMK");
+ break;
+ case IW_ENCODE_ALG_AES_CMAC:
+ ffStrbufAppendS(&item->conn.security, "CMAC");
+ break;
+ default:
+ ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe->alg);
+ break;
+ }
+ }
+
+ close(sock);
}
if_freenameindex(infs);
ffStrbufDestroy(&path);
- if(result->length == 0)
- return "No wifi interfaces found";
-
return NULL;
}
+
+const char* ffDetectWifi(const FFinstance* instance, FFlist* result)
+{
+ #ifdef FF_HAVE_LIBNM
+ if(!detectWifiWithLibnm(instance, result))
+ return NULL;
+ #endif
+
+ return detectWifiWithIoctls(instance, result);
+}
diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c
index 92322440f..70d7ea577 100644
--- a/src/detection/wifi/wifi_windows.c
+++ b/src/detection/wifi/wifi_windows.c
@@ -40,7 +40,7 @@ static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result)
}
}
-const char* ffDetectWifi(FF_UNUSED_PARAM const FFinstance* instance, FFlist* result)
+const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result)
{
FF_LIBRARY_LOAD(wlanapi, NULL, "dlopen wlanapi"FF_LIBRARY_EXTENSION" failed", "wlanapi"FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle)
@@ -66,12 +66,6 @@ const char* ffDetectWifi(FF_UNUSED_PARAM const FFinstance* instance, FFlist* res
goto exit;
}
- if(ifList->dwNumberOfItems == 0)
- {
- error = "No wifi interfaces found";
- goto exit;
- }
-
for(uint32_t index = 0; index < ifList->dwNumberOfItems; ++index)
{
WLAN_INTERFACE_INFO* ifInfo = (WLAN_INTERFACE_INFO*)&ifList->InterfaceInfo[index];
@@ -82,13 +76,11 @@ const char* ffDetectWifi(FF_UNUSED_PARAM const FFinstance* instance, FFlist* res
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
- ffStrbufInit(&item->conn.phyType);
+ 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->security.enabled = false;
- item->security.oneXEnabled = false;
- ffStrbufInit(&item->security.algorithm);
ffStrbufSetWS(&item->inf.description, ifInfo->strInterfaceDescription);
convertIfStateToString(ifInfo->isState, &item->inf.status);
@@ -121,40 +113,40 @@ const char* ffDetectWifi(FF_UNUSED_PARAM const FFinstance* instance, FFlist* res
switch (connInfo->wlanAssociationAttributes.dot11PhyType)
{
case dot11_phy_type_fhss:
- ffStrbufAppendS(&item->conn.phyType, "802.11 (FHSS)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11 (FHSS)");
break;
case dot11_phy_type_dsss:
- ffStrbufAppendS(&item->conn.phyType, "802.11 (DSSS)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11 (DSSS)");
break;
case dot11_phy_type_irbaseband:
- ffStrbufAppendS(&item->conn.phyType, "802.11 (IR)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11 (IR)");
break;
case dot11_phy_type_ofdm:
- ffStrbufAppendS(&item->conn.phyType, "802.11a");
+ ffStrbufAppendS(&item->conn.protocol, "802.11a");
break;
case dot11_phy_type_hrdsss:
- ffStrbufAppendS(&item->conn.phyType, "802.11b");
+ ffStrbufAppendS(&item->conn.protocol, "802.11b");
break;
case dot11_phy_type_erp:
- ffStrbufAppendS(&item->conn.phyType, "802.11g");
+ ffStrbufAppendS(&item->conn.protocol, "802.11g");
break;
case dot11_phy_type_ht:
- ffStrbufAppendS(&item->conn.phyType, "802.11n (Wi-Fi 4)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11n (Wi-Fi 4)");
break;
case 8 /*dot11_phy_type_vht*/:
- ffStrbufAppendS(&item->conn.phyType, "802.11ac (Wi-Fi 5)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
break;
case 9 /*dot11_phy_type_dmg*/:
- ffStrbufAppendS(&item->conn.phyType, "802.11ad (WiGig)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11ad (WiGig)");
break;
case 10 /*dot11_phy_type_he*/:
- ffStrbufAppendS(&item->conn.phyType, "802.11ax (Wi-Fi 6)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
break;
case 11 /*dot11_phy_type_eht*/:
- ffStrbufAppendS(&item->conn.phyType, "802.11be (Wi-Fi 7)");
+ ffStrbufAppendS(&item->conn.protocol, "802.11be (Wi-Fi 7)");
break;
default:
- ffStrbufAppendF(&item->conn.phyType, "Unknown (%u)", (unsigned)connInfo->wlanAssociationAttributes.dot11PhyType);
+ ffStrbufAppendF(&item->conn.protocol, "Unknown (%u)", (unsigned)connInfo->wlanAssociationAttributes.dot11PhyType);
break;
}
@@ -162,93 +154,53 @@ const char* ffDetectWifi(FF_UNUSED_PARAM const FFinstance* instance, FFlist* res
item->conn.rxRate = connInfo->wlanAssociationAttributes.ulRxRate;
item->conn.txRate = connInfo->wlanAssociationAttributes.ulTxRate;
- item->security.enabled = connInfo->wlanSecurityAttributes.bSecurityEnabled;
- item->security.oneXEnabled = connInfo->wlanSecurityAttributes.bOneXEnabled;
- switch (connInfo->wlanSecurityAttributes.dot11AuthAlgorithm)
+ if(connInfo->wlanSecurityAttributes.bSecurityEnabled)
{
- case DOT11_AUTH_ALGO_80211_OPEN:
- ffStrbufAppendS(&item->security.algorithm, "802.11 Open");
- break;
- case DOT11_AUTH_ALGO_80211_SHARED_KEY:
- ffStrbufAppendS(&item->security.algorithm, "802.11 Shared");
- break;
- case DOT11_AUTH_ALGO_WPA:
- ffStrbufAppendS(&item->security.algorithm, "WPA");
- break;
- case DOT11_AUTH_ALGO_WPA_PSK:
- ffStrbufAppendS(&item->security.algorithm, "WPA-PSK");
- break;
- case DOT11_AUTH_ALGO_WPA_NONE:
- ffStrbufAppendS(&item->security.algorithm, "WPA-None");
- break;
- case DOT11_AUTH_ALGO_RSNA:
- ffStrbufAppendS(&item->security.algorithm, "RSNA");
- break;
- case DOT11_AUTH_ALGO_RSNA_PSK:
- ffStrbufAppendS(&item->security.algorithm, "RSNA with PSK");
- break;
- case 8 /* DOT11_AUTH_ALGO_WPA3 */:
- ffStrbufAppendS(&item->security.algorithm, "WPA3");
- break;
- case 9 /* DOT11_AUTH_ALGO_WPA3_SAE */:
- ffStrbufAppendS(&item->security.algorithm, "WPA3-SAE");
- break;
- case 10 /* DOT11_AUTH_ALGO_OWE */:
- ffStrbufAppendS(&item->security.algorithm, "OWE");
- break;
- case 11 /* DOT11_AUTH_ALGO_WPA3_ENT */:
- ffStrbufAppendS(&item->security.algorithm, "OWE-ENT");
- break;
- default:
- ffStrbufAppendF(&item->security.algorithm, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11AuthAlgorithm);
- break;
- }
- ffStrbufAppendS(&item->security.algorithm, " - ");
- switch (connInfo->wlanSecurityAttributes.dot11CipherAlgorithm)
- {
- case DOT11_CIPHER_ALGO_NONE:
- ffStrbufAppendS(&item->security.algorithm, "None");
- break;
- case DOT11_CIPHER_ALGO_WEP40:
- ffStrbufAppendS(&item->security.algorithm, "WEP-40");
- break;
- case DOT11_CIPHER_ALGO_TKIP:
- ffStrbufAppendS(&item->security.algorithm, "TKIP");
- break;
- case DOT11_CIPHER_ALGO_CCMP:
- ffStrbufAppendS(&item->security.algorithm, "CCMP");
- break;
- case DOT11_CIPHER_ALGO_WEP104:
- ffStrbufAppendS(&item->security.algorithm, "WEP-104");
- break;
- case 0x06 /* DOT11_CIPHER_ALGO_BIP */:
- ffStrbufAppendS(&item->security.algorithm, "BIP-CMAC-128");
- break;
- case 0x08 /* DOT11_CIPHER_ALGO_GCMP */:
- ffStrbufAppendS(&item->security.algorithm, "GCMP-128");
- break;
- case 0x09 /* DOT11_CIPHER_ALGO_GCMP_256 */:
- ffStrbufAppendS(&item->security.algorithm, "GCMP-256");
- break;
- case 0x0a /* DOT11_CIPHER_ALGO_CCMP_256 */:
- ffStrbufAppendS(&item->security.algorithm, "CCMP-256");
- break;
- case 0x0b /* DOT11_CIPHER_ALGO_BIP_GMAC_128 */:
- ffStrbufAppendS(&item->security.algorithm, "BIP-GMAC-128");
- break;
- case 0x0c /* DOT11_CIPHER_ALGO_BIP_GMAC_256 */:
- ffStrbufAppendS(&item->security.algorithm, "BIP-GMAC-256");
- break;
- case 0x0d /* DOT11_CIPHER_ALGO_BIP_CMAC_256 */:
- ffStrbufAppendS(&item->security.algorithm, "BIP-CMAC-256");
- break;
- case DOT11_CIPHER_ALGO_WEP:
- ffStrbufAppendS(&item->security.algorithm, "WEP");
- break;
- default:
- ffStrbufAppendF(&item->security.algorithm, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11CipherAlgorithm);
- break;
+ switch (connInfo->wlanSecurityAttributes.dot11AuthAlgorithm)
+ {
+ case DOT11_AUTH_ALGO_80211_OPEN:
+ ffStrbufAppendS(&item->conn.security, "802.11 Open");
+ break;
+ case DOT11_AUTH_ALGO_80211_SHARED_KEY:
+ ffStrbufAppendS(&item->conn.security, "802.11 Shared");
+ break;
+ case DOT11_AUTH_ALGO_WPA:
+ ffStrbufAppendS(&item->conn.security, "WPA");
+ break;
+ case DOT11_AUTH_ALGO_WPA_PSK:
+ ffStrbufAppendS(&item->conn.security, "WPA-PSK");
+ break;
+ case DOT11_AUTH_ALGO_WPA_NONE:
+ ffStrbufAppendS(&item->conn.security, "WPA-None");
+ break;
+ case DOT11_AUTH_ALGO_RSNA:
+ ffStrbufAppendS(&item->conn.security, "WPA2");
+ break;
+ case DOT11_AUTH_ALGO_RSNA_PSK:
+ ffStrbufAppendS(&item->conn.security, "WPA2-PSK");
+ break;
+ case 8 /* DOT11_AUTH_ALGO_WPA3 */:
+ ffStrbufAppendS(&item->conn.security, "WPA3");
+ break;
+ case 9 /* DOT11_AUTH_ALGO_WPA3_SAE */:
+ ffStrbufAppendS(&item->conn.security, "WPA3-SAE");
+ break;
+ case 10 /* DOT11_AUTH_ALGO_OWE */:
+ ffStrbufAppendS(&item->conn.security, "OWE");
+ break;
+ case 11 /* DOT11_AUTH_ALGO_WPA3_ENT */:
+ ffStrbufAppendS(&item->conn.security, "OWE-ENT");
+ break;
+ default:
+ ffStrbufAppendF(&item->conn.security, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11AuthAlgorithm);
+ break;
+ }
+ if(connInfo->wlanSecurityAttributes.bOneXEnabled)
+ ffStrbufAppendS(&item->conn.security, " 802.11X");
}
+ else
+ ffStrbufAppendS(&item->conn.security, "Insecure");
+
ffWlanFreeMemory(connInfo);
}
diff --git a/src/detection/wmtheme/wmtheme_apple.m b/src/detection/wmtheme/wmtheme_apple.m
index d0b099790..437d6ed97 100644
--- a/src/detection/wmtheme/wmtheme_apple.m
+++ b/src/detection/wmtheme/wmtheme_apple.m
@@ -9,7 +9,7 @@ static bool detectQuartzCompositor(FFinstance* instance, FFstrbuf* themeOrError)
FF_UNUSED(instance);
NSError* error;
- NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/.GlobalPreferences.plist", instance->state.passwd->pw_dir];
+ NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/.GlobalPreferences.plist", instance->state.platform.homeDir.chars];
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
error:&error];
if(error)
diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c
index 19765c79a..6efba12c5 100644
--- a/src/detection/wmtheme/wmtheme_linux.c
+++ b/src/detection/wmtheme/wmtheme_linux.c
@@ -131,9 +131,9 @@ static bool detectOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName, FF
{
FFstrbuf absolutePath;
ffStrbufInitA(&absolutePath, 64);
- ffStrbufAppendS(&absolutePath, instance->state.passwd->pw_dir);
- ffStrbufAppendC(&absolutePath, '/');
+ ffStrbufAppend(&absolutePath, &instance->state.platform.homeDir);
+ //TODO: use config dirs
if(ffStrbufIgnCaseCompS(dePrettyName, "LXQT") == 0)
ffStrbufAppendS(&absolutePath, ".config/openbox/lxqt-rc.xml");
else if(ffStrbufIgnCaseCompS(dePrettyName, "LXDE") == 0)
diff --git a/src/fastfetch.c b/src/fastfetch.c
index fd36ebc1d..18c130ef2 100644
--- a/src/fastfetch.c
+++ b/src/fastfetch.c
@@ -174,12 +174,13 @@ static inline void printCommandHelp(const char* command)
"User shell version"
);
}
- else if(strcasecmp(command, "resolution-format") == 0)
+ else if(strcasecmp(command, "display-format") == 0)
{
- constructAndPrintCommandHelpFormat("resolution", "{}x{} @ {}Hz", 3,
+ constructAndPrintCommandHelpFormat("display", "{}x{} @ {}Hz", 4,
"Screen width",
"Screen height",
- "Screen refresh rate"
+ "Screen refresh rate",
+ "Screen brightness"
);
}
else if(strcasecmp(command, "de-format") == 0)
@@ -287,12 +288,13 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "gpu-format") == 0)
{
- constructAndPrintCommandHelpFormat("gpu", "{} {}", 5,
+ constructAndPrintCommandHelpFormat("gpu", "{} {}", 6,
"GPU vendor",
"GPU name",
"GPU driver",
"GPU temperature",
- "GPU core count"
+ "GPU core count",
+ "GPU type"
);
}
else if(strcasecmp(command, "memory-format") == 0)
@@ -371,13 +373,11 @@ static inline void printCommandHelp(const char* command)
"Connection status",
"Connection SSID",
"Connection mac address",
- "Connection PHY type",
+ "Connection protocol",
"Connection signal quality (percentage)",
"Connection RX rate",
"Connection TX rate",
- "Security enabled",
- "Security 802.1X enabled",
- "Security algorithm"
+ "Connection Security algorithm"
);
}
else if(strcasecmp(command, "player-format") == 0)
@@ -525,17 +525,29 @@ static inline void listAvailablePresetsFromFolder(FFstrbuf* folder, uint8_t inde
static inline void listAvailablePresets(FFinstance* instance)
{
- FFstrbuf folder;
- ffStrbufInitA(&folder, 64);
+ FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs)
+ {
+ ffStrbufAppendS(path, "fastfetch/presets/");
+ listAvailablePresetsFromFolder(path, 0, NULL);
+ }
+}
- ffStrbufSetS(&folder, instance->state.passwd->pw_dir);
- ffStrbufAppendS(&folder, "/.local/share/fastfetch/presets/");
- listAvailablePresetsFromFolder(&folder, 0, NULL);
+static void listConfigPaths(FFinstance* instance)
+{
+ FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.platform.configDirs)
+ {
+ ffStrbufAppendS(folder, "fastfetch/config.conf");
+ printf("%s%s\n", folder->chars, ffFileExists(folder->chars, S_IFREG) ? " (*)" : "");
+ }
+}
- ffStrbufSetS(&folder, FASTFETCH_TARGET_DIR_USR"/share/fastfetch/presets/");
- listAvailablePresetsFromFolder(&folder, 0, NULL);
-
- ffStrbufDestroy(&folder);
+static void listDataPaths(FFinstance* instance)
+{
+ FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.platform.dataDirs)
+ {
+ ffStrbufAppendS(folder, "fastfetch/");
+ puts(folder->chars);
+ }
}
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value);
@@ -603,6 +615,25 @@ static bool parseConfigFile(FFinstance* instance, FFdata* data, const char* path
return true;
}
+static void generateConfigFile(FFinstance* instance, bool force)
+{
+ FFstrbuf* filename = (FFstrbuf*) ffListGet(&instance->state.platform.configDirs, 0);
+ // Paths generated in `init.c/initConfigDirs` end with `/`
+ ffStrbufAppendS(filename, "fastfetch/config.conf");
+
+ if (!force && ffFileExists(filename->chars, S_IFREG))
+ {
+ fprintf(stderr, "Config file exists in `%s`, use `--gen-config-force` to overwrite\n", filename->chars);
+ exit(1);
+ }
+ else
+ {
+ ffWriteFileData(filename->chars, sizeof(FASTFETCH_DATATEXT_CONFIG_USER), FASTFETCH_DATATEXT_CONFIG_USER);
+ printf("A sample config file has been written in `%s`\n", filename->chars);
+ exit(0);
+ }
+}
+
static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char* key, const char* value)
{
if(value == NULL)
@@ -616,37 +647,29 @@ static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char
if(parseConfigFile(instance, data, value))
return;
- //Try to load as an user preset
+ //Try to load as a relative path
- FFstrbuf filename;
- ffStrbufInitA(&filename, 64);
+ FFstrbuf absolutePath;
+ ffStrbufInitA(&absolutePath, 128);
- ffStrbufAppendS(&filename, instance->state.passwd->pw_dir);
- ffStrbufAppendS(&filename, "/.local/share/fastfetch/presets/");
- ffStrbufAppendS(&filename, value);
-
- if(parseConfigFile(instance, data, filename.chars))
+ FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs)
{
- ffStrbufDestroy(&filename);
- return;
+ //We need to copy it, because if a config file loads a config file, the value of path must be unchanged
+ ffStrbufSet(&absolutePath, path);
+ ffStrbufAppendS(&absolutePath, "fastfetch/presets/");
+ ffStrbufAppendS(&absolutePath, value);
+
+ bool success = parseConfigFile(instance, data, absolutePath.chars);
+
+ if(success)
+ return;
}
-
- //Try to load as a system preset
-
- ffStrbufSetS(&filename, FASTFETCH_TARGET_DIR_USR"/share/fastfetch/presets/");
- ffStrbufAppendS(&filename, value);
-
- if(parseConfigFile(instance, data, filename.chars))
- {
- ffStrbufDestroy(&filename);
- return;
- }
+ ffStrbufDestroy(&absolutePath);
//File not found
fprintf(stderr, "Error: couldn't find config: %s\n", value);
- ffStrbufDestroy(&filename);
exit(414);
}
@@ -836,7 +859,35 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
}
else if(strcasecmp(key, "-v") == 0 || strcasecmp(key, "--version") == 0)
{
- puts("fastfetch "FASTFETCH_PROJECT_VERSION""FASTFETCH_PROJECT_VERSION_TWEAK);
+ #ifndef NDEBUG
+ #define FF_BUILD_TYPE "-debug"
+ #else
+ #define FF_BUILD_TYPE
+ #endif
+
+ #if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64)
+ #define FF_ARCHITECTURE "x86_64"
+ #elif defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(__i586__) || defined(__i586) || defined(__i686__) || defined(__i686)
+ #define FF_ARCHITECTURE "i386"
+ #elif defined(__aarch64__)
+ #define FF_ARCHITECTURE "aarch64"
+ #elif defined(__arm__)
+ #define FF_ARCHITECTURE "arm"
+ #elif defined(__mips__)
+ #define FF_ARCHITECTURE "mips"
+ #elif defined(__powerpc__) || defined(__powerpc)
+ #define FF_ARCHITECTURE "powerpc"
+ #elif defined(__riscv__) || defined(__riscv)
+ #define FF_ARCHITECTURE "riscv"
+ #elif
+ #define FF_ARCHITECTURE "unknown"
+ #endif
+
+ puts("fastfetch " FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK FF_BUILD_TYPE " (" FF_ARCHITECTURE ")");
+
+ #undef FF_ARCHITECTURE
+ #undef FF_BUILD_TYPE
+
exit(0);
}
else if(strcasecmp(key, "--version-raw") == 0)
@@ -883,6 +934,16 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
listAvailablePresets(instance);
exit(0);
}
+ else if(strcasecmp(subkey, "-config-paths") == 0)
+ {
+ listConfigPaths(instance);
+ exit(0);
+ }
+ else if(strcasecmp(subkey, "-data-paths") == 0)
+ {
+ listDataPaths(instance);
+ exit(0);
+ }
else if(strcasecmp(subkey, "-features") == 0)
{
ffListFeatures();
@@ -912,6 +973,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
fputs("`--nocache` are obsoleted. Caching functions other than image caching are removed.\n\n", stderr);
else if(strcasecmp(key, "--load-config") == 0)
optionParseConfigFile(instance, data, key, value);
+ else if(strcasecmp(key, "--gen-config") == 0)
+ generateConfigFile(instance, false);
+ else if(strcasecmp(key, "--gen-config-force") == 0)
+ generateConfigFile(instance, true);
else if(strcasecmp(key, "--thread") == 0 || strcasecmp(key, "--multithreading") == 0)
instance->config.multithreading = optionParseBoolean(value);
else if(strcasecmp(key, "--stat") == 0)
@@ -939,8 +1004,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
//this is usally wanted when using the none logo
if(strcasecmp(value, "none") == 0)
{
+ instance->config.logo.paddingTop = 0;
instance->config.logo.paddingRight = 0;
instance->config.logo.paddingLeft = 0;
+ instance->config.logo.type = FF_LOGO_TYPE_NONE;
}
}
else if(startsWith(key, "--logo"))
@@ -957,7 +1024,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
"data-raw", FF_LOGO_TYPE_DATA_RAW,
"sixel", FF_LOGO_TYPE_IMAGE_SIXEL,
"kitty", FF_LOGO_TYPE_IMAGE_KITTY,
+ "iterm", FF_LOGO_TYPE_IMAGE_ITERM,
"chafa", FF_LOGO_TYPE_IMAGE_CHAFA,
+ "raw", FF_LOGO_TYPE_IMAGE_RAW,
+ "none", FF_LOGO_TYPE_NONE,
NULL
);
}
@@ -985,6 +1055,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
instance->config.logo.paddingLeft = padding;
instance->config.logo.paddingRight = padding;
}
+ else if(strcasecmp(subkey, "-padding-top") == 0)
+ instance->config.logo.paddingTop = optionParseUInt32(key, value);
else if(strcasecmp(subkey, "-padding-left") == 0)
instance->config.logo.paddingLeft = optionParseUInt32(key, value);
else if(strcasecmp(subkey, "-padding-right") == 0)
@@ -1036,6 +1108,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.logo.source);
instance->config.logo.type = FF_LOGO_TYPE_IMAGE_ITERM;
}
+ else if(strcasecmp(key, "--raw") == 0)
+ {
+ optionParseString(key, value, &instance->config.logo.source);
+ instance->config.logo.type = FF_LOGO_TYPE_IMAGE_RAW;
+ }
else if(strcasecmp(key, "--chafa-fg-only") == 0)
instance->config.logo.chafaFgOnly = optionParseBoolean(value);
else if(strcasecmp(key, "--chafa-symbols") == 0)
@@ -1098,7 +1175,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
else if(optionParseModuleArgs(key, value, "processes", &instance->config.processes)) {}
else if(optionParseModuleArgs(key, value, "packages", &instance->config.packages)) {}
else if(optionParseModuleArgs(key, value, "shell", &instance->config.shell)) {}
- else if(optionParseModuleArgs(key, value, "resolution", &instance->config.resolution)) {}
+ else if(optionParseModuleArgs(key, value, "display", &instance->config.display)) {}
+ else if(optionParseModuleArgs(key, value, "brightness", &instance->config.brightness)) {}
else if(optionParseModuleArgs(key, value, "de", &instance->config.de)) {}
else if(optionParseModuleArgs(key, value, "wifi", &instance->config.wifi)) {}
else if(optionParseModuleArgs(key, value, "wm", &instance->config.wm)) {}
@@ -1184,6 +1262,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.libcJSON);
else if(strcasecmp(subkey, "-wlanapi") == 0)
optionParseString(key, value, &instance->config.libwlanapi);
+ else if(strcasecmp(subkey, "-nm") == 0)
+ optionParseString(key, value, &instance->config.libnm);
else
goto error;
}
@@ -1198,14 +1278,26 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
instance->config.gpuTemp = optionParseBoolean(value);
else if(strcasecmp(key, "--battery-temp") == 0)
instance->config.batteryTemp = optionParseBoolean(value);
+ else if(strcasecmp(key, "--gpu-hide-integrated") == 0)
+ instance->config.gpuHideIntegrated = optionParseBoolean(value);
+ else if(strcasecmp(key, "--gpu-hide-discrete") == 0)
+ instance->config.gpuHideDiscrete = optionParseBoolean(value);
else if(strcasecmp(key, "--title-fqdn") == 0)
instance->config.titleFQDN = optionParseBoolean(value);
+ else if(strcasecmp(key, "--shell-version") == 0)
+ instance->config.shellVersion = optionParseBoolean(value);
+ else if(strcasecmp(key, "--terminal-version") == 0)
+ instance->config.terminalVersion = optionParseBoolean(value);
else if(strcasecmp(key, "--disk-folders") == 0)
optionParseString(key, value, &instance->config.diskFolders);
else if(strcasecmp(key, "--disk-show-removable") == 0)
instance->config.diskShowRemovable = optionParseBoolean(value);
else if(strcasecmp(key, "--disk-show-hidden") == 0)
instance->config.diskShowHidden = optionParseBoolean(value);
+ else if(strcasecmp(key, "--disk-show-subvolumes") == 0)
+ instance->config.diskShowSubvolumes = optionParseBoolean(value);
+ else if(strcasecmp(key, "--disk-show-unknown") == 0)
+ instance->config.diskShowUnknown = optionParseBoolean(value);
else if(strcasecmp(key, "--battery-dir") == 0)
optionParseString(key, value, &instance->config.batteryDir);
else if(strcasecmp(key, "--separator-string") == 0)
@@ -1242,6 +1334,20 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
}
else if(strcasecmp(key, "--percent-type") == 0)
instance->config.percentType = optionParseUInt32(key, value);
+ else if(strcasecmp(key, "--command-shell") == 0)
+ optionParseString(key, value, &instance->config.commandShell);
+ else if(strcasecmp(key, "--command-key") == 0)
+ {
+ FFstrbuf* result = (FFstrbuf*) ffListAdd(&instance->config.commandKeys);
+ ffStrbufInit(result);
+ optionParseString(key, value, result);
+ }
+ else if(strcasecmp(key, "--command-text") == 0)
+ {
+ FFstrbuf* result = (FFstrbuf*) ffListAdd(&instance->config.commandTexts);
+ ffStrbufInit(result);
+ optionParseString(key, value, result);
+ }
//////////////////
//Unknown option//
@@ -1255,25 +1361,20 @@ error:
}
}
-static void parseConfigFileSystem(FFinstance* instance, FFdata* data)
+static void parseConfigFiles(FFinstance* instance, FFdata* data)
{
- parseConfigFile(instance, data, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/fastfetch/config.conf");
-}
+ for(uint32_t i = instance->state.platform.configDirs.length; i > 0; --i)
+ {
+ if(!data->loadUserConfig)
+ return;
-static void parseConfigFileUser(FFinstance* instance, FFdata* data)
-{
- if(!data->loadUserConfig)
- return;
+ FFstrbuf* dir = ffListGet(&instance->state.platform.configDirs, i - 1);
+ uint32_t dirLength = dir->length;
- FFstrbuf* filename = ffListGet(&instance->state.configDirs, 0);
- uint32_t filenameLength = filename->length;
-
- ffStrbufAppendS(filename, "/fastfetch/config.conf");
-
- if(!parseConfigFile(instance, data, filename->chars))
- ffWriteFileData(filename->chars, sizeof(FASTFETCH_DATATEXT_CONFIG_USER), FASTFETCH_DATATEXT_CONFIG_USER);
-
- ffStrbufSubstrBefore(filename, filenameLength);
+ ffStrbufAppendS(dir, "fastfetch/config.conf");
+ parseConfigFile(instance, data, dir->chars);
+ ffStrbufSubstrBefore(dir, dirLength);
+ }
}
static void parseArguments(FFinstance* instance, FFdata* data, int argc, const char** argv)
@@ -1320,6 +1421,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
ffPrintBios(instance);
else if(strcasecmp(line, "board") == 0)
ffPrintBoard(instance);
+ else if(strcasecmp(line, "brightness") == 0)
+ ffPrintBrightness(instance);
else if(strcasecmp(line, "chassis") == 0)
ffPrintChassis(instance);
else if(strcasecmp(line, "kernel") == 0)
@@ -1332,8 +1435,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
ffPrintPackages(instance);
else if(strcasecmp(line, "shell") == 0)
ffPrintShell(instance);
- else if(strcasecmp(line, "resolution") == 0)
- ffPrintResolution(instance);
+ else if(strcasecmp(line, "display") == 0)
+ ffPrintDisplay(instance);
else if(strcasecmp(line, "desktopenvironment") == 0 || strcasecmp(line, "de") == 0)
ffPrintDesktopEnvironment(instance);
else if(strcasecmp(line, "windowmanager") == 0 || strcasecmp(line, "wm") == 0)
@@ -1398,6 +1501,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
ffPrintOpenCL(instance);
else if(strcasecmp(line, "users") == 0)
ffPrintUsers(instance);
+ else if(strcasecmp(line, "command") == 0)
+ ffPrintCommand(instance);
else
ffPrintErrorString(instance, line, 0, NULL, NULL, "");
}
@@ -1413,8 +1518,8 @@ int main(int argc, const char** argv)
ffStrbufInitA(&data.structure, 256);
data.loadUserConfig = true;
- parseConfigFileSystem(&instance, &data);
- parseConfigFileUser(&instance, &data);
+ if(!getenv("NO_CONFIG"))
+ parseConfigFiles(&instance, &data);
parseArguments(&instance, &data, argc, argv);
//If we don't have a custom structure, use the default one
@@ -1432,6 +1537,10 @@ int main(int argc, const char** argv)
ffStart(&instance);
+ #if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
+ fflush(stdout);
+ #endif
+
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data.structure.length)
diff --git a/src/fastfetch.h b/src/fastfetch.h
index a99eadc44..69121e4c9 100644
--- a/src/fastfetch.h
+++ b/src/fastfetch.h
@@ -8,20 +8,13 @@
#include
#include
-#ifndef _WIN32
- #include
- #include
-#else
- #include "util/windows/pwd.h"
- #include "util/windows/utsname.h"
-#endif
-
#include "util/FFstrbuf.h"
#include "util/FFlist.h"
+#include "util/platform/FFPlatform.h"
static inline void ffUnused(int dummy, ...) { (void) dummy; }
#define FF_UNUSED(...) ffUnused(0, __VA_ARGS__);
-#define FF_UNUSED_PARAM __attribute__ ((__unused__))
+#define FF_MAYBE_UNUSED __attribute__ ((__unused__))
#define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9)
@@ -37,6 +30,8 @@ typedef enum FFLogoType
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol
FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa
+ FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string
+ FF_LOGO_TYPE_NONE, //--logo none
} FFLogoType;
typedef enum FFBinaryPrefixType
@@ -70,6 +65,7 @@ typedef struct FFconfig
FFstrbuf colors[FASTFETCH_LOGO_MAX_COLORS];
uint32_t width;
uint32_t height;
+ uint32_t paddingTop;
uint32_t paddingLeft;
uint32_t paddingRight;
bool printRemaining;
@@ -103,14 +99,15 @@ typedef struct FFconfig
FFModuleArgs os;
FFModuleArgs host;
FFModuleArgs bios;
- FFModuleArgs chassis;
FFModuleArgs board;
+ FFModuleArgs brightness;
+ FFModuleArgs chassis;
FFModuleArgs kernel;
FFModuleArgs uptime;
FFModuleArgs processes;
FFModuleArgs packages;
FFModuleArgs shell;
- FFModuleArgs resolution;
+ FFModuleArgs display;
FFModuleArgs de;
FFModuleArgs wifi;
FFModuleArgs wm;
@@ -166,16 +163,25 @@ typedef struct FFconfig
FFstrbuf libcJSON;
FFstrbuf libfreetype;
FFstrbuf libwlanapi;
+ FFstrbuf libnm;
bool cpuTemp;
bool gpuTemp;
bool batteryTemp;
+ bool gpuHideIntegrated;
+ bool gpuHideDiscrete;
+
bool titleFQDN;
+ bool shellVersion;
+ bool terminalVersion;
+
FFstrbuf diskFolders;
bool diskShowRemovable;
bool diskShowHidden;
+ bool diskShowUnknown;
+ bool diskShowSubvolumes;
FFstrbuf batteryDir;
@@ -197,6 +203,10 @@ typedef struct FFconfig
FFstrbuf playerName;
uint32_t percentType;
+
+ FFstrbuf commandShell;
+ FFlist commandKeys;
+ FFlist commandTexts;
} FFconfig;
typedef struct FFstate
@@ -205,10 +215,7 @@ typedef struct FFstate
uint32_t logoHeight;
uint32_t keysHeight;
- struct passwd* passwd;
- struct utsname utsname;
-
- FFlist configDirs;
+ FFPlatform platform;
} FFstate;
typedef struct FFinstance
@@ -268,7 +275,8 @@ void ffPrintUptime(FFinstance* instance);
void ffPrintProcesses(FFinstance* instance);
void ffPrintPackages(FFinstance* instance);
void ffPrintShell(FFinstance* instance);
-void ffPrintResolution(FFinstance* instance);
+void ffPrintDisplay(FFinstance* instance);
+void ffPrintBrightness(FFinstance* instance);
void ffPrintDesktopEnvironment(FFinstance* instance);
void ffPrintWM(FFinstance* instance);
void ffPrintWMTheme(FFinstance* instance);
@@ -301,5 +309,6 @@ void ffPrintVulkan(FFinstance* instance);
void ffPrintOpenGL(FFinstance* instance);
void ffPrintOpenCL(FFinstance* instance);
void ffPrintUsers(FFinstance* instance);
+void ffPrintCommand(FFinstance* instance);
#endif
diff --git a/src/flashfetch.c b/src/flashfetch.c
index 196e94bb5..0c24732e3 100644
--- a/src/flashfetch.c
+++ b/src/flashfetch.c
@@ -30,7 +30,8 @@ int main(int argc, char** argv)
//ffPrintProcesses(&instance);
ffPrintPackages(&instance);
ffPrintShell(&instance);
- ffPrintResolution(&instance);
+ ffPrintDisplay(&instance);
+ // ffPrintBrightness(&instance);
ffPrintDesktopEnvironment(&instance);
ffPrintWM(&instance);
ffPrintWMTheme(&instance);
diff --git a/src/logo/builtin.c b/src/logo/builtin.c
index d13b7e4f8..09d13a2f0 100644
--- a/src/logo/builtin.c
+++ b/src/logo/builtin.c
@@ -1871,6 +1871,68 @@ static const FFlogo* getLogoPopSmall()
FF_LOGO_COLOR_TITLE("36"); //cyan
FF_LOGO_RETURN
}
+static const FFlogo* getLogoRaspbian()
+{
+ FF_LOGO_INIT
+ FF_LOGO_NAMES("raspbian", "raspi", "raspberrypi" "raspberrypios" "pios")
+ FF_LOGO_LINES(
+ " $2`.::///+:/-. --///+//-:`\n"
+ " `+oooooooooooo: `+oooooooooooo:\n"
+ " /oooo++//ooooo: ooooo+//+ooooo.\n"
+ " `+ooooooo:-:oo- +o+::/ooooooo:\n"
+ " `:oooooooo+`` `.oooooooo+-\n"
+ " `:++ooo/. :+ooo+/.`$1\n"
+ " ...` `.----.` ``..\n"
+ " .::::-``:::::::::.`-:::-`\n"
+ " -:::-` .:::::::-` `-:::-\n"
+ " `::. `.--.` `` `.---.``.::`\n"
+ " .::::::::` -::::::::` `\n"
+ " .::` .:::::::::- `::::::::::``::.\n"
+ "-:::` ::::::::::. ::::::::::.`:::-\n"
+ ":::: -::::::::. `-:::::::: ::::\n"
+ "-::- .-:::-.``....``.-::-. -::-\n"
+ " .. `` .::::::::. `..`..\n"
+ " -:::-` -::::::::::` .:::::`\n"
+ " :::::::` -::::::::::` :::::::.\n"
+ " .::::::: -::::::::. ::::::::\n"
+ " `-:::::` ..--.` ::::::.\n"
+ " `...` `...--..` `...`\n"
+ " .::::::::::\n"
+ " `.-::::-`"
+ )
+ FF_LOGO_COLORS(
+ "31", //red
+ "32" //green
+ )
+ FF_LOGO_COLOR_KEYS("31"); //red
+ FF_LOGO_COLOR_TITLE("32"); //green
+ FF_LOGO_RETURN
+}
+
+static const FFlogo* getLogoRaspbianSmall()
+{
+ FF_LOGO_INIT
+ FF_LOGO_NAMES("raspbian_small", "raspi_small", "raspberrypi_small" "raspberrypios_small" "pios_small")
+ FF_LOGO_LINES(
+ " $2.~~. .~~.\n"
+ " '. \\ ' ' / .'$1\n"
+ " .~ .~~~..~.\n"
+ " : .~.'~'.~. :\n"
+ " ~ ( ) ( ) ~\n"
+ "( : '~'.~.'~' : )\n"
+ " ~ .~ ( ) ~. ~\n"
+ " ( : '~' : )\n"
+ " '~ .~~~. ~'\n"
+ " '~'"
+ )
+ FF_LOGO_COLORS(
+ "31", //red
+ "32" //green
+ )
+ FF_LOGO_COLOR_KEYS("31"); //red
+ FF_LOGO_COLOR_TITLE("32"); //green
+ FF_LOGO_RETURN
+}
static const FFlogo* getLogoReborn()
{
@@ -2430,6 +2492,8 @@ GetLogoMethod* ffLogoBuiltinGetAll()
getLogoPopSmall,
getLogoParabola,
getLogoParabolaSmall,
+ getLogoRaspbian,
+ getLogoRaspbianSmall,
getLogoReborn,
getLogoRebornSmall,
getLogoRedHatEnterpriseLinux,
diff --git a/src/logo/image/image.c b/src/logo/image/image.c
index aed67ca6a..b2bfff6b5 100644
--- a/src/logo/image/image.c
+++ b/src/logo/image/image.c
@@ -2,6 +2,10 @@
#include "common/io.h"
#include "common/printing.h"
+#ifdef __APPLE__
+ #include
+#endif
+
static FFstrbuf base64Encode(FFstrbuf* in)
{
const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -30,24 +34,31 @@ static FFstrbuf base64Encode(FFstrbuf* in)
static bool printImageIterm(FFinstance* instance)
{
if(instance->config.logo.width == 0 || instance->config.logo.height == 0)
+ {
+ fputs("Logo: `iterm` protocol only works when both `--logo-width` and `--logo-height` being specified\n", stderr);
return false;
+ }
FFstrbuf buf;
ffStrbufInit(&buf);
if(!ffAppendFileBuffer(instance->config.logo.source.chars, &buf))
+ {
+ fputs("Logo: Failed to load image file\n", stderr);
return false;
+ }
ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
+ ffPrintCharTimes('\n', instance->config.logo.paddingTop);
FFstrbuf base64 = base64Encode(&buf);
+ instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight;
+ instance->state.logoHeight = instance->config.logo.paddingTop + instance->config.logo.height;
printf("\033]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\033[9999999D\n\033[%uA",
(unsigned) instance->config.logo.width,
(unsigned) instance->config.logo.height,
(unsigned) instance->config.logo.preserveAspectRadio,
base64.chars,
- (unsigned) instance->config.logo.height
+ (unsigned) instance->state.logoHeight
);
- instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight;
- instance->state.logoHeight = instance->config.logo.height;
ffStrbufDestroy(&buf);
ffStrbufDestroy(&base64);
@@ -58,6 +69,7 @@ static bool printImageIterm(FFinstance* instance)
static bool printImageKittyDirect(FFinstance* instance)
{
ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
+ ffPrintCharTimes('\n', instance->config.logo.paddingTop);
FFstrbuf base64 = base64Encode(&instance->config.logo.source);
printf("\033_Ga=T,f=100,t=f,c=%u,r=%u,C=1;%s\033\\\033[9999999D",
(unsigned) instance->config.logo.width,
@@ -66,7 +78,7 @@ static bool printImageKittyDirect(FFinstance* instance)
);
instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight;
- instance->state.logoHeight = instance->config.logo.height;
+ instance->state.logoHeight = instance->config.logo.paddingTop + instance->config.logo.height;
ffStrbufDestroy(&base64);
@@ -101,6 +113,7 @@ static inline char* realpath(const char* restrict file_name, char* restrict reso
resolved_name[1] = resolved_name[0]; // Drive Name
resolved_name[0] = '/';
}
+ return result;
}
#endif
@@ -199,7 +212,7 @@ static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestDat
//Calculate character dimensions
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logo.paddingLeft + instance->config.logo.paddingRight;
- instance->state.logoHeight = requestData->logoCharacterHeight;
+ instance->state.logoHeight = requestData->logoCharacterHeight + instance->config.logo.paddingTop;
if(requestData->type == FF_LOGO_TYPE_IMAGE_KITTY)
instance->state.logoHeight -= 1;
@@ -213,6 +226,7 @@ static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestDat
writeCacheUint32(requestData, instance->state.logoHeight, FF_CACHE_FILE_HEIGHT);
//Write result to stdout
+ ffPrintCharTimes('\n', instance->config.logo.paddingTop);
ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
fflush(stdout);
ffWriteFDBuffer(STDOUT_FILENO, result);
@@ -594,6 +608,7 @@ static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestDat
if(fd == -1)
return false;
+ ffPrintCharTimes('\n', instance->config.logo.paddingTop);
ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
fflush(stdout);
@@ -605,7 +620,7 @@ static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestDat
close(fd);
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logo.paddingLeft + instance->config.logo.paddingRight;
- instance->state.logoHeight = requestData->logoCharacterHeight;
+ instance->state.logoHeight = requestData->logoCharacterHeight + instance->config.logo.paddingTop;
//Go to upper left corner
fputs("\033[9999999D", stdout);
@@ -676,20 +691,8 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type)
requestData.logoPixelWidth = simpleCeil((double) instance->config.logo.width * requestData.characterPixelWidth);
requestData.logoPixelHeight = simpleCeil((double) instance->config.logo.height * requestData.characterPixelHeight);
- ffStrbufInitA(&requestData.cacheDir, PATH_MAX * 2);
-
- #if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
- ffStrbufAppendS(&requestData.cacheDir, getenv("XDG_CACHE_HOME"));
- #endif
-
- if(requestData.cacheDir.length == 0)
- {
- ffStrbufAppendS(&requestData.cacheDir, instance->state.passwd->pw_dir);
- ffStrbufAppendS(&requestData.cacheDir, "/.cache/");
- }
- else
- ffStrbufEnsureEndsWithC(&requestData.cacheDir, '/');
-
+ ffStrbufInit(&requestData.cacheDir);
+ ffStrbufAppend(&requestData.cacheDir, &instance->state.platform.cacheDir);
ffStrbufAppendS(&requestData.cacheDir, "fastfetch");
ffStrbufEnsureFree(&requestData.cacheDir, PATH_MAX);
diff --git a/src/logo/logo.c b/src/logo/logo.c
index 3c48e0854..60cbdf8bb 100644
--- a/src/logo/logo.c
+++ b/src/logo/logo.c
@@ -8,13 +8,27 @@
#include
#include
+static void ffLogoPrintCharsRaw(FFinstance* instance, const char* data, size_t length)
+{
+ fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
+ ffPrintCharTimes('\n', instance->config.logo.paddingTop);
+ ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
+ fwrite(data, length, 1, stdout);
+ instance->state.logoHeight = instance->config.logo.paddingTop + instance->config.logo.height;
+ instance->state.logoWidth = instance->config.logo.paddingLeft + instance->config.logo.width + instance->config.logo.paddingRight;
+ printf("\033[9999999D\n\033[%uA", instance->state.logoHeight);
+}
+
void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement)
{
uint32_t currentlineLength = 0;
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
+ ffPrintCharTimes('\n', instance->config.logo.paddingTop);
ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
+ instance->state.logoHeight = instance->config.logo.paddingTop;
+
//Use logoColor[0] as the default color
if(doColorReplacement)
ffPrintColor(&instance->config.logo.colors[0]);
@@ -191,7 +205,7 @@ static const FFlogo* logoGetBuiltin(const char* name)
return NULL;
}
-static const FFlogo* logoGetBuiltinDetected(FFinstance* instance)
+static const FFlogo* logoGetBuiltinDetected(const FFinstance* instance)
{
const FFOSResult* os = ffDetectOS(instance);
@@ -211,7 +225,7 @@ static const FFlogo* logoGetBuiltinDetected(FFinstance* instance)
if(logo != NULL)
return logo;
- logo = logoGetBuiltin(os->systemName.chars);
+ logo = logoGetBuiltin(instance->state.platform.systemName.chars);
if(logo != NULL)
return logo;
@@ -271,19 +285,49 @@ static void logoPrintData(FFinstance* instance, bool doColorReplacement) {
logoApplyColorsDetected(instance);
}
-static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement)
+static bool loadLogoFile(const FFinstance* instance, FFstrbuf* buffer)
+{
+ if(ffAppendFileBuffer(instance->config.logo.source.chars, buffer))
+ return true;
+
+ FFstrbuf fullPath;
+ ffStrbufInit(&fullPath);
+
+ FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance->state.platform.dataDirs)
+ {
+ //We need to copy it, because multiple threads might be using dataDirs at the same time
+ ffStrbufSet(&fullPath, dataDir);
+ ffStrbufAppendS(&fullPath, "fastfetch/logos/");
+ ffStrbufAppend(&fullPath, &instance->config.logo.source);
+
+ if(ffAppendFileBuffer(fullPath.chars, buffer))
+ {
+ ffStrbufDestroy(&fullPath);
+ return true;
+ }
+ }
+
+ ffStrbufDestroy(&fullPath);
+ return false;
+}
+
+static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement, bool raw)
{
FFstrbuf content;
- ffStrbufInitA(&content, 2047);
+ ffStrbufInit(&content);
- if(!ffAppendFileBuffer(instance->config.logo.source.chars, &content))
+ if(!loadLogoFile(instance, &content))
{
ffStrbufDestroy(&content);
+ fputs("Logo: Failed to load file content from logo source\n", stderr);
return false;
}
logoApplyColorsDetected(instance);
- ffLogoPrintChars(instance, content.chars, doColorReplacement);
+ if(raw)
+ ffLogoPrintCharsRaw(instance, content.chars, content.length);
+ else
+ ffLogoPrintChars(instance, content.chars, doColorReplacement);
ffStrbufDestroy(&content);
return true;
}
@@ -304,13 +348,25 @@ static void logoPrintKnownType(FFinstance* instance)
if(instance->config.logo.type == FF_LOGO_TYPE_BUILTIN)
successfull = logoPrintBuiltinIfExists(instance, instance->config.logo.source.chars);
else if(instance->config.logo.type == FF_LOGO_TYPE_FILE)
- successfull = logoPrintFileIfExists(instance, true);
+ successfull = logoPrintFileIfExists(instance, true, false);
else if(instance->config.logo.type == FF_LOGO_TYPE_FILE_RAW)
- successfull = logoPrintFileIfExists(instance, false);
+ successfull = logoPrintFileIfExists(instance, false, false);
else if(instance->config.logo.type == FF_LOGO_TYPE_DATA)
logoPrintData(instance, true);
else if(instance->config.logo.type == FF_LOGO_TYPE_DATA_RAW)
logoPrintData(instance, false);
+ else if(instance->config.logo.type == FF_LOGO_TYPE_IMAGE_RAW)
+ {
+ if(instance->config.logo.width == 0 || instance->config.logo.height == 0)
+ {
+ fputs("both `--logo-width` and `--logo-height` must be specified\n", stderr);
+ successfull = false;
+ }
+ else
+ successfull = logoPrintFileIfExists(instance, false, true);
+ }
+ else if(instance->config.logo.type == FF_LOGO_TYPE_NONE)
+ logoApplyColorsDetected(instance);
else //image
successfull = logoPrintImageIfExists(instance, instance->config.logo.type);
@@ -362,7 +418,7 @@ void ffLogoPrint(FFinstance* instance)
return;
//Try to load the logo as a file. If it succeeds, print it and return.
- if(logoPrintFileIfExists(instance, true))
+ if(logoPrintFileIfExists(instance, true, false))
return;
logoPrintDetected(instance);
diff --git a/src/modules/battery.c b/src/modules/battery.c
index 97c603d9a..79cdf4c79 100644
--- a/src/modules/battery.c
+++ b/src/modules/battery.c
@@ -13,6 +13,7 @@ static void printBattery(FFinstance* instance, BatteryResult* result, uint8_t in
ffPrintLogoAndKey(instance, FF_BATTERY_MODULE_NAME, index, &instance->config.battery.key);
bool showStatus =
+ !(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) &&
result->status.length > 0 &&
ffStrbufIgnCaseCompS(&result->status, "Unknown") != 0;
@@ -35,7 +36,7 @@ static void printBattery(FFinstance* instance, BatteryResult* result, uint8_t in
{
if(str.length > 0)
ffStrbufAppendC(&str, ' ');
- ffStrbufAppendF(&str, "%.0f%%", result->capacity);
+ ffStrbufAppendF(&str, str.length > 0 ? "(%u%%)" : "%u%%", (unsigned) result->capacity);
}
}
diff --git a/src/modules/brightness.c b/src/modules/brightness.c
new file mode 100644
index 000000000..edede6543
--- /dev/null
+++ b/src/modules/brightness.c
@@ -0,0 +1,62 @@
+#include "fastfetch.h"
+#include "common/printing.h"
+#include "detection/brightness/brightness.h"
+
+#define FF_BRIGHTNESS_MODULE_NAME "Brightness"
+#define FF_BRIGHTNESS_NUM_FORMAT_ARGS 2
+
+void ffPrintBrightness(FFinstance* instance)
+{
+ FFlist result;
+ ffListInit(&result, sizeof(FFBrightnessResult));
+ const char* error = ffDetectBrightness(&result);
+
+ if(error)
+ {
+ ffPrintError(instance, FF_BRIGHTNESS_MODULE_NAME, 0, &instance->config.brightness, "%s", error);
+ goto exit;
+ }
+
+ if(result.length == 0)
+ {
+ ffPrintError(instance, FF_BRIGHTNESS_MODULE_NAME, 0, &instance->config.brightness, "No result is detected.");
+ goto exit;
+ }
+
+ FFstrbuf key;
+ ffStrbufInit(&key);
+
+ FF_LIST_FOR_EACH(FFBrightnessResult, item, result)
+ {
+ if(instance->config.brightness.key.length == 0)
+ {
+ ffStrbufAppendF(&key, "%s (%s)", FF_BRIGHTNESS_MODULE_NAME, item->name.chars);
+ }
+ else
+ {
+ ffParseFormatString(&key, &instance->config.brightness.key, 1, (FFformatarg[]){
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->name}
+ });
+ }
+
+ if(instance->config.brightness.outputFormat.length == 0)
+ {
+ ffPrintLogoAndKey(instance, key.chars, 0, NULL);
+ printf("%.0f%%\n", item->value);
+ }
+ else
+ {
+ ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.brightness.outputFormat, FF_BRIGHTNESS_NUM_FORMAT_ARGS, (FFformatarg[]) {
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->value},
+ {FF_FORMAT_ARG_TYPE_FLOAT, &item->name}
+ });
+ }
+
+ ffStrbufDestroy(&item->name);
+ }
+
+ ffStrbufDestroy(&key);
+
+exit:
+ ffListDestroy(&result);
+}
diff --git a/src/modules/command.c b/src/modules/command.c
new file mode 100644
index 000000000..1b767013b
--- /dev/null
+++ b/src/modules/command.c
@@ -0,0 +1,67 @@
+#include "fastfetch.h"
+
+#include "common/printing.h"
+#include "common/processing.h"
+#include "util/textModifier.h"
+
+#define FF_COMMAND_MODULE_NAME "Command"
+
+static void printError(FFinstance* instance, const char* key, const char* error)
+{
+ ffPrintLogoAndKey(instance, key, 0, NULL);
+
+ if(instance->config.pipe)
+ fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
+
+ fputs(error, stdout);
+
+ if(!instance->config.pipe)
+ fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
+
+ putchar('\n');
+}
+
+void ffPrintCommand(FFinstance* instance)
+{
+ FF_STRBUF_AUTO_DESTROY key;
+ ffStrbufInit(&key);
+
+ if(!ffListShift(&instance->config.commandKeys, &key))
+ ffStrbufInitS(&key, FF_COMMAND_MODULE_NAME);
+
+ FF_STRBUF_AUTO_DESTROY text;
+ ffStrbufInit(&text);
+ if(!ffListShift(&instance->config.commandTexts, &text))
+ {
+ printError(instance, key.chars, "No command text left");
+ return;
+ }
+
+ FF_STRBUF_AUTO_DESTROY result;
+ ffStrbufInit(&result);
+ const char* error = ffProcessAppendStdOut(&result, (char* const[]){
+ instance->config.commandShell.chars,
+ #ifdef _WIN32
+ "/c",
+ #else
+ "-c",
+ #endif
+ text.chars,
+ NULL
+ });
+
+ if(error)
+ {
+ printError(instance, key.chars, error);
+ return;
+ }
+
+ if(!result.length)
+ {
+ printError(instance, key.chars, "No result printed");
+ return;
+ }
+
+ ffPrintLogoAndKey(instance, key.chars, 0, NULL);
+ puts(result.chars);
+}
diff --git a/src/modules/disk.c b/src/modules/disk.c
index eb6baeb47..c1e074812 100644
--- a/src/modules/disk.c
+++ b/src/modules/disk.c
@@ -47,17 +47,22 @@ static void printDisk(FFinstance* instance, const FFDisk* disk)
ffAppendPercentBar(instance, &str, bytesPercentage, 0, 5, 8);
ffStrbufAppendC(&str, ' ');
}
- ffStrbufAppendF(&str, "%s / %s", usedPretty.chars, totalPretty.chars);
+
+ if(!(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
+ ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars);
if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
- ffStrbufAppendF(&str, " (%u%%)", bytesPercentage);
+ {
+ ffStrbufAppendF(&str, str.length > 0 ? "(%u%%) " : "%u%% ", bytesPercentage);
+ }
}
else
- ffStrbufAppendS(&str, "Unknown");
+ ffStrbufAppendS(&str, "Unknown ");
- if(disk->type == FF_DISK_TYPE_EXTERNAL)
- ffStrbufAppendS(&str, " [Removable]");
+ if(disk->type == FF_DISK_TYPE_EXTERNAL && !(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
+ ffStrbufAppendS(&str, "[Removable]");
+ ffStrbufTrimRight(&str, ' ');
ffStrbufPutTo(&str, stdout);
ffStrbufDestroy(&str);
}
@@ -132,9 +137,15 @@ static void printAutodetected(FFinstance* instance, const FFlist* disks)
if(disk->type == FF_DISK_TYPE_EXTERNAL && !instance->config.diskShowRemovable)
continue;
+ if(disk->type == FF_DISK_TYPE_SUBVOLUME && !instance->config.diskShowSubvolumes)
+ continue;
+
if(disk->type == FF_DISK_TYPE_HIDDEN && !instance->config.diskShowHidden)
continue;
+ if(disk->bytesTotal == 0 && !instance->config.diskShowUnknown)
+ continue;
+
printDisk(instance, disk);
}
}
diff --git a/src/modules/display.c b/src/modules/display.c
new file mode 100644
index 000000000..45d93234b
--- /dev/null
+++ b/src/modules/display.c
@@ -0,0 +1,51 @@
+#include "fastfetch.h"
+#include "common/printing.h"
+#include "detection/displayserver/displayserver.h"
+
+#define FF_RESOLUTION_MODULE_NAME "Display"
+#define FF_RESOLUTION_NUM_FORMAT_ARGS 3
+
+void ffPrintDisplay(FFinstance* instance)
+{
+ #ifdef __ANDROID__
+ ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.display, "Display detection is not supported on Android");
+ return;
+ #endif
+
+ const FFDisplayServerResult* dsResult = ffConnectDisplayServer(instance);
+
+ for(uint32_t i = 0; i < dsResult->displays.length; i++)
+ {
+ FFDisplayResult* result = ffListGet(&dsResult->displays, i);
+ uint8_t moduleIndex = dsResult->displays.length == 1 ? 0 : (uint8_t) (i + 1);
+
+ if(instance->config.display.outputFormat.length == 0)
+ {
+ ffPrintLogoAndKey(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.display.key);
+ printf("%ix%i", result->width, result->height);
+
+ if(result->refreshRate > 0)
+ printf(" @ %iHz", result->refreshRate);
+
+ if(
+ result->scaledWidth > 0 && result->scaledWidth != result->width &&
+ result->scaledHeight > 0 && result->scaledHeight != result->height)
+ printf(" (as %ix%i)", result->scaledWidth, result->scaledHeight);
+
+ putchar('\n');
+ }
+ else
+ {
+ ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.display, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) {
+ {FF_FORMAT_ARG_TYPE_UINT, &result->width},
+ {FF_FORMAT_ARG_TYPE_UINT, &result->height},
+ {FF_FORMAT_ARG_TYPE_UINT, &result->refreshRate},
+ {FF_FORMAT_ARG_TYPE_UINT, &result->scaledWidth},
+ {FF_FORMAT_ARG_TYPE_UINT, &result->scaledHeight}
+ });
+ }
+ }
+
+ if(dsResult->displays.length == 0)
+ ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.display, "Couldn't detect display");
+}
diff --git a/src/modules/font.c b/src/modules/font.c
index 25f394f61..0b2e05e16 100644
--- a/src/modules/font.c
+++ b/src/modules/font.c
@@ -48,12 +48,18 @@ static void printFont(const FFFontResult* font)
const char* types[] = { "Caption", "Menu", "Message", "Status" };
for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i)
{
- if(font->fonts[i].length > 0)
+ if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i]))
{
- printf("%s [%s]", font->fonts[i].chars, types[i]);
- break;
+ if(i > 0)
+ fputs("], ", stdout);
+ printf("%s [%s", font->fonts[i].chars, types[i]);
+ }
+ else
+ {
+ printf(" / %s", types[i]);
}
}
+ putchar(']');
}
#else
diff --git a/src/modules/gpu.c b/src/modules/gpu.c
index 0d0ae8266..6c673df36 100644
--- a/src/modules/gpu.c
+++ b/src/modules/gpu.c
@@ -6,13 +6,13 @@
#include
#define FF_GPU_MODULE_NAME "GPU"
-#define FF_GPU_NUM_FORMAT_ARGS 5
+#define FF_GPU_NUM_FORMAT_ARGS 6
-static void printGPUResult(FFinstance* instance, uint8_t index, FFGPUResult* gpu)
+static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResult* gpu)
{
if(instance->config.gpu.outputFormat.length == 0)
{
- ffPrintLogoAndKey(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu.key);
+ ffPrintLogoAndKey(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu.key);
FFstrbuf output;
ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length);
@@ -37,12 +37,21 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFGPUResult* gpu
}
else
{
+ const char* type;
+ if(gpu->type == FF_GPU_TYPE_INTEGRATED)
+ type = "Integrated";
+ else if(gpu->type == FF_GPU_TYPE_DISCRETE)
+ type = "Discrete";
+ else
+ type = "Unknown";
+
ffPrintFormat(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver},
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature},
{FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount},
+ {FF_FORMAT_ARG_TYPE_STRING, type},
});
}
}
@@ -51,12 +60,27 @@ void ffPrintGPU(FFinstance* instance)
{
const FFlist* gpus = ffDetectGPU(instance);
- if(gpus->length == 0)
+ FFlist selectedGpus;
+ ffListInitA(&selectedGpus, sizeof(const FFGPUResult*), gpus->length);
+
+ for(uint32_t i = 0; i < gpus->length; i++)
{
- ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found");
- return;
+ const FFGPUResult* gpu = ffListGet(gpus, i);
+
+ if(gpu->type == FF_GPU_TYPE_INTEGRATED && instance->config.gpuHideIntegrated)
+ continue;
+
+ if(gpu->type == FF_GPU_TYPE_DISCRETE && instance->config.gpuHideDiscrete)
+ continue;
+
+ * (const FFGPUResult**) ffListAdd(&selectedGpus) = gpu;
}
- for(uint8_t i = 0; i < (uint8_t) gpus->length; i++)
- printGPUResult(instance, gpus->length == 1 ? 0 : (uint8_t) (i + 1), ffListGet(gpus, i));
+ for(uint32_t i = 0; i < selectedGpus.length; i++)
+ printGPUResult(instance, selectedGpus.length == 1 ? 0 : (uint8_t) (i + 1), * (const FFGPUResult**) ffListGet(&selectedGpus, i));
+
+ if(selectedGpus.length == 0)
+ ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found");
+
+ ffListDestroy(&selectedGpus);
}
diff --git a/src/modules/host.c b/src/modules/host.c
index e8d8e6044..9fa3bafee 100644
--- a/src/modules/host.c
+++ b/src/modules/host.c
@@ -33,7 +33,7 @@ void ffPrintHost(FFinstance* instance)
else
ffStrbufAppend(&output, &host->productFamily);
- if(host->productVersion.length > 0)
+ if(host->productVersion.length > 0 && !ffStrbufIgnCaseEqualS(&host->productVersion, "none"))
{
ffStrbufAppendF(&output, " (%s)", host->productVersion.chars);
}
diff --git a/src/modules/kernel.c b/src/modules/kernel.c
index 72096ce55..bc1139833 100644
--- a/src/modules/kernel.c
+++ b/src/modules/kernel.c
@@ -2,29 +2,29 @@
#include "common/printing.h"
#define FF_KERNEL_MODULE_NAME "Kernel"
-#define FF_KERNEL_NUM_FORMAT_ARGS 3
+#define FF_KERNEL_NUM_FORMAT_ARGS 4
void ffPrintKernel(FFinstance* instance)
{
if(instance->config.kernel.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel.key);
+ ffStrbufWriteTo(&instance->state.platform.systemRelease, stdout);
#ifdef _WIN32
- if(instance->state.utsname.version[0] != '\0')
- printf("%s (%s)\n", instance->state.utsname.release, instance->state.utsname.version);
- else
- puts(instance->state.utsname.release);
- #else
- puts(instance->state.utsname.release);
+ if(instance->state.platform.systemVersion.length > 0)
+ printf(" (%s)", instance->state.platform.systemVersion.chars);
#endif
+
+ putchar('\n');
}
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, &instance->state.platform.systemName},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemRelease},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemVersion},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemArchitecture}
});
}
}
diff --git a/src/modules/memory.c b/src/modules/memory.c
index 149eef45b..fbb893f02 100644
--- a/src/modules/memory.c
+++ b/src/modules/memory.c
@@ -52,11 +52,13 @@ static void printMemory(FFinstance* instance, const char* name, const FFModuleAr
ffStrbufAppendC(&str, ' ');
}
- ffStrbufAppendF(&str, "%s / %s", usedPretty.chars, totalPretty.chars);
+ if(!(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
+ ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars);
if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
- ffStrbufAppendF(&str, " (%u%%)", percentage);
+ ffStrbufAppendF(&str, str.length > 0 ? "(%u%%)" : "%u%%", percentage);
+ ffStrbufTrimRight(&str, ' ');
ffStrbufPutTo(&str, stdout);
ffStrbufDestroy(&str);
}
diff --git a/src/modules/os.c b/src/modules/os.c
index 7d5a15842..140cfdbbe 100644
--- a/src/modules/os.c
+++ b/src/modules/os.c
@@ -7,7 +7,7 @@
#define FF_OS_MODULE_NAME "OS"
#define FF_OS_NUM_FORMAT_ARGS 12
-static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
+static void buildOutputDefault(const FFinstance* instance, const FFOSResult* os, FFstrbuf* result)
{
//Create the basic output
if(os->name.length > 0)
@@ -17,7 +17,7 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
else if(os->id.length > 0)
ffStrbufAppend(result, &os->id);
else
- ffStrbufAppend(result, &os->systemName);
+ ffStrbufAppend(result, &instance->state.platform.systemName);
#ifdef __APPLE__
if(os->codename.length > 0)
@@ -62,14 +62,14 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
}
//Append architecture if it is missing
- if(ffStrbufFirstIndex(result, &os->architecture) == result->length)
+ if(ffStrbufFirstIndex(result, &instance->state.platform.systemArchitecture) == result->length)
{
ffStrbufAppendC(result, ' ');
- ffStrbufAppend(result, &os->architecture);
+ ffStrbufAppend(result, &instance->state.platform.systemArchitecture);
}
}
-static void buildOutputNixOS(const FFOSResult* os, FFstrbuf* result)
+static void buildOutputNixOS(const FFinstance* instance, const FFOSResult* os, FFstrbuf* result)
{
ffStrbufAppendS(result, "NixOS");
@@ -87,10 +87,10 @@ static void buildOutputNixOS(const FFOSResult* os, FFstrbuf* result)
ffStrbufAppendC(result, ')');
}
- if(os->architecture.length > 0)
+ if(instance->state.platform.systemArchitecture.length > 0)
{
ffStrbufAppendC(result, ' ');
- ffStrbufAppend(result, &os->architecture);
+ ffStrbufAppend(result, &instance->state.platform.systemArchitecture);
}
}
@@ -98,7 +98,7 @@ void ffPrintOS(FFinstance* instance)
{
const FFOSResult* os = ffDetectOS(instance);
- if(os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0 && os->systemName.length == 0)
+ if(os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0)
{
ffPrintError(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, "Could not detect OS");
return;
@@ -110,9 +110,9 @@ void ffPrintOS(FFinstance* instance)
ffStrbufInit(&result);
if(ffStrbufIgnCaseCompS(&os->id, "nixos") == 0)
- buildOutputNixOS(os, &result);
+ buildOutputNixOS(instance, os, &result);
else
- buildOutputDefault(os, &result);
+ buildOutputDefault(instance, os, &result);
ffPrintLogoAndKey(instance, FF_OS_MODULE_NAME, 0, &instance->config.os.key);
ffStrbufPutTo(&result, stdout);
@@ -121,7 +121,7 @@ void ffPrintOS(FFinstance* instance)
else
{
ffPrintFormat(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, FF_OS_NUM_FORMAT_ARGS, (FFformatarg[]){
- {FF_FORMAT_ARG_TYPE_STRBUF, &os->systemName},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemName},
{FF_FORMAT_ARG_TYPE_STRBUF, &os->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &os->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &os->id},
@@ -132,7 +132,7 @@ void ffPrintOS(FFinstance* instance)
{FF_FORMAT_ARG_TYPE_STRBUF, &os->versionID},
{FF_FORMAT_ARG_TYPE_STRBUF, &os->codename},
{FF_FORMAT_ARG_TYPE_STRBUF, &os->buildID},
- {FF_FORMAT_ARG_TYPE_STRBUF, &os->architecture}
+ {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemArchitecture}
});
}
}
diff --git a/src/modules/resolution.c b/src/modules/resolution.c
deleted file mode 100644
index 396d435b1..000000000
--- a/src/modules/resolution.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "fastfetch.h"
-#include "common/printing.h"
-#include "detection/displayserver/displayserver.h"
-
-#define FF_RESOLUTION_MODULE_NAME "Resolution"
-#define FF_RESOLUTION_NUM_FORMAT_ARGS 3
-
-void ffPrintResolution(FFinstance* instance)
-{
- #ifdef __ANDROID__
- ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolution, "Resolution detection is not supported on Android");
- return;
- #endif
-
- const FFDisplayServerResult* dsResult = ffConnectDisplayServer(instance);
-
- for(uint32_t i = 0; i < dsResult->resolutions.length; i++)
- {
- FFResolutionResult* result = ffListGet(&dsResult->resolutions, i);
- uint8_t moduleIndex = dsResult->resolutions.length == 1 ? 0 : (uint8_t) (i + 1);
-
- if(instance->config.resolution.outputFormat.length == 0)
- {
- ffPrintLogoAndKey(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution.key);
- printf("%ix%i", result->width, result->height);
-
- if(result->refreshRate > 0)
- printf(" @ %iHz", result->refreshRate);
-
- putchar('\n');
- }
- else
- {
- ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) {
- {FF_FORMAT_ARG_TYPE_INT, &result->width},
- {FF_FORMAT_ARG_TYPE_INT, &result->height},
- {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate}
- });
- }
- }
-
- if(dsResult->resolutions.length == 0)
- ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolution, "Couldn't detect resolution");
-}
diff --git a/src/modules/separator.c b/src/modules/separator.c
index 7227f9ae4..879bc5bb8 100644
--- a/src/modules/separator.c
+++ b/src/modules/separator.c
@@ -1,12 +1,12 @@
#include "fastfetch.h"
#include "common/printing.h"
-#include "detection/title.h"
void ffPrintSeparator(FFinstance* instance)
{
- const FFTitleResult* result = ffDetectTitle(instance);
- uint32_t titleLength = result->userName.length + 1 +
- (instance->config.titleFQDN ? result->fqdn.length : result->hostname.length);
+ uint32_t titleLength = instance->state.platform.userName.length + 1 + (instance->config.titleFQDN ?
+ instance->state.platform.domainName.length :
+ instance->state.platform.hostName.length
+ );
ffLogoPrintLine(instance);
diff --git a/src/modules/terminal.c b/src/modules/terminal.c
index 469ece23b..28e8d14a5 100644
--- a/src/modules/terminal.c
+++ b/src/modules/terminal.c
@@ -20,7 +20,11 @@ void ffPrintTerminal(FFinstance* instance)
if(instance->config.terminal.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminal.key);
- ffStrbufPutTo(&result->terminalPrettyName, stdout);
+
+ if(result->terminalVersion.length)
+ printf("%s %s\n", result->terminalPrettyName.chars, result->terminalVersion.chars);
+ else
+ ffStrbufPutTo(&result->terminalPrettyName, stdout);
}
else
{
diff --git a/src/modules/title.c b/src/modules/title.c
index cef00d146..4e509fbe5 100644
--- a/src/modules/title.c
+++ b/src/modules/title.c
@@ -1,6 +1,5 @@
#include "fastfetch.h"
#include "common/printing.h"
-#include "detection/title.h"
#include "util/textModifier.h"
static inline void printTitlePart(FFinstance* instance, const FFstrbuf* content)
@@ -19,12 +18,13 @@ static inline void printTitlePart(FFinstance* instance, const FFstrbuf* content)
void ffPrintTitle(FFinstance* instance)
{
- const FFTitleResult* result = ffDetectTitle(instance);
-
ffLogoPrintLine(instance);
- printTitlePart(instance, &result->userName);
+ printTitlePart(instance, &instance->state.platform.userName);
putchar('@');
- printTitlePart(instance, instance->config.titleFQDN ? &result->fqdn : &result->hostname);
+ printTitlePart(instance, instance->config.titleFQDN ?
+ &instance->state.platform.domainName :
+ &instance->state.platform.hostName
+ );
putchar('\n');
}
diff --git a/src/modules/wifi.c b/src/modules/wifi.c
index 596c18baa..fa9d19caf 100644
--- a/src/modules/wifi.c
+++ b/src/modules/wifi.c
@@ -3,67 +3,69 @@
#include "detection/wifi/wifi.h"
#define FF_WIFI_MODULE_NAME "Wifi"
-#define FF_WIFI_NUM_FORMAT_ARGS 12
+#define FF_WIFI_NUM_FORMAT_ARGS 10
void ffPrintWifi(FFinstance* instance)
{
- FFlist result;
+ FF_LIST_AUTO_DESTROY result;
ffListInit(&result, sizeof(FFWifiResult));
const char* error = ffDetectWifi(instance, &result);
-
- if(!error)
+ if(error)
{
- for(uint32_t index = 0; index < result.length; ++index)
- {
- FFWifiResult* item = (FFWifiResult*)ffListGet(&result, index);
- uint8_t moduleIndex = result.length == 1 ? 0 : (uint8_t)(index + 1);
+ ffPrintError(instance, FF_WIFI_MODULE_NAME, 0, &instance->config.wifi, "%s", error);
+ return;
+ }
+ if(!result.length)
+ {
+ ffPrintError(instance, FF_WIFI_MODULE_NAME, 0, &instance->config.wifi, "No Wifi interfaces found");
+ return;
+ }
- if(instance->config.wifi.outputFormat.length == 0)
+ for(uint32_t index = 0; index < result.length; ++index)
+ {
+ FFWifiResult* item = (FFWifiResult*)ffListGet(&result, index);
+ uint8_t moduleIndex = result.length == 1 ? 0 : (uint8_t)(index + 1);
+
+ if(instance->config.wifi.outputFormat.length == 0)
+ {
+ ffPrintLogoAndKey(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi.key);
+ if(item->conn.ssid.length)
{
- ffPrintLogoAndKey(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi.key);
- if(item->conn.ssid.length)
- {
- printf("%s - %s", item->conn.ssid.chars, item->conn.phyType.chars);
- if(!item->security.enabled)
- puts(" - insecure");
- else
- putchar('\n');
- }
- else
- {
- puts(item->inf.status.chars);
- }
+ ffStrbufWriteTo(&item->conn.ssid, stdout);
+ if(item->conn.protocol.length)
+ printf("- %s", item->conn.protocol.chars);
+ if(item->conn.security.length)
+ printf("- %s", item->conn.security.chars);
+ putchar('\n');
}
else
{
- ffPrintFormat(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi, FF_WIFI_NUM_FORMAT_ARGS, (FFformatarg[]){
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.description},
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status},
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status},
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid},
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress},
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.phyType},
- {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality},
- {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate},
- {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate},
- {FF_FORMAT_ARG_TYPE_BOOL, &item->security.enabled},
- {FF_FORMAT_ARG_TYPE_BOOL, &item->security.oneXEnabled},
- {FF_FORMAT_ARG_TYPE_STRBUF, &item->security.algorithm},
- });
+ puts(item->inf.status.chars);
}
-
- ffStrbufDestroy(&item->inf.description);
- ffStrbufDestroy(&item->inf.status);
- ffStrbufDestroy(&item->conn.status);
- ffStrbufDestroy(&item->conn.ssid);
- ffStrbufDestroy(&item->conn.macAddress);
- ffStrbufDestroy(&item->conn.phyType);
- ffStrbufDestroy(&item->security.algorithm);
}
- }
- else
- {
- ffPrintError(instance, FF_WIFI_MODULE_NAME, 0, &instance->config.wmTheme, "%s", error);
+ else
+ {
+ ffPrintFormat(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi, FF_WIFI_NUM_FORMAT_ARGS, (FFformatarg[]){
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.description},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol},
+ {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality},
+ {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate},
+ {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate},
+ {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.security},
+ });
+ }
+
+ ffStrbufDestroy(&item->inf.description);
+ ffStrbufDestroy(&item->inf.status);
+ ffStrbufDestroy(&item->conn.status);
+ ffStrbufDestroy(&item->conn.ssid);
+ ffStrbufDestroy(&item->conn.macAddress);
+ ffStrbufDestroy(&item->conn.protocol);
+ ffStrbufDestroy(&item->conn.security);
}
}
diff --git a/src/util/FFlist.c b/src/util/FFlist.c
index d01353ffb..bd643014a 100644
--- a/src/util/FFlist.c
+++ b/src/util/FFlist.c
@@ -1,6 +1,7 @@
#include "FFlist.h"
#include
+#include
void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity)
{
@@ -34,6 +35,27 @@ uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compF
return list->length;
}
+bool ffListShift(FFlist* list, void* result)
+{
+ if(list->length == 0)
+ return false;
+
+ memcpy(result, list->data, list->elementSize);
+ memmove(list->data, list->data + list->elementSize, (size_t) list->elementSize * (list->length - 1));
+ --list->length;
+ return true;
+}
+
+bool ffListPop(FFlist* list, void* result)
+{
+ if(list->length == 0)
+ return false;
+
+ memcpy(result, ffListGet(list, list->length - 1), list->elementSize);
+ --list->length;
+ return result;
+}
+
void ffListDestroy(FFlist* list)
{
//Avoid free-after-use. These 3 assignments are cheap so don't remove them
diff --git a/src/util/FFlist.h b/src/util/FFlist.h
index fd7a0f5ca..58612e347 100644
--- a/src/util/FFlist.h
+++ b/src/util/FFlist.h
@@ -26,6 +26,11 @@ void* ffListAdd(FFlist* list);
FF_C_NODISCARD uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compFunc)(const void*, const void*));
+// Removes the first element, and copy its value to `*result`
+bool ffListShift(FFlist* list, void* result);
+// Removes the last element, and copy its value to `*result`
+bool ffListPop(FFlist* list, void* result);
+
void ffListDestroy(FFlist* list);
static inline void ffListInit(FFlist* list, uint32_t elementSize)
@@ -45,8 +50,12 @@ static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void
qsort(list->data, list->length, list->elementSize, compar);
}
-#if defined(_WIN32) || defined(__APPLE__)
- #define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy)))
-#endif
+#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
+ assert(sizeof(itemType) == (listVar).elementSize); \
+ for(itemType* itemVarName = (itemType*)(listVar).data; \
+ itemVarName - (itemType*)(listVar).data < (intptr_t)(listVar).length; \
+ ++itemVarName)
+
+#define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy)))
#endif
diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c
index 27150ef24..375c53aaa 100644
--- a/src/util/FFstrbuf.c
+++ b/src/util/FFstrbuf.c
@@ -3,6 +3,17 @@
#include
#include
+bool ffStrSet(const char* str)
+{
+ if(str == NULL)
+ return false;
+
+ while(isspace(*str))
+ str++;
+
+ return *str != '\0';
+}
+
static char* CHAR_NULL_PTR = "";
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate)
@@ -328,6 +339,12 @@ uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c)
return strbuf->length;
}
+void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace)
+{
+ for (char *current_pos = strchr(strbuf->chars, find); current_pos; current_pos = strchr(current_pos + 1, find))
+ *current_pos = replace;
+}
+
void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index)
{
if(strbuf->length <= index)
diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h
index 22133a7ea..7342cb607 100644
--- a/src/util/FFstrbuf.h
+++ b/src/util/FFstrbuf.h
@@ -18,6 +18,8 @@
#define strcasestr StrStrIA
#endif
+bool ffStrSet(const char* str);
+
#define FASTFETCH_STRBUF_DEFAULT_ALLOC 32
typedef struct FFstrbuf
@@ -69,6 +71,8 @@ FF_C_NODISCARD uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t star
FF_C_NODISCARD uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c);
+void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace);
+
void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index);
void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c);
void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c);
@@ -308,8 +312,6 @@ static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf
return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars);
}
-#if defined(_WIN32) || defined(__APPLE__)
- #define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy)))
-#endif
+#define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy)))
#endif
diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c
index 65dcd7248..f5c37b7ad 100644
--- a/src/util/apple/cf_helpers.c
+++ b/src/util/apple/cf_helpers.c
@@ -44,7 +44,10 @@ const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* r
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result)
{
CFBooleanRef cf = (CFBooleanRef)CFDictionaryGetValue(dict, key);
- if(cf == NULL || CFGetTypeID(cf) != CFBooleanGetTypeID())
+ if(cf == NULL)
+ return "CFDictionaryGetValue() failed";
+
+ if(CFGetTypeID(cf) != CFBooleanGetTypeID())
return "TypeID is not 'CFBoolean'";
*result = CFBooleanGetValue(cf);
@@ -53,13 +56,25 @@ const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result)
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result)
{
- CFNumberRef cf = (CFNumberRef)CFDictionaryGetValue(dict, key);
- if (cf == NULL || CFGetTypeID(cf) != CFNumberGetTypeID())
- return "TypeID is not 'CFNumber'";
+ CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key);
+ if(cf == NULL)
+ return "CFDictionaryGetValue() failed";
- if(!CFNumberGetValue(cf, kCFNumberSInt32Type, result))
- return "Number type is not SInt32";
- return NULL;
+ if(CFGetTypeID(cf) == CFNumberGetTypeID())
+ {
+ if(!CFNumberGetValue((CFNumberRef)cf, kCFNumberSInt32Type, result))
+ return "Number type is not SInt32";
+ return NULL;
+ }
+ else if(CFGetTypeID(cf) == CFDataGetTypeID())
+ {
+ if(CFDataGetLength((CFDataRef)cf) != sizeof(int))
+ return "Data length is not sizeof(int)";
+ CFDataGetBytes((CFDataRef)cf, CFRangeMake(0, sizeof(int)), (uint8_t*)result);
+ return NULL;
+ }
+
+ return "TypeID is neither 'CFNumber' nor 'CFData'";
}
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result)
diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c
new file mode 100644
index 000000000..d549b6501
--- /dev/null
+++ b/src/util/platform/FFPlatform.c
@@ -0,0 +1,115 @@
+#include "FFPlatform_private.h"
+
+void ffPlatformInit(FFPlatform* platform)
+{
+ ffStrbufInit(&platform->homeDir);
+ ffStrbufInit(&platform->cacheDir);
+ ffListInit(&platform->configDirs, sizeof(FFstrbuf));
+ ffListInit(&platform->dataDirs, sizeof(FFstrbuf));
+
+ ffStrbufInit(&platform->userName);
+ ffStrbufInit(&platform->hostName);
+ ffStrbufInit(&platform->domainName);
+ ffStrbufInit(&platform->userShell);
+
+ ffStrbufInit(&platform->systemName);
+ ffStrbufInit(&platform->systemRelease);
+ ffStrbufInit(&platform->systemVersion);
+ ffStrbufInit(&platform->systemArchitecture);
+
+ ffPlatformInitImpl(platform);
+
+ if(platform->domainName.length == 0)
+ ffStrbufAppend(&platform->domainName, &platform->hostName);
+
+ if(platform->systemName.length == 0)
+ {
+ #if defined(__linux__)
+ ffStrbufAppendS(&platform->systemName, "Linux");
+ #elif defined(__FreeBSD__)
+ ffStrbufAppendS(&platform->systemName, "FreeBSD");
+ #elif defined(__APPLE__)
+ ffStrbufAppendS(&platform->systemName, "Darwin");
+ #elif defined(_WIN32)
+ ffStrbufAppendS(&platform->systemName, "Windows_NT");
+ #else
+ ffStrbufAppendS(&platform->systemName, "Unknown");
+ #endif
+ }
+
+ if(platform->systemArchitecture.length == 0)
+ ffStrbufAppendS(&platform->systemArchitecture, "Unknown");
+}
+
+void ffPlatformDestroy(FFPlatform* platform)
+{
+ ffStrbufDestroy(&platform->homeDir);
+ ffStrbufDestroy(&platform->cacheDir);
+
+ FF_LIST_FOR_EACH(FFstrbuf, dir, platform->configDirs)
+ ffStrbufDestroy(dir);
+ ffListDestroy(&platform->configDirs);
+
+ FF_LIST_FOR_EACH(FFstrbuf, dir, platform->dataDirs)
+ ffStrbufDestroy(dir);
+ ffListDestroy(&platform->dataDirs);
+
+ ffStrbufDestroy(&platform->userName);
+ ffStrbufDestroy(&platform->hostName);
+ ffStrbufDestroy(&platform->domainName);
+ ffStrbufDestroy(&platform->userShell);
+
+ ffStrbufDestroy(&platform->systemArchitecture);
+ ffStrbufDestroy(&platform->systemName);
+ ffStrbufDestroy(&platform->systemRelease);
+ ffStrbufDestroy(&platform->systemVersion);
+}
+
+void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path)
+{
+ FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs);
+ ffStrbufInitA(buffer, 64);
+ ffStrbufAppendS(buffer, path);
+ ffStrbufEnsureEndsWithC(buffer, '/');
+ FF_PLATFORM_PATH_UNIQUE(dirs, buffer);
+}
+
+void ffPlatformPathAddHome(FFlist* dirs, const FFPlatform* platform, const char* suffix)
+{
+ FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs);
+ ffStrbufInitA(buffer, 64);
+ ffStrbufAppend(buffer, &platform->homeDir);
+ ffStrbufAppendS(buffer, suffix);
+ ffStrbufEnsureEndsWithC(buffer, '/');
+ FF_PLATFORM_PATH_UNIQUE(dirs, buffer);
+}
+
+void ffPlatformPathAddEnv(FFlist* dirs, const char* env)
+{
+ const char* envValue = getenv(env);
+ if(!ffStrSet(envValue))
+ return;
+
+ FFstrbuf value;
+ ffStrbufInitA(&value, 64);
+ ffStrbufAppendS(&value, envValue);
+
+ uint32_t startIndex = 0;
+ while (startIndex < value.length)
+ {
+ uint32_t colonIndex = ffStrbufNextIndexC(&value, startIndex, ':');
+ value.chars[colonIndex] = '\0';
+
+ if(!ffStrSet(value.chars + startIndex))
+ {
+ startIndex = colonIndex + 1;
+ continue;
+ }
+
+ ffPlatformPathAddAbsolute(dirs, value.chars + startIndex);
+
+ startIndex = colonIndex + 1;
+ }
+
+ ffStrbufDestroy(&value);
+}
diff --git a/src/util/platform/FFPlatform.h b/src/util/platform/FFPlatform.h
new file mode 100644
index 000000000..caebc7c6f
--- /dev/null
+++ b/src/util/platform/FFPlatform.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#ifndef FF_INCLUDED_util_platform_FFPlatform
+#define FF_INCLUDED_util_platform_FFPlatform
+
+#include "util/FFstrbuf.h"
+#include "util/FFlist.h"
+
+typedef struct FFPlatform {
+ FFstrbuf homeDir; // Trailing slash included
+ FFstrbuf cacheDir; // Trailing slash included
+ FFlist configDirs; // List of FFstrbuf, trailing slash included
+ FFlist dataDirs; // List of FFstrbuf, trailing slash included
+
+ FFstrbuf userName;
+ FFstrbuf hostName;
+ FFstrbuf domainName;
+ FFstrbuf userShell;
+
+ FFstrbuf systemName;
+ FFstrbuf systemRelease;
+ FFstrbuf systemVersion;
+ FFstrbuf systemArchitecture;
+} FFPlatform;
+
+void ffPlatformInit(FFPlatform* platform);
+void ffPlatformDestroy(FFPlatform* platform);
+
+#endif
diff --git a/src/util/platform/FFPlatform_private.h b/src/util/platform/FFPlatform_private.h
new file mode 100644
index 000000000..698f07609
--- /dev/null
+++ b/src/util/platform/FFPlatform_private.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#ifndef FF_INCLUDED_util_platform_FFPlatform_private
+#define FF_INCLUDED_util_platform_FFPlatform_private
+
+#include "FFPlatform.h"
+
+void ffPlatformInitImpl(FFPlatform* platform);
+
+#define FF_PLATFORM_PATH_UNIQUE(list, element) \
+ if(ffListFirstIndexComp(list, element, (bool(*)(const void*, const void*))ffStrbufEqual) < list->length - 1) \
+ { \
+ ffStrbufDestroy(ffListGet(list, list->length - 1)); \
+ --list->length; \
+ }
+
+void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path);
+void ffPlatformPathAddHome(FFlist* dirs, const FFPlatform* platform, const char* suffix);
+void ffPlatformPathAddEnv(FFlist* dirs, const char* env);
+
+#endif
diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c
new file mode 100644
index 000000000..393d2290b
--- /dev/null
+++ b/src/util/platform/FFPlatform_unix.c
@@ -0,0 +1,149 @@
+#include "FFPlatform_private.h"
+
+#include "fastfetch_config.h"
+
+#include
+#include
+#include
+
+static void getHomeDir(FFPlatform* platform, const struct passwd* pwd)
+{
+ const char* home = getenv("HOME");
+ if(!ffStrSet(home) && pwd)
+ home = pwd->pw_dir;
+
+ ffStrbufAppendS(&platform->homeDir, home);
+ ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
+}
+
+static void getCacheDir(FFPlatform* platform)
+{
+ const char* cache = getenv("XDG_CACHE_HOME");
+ if(ffStrSet(cache))
+ {
+ ffStrbufAppendS(&platform->cacheDir, cache);
+ ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
+ }
+ else
+ {
+ ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
+ ffStrbufAppendS(&platform->cacheDir, ".cache/");
+ }
+
+ ffStrbufAppendS(&platform->cacheDir, "fastfetch/");
+}
+
+static void getConfigDirs(FFPlatform* platform)
+{
+ ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME");
+ ffPlatformPathAddHome(&platform->configDirs, platform, ".config/");
+
+ #if defined(__APPLE__)
+ ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Preferences/");
+ #endif
+
+ ffPlatformPathAddHome(&platform->configDirs, platform, "");
+ ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS");
+
+ #if !defined(__APPLE__)
+ ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/");
+ #endif
+
+ ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC"/");
+ ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/");
+}
+
+static void getDataDirs(FFPlatform* platform)
+{
+ ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME");
+ ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/");
+
+ #if defined(__APPLE__)
+ ffPlatformPathAddHome(&platform->dataDirs, platform, "/Library/Application Support/");
+ #endif
+
+ ffPlatformPathAddHome(&platform->dataDirs, platform, "");
+ ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS");
+ ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/");
+ ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/share/");
+}
+
+static void getUserName(FFPlatform* platform, const struct passwd* pwd)
+{
+ const char* user = getenv("USER");
+ if(!ffStrSet(user) && pwd)
+ user = pwd->pw_name;
+
+ ffStrbufAppendS(&platform->userName, user);
+}
+
+static void getHostName(FFPlatform* platform, const struct utsname* uts)
+{
+ char hostname[256];
+ if(gethostname(hostname, sizeof(hostname)) == 0)
+ ffStrbufAppendS(&platform->hostName, hostname);
+
+ if(platform->hostName.length == 0)
+ ffStrbufAppendS(&platform->hostName, uts->nodename);
+}
+
+#ifdef __linux__
+#include
+static void getDomainName(FFPlatform* platform)
+{
+ struct addrinfo hints = {0};
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+
+ struct addrinfo* info = NULL;
+
+ if(getaddrinfo(platform->hostName.chars, "80", &hints, &info) != 0)
+ return;
+
+ struct addrinfo* current = info;
+ while(platform->domainName.length == 0 && current != NULL)
+ {
+ ffStrbufAppendS(&platform->domainName, current->ai_canonname);
+ current = current->ai_next;
+ }
+
+ freeaddrinfo(info);
+}
+#endif
+
+static void getUserShell(FFPlatform* platform, const struct passwd* pwd)
+{
+ const char* shell = getenv("SHELL");
+ if(!ffStrSet(shell) && pwd)
+ shell = pwd->pw_shell;
+
+ ffStrbufAppendS(&platform->userShell, shell);
+}
+
+void ffPlatformInitImpl(FFPlatform* platform)
+{
+ struct passwd* pwd = getpwuid(getuid());
+
+ struct utsname uts;
+ if(uname(&uts) != 0)
+ memset(&uts, 0, sizeof(uts));
+
+ getHomeDir(platform, pwd);
+ getCacheDir(platform);
+ getConfigDirs(platform);
+ getDataDirs(platform);
+
+ getUserName(platform, pwd);
+ getHostName(platform, &uts);
+
+ #ifdef __linux__
+ getDomainName(platform);
+ #endif
+
+ getUserShell(platform, pwd);
+
+ ffStrbufAppendS(&platform->systemName, uts.sysname);
+ ffStrbufAppendS(&platform->systemRelease, uts.release);
+ ffStrbufAppendS(&platform->systemVersion, uts.version);
+ ffStrbufAppendS(&platform->systemArchitecture, uts.machine);
+}
diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c
new file mode 100644
index 000000000..2fff50ef5
--- /dev/null
+++ b/src/util/platform/FFPlatform_windows.c
@@ -0,0 +1,232 @@
+#include "FFPlatform_private.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+
+#include "util/windows/unicode.h"
+
+static void getHomeDir(FFPlatform* platform)
+{
+ PWSTR pPath;
+ if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath)))
+ {
+ ffStrbufSetWS(&platform->homeDir, pPath);
+ ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
+ ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
+ }
+ CoTaskMemFree(pPath);
+}
+
+static void getCacheDir(FFPlatform* platform)
+{
+ PWSTR pPath;
+ if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath)))
+ {
+ ffStrbufSetWS(&platform->cacheDir, pPath);
+ ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
+ ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
+ }
+ else
+ {
+ ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
+ ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
+ }
+ CoTaskMemFree(pPath);
+
+ ffStrbufAppendS(&platform->cacheDir, "fastfetch/");
+}
+
+static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
+{
+ PWSTR pPath;
+ if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath)))
+ {
+ FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs);
+ ffStrbufInit(buffer);
+ ffStrbufSetWS(buffer, pPath);
+ ffStrbufReplaceAllC(buffer, '\\', '/');
+ ffStrbufEnsureEndsWithC(buffer, '/');
+ FF_PLATFORM_PATH_UNIQUE(dirs, buffer);
+ }
+ CoTaskMemFree(pPath);
+}
+
+static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
+{
+ const char* value = getenv(env);
+ if(!ffStrSet(value))
+ return;
+
+ FFstrbuf* buffer = ffListAdd(dirs);
+ ffStrbufInitA(buffer, 64);
+ ffStrbufAppendS(buffer, value);
+ ffStrbufReplaceAllC(buffer, '\\', '/');
+ ffStrbufEnsureEndsWithC(buffer, '/');
+ ffStrbufAppendS(buffer, suffix);
+ ffStrbufEnsureEndsWithC(buffer, '/');
+ FF_PLATFORM_PATH_UNIQUE(dirs, buffer);
+}
+
+static void getConfigDirs(FFPlatform* platform)
+{
+ ffListInit(&platform->configDirs, sizeof(FFstrbuf));
+
+ ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME");
+ ffPlatformPathAddHome(&platform->configDirs, platform, "/.config/");
+ platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_RoamingAppData);
+ platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_LocalAppData);
+ ffPlatformPathAddHome(&platform->configDirs, platform, "");
+
+ if(getenv("MSYSTEM") && getenv("HOME"))
+ {
+ // We are in MSYS2 / Git Bash
+ platformPathAddEnvSuffix(&platform->configDirs, "HOME", ".config/");
+ platformPathAddEnvSuffix(&platform->configDirs, "HOME", "");
+ }
+
+ ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS");
+}
+
+static void getDataDirs(FFPlatform* platform)
+{
+ ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME");
+ ffPlatformPathAddHome(&platform->dataDirs, platform, "/.local/share/");
+ platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData);
+ platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData);
+ ffPlatformPathAddHome(&platform->dataDirs, platform, "");
+
+ if(getenv("MSYSTEM") && getenv("HOME"))
+ {
+ // We are in MSYS2 / Git Bash
+ platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ".local/share/");
+ platformPathAddEnvSuffix(&platform->dataDirs, "HOME", "");
+ }
+
+ ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS");
+}
+
+static void getUserName(FFPlatform* platform)
+{
+ ffStrbufEnsureFree(&platform->userName, 64);
+ DWORD len = (DWORD) ffStrbufGetFree(&platform->userName);
+ if(GetUserNameA(platform->userName.chars, &len))
+ platform->userName.length = (uint32_t) len;
+}
+
+static void getHostName(FFPlatform* platform)
+{
+ ffStrbufEnsureFree(&platform->hostName, 64);
+ DWORD len = (DWORD) ffStrbufGetFree(&platform->hostName);
+ if(GetComputerNameExA(ComputerNameDnsHostname, platform->hostName.chars, &len))
+ platform->hostName.length = (uint32_t) len;
+}
+
+static void getDomainName(FFPlatform* platform)
+{
+ ffStrbufEnsureFree(&platform->domainName, 64);
+ DWORD len = (DWORD) ffStrbufGetFree(&platform->domainName);
+ if(GetComputerNameExA(ComputerNameDnsDomain, platform->domainName.chars, &len))
+ platform->domainName.length = (uint32_t) len;
+}
+
+static void getSystemName(FFPlatform* platform)
+{
+ ffStrbufAppendS(&platform->systemName, "Windows_NT");
+}
+
+static void getSystemReleaseAndVersion(FFPlatform* platform)
+{
+ HKEY hKey;
+ if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+ return;
+
+ DWORD bufSize;
+
+ char currentVersion[32];
+
+ {
+ DWORD currentMajorVersionNumber;
+ DWORD currentMinorVersionNumber;
+ bufSize = sizeof(currentMajorVersionNumber);
+ if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS &&
+ RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS
+ )
+ snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber);
+ else
+ {
+ bufSize = sizeof(currentVersion);
+ if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS)
+ strcpy(currentVersion, "0.0");
+ }
+ }
+
+ char currentBuildNumber[32];
+ bufSize = sizeof(currentBuildNumber);
+ if(RegGetValueA(hKey, NULL, "CurrentBuildNumber", RRF_RT_REG_SZ, NULL, currentBuildNumber, &bufSize) != ERROR_SUCCESS)
+ strcpy(currentBuildNumber, "0");
+
+ DWORD ubr;
+ bufSize = sizeof(ubr);
+ if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr))
+ ubr = 0;
+
+ ffStrbufAppendF(&platform->systemRelease, "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr);
+
+ ffStrbufEnsureFree(&platform->systemVersion, 256);
+ bufSize = (DWORD) ffStrbufGetFree(&platform->systemVersion);
+ if(RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, platform->systemVersion.chars, &bufSize) == ERROR_SUCCESS)
+ platform->systemVersion.length = (uint32_t) bufSize;
+
+ RegCloseKey(hKey);
+}
+
+static void getSystemArchitecture(FFPlatform* platform)
+{
+ SYSTEM_INFO sysInfo = {0};
+ GetNativeSystemInfo(&sysInfo);
+
+ switch(sysInfo.wProcessorArchitecture)
+ {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ ffStrbufAppendS(&platform->systemArchitecture, "x86_64");
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ ffStrbufAppendS(&platform->systemArchitecture, "ia64");
+ break;
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ ffStrbufAppendS(&platform->systemArchitecture, "i686");
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM64:
+ ffStrbufAppendS(&platform->systemArchitecture, "aarch64");
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ ffStrbufAppendS(&platform->systemArchitecture, "arm");
+ break;
+ case PROCESSOR_ARCHITECTURE_PPC:
+ ffStrbufAppendS(&platform->systemArchitecture, "ppc");
+ break;
+ case PROCESSOR_ARCHITECTURE_MIPS:
+ ffStrbufAppendS(&platform->systemArchitecture, "mips");
+ break;
+ case PROCESSOR_ARCHITECTURE_UNKNOWN:
+ default:
+ break;
+ }
+}
+
+void ffPlatformInitImpl(FFPlatform* platform)
+{
+ getHomeDir(platform);
+ getCacheDir(platform);
+ getConfigDirs(platform);
+ getDataDirs(platform);
+
+ getUserName(platform);
+ getHostName(platform);
+ getDomainName(platform);
+
+ getSystemName(platform);
+ getSystemReleaseAndVersion(platform);
+ getSystemArchitecture(platform);
+}
diff --git a/src/util/windows/manifest.xml b/src/util/windows/manifest.xml
index 420545ded..86d623144 100644
--- a/src/util/windows/manifest.xml
+++ b/src/util/windows/manifest.xml
@@ -16,7 +16,7 @@
UTF-8
- true
+ false
SegmentHeap
diff --git a/src/util/windows/pwd.c b/src/util/windows/pwd.c
deleted file mode 100644
index a52f2689a..000000000
--- a/src/util/windows/pwd.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "pwd.h"
-
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-
-struct passwd* ffGetPasswd()
-{
- static struct passwd res;
-
- DWORD len = sizeof(res.pw_name);
- GetUserNameA(res.pw_name, &len);
-
- SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, res.pw_dir);
-
- return &res;
-}
diff --git a/src/util/windows/pwd.h b/src/util/windows/pwd.h
deleted file mode 100644
index 29d4c883b..000000000
--- a/src/util/windows/pwd.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#ifndef FASTFETCH_INCLUDED_UTIL_PWD
-#define FASTFETCH_INCLUDED_UTIL_PWD
-
-#include
-#include
-
-struct passwd
-{
- char pw_name[UNLEN + 1]; /* username */
- // char *pw_passwd[1]; /* user password */
- // int pw_uid; /* user ID */
- // int pw_gid; /* group ID */
- // char *pw_gecos; /* user information */
- char pw_dir[MAX_PATH]; /* home directory */
- // char *pw_shell; /* shell program */
-};
-
-struct passwd* ffGetPasswd();
-
-#endif
diff --git a/src/util/windows/unicode.h b/src/util/windows/unicode.h
index d70fbb22e..f01080b0a 100644
--- a/src/util/windows/unicode.h
+++ b/src/util/windows/unicode.h
@@ -3,16 +3,18 @@
#ifndef FASTFETCH_INCLUDED_UNICODE_H
#define FASTFETCH_INCLUDED_UNICODE_H
-#include "fastfetch.h"
+#include "util/FFstrbuf.h"
#include
void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source);
+
static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source)
{
return ffStrbufSetNWS(result, (uint32_t)wcslen(source), source);
}
FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source);
+
static inline FFstrbuf ffStrbufCreateWS(const wchar_t* source)
{
return ffStrbufCreateNWS((uint32_t)wcslen(source), source);
diff --git a/src/util/windows/utsname.c b/src/util/windows/utsname.c
deleted file mode 100644
index a1f68021d..000000000
--- a/src/util/windows/utsname.c
+++ /dev/null
@@ -1,116 +0,0 @@
-#include "fastfetch.h"
-#include "utsname.h"
-
-#define WIN32_LEAN_AND_MEAN 1
-#include
-
-static int detectSysname(struct utsname *name)
-{
- strncpy(name->sysname, "Windows_NT", UTSNAME_MAXLENGTH);
- return 0;
-}
-
-static int detectNodename(struct utsname *name)
-{
- DWORD bufSize = UTSNAME_MAXLENGTH - 1;
- if(!GetComputerNameA(name->nodename, &bufSize))
- return 1;
- name->nodename[bufSize] = '\0';
- return 0;
-}
-
-static int detectVersion(struct utsname *name)
-{
- HKEY hKey;
- if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
- return 1;
-
- DWORD bufSize;
-
- char currentVersion[32];
-
- {
- DWORD currentMajorVersionNumber;
- DWORD currentMinorVersionNumber;
- bufSize = sizeof(currentMajorVersionNumber);
- if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS &&
- RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS
- )
- snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber);
- else
- {
- bufSize = sizeof(currentVersion);
- if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS)
- strcpy(currentVersion, "0.0");
- }
- }
-
- char currentBuildNumber[32];
- bufSize = sizeof(currentBuildNumber);
- if(RegGetValueA(hKey, NULL, "CurrentBuildNumber", RRF_RT_REG_SZ, NULL, currentBuildNumber, &bufSize) != ERROR_SUCCESS)
- strcpy(currentBuildNumber, "0");
-
- DWORD ubr;
- bufSize = sizeof(ubr);
- if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr))
- ubr = 0;
-
- snprintf(name->release, sizeof(name->release), "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr);
-
- bufSize = sizeof(name->version);
- RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, name->version, &bufSize);
-
- RegCloseKey(hKey);
- return 0;
-}
-
-static int detectMachine(struct utsname *name)
-{
- // Get hardware info
- SYSTEM_INFO sysInfo = {0};
- GetNativeSystemInfo(&sysInfo);
-
- // Set processor architecture
- switch(sysInfo.wProcessorArchitecture)
- {
- case PROCESSOR_ARCHITECTURE_AMD64:
- strcpy(name->machine, "x86_64");
- break;
- case PROCESSOR_ARCHITECTURE_IA64:
- strcpy(name->machine, "ia64");
- break;
- case PROCESSOR_ARCHITECTURE_INTEL:
- strcpy(name->machine, "x86");
- break;
- case PROCESSOR_ARCHITECTURE_ARM64:
- strcpy(name->machine, "aarch64");
- break;
- case PROCESSOR_ARCHITECTURE_ARM:
- strcpy(name->machine, "arm");
- break;
- case PROCESSOR_ARCHITECTURE_PPC:
- strcpy(name->machine, "ppc");
- break;
- case PROCESSOR_ARCHITECTURE_MIPS:
- strcpy(name->machine, "mips");
- break;
- case PROCESSOR_ARCHITECTURE_UNKNOWN:
- default:
- strcpy(name->machine, "unknown");
- break;
- }
-
- return 0;
-}
-
-int uname(struct utsname *name)
-{
- memset(name, 0, sizeof(*name));
-
- int sysnameResult = detectSysname(name);
- int nodenameResult = detectNodename(name);
- int versionResult = detectVersion(name);
- int machineResult = detectMachine(name);
-
- return sysnameResult || nodenameResult || versionResult || machineResult;
-}
diff --git a/src/util/windows/utsname.h b/src/util/windows/utsname.h
deleted file mode 100644
index 96bc53adc..000000000
--- a/src/util/windows/utsname.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#ifndef FASTFETCH_INCLUDED_UTSNAME_H
-#define FASTFETCH_INCLUDED_UTSNAME_H
-
-#define UTSNAME_MAXLENGTH 256
-
-struct utsname
-{
- char sysname[UTSNAME_MAXLENGTH]; // name of this implementation of the operating system
- char nodename[UTSNAME_MAXLENGTH]; // name of this node within an implementation - dependent communications network
- char release[UTSNAME_MAXLENGTH]; // current release level of this implementation
- char version[UTSNAME_MAXLENGTH]; // current version level of this release
- char machine[UTSNAME_MAXLENGTH]; // name of the hardware type on which the system is running
-};
-
-int uname(struct utsname *name);
-
-#endif
diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp
index cba0c07c5..1da4ac0ff 100644
--- a/src/util/windows/wmi.cpp
+++ b/src/util/windows/wmi.cpp
@@ -26,7 +26,7 @@ static void CoUninitializeWrap()
CoUninitialize();
}
-static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext)
+static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lpContext)
{
HRESULT hres;
@@ -76,15 +76,15 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext)
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
- bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
- nullptr, // User name. nullptr = current user
- nullptr, // User password. nullptr = current
- 0, // Locale. nullptr indicates current
- 0, // Security flags.
- 0, // Authority (for example, Kerberos)
- 0, // Context object
- &pSvc // pointer to IWbemServices proxy
- );
+ bstr_t((const wchar_t*) lpParameter), // Object path of WMI namespace
+ nullptr, // User name. nullptr = current user
+ nullptr, // User password. nullptr = current
+ 0, // Locale. nullptr indicates current
+ 0, // Security flags.
+ 0, // Authority (for example, Kerberos)
+ 0, // Context object
+ &pSvc // pointer to IWbemServices proxy
+ );
pLoc->Release();
pLoc = nullptr;
@@ -120,13 +120,17 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext)
return TRUE;
}
-FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error)
+FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs)
: pEnumerator(nullptr)
{
- static INIT_ONCE s_InitOnce = INIT_ONCE_STATIC_INIT;
+ static INIT_ONCE s_InitOnce[(int) FFWmiNamespace::LAST] = {};
const char* context;
- if (InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, nullptr, (void**)&context) == FALSE)
- {
+ if (InitOnceExecuteOnce(
+ &s_InitOnce[(int)wmiNs],
+ &InitHandleFunction,
+ (PVOID) (wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI"),
+ (void**)&context) == FALSE
+ ) {
if(error)
ffStrbufAppendS(error, context);
return;
diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp
index 6f7d214cb..25bef6e91 100644
--- a/src/util/windows/wmi.hpp
+++ b/src/util/windows/wmi.hpp
@@ -11,6 +11,12 @@ extern "C" {
#include
+enum class FFWmiNamespace {
+ CIMV2,
+ WMI,
+ LAST,
+};
+
struct FFWmiRecord
{
IWbemClassObject* obj;
@@ -43,7 +49,7 @@ struct FFWmiQuery
{
IEnumWbemClassObject* pEnumerator = nullptr;
- FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr);
+ FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr, FFWmiNamespace wmiNs = FFWmiNamespace::CIMV2);
explicit FFWmiQuery(IEnumWbemClassObject* pEnumerator): pEnumerator(pEnumerator) {}
FFWmiQuery(const FFWmiQuery& other) = delete;
FFWmiQuery(FFWmiQuery&& other) { *this = (FFWmiQuery&&)other; }
diff --git a/tests/list.c b/tests/list.c
index e9c10423e..db4db544a 100644
--- a/tests/list.c
+++ b/tests/list.c
@@ -31,6 +31,7 @@ static bool numEqualsAdapter(const void* first, const void* second)
int main(void)
{
FFlist list;
+ uint32_t n = 0;
//initA
@@ -40,6 +41,18 @@ int main(void)
VERIFY(list.capacity == 0);
VERIFY(list.length == 0);
+ //forEach
+ FF_LIST_FOR_EACH(uint32_t, item, list)
+ VERIFY(false);
+
+ //shift
+ VERIFY(!ffListShift(&list, &n));
+ VERIFY(list.length == 0);
+
+ //pop
+ VERIFY(!ffListPop(&list, &n));
+ VERIFY(list.length == 0);
+
//add
for (uint32_t i = 1; i <= FF_LIST_DEFAULT_ALLOC + 1; ++i)
{
@@ -60,13 +73,34 @@ int main(void)
VERIFY(*(uint32_t*)ffListGet(&list, 0) == 1);
VERIFY(*(uint32_t*)ffListGet(&list, i - 1) == i);
}
+ VERIFY(list.length == FF_LIST_DEFAULT_ALLOC + 1);
+
+ uint32_t sum = 0;
+ //forEach
+ FF_LIST_FOR_EACH(uint32_t, item, list)
+ sum += *item;
+ VERIFY(sum == (1 + FF_LIST_DEFAULT_ALLOC + 1) * (FF_LIST_DEFAULT_ALLOC + 1) / 2);
// ffListFirstIndexComp
- uint32_t n = 10;
+ n = 10;
VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == 9);
n = 999;
VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == list.length);
+ //shift
+ VERIFY(ffListShift(&list, &n));
+ VERIFY(n == 1);
+ VERIFY(list.length == FF_LIST_DEFAULT_ALLOC);
+ VERIFY(*(uint32_t*) ffListGet(&list, 0) == 2);
+ VERIFY(*(uint32_t*) ffListGet(&list, list.length - 1) == FF_LIST_DEFAULT_ALLOC + 1);
+
+ //pop
+ VERIFY(ffListPop(&list, &n));
+ VERIFY(n == FF_LIST_DEFAULT_ALLOC + 1);
+ VERIFY(list.length == FF_LIST_DEFAULT_ALLOC - 1);
+ VERIFY(*(uint32_t*) ffListGet(&list, 0) == 2);
+ VERIFY(*(uint32_t*) ffListGet(&list, list.length - 1) == FF_LIST_DEFAULT_ALLOC);
+
//Destroy
ffListDestroy(&list);
diff --git a/tests/strbuf.c b/tests/strbuf.c
index 3b55142ec..3d8d3d057 100644
--- a/tests/strbuf.c
+++ b/tests/strbuf.c
@@ -208,6 +208,12 @@ int main(void)
VERIFY(ffStrbufContainC(&strbuf, '1'));
VERIFY(!ffStrbufContainC(&strbuf, '-'));
+ //replaceAllC
+ ffStrbufReplaceAllC(&strbuf, '1', '-');
+ VERIFY(ffStrbufEqualS(&strbuf, "-234567890-234567890-234567890-"));
+ ffStrbufReplaceAllC(&strbuf, '1', '-');
+ VERIFY(ffStrbufEqualS(&strbuf, "-234567890-234567890-234567890-"));
+
ffStrbufDestroy(&strbuf);
//Success