aboutsummaryrefslogtreecommitdiffstats
path: root/stat.c
diff options
context:
space:
mode:
authorverdant <im@verdant.ee>2026-07-21 19:04:31 +0800
committerverdant <im@verdant.ee>2026-07-21 19:04:31 +0800
commitb921e3b0d305f494d37b928ca52995b52b8657f9 (patch)
tree86c1d4e261b1c7f5114a6db1f5d699aeac675d3f /stat.c
parentf77177e2f3ae27c48151a297dd0a4b36101038a2 (diff)
downloadsf-b921e3b0d305f494d37b928ca52995b52b8657f9.tar.gz
sf-b921e3b0d305f494d37b928ca52995b52b8657f9.zip
Add status information manager
Diffstat (limited to 'stat.c')
-rw-r--r--stat.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/stat.c b/stat.c
new file mode 100644
index 0000000..c0d94a3
--- /dev/null
+++ b/stat.c
@@ -0,0 +1,201 @@
+#include "stat.h"
+
+#include <ncurses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/statvfs.h>
+#include <unistd.h>
+
+#include "display.h"
+#include "err.h"
+#include "log.h"
+#include "mem.h"
+
+stat* stat_init() {
+ stat* s = xmalloc(sizeof(stat));
+ *s = (stat){
+ .sysver = "",
+ .meminfo = {.mem_available = 0, .mem_total = 0},
+ .diskinfo = {.disk_available = 0, .disk_total = 0},
+ };
+
+ return s;
+}
+
+void stat_get_sysver(stat* s) {
+ FILE* fp = fopen(PROC_PATH_VERSION, "r");
+ if (!fp) die("Cannot open %s", PROC_PATH_VERSION);
+
+ if (fgets(s->sysver, sizeof(s->sysver), fp) != NULL) {
+ s->sysver[strcspn(s->sysver, "\n")] = '\0';
+ }
+ fclose(fp);
+}
+void stat_print_cpu_info(WINDOW* w, int y, int maxx, stat* s) {
+ mvwprintw(w, y, maxx - STAT_INFO_WIDTH, " %.2f %%", s->cpu_occupy.cpu);
+}
+void stat_print_info(WINDOW* w, int y, int maxx, const char* label,
+ unsigned long total, unsigned long ava) {
+ unsigned long long t_bytes = total;
+ unsigned long long a_bytes = ava;
+
+ if (strcmp(label, "Mem") == 0 || strcmp(label, "Mem ") == 0) {
+ t_bytes *= 1024;
+ a_bytes *= 1024;
+ }
+
+ const char* units[] = {"B", "K", "M", "G", "T"};
+
+ int t_idx = 0;
+ int a_idx = 0;
+
+ double d_total = (double)t_bytes;
+ double d_ava = (double)a_bytes;
+
+ while (d_total >= 1024.0 && t_idx < 4) {
+ d_total /= 1024.0;
+ t_idx++;
+ }
+
+ while (d_ava >= 1024.0 && a_idx < 4) {
+ d_ava /= 1024.0;
+ a_idx++;
+ }
+
+ int startx = maxx - STAT_INFO_WIDTH;
+
+ mvwprintw(w, y, startx, " %.2f%s/%.2f%s", d_ava, units[t_idx], d_total,
+ units[t_idx]);
+
+ /* wrefresh(w); */
+}
+
+int stat_get_bar_ticks(int maxx, unsigned long long total,
+ unsigned long long ava) {
+ if (total == 0) return 0;
+ if (ava >= total) return 0;
+
+ unsigned long long used = total - ava;
+
+ unsigned long long slots = (unsigned long long)(maxx);
+
+ return (int)((slots * used) / total);
+}
+
+void stat_draw_cpu_bar(WINDOW* w, int maxx, int y, int x, stat* s) {
+ int ava_to_draw_x = maxx - STAT_INFO_WIDTH - BAR_LABEL_WIDTH;
+ int total_hashes = ava_to_draw_x * s->cpu_occupy.cpu;
+ log_write(LOG_INFO, "stat_draw_cpu_bar: ava_to_draw = %d", ava_to_draw_x);
+ log_write(LOG_INFO, "s->cpu_occupy.cpu = %f", s->cpu_occupy.cpu);
+ log_write(LOG_INFO, "CPU Hashes = %d", total_hashes);
+ char hashes[2048] = {0};
+
+ if (total_hashes > ava_to_draw_x) total_hashes = ava_to_draw_x;
+ memset(hashes, '#', total_hashes);
+ hashes[total_hashes] = '\0';
+
+ mvwprintw(w, y, x, "%-*s [", 4, "CPU");
+ wprintw_colorful(w, COLOR_PAIR_PROGRESS, "%.*s", total_hashes, hashes);
+
+ int remaining_spaces = ava_to_draw_x - total_hashes;
+ if (remaining_spaces > 0) {
+ wprintw(w, "%*s", remaining_spaces, "");
+ }
+
+ waddch(w, ']');
+}
+
+void stat_draw_bar(WINDOW* w, const char* label, int maxx, int y, int x,
+ unsigned long total, unsigned long ava) {
+ int ava_to_draw_x = maxx - STAT_INFO_WIDTH - BAR_LABEL_WIDTH;
+ int total_hashes = stat_get_bar_ticks(ava_to_draw_x, total, ava);
+ char hashes[2048] = {0};
+
+ init_pair(COLOR_PAIR_PROGRESS, COLOR_GREEN, COLOR_BLACK);
+
+ if (total_hashes > ava_to_draw_x) total_hashes = ava_to_draw_x;
+ memset(hashes, '#', total_hashes);
+ hashes[total_hashes] = '\0';
+
+ mvwprintw(w, y, x, "%-*s [", 4, label);
+ wprintw_colorful(w, COLOR_PAIR_PROGRESS, "%.*s", total_hashes, hashes);
+
+ int remaining_spaces = ava_to_draw_x - total_hashes;
+ if (remaining_spaces > 0) {
+ wprintw(w, "%*s", remaining_spaces, "");
+ }
+
+ waddch(w, ']');
+
+ /* wrefresh(w); */
+}
+
+void stat_get_meminfo(stat* s) {
+ static char buf[128];
+ char key[32] = "";
+ unsigned long long val = 0;
+
+ FILE* fp = fopen(PROC_PATH_MEMINFO, "r");
+ if (!fp) die("Cannot open %s", PROC_PATH_MEMINFO);
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (sscanf(buf, "%31[^:]: %llu", key, &val) == 2) {
+ if (strcmp(key, "MemTotal") == 0) {
+ s->meminfo.mem_total = val;
+ } else if (strcmp(key, "MemAvailable") == 0) {
+ s->meminfo.mem_available = val;
+ break;
+ }
+ }
+ }
+
+ fclose(fp);
+}
+
+void stat_get_diskinfo(stat* s) {
+ struct statvfs vfs;
+ if (statvfs("/", &vfs) != 0) {
+ s->diskinfo.disk_total = 0;
+ s->diskinfo.disk_available = 0;
+ log_write(LOG_WARN, "Cannot get disk info");
+ }
+
+ s->diskinfo.disk_total = (unsigned long long)vfs.f_blocks * vfs.f_frsize;
+ s->diskinfo.disk_available =
+ (unsigned long long)vfs.f_bavail * vfs.f_frsize;
+}
+
+void stat_get_cpuinfo(stat* s) {
+ char buf[128];
+ FILE* fp = fopen(PROC_PATH_STAT, "r");
+ if (!fp) {
+ log_write(LOG_WARN, "Cannot open %s", PROC_PATH_STAT);
+ return;
+ }
+
+ fgets(buf, sizeof(buf), fp);
+ sscanf(buf, "%s %llu %llu %llu %llu", s->cpu_occupy.name,
+ &s->cpu_occupy.user, &s->cpu_occupy.nice, &s->cpu_occupy.system,
+ &s->cpu_occupy.idle);
+ fclose(fp);
+}
+
+void stat_calc_cpuocc(stat* s) {
+ cpu_occupy* co = xmalloc(sizeof(cpu_occupy));
+ stat_get_cpuinfo(s);
+ co->idle = s->cpu_occupy.idle;
+ co->nice = s->cpu_occupy.nice;
+ co->system = s->cpu_occupy.system;
+ co->user = s->cpu_occupy.user;
+ usleep(200000);
+ stat_get_cpuinfo(s);
+ unsigned long long t1 = co->user + co->nice + co->system + co->idle;
+ unsigned long long t2 = s->cpu_occupy.user + s->cpu_occupy.nice +
+ s->cpu_occupy.system + s->cpu_occupy.idle;
+ unsigned long long user = s->cpu_occupy.user - co->user;
+ unsigned long long system = s->cpu_occupy.system - co->system;
+
+ s->cpu_occupy.cpu = (user + system) * 1.0 / (t2 - t1);
+ free(co);
+}