sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

slstatus-dyn_battery-20260102-8723e8b.diff (5558B)


      1 From 6316c8cb7b2b92098907943223ffe1a748359146 Mon Sep 17 00:00:00 2001
      2 From: Madison Lynch <madi@mxdi.xyz>
      3 Date: Fri, 2 Jan 2026 04:33:17 -0800
      4 Subject: [PATCH] Code refactor + Improved memory safety
      5 
      6 ---
      7  Makefile                 |   1 +
      8  components/dyn_battery.c | 124 +++++++++++++++++++++++++++++++++++++++
      9  config.def.h             |   1 +
     10  slstatus.h               |   3 +
     11  4 files changed, 129 insertions(+)
     12  create mode 100644 components/dyn_battery.c
     13 
     14 diff --git a/Makefile b/Makefile
     15 index 7a18274..d1b24dd 100644
     16 --- a/Makefile
     17 +++ b/Makefile
     18 @@ -11,6 +11,7 @@ COM =\
     19  	components/cpu\
     20  	components/datetime\
     21  	components/disk\
     22 +	components/dyn_battery\
     23  	components/entropy\
     24  	components/hostname\
     25  	components/ip\
     26 diff --git a/components/dyn_battery.c b/components/dyn_battery.c
     27 new file mode 100644
     28 index 0000000..cc87fc1
     29 --- /dev/null
     30 +++ b/components/dyn_battery.c
     31 @@ -0,0 +1,124 @@
     32 +/* Written by Lukas Lynch <madi@mxdi.xyz> */
     33 +/* Only Linux is supported */
     34 +#include <stdio.h>
     35 +#include <stdlib.h>
     36 +#include <stdbool.h>
     37 +#include <string.h>
     38 +#include <dirent.h>
     39 +
     40 +#include "../util.h"
     41 +#include "../slstatus.h"
     42 +
     43 +#define BAT_PREFIX "BAT"
     44 +#define BAT_DIR "/sys/class/power_supply"
     45 +
     46 +static bool err;
     47 +static const char *err_str = "err";
     48 +
     49 +/**
     50 +* Calculates the number of digits in a given positive integer.
     51 +*/
     52 +static size_t
     53 +count_digits(const unsigned int input) {
     54 +    size_t count = 0;
     55 +    unsigned int n = input;
     56 +
     57 +    while(n/10 != 0)
     58 +        count++;
     59 +
     60 +    return count+1;
     61 +}
     62 +
     63 +/**
     64 +* Counts number of batteries detected by system.
     65 +*
     66 +* @return Unsigned integer denoting the number of detected batteries
     67 +* @author Lukas Lynch
     68 +*/
     69 +static unsigned int
     70 +count_batteries(void) {
     71 +    const size_t bat_prefix_s = strlen(BAT_PREFIX);
     72 +    DIR *dir = opendir(BAT_DIR);
     73 +    if(!dir) {
     74 +        fprintf(stderr, "dyn_battery: Failed to open %s\n", BAT_DIR);
     75 +        err = true;
     76 +        return 0;
     77 +    }
     78 +
     79 +    unsigned int batc = 0;
     80 +    struct dirent *entry;
     81 +    while((entry = readdir(dir)))
     82 +        if(
     83 +            strlen(entry->d_name) > bat_prefix_s &&
     84 +            strncmp(entry->d_name, BAT_PREFIX, bat_prefix_s) == 0
     85 +        ) batc++;
     86 +
     87 +    (void) closedir(dir);
     88 +    return batc;
     89 +}
     90 +
     91 +/**
     92 +* Displays the status and capacity of a dynamic amount of batteries (i.e.
     93 +* laptops may have secondary external batteries).
     94 +*
     95 +* @param  fmt format string to use for each battery display. ordered key:
     96 +*             %u: battery number || %s: battery state || %s battery capacity
     97 +* @return string containing the status and capacities of all detected batteries
     98 +* @author Lukas Lynch
     99 +*/
    100 +const char *
    101 +dyn_battery(const char *fmt) {
    102 +    err = false;
    103 +    const size_t fmt_s = strlen(fmt);
    104 +    const unsigned int batc = count_batteries();
    105 +
    106 +    if(err) // err set by count_batteries()
    107 +        return err_str;
    108 +
    109 +    if(batc == 0) 
    110 +        return NULL;
    111 +
    112 +    // We need the amount of digits in bat_c for displaying it in strings
    113 +    const size_t batc_digits = count_digits(batc);
    114 +
    115 +    char buf[
    116 +          (batc * (fmt_s - 2)) // bat count * (format string - "%u" format specifier)
    117 +        + (batc * batc_digits) // bat count * digits in bat count
    118 +        + 1                    // NULL byte
    119 +    ];
    120 +
    121 +    // Fill buffer with 0s, otherwise displacement calculations below can fail
    122 +    memset(buf, 0, sizeof(buf));
    123 +
    124 +    /*
    125 +    * The displacement variable will be updated with the current string length,
    126 +    * which is independent from the buffer size, in order to allow us to write
    127 +    * to the buffer without overwriting.
    128 +    */
    129 +    unsigned int displacement = 0;
    130 +    for(unsigned int i=0; i<batc; i++) {
    131 +        // Length of BAT_PREFIX + number of digits in bat count + 1 (NULL byte)
    132 +        char bat[strlen(BAT_PREFIX) + batc_digits + 1];
    133 +        (void) sprintf(bat, "%s%u", BAT_PREFIX, i);
    134 +
    135 +        // Add battery info to output buffer
    136 +        displacement += sprintf(
    137 +            buf + displacement, // Write into buffer after previous writes
    138 +            fmt,                // Format string specified by config.h
    139 +            i,
    140 +            battery_state(bat), // See components/battery.c
    141 +            battery_perc(bat)   // See components/battery.c
    142 +        );
    143 +
    144 +        // Add space between battery entries
    145 +        buf[displacement++] = ' ';
    146 +    }
    147 +
    148 +    // Remove extra space after last battery entry
    149 +    buf[--displacement] = '\0';
    150 +
    151 +    return bprintf("%s", buf);
    152 +}
    153 +
    154 +#undef BAT_DIR
    155 +#undef BAT_PREFIX
    156 \ No newline at end of file
    157 diff --git a/config.def.h b/config.def.h
    158 index 100093e..7f26909 100644
    159 --- a/config.def.h
    160 +++ b/config.def.h
    161 @@ -26,6 +26,7 @@ static const char unknown_str[] = "n/a";
    162   * disk_perc           disk usage in percent           mountpoint path (/)
    163   * disk_total          total disk space in GB          mountpoint path (/)
    164   * disk_used           used disk space in GB           mountpoint path (/)
    165 + * dyn_battery         displays the name, state and    format string (%u, %s, %s)
    166   * entropy             available entropy               NULL
    167   * gid                 GID of current user             NULL
    168   * hostname            hostname                        NULL
    169 diff --git a/slstatus.h b/slstatus.h
    170 index 394281c..6beeaec 100644
    171 --- a/slstatus.h
    172 +++ b/slstatus.h
    173 @@ -21,6 +21,9 @@ const char *disk_perc(const char *path);
    174  const char *disk_total(const char *path);
    175  const char *disk_used(const char *path);
    176  
    177 +/* dyn_battery */
    178 +const char *dyn_battery(const char *fmt);
    179 +
    180  /* entropy */
    181  const char *entropy(const char *unused);
    182  
    183 -- 
    184 2.52.0
    185