Files
optifetch/sysinfo.c
T
2026-06-26 21:41:36 +02:00

169 lines
7.6 KiB
C

#include "optifetch.h"
static void read_file(const char *path, char *buf, size_t size) {
FILE *f = fopen(path, "r");
if (!f) { if(size>0) buf[0] = '\0'; return; }
size_t n = fread(buf, 1, size - 1, f);
buf[n] = '\0';
fclose(f);
}
static void extract_value(const char *buf, const char *key, char *out, size_t size) {
out[0] = '\0';
const char *p = strstr(buf, key);
if (p) {
p += strlen(key);
while (*p == ' ' || *p == '\t' || *p == ':' || *p == '=' || *p == '"') p++;
size_t i = 0;
while (p[i] && p[i] != '\n' && p[i] != '"' && i < size - 1) {
out[i] = p[i];
i++;
}
out[i] = '\0';
}
}
static void clean_newline(char *str) {
str[strcspn(str, "\n")] = 0;
}
void get_info(SysInfo *info) {
struct passwd *pw = getpwuid(getuid());
snprintf(info->user, sizeof(info->user), "%s", pw ? pw->pw_name : "unknown");
gethostname(info->hostname, sizeof(info->hostname));
char buf[BUF_SIZE];
read_file("/etc/os-release", buf, sizeof(buf));
extract_value(buf, "PRETTY_NAME", info->os, sizeof(info->os));
extract_value(buf, "ID", info->os_id, sizeof(info->os_id));
extract_value(buf, "ANSI_COLOR", info->distro_color, sizeof(info->distro_color)); // NOUVEAU
struct utsname uts;
uname(&uts);
snprintf(info->kernel, sizeof(info->kernel), "%s", uts.release);
snprintf(info->arch, sizeof(info->arch), "%s", uts.machine);
struct sysinfo s_info;
sysinfo(&s_info);
int days = s_info.uptime / 86400;
int hours = (s_info.uptime % 86400) / 3600;
int mins = (s_info.uptime % 3600) / 60;
snprintf(info->uptime, sizeof(info->uptime), "%dd %dh %dm", days, hours, mins);
const char *sh = getenv("SHELL");
snprintf(info->shell, sizeof(info->shell), "%s", sh ? sh : "unknown");
const char *ds = getenv("XDG_SESSION_TYPE");
snprintf(info->display_server, sizeof(info->display_server), "%s", ds ? ds : "Unknown");
const char *loc = getenv("LANG");
snprintf(info->locale, sizeof(info->locale), "%s", loc ? loc : "Unknown");
read_file("/proc/cpuinfo", buf, sizeof(buf));
extract_value(buf, "model name", info->cpu, sizeof(info->cpu));
info->cores = sysconf(_SC_NPROCESSORS_ONLN);
read_file("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", buf, sizeof(buf));
info->cpu_max_freq = atol(buf) / 1000;
read_file("/sys/class/dmi/id/product_name", info->host_model, sizeof(info->host_model));
clean_newline(info->host_model);
if (strlen(info->host_model) == 0) snprintf(info->host_model, sizeof(info->host_model), "Unknown");
info->ram_total_mb = s_info.totalram * s_info.mem_unit / (1024 * 1024);
info->ram_used_mb = (s_info.totalram - s_info.freeram) * s_info.mem_unit / (1024 * 1024);
info->swap_total_mb = s_info.totalswap * s_info.mem_unit / (1024 * 1024);
info->swap_used_mb = (s_info.totalswap - s_info.freeswap) * s_info.mem_unit / (1024 * 1024);
struct statvfs vfs;
if (statvfs("/", &vfs) == 0) {
info->disk_total_mb = (vfs.f_blocks * vfs.f_frsize) / (1024 * 1024);
info->disk_used_mb = info->disk_total_mb - ((vfs.f_bfree * vfs.f_frsize) / (1024 * 1024));
} else {
info->disk_total_mb = 0; info->disk_used_mb = 0;
}
FILE *fp_fs = popen("findmnt -no FSTYPE / 2>/dev/null", "r");
if (fp_fs) { if (fgets(info->disk_fs, sizeof(info->disk_fs), fp_fs)) clean_newline(info->disk_fs); pclose(fp_fs); }
const char *de = getenv("XDG_CURRENT_DESKTOP");
const char *wm = getenv("DESKTOP_SESSION");
snprintf(info->de, sizeof(info->de), "%s", de ? de : "Unknown");
snprintf(info->wm, sizeof(info->wm), "%s", wm ? wm : info->de);
const char *term = getenv("TERM");
snprintf(info->term, sizeof(info->term), "%s", term ? term : "Unknown");
info->gpu[0] = '\0';
FILE *fdrm = popen("cat /sys/class/drm/card*/device/uevent 2>/dev/null | grep DRIVER | head -n 1", "r");
if (fdrm) {
char drmbuf[256];
if (fgets(drmbuf, sizeof(drmbuf), fdrm)) {
extract_value(drmbuf, "DRIVER", info->gpu, sizeof(info->gpu));
if(info->gpu[0] >= 'a' && info->gpu[0] <= 'z') info->gpu[0] -= 32;
}
pclose(fdrm);
}
FILE *fp_th = popen("gsettings get org.gnome.desktop.interface gtk-theme 2>/dev/null | tr -d \"'\"", "r");
if (fp_th) { if (fgets(info->theme, sizeof(info->theme), fp_th)) clean_newline(info->theme); pclose(fp_th); }
FILE *fp_fn = popen("gsettings get org.gnome.desktop.interface font-name 2>/dev/null | tr -d \"'\"", "r");
if (fp_fn) { if (fgets(info->font, sizeof(info->font), fp_fn)) clean_newline(info->font); pclose(fp_fn); }
int pkg_count = 0;
DIR *d; struct dirent *dir;
d = opendir("/var/lib/pacman/local");
if (d) { while ((dir = readdir(d)) != NULL) if (dir->d_type == DT_DIR && dir->d_name[0] != '.') pkg_count++; closedir(d); }
else {
FILE *fp = popen("ls /var/lib/dpkg/info 2>/dev/null | grep -c '.list$' ; rpm -qa 2>/dev/null | wc -l", "r");
if(fp) { char out[32]; if(fgets(out, sizeof(out), fp)) pkg_count = atoi(out); pclose(fp); }
}
snprintf(info->packages, sizeof(info->packages), "%d", pkg_count);
char bat_path[256] = "";
if (access("/sys/class/power_supply/BAT0/capacity", F_OK) == 0) snprintf(bat_path, sizeof(bat_path), "/sys/class/power_supply/BAT0");
else if (access("/sys/class/power_supply/BAT1/capacity", F_OK) == 0) snprintf(bat_path, sizeof(bat_path), "/sys/class/power_supply/BAT1");
if (strlen(bat_path) > 0) {
char cap_path[512], stat_path[512];
snprintf(cap_path, sizeof(cap_path), "%s/capacity", bat_path);
snprintf(stat_path, sizeof(stat_path), "%s/status", bat_path);
read_file(cap_path, buf, sizeof(buf)); clean_newline(buf);
snprintf(info->battery, sizeof(info->battery), "%s%%", buf);
read_file(stat_path, buf, sizeof(buf)); clean_newline(buf);
snprintf(info->battery_status, sizeof(info->battery_status), "%s", buf);
} else {
snprintf(info->battery, sizeof(info->battery), "N/A");
snprintf(info->battery_status, sizeof(info->battery_status), "N/A");
}
time_t t = time(NULL);
struct tm tm = *localtime(&t);
snprintf(info->date, sizeof(info->date), "%02d/%02d/%04d", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900);
snprintf(info->time_str, sizeof(info->time_str), "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
info->ip_local[0] = '\0';
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == 0) {
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) continue;
if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *sa = (struct sockaddr_in *)ifa->ifa_addr;
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &sa->sin_addr, ip, INET_ADDRSTRLEN);
if (strcmp(ip, "127.0.0.1") != 0) {
snprintf(info->ip_local, sizeof(info->ip_local), "%s (%s)", ip, ifa->ifa_name);
break;
}
}
}
freeifaddrs(ifaddr);
}
read_file("/etc/resolv.conf", buf, sizeof(buf));
extract_value(buf, "nameserver", info->dns, sizeof(info->dns));
info->wifi[0] = '\0';
FILE *fp_wf = popen("iwgetid -r 2>/dev/null", "r");
if (fp_wf) { if (fgets(info->wifi, sizeof(info->wifi), fp_wf)) clean_newline(info->wifi); pclose(fp_wf); }
info->ip_public[0] = '\0';
FILE *fp_ip = popen("curl -s --max-time 2 ifconfig.me 2>/dev/null", "r");
if (fp_ip) { if (fgets(info->ip_public, sizeof(info->ip_public), fp_ip)) clean_newline(info->ip_public); pclose(fp_ip); }
}