status

statusbar program for dwm
git clone anongit@rnpnr.xyz:status.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 244b48cc3ef715e190ecdaac511f302404eb8365
Parent: 14800b7b382676f2e8e8760ff99145124337f8b3
Author: Randy Palamar
Date:   Tue, 24 Dec 2024 10:59:51 -0700

battery_info: remove 4K stack buffer

We have an Arena for this purpose and we can determine the needed
size at compile time so we don't need to do this.

Diffstat:
Mblocks/linux/battery_info.c | 46++++++++++++++++++++++++++++++++++------------
Mbuild.sh | 5+++--
Mconfig.def.h | 2+-
Mstatus.c | 21+++++++++++++++++++++
4 files changed, 59 insertions(+), 15 deletions(-)

diff --git a/blocks/linux/battery_info.c b/blocks/linux/battery_info.c @@ -1,13 +1,13 @@ /* See LICENSE for license details. */ struct bat_arg { - char *bat; /* BAT name (ex. BAT0) */ + s8 bat; /* BAT name (ex. s8("BAT0")) */ char *pre; /* prefix for percentages less than thres */ char *suf; /* suffix for percentages less than thres */ i32 thres; /* % threshold to consider low (-1 to disable) */ f32 interval; /* [s] */ }; -struct linux_battery_data { i64 energy_full; f32 timer; }; +struct linux_battery_data { Stream path_base; i64 energy_full; f32 timer; }; static BLOCK_UPDATE_FN(battery_info_update) { @@ -19,29 +19,34 @@ static BLOCK_UPDATE_FN(battery_info_update) char *pre = ba->pre ? ba->pre : ""; char *suf = ba->suf ? ba->suf : ""; - char path[4096], state[12]; + char state[12]; i32 h, m; i64 power_now, energy_now; f64 timeleft; - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/energy_now", ba->bat); - if (pscanf(path, "%ld", &energy_now) != 1) + size sidx = lbd->path_base.write_index; + + stream_push_s8(&lbd->path_base, s8("/energy_now")); + if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &energy_now) != 1) energy_now = 0; + lbd->path_base.write_index = sidx; f32 percent = (100 * energy_now / (f64)lbd->energy_full) + 0.5; b32 warn = percent < ba->thres; - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/status", ba->bat); - if (pscanf(path, "%12s", &state) != 1) + stream_push_s8(&lbd->path_base, s8("/status")); + if (pscanf(stream_ensure_c_str(&lbd->path_base), "%12s", &state) != 1) snprintf(state, sizeof(state), "Unknown"); + lbd->path_base.write_index = sidx; /* NOTE(rnp): proper devices use negative power to indicate discharging but that * is not always the case. The status string can mostly be trusted */ if (!strcmp(state, "Discharging")) { - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/power_now", ba->bat); - if (pscanf(path, "%ld", &power_now) != 1) + stream_push_s8(&lbd->path_base, s8("/power_now")); + if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &power_now) != 1) power_now = 1; + lbd->path_base.write_index = sidx; timeleft = energy_now / (f64)ABS(power_now); h = timeleft; @@ -60,16 +65,33 @@ static BLOCK_UPDATE_FN(battery_info_update) return 1; } +#define LINUX_BAT_INFO_STRS \ + X("/energy_full") \ + X("/energy_now") \ + X("/power_now") \ + X("/status") + static BLOCK_INIT_FN(battery_info_init) { struct bat_arg *ba = b->arg; struct linux_battery_data *lbd; b->user_data = lbd = push_struct(a, struct linux_battery_data); - char path[4096]; - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/energy_full", ba->bat); - if (pscanf(path, "%ld", &lbd->energy_full) != 1) + size max_length = 0; + #define X(cstr) if (sizeof(cstr) > max_length) max_length = sizeof(cstr); + LINUX_BAT_INFO_STRS + #undef X + + size needed_length = max_length + sizeof("/sys/class/power_supply/") - 1 + ba->bat.len; + lbd->path_base = stream_alloc(a, needed_length); + + stream_push_s8(&lbd->path_base, s8("/sys/class/power_supply/")); + stream_push_s8(&lbd->path_base, ba->bat); + size sidx = lbd->path_base.write_index; + stream_push_s8(&lbd->path_base, s8("/energy_full")); + if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &lbd->energy_full) != 1) die("battery_info_init: failed to read battery capacity\n"); + lbd->path_base.write_index = sidx; battery_info_update(b, 1); } diff --git a/build.sh b/build.sh @@ -3,12 +3,13 @@ cflags="-march=native -O3 -std=c11 -Wall -pedantic" cflags="$cflags -D_XOPEN_SOURCE=500" cflags="$cflags -I /usr/X11R6/include" +#cflags="${cflags} -O0 -ggdb -D_DEBUG" ldflags="-lX11" #ldflags="$ldflags -lmpdclient" # needed for blocks/mpd.c #ldflags="$ldflags -lasound" # needed for blocks/linux/volume.c -echo "cflags: $cflags" -echo "ldflags: $ldflags" +#echo "cflags: $cflags" +#echo "ldflags: $ldflags" cc $cflags status.c $ldflags -o status diff --git a/config.def.h b/config.def.h @@ -14,7 +14,7 @@ // static struct vol_arg va = { "default", "Speaker" }; /* check blocks/xxx/battery_info.c for info */ -static struct bat_arg ba = {.bat = "BAT0", .interval = 30}; +static struct bat_arg ba = {.bat = s8("BAT0"), .interval = 30}; /* check blocks/date.c for info */ static struct date_arg da = {.fmt = "%R", .interval = 30}; diff --git a/status.c b/status.c @@ -62,6 +62,9 @@ typedef size_t usize; typedef struct { u8 *beg, *end; } Arena; +#define s8(s) (s8){.len = sizeof(s) - 1, .data = (u8 *)s} +typedef struct { size len; u8 *data; } s8; + typedef struct { u8 *buffer; i32 capacity; @@ -180,6 +183,24 @@ stream_alloc(Arena *a, size capacity) return result; } +static char * +stream_ensure_c_str(Stream *s) +{ + ASSERT(s->write_index < s->capacity); + s->buffer[s->write_index] = 0; + return (char *)s->buffer; +} + +static void +stream_push_s8(Stream *s, s8 str) +{ + s->errors |= s->capacity <= (s->write_index + str.len); + if (!s->errors) { + memcpy(s->buffer + s->write_index, str.data, str.len); + s->write_index += str.len; + } +} + static void add_file_watch(Arena *a, char *path, i32 block_index, block_update_fn *update_fn) {