mirror of
https://github.com/arthur-pbty/optifetch.git
synced 2026-08-01 20:29:33 +02:00
first commit
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
#include "optifetch.h"
|
||||||
|
|
||||||
|
void generate_default_config(const char* path) {
|
||||||
|
FILE *f = fopen(path, "w");
|
||||||
|
if (!f) return;
|
||||||
|
|
||||||
|
fprintf(f, "{reset}{align:L}{bold}{user}{reset}@{bold}{host}{reset}\n");
|
||||||
|
fprintf(f, "{align:L}-----------------------------\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}OS{reset}: {align:V}{os}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Host{reset}: {align:V}{host_model}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Kernel{reset}: {align:V}{kernel} {arch}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Uptime{reset}: {align:V}{uptime}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Packages{reset}: {align:V}{packages}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Shell{reset}: {align:V}{shell}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}DE/WM{reset}: {align:V}{de} ({wm})\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Display{reset}: {align:V}{display_server}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Terminal{reset}: {align:V}{term}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}CPU{reset}: {align:V}{cpu} ({cores}) @ {cpu_max_freq}MHz\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{if:gpu}{fg:255,255,0}GPU{reset}: {align:V}{gpu}{endif}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Memory{reset}: {align:V}{ram:gb} ({ram:%%})\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{if:swap}{fg:255,255,0}Swap{reset}: {align:V}{swap:gb} ({swap:%%}){endif}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Disk{reset}: {align:V}{disk:gb} ({disk:%%}) - {disk_fs}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Theme{reset}: {align:V}{theme}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Font{reset}: {align:V}{font}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Locale{reset}: {align:V}{locale}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{if:laptop}{fg:255,255,0}Battery{reset}: {align:V}{battery} ({bat_status}){endif}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Date{reset}: {align:V}{date} {time}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Local IP{reset}: {align:V}{ip_local}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{if:wifi}{fg:255,255,0}Wifi{reset}: {align:V}{wifi}{endif}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}Public IP{reset}: {align:V}{ip_public}\n");
|
||||||
|
fprintf(f, "{fg:0,255,255} {logo} {align:L}{fg:255,255,0}DNS{reset}: {align:V}{dns}\n");
|
||||||
|
fprintf(f, "\n");
|
||||||
|
fprintf(f, "{align:L}{fg:0,255,0}███{fg:255,255,0}███{fg:255,0,255}███{fg:0,255,255}███{reset}\n");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#include "optifetch.h"
|
||||||
|
|
||||||
|
#define MAX_LOGO_LINES 100
|
||||||
|
#define MAX_LOGO_WIDTH 512
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char id[64];
|
||||||
|
char lines[MAX_LOGO_LINES][MAX_LOGO_WIDTH];
|
||||||
|
int count;
|
||||||
|
int width;
|
||||||
|
} LogoCache;
|
||||||
|
|
||||||
|
static LogoCache cache_normal[32];
|
||||||
|
static LogoCache cache_small[32];
|
||||||
|
static int cache_normal_count = 0;
|
||||||
|
static int cache_small_count = 0;
|
||||||
|
|
||||||
|
static LogoCache* load_logo(const char* os_id, int small) {
|
||||||
|
LogoCache* cache_arr = small ? cache_small : cache_normal;
|
||||||
|
int* cache_cnt = small ? &cache_small_count : &cache_normal_count;
|
||||||
|
|
||||||
|
for(int i=0; i<*cache_cnt; i++) {
|
||||||
|
if(strcmp(cache_arr[i].id, os_id) == 0) return &cache_arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cache_cnt >= 32) return NULL;
|
||||||
|
|
||||||
|
LogoCache* new_cache = &cache_arr[(*cache_cnt)++];
|
||||||
|
snprintf(new_cache->id, sizeof(new_cache->id), "%s", os_id);
|
||||||
|
new_cache->count = 0;
|
||||||
|
new_cache->width = 0;
|
||||||
|
|
||||||
|
char path[256];
|
||||||
|
snprintf(path, sizeof(path), "logos/%s%s.txt", os_id, small ? "_small" : "");
|
||||||
|
|
||||||
|
FILE *f = fopen(path, "r");
|
||||||
|
if (!f) return new_cache;
|
||||||
|
|
||||||
|
char line[MAX_LOGO_WIDTH];
|
||||||
|
while(fgets(line, sizeof(line), f) && new_cache->count < MAX_LOGO_LINES) {
|
||||||
|
line[strcspn(line, "\n")] = 0;
|
||||||
|
snprintf(new_cache->lines[new_cache->count], MAX_LOGO_WIDTH, "%s", line);
|
||||||
|
|
||||||
|
int w = 0;
|
||||||
|
for(int j=0; j<strlen(line); j++) {
|
||||||
|
if((line[j] & 0xC0) != 0x80) w++;
|
||||||
|
}
|
||||||
|
if(w > new_cache->width) new_cache->width = w;
|
||||||
|
|
||||||
|
new_cache->count++;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return new_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_logo_line(const char* os_id, int small, int idx, char* out, size_t size) {
|
||||||
|
LogoCache* c = load_logo(os_id, small);
|
||||||
|
|
||||||
|
if(!c) {
|
||||||
|
out[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(idx < c->count) {
|
||||||
|
snprintf(out, size, "%s", c->lines[idx]);
|
||||||
|
// CORRECTION : On pad la ligne avec des espaces pour que toutes les lignes du logo
|
||||||
|
// fassent exactement la même largeur visuelle. C'est vital pour l'alignement.
|
||||||
|
int current_w = 0;
|
||||||
|
for(int j=0; j<strlen(out); j++) {
|
||||||
|
if((out[j] & 0xC0) != 0x80) current_w++;
|
||||||
|
}
|
||||||
|
int pad = c->width - current_w;
|
||||||
|
if(pad > 0) {
|
||||||
|
int len = strlen(out);
|
||||||
|
if (len + pad + 1 < (int)size) {
|
||||||
|
for(int i=0; i<pad; i++) out[len + i] = ' ';
|
||||||
|
out[len + pad] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Lignes en dessous du logo : on remplit par des espaces
|
||||||
|
if (c->width > 0 && size > (size_t)c->width) {
|
||||||
|
for(int i=0; i<c->width; i++) out[i] = ' ';
|
||||||
|
out[c->width] = '\0';
|
||||||
|
} else {
|
||||||
|
out[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_logo_height(const char* os_id, int small) {
|
||||||
|
LogoCache* c = load_logo(os_id, small);
|
||||||
|
return c ? c->count : 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
-`
|
||||||
|
.o+`
|
||||||
|
`ooo/
|
||||||
|
`+oooo:
|
||||||
|
`+oooooo:
|
||||||
|
-+oooooo+:
|
||||||
|
`/:-:++oooo+:
|
||||||
|
`/++++/+++++++:
|
||||||
|
`/++++++++++++++:
|
||||||
|
`/+++ooooooooooooo/`
|
||||||
|
./ooosssso++osssssso+`
|
||||||
|
.oossssso-````/ossssss+`
|
||||||
|
-osssssso. :ssssssso.
|
||||||
|
:osssssss/ osssso+++.
|
||||||
|
/ossssssss/ +ssssooo/-
|
||||||
|
`/ossssso+/:- -:/+osssso+-
|
||||||
|
`+sso+:-` `.-/+oso:
|
||||||
|
`++:. `-/+/
|
||||||
|
.` `/
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#include "optifetch.h"
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
printf("Optifetch - Lightweight system info tool\n\n");
|
||||||
|
printf("Usage: optifetch [options]\n\n");
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" help Show this help message\n");
|
||||||
|
printf(" (none) Run optifetch with default or custom config\n\n");
|
||||||
|
printf("Configuration:\n");
|
||||||
|
printf(" A file named 'optifetch.conf' is generated on first run.\n");
|
||||||
|
printf(" You can edit it to customize the output.\n\n");
|
||||||
|
printf("Available Variables:\n");
|
||||||
|
printf(" {logo} {small_logo} {user} {host} {os} {kernel} {uptime} {arch}\n");
|
||||||
|
printf(" {shell} {cpu} {cores} {cpu_max_freq} {gpu} {de} {wm} {term}\n");
|
||||||
|
printf(" {packages} {battery} {bat_status} {date} {time}\n");
|
||||||
|
printf(" {ip_local} {ip_public} {dns} {wifi} {host_model}\n");
|
||||||
|
printf(" {display_server} {theme} {font} {locale} {disk_fs}\n\n");
|
||||||
|
printf("Variables with Units:\n");
|
||||||
|
printf(" {ram:gb} {ram:mb} {ram:%%}\n");
|
||||||
|
printf(" {swap:gb} {swap:mb} {swap:%%}\n");
|
||||||
|
printf(" {disk:gb} {disk:mb} {disk:%%}\n\n");
|
||||||
|
printf("Formatting:\n");
|
||||||
|
printf(" {align:id} Align text to the max width of all 'id' tags\n");
|
||||||
|
printf(" {fg:R,G,B} Set foreground color (e.g. {fg:255,0,0})\n");
|
||||||
|
printf(" {bg:R,G,B} Set background color\n");
|
||||||
|
printf(" {fg:red} Named colors (red, green, blue, yellow, cyan, magenta, white, black)\n");
|
||||||
|
printf(" {bold} Bold text\n");
|
||||||
|
printf(" {reset} Reset formatting\n\n");
|
||||||
|
printf("Conditionals:\n");
|
||||||
|
printf(" {if:laptop} ... {endif} Show only if battery exists\n");
|
||||||
|
printf(" {if:gpu} ... {endif} Show only if GPU exists\n");
|
||||||
|
printf(" {if:swap} ... {endif} Show only if swap is active\n");
|
||||||
|
printf(" {if:wifi} ... {endif} Show only if connected to wifi\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc > 1 && (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)) {
|
||||||
|
print_help();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SysInfo info;
|
||||||
|
get_info(&info);
|
||||||
|
|
||||||
|
const char *config_path = "optifetch.conf";
|
||||||
|
|
||||||
|
if (access(config_path, F_OK) != 0) {
|
||||||
|
generate_default_config(config_path);
|
||||||
|
printf("Fichier de configuration '%s' créé. Modifiez-le pour personnaliser l'affichage.\n\n", config_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_config(config_path, &info);
|
||||||
|
|
||||||
|
printf("\033[0m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{reset}{align:L}{bold}{user}{reset}@{bold}{host}{reset}
|
||||||
|
{align:L}-----------------------------
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}OS{reset}: {align:V}{os}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Host{reset}: {align:V}{host_model}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Kernel{reset}: {align:V}{kernel} {arch}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Uptime{reset}: {align:V}{uptime}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Packages{reset}: {align:V}{packages}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Shell{reset}: {align:V}{shell}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}DE/WM{reset}: {align:V}{de} ({wm})
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Display{reset}: {align:V}{display_server}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Terminal{reset}: {align:V}{term}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}CPU{reset}: {align:V}{cpu} ({cores}) @ {cpu_max_freq}MHz
|
||||||
|
{fg:0,255,255} {logo} {if:gpu}{fg:255,255,0}GPU{reset}: {align:V}{gpu}{endif}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Memory{reset}: {align:V}{ram:gb} ({ram:%})
|
||||||
|
{fg:0,255,255} {logo} {if:swap}{fg:255,255,0}Swap{reset}: {align:V}{swap:gb} ({swap:%}){endif}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Disk{reset}: {align:V}{disk:gb} ({disk:%}) - {disk_fs}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Theme{reset}: {align:V}{theme}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Font{reset}: {align:V}{font}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Locale{reset}: {align:V}{locale}
|
||||||
|
{fg:0,255,255} {logo} {if:laptop}{fg:255,255,0}Battery{reset}: {align:V}{battery} ({bat_status}){endif}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Date{reset}: {align:V}{date} {time}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Local IP{reset}: {align:V}{ip_local}
|
||||||
|
{fg:0,255,255} {logo} {if:wifi}{fg:255,255,0}Wifi{reset}: {align:V}{wifi}{endif}
|
||||||
|
{fg:0,255,255} {logo} {fg:255,255,0}Public IP{reset}: {align:V}{ip_public}
|
||||||
|
{fg:0,255,255} {logo} {align:L}{fg:255,255,0}DNS{reset}: {align:V}{dns}
|
||||||
|
|
||||||
|
{fg:0,255,0}███{fg:255,255,0}███{fg:255,0,255}███{fg:0,255,255}███{reset}
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef OPTIFETCH_H
|
||||||
|
#define OPTIFETCH_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define BUF_SIZE 4096
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char user[128];
|
||||||
|
char hostname[256];
|
||||||
|
char os[256];
|
||||||
|
char os_id[64];
|
||||||
|
char kernel[128];
|
||||||
|
char uptime[128];
|
||||||
|
char arch[128];
|
||||||
|
char shell[128];
|
||||||
|
char cpu[256];
|
||||||
|
char gpu[256];
|
||||||
|
char de[128];
|
||||||
|
char wm[128];
|
||||||
|
char term[128];
|
||||||
|
char packages[128];
|
||||||
|
long cores;
|
||||||
|
long cpu_max_freq;
|
||||||
|
|
||||||
|
char host_model[128];
|
||||||
|
char display_server[32];
|
||||||
|
char theme[128];
|
||||||
|
char font[128];
|
||||||
|
char locale[64];
|
||||||
|
char dns[64];
|
||||||
|
char wifi[128];
|
||||||
|
char ip_public[64];
|
||||||
|
char disk_fs[32];
|
||||||
|
|
||||||
|
unsigned long ram_total_mb;
|
||||||
|
unsigned long ram_used_mb;
|
||||||
|
unsigned long swap_total_mb;
|
||||||
|
unsigned long swap_used_mb;
|
||||||
|
unsigned long disk_total_mb;
|
||||||
|
unsigned long disk_used_mb;
|
||||||
|
char battery[64];
|
||||||
|
char battery_status[64];
|
||||||
|
char date[64];
|
||||||
|
char time_str[64];
|
||||||
|
char ip_local[128];
|
||||||
|
} SysInfo;
|
||||||
|
|
||||||
|
void get_info(SysInfo *info);
|
||||||
|
void get_logo_line(const char* os_id, int small, int idx, char* out, size_t size);
|
||||||
|
int get_logo_height(const char* os_id, int small); // NOUVEAU
|
||||||
|
void generate_default_config(const char* path);
|
||||||
|
void render_config(const char* path, SysInfo *info);
|
||||||
|
void print_help();
|
||||||
|
|
||||||
|
#endif
|
||||||
+253
@@ -0,0 +1,253 @@
|
|||||||
|
#include "optifetch.h"
|
||||||
|
|
||||||
|
#define MAX_ALIGN_IDS 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char id[32];
|
||||||
|
int max_width;
|
||||||
|
} AlignID;
|
||||||
|
|
||||||
|
static AlignID align_ids[MAX_ALIGN_IDS];
|
||||||
|
static int align_count = 0;
|
||||||
|
|
||||||
|
static int current_col = 0;
|
||||||
|
static int skip_output = 0;
|
||||||
|
static int current_line_num = 0;
|
||||||
|
static int current_pass = 1;
|
||||||
|
|
||||||
|
// NOUVEAU : Variables pour gérer l'index du logo indépendamment des lignes du fichier
|
||||||
|
static int logo_line_idx = 0;
|
||||||
|
static int prev_line_had_logo = 0;
|
||||||
|
|
||||||
|
static int get_align_width(const char* id) {
|
||||||
|
for(int i=0; i<align_count; i++) {
|
||||||
|
if(strcmp(align_ids[i].id, id) == 0) return align_ids[i].max_width;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_align_width(const char* id, int width) {
|
||||||
|
for(int i=0; i<align_count; i++) {
|
||||||
|
if(strcmp(align_ids[i].id, id) == 0) {
|
||||||
|
if(width > align_ids[i].max_width) align_ids[i].max_width = width;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(align_count < MAX_ALIGN_IDS) {
|
||||||
|
snprintf(align_ids[align_count].id, sizeof(align_ids[align_count].id), "%.31s", id);
|
||||||
|
align_ids[align_count].max_width = width;
|
||||||
|
align_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_putchar(char c) {
|
||||||
|
if (skip_output) return;
|
||||||
|
if (current_pass == 2) {
|
||||||
|
putchar(c);
|
||||||
|
}
|
||||||
|
if ((c & 0xC0) != 0x80) {
|
||||||
|
current_col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_putstr(const char* s) {
|
||||||
|
for (int i = 0; s[i]; i++) my_putchar(s[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_color(const char* params, int is_bg) {
|
||||||
|
if (skip_output || current_pass == 1) return;
|
||||||
|
int r, g, b;
|
||||||
|
if (sscanf(params, "%d,%d,%d", &r, &g, &b) == 3) {
|
||||||
|
printf("\033[%d;2;%d;%d;%dm", is_bg ? 48 : 38, r, g, b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp(params, "red") == 0) r=255, g=0, b=0;
|
||||||
|
else if (strcmp(params, "green") == 0) r=0, g=255, b=0;
|
||||||
|
else if (strcmp(params, "blue") == 0) r=0, g=0, b=255;
|
||||||
|
else if (strcmp(params, "yellow") == 0) r=255, g=255, b=0;
|
||||||
|
else if (strcmp(params, "cyan") == 0) r=0, g=255, b=255;
|
||||||
|
else if (strcmp(params, "magenta") == 0) r=255, g=0, b=255;
|
||||||
|
else if (strcmp(params, "white") == 0) r=255, g=255, b=255;
|
||||||
|
else if (strcmp(params, "black") == 0) r=0, g=0, b=0;
|
||||||
|
else r=200, g=200, b=200;
|
||||||
|
printf("\033[%d;2;%d;%d;%dm", is_bg ? 48 : 38, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_variable(const char* name, SysInfo *info) {
|
||||||
|
if (skip_output) return;
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
if (strcmp(name, "logo") == 0 || strcmp(name, "small_logo") == 0) {
|
||||||
|
// NOUVEAU : On utilise logo_line_idx au lieu de current_line_num
|
||||||
|
get_logo_line(info->os_id, name[0] == 's', logo_line_idx, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "user") == 0) snprintf(buf, sizeof(buf), "%s", info->user);
|
||||||
|
else if (strcmp(name, "host") == 0) snprintf(buf, sizeof(buf), "%s", info->hostname);
|
||||||
|
else if (strcmp(name, "os") == 0) snprintf(buf, sizeof(buf), "%s", info->os);
|
||||||
|
else if (strcmp(name, "kernel") == 0) snprintf(buf, sizeof(buf), "%s", info->kernel);
|
||||||
|
else if (strcmp(name, "uptime") == 0) snprintf(buf, sizeof(buf), "%s", info->uptime);
|
||||||
|
else if (strcmp(name, "arch") == 0) snprintf(buf, sizeof(buf), "%s", info->arch);
|
||||||
|
else if (strcmp(name, "shell") == 0) snprintf(buf, sizeof(buf), "%s", info->shell);
|
||||||
|
else if (strcmp(name, "cpu") == 0) snprintf(buf, sizeof(buf), "%s", info->cpu);
|
||||||
|
else if (strcmp(name, "cores") == 0) snprintf(buf, sizeof(buf), "%ld", info->cores);
|
||||||
|
else if (strcmp(name, "cpu_max_freq") == 0) snprintf(buf, sizeof(buf), "%ld", info->cpu_max_freq);
|
||||||
|
else if (strcmp(name, "gpu") == 0) snprintf(buf, sizeof(buf), "%s", info->gpu);
|
||||||
|
else if (strcmp(name, "de") == 0) snprintf(buf, sizeof(buf), "%s", info->de);
|
||||||
|
else if (strcmp(name, "wm") == 0) snprintf(buf, sizeof(buf), "%s", info->wm);
|
||||||
|
else if (strcmp(name, "term") == 0) snprintf(buf, sizeof(buf), "%s", info->term);
|
||||||
|
else if (strcmp(name, "packages") == 0) snprintf(buf, sizeof(buf), "%s", info->packages);
|
||||||
|
else if (strcmp(name, "battery") == 0) snprintf(buf, sizeof(buf), "%s", info->battery);
|
||||||
|
else if (strcmp(name, "bat_status") == 0) snprintf(buf, sizeof(buf), "%s", info->battery_status);
|
||||||
|
else if (strcmp(name, "date") == 0) snprintf(buf, sizeof(buf), "%s", info->date);
|
||||||
|
else if (strcmp(name, "time") == 0) snprintf(buf, sizeof(buf), "%s", info->time_str);
|
||||||
|
else if (strcmp(name, "ip_local") == 0) snprintf(buf, sizeof(buf), "%s", info->ip_local);
|
||||||
|
else if (strcmp(name, "ip_public") == 0) snprintf(buf, sizeof(buf), "%s", info->ip_public);
|
||||||
|
else if (strcmp(name, "dns") == 0) snprintf(buf, sizeof(buf), "%s", info->dns);
|
||||||
|
else if (strcmp(name, "wifi") == 0) snprintf(buf, sizeof(buf), "%s", info->wifi[0] ? info->wifi : "N/A");
|
||||||
|
else if (strcmp(name, "host_model") == 0) snprintf(buf, sizeof(buf), "%s", info->host_model);
|
||||||
|
else if (strcmp(name, "display_server") == 0) snprintf(buf, sizeof(buf), "%s", info->display_server);
|
||||||
|
else if (strcmp(name, "theme") == 0) snprintf(buf, sizeof(buf), "%s", info->theme);
|
||||||
|
else if (strcmp(name, "font") == 0) snprintf(buf, sizeof(buf), "%s", info->font);
|
||||||
|
else if (strcmp(name, "locale") == 0) snprintf(buf, sizeof(buf), "%s", info->locale);
|
||||||
|
else if (strcmp(name, "disk_fs") == 0) snprintf(buf, sizeof(buf), "%s", info->disk_fs);
|
||||||
|
else if (strncmp(name, "ram", 3) == 0) {
|
||||||
|
char unit[128] = "mb";
|
||||||
|
if (strlen(name) > 4 && name[3] == ':') snprintf(unit, sizeof(unit), "%s", name + 4);
|
||||||
|
if (strcmp(unit, "gb") == 0) snprintf(buf, sizeof(buf), "%.1fGB / %.1fGB", (double)info->ram_used_mb / 1024.0, (double)info->ram_total_mb / 1024.0);
|
||||||
|
else if (strcmp(unit, "%") == 0) snprintf(buf, sizeof(buf), "%.1f%%", info->ram_total_mb ? (double)info->ram_used_mb / (double)info->ram_total_mb * 100.0 : 0);
|
||||||
|
else snprintf(buf, sizeof(buf), "%luMB / %luMB", info->ram_used_mb, info->ram_total_mb);
|
||||||
|
}
|
||||||
|
else if (strncmp(name, "swap", 4) == 0) {
|
||||||
|
char unit[128] = "mb";
|
||||||
|
if (strlen(name) > 5 && name[4] == ':') snprintf(unit, sizeof(unit), "%s", name + 5);
|
||||||
|
if (strcmp(unit, "gb") == 0) snprintf(buf, sizeof(buf), "%.1fGB / %.1fGB", (double)info->swap_used_mb / 1024.0, (double)info->swap_total_mb / 1024.0);
|
||||||
|
else if (strcmp(unit, "%") == 0) snprintf(buf, sizeof(buf), "%.1f%%", info->swap_total_mb ? (double)info->swap_used_mb / (double)info->swap_total_mb * 100.0 : 0);
|
||||||
|
else snprintf(buf, sizeof(buf), "%luMB / %luMB", info->swap_used_mb, info->swap_total_mb);
|
||||||
|
}
|
||||||
|
else if (strncmp(name, "disk", 4) == 0) {
|
||||||
|
char unit[128] = "mb";
|
||||||
|
if (strlen(name) > 5 && name[4] == ':') snprintf(unit, sizeof(unit), "%s", name + 5);
|
||||||
|
if (strcmp(unit, "gb") == 0) snprintf(buf, sizeof(buf), "%.1fGB / %.1fGB", (double)info->disk_used_mb / 1024.0, (double)info->disk_total_mb / 1024.0);
|
||||||
|
else if (strcmp(unit, "%") == 0) snprintf(buf, sizeof(buf), "%.1f%%", info->disk_total_mb ? (double)info->disk_used_mb / (double)info->disk_total_mb * 100.0 : 0);
|
||||||
|
else snprintf(buf, sizeof(buf), "%luMB / %luMB", info->disk_used_mb, info->disk_total_mb);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf(buf, sizeof(buf), "{%s}", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_putstr(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_line(const char* line, SysInfo *info) {
|
||||||
|
int i = 0;
|
||||||
|
current_col = 0;
|
||||||
|
skip_output = 0;
|
||||||
|
|
||||||
|
// NOUVEAU : Détection de la présence du logo sur la ligne courante
|
||||||
|
int has_logo = (strstr(line, "{logo}") != NULL || strstr(line, "{small_logo}") != NULL);
|
||||||
|
if (has_logo && !prev_line_had_logo) {
|
||||||
|
logo_line_idx = 0; // On réinitialise l'index du logo à 0 si c'est le début du logo
|
||||||
|
}
|
||||||
|
|
||||||
|
while (line[i] != '\0' && line[i] != '\n') {
|
||||||
|
if (line[i] == '{') {
|
||||||
|
int j = i + 1;
|
||||||
|
char token[128];
|
||||||
|
int k = 0;
|
||||||
|
while (line[j] != '}' && line[j] != '\0' && line[j] != '\n' && k < 127) {
|
||||||
|
token[k++] = line[j++];
|
||||||
|
}
|
||||||
|
token[k] = '\0';
|
||||||
|
if (line[j] == '}') {
|
||||||
|
i = j + 1;
|
||||||
|
|
||||||
|
if (strcmp(token, "if:laptop") == 0) skip_output = (strcmp(info->battery, "N/A") == 0);
|
||||||
|
else if (strcmp(token, "if:gpu") == 0) skip_output = (strlen(info->gpu) == 0);
|
||||||
|
else if (strcmp(token, "if:swap") == 0) skip_output = (info->swap_total_mb == 0);
|
||||||
|
else if (strcmp(token, "if:wifi") == 0) skip_output = (strlen(info->wifi) == 0);
|
||||||
|
else if (strcmp(token, "endif") == 0) skip_output = 0;
|
||||||
|
|
||||||
|
else if (strncmp(token, "align:", 6) == 0) {
|
||||||
|
if (!skip_output) {
|
||||||
|
if (current_pass == 1) {
|
||||||
|
set_align_width(token + 6, current_col);
|
||||||
|
}
|
||||||
|
int target = get_align_width(token + 6);
|
||||||
|
while (current_col < target) my_putchar(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strncmp(token, "fg:", 3) == 0) print_color(token + 3, 0);
|
||||||
|
else if (strncmp(token, "bg:", 3) == 0) print_color(token + 3, 1);
|
||||||
|
else if (strcmp(token, "reset") == 0) { if(!skip_output && current_pass == 2) printf("\033[0m"); }
|
||||||
|
else if (strcmp(token, "bold") == 0) { if(!skip_output && current_pass == 2) printf("\033[1m"); }
|
||||||
|
else print_variable(token, info);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
my_putchar(line[i++]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
my_putchar(line[i++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current_pass == 2 && !skip_output) putchar('\n');
|
||||||
|
current_line_num++;
|
||||||
|
|
||||||
|
// NOUVEAU : Mise à jour des variables pour la gestion du logo
|
||||||
|
prev_line_had_logo = has_logo;
|
||||||
|
if (has_logo) logo_line_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_config(const char* path, SysInfo *info) {
|
||||||
|
FILE *f = fopen(path, "r");
|
||||||
|
if (!f) return;
|
||||||
|
|
||||||
|
static char lines[200][1024];
|
||||||
|
int line_count = 0;
|
||||||
|
while (fgets(lines[line_count], sizeof(lines[line_count]), f) && line_count < 200) {
|
||||||
|
line_count++;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
int logo_h = 0;
|
||||||
|
char logo_token[20] = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < line_count; i++) {
|
||||||
|
if (strstr(lines[i], "{logo}")) {
|
||||||
|
snprintf(logo_token, sizeof(logo_token), "{logo}");
|
||||||
|
logo_h = get_logo_height(info->os_id, 0);
|
||||||
|
}
|
||||||
|
if (strstr(lines[i], "{small_logo}")) {
|
||||||
|
snprintf(logo_token, sizeof(logo_token), "{small_logo}");
|
||||||
|
int sh = get_logo_height(info->os_id, 1);
|
||||||
|
if (sh > logo_h) logo_h = sh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(logo_token) > 0) {
|
||||||
|
while (line_count < logo_h && line_count < 200) {
|
||||||
|
snprintf(lines[line_count++], 1024, "%s{align:L} \n", logo_token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
align_count = 0;
|
||||||
|
|
||||||
|
// Pass 1
|
||||||
|
current_pass = 1;
|
||||||
|
current_line_num = 0;
|
||||||
|
logo_line_idx = 0;
|
||||||
|
prev_line_had_logo = 0;
|
||||||
|
for (int i = 0; i < line_count; i++) {
|
||||||
|
process_line(lines[i], info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass 2
|
||||||
|
current_pass = 2;
|
||||||
|
current_line_num = 0;
|
||||||
|
logo_line_idx = 0;
|
||||||
|
prev_line_had_logo = 0;
|
||||||
|
for (int i = 0; i < line_count; i++) {
|
||||||
|
process_line(lines[i], info);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
#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));
|
||||||
|
|
||||||
|
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); }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user