/* * UwUfetch is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UWUFETCH_VERSION #define UWUFETCH_VERSION "unkown" // needs to be changed by the build script #endif #define _GNU_SOURCE // for strcasestr #ifdef __APPLE__ #include // for checking iOS #endif #include #include #include #include #include #include #if defined(__APPLE__) || defined(__FREEBSD__) #include #include #else // defined(__APPLE__) || defined(__FREEBSD__) #ifdef __FREEBSD__ #else // defined(__FREEBSD__) || defined(_WIN32) #ifndef _WIN32 #include #else // _WIN32 #include #endif // _WIN32 #endif // defined(__FREEBSD__) || defined(_WIN32) #endif // defined(__APPLE__) || defined(__FREEBSD__) #ifndef _WIN32 #include #include #else // _WIN32 #include CONSOLE_SCREEN_BUFFER_INFO csbi; #endif // _WIN32 // COLORS #define NORMAL "\x1b[0m" #define BOLD "\x1b[1m" #define BLACK "\x1b[30m" #define RED "\x1b[31m" #define GREEN "\x1b[32m" #define SPRING_GREEN "\x1b[38;5;120m" #define YELLOW "\x1b[33m" #define BLUE "\x1b[34m" #define MAGENTA "\x1b[0;35m" #define CYAN "\x1b[36m" #define WHITE "\x1b[37m" #define PINK "\x1b[38;5;201m" #define LPINK "\x1b[38;5;213m" #ifdef _WIN32 #define BLOCK_CHAR "\xdb" // block char for colors #else // _WIN32 #define BLOCK_CHAR "\u2587" #endif // _WIN32 #ifdef __APPLE__ // buffers where data fetched from sysctl are stored // CPU #define CPUBUFFERLEN 128 char cpu_buffer[CPUBUFFERLEN]; size_t cpu_buffer_len = CPUBUFFERLEN; // Installed RAM int64_t mem_buffer = 0; size_t mem_buffer_len = sizeof(mem_buffer); // uptime struct timeval time_buffer; size_t time_buffer_len = sizeof(time_buffer); #endif // __APPLE__ struct package_manager { char command_string[128]; // command to get number of packages installed char pkgman_name[16]; // name of the package manager }; // all configuration flags available struct configuration { int // when (0) ascii is printed, when (1) image is printed ascii_image_flag, show_user_info, // all the following flags are 1 (true) by default show_os, show_host, show_kernel, show_cpu, // if show_gpu[0] == -2, all gpus are shown, if == -3 no gpu is shown show_gpu[256], show_ram, show_resolution, show_shell, show_pkgs, show_uptime, show_colors; }; // info that will be printed with the logo struct info { char user[128], // username host[256], // hostname (computer name) shell[64], // shell name model[256], // model name kernel[256], // kernel name (linux 5.x-whatever) os_name[64], // os name (arch linux, windows, mac os) cpu_model[256], gpu_model[64][256], pkgman_name[64], // package managers string image_name[128], *config_directory, // configuration directory name *cache_content; // cache file content int target_width, // for the truncate_str function screen_width, screen_height, ram_total, ram_used, pkgs; // full package count long uptime; #ifndef _WIN32 struct utsname sys_var; #endif // _WIN32 #ifndef __APPLE__ #ifdef __linux__ struct sysinfo sys; #else // __linux__ #ifdef _WIN32 struct _SYSTEM_INFO sys; #endif // _WIN32 #endif // __linux__ #endif // __APPLE__ #ifndef _WIN32 struct winsize win; #else // _WIN32 int ws_col, ws_rows; #endif // _WIN32 }; #ifdef _WIN32 char* MOVE_CURSOR = "\033[21C"; // moves the cursor after printing the image or the ascii logo #else char* MOVE_CURSOR = "\033[18C"; #endif // reads the config file struct configuration parse_config(struct info* user_info) { char buffer[256]; // buffer for the current line // enabling all flags by default struct configuration config_flags; memset(&config_flags, 1, sizeof(config_flags)); memset(&config_flags.show_gpu, -1, 256 * sizeof(int)); // -1 means 'undefined' config_flags.show_gpu[0] = -2; // show all gpus config_flags.ascii_image_flag = 0; FILE* config = NULL; // config file pointer if (user_info->config_directory == NULL) { // if config directory is not set, try to open the default if (getenv("HOME") != NULL) { char homedir[512]; sprintf(homedir, "%s/.config/uwufetch/config", getenv("HOME")); config = fopen(homedir, "r"); if (!config) { if (getenv("PREFIX") != NULL) { char prefixed_etc[512]; sprintf(prefixed_etc, "%s/etc/uwufetch/config", getenv("PREFIX")); config = fopen(prefixed_etc, "r"); } else config = fopen("/etc/uwufetch/config", "r"); } } } else config = fopen(user_info->config_directory, "r"); if (config == NULL) return config_flags; // if config file does not exist, return the defaults int gpu_cfg_count = 0; // reading the config file while (fgets(buffer, sizeof(buffer), config)) { sscanf(buffer, "distro=%s", user_info->os_name); if (sscanf(buffer, "ascii=%[truefalse]", buffer)) config_flags.ascii_image_flag = !strcmp(buffer, "false"); if (sscanf(buffer, "image=\"%[^\"]\"", user_info->image_name)) { if (user_info->image_name[0] == '~') { // replacing the ~ character with the home directory memmove(&user_info->image_name[0], &user_info->image_name[1], strlen(user_info->image_name)); // remove the first char char temp[128] = "/home/"; strcat(temp, user_info->user); strcat(temp, user_info->image_name); sprintf(user_info->image_name, "%s", temp); } config_flags.ascii_image_flag = 1; // enable the image flag } // reading other values if (sscanf(buffer, "user=%[truefalse]", buffer)) config_flags.show_user_info = !strcmp(buffer, "true"); if (sscanf(buffer, "os=%[truefalse]", buffer)) config_flags.show_os = strcmp(buffer, "false"); if (sscanf(buffer, "host=%[truefalse]", buffer)) config_flags.show_host = strcmp(buffer, "false"); if (sscanf(buffer, "kernel=%[truefalse]", buffer)) config_flags.show_kernel = strcmp(buffer, "false"); if (sscanf(buffer, "cpu=%[truefalse]", buffer)) config_flags.show_cpu = strcmp(buffer, "false"); if (sscanf(buffer, "gpu=%d", &config_flags.show_gpu[gpu_cfg_count])) // enabling single gpu gpu_cfg_count++; if (sscanf(buffer, "gpu=%[truefalse]", buffer)) { // enabling all gpus if (strcmp(buffer, "false") == 0) config_flags.show_gpu[0] = -3; // disable all gpus } if (sscanf(buffer, "ram=%[truefalse]", buffer)) config_flags.show_ram = strcmp(buffer, "false"); if (sscanf(buffer, "resolution=%[truefalse]", buffer)) config_flags.show_resolution = strcmp(buffer, "false"); if (sscanf(buffer, "shell=%[truefalse]", buffer)) config_flags.show_shell = strcmp(buffer, "false"); if (sscanf(buffer, "pkgs=%[truefalse]", buffer)) config_flags.show_pkgs = strcmp(buffer, "false"); if (sscanf(buffer, "uptime=%[truefalse]", buffer)) config_flags.show_uptime = strcmp(buffer, "false"); if (sscanf(buffer, "colors=%[truefalse]", buffer)) config_flags.show_colors = strcmp(buffer, "false"); } fclose(config); return config_flags; } // gets the installed package count and package managers name #ifdef _WIN32 int pkgman(struct info* user_info, struct configuration* config_flags) #else // _WIN32 int pkgman(struct info* user_info) #endif { // this is just a function that returns the total of installed packages int total = 0; #ifndef __APPLE__ // this function is not used on mac os because it causes lots of problems #ifndef _WIN32 // all supported package managers struct package_manager pkgmans[] = {{"apt list --installed 2> /dev/null | wc -l", "(apt)"}, {"apk info 2> /dev/null | wc -l", "(apk)"}, // {"dnf list installed 2> /dev/null | wc -l", "(dnf)"}, // according to https://stackoverflow.com/questions/48570019/advantages-of-dnf-vs-rpm-on-fedora, dnf and rpm return the same number of packages {"qlist -I 2> /dev/null | wc -l", "(emerge)"}, {"flatpak list 2> /dev/null | wc -l", "(flatpak)"}, {"snap list 2> /dev/null | wc -l", "(snap)"}, {"guix package --list-installed 2> /dev/null | wc -l", "(guix)"}, {"nix-store -q --requisites /run/current-system/sw 2> /dev/null | wc -l", "(nix)"}, {"pacman -Qq 2> /dev/null | wc -l", "(pacman)"}, {"pkg info 2>/dev/null | wc -l", "(pkg)"}, {"port installed 2> /dev/null | tail -n +2 | wc -l", "(port)"}, {"brew list 2> /dev/null | wc -l", "(brew)"}, {"rpm -qa --last 2> /dev/null | wc -l", "(rpm)"}, {"xbps-query -l 2> /dev/null | wc -l", "(xbps)"}, {"zypper -q se --installed-only 2> /dev/null | wc -l", "(zypper)"}}; const int pkgman_count = sizeof(pkgmans) / sizeof(pkgmans[0]); // number of package managers int comma_separator = 0; for (int i = 0; i < pkgman_count; i++) { struct package_manager* current = &pkgmans[i]; // pointer to current package manager FILE* fp = popen(current->command_string, "r"); // trying current package manager unsigned int pkg_count = 0; if (fscanf(fp, "%u", &pkg_count) == 3) continue; // if a number is found, continue the loop pclose(fp); // adding a package manager with its package count to user_info->pkgman_name total += pkg_count; if (pkg_count > 0) { if (comma_separator++) strcat(user_info->pkgman_name, ", "); char spkg_count[16]; sprintf(spkg_count, "%u", pkg_count); strcat(user_info->pkgman_name, spkg_count); strcat(user_info->pkgman_name, " "); strcat(user_info->pkgman_name, current->pkgman_name); } } #else // _WIN32 // chocolatey for windows if (config_flags->show_pkgs) { FILE* fp = popen("choco list -l --no-color 2> nul", "r"); unsigned int pkg_count; char buffer[7562] = {0}; while (fgets(buffer, sizeof(buffer), fp)) { sscanf(buffer, "%u packages installed.", &pkg_count); } if (fp) pclose(fp); total = pkg_count; char spkg_count[16]; sprintf(spkg_count, "%u", pkg_count); strcat(user_info->pkgman_name, spkg_count); strcat(user_info->pkgman_name, " "); strcat(user_info->pkgman_name, "(chocolatey)"); } #endif // _WIN32 #endif return total; } #ifdef __APPLE__ // gets the uptime for mac os int uptime_apple() { int mib[2] = {CTL_KERN, KERN_BOOTTIME}; sysctl(mib, 2, &time_buffer, &time_buffer_len, NULL, 0); time_t bsec = time_buffer.tv_sec; time_t csec = time(NULL); return difftime(csec, bsec); } #endif #ifdef __FREEBSD__ // gets the uptime for freebsd int uptime_freebsd() { // this code is from coreutils uptime: https://github.com/coreutils/coreutils/blob/master/src/uptime.c int boot_time = 0; static int request[2] = {CTL_KERN, KERN_BOOTTIME}; struct timeval result; size_t result_len = sizeof result; if (sysctl(request, 2, &result, &result_len, NULL, 0) >= 0) boot_time = result.tv_sec; int time_now = time(NULL); return time_now - boot_time; } #endif // prints logo (as an image) of the given system. void print_image(struct info* user_info) { #ifndef __IPHONE__ char command[256]; if (strlen(user_info->image_name) > 1) sprintf(command, "viu -t -w 18 -h 8 %s 2> /dev/null", user_info->image_name); // creating the command to show the image else { if (strcmp(user_info->os_name, "android") == 0) sprintf(command, "viu -t -w 18 -h 8 /data/data/com.termux/files/usr/lib/uwufetch/%s.png 2> /dev/null", user_info->os_name); // image command for android else if (strcmp(user_info->os_name, "macos") == 0) sprintf(command, "viu -t -w 18 -h 8 /usr/local/lib/uwufetch/%s.png 2> /dev/null", user_info->os_name); else sprintf(command, "viu -t -w 18 -h 8 /usr/lib/uwufetch/%s.png 2> /dev/null", user_info->os_name); // image command for other systems } printf("\n"); if (system(command) != 0) // if viu is not installed or the image is missing printf("\033[0E\033[3C%s\n" " There was an\n" " error: viu\n" " is not installed\n" " or the image\n" " is not found\n" " Read IMAGES.md\n" " for more info.\n\n", RED); #else // unfortunately, the iOS stdlib does not have // system(); // because it reports that it is not available under iOS during compilation printf("\033[0E\033[3C%s\n" " There was an\n" " error: images\n" " are currently\n" " disabled on iOS.\n\n", RED); #endif } // uwufies distro name void uwu_name(struct configuration* config_flags, struct info* user_info) { #define STRING_TO_UWU(original, uwufied) \ if (strcmp(user_info->os_name, original) == 0) \ sprintf(user_info->os_name, "%s", uwufied) // linux STRING_TO_UWU("alpine", "Nyalpine"); else STRING_TO_UWU("amogos", "AmogOwOS"); else STRING_TO_UWU("arch", "Nyarch Linuwu"); else STRING_TO_UWU("arcolinux", "ArcOwO Linuwu"); else STRING_TO_UWU("artix", "Nyartix Linuwu"); else STRING_TO_UWU("debian", "Debinyan"); else STRING_TO_UWU("endeavouros", "endeavOwO"); else STRING_TO_UWU("EndeavourOS", "endeavOwO"); else STRING_TO_UWU("fedora", "Fedowa"); else STRING_TO_UWU("gentoo", "GentOwO"); else STRING_TO_UWU("gnu", "gnUwU"); else STRING_TO_UWU("guix", "gnUwU gUwUix"); else STRING_TO_UWU("linuxmint", "LinUWU Miwint"); else STRING_TO_UWU("manjaro", "Myanjawo"); else STRING_TO_UWU("manjaro-arm", "Myanjawo AWM"); else STRING_TO_UWU("neon", "KDE NeOwOn"); else STRING_TO_UWU("nixos", "nixOwOs"); else STRING_TO_UWU("opensuse-leap", "OwOpenSUSE Leap"); else STRING_TO_UWU("opensuse-tumbleweed", "OwOpenSUSE Tumbleweed"); else STRING_TO_UWU("pop", "PopOwOS"); else STRING_TO_UWU("raspbian", "RaspNyan"); else STRING_TO_UWU("slackware", "Swackwawe"); else STRING_TO_UWU("solus", "sOwOlus"); else STRING_TO_UWU("ubuntu", "Uwuntu"); else STRING_TO_UWU("void", "OwOid"); else STRING_TO_UWU("xerolinux", "xuwulinux"); else STRING_TO_UWU("android", "Nyandroid"); // android at the end because it could be not considered as an actual distribution of gnu/linux // BSD else STRING_TO_UWU("freebsd", "FweeBSD"); else STRING_TO_UWU("openbsd", "OwOpenBSD"); // Apple family else STRING_TO_UWU("macos", "macOwOS"); else STRING_TO_UWU("ios", "iOwOS"); // Windows else STRING_TO_UWU("windows", "WinyandOwOws"); else { sprintf(user_info->os_name, "%s", "unknown"); // replacing the original os name with the uwufied version if (config_flags->ascii_image_flag == 1) { print_image(user_info); printf("\n"); } } #undef STRING_TO_UWU } // prints all the collected info and returns the number of printed lines int print_info(struct configuration* config_flags, struct info* user_info) { int line_count = 0; #ifdef _WIN32 // prints without overflowing the terminal width #define responsively_printf(buf, format, ...) \ { \ sprintf(buf, format, __VA_ARGS__); \ printf("%.*s\n", user_info->ws_col - 1, buf); \ line_count++; \ } #else // _WIN32 // prints without overflowing the terminal width #define responsively_printf(buf, format, ...) \ { \ sprintf(buf, format, __VA_ARGS__); \ printf("%.*s\n", user_info->win.ws_col - 1, buf); \ line_count++; \ } #endif // _WIN32 char print_buf[1024]; // for responsively print // print collected info - from host to cpu info printf("\033[9A"); // to align info text if (config_flags->show_user_info) responsively_printf(print_buf, "%s%s%s%s@%s", MOVE_CURSOR, NORMAL, BOLD, user_info->user, user_info->host); uwu_name(config_flags, user_info); if (config_flags->show_os) responsively_printf(print_buf, "%s%s%sOWOS %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->os_name); if (config_flags->show_host) responsively_printf(print_buf, "%s%s%sMOWODEL %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->model); if (config_flags->show_kernel) responsively_printf(print_buf, "%s%s%sKEWNEL %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->kernel); if (config_flags->show_cpu) responsively_printf(print_buf, "%s%s%sCPUWU %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->cpu_model); if (config_flags->show_gpu[0] == -2) { // print all gpu models for (int i = 0; i < 256 && user_info->gpu_model[i][0]; i++) { responsively_printf(print_buf, "%s%s%sGPUWU %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->gpu_model[i]); } } else if (config_flags->show_gpu[0] != -3) { // print only the configured gpu models for (int i = 0; i < 256; i++) { if (config_flags->show_gpu[i] >= 0) if (user_info->gpu_model[config_flags->show_gpu[i]][0]) responsively_printf(print_buf, "%s%s%sGPUWU %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->gpu_model[config_flags->show_gpu[i]]); } } if (config_flags->show_ram) // print ram responsively_printf(print_buf, "%s%s%sMEMOWY %s%i MiB/%i MiB", MOVE_CURSOR, NORMAL, BOLD, NORMAL, (user_info->ram_used), user_info->ram_total); if (config_flags->show_resolution) // print resolution if (user_info->screen_width != 0 || user_info->screen_height != 0) responsively_printf(print_buf, "%s%s%sWESOWUTION%s %dx%d", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->screen_width, user_info->screen_height); if (config_flags->show_shell) // print shell name responsively_printf(print_buf, "%s%s%sSHEWW %s%s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->shell); #if defined(__APPLE__) && !defined(__IPHONE__) // some time ago __IPHONE__ was defined as TARGET_OS_IPHONE, but it was defined also in m1 macs, so I changed it if (config_flags->show_pkgs) // print pkgs for mac os system("ls $(brew --cellar) | wc -l | awk -F' ' '{print \" \x1b[34m \x1b[0m\x1b[1mPKGS\x1b[0m \"$1 \" (brew)\"}'"); #else if (config_flags->show_pkgs) // print pkgs responsively_printf(print_buf, "%s%s%sPKGS %s%s%d: %s", MOVE_CURSOR, NORMAL, BOLD, NORMAL, NORMAL, user_info->pkgs, user_info->pkgman_name); #endif if (config_flags->show_uptime) { // print uptime if (user_info->uptime == 0) { #ifdef __APPLE__ user_info->uptime = uptime_apple(); #else #ifdef __FREEBSD__ user_info->uptime = uptime_freebsd(); #else #ifdef _WIN32 user_info->uptime = GetTickCount() / 1000; #else // _WIN32 user_info->uptime = user_info->sys.uptime; #endif // _WIN32 #endif #endif } switch (user_info->uptime) { // formatting the uptime which is store in seconds case 0 ... 3599: responsively_printf(print_buf, "%s%s%sUWUPTIME %s%lim", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->uptime / 60 % 60); break; case 3600 ... 86399: responsively_printf(print_buf, "%s%s%sUWUPTIME %s%lih, %lim", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->uptime / 3600, user_info->uptime / 60 % 60); break; default: responsively_printf(print_buf, "%s%s%sUWUPTIME %s%lid, %lih, %lim", MOVE_CURSOR, NORMAL, BOLD, NORMAL, user_info->uptime / 86400, user_info->uptime / 3600 % 24, user_info->uptime / 60 % 60); } } if (config_flags->show_colors) // print colors printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", MOVE_CURSOR, BOLD, BLACK, BLOCK_CHAR, BLOCK_CHAR, RED, BLOCK_CHAR, BLOCK_CHAR, GREEN, BLOCK_CHAR, BLOCK_CHAR, YELLOW, BLOCK_CHAR, BLOCK_CHAR, BLUE, BLOCK_CHAR, BLOCK_CHAR, MAGENTA, BLOCK_CHAR, BLOCK_CHAR, CYAN, BLOCK_CHAR, BLOCK_CHAR, WHITE, BLOCK_CHAR, BLOCK_CHAR, NORMAL); return line_count; } // writes cache to cache file void write_cache(struct info* user_info) { char cache_file[512]; sprintf(cache_file, "%s/.cache/uwufetch.cache", getenv("HOME")); // default cache file location FILE* cache_fp = fopen(cache_file, "w"); if (cache_fp == NULL) { fprintf(stderr, "Failed to write to %s!", cache_file); return; } // writing all info to the cache file #ifdef __APPLE__ user_info->uptime = uptime_apple(); #else #ifdef __FREEBSD__ user_info->uptime = uptime_freebsd(); #else #ifndef _WIN32 user_info->uptime = user_info->sys.uptime; #endif // _WIN32 #endif #endif fprintf( // writing most of the values to config file cache_fp, "user=%s\nhost=%s\nversion_name=%s\nhost_model=%s\nkernel=%s\ncpu=%" "s\nscreen_width=%d\nscreen_height=%d\nshell=%s\npkgs=%d\npkgman_name=%" "s\n", user_info->user, user_info->host, user_info->os_name, user_info->model, user_info->kernel, user_info->cpu_model, user_info->screen_width, user_info->screen_height, user_info->shell, user_info->pkgs, user_info->pkgman_name); for (int i = 0; user_info->gpu_model[i][0]; i++) // writing gpu names to file fprintf(cache_fp, "gpu=%s\n", user_info->gpu_model[i]); #ifdef __APPLE__ /* char brew_command[2048]; sprintf(brew_command, "ls $(brew --cellar) | wc -l | awk -F' ' '{print \" \x1b[34mw w \x1b[0m\x1b[1mPKGS\x1b[0m \"$1 \" (brew)\"}' > %s", cache_file); system(brew_command); */ #endif fclose(cache_fp); return; } // reads cache file if it exists int read_cache(struct info* user_info) { char cache_file[512]; sprintf(cache_file, "%s/.cache/uwufetch.cache", getenv("HOME")); // cache file location FILE* cache_fp = fopen(cache_file, "r"); if (cache_fp == NULL) return 0; char buffer[256]; // line buffer int gpuc = 0; // gpu counter while (fgets(buffer, sizeof(buffer), cache_fp)) { // reading the file sscanf(buffer, "user=%99[^\n]", user_info->user); sscanf(buffer, "host=%99[^\n]", user_info->host); sscanf(buffer, "version_name=%99[^\n]", user_info->os_name); sscanf(buffer, "host_model=%99[^\n]", user_info->model); sscanf(buffer, "kernel=%99[^\n]", user_info->kernel); sscanf(buffer, "cpu=%99[^\n]", user_info->cpu_model); if (sscanf(buffer, "gpu=%99[^\n]", user_info->gpu_model[gpuc]) != 0) gpuc++; sscanf(buffer, "screen_width=%i", &user_info->screen_width); sscanf(buffer, "screen_height=%i", &user_info->screen_height); sscanf(buffer, "shell=%99[^\n]", user_info->shell); sscanf(buffer, "pkgs=%i", &user_info->pkgs); sscanf(buffer, "pkgman_name=%99[^\n]", user_info->pkgman_name); } fclose(cache_fp); return 1; } /* This replaces all terms in a string with another term. replace("Hello World!", "World", "everyone") This returns "Hello everyone!". */ void replace(char* original, char* search, char* replacer) { char* ch; char buffer[1024]; while ((ch = strstr(original, search))) { ch = strstr(original, search); strncpy(buffer, original, ch - original); buffer[ch - original] = 0; sprintf(buffer + (ch - original), "%s%s", replacer, ch + strlen(search)); original[0] = 0; strcpy(original, buffer); } } /* This replaces all terms in a string with another term, case insensitive replace("Hello wOrLd!", "WoRlD", "everyone") This returns "Hello everyone!". */ void replace_ignorecase(char* original, char* search, char* replacer) { char* ch; char buffer[1024]; #ifdef _WIN32 #define strcasestr(o, s) strstr(o, s) #endif while ((ch = strcasestr(original, search))) { strncpy(buffer, original, ch - original); buffer[ch - original] = 0; sprintf(buffer + (ch - original), "%s%s", replacer, ch + strlen(search)); original[0] = 0; strcpy(original, buffer); } } // prints logo (as ascii art) of the given system. void print_ascii(struct info* user_info) { printf("\n"); FILE* file; char ascii_file[1024]; // First tries to get ascii art file from local directory. Useful for debugging sprintf(ascii_file, "./res/ascii/%s.txt", user_info->os_name); file = fopen(ascii_file, "r"); if (!file) { // if the file does not exist in the local directory, open it from the installation directory if (strcmp(user_info->os_name, "android") == 0) sprintf(ascii_file, "/data/data/com.termux/files/usr/lib/uwufetch/ascii/%s.txt", user_info->os_name); else if (strcmp(user_info->os_name, "macos") == 0) sprintf(ascii_file, "/usr/local/lib/uwufetch/ascii/%s.txt", user_info->os_name); else sprintf(ascii_file, "/usr/lib/uwufetch/ascii/%s.txt", user_info->os_name); file = fopen(ascii_file, "r"); if (!file) { // Prevent infinite loops if (strcmp(user_info->os_name, "unknown") == 0) { printf("No\nunknown\nascii\nfile\n\n\n\n"); return; } sprintf(user_info->os_name, "unknown"); // current os is not supported return print_ascii(user_info); } } char buffer[256]; // line buffer while (fgets(buffer, 256, file)) { // replacing color placecholders replace(buffer, "{NORMAL}", NORMAL); replace(buffer, "{BOLD}", BOLD); replace(buffer, "{BLACK}", BLACK); replace(buffer, "{RED}", RED); replace(buffer, "{GREEN}", GREEN); replace(buffer, "{SPRING_GREEN}", SPRING_GREEN); replace(buffer, "{YELLOW}", YELLOW); replace(buffer, "{BLUE}", BLUE); replace(buffer, "{MAGENTA}", MAGENTA); replace(buffer, "{CYAN}", CYAN); replace(buffer, "{WHITE}", WHITE); replace(buffer, "{PINK}", PINK); replace(buffer, "{LPINK}", LPINK); replace(buffer, "{BLOCK}", BLOCK_CHAR); replace(buffer, "{BLOCK_VERTICAL}", BLOCK_CHAR); replace(buffer, "{BACKGROUND_GREEN}", "\e[0;42m"); replace(buffer, "{BACKGROUND_RED}", "\e[0;41m"); replace(buffer, "{BACKGROUND_WHITE}", "\e[0;47m"); printf("%s", buffer); // print the line after setting the color } // Always set color to NORMAL, so there's no need to do this in every ascii file. printf(NORMAL); fclose(file); } // prints the info after reading the cache file and returns the count of printed lines int print_cache(struct configuration* config_flags, struct info* user_info) { #ifndef __APPLE__ #ifndef _WIN32 #ifndef __FREEBSD__ sysinfo(&user_info->sys); // to get uptime #endif #endif FILE* meminfo; #ifdef __FREEBSD__ meminfo = popen("LANG=EN_us freecolor -om 2> /dev/null", "r"); // free alternative #else // getting memory info from /proc/meminfo: https://github.com/KittyKatt/screenFetch/issues/386#issuecomment-249312716 meminfo = fopen("/proc/meminfo", "r"); // popen("LANG=EN_us free -m 2> /dev/null", "r"); // get ram info with free #endif // brackets are here to restrict the access to this int variables, which are temporary { char buffer[256]; int memtotal = 0, shmem = 0, memfree = 0, buffers = 0, cached = 0, sreclaimable = 0; while (fgets(buffer, sizeof(buffer), meminfo)) { sscanf(buffer, "MemTotal: %d", &memtotal); sscanf(buffer, "Shmem: %d", &shmem); sscanf(buffer, "MemFree: %d", &memfree); sscanf(buffer, "Buffers: %d", &buffers); sscanf(buffer, "Cached: %d", &cached); sscanf(buffer, "SReclaimable: %d", &sreclaimable); } user_info->ram_total = memtotal / 1024; user_info->ram_used = ((memtotal + shmem) - (memfree + buffers + cached + sreclaimable)) / 1024; } // char line[256]; // while (fgets(line, sizeof(line), meminfo)) // old way to get ram usage that uses the "free" command // // free command prints like this: "Mem:" total used free shared buff/cache available // sscanf(line, "Mem: %d %d", &user_info->ram_total, &user_info->ram_used); fclose(meminfo); #elif defined(_WIN32) FILE* mem_used_fp; mem_used_fp = popen("wmic OS GET FreePhysicalMemory", "r"); // free does not exist for windows char mem_used_ch[2137]; printf("\n\n\n\\\n"); while (fgets(mem_used_ch, sizeof(mem_used_ch), mem_used_fp) != NULL) printf("%s\n", mem_used_ch); pclose(mem_used_fp); int mem_used = atoi(mem_used_ch); ram_used = mem_used / 1024; #else // __APPLE__ // Used ram FILE *mem_wired_fp, *mem_active_fp, *mem_compressed_fp; mem_wired_fp = popen("vm_stat | awk '/wired/ { printf $4 }' | cut -d '.' -f 1", "r"); mem_active_fp = popen("vm_stat | awk '/active/ { printf $3 }' | cut -d '.' -f 1", "r"); mem_compressed_fp = popen("vm_stat | awk '/occupied/ { printf $5 }' | cut -d '.' -f 1", "r"); char mem_wired_ch[2137], mem_active_ch[2137], mem_compressed_ch[2137]; while (fgets(mem_wired_ch, sizeof(mem_wired_ch), mem_wired_fp) != NULL) while (fgets(mem_active_ch, sizeof(mem_active_ch), mem_active_fp) != NULL) while (fgets(mem_compressed_ch, sizeof(mem_compressed_ch), mem_compressed_fp) != NULL) ; pclose(mem_wired_fp); pclose(mem_active_fp); pclose(mem_compressed_fp); int mem_wired = atoi(mem_wired_ch); int mem_active = atoi(mem_active_ch); int mem_compressed = atoi(mem_compressed_ch); // Total ram sysctlbyname("hw.memsize", &mem_buffer, &mem_buffer_len, NULL, 0); user_info->ram_used = ((mem_wired + mem_active + mem_compressed) * 4 / 1024); #endif // __APPLE__ print_ascii(user_info); return print_info(config_flags, user_info); } // truncates the given string void truncate_str(char* string, int target_width) { char arr[target_width]; for (int i = 0; i < target_width; i++) arr[i] = string[i]; string = arr; } // remove square brackets (for gpu names) void remove_brackets(char* str) { int i = 0, j = 0; while (i < (int)strlen(str)) if (str[i] == '[' || str[i] == ']') for (j = i; j < (int)strlen(str); j++) str[j] = str[j + 1]; else i++; } #ifdef _WIN32 // windows sucks and hasn't a strstep, so I copied one from // https://stackoverflow.com/questions/8512958/is-there-a-windows-variant-of-strsep-function char* strsep(char** stringp, const char* delim) { char* start = *stringp; char* p; p = (start != NULL) ? strpbrk(start, delim) : NULL; if (p == NULL) *stringp = NULL; else { *p = '\0'; *stringp = p + 1; } return start; } #endif // uwufies kernel name void uwu_kernel(char* kernel) { #define KERNEL_TO_UWU(str, original, uwufied) \ if (strcmp(str, original) == 0) sprintf(str, "%s", uwufied) char* temp_kernel = kernel; char* token; char splitted[16][128] = {}; int count = 0; while ((token = strsep(&temp_kernel, " "))) { // split kernel name strcpy(splitted[count], token); count++; } strcpy(kernel, ""); for (int i = 0; i < 16; i++) { // replace kernel name with uwufied version KERNEL_TO_UWU(splitted[i], "Linux", "Linuwu"); else KERNEL_TO_UWU(splitted[i], "linux", "linuwu"); else KERNEL_TO_UWU(splitted[i], "alpine", "Nyalpine"); else KERNEL_TO_UWU(splitted[i], "amogos", "AmogOwOS"); else KERNEL_TO_UWU(splitted[i], "arch", "Nyarch Linuwu"); else KERNEL_TO_UWU(splitted[i], "artix", "Nyartix Linuwu"); else KERNEL_TO_UWU(splitted[i], "debian", "Debinyan"); else KERNEL_TO_UWU(splitted[i], "endeavouros", "endeavOwO"); else KERNEL_TO_UWU(splitted[i], "EndeavourOS", "endeavOwO"); else KERNEL_TO_UWU(splitted[i], "fedora", "Fedowa"); else KERNEL_TO_UWU(splitted[i], "gentoo", "GentOwO"); else KERNEL_TO_UWU(splitted[i], "gnu", "gnUwU"); else KERNEL_TO_UWU(splitted[i], "guix", "gnUwU gUwUix"); else KERNEL_TO_UWU(splitted[i], "linuxmint", "LinUWU Miwint"); else KERNEL_TO_UWU(splitted[i], "manjaro", "Myanjawo"); else KERNEL_TO_UWU(splitted[i], "manjaro-arm", "Myanjawo AWM"); else KERNEL_TO_UWU(splitted[i], "neon", "KDE NeOwOn"); else KERNEL_TO_UWU(splitted[i], "nixos", "nixOwOs"); else KERNEL_TO_UWU(splitted[i], "opensuse-leap", "OwOpenSUSE Leap"); else KERNEL_TO_UWU(splitted[i], "opensuse-tumbleweed", "OwOpenSUSE Tumbleweed"); else KERNEL_TO_UWU(splitted[i], "pop", "PopOwOS"); else KERNEL_TO_UWU(splitted[i], "raspbian", "RaspNyan"); else KERNEL_TO_UWU(splitted[i], "slackware", "Swackwawe"); else KERNEL_TO_UWU(splitted[i], "solus", "sOwOlus"); else KERNEL_TO_UWU(splitted[i], "ubuntu", "Uwuntu"); else KERNEL_TO_UWU(splitted[i], "void", "OwOid"); else KERNEL_TO_UWU(splitted[i], "xerolinux", "xuwulinux"); else KERNEL_TO_UWU(splitted[i], "android", "Nyandroid"); // android at the end because it could be not considered as an actual distribution of gnu/linux // BSD else KERNEL_TO_UWU(splitted[i], "freebsd", "FweeBSD"); else KERNEL_TO_UWU(splitted[i], "openbsd", "OwOpenBSD"); // Apple family else KERNEL_TO_UWU(splitted[i], "macos", "macOwOS"); else KERNEL_TO_UWU(splitted[i], "ios", "iOwOS"); // Windows else KERNEL_TO_UWU(splitted[i], "windows", "WinyandOwOws"); if (i != 0) strcat(kernel, " "); strcat(kernel, splitted[i]); } #undef KERNEL_TO_UWU } void uwu_hw(char* hwname) { #define HW_TO_UWU(original, uwuified) \ replace_ignorecase(hwname, original, uwuified); HW_TO_UWU("lenovo", "LenOwO") HW_TO_UWU("cpu", "CC\bPUwU"); // for some reasons this caused a segfault, using a \b (backspace) char fixes it HW_TO_UWU("gpu", "GG\bPUwU") HW_TO_UWU("graphics", "Gwaphics") HW_TO_UWU("corporation", "COwOpowation") HW_TO_UWU("nvidia", "NyaVIDIA") HW_TO_UWU("mobile", "Mwobile") HW_TO_UWU("intel", "Inteww") HW_TO_UWU("radeon", "Radenyan") HW_TO_UWU("geforce", "GeFOwOce") HW_TO_UWU("raspberry", "Nyasberry") HW_TO_UWU("broadcom", "Bwoadcom") HW_TO_UWU("motorola", "MotOwOwa") HW_TO_UWU("proliant", "ProLinyant") HW_TO_UWU("poweredge", "POwOwEdge") HW_TO_UWU("apple", "Nyaa\bpple") HW_TO_UWU("electronic", "ElectrOwOnic") #undef HW_TO_UWU } // get all necessary info #ifdef _WIN32 struct info get_info(struct configuration* config_flags) #else struct info get_info() #endif { struct info user_info = {0}; char buffer[256]; // line buffer // get terminal width used to truncate long names #ifndef _WIN32 ioctl(STDOUT_FILENO, TIOCGWINSZ, &user_info.win); user_info.target_width = user_info.win.ws_col - 30; #else // _WIN32 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); user_info.ws_col = csbi.srWindow.Right - csbi.srWindow.Left - 29; user_info.ws_rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; #endif // _WIN32 // os version, cpu and board info FILE* os_release = fopen("/etc/os-release", "r"); // os name file #ifndef __FREEBSD__ FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); // cpu name file for not-freebsd systems #else FILE* cpuinfo = popen("sysctl -a | egrep -i 'hw.model'", "r"); // cpu name command for freebsd #endif // trying to get some kind of information about the name of the computer (hopefully a product full name) FILE* model_fp /* = fopen("/sys/devices/virtual/dmi/id/product_version", "r") */; // trying to get product version // if (!model_fp) model_fp = fopen("/sys/devices/virtual/dmi/id/product_name", "r"); // trying to get product name // if (!model_fp) model_fp = fopen("/sys/devices/virtual/dmi/id/board_name", "r"); // trying to get motherboard name char model_filename[3][256] = {"/sys/devices/virtual/dmi/id/product_version", "/sys/devices/virtual/dmi/id/product_name", "/sys/devices/virtual/dmi/id/board_name"}; char tmp_model[3][256]; // temporary variable to store the contents of all 3 files int longest_model = 0, best_len = 0, currentlen = 0; for (int i = 0; i < 3; i++) { // read file model_fp = fopen(model_filename[i], "r"); if (model_fp) { fgets(tmp_model[i], 256, model_fp); tmp_model[i][strlen(tmp_model[i]) - 1] = '\0'; fclose(model_fp); } // choose the file with the longest name currentlen = strlen(tmp_model[i]); if (currentlen > best_len) { best_len = currentlen; longest_model = i; } } sprintf(user_info.model, "%s", tmp_model[longest_model]); // read model name #ifdef _WIN32 // all the previous files obviously did not exist on windows model_fp = popen("wmic computersystem get model", "r"); while (fgets(buffer, sizeof(buffer), model_fp)) { if (strstr(buffer, "Model") != 0) continue; else { sprintf(user_info.model, "%s", buffer); user_info.model[strlen(user_info.model) - 2] = '\0'; break; } } #elif defined(__FREEBSD__) || defined(__APPLE__) #if defined(__FREEBSD__) #define HOSTCTL "hw.hv_vendor" #elif defined(__APPLE__) #define HOSTCTL "hw.model" #endif model_fp = popen("sysctl -a " HOSTCTL, "r"); while (fgets(buffer, sizeof(buffer), model_fp)) if (sscanf(buffer, HOSTCTL ": %[^\n]", user_info.model)) break; #endif // _WIN32 if (os_release) { // get normal vars if os_release exists while (fgets(buffer, sizeof(buffer), os_release) && !(sscanf(buffer, "\nID=\"%s\"", user_info.os_name) || sscanf(buffer, "\nID=%s", user_info.os_name))) ; // sometimes for some reason sscanf reads the last '\"' too int os_name_len = strlen(user_info.os_name); if (user_info.os_name[os_name_len - 1] == '\"') { user_info.os_name[os_name_len - 1] = '\0'; } /* trying to detect amogos because in its os-release file ID value is just "debian", will be removed when amogos will have an os-release file with ID=amogos */ if (strcmp(user_info.os_name, "debian") == 0 || strcmp(user_info.os_name, "raspbian") == 0) { DIR* amogos_plymouth = opendir("/usr/share/plymouth/themes/amogos"); if (amogos_plymouth) { closedir(amogos_plymouth); sprintf(user_info.os_name, "amogos"); } } /* if (model_fp) { // what the fuck is this? I don't remember writing this code while (fgets(buffer, sizeof(buffer), model_fp) && !(sscanf(buffer, "%[^\n]", user_info.model))) ; char version[32]; while (fgets(buffer, sizeof(buffer), model_fp)) { if (sscanf(buffer, "%[^\n]", version)) { strcat(user_info.model, " "); strcat(user_info.model, version); break; } } } */ // getting cpu name while (fgets(buffer, sizeof(buffer), cpuinfo)) { #ifdef __FREEBSD__ if (sscanf(buffer, "hw.model: %[^\n]", user_info.cpu_model)) break; #else if (sscanf(buffer, "model name : %[^\n]", user_info.cpu_model)) break; #endif // __FREEBSD__ } // getting username char* tmp_user = getenv("USER"); if (tmp_user == NULL) sprintf(user_info.user, "%s", ""); else sprintf(user_info.user, "%s", tmp_user); fclose(os_release); } else { // try for android vars, next for Apple var, or unknown system // android DIR* system_app = opendir("/system/app/"); DIR* system_priv_app = opendir("/system/priv-app/"); DIR* library = opendir("/Library/"); if (system_app && system_priv_app) { closedir(system_app); closedir(system_priv_app); sprintf(user_info.os_name, "android"); // username FILE* whoami = popen("whoami", "r"); if (fscanf(whoami, "%s", user_info.user) == 3) sprintf(user_info.user, "unknown"); pclose(whoami); // model name model_fp = popen("getprop ro.product.model", "r"); while (fgets(buffer, sizeof(buffer), model_fp) && !sscanf(buffer, "%[^\n]", user_info.model)) ; #ifndef __FREEBSD__ while (fgets(buffer, sizeof(buffer), cpuinfo) && !sscanf(buffer, "Hardware : %[^\n]", user_info.cpu_model)) ; #endif } else if (library) { // Apple closedir(library); #ifdef __APPLE__ sysctlbyname("machdep.cpu.brand_string", &cpu_buffer, &cpu_buffer_len, NULL, 0); // cpu name #ifndef __IPHONE__ sprintf(user_info.os_name, "macos"); #else sprintf(user_info.os_name, "ios"); #endif sprintf(user_info.cpu_model, "%s", cpu_buffer); #endif } else sprintf(user_info.os_name, "unknown"); // if no option before is working, the system is unknown } #ifndef __FREEBSD__ fclose(cpuinfo); #endif #ifndef _WIN32 gethostname(user_info.host, 256); // hostname char* tmp_shell = getenv("SHELL"); // shell name if (tmp_shell == NULL) sprintf(user_info.shell, "%s", ""); else sprintf(user_info.shell, "%s", tmp_shell); if (strlen(user_info.shell) > 16) // android shell was too long, this works only for termux memmove(&user_info.shell, &user_info.shell[27], strlen(user_info.shell)); #else // if _WIN32 // cpu name cpuinfo = popen("wmic cpu get caption", "r"); while (fgets(buffer, sizeof(buffer), cpuinfo)) { if (strstr(buffer, "Caption") != 0) continue; else { sprintf(user_info.cpu_model, "%s", buffer); user_info.cpu_model[strlen(user_info.cpu_model) - 2] = '\0'; break; } } // username FILE* user_host_fp = popen("wmic computersystem get username", "r"); while (fgets(buffer, sizeof(buffer), user_host_fp)) { if (strstr(buffer, "UserName") != 0) continue; else { sscanf(buffer, "%[^\\]%s", user_info.host, user_info.user); memmove(user_info.user, user_info.user + 1, sizeof(user_info.user) - 1); break; } } // powershell version FILE* shell_fp = popen("powershell $PSVersionTable", "r"); sprintf(user_info.shell, "PowerShell "); char tmp_shell[64]; while (fgets(buffer, sizeof(buffer), shell_fp) && sscanf(buffer, "PSVersion %s", tmp_shell) == 0) ; strcat(user_info.shell, tmp_shell); #endif // _WIN32 truncate_str(user_info.cpu_model, user_info.target_width); // system resources #ifndef _WIN32 uname(&user_info.sys_var); #endif // _WIN32 #ifndef __APPLE__ #ifndef __FREEBSD__ #ifndef _WIN32 sysinfo(&user_info.sys); // somehow this function has to be called again in print_info() #else GetSystemInfo(&user_info.sys); #endif #endif #endif #ifndef _WIN32 truncate_str(user_info.sys_var.release, user_info.target_width); sprintf(user_info.kernel, "%s %s %s", user_info.sys_var.sysname, user_info.sys_var.release, user_info.sys_var.machine); // kernel name truncate_str(user_info.kernel, user_info.target_width); #else // _WIN32 // os name and windows version sprintf(user_info.os_name, "windows"); FILE* kernel_fp = popen("wmic computersystem get systemtype", "r"); while (fgets(buffer, sizeof(buffer), kernel_fp)) { if (strstr(buffer, "SystemType") != 0) continue; else { sprintf(user_info.kernel, "%s", buffer); user_info.kernel[strlen(user_info.kernel) - 2] = '\0'; break; } } if (kernel_fp) pclose(kernel_fp); #endif // _WIN32 // ram #ifndef __APPLE__ #ifdef _WIN32 FILE* mem_used_fp = popen("wmic os get freevirtualmemory", "r"); // free memory FILE* mem_total_fp = popen("wmic os get totalvirtualmemorysize", "r"); // total memory char mem_used_ch[2137] = {0}, mem_total_ch[2137] = {0}; while (fgets(mem_total_ch, sizeof(mem_total_ch), mem_total_fp) != NULL) { if (strstr(mem_total_ch, "TotalVirtualMemorySize") != 0) continue; else if (strstr(mem_total_ch, " ") == 0) continue; else user_info.ram_total = atoi(mem_total_ch) / 1024; } while (fgets(mem_used_ch, sizeof(mem_used_ch), mem_used_fp) != NULL) { if (strstr(mem_used_ch, "FreeVirtualMemory") != 0) continue; else if (strstr(mem_used_ch, " ") == 0) continue; else user_info.ram_used = user_info.ram_total - (atoi(mem_used_ch) / 1024); } pclose(mem_used_fp); pclose(mem_total_fp); #else // if not _WIN32 FILE* meminfo; #ifdef __FREEBSD__ meminfo = popen("LANG=EN_us freecolor -om 2> /dev/null", "r"); // free alternative for freebsd #else // getting memory info from /proc/meminfo: https://github.com/KittyKatt/screenFetch/issues/386#issuecomment-249312716 meminfo = fopen("/proc/meminfo", "r"); // popen("LANG=EN_us free -m 2> /dev/null", "r"); // get ram info with free #endif // brackets are here to restrict the access to this int variables, which are temporary { int memtotal = 0, shmem = 0, memfree = 0, buffers = 0, cached = 0, sreclaimable = 0; while (fgets(buffer, sizeof(buffer), meminfo)) { sscanf(buffer, "MemTotal: %d", &memtotal); sscanf(buffer, "Shmem: %d", &shmem); sscanf(buffer, "MemFree: %d", &memfree); sscanf(buffer, "Buffers: %d", &buffers); sscanf(buffer, "Cached: %d", &cached); sscanf(buffer, "SReclaimable: %d", &sreclaimable); } user_info.ram_total = memtotal / 1024; user_info.ram_used = ((memtotal + shmem) - (memfree + buffers + cached + sreclaimable)) / 1024; } // while (fgets(buffer, sizeof(buffer), meminfo)) // old way to get ram usage that uses the "free" command // // free command prints like this: "Mem:" total used free shared buff/cache available // sscanf(buffer, "Mem: %d %d", &user_info.ram_total, &user_info.ram_used); fclose(meminfo); #endif #else // if __APPLE__ // Used FILE *mem_wired_fp, *mem_active_fp, *mem_compressed_fp; mem_wired_fp = popen("vm_stat | awk '/wired/ { printf $4 }' | cut -d '.' -f 1", "r"); mem_active_fp = popen("vm_stat | awk '/active/ { printf $3 }' | cut -d '.' -f 1", "r"); mem_compressed_fp = popen("vm_stat | awk '/occupied/ { printf $5 }' | cut -d '.' -f 1", "r"); char mem_wired_ch[2137], mem_active_ch[2137], mem_compressed_ch[2137]; while (fgets(mem_wired_ch, sizeof(mem_wired_ch), mem_wired_fp) != NULL) while (fgets(mem_active_ch, sizeof(mem_active_ch), mem_active_fp) != NULL) while (fgets(mem_compressed_ch, sizeof(mem_compressed_ch), mem_compressed_fp) != NULL) ; pclose(mem_wired_fp); pclose(mem_active_fp); pclose(mem_compressed_fp); int mem_wired = atoi(mem_wired_ch); int mem_active = atoi(mem_active_ch); int mem_compressed = atoi(mem_compressed_ch); // Total sysctlbyname("hw.memsize", &mem_buffer, &mem_buffer_len, NULL, 0); user_info.ram_used = ((mem_wired + mem_active + mem_compressed) * 4 / 1024); user_info.ram_total = mem_buffer / 1024 / 1024; #endif // gpus int gpuc = 0; // gpu counter #ifndef _WIN32 setenv("LANG", "en_US", 1); // force language to english #endif FILE* gpu; #ifndef _WIN32 gpu = popen("lshw -class display 2> /dev/null", "r"); // add all gpus to the array gpu_model while (fgets(buffer, sizeof(buffer), gpu)) if (sscanf(buffer, " product: %[^\n]", user_info.gpu_model[gpuc])) gpuc++; #endif if (strlen(user_info.gpu_model[0]) < 2) { // get gpus with lspci command if (strcmp(user_info.os_name, "android") != 0) { #ifndef __APPLE__ #ifdef _WIN32 gpu = popen("wmic PATH Win32_VideoController GET Name", "r"); #else gpu = popen("lspci -mm 2> /dev/null | grep \"VGA\" | awk -F '\"' '{print $4 $5 $6}'", "r"); #endif #else gpu = popen("system_profiler SPDisplaysDataType | awk -F ': ' '/Chipset Model: /{ print $2 }'", "r"); #endif } else gpu = popen("getprop ro.hardware.vulkan 2> /dev/null", "r"); // for android } // get all the gpus while (fgets(buffer, sizeof(buffer), gpu)) { // windows if (strstr(buffer, "Name") || (strlen(buffer) == 2)) continue; else if (sscanf(buffer, "%[^\n]", user_info.gpu_model[gpuc])) gpuc++; } fclose(gpu); // format gpu names for (int i = 0; i < gpuc; i++) { remove_brackets(user_info.gpu_model[i]); truncate_str(user_info.gpu_model[i], user_info.target_width); } // Resolution #ifndef _WIN32 FILE* resolution = popen("xwininfo -root 2> /dev/null | grep -E 'Width|Height'", "r"); while (fgets(buffer, sizeof(buffer), resolution)) { sscanf(buffer, " Width: %d", &user_info.screen_width); sscanf(buffer, " Height: %d", &user_info.screen_height); } #endif if (strcmp(user_info.os_name, "windows")) MOVE_CURSOR = "\033[21C"; // to print windows logo on not windows systems // package count #ifdef _WIN32 user_info.pkgs = pkgman(&user_info, config_flags); #else // _WIN32 user_info.pkgs = pkgman(&user_info); #endif // _WIN32 // uwufy info uwu_kernel(user_info.kernel); for (int i = 0; user_info.gpu_model[i][0]; i++) uwu_hw(user_info.gpu_model[i]); uwu_hw(user_info.cpu_model); uwu_hw(user_info.model); return user_info; } /* prints distribution list distributions are listed by distribution branch to make the output easier to understand by the user.*/ void list(char* arg) { printf("%s -d \n" " Available distributions:\n" " %sArch linux %sbased:\n" " %sarch, arcolinux, %sartix, endeavouros %smanjaro, " "manjaro-arm, %sxerolinux\n\n" " %sDebian/%sUbuntu %sbased:\n" " %samogos, debian, %slinuxmint, neon %spop, %sraspbian " "%subuntu\n\n" " %sBSD %sbased:\n" " %sfreebsd, %sopenbsd, %sm%sa%sc%so%ss, %sios\n\n" " %sOther/spare distributions:\n" " %salpine, %sfedora, %sgentoo, %sslackware, %ssolus, %svoid, " "opensuse-leap, android, %sgnu, guix, %swindows, %sunknown\n\n", arg, BLUE, NORMAL, BLUE, MAGENTA, GREEN, BLUE, // Arch based colors RED, YELLOW, NORMAL, RED, GREEN, BLUE, RED, YELLOW, // Debian based colors RED, NORMAL, RED, YELLOW, GREEN, YELLOW, RED, PINK, BLUE, WHITE, // BSD/Apple colors NORMAL, BLUE, BLUE, PINK, MAGENTA, WHITE, GREEN, YELLOW, BLUE, WHITE); // Other/spare distributions colors } // prints the usage void usage(char* arg) { printf("Usage: %s \n" " -a, --ascii prints logo as ascii text (default)\n" " -c --config use custom config path\n" " -d, --distro lets you choose the logo to print\n" " -h, --help prints this help page\n" #ifndef __IPHONE__ " -i, --image prints logo as image and use a custom image if provided\n" " %sworks in most terminals\n" #else " -i, --image prints logo as image and use a custom image if provided\n" " %sdisabled under iOS\n" #endif " read README.md for more info%s\n" " -l, --list lists all supported distributions\n" " -v, --version prints the current uwufetch version\n" " -w, --write-cache writes to the cache file (~/.cache/uwufetch.cache)\n" " using the cache set $UWUFETCH_CACHE_ENABLED to TRUE, true or 1\n", arg, #ifndef __IPHONE__ BLUE, #else RED, #endif NORMAL); } // the main function is on the bottom of the file to avoid double function declarations int main(int argc, char* argv[]) { char* cache_env = getenv("UWUFETCH_CACHE_ENABLED"); // getting cache env variable struct configuration config_flags; struct info user_info = {0}; if (cache_env != NULL) { // if cache env variable is set, read itz value int cache_enabled = 0; char buffer[128]; sscanf(cache_env, "%4[TRUEtrue1]", buffer); cache_enabled = (strcmp(buffer, "true") == 0 || strcmp(buffer, "TRUE") == 0 || strcmp(buffer, "1") == 0); // enable the cache if necessary if (cache_enabled) { // if no cache file found write to it if (!read_cache(&user_info)) { #ifdef _WIN32 user_info = get_info(&config_flags); #else user_info = get_info(); #endif write_cache(&user_info); } config_flags = parse_config(&user_info); // reading the config if (print_cache(&config_flags, &user_info) < 7) printf("\033[3B"); return 0; } } #ifdef _WIN32 // packages disabled by default because chocolatey is too slow config_flags.show_pkgs = 0; #endif int opt = 0; static struct option long_options[] = {{"ascii", no_argument, NULL, 'a'}, {"config", required_argument, NULL, 'c'}, // {"cache", no_argument, NULL, 'C'}, // using an environment variable is not a good idea, maybe some time in the future, uwufetch will use a command line option {"distro", required_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"image", optional_argument, NULL, 'i'}, {"list", no_argument, NULL, 'l'}, {"version", no_argument, NULL, 'v'}, {"write-cache", no_argument, NULL, 'w'}, {NULL, 0, NULL, 0}}; #ifdef _WIN32 user_info = get_info(&config_flags); // get the info to modify it with cmdline options #else user_info = get_info(); #endif config_flags = parse_config(&user_info); // same as user_info // reading cmdline options while ((opt = getopt_long(argc, argv, "ac:d:hi::lvw", long_options, NULL)) != -1) { switch (opt) { case 'a': // set ascii logo as output config_flags.ascii_image_flag = 0; break; case 'c': // set the config directory user_info.config_directory = optarg; break; case 'd': // set the distribution name if (optarg) sprintf(user_info.os_name, "%s", optarg); break; case 'h': usage(argv[0]); return 0; case 'i': // set ascii logo as output config_flags.ascii_image_flag = 1; if (!optarg && argv[optind] != NULL && argv[optind][0] != '-') // set default image name sprintf(user_info.image_name, "%s", argv[optind++]); else if (optarg) // set user-defined image name sprintf(user_info.image_name, "%s", optarg); break; case 'l': list(argv[0]); return 0; case 'v': printf("UwUfetch version %s\n", UWUFETCH_VERSION); return 0; case 'w': write_cache(&user_info); if (print_cache(&config_flags, &user_info) < 7) printf("\033[3B"); return 0; default: break; } } if ((argc == 1 && config_flags.ascii_image_flag == 0) || (argc > 1 && config_flags.ascii_image_flag == 0)) print_ascii(&user_info); else if (config_flags.ascii_image_flag == 1) print_image(&user_info); // if the number of printed lines is too small, move the cursor down if (print_info(&config_flags, &user_info) < 7) printf("\033[3B"); return 0; }