// Copyright (c) 2023-2026 Chris (boreddevnl) // This software is released under the GNU General Public License v3.0. See LICENSE file for details. // This header needs to maintain in any file it is present in, as per the GPL license terms. #include #include #include #define MAX_ASCII_LINES 32 #define MAX_ASCII_WIDTH 80 #define MAX_INFO_LINES 15 static char* strncpy(char *dest, const char *src, size_t n) { size_t i; for (i = 0; i < n && src[i] != '\0'; i++) dest[i] = src[i]; for ( ; i < n; i++) dest[i] = '\0'; return dest; } typedef struct { char ascii_art_file[256]; char user_host_string[64]; char separator[64]; char os_label[32]; char kernel_label[32]; char uptime_label[32]; char shell_label[32]; char memory_label[32]; char cpu_label[32]; char date_label[32]; } SysfetchConfig; static SysfetchConfig config; static char ascii_lines[MAX_ASCII_LINES][MAX_ASCII_WIDTH]; static int ascii_line_count = 0; static uint32_t ansi_to_boredos_color(int code) { uint32_t default_color = sys_get_shell_config("default_text_color"); if (default_color == 0) default_color = 0xFFCCCCCC; switch (code) { case 0: return default_color; case 30: return 0xFF000000; // Black case 31: return 0xFFFF4444; // Red case 32: return 0xFF6A9955; // Green case 33: return 0xFFFFFF00; // Yellow case 34: return 0xFF569CD6; // Blue case 35: return 0xFFB589D6; // Magenta case 36: return 0xFF4EC9B0; // Cyan case 37: return 0xFFCCCCCC; // White case 90: return 0xFF808080; // Bright Black (Gray) case 91: return 0xFFFF6B6B; // Bright Red case 92: return 0xFF78DE78; // Bright Green case 93: return 0xFFFFFF55; // Bright Yellow case 94: return 0xFF87CEEB; // Bright Blue case 95: return 0xFFFF77FF; // Bright Magenta case 96: return 0xFF66D9EF; // Bright Cyan case 97: return 0xFFFFFFFF; // Bright White case 38: return 0xFF473ba3; // Bored Blue default: return default_color; } } static void printf_ansi(const char *str) { uint32_t original_color = sys_get_shell_config("default_text_color"); if (original_color == 0) original_color = 0xFFCCCCCC; while (*str) { bool is_escape = false; if (*str == '\033' && *(str + 1) == '[') { str += 2; is_escape = true; } else if (*str == '\\' && *(str + 1) == '0' && *(str + 2) == '3' && *(str + 3) == '3' && *(str + 4) == '[') { str += 5; is_escape = true; } if (is_escape) { int code = 0; while (*str >= '0' && *str <= '9') { code = code * 10 + (*str - '0'); str++; } if (*str == 'm') { sys_set_text_color(ansi_to_boredos_color(code)); str++; } } else { char c[2] = {*str, 0}; sys_write(1, c, 1); str++; } } sys_set_text_color(original_color); } static int strlen_ansi(const char *str) { int len = 0; while (*str) { if (*str == '\033' && *(str + 1) == '[') { str += 2; while (*str && *str != 'm') str++; if (*str == 'm') str++; } else if (*str == '\\' && *(str + 1) == '0' && *(str + 2) == '3' && *(str + 3) == '3' && *(str + 4) == '[') { str += 5; while (*str && *str != 'm') str++; if (*str == 'm') str++; } else { len++; str++; } } return len; } static char* trim(char *str) { char *end; while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r') str++; if (*str == 0) return str; end = str + strlen(str) - 1; while (end > str && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) end--; *(end + 1) = 0; return str; } static void set_config_defaults() { strcpy(config.ascii_art_file, "/Library/art/boredos.txt"); strcpy(config.user_host_string, "root@boredos"); strcpy(config.separator, "------------"); strcpy(config.os_label, "OS"); strcpy(config.kernel_label, "Kernel"); strcpy(config.uptime_label, "Uptime"); strcpy(config.shell_label, "Shell"); strcpy(config.memory_label, "Memory"); strcpy(config.cpu_label, "CPU"); strcpy(config.date_label, "Date"); } static void parse_config(char* buffer) { char *line = buffer; while (*line) { char *next_line = strchr(line, '\n'); if (next_line) *next_line = 0; if (line[0] != '/' && line[0] != '\0') { char *key = line; char *val = strchr(line, '='); if (val) { *val = 0; val++; key = trim(key); val = trim(val); if (strcmp(key, "ascii_art_file") == 0) strcpy(config.ascii_art_file, val); else if (strcmp(key, "user_host_string") == 0) strcpy(config.user_host_string, val); else if (strcmp(key, "separator") == 0) strcpy(config.separator, val); else if (strcmp(key, "os_label") == 0) strcpy(config.os_label, val); else if (strcmp(key, "kernel_label") == 0) strcpy(config.kernel_label, val); else if (strcmp(key, "uptime_label") == 0) strcpy(config.uptime_label, val); else if (strcmp(key, "shell_label") == 0) strcpy(config.shell_label, val); else if (strcmp(key, "memory_label") == 0) strcpy(config.memory_label, val); else if (strcmp(key, "cpu_label") == 0) strcpy(config.cpu_label, val); else if (strcmp(key, "date_label") == 0) strcpy(config.date_label, val); } } if (next_line) line = next_line + 1; else break; } } static void load_config() { set_config_defaults(); int fd = sys_open("/Library/conf/sysfetch.cfg", "r"); if (fd < 0) return; char *buffer = malloc(4096); if (!buffer) { sys_close(fd); return; } int bytes = sys_read(fd, buffer, 4095); sys_close(fd); if (bytes > 0) { buffer[bytes] = 0; parse_config(buffer); } free(buffer); } static void load_ascii_art() { int fd = sys_open(config.ascii_art_file, "r"); if (fd < 0) { strcpy(ascii_lines[0], "\033[38m @@@@\033[0m"); strcpy(ascii_lines[1], "\033[38m @@@@@@@\033[0m"); strcpy(ascii_lines[2], "\033[38m @@@@@@\033[0m"); strcpy(ascii_lines[3], "\033[38m @@@@@@@\033[0m"); strcpy(ascii_lines[4], "\033[38m @@@@@@@ @@@@@@\033[0m"); strcpy(ascii_lines[5], "\033[38m @@@@@@ @@@@@@@@@@@@\033[0m"); strcpy(ascii_lines[6], "\033[38m @@@@@@ @@@@@@@@@@@@@@a\033[0m"); strcpy(ascii_lines[7], "\033[38m @@@@@@@@@@@X @@@@@@@@w\033[0m"); strcpy(ascii_lines[8], "\033[38m @@@@@@@@ @@@@@@@\033[0m"); strcpy(ascii_lines[9], "\033[38m @@@@@@M @@@@@@\033[0m"); strcpy(ascii_lines[10], "\033[38m @@@@@@@ @@@@@@\033[0m"); strcpy(ascii_lines[11], "\033[38m @@@@@@@ @@@@@@@@\033[0m"); strcpy(ascii_lines[12], "\033[38m @@@@@@@@@@@@@@@@@@\033[0m"); strcpy(ascii_lines[13], "\033[38m i@@@@@@@@@@@@@@@\033[0m"); strcpy(ascii_lines[14], "\033[38m @@@@@@@\033[0m"); strcpy(ascii_lines[15], "\033[38m @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\033[0m"); strcpy(ascii_lines[16], "\033[38m @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\033[0m"); strcpy(ascii_lines[17], "\033[38m @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\033[0m"); ascii_line_count = 18; return; } char *buffer = malloc(4096); if (!buffer) { sys_close(fd); return; } int bytes = sys_read(fd, buffer, 4095); sys_close(fd); if (bytes > 0) { buffer[bytes] = 0; char *line = buffer; while (*line && ascii_line_count < MAX_ASCII_LINES) { char *next_line = strchr(line, '\n'); if (next_line) *next_line = 0; strncpy(ascii_lines[ascii_line_count], line, MAX_ASCII_WIDTH - 1); ascii_lines[ascii_line_count][MAX_ASCII_WIDTH - 1] = 0; ascii_line_count++; if (next_line) line = next_line + 1; else break; } } free(buffer); } int main(int argc, char **argv) { (void)argc; (void)argv; load_config(); load_ascii_art(); char info_lines[MAX_INFO_LINES][128]; char temp_buf[32]; int info_line_count = 0; if (config.user_host_string[0]) { strcpy(info_lines[info_line_count++], config.user_host_string); } if (config.separator[0]) { strcpy(info_lines[info_line_count++], config.separator); } // Helper for proc parsing auto int find_v(const char *b, const char *k) { char *p = (char*)b; int kl = strlen(k); while (*p) { if (memcmp(p, k, kl) == 0 && (p[kl] == ':' || p[kl] == '\t')) { p += kl; while (*p == ':' || *p == '\t' || *p == ' ') p++; return atoi(p); } while (*p && *p != '\n') p++; if (*p == '\n') p++; } return 0; } auto void find_s(const char *b, const char *k, char *out) { char *p = (char*)b; int kl = strlen(k); while (*p) { if (memcmp(p, k, kl) == 0 && (p[kl] == ':' || p[kl] == '\t')) { p += kl; while (*p == ':' || *p == '\t' || *p == ' ') p++; int i = 0; while (*p && *p != '\n' && i < 127) out[i++] = *p++; out[i] = 0; return; } while (*p && *p != '\n') p++; if (*p == '\n') p++; } strcpy(out, "Unknown"); } int fd_v = sys_open("/proc/version", "r"); char v_buf[512]; if (fd_v >= 0) { int b = sys_read(fd_v, v_buf, 511); v_buf[b] = 0; sys_close(fd_v); } else strcpy(v_buf, "Unknown"); if (config.os_label[0]) { strcpy(info_lines[info_line_count], config.os_label); strcat(info_lines[info_line_count], ": "); // Parse "BoredOS [codename] Version X.Y.Z" strcat(info_lines[info_line_count], v_buf); // Truncate at newline char *nl = strchr(info_lines[info_line_count], '\n'); if (nl) *nl = 0; info_line_count++; } if (config.kernel_label[0]) { strcpy(info_lines[info_line_count], config.kernel_label); strcat(info_lines[info_line_count], ": "); char *kstart = strchr(v_buf, '\n'); if (kstart) { strcat(info_lines[info_line_count], kstart + 1); char *knext = strchr(info_lines[info_line_count], '\n'); if (knext) *knext = 0; } else strcat(info_lines[info_line_count], "Unknown"); info_line_count++; } if (config.uptime_label[0]) { int fd_u = sys_open("/proc/uptime", "r"); if (fd_u >= 0) { char u_buf[64]; int b = sys_read(fd_u, u_buf, 63); u_buf[b] = 0; sys_close(fd_u); int sec = atoi(u_buf); int mins = sec / 60; strcpy(info_lines[info_line_count], config.uptime_label); strcat(info_lines[info_line_count], ": "); itoa(mins, temp_buf); strcat(info_lines[info_line_count], temp_buf); strcat(info_lines[info_line_count++], " mins"); } } if (config.cpu_label[0]) { int fd_c = sys_open("/proc/cpuinfo", "r"); if (fd_c >= 0) { char c_buf[2048]; int b = sys_read(fd_c, c_buf, 2047); c_buf[b] = 0; sys_close(fd_c); char model[128]; find_s(c_buf, "model name", model); int cores = find_v(c_buf, "cpu cores"); strcpy(info_lines[info_line_count], config.cpu_label); strcat(info_lines[info_line_count], ": "); strcat(info_lines[info_line_count], model); if (cores > 0) { strcat(info_lines[info_line_count], " ("); itoa(cores, temp_buf); strcat(info_lines[info_line_count], temp_buf); strcat(info_lines[info_line_count], ")"); } info_line_count++; } } if (config.shell_label[0]) { strcpy(info_lines[info_line_count], config.shell_label); strcat(info_lines[info_line_count++], ": bsh"); } if (config.memory_label[0]) { int fd_m = sys_open("/proc/meminfo", "r"); if (fd_m >= 0) { char m_buf[512]; int b = sys_read(fd_m, m_buf, 511); m_buf[b] = 0; sys_close(fd_m); int total = find_v(m_buf, "MemTotal"); int used = find_v(m_buf, "MemUsed"); strcpy(info_lines[info_line_count], config.memory_label); strcat(info_lines[info_line_count], ": "); itoa(used / 1024, temp_buf); strcat(info_lines[info_line_count], temp_buf); strcat(info_lines[info_line_count], "MiB / "); itoa(total / 1024, temp_buf); strcat(info_lines[info_line_count], temp_buf); strcat(info_lines[info_line_count++], "MiB"); } } if (config.date_label[0]) { int fd_d = sys_open("/proc/datetime", "r"); if (fd_d >= 0) { char d_buf[64]; int b = sys_read(fd_d, d_buf, 63); d_buf[b] = 0; sys_close(fd_d); strcpy(info_lines[info_line_count], config.date_label); strcat(info_lines[info_line_count], ": "); strcat(info_lines[info_line_count], d_buf); char *nl = strchr(info_lines[info_line_count], '\n'); if (nl) *nl = 0; info_line_count++; } } int max_lines = (ascii_line_count > info_line_count) ? ascii_line_count : info_line_count; int ascii_width = 0; for (int i = 0; i < ascii_line_count; i++) { int len = strlen_ansi(ascii_lines[i]); if (len > ascii_width) ascii_width = len; } for (int i = 0; i < max_lines; i++) { if (i < ascii_line_count) { printf_ansi(ascii_lines[i]); int padding = ascii_width - strlen_ansi(ascii_lines[i]); for(int j=0; j