diff options
| author | Federico Angelilli <code@fedang.net> | 2024-09-08 15:45:57 +0200 |
|---|---|---|
| committer | Federico Angelilli <code@fedang.net> | 2024-09-08 15:45:57 +0200 |
| commit | 5e7f66b34826697537bcdcb60c81f56da956a32b (patch) | |
| tree | cea519be41162f4da216f564a665bb755ac6cdc3 /src/blocks/ram.c | |
| parent | feae7fb2bed5357a5e685063e3f6ff005bfc0bd5 (diff) | |
Add ram formatting
Diffstat (limited to 'src/blocks/ram.c')
| -rw-r--r-- | src/blocks/ram.c | 110 |
1 files changed, 108 insertions, 2 deletions
diff --git a/src/blocks/ram.c b/src/blocks/ram.c index a626413..44dd1a3 100644 --- a/src/blocks/ram.c +++ b/src/blocks/ram.c @@ -1,12 +1,118 @@ +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> + #include "scheme.h" +#include "../any_log.h" + +char *str_replace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + +static void block_ram_update(block_t *block) +{ + FILE *meminfo = fopen("/proc/meminfo", "rb"); + assert(meminfo != NULL); + + uintmax_t total, unused, buffers, cached; + assert(5 == fscanf(meminfo, + "MemTotal: %ju kB\n" + "MemFree: %ju kB\n" + "MemAvailable: %ju kB\n" + "Buffers: %ju kB\n" + "Cached: %ju kB\n", + &total, &unused, &buffers, &buffers, &cached)); + + int usage = 100 * (total - unused - buffers - cached) / total; + fclose(meminfo); + + free(block->text.text); + + char str[100]; + sprintf(str, "%d", usage); + + block->text.text = str_replace(block->state, "%{ram}", str); + assert(block->text.text != NULL); +} + +static void block_ram_finalize(block_t *block) +{ + free(block->state); +} + +static bool block_ram_validate(block_t *block, const block_scheme_t *scheme) +{ + block->state = block->text.text; + block->text.text = NULL; + + if (block->state == NULL) { + log_error("Block '%s' requires key '%s'", block->label, "text"); + return false; + } + + if (strstr(block->state, "%{ram}") != NULL) + log_warn("Block '%s' does not have a ram format", block->label); + + return true; +} + const block_scheme_t block_ram_scheme = { .name = "ram", .block = { .type = BLOCK_TEXT, + .update_interval = { + .tv_sec = 1, + .tv_nsec = 0, + }, + .update_cb = block_ram_update, + .finalize_cb = block_ram_finalize, }, - .size = 0, + .size = sizeof(char *), .entries = NULL, - .verify = NULL, + .validate = block_ram_validate, }; |
