diff options
| author | verdant <im@verdant.ee> | 2026-07-21 19:04:31 +0800 |
|---|---|---|
| committer | verdant <im@verdant.ee> | 2026-07-21 19:04:31 +0800 |
| commit | b921e3b0d305f494d37b928ca52995b52b8657f9 (patch) | |
| tree | 86c1d4e261b1c7f5114a6db1f5d699aeac675d3f /stat.c | |
| parent | f77177e2f3ae27c48151a297dd0a4b36101038a2 (diff) | |
| download | sf-b921e3b0d305f494d37b928ca52995b52b8657f9.tar.gz sf-b921e3b0d305f494d37b928ca52995b52b8657f9.zip | |
Add status information manager
Diffstat (limited to 'stat.c')
| -rw-r--r-- | stat.c | 201 |
1 files changed, 201 insertions, 0 deletions
@@ -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); +} |
