Compare commits

..

1 Commits

Author SHA1 Message Date
marco 54fbac7e59 Updated documentation
build / clang-build (push) Successful in 18s
2026-04-07 16:12:52 +02:00
5 changed files with 72 additions and 307 deletions
-2
View File
@@ -6,7 +6,6 @@
*.ko *.ko
*.obj *.obj
*.elf *.elf
zfetch
# Linker output # Linker output
*.ilk *.ilk
@@ -54,4 +53,3 @@ dkms.conf
# debug information files # debug information files
*.dwo *.dwo
.vscode/
+31 -46
View File
@@ -27,8 +27,8 @@ In both cases, you will get a binary file named `zfetch` that you can move where
want. want.
## Usage ## Usage
In its simplest form, you can just invoke the program without any additional parameter and it will In its most basic form, you can just invoke the program without any additional parameter and it will
run with all options enabled, that is: run with all option enabled, that is:
![](imgs/ex1.png) ![](imgs/ex1.png)
@@ -38,23 +38,18 @@ you can do so by creating a configuration file in one of the following paths:
- `$HOME/.zfetch.conf`; - `$HOME/.zfetch.conf`;
- `$HOME/.config/zfetch/conf` (**this takes precedence**). - `$HOME/.config/zfetch/conf` (**this takes precedence**).
Inside it, you can specify which options to enable and which one to disable: Inside it, you can specify which option to enable and which one to disable:
```conf ```conf
HOST = 1 HOST = 1
OS = 0 OS = 0
UPTIME = 1 UPTIME = 1
CPU = 1 CPU = 1
MEMORY = 1 MEMORY = 1
DISK = 1 DISK = 1
IP = 1 IP = 1
LOGO = 1 LOGO = 1
BARS = 0 BARS = 0
SHELL = 1
TERMINAL = 0
DESKTOP = 1
INIT = 1
BATTERY = 1
``` ```
Any other line will be considered invalid and silently skipped by the builtin parser. Any other line will be considered invalid and silently skipped by the builtin parser.
@@ -62,20 +57,15 @@ To retrieve which options are currently enabled, you can run the program with th
```sh ```sh
$ ./zfetch --list-opts # or -s $ ./zfetch --list-opts # or -s
HOST : ON HOST : ON
OS : OFF OS : OFF
UPTIME : ON UPTIME : ON
CPU : ON CPU : ON
MEMORY : ON MEMORY : ON
DISK : ON DISK : ON
IP : ON IP : ON
LOGO : ON LOGO : ON
BARS : OFF BARS : OFF
SHELL : ON
TERMINAL : OFF
DESKTOP : ON
INIT : ON
BATTERY : ON
``` ```
You can also dynamically specify a different path by using the `-c` CLI argument: You can also dynamically specify a different path by using the `-c` CLI argument:
@@ -83,20 +73,15 @@ You can also dynamically specify a different path by using the `-c` CLI argument
```sh ```sh
$ ./zfetch -c $PWD/config -s $ ./zfetch -c $PWD/config -s
Using custom config file: '/home/marco/Projects/zfetch/config' Using custom config file: '/home/marco/Projects/zfetch/config'
HOST : ON HOST : OFF
OS : OFF OS : OFF
UPTIME : OFF UPTIME : OFF
CPU : OFF CPU : OFF
MEMORY : ON MEMORY : ON
DISK : ON DISK : ON
IP : ON IP : ON
LOGO : ON LOGO : OFF
BARS : OFF BARS : ON
SHELL : ON
TERMINAL : OFF
DESKTOP : ON
INIT : ON
BATTERY : ON
``` ```
Finally, you can list all supported distribution, using the `--list-logos/-a` flag: Finally, you can list all supported distribution, using the `--list-logos/-a` flag:
@@ -107,7 +92,7 @@ Available logos: alpine, arch, debian, fedora, mint, gentoo, artix, linux, nixos
``` ```
## License & acknowledgement ## License & acknowledge
This tool is distributed under the [MIT license](https://choosealicense.com/licenses/mit/), the logos were taken from This tool is distributed under the [MIT license](https://choosealicense.com/licenses/mit/), the logos were taken from
[pfetch](https://github.com/dylanaraps/pfetch), [neofetch](https://github.com/dylanaraps/neofetch) [pfetch](https://github.com/dylanaraps/pfetch), [neofetch](https://github.com/dylanaraps/neofetch)
and [fastfetch](https://github.com/fastfetch-cli/fastfetch). and [fastfetch](https://github.com/fastfetch-cli/fastfetch).
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 126 KiB

+39 -257
View File
@@ -33,7 +33,6 @@
#include <unistd.h> #include <unistd.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/stat.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
@@ -42,7 +41,6 @@
#include <getopt.h> #include <getopt.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <dirent.h>
#define Z_PATH_MAX 4096 #define Z_PATH_MAX 4096
#define IFACE_ENTRY_LEN 64 #define IFACE_ENTRY_LEN 64
@@ -87,11 +85,6 @@
#define OPT_IP 1U << 6 #define OPT_IP 1U << 6
#define OPT_LOGO 1U << 7 #define OPT_LOGO 1U << 7
#define OPT_BARS 1U << 8 #define OPT_BARS 1U << 8
#define OPT_SHELL 1U << 9
#define OPT_TERMINAL 1U << 0xA
#define OPT_DESKTOP 1U << 0xB
#define OPT_INIT 1U << 0xC
#define OPT_BATTERY 1U << 0xD
#define ARR_LEN(X) (sizeof(X) / sizeof(X[0])) #define ARR_LEN(X) (sizeof(X) / sizeof(X[0]))
#define STRCMP(X, Y) (strcmp(X, Y) == 0) #define STRCMP(X, Y) (strcmp(X, Y) == 0)
@@ -311,10 +304,9 @@ static void strip_quotes(char *str) {
} }
} }
static inline uint16_t default_opts(void) { static uint16_t default_opts(void) {
return OPT_HOST | OPT_OS | OPT_UPTIME | OPT_CPU | return OPT_HOST | OPT_OS | OPT_UPTIME | OPT_CPU |
OPT_MEMORY | OPT_DISK | OPT_IP | OPT_LOGO | OPT_BARS | OPT_MEMORY | OPT_DISK | OPT_IP | OPT_LOGO | OPT_BARS;
OPT_SHELL | OPT_TERMINAL | OPT_DESKTOP | OPT_INIT | OPT_BATTERY;
} }
static void set_option(uint16_t *options, const char *opt, int value) { static void set_option(uint16_t *options, const char *opt, int value) {
@@ -329,11 +321,6 @@ static void set_option(uint16_t *options, const char *opt, int value) {
else if (STRCMP(opt, "IP")) { flag = OPT_IP; } else if (STRCMP(opt, "IP")) { flag = OPT_IP; }
else if (STRCMP(opt, "LOGO")) { flag = OPT_LOGO; } else if (STRCMP(opt, "LOGO")) { flag = OPT_LOGO; }
else if (STRCMP(opt, "BARS")) { flag = OPT_BARS; } else if (STRCMP(opt, "BARS")) { flag = OPT_BARS; }
else if (STRCMP(opt, "SHELL")) { flag = OPT_SHELL; }
else if (STRCMP(opt, "TERMINAL")) { flag = OPT_TERMINAL; }
else if (STRCMP(opt, "DESKTOP")) { flag = OPT_DESKTOP; }
else if (STRCMP(opt, "INIT")) { flag = OPT_INIT; }
else if (STRCMP(opt, "BATTERY")) { flag = OPT_BATTERY; }
if (flag == 0) { return; } if (flag == 0) { return; }
@@ -476,21 +463,14 @@ static const char **get_logo(const char *id) {
return logo_linux; return logo_linux;
} }
static inline const char *get_percentage_color(double percent) { static const char *get_percentage_color(double percent) {
if (percent >= 85.0) { return C1; } // Red if (percent >= 85.0) { return C1; } // Red
else if (percent >= 60.0) { return C3; } // Yellow/orange else if (percent >= 60.0) { return C3; } // Yellow/orange
return C2; // Green return C2; // Green
} }
static inline const char *get_battery_color(int percent) { static const char *get_logo_accent(const char **logo) {
if (percent >= 90) { return C2; } // Green
else if (percent >= 50) { return C3; } // Yellow/Orange
return C1; // Red
}
static inline const char *get_logo_accent(const char **logo) {
if (logo == logo_arch || logo == logo_artix) { if (logo == logo_arch || logo == logo_artix) {
return C6; // Cyan return C6; // Cyan
} else if (logo == logo_debian || logo == logo_redhat) { } else if (logo == logo_debian || logo == logo_redhat) {
@@ -568,35 +548,6 @@ static void fmt_size(uint64_t used_kib, uint64_t total_kib, char *buf, size_t bu
used, unit, total, unit, get_percentage_color(percent), percent, RESET); used, unit, total, unit, get_percentage_color(percent), percent, RESET);
} }
static size_t fmt_uptime(char *buf, size_t buf_size, size_t offset, uint64_t value, const char *unit) {
if (value == 0) {
return offset;
}
const char *sep = (offset == 0) ? "" : ", ";
if (offset >= buf_size) {
return offset;
}
int n = snprintf(buf + offset, buf_size - offset,
"%s%" PRIu64 " %s%s",
sep, value, unit,
value == 1 ? "" : "s");
if (n < 0) {
return offset;
}
const size_t written = (size_t)n;
if (written >= buf_size - offset) {
return buf_size;
}
return offset + written;
}
// Retrieve the first line of a file // Retrieve the first line of a file
static bool get_head(const char *path, const char *prefix, char *buf, size_t buf_size) { static bool get_head(const char *path, const char *prefix, char *buf, size_t buf_size) {
FILE *fp = fopen(path, "r"); FILE *fp = fopen(path, "r");
@@ -627,6 +578,35 @@ static inline void str_to_lower(char *str) {
} }
} }
static inline size_t fmt_uptime(char *buf, size_t buf_size, size_t offset, uint64_t value, const char *unit) {
if (value == 0) {
return offset;
}
const char *sep = (offset == 0) ? "" : ", ";
if (offset >= buf_size) {
return offset;
}
int n = snprintf(buf + offset, buf_size - offset,
"%s%" PRIu64 " %s%s",
sep, value, unit,
value == 1 ? "" : "s");
if (n < 0) {
return offset;
}
const size_t written = (size_t)n;
if (written >= buf_size - offset) {
return buf_size;
}
return offset + written;
}
/* /*
* Features * Features
*/ */
@@ -702,6 +682,7 @@ static void get_ram(char *buf, size_t buf_size) {
char key[64]; char key[64];
unsigned long long value; unsigned long long value;
unsigned long long total = 0, available = 0; unsigned long long total = 0, available = 0;
bool mem_available = false;
if (fp == NULL) { if (fp == NULL) {
snprintf(buf, buf_size, "unknown"); snprintf(buf, buf_size, "unknown");
@@ -718,6 +699,7 @@ static void get_ram(char *buf, size_t buf_size) {
total = value; total = value;
} else if (STRCMP(key, "MemAvailable:")) { } else if (STRCMP(key, "MemAvailable:")) {
available = value; available = value;
mem_available = true;
} }
} }
@@ -725,12 +707,12 @@ static void get_ram(char *buf, size_t buf_size) {
int ch; int ch;
while ((ch = fgetc(fp)) != '\n' && ch != EOF) { } while ((ch = fgetc(fp)) != '\n' && ch != EOF) { }
if (total != 0 && available != 0) { break; } if (total != 0 && mem_available) { break; }
} }
fclose(fp); fclose(fp);
if (total == 0 || available == 0) { if (total == 0 || !mem_available) {
snprintf(buf, buf_size, "unknown"); snprintf(buf, buf_size, "unknown");
return; return;
} }
@@ -754,171 +736,6 @@ static void get_disk(char *buf, size_t buf_size) {
fmt_size(used_kib, total_kib, buf, buf_size); fmt_size(used_kib, total_kib, buf, buf_size);
} }
static void get_shell(char *buf, size_t buf_size) {
const char *shell = getenv("SHELL");
const char *base;
if (shell == NULL || *shell == '\0') {
snprintf(buf, buf_size, "unknown");
return;
}
// Find last slash (if available) and return
// the right part only (the name)
base = strrchr(shell, '/');
snprintf(buf, buf_size, "%s", base != NULL ? base + 1 : shell);
}
static void get_terminal(char *buf, size_t buf_size) {
const char *term_program = getenv("TERM_PROGRAM");
const char *term = getenv("TERM");
if (term_program != NULL && *term_program != '\0') {
snprintf(buf, buf_size, "%s", term_program);
} else if (term != NULL && *term != '\0') {
snprintf(buf, buf_size, "%s", term);
} else {
snprintf(buf, buf_size, "unknown");
}
}
static void get_desktop(char *buf, size_t buf_size) {
const char *desktop = getenv("XDG_CURRENT_DESKTOP");
const char *session = getenv("DESKTOP_SESSION");
const char *wayland = getenv("WAYLAND_DISPLAY");
const char *display = getenv("DISPLAY");
if (desktop != NULL && *desktop != '\0') {
if (wayland != NULL && *wayland != '\0') {
snprintf(buf, buf_size, "%s (Wayland)", desktop);
} else if (display != NULL && *display != '\0') {
snprintf(buf, buf_size, "%s (X11)", desktop);
} else {
snprintf(buf, buf_size, "%s", desktop);
}
return;
}
if (session != NULL && *session != '\0') {
if (wayland != NULL && *wayland != '\0') {
snprintf(buf, buf_size, "%s (Wayland)", session);
} else if (display != NULL && *display != '\0') {
snprintf(buf, buf_size, "%s (X11)", session);
} else {
snprintf(buf, buf_size, "%s", session);
}
return;
}
if (wayland != NULL && *wayland != '\0') {
snprintf(buf, buf_size, "Wayland");
} else if (display != NULL && *display != '\0') {
snprintf(buf, buf_size, "X11");
} else {
snprintf(buf, buf_size, "unknown");
}
}
static void get_init(char *buf, size_t buf_size) {
struct stat st;
char target[Z_PATH_MAX];
const char *base;
if (access("/run/systemd/system", F_OK) == 0) {
snprintf(buf, buf_size, "systemd");
return;
}
ssize_t len = readlink("/sbin/init", target, sizeof(target) - 1);
if (len > 0) {
target[len] = '\0';
base = strrchr(target, '/');
base = base != NULL ? base + 1 : target;
if (strstr(base, "systemd") != NULL) {
snprintf(buf, buf_size, "systemd");
} else if (strstr(base, "openrc") != NULL) {
snprintf(buf, buf_size, "openrc");
} else if (strstr(base, "runit") != NULL) {
snprintf(buf, buf_size, "runit");
} else if (strstr(base, "s6") != NULL) {
snprintf(buf, buf_size, "s6");
} else if (strstr(base, "dinit") != NULL) {
snprintf(buf, buf_size, "dinit");
} else if (strstr(base, "busybox") != NULL) {
snprintf(buf, buf_size, "busybox init");
} else {
snprintf(buf, buf_size, "%.*s", (int)(buf_size - 1), base);
}
return;
}
if (stat("/sbin/init", &st) == 0 && S_ISREG(st.st_mode) && access("/sbin/init", X_OK) == 0) {
snprintf(buf, buf_size, "sysvinit");
} else {
snprintf(buf, buf_size, "unknown");
}
}
static bool get_battery_value(const char *name, const char *file, char *buf, size_t buf_size) {
char path[Z_PATH_MAX];
snprintf(path, sizeof(path), "/sys/class/power_supply/%s/%s", name, file);
FILE *fp = fopen(path, "r");
if (fp == NULL) {
return false;
}
if (fgets(buf, (int)buf_size, fp) == NULL) {
fclose(fp);
return false;
}
fclose(fp);
trim_whitespace(buf);
return true;
}
static void get_battery(char *buf, size_t buf_size) {
struct dirent *dir_entry;
DIR *dir = opendir("/sys/class/power_supply");
if (dir == NULL) {
snprintf(buf, buf_size, "unknown");
return;
}
while ((dir_entry = readdir(dir)) != NULL) {
char capacity[32];
char status[64];
int percent;
const char *battery_name = dir_entry->d_name;
if (strncmp(battery_name, "BAT", 3) != 0) {
continue;
}
if (!get_battery_value(battery_name, "capacity", capacity, sizeof(capacity))) {
continue;
}
if (!get_battery_value(battery_name, "status", status, sizeof(status))) {
snprintf(status, sizeof(status), "unknown");
}
percent = atoi(capacity);
snprintf(buf, buf_size, "%s%d%%%s (%s, %s)",
get_battery_color(percent),
percent, RESET, battery_name, status);
closedir(dir);
return;
}
closedir(dir);
snprintf(buf, buf_size, "unknown");
}
static size_t get_ips(char entries[][IFACE_ENTRY_LEN], size_t max_entries) { static size_t get_ips(char entries[][IFACE_ENTRY_LEN], size_t max_entries) {
size_t count = 0; size_t count = 0;
struct ifaddrs *ifa_list = NULL; struct ifaddrs *ifa_list = NULL;
@@ -979,12 +796,7 @@ static void get_options(uint16_t options, const char *config_path) {
{ "DISK", OPT_DISK }, { "DISK", OPT_DISK },
{ "IP", OPT_IP }, { "IP", OPT_IP },
{ "LOGO", OPT_LOGO }, { "LOGO", OPT_LOGO },
{ "BARS", OPT_BARS }, { "BARS", OPT_BARS }
{ "SHELL", OPT_SHELL },
{ "TERMINAL", OPT_TERMINAL },
{ "DESKTOP", OPT_DESKTOP },
{ "INIT", OPT_INIT },
{ "BATTERY", OPT_BATTERY }
}; };
if (config_path) { if (config_path) {
@@ -994,7 +806,7 @@ static void get_options(uint16_t options, const char *config_path) {
for (size_t idx = 0; idx < ARR_LEN(flags); idx++) { for (size_t idx = 0; idx < ARR_LEN(flags); idx++) {
const bool enabled = (options & flags[idx].flag) != 0; const bool enabled = (options & flags[idx].flag) != 0;
printf("%-8s : %s%s%s\n", flags[idx].name, printf("%-6s : %s%s%s\n", flags[idx].name,
enabled ? C2 : C1, enabled ? C2 : C1,
enabled ? "ON" : "OFF", enabled ? "ON" : "OFF",
RESET); RESET);
@@ -1189,36 +1001,6 @@ int main(int argc, char **argv) {
line_count++; line_count++;
} }
if (options & OPT_SHELL) {
lines[line_count].label = "Shell:";
get_shell(lines[line_count].value, sizeof(lines[line_count].value));
line_count++;
}
if (options & OPT_TERMINAL) {
lines[line_count].label = "Terminal:";
get_terminal(lines[line_count].value, sizeof(lines[line_count].value));
line_count++;
}
if (options & OPT_DESKTOP) {
lines[line_count].label = "Desktop:";
get_desktop(lines[line_count].value, sizeof(lines[line_count].value));
line_count++;
}
if (options & OPT_INIT) {
lines[line_count].label = "Init:";
get_init(lines[line_count].value, sizeof(lines[line_count].value));
line_count++;
}
if (options & OPT_BATTERY) {
lines[line_count].label = "Battery:";
get_battery(lines[line_count].value, sizeof(lines[line_count].value));
line_count++;
}
if (options & OPT_IP) { if (options & OPT_IP) {
char interfaces[MAX_LOCAL_IPS][IFACE_ENTRY_LEN]; char interfaces[MAX_LOCAL_IPS][IFACE_ENTRY_LEN];
const size_t ifaces_count = get_ips(interfaces, MAX_LOCAL_IPS); const size_t ifaces_count = get_ips(interfaces, MAX_LOCAL_IPS);