diff --git a/main.c b/main.c index 0339e7d..47bb455 100644 --- a/main.c +++ b/main.c @@ -214,11 +214,10 @@ int main(int argc, char *argv[]) { #endif #if !defined(__HAIKU__) + const char *machine = display_host(); if (ishost) { printf("%s ", LOGO[lc]); - printf("%s%s%s%s", color, "Host", reset, ": "); - display_host_model(); - printf("\n"); + printf("%sHost%s: %s\n", color, reset, machine); lc++; } else minsize--; #endif diff --git a/src/common.c b/src/common.c index acb0a45..5070d6e 100644 --- a/src/common.c +++ b/src/common.c @@ -1,8 +1,12 @@ -#include "common.h" - #include #include #include +#include +#include +#include +#include + +#include "common.h" long long int run_command_lld(const char *command) { char buf[128]; @@ -58,3 +62,53 @@ const char *run_command_s(const char *command) { return out; } + +#if !defined(__HAIKU__) +const char *from_cache(const char *file) { + struct stat st; + if (stat(file, &st) != 0) { + return NULL; + } + + FILE *f = fopen(file, "r"); + if (!f) { + return NULL; + } + + char *cmd = (char *)malloc(128 * sizeof(char)); + if (!cmd) { + fclose(f); + return NULL; + } + + if (fgets(cmd, 128, f) == NULL) { + free(cmd); + fclose(f); + return NULL; + } + + fclose(f); + + cmd[strcspn(cmd, "\n")] = '\0'; + return cmd; +} + +int to_cache(const char *file, const char *res) { + char dir[256]; + snprintf(dir, sizeof(dir), "%s", "/tmp/farfetch"); + + struct stat st; + + if (stat(dir, &st) != 0) { + if (mkdir(dir, 0755) != 0 && errno != EEXIST) return -1; + } + + FILE *f = fopen(file, "w"); + if (!f) return -1; + + fprintf(f, "%s", res); + fclose(f); + + return 0; +} +#endif diff --git a/src/common.h b/src/common.h index 7955ffe..bddbb8b 100644 --- a/src/common.h +++ b/src/common.h @@ -3,5 +3,9 @@ long long int run_command_lld(const char *command); const char *run_command_s(const char *command); +#if !defined(__HAIKU__) +const char *from_cache(const char *file); +int to_cache(const char *file, const char *res); +#endif #endif diff --git a/src/cpu.c b/src/cpu.c index 2c57ee1..bd8916f 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1,33 +1,44 @@ #include "cpu.h" #include "common.h" - #include -#if defined(__linux__) || defined(__HAIKU__) #include -#endif const char *display_cpu() { +#if !defined(__HAIKU__) + const char *out = from_cache("/tmp/farfetch/cpu"); + if (out) return out; +#else + const char *out = NULL; +#endif + char *cmd = NULL; + #if defined(__NetBSD__) - return run_command_s("sysctl -n machdep.cpu_brand | sed 's/(R)//' | " - "sed 's/(TM)//' | sed 's/CPU //' | sed 's/Processor//' && " - "echo \" (\" && sysctl -n hw.ncpu && echo \" core)\""); + cmd = malloc(256); + if (!cmd) return NULL; + snprintf(cmd, 256, "sysctl -n machdep.cpu_brand | sed 's/(R)//' | " + "sed 's/(TM)//' | sed 's/CPU //' | sed 's/Processor//' && " + "echo \" (\" && sysctl -n hw.ncpu && echo \" core)\""); #elif defined(__FreeBSD__) || defined(__OpenBSD__) - return run_command_s("sysctl -n hw.model | sed 's/(R)//' | " - "sed 's/(TM)//' | sed 's/CPU //' | sed 's/ Processor//' && " - "echo \" (\" && sysctl -n hw.ncpu && echo \" core)\""); + cmd = malloc(1024); + if (!cmd) return NULL; + snprintf(cmd, 1024, "sysctl -n hw.model | sed 's/(R)//' | " + "sed 's/(TM)//' | sed 's/CPU //' | sed 's/ Processor//' && " + "echo \" (\" && sysctl -n hw.ncpu && echo \" core)\""); #elif defined(__sun) - return run_command_s("psrinfo -pv | tail -1 | " - "sed 's/(r)//g; s/ CPU//; s/^ *//; s/ $//' | awk '{$1=$1};1' && " - "echo \" (\" && psrinfo -p && echo \" core)\""); + cmd = malloc(1024); + if (!cmd) return NULL; + snprintf(cmd, 1024, "psrinfo -pv | tail -1 | " + "sed 's/(r)//g; s/ CPU//; s/^ *//; s/ $//' | awk '{$1=$1};1' && " + "echo \" (\" && psrinfo -p && echo \" core)\""); #elif defined(__linux__) - return run_command_s("cat /proc/cpuinfo | awk -F '\\\\s*: | @' " - "'/model name|Hardware|Processor|^cpu model|chip type|^cpu type/ { " - "cpu=$2; if ($1 == \"Hardware\") exit } END { print cpu }' | " - "sed 's/(R)//' | sed 's/(TM)//' | sed 's/CPU //' | sed 's/ Processor//' | " - "sed 's/ [0-9]-Core//' && echo \" @ \" && " - "cat /proc/cpuinfo | grep \"cpu MHz\" | sort -nr | head -1 | sed 's/^.*: //' | " - "awk '{printf \"%.2f\", $1/1000}' && " - "echo \"GHz (\" && nproc && echo \" core)\""); + cmd = "cat /proc/cpuinfo | awk -F '\\\\s*: | @' " + "'/model name|Hardware|Processor|^cpu model|chip type|^cpu type/ { " + "cpu=$2; if ($1 == \"Hardware\") exit } END { print cpu }' | " + "sed 's/(R)//' | sed 's/(TM)//' | sed 's/CPU //' | sed 's/ Processor//' | " + "sed 's/ [0-9]-Core//' && echo \" @ \" && " + "cat /proc/cpuinfo | grep \"cpu MHz\" | sort -nr | head -1 | " + "sed 's/^.*: //' | awk '{printf \"%.2f\", $1/1000}' && " + "echo \"GHz (\" && nproc && echo \" core)\""; #elif defined(__HAIKU__) const char *cpuname = run_command_s("sysinfo | grep \"CPU #0:\" | " "sed 's/CPU #0: \"'// | sed 's/\"//' | sed 's/(R)//' | sed 's/(TM)//' | " @@ -36,18 +47,31 @@ const char *display_cpu() { "sed 's/^.*: //' | awk '{ printf \"%.2f\", $1 / 1000 }'"); long long int proc = run_command_lld("nproc"); - char *cmd = (char *)malloc(128 * sizeof(char)); - if (!cmd) { - return NULL; - } + cmd = (char *)malloc(128 * sizeof(char)); + if (!cmd) return NULL; snprintf(cmd, 128, "%s @ %sGHz (%lld core)", cpuname, freq, proc); - return cmd; + free((void *)cpuname); + free((void *)freq); #elif defined(__APPLE__) - return run_command_s("sysctl -n machdep.cpu.brand_string | sed 's/(R)//' | " - "sed 's/(TM)//' | sed 's/CPU //' | sed 's/ Processor//' && " - "echo \" (\" && sysctl -n hw.logicalcpu_max && echo \" core)\""); -#endif + cmd = malloc(1024); + if (!cmd) return NULL; + snprintf(cmd, 1024, "sysctl -n machdep.cpu.brand_string | sed 's/(R)//' | " + "sed 's/(TM)//' | sed 's/CPU //' | sed 's/ Processor//' && " + "echo \" (\" && sysctl -n hw.logicalcpu_max && echo \" core)\""); +#else return NULL; +#endif + + if (!cmd) return NULL; + out = run_command_s(cmd); +#if !defined(__linux__) + free(cmd); +#endif +#if !defined(__HAIKU__) + to_cache("/tmp/farfetch/cpu", out); +#endif + + return out; } diff --git a/src/distro.c b/src/distro.c index 95d60e9..b9a7336 100644 --- a/src/distro.c +++ b/src/distro.c @@ -14,7 +14,11 @@ const char *display_distro() { char *out = NULL; size_t outsize = 0; - const char *cmd = NULL; + const char *cmd = from_cache("/tmp/farfetch/distro"); + + if (cmd) { + return cmd; + } if (access("/bedrock/etc/bedrock-release", F_OK) != -1) { cmd = "cat /bedrock/etc/bedrock-release | grep '^PRETTY_NAME' | " @@ -69,12 +73,12 @@ const char *display_distro() { } out = nout; - memccpy(out + outsize, buf, sizeof(buf), len); outsize += len; out[outsize] = '\0'; } + to_cache("/tmp/farfetch/distro", out); pclose(p); return out; @@ -82,6 +86,14 @@ const char *display_distro() { void get_distro() { const char *buf = display_distro(); + if (!buf) { +#if defined(__sunos) + distroname = "solaris"; +#else + distroname = "linux"; +#endif + return; + } if (strstr(buf, "Alpine") != NULL) distroname = "alpine"; else if (strstr(buf, "Arch Linux") != NULL) distroname = "arch"; @@ -105,7 +117,11 @@ void get_distro() { else if (strstr(buf, "Rocky") != NULL) distroname = "rocky"; else if (strstr(buf, "Ubuntu") != NULL) distroname = "ubuntu"; else if (strstr(buf, "Void Linux") != NULL) distroname = "void"; +#if defined(__sunos) + else distroname = "solaris"; +#else else distroname = "linux"; +#endif if (strncmp(distroname, "ubuntu", strlen("ubuntu")) == 0) { const char *desktop = run_command_s("echo $XDG_CURRENT_DESKTOP"); diff --git a/src/gpu.c b/src/gpu.c index 68e26b4..4ab0d04 100644 --- a/src/gpu.c +++ b/src/gpu.c @@ -1,9 +1,7 @@ #include "gpu.h" #include "common.h" - -#if defined(__HAIKU__) #include -#endif +#include #if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__) &&\ !defined(__linux__) && !defined(__DragonFly__) && !defined(__APPLE__) &&\ @@ -13,12 +11,21 @@ #if defined(__FreeBSD__) || defined(__Dragonfly__) || defined(__HAIKU__) #include -#include #endif const char *display_gpu() { +#if !defined(__HAIKU__) + const char *out = from_cache("/tmp/farfetch/gpu"); + if (out) return out; +#else + const char *out = NULL; +#endif + char *cmd = NULL; + #if defined(__OpenBSD__) || defined(__NetBSD__) - return run_command_s("dmesg | " + cmd = malloc(2048); + if (!cmd) return NULL; + snprintf(cmd, 2048, "dmesg | " "if [ \"$(dmesg | grep \"radeondrm.* at pci.*\")\" ]; " "then grep -i \"radeondrm.* at pci.*\"; " "elif [ \"$(dmesg | grep \"inteldrm.* at pci.*\")\" ]; " @@ -63,24 +70,33 @@ const char *display_gpu() { } free((void *)test); - return run_command_s("pciconf -lv | grep -B 4 -F \"VGA\" | " - "grep -F \"device\" | sed 's/^.* device//' | " - "sed \"s/^.* '//\" | sed \"s/'//\" | tail -1 | " - "sed 's/ Core Processor Integrated Graphics Controller//'"); + + cmd = malloc(256); + if (!cmd) return NULL; + snprintf(cmd, 256, "pciconf -lv | grep -B 4 -F \"VGA\" | " + "grep -F \"device\" | sed 's/^.* device//' | " + "sed \"s/^.* '//\" | sed \"s/'//\" | tail -1 | " + "sed 's/ Core Processor Integrated Graphics Controller//'"); #elif defined(__sun) - return run_command_s("prtconf -v | grep -A 30 \"value='display'\" | " + cmd = malloc(512); + if (!cmd) return NULL; + snprintf(cmd, 512, "prtconf -v | grep -A 30 \"value='display'\" | " "grep -A 1 vendor-name | tail -1 | sed 's/^.*value=//' | sed \"s/'//g\" | " "sed 's/ Corporation//' && echo \" \" && prtconf -v | " "grep -A 30 \"value='display'\" | grep -A 1 device-name | tail -1 | " "sed 's/^.*value=//' | sed \"s/'//g\""); #elif defined(__linux__) - return run_command_s("lspci | grep VGA | sed 's/^.*: //' | " + cmd = malloc(256); + if (!cmd) return NULL; + snprintf(cmd, 256, "lspci | grep VGA | sed 's/^.*: //' | " "sed 's/Corporation //' | sed 's/ (.*$//' | " "sed 's/Advanced Micro Devices//' | " "sed 's/, Inc. //' | sed 's/Navi [0-9]* //' | " "sed 's/\\[//g' | sed 's/\\]//g'"); #elif defined(__APPLE__) - return run_command_s("system_profiler SPDisplaysDataType | " + cmd = malloc(128); + if (!cmd) return NULL; + snprintf(cmd, 128, "system_profiler SPDisplaysDataType | " "awk -F': ' '/^ *Chipset Model:/ {printf $2 \", \"}'"); #elif defined(__HAIKU__) const char *vendor = run_command_s("listdev | grep -A1 \"device Display\" | " @@ -91,12 +107,14 @@ const char *display_gpu() { char *cmd = (char *)malloc(128 * sizeof(char)); if (!cmd) return NULL; - if (strncmp(vendor, device, strlen(device)) == 0) + if (strncmp(vendor, device, strlen(device)) == 0) { snprintf(cmd, 128, "%s", device); - else + free((void *)device); + } else { snprintf(cmd, 128, "%s %s", device, vendor); - - return cmd; + free((void *)device); + free((void *)vendor); + } #else if ( access("/bin/glxinfo", F_OK) == -1 && @@ -106,8 +124,20 @@ const char *display_gpu() { access("/usr/X11R7/bin/glxinfo", F_OK) == -1 && access("/usr/pkg/bin/glxinfo", F_OK) == -1 ) return NULL; - return run_command_s("glxinfo -B | grep -F 'OpenGL renderer string' | " + + cmd = malloc(256); + if (!cmd) return NULL; + snprintf(cmd, 256, "glxinfo -B | grep -F 'OpenGL renderer string' | " "sed 's/OpenGL renderer string: //' | sed 's/Mesa //' | " "sed 's/DRI //' | sed 's/(R)//' | sed 's/(.*$//'"); #endif + + if (!cmd) return NULL; + out = run_command_s(cmd); + free((void *)cmd); +#if !defined(__HAIKU__) + if (out) to_cache("/tmp/farfetch/gpu", out); +#endif + + return out; } diff --git a/src/host.c b/src/host.c index 5a99464..9f1a458 100644 --- a/src/host.c +++ b/src/host.c @@ -1,4 +1,5 @@ #include "host.h" +#include "common.h" #include #include @@ -8,141 +9,76 @@ #include #endif -const char *run_host_command(const char *command) { - char buf[64]; +const char *display_host() { +#if !defined(__HAIKU__) + char *out = (char *)from_cache("/tmp/farfetch/host"); + if (out) return out; +#else char *out = NULL; - size_t outsize = 0; - - FILE *p = popen(command, "r"); - if (!p) { - fprintf(stderr, "ホストコマンドを実効に失敗: %s", command); - return NULL; - } - - while (fgets(buf, sizeof(buf), p) != NULL) { - buf[strcspn(buf, "\n")] = '\0'; -#if defined(__linux__) - if ( - strstr(buf, "To be filled by O.E.M.") != NULL || - strstr(buf, "To Be Filled By O.E.M.") != NULL || - strstr(buf, "OEM") != NULL || - strstr(buf, "Not Applicable") != NULL || - strstr(buf, "System Product Name") != NULL || - strstr(buf, "System Version") != NULL || - strstr(buf, "Undefined") != NULL || - strstr(buf, "Default string") != NULL || - strstr(buf, "Not Specified") != NULL || - strstr(buf, "Type1ProductConfigId") != NULL || - strstr(buf, "INVALID") != NULL || - strstr(buf, "All Series") != NULL - ) { - return NULL; - } #endif + const char *cmd = NULL; - size_t len = strlen(buf); - char *nout = realloc(out, outsize + len + 1); - if (nout == NULL) { - perror("メモリの役割に失敗"); - free(out); - pclose(p); - return NULL; - } - - out = nout; - - memccpy(out + outsize, buf, sizeof(buf), len); - outsize += len; - out[outsize] = '\0'; - } - - pclose(p); - - return out; -} - -void display_host_model() { #if defined(__OpenBSD__) - const char *cmd = run_host_command("sysctl -n hw.vendor && echo \" \" && " - "if [ \"$(sysctl -n hw.version 2>&1)\" != " - "\"sysctl: hw.version: value is not available\" ]; then " - "sysctl -n hw.version && echo \" \"; fi && " - "sysctl -n hw.product"); - if (!cmd) return; - printf("%s", cmd); - free((void *)cmd); + cmd = "sysctl -n hw.vendor && echo \" \" && " + "if [ \"$(sysctl -n hw.version 2>&1)\" != " + "\"sysctl: hw.version: value is not available\" ]; then " + "sysctl -n hw.version && echo \" \"; fi && " + "sysctl -n hw.product"; #elif defined(__FreeBSD__) - const char *family = run_host_command("kenv | grep smbios.system.family | " - "sed 's/\"//g' | sed 's/smbios.system.family=//'"); - if (strncmp(family, " ", strlen(family)) == 0) { - family = run_host_command("kenv | grep smbios.system.version | " - "sed 's/\"//g' | sed 's/smbios.system.version=//'"); - } - const char *product = run_host_command("kenv | grep smbios.system.product | " - "sed 's/\"//g' | sed 's/smbios.system.product=//'"); - const char *maker = run_host_command("kenv | grep smbios.system.maker | " - "sed 's/\"//g' | sed 's/smbios.system.maker=//'"); - printf("%s %s %s", maker, family, product); - if (maker) free((void *)maker); - if (family) free((void *)family); - if (product) free((void *)product); + cmd = "kenv | grep smbios.system.family | sed 's/\"//g' | " + "sed 's/smbios.system.family=//' && " + "kenv | grep smbios.system.version | sed 's/\"//g' | " + "sed 's/smbios.system.version=//' && " + "kenv | grep smbios.system.product | sed 's/\"//g' | " + "sed 's/smbios.system.product=//' && " + "kenv | grep smbios.system.maker | sed 's/\"//g' | " + "sed 's/smbios.system.maker=//'"; #elif defined(__NetBSD__) - const char *cmd = run_host_command("sysctl -n machdep.dmi.system-vendor && " - "echo \" \" && sysctl -n machdep.dmi.system-version && " - "echo \" \" && sysctl -n machdep.dmi.system-product"); - if (!cmd) return; - printf("%s", cmd); - free((void *)cmd); + cmd = "sysctl -n machdep.dmi.system-vendor && " + "echo \" \" && sysctl -n machdep.dmi.system-version && " + "echo \" \" && sysctl -n machdep.dmi.system-product"; #elif defined(__sun) - const char *cmd = run_host_command("smbios | grep \"Product\" | " - "sed 's/ Product: //' | awk '{$1=$1};1' | head -1"); - if (!cmd) return; - printf("%s", cmd); - free((void *)cmd); + cmd = "smbios | grep \"Product\" | " + "sed 's/ Product: //' | awk '{$1=$1};1' | head -1"; #elif defined(__linux__) - const char *cmd1 = NULL; - const char *cmd2 = NULL; + const char *pre_cmd = NULL; + if (access("/system/app/", F_OK) != -1) { - cmd1 = "getprop ro.product.brand"; - cmd2 = "getprop ro.product.model"; + pre_cmd = "getprop ro.product.brand && echo \" \" && getprop ro.product.model"; } else if ( access("/sys/devices/virtual/dmi/id/product_name", F_OK) != -1 && access("/sys/devices/virtual/dmi/id/product_version", F_OK) != 1 ) { - cmd1 = "cat /sys/devices/virtual/dmi/id/product_name"; - cmd2 = "cat /sys/devices/virtual/dmi/id/product_version"; + pre_cmd = "cat /sys/devices/virtual/dmi/id/product_name && echo \" \" && " + "cat /sys/devices/virtual/dmi/id/product_version"; } else if (access("/sys/firmware/devicetree/base/model", F_OK) != -1) { - cmd1 = "cat /sys/firmware/devicetree/base/model"; + pre_cmd = "cat /sys/firmware/devicetree/base/model"; } else if (access("/tmp/sysinfo/model", F_OK) != 1) { - cmd1 = "cat /tmp/sysinfo/model"; - } - - if (!cmd1) { - printf("Unknown"); + pre_cmd = "cat /tmp/sysinfo/model"; } else { - const char *cmd = run_host_command(cmd1); - if (!cmd) return; - printf("%s", cmd); - free((void *)cmd); + return "Unknown"; } - if (cmd2) { - const char *model = run_host_command(cmd2); - if (!model) return; - printf(" %s", model); - free((void *)model); - } + size_t cmdlen = 1024; + cmd = malloc(cmdlen); + if (!cmd) return "Unknown"; + + snprintf((char *)cmd, cmdlen, "%s | sed '/To be filled by O.E.M./d; " + "/To Be Filled By O.E.M./d; /OEM/d; /Not Applicable/d; " + "/System Product Name/d; /System Version/d; /Undefined/d; /Default string/d; " + "/Not Specified/d; /Type1ProductConfigId/d; /INVALID/d; " + "/All Series/d' ", pre_cmd); #elif defined(__APPLE__) - const char *cmd = run_host_command("sysctl -n hw.model"); - if (!cmd) return; - printf("%s", cmd); - free((void *)cmd); - - // TODO: Hackingtoshユーザーさん、助けて〜!! - /* const char *kext = run_host_command("kextstat | grep -F -e \"FakeSMC\" " */ - /* "-e \"VirtualSMC\""); */ - /* if (!kext) return; */ - /* printf(", %s", kext); */ - /* free((void *)kext); */ + cmd = "sysctl -n hw.model"; #endif + + if (!cmd) return "Unknown"; + + out = (char *)run_command_s(cmd); + free((void *)cmd); +#if !defined(__HAIKU__) + to_cache("/tmp/farfetch/host", out); +#endif + + return out; } diff --git a/src/host.h b/src/host.h index 77b8ba5..ded843c 100644 --- a/src/host.h +++ b/src/host.h @@ -1,6 +1,6 @@ #ifndef HOST_H #define HOST_H -void display_host_model(); +const char *display_host(); #endif diff --git a/src/os.c b/src/os.c index bea876f..fa81fc5 100644 --- a/src/os.c +++ b/src/os.c @@ -8,18 +8,64 @@ const char *display_os() { const char *osname = NULL; const char *osversion = NULL; const char *osarch = NULL; + char *cmd; #if defined(__APPLE__) - osname = run_command_s("sw_vers | grep \"ProductName\" | awk '{print $2}'"); - osversion = run_command_s("sw_vers | grep \"ProductVersion\" | awk '{print $2}'"); -#else + if (!from_cache("/tmp/farfetch/os")) { + osname = run_command_s("sw_vers | grep \"ProductName\" | awk '{print $2}'"); + osversion = run_command_s("sw_vers | grep \"ProductVersion\" | awk '{print $2}'"); + osarch = run_command_s("uname -m"); + + cmd = (char *)malloc(128 * sizeof(char)); + if (!cmd) { + perror("malloc"); + free((void *)osname); + free((void *)osversion); + free((void *)osarch); + return NULL; + } + snprintf(cmd, 128, "%s %s %s", osname, osversion, osarch); + + to_cache("/tmp/farfetch/os", cmd); + } else { + cmd = (char *)from_cache("/tmp/farfetch/os"); + } +#elif defined(__HAIKU__) osname = run_command_s("uname -s"); osversion = run_command_s("uname -r"); -#endif osarch = run_command_s("uname -m"); - char *cmd = (char *)malloc(128 * sizeof(char)); + cmd = (char *)malloc(128 * sizeof(char)); + if (!cmd) { + perror("malloc"); + free((void *)osname); + free((void *)osversion); + free((void *)osarch); + return NULL; + } snprintf(cmd, 128, "%s %s %s", osname, osversion, osarch); +#else + if (!from_cache("/tmp/farfetch/os")) { + osname = run_command_s("uname -s"); + osversion = run_command_s("uname -r"); + osarch = run_command_s("uname -m"); + + cmd = (char *)malloc(128 * sizeof(char)); + if (!cmd) { + perror("malloc"); + free((void *)osname); + free((void *)osversion); + free((void *)osarch); + return NULL; + } + snprintf(cmd, 128, "%s %s %s", osname, osversion, osarch); + + to_cache("/tmp/farfetch/os", cmd); + } else { + cmd = (char *)from_cache("/tmp/farfetch/os"); + } +#endif + free((void *)osname); free((void *)osversion); free((void *)osarch);