Files
optifetch/sysinfo.c
T

261 lines
8.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;
}
// NOUVEAU : Lecture précise de la mémoire depuis /proc/meminfo
static long get_meminfo_kb(const char *buf, const char *key)
{
const char *p = strstr(buf, key);
if (p)
{
p += strlen(key);
while (*p == ' ' || *p == '\t' || *p == ':')
p++;
return atol(p);
}
return 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));
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");
// NOUVEAU : Calcul de la RAM et Swap sans le cache
read_file("/proc/meminfo", buf, sizeof(buf));
long mem_total_kb = get_meminfo_kb(buf, "MemTotal");
long mem_avail_kb = get_meminfo_kb(buf, "MemAvailable");
long swap_total_kb = get_meminfo_kb(buf, "SwapTotal");
long swap_free_kb = get_meminfo_kb(buf, "SwapFree");
info->ram_total_mb = mem_total_kb / 1024;
info->ram_used_mb = (mem_total_kb - mem_avail_kb) / 1024; // Vraie RAM utilisée
info->swap_total_mb = swap_total_kb / 1024;
info->swap_used_mb = (swap_total_kb - swap_free_kb) / 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);
}
}