diff --git a/src/common/settings.c b/src/common/settings.c index 8f44aaf7d..de79ce131 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -357,4 +357,21 @@ void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) { result->length += (uint32_t) __system_property_get(propName, result->chars + result->length); result->chars[result->length] = '\0'; } -#endif +#endif //__ANDROID__ + +#ifdef __APPLE__ +#include +void ffSettingsGetAppleProperty(const char* propName, FFstrbuf* result) +{ + size_t neededLength; + if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 0) + return; + + ffStrbufEnsureFree(result, (uint32_t) neededLength); + + if(sysctlbyname(propName, result->chars + result->length, &neededLength, NULL, 0) == 0) + result->length += (uint32_t) neededLength; + + result->chars[result->length] = '\0'; +} +#endif //__APPLE__ diff --git a/src/common/settings.h b/src/common/settings.h index 8f487eabb..836901d06 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -36,4 +36,8 @@ int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, cons void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result); #endif +#ifdef __APPLE__ +void ffSettingsGetAppleProperty(const char* propName, FFstrbuf* result); +#endif + #endif diff --git a/src/detection/host/host_apple.c b/src/detection/host/host_apple.c index b2fc8385f..15727ba4b 100644 --- a/src/detection/host/host_apple.c +++ b/src/detection/host/host_apple.c @@ -1,9 +1,11 @@ #include "host.h" +#include "common/settings.h" void ffDetectHostImpl(FFHostResult* host) { + ffStrbufInit(&host->productName); + ffStrbufInitA(&host->productFamily, 0); - ffStrbufInitA(&host->productName, 0); ffStrbufInitA(&host->sysVendor, 0); ffStrbufInitA(&host->productVersion, 0); ffStrbufInitA(&host->productSku, 0); @@ -17,4 +19,6 @@ void ffDetectHostImpl(FFHostResult* host) ffStrbufInitA(&host->chassisType, 0); ffStrbufInitA(&host->chassisVendor, 0); ffStrbufInitA(&host->chassisVersion, 0); + + ffSettingsGetAppleProperty("hw.model", &host->productName); } diff --git a/src/detection/os/os_apple.c b/src/detection/os/os_apple.c index d37017476..1bde7d465 100644 --- a/src/detection/os/os_apple.c +++ b/src/detection/os/os_apple.c @@ -1,19 +1,93 @@ #include "os.h" +#include "common/properties.h" #include "common/settings.h" +#include +#include + +typedef enum PListKey +{ + PLIST_KEY_NAME, + PLIST_KEY_VERSION, + PLIST_KEY_BUILD, + PLIST_KEY_OTHER +} PListKey; + +static void parseFile(FFOSResult* os) +{ + FILE* plist = fopen("/System/Library/CoreServices/SystemVersion.plist", "r"); + if(plist == NULL) + return; + + char* line = NULL; + size_t len = 0; + PListKey key = PLIST_KEY_OTHER; + + FFstrbuf keyBuffer; + ffStrbufInit(&keyBuffer); + + while(getline(&line, &len, plist) != EOF) + { + if(ffParsePropLine(line, "", &keyBuffer)) + { + if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductName") == 0) + key = PLIST_KEY_NAME; + else if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductUserVisibleVersion") == 0) + key = PLIST_KEY_VERSION; + else if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductBuildVersion") == 0) + key = PLIST_KEY_BUILD; + else + key = PLIST_KEY_OTHER; + + ffStrbufClear(&keyBuffer); + continue; + } + + if(key == PLIST_KEY_NAME) + ffParsePropLine(line, "", &os->name); + else if(key == PLIST_KEY_VERSION) + ffParsePropLine(line, "", &os->version); + else if(key == PLIST_KEY_BUILD) + ffParsePropLine(line, "", &os->buildID); + } + + ffStrbufDestroy(&keyBuffer); + + if(line != NULL) + free(line); + + fclose(plist); +} + void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) { FF_UNUSED(instance); - ffStrbufInitA(&os->name, 0); - ffStrbufInitA(&os->prettyName, 0); - ffStrbufInitA(&os->id, 0); - ffStrbufInitA(&os->version, 0); - ffStrbufInitA(&os->versionID, 0); + + ffStrbufInit(&os->name); + ffStrbufInit(&os->version); + ffStrbufInit(&os->buildID); + ffStrbufInit(&os->id); + ffStrbufInit(&os->prettyName); + ffStrbufInit(&os->versionID); + ffStrbufInit(&os->systemName); + ffStrbufInit(&os->architecture); + ffStrbufInitA(&os->codename, 0); - ffStrbufInitA(&os->buildID, 0); - ffStrbufInitA(&os->systemName, 0); - ffStrbufInitA(&os->architecture, 0); ffStrbufInitA(&os->idLike, 0); ffStrbufInitA(&os->variant, 0); ffStrbufInitA(&os->variantID, 0); + + parseFile(os); + + if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS")) + ffStrbufAppendS(&os->id, "macos"); + + if(os->version.length == 0) + ffSettingsGetAppleProperty("kern.osproductversion", &os->version); + + //TODO map version to pretty name + ffStrbufAppend(&os->prettyName, &os->name); + ffStrbufAppend(&os->versionID, &os->version); + ffSettingsGetAppleProperty("kern.ostype", &os->systemName); + ffSettingsGetAppleProperty("hw.machine", &os->architecture); } diff --git a/src/detection/terminalShell.c b/src/detection/terminalShell.c index cbd8c4b2e..bfbbabd0f 100644 --- a/src/detection/terminalShell.c +++ b/src/detection/terminalShell.c @@ -137,6 +137,10 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) getenv("TMUX_TMPDIR") != NULL )) term = "Termux"; + //MacOS + if(!ffStrSet(term)) + term = getenv("TERM_PROGRAM"); + //Normal Terminal if(!ffStrSet(term)) term = getenv("TERM"); diff --git a/src/detection/title.c b/src/detection/title.c index 087621247..595ae3823 100644 --- a/src/detection/title.c +++ b/src/detection/title.c @@ -32,6 +32,7 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance) ffStrbufInitA(&result.fqdn, HOST_NAME_MAX); + #ifndef __APPLE__ struct addrinfo hints = {0}; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; @@ -49,6 +50,7 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance) freeaddrinfo(info); } + #endif if(result.fqdn.length == 0) ffStrbufAppend(&result.fqdn, &result.hostname); diff --git a/src/modules/uptime.c b/src/modules/uptime.c index 926e682ec..9cbd9f9f8 100644 --- a/src/modules/uptime.c +++ b/src/modules/uptime.c @@ -1,17 +1,41 @@ #include "fastfetch.h" #include "common/printing.h" +#if __APPLE__ + #include "time.h" + #include "sys/sysctl.h" +#endif + #define FF_UPTIME_MODULE_NAME "Uptime" #define FF_UPTIME_NUM_FORMAT_ARGS 4 void ffPrintUptime(FFinstance* instance) { + uint64_t uptime; + #if FF_HAVE_SYSINFO_H - uint64_t uptime = (uint64_t) instance->state.sysinfo.uptime; + uptime = (uint64_t) instance->state.sysinfo.uptime; + #elif __APPLE__ + struct timeval bootTime; + size_t bootTimeSize = sizeof(bootTime); + if(sysctl( + (int[]) {CTL_KERN, KERN_BOOTTIME}, 2, + &bootTime, &bootTimeSize, + NULL, 0 + ) == 0) + uptime = (uint64_t) difftime(time(NULL), bootTime.tv_sec); + else + uptime = 0; #else - uint64_t uptime = 0; + uptime = 0; #endif + if(uptime == 0) + { + ffPrintError(instance, FF_UPTIME_MODULE_NAME, 0, &instance->config.uptime, "Uptime could't be detected"); + return; + } + uint32_t days = (uint32_t) uptime / 86400; uint32_t hours = (uint32_t) (uptime - (days * 86400)) / 3600; uint32_t minutes = (uint32_t) (uptime - (days * 86400) - (hours * 3600)) / 60;