Compare commits

...

10 Commits

Author SHA1 Message Date
lucic71 7f523c33d9 Add link to FreeBSD implementation 2022-07-20 13:09:12 +00:00
lucic71 2f9efa9ed3 Add some more requirements for OpenBSD 2022-07-20 14:24:24 +03:00
lucic71 c1b088b21f Handle memory used and threshold options 2022-07-20 14:02:45 +03:00
lucic71 b3a120611f Make local function static 2022-07-20 13:50:08 +03:00
lucic71 685817c17e Delete bad code 2022-07-20 13:49:51 +03:00
lucic71 547683e84f Use bytes instead of kbytes 2022-07-20 13:49:19 +03:00
lucic71 a6ca7b4f2f Get memory info in a different function 2022-07-20 09:50:49 +03:00
lucic71 6b28312230 Add function that prints formatted output
This function will be called from all architectures
2022-07-20 09:28:53 +03:00
lucic71 0ade29c99b Document some of the requirements on OpenBSD 2022-07-19 23:59:33 +03:00
lucic71 abba2c89ab Fix platform dependent field 2022-07-19 23:56:57 +03:00
3 changed files with 122 additions and 77 deletions

View File

@ -25,6 +25,11 @@ On debian-based systems, the following line will install all requirements:
apt-get install autoconf libconfuse-dev libyajl-dev libasound2-dev libiw-dev asciidoc libpulse-dev libnl-genl-3-dev meson
```
On OpenBSD, the following line will install some of the requirements:
```bash
pkg_add autoconf libconfuse libyajl asciidoc pluseaudio meson
```
## Upstream
i3status is developed at https://github.com/i3/i3status

View File

@ -45,14 +45,12 @@ struct cpu_usage {
long system;
long idle;
long total;
int spin;
#else
int user;
int nice;
int system;
int idle;
#if defined(__OpenBSD__)
int spin;
#endif
int total;
#endif
};

View File

@ -5,6 +5,8 @@
#include <stdlib.h>
#include <yajl/yajl_gen.h>
#include <yajl/yajl_version.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include "i3status.h"
#define MAX_DECIMALS 4
@ -12,12 +14,20 @@
#define BINARY_BASE 1024UL
#if defined(__linux__)
static const char *const iec_symbols[] = {"B", "KiB", "MiB", "GiB", "TiB"};
#define MAX_EXPONENT ((sizeof iec_symbols / sizeof *iec_symbols) - 1)
#endif
#if defined(__linux__)
struct print_mem_info {
unsigned long ram_total;
unsigned long ram_free;
unsigned long ram_used;
unsigned long ram_available;
unsigned long ram_buffers;
unsigned long ram_cached;
unsigned long ram_shared;
char *output_color;
};
/*
* Prints the given amount of bytes in a human readable manner.
*
@ -40,9 +50,11 @@ static int print_bytes_human(char *outwalk, unsigned long bytes, const char *uni
static int print_percentage(char *outwalk, float percent) {
return snprintf(outwalk, STRING_SIZE, "%.1f%s", percent, pct_mark);
}
#endif
#if defined(__linux__)
static unsigned long page2byte (unsigned pageCnt) {
return pageCnt * getpagesize ();
}
/*
* Convert a string to its absolute representation based on the total
* memory of `mem_total`.
@ -84,22 +96,39 @@ static unsigned long memory_absolute(const char *mem_amount, const unsigned long
return amount;
}
#endif
void print_memory(memory_ctx_t *ctx) {
static void handle_used_method(struct print_mem_info *minfo, memory_ctx_t *ctx) {
if (BEGINS_WITH(ctx->memory_used_method, "memavailable")) {
minfo->ram_used = minfo->ram_total - minfo->ram_available;
} else if (BEGINS_WITH(ctx->memory_used_method, "classical")) {
minfo->ram_used = minfo->ram_total - minfo->ram_free - minfo->ram_buffers - minfo->ram_cached;
} else {
die("Unexpected value: memory_used_method = %s", ctx->memory_used_method);
}
}
static void handle_threshold(struct print_mem_info *minfo, memory_ctx_t *ctx) {
if (ctx->threshold_degraded) {
const unsigned long threshold = memory_absolute(ctx->threshold_degraded, minfo->ram_total);
if (minfo->ram_available < threshold) {
minfo->output_color = "color_degraded";
}
}
if (ctx->threshold_critical) {
const unsigned long threshold = memory_absolute(ctx->threshold_critical, minfo->ram_total);
if (minfo->ram_available < threshold) {
minfo->output_color = "color_bad";
}
}
}
static void get_memory_info(struct print_mem_info *minfo, memory_ctx_t *ctx) {
char *outwalk = ctx->buf;
#if defined(__linux__)
const char *selected_format = ctx->format;
const char *output_color = NULL;
int unread_fields = 6;
unsigned long ram_total;
unsigned long ram_free;
unsigned long ram_available;
unsigned long ram_buffers;
unsigned long ram_cached;
unsigned long ram_shared;
minfo->output_color = NULL
FILE *file = fopen("/proc/meminfo", "r");
if (!file) {
@ -107,17 +136,17 @@ void print_memory(memory_ctx_t *ctx) {
}
for (char line[128]; fgets(line, sizeof line, file);) {
if (BEGINS_WITH(line, "MemTotal:")) {
ram_total = strtoul(line + strlen("MemTotal:"), NULL, 10);
minfo->ram_total = strtoul(line + strlen("MemTotal:"), NULL, 10);
} else if (BEGINS_WITH(line, "MemFree:")) {
ram_free = strtoul(line + strlen("MemFree:"), NULL, 10);
minfo->ram_free = strtoul(line + strlen("MemFree:"), NULL, 10);
} else if (BEGINS_WITH(line, "MemAvailable:")) {
ram_available = strtoul(line + strlen("MemAvailable:"), NULL, 10);
minfo->ram_available = strtoul(line + strlen("MemAvailable:"), NULL, 10);
} else if (BEGINS_WITH(line, "Buffers:")) {
ram_buffers = strtoul(line + strlen("Buffers:"), NULL, 10);
minfo->ram_buffers = strtoul(line + strlen("Buffers:"), NULL, 10);
} else if (BEGINS_WITH(line, "Cached:")) {
ram_cached = strtoul(line + strlen("Cached:"), NULL, 10);
minfo->ram_cached = strtoul(line + strlen("Cached:"), NULL, 10);
} else if (BEGINS_WITH(line, "Shmem:")) {
ram_shared = strtoul(line + strlen("Shmem:"), NULL, 10);
minfo->ram_shared = strtoul(line + strlen("Shmem:"), NULL, 10);
} else {
continue;
}
@ -132,43 +161,51 @@ void print_memory(memory_ctx_t *ctx) {
}
// Values are in kB, convert them to B.
ram_total *= 1024UL;
ram_free *= 1024UL;
ram_available *= 1024UL;
ram_buffers *= 1024UL;
ram_cached *= 1024UL;
ram_shared *= 1024UL;
minfo->ram_total *= 1024UL;
minfo->ram_free *= 1024UL;
minfo->ram_available *= 1024UL;
minfo->ram_buffers *= 1024UL;
minfo->ram_cached *= 1024UL;
minfo->ram_shared *= 1024UL;
unsigned long ram_used;
if (BEGINS_WITH(ctx->memory_used_method, "memavailable")) {
ram_used = ram_total - ram_available;
} else if (BEGINS_WITH(ctx->memory_used_method, "classical")) {
ram_used = ram_total - ram_free - ram_buffers - ram_cached;
} else {
die("Unexpected value: memory_used_method = %s", ctx->memory_used_method);
handle_used_method(minfo, ctx);
handle_threshold(minfo, ctx);
error:
OUTPUT_FULL_TEXT("can't read memory");
fputs("i3status: Cannot read system memory using /proc/meminfo\n", stderr);
#elif defined(__OpenBSD__)
int mib [] = { CTL_VM, VM_UVMEXP };
struct uvmexp our_uvmexp;
size_t size = sizeof (our_uvmexp);
if (sysctl (mib, 2, &our_uvmexp, &size, NULL, 0) < 0) {
OUTPUT_FULL_TEXT("");
fputs("i3status: cannot get memory info!\n", stderr);
return;
}
if (ctx->threshold_degraded) {
const unsigned long threshold = memory_absolute(ctx->threshold_degraded, ram_total);
if (ram_available < threshold) {
output_color = "color_degraded";
}
}
minfo->ram_total = page2byte(our_uvmexp.npages);
minfo->ram_free = page2byte(our_uvmexp.free + our_uvmexp.inactive);
minfo->ram_used = page2byte(our_uvmexp.npages - our_uvmexp.free - our_uvmexp.inactive);
minfo->ram_available = minfo->ram_free;
minfo->ram_buffers = 0;
minfo->ram_cached = 0;
minfo->ram_shared = 0;
minfo->output_color = NULL;
if (ctx->threshold_critical) {
const unsigned long threshold = memory_absolute(ctx->threshold_critical, ram_total);
if (ram_available < threshold) {
output_color = "color_bad";
}
}
if (output_color) {
START_COLOR(output_color);
if (ctx->format_degraded)
selected_format = ctx->format_degraded;
}
handle_used_method(minfo, ctx);
handle_threshold(minfo, ctx);
#else
// For FreeBSD implementation see: https://bal0n.es/git/slstatus/file/components/ram.c.html
OUTPUT_FULL_TEXT("");
fputs("i3status: Memory status information is not supported on this system\n", stderr);
#endif
}
static void print_formatted_memory(struct print_mem_info *minfo, memory_ctx_t *ctx) {
char *outwalk = ctx->buf;
const char *selected_format = ctx->format;
char string_ram_total[STRING_SIZE];
char string_ram_used[STRING_SIZE];
char string_ram_free[STRING_SIZE];
@ -179,15 +216,22 @@ void print_memory(memory_ctx_t *ctx) {
char string_percentage_used[STRING_SIZE];
char string_percentage_shared[STRING_SIZE];
print_bytes_human(string_ram_total, ram_total, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_used, ram_used, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_free, ram_free, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_available, ram_available, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_shared, ram_shared, ctx->unit, ctx->decimals);
print_percentage(string_percentage_free, 100.0 * ram_free / ram_total);
print_percentage(string_percentage_available, 100.0 * ram_available / ram_total);
print_percentage(string_percentage_used, 100.0 * ram_used / ram_total);
print_percentage(string_percentage_shared, 100.0 * ram_shared / ram_total);
if (minfo->output_color) {
START_COLOR(minfo->output_color);
if (ctx->format_degraded)
selected_format = ctx->format_degraded;
}
print_bytes_human(string_ram_total, minfo->ram_total, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_used, minfo->ram_used, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_free, minfo->ram_free, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_available, minfo->ram_available, ctx->unit, ctx->decimals);
print_bytes_human(string_ram_shared, minfo->ram_shared, ctx->unit, ctx->decimals);
print_percentage(string_percentage_free, 100.0 * minfo->ram_free / minfo->ram_total);
print_percentage(string_percentage_available, 100.0 * minfo->ram_available / minfo->ram_total);
print_percentage(string_percentage_used, 100.0 * minfo->ram_used / minfo->ram_total);
print_percentage(string_percentage_shared, 100.0 * minfo->ram_shared / minfo->ram_total);
placeholder_t placeholders[] = {
{.name = "%total", .value = string_ram_total},
@ -205,17 +249,15 @@ void print_memory(memory_ctx_t *ctx) {
OUTPUT_FORMATTED;
free(formatted);
if (output_color)
if (minfo->output_color)
END_COLOR;
OUTPUT_FULL_TEXT(ctx->buf);
return;
error:
OUTPUT_FULL_TEXT("can't read memory");
fputs("i3status: Cannot read system memory using /proc/meminfo\n", stderr);
#else
OUTPUT_FULL_TEXT("");
fputs("i3status: Memory status information is not supported on this system\n", stderr);
#endif
}
void print_memory(memory_ctx_t *ctx) {
struct print_mem_info minfo;
get_memory_info(&minfo, ctx);
print_formatted_memory(&minfo, ctx);
}