mirror of
https://github.com/arthur-pbty/optifetch.git
synced 2026-08-01 20:29:33 +02:00
240 lines
8.1 KiB
C
240 lines
8.1 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);
|
|
}
|
|
} |