Compare commits

..

No commits in common. "774894486fc7ee7f31b4f486750a60641525e2f7" and "57a7653632ba15aa0fdd8cbe1831363e4247996d" have entirely different histories.

37 changed files with 58 additions and 199 deletions

View File

@ -1,6 +1,6 @@
ISC License ISC License
Copyright 2016-2026 Aaron Marcher <me@drkhsh.at> Copyright 2016-2022 Aaron Marcher <me@drkhsh.at>
Copyright 2016 Roy Freytag <rfreytag@hs-mittweida.de> Copyright 2016 Roy Freytag <rfreytag@hs-mittweida.de>
Copyright 2016 Vincent Loupmon <vincentloupmon@gmail.com> Copyright 2016 Vincent Loupmon <vincentloupmon@gmail.com>
@ -21,7 +21,7 @@ Copyright 2018 Ian Remmler <ian@remmler.org>
Copyright 2016-2019 Joerg Jung <jung@openbsd.org> Copyright 2016-2019 Joerg Jung <jung@openbsd.org>
Copyright 2019 Ryan Kes <alrayyes@gmail.com> Copyright 2019 Ryan Kes <alrayyes@gmail.com>
Copyright 2019 Cem Keylan <cem@ckyln.com> Copyright 2019 Cem Keylan <cem@ckyln.com>
Copyright 2019 Spiros Thanasoulas <dsp@2f30.org> Copyright 2019 Dimitris Papastamos <dsp@2f30.org>
Copyright 2019-2022 Ingo Feinerer <feinerer@logic.at> Copyright 2019-2022 Ingo Feinerer <feinerer@logic.at>
Copyright 2020 Alexandre Ratchov <alex@caoua.org> Copyright 2020 Alexandre Ratchov <alex@caoua.org>
Copyright 2020 Mart Lubbers <mart@martlubbers.net> Copyright 2020 Mart Lubbers <mart@martlubbers.net>
@ -29,9 +29,6 @@ Copyright 2020 Daniel Moch <daniel@danielmoch.com>
Copyright 2022 Nickolas Raymond Kaczynski <nrk@disroot.org> Copyright 2022 Nickolas Raymond Kaczynski <nrk@disroot.org>
Copyright 2022 Patrick Iacob <iacobp@oregonstate.edu> Copyright 2022 Patrick Iacob <iacobp@oregonstate.edu>
Copyright 2021-2022 Steven Ward <planet36@gmail.com> Copyright 2021-2022 Steven Ward <planet36@gmail.com>
Copyright 2025 Joakim Sindholt <opensource@zhasha.com>
Copyright 2025 Al <eirann@disroot.org>
Copyright 2025 sewn <sewn@disroot.org>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

2
README
View File

@ -18,7 +18,7 @@ Features
- Available entropy - Available entropy
- Username/GID/UID - Username/GID/UID
- Hostname - Hostname
- IP address (IPv4 and IPv6), interface status - IP address (IPv4 and IPv6)
- Kernel version - Kernel version
- Keyboard indicators - Keyboard indicators
- Keymap - Keymap

View File

@ -62,7 +62,7 @@
{ "Not charging", "o" }, { "Not charging", "o" },
}; };
size_t i; size_t i;
char path[PATH_MAX], state[13]; char path[PATH_MAX], state[12];
if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0)
return NULL; return NULL;
@ -81,7 +81,7 @@
{ {
uintmax_t charge_now, current_now, m, h; uintmax_t charge_now, current_now, m, h;
double timeleft; double timeleft;
char path[PATH_MAX], state[13]; char path[PATH_MAX], state[12];
if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0)
return NULL; return NULL;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,45 +11,36 @@
ram_free(const char *unused) ram_free(const char *unused)
{ {
uintmax_t free; uintmax_t free;
FILE *fp;
if (!(fp = fopen("/proc/meminfo", "r"))) if (pscanf("/proc/meminfo",
"MemTotal: %ju kB\n"
"MemFree: %ju kB\n"
"MemAvailable: %ju kB\n",
&free, &free, &free) != 3)
return NULL; return NULL;
if (lscanf(fp, "MemFree:", "%ju kB", &free) != 1) {
fclose(fp);
return NULL;
}
fclose(fp);
return fmt_human(free * 1024, 1024); return fmt_human(free * 1024, 1024);
} }
const char * const char *
ram_perc(const char *unused) ram_perc(const char *unused)
{ {
uintmax_t total, free, buffers, cached, shmem, sreclaimable; uintmax_t total, free, buffers, cached;
int percent; int percent;
FILE *fp;
if (!(fp = fopen("/proc/meminfo", "r"))) if (pscanf("/proc/meminfo",
"MemTotal: %ju kB\n"
"MemFree: %ju kB\n"
"MemAvailable: %ju kB\n"
"Buffers: %ju kB\n"
"Cached: %ju kB\n",
&total, &free, &buffers, &buffers, &cached) != 5)
return NULL; return NULL;
if (lscanf(fp, "MemTotal:", "%ju kB", &total) != 1 ||
lscanf(fp, "MemFree:", "%ju kB", &free) != 1 ||
lscanf(fp, "Buffers:", "%ju kB", &buffers) != 1 ||
lscanf(fp, "Cached:", "%ju kB", &cached) != 1 ||
lscanf(fp, "Shmem:", "%ju kB", &shmem) != 1 ||
lscanf(fp, "SReclaimable:", "%ju kB", &sreclaimable) != 1) {
fclose(fp);
return NULL;
}
fclose(fp);
if (total == 0) if (total == 0)
return NULL; return NULL;
percent = 100 * (total - free - buffers - cached - sreclaimable + shmem) / total; percent = 100 * ((total - free) - (buffers + cached)) / total;
return bprintf("%d", percent); return bprintf("%d", percent);
} }
@ -68,24 +59,18 @@
const char * const char *
ram_used(const char *unused) ram_used(const char *unused)
{ {
uintmax_t total, free, buffers, cached, used, shmem, sreclaimable; uintmax_t total, free, buffers, cached, used;
FILE *fp;
if (!(fp = fopen("/proc/meminfo", "r"))) if (pscanf("/proc/meminfo",
"MemTotal: %ju kB\n"
"MemFree: %ju kB\n"
"MemAvailable: %ju kB\n"
"Buffers: %ju kB\n"
"Cached: %ju kB\n",
&total, &free, &buffers, &buffers, &cached) != 5)
return NULL; return NULL;
if (lscanf(fp, "MemTotal:", "%ju kB", &total) != 1 || used = (total - free - buffers - cached);
lscanf(fp, "MemFree:", "%ju kB", &free) != 1 ||
lscanf(fp, "Buffers:", "%ju kB", &buffers) != 1 ||
lscanf(fp, "Cached:", "%ju kB", &cached) != 1 ||
lscanf(fp, "Shmem:", "%ju kB", &shmem) != 1 ||
lscanf(fp, "SReclaimable:", "%ju kB", &sreclaimable) != 1) {
fclose(fp);
return NULL;
}
fclose(fp);
used = total - free - buffers - cached - sreclaimable + shmem;
return fmt_human(used * 1024, 1024); return fmt_human(used * 1024, 1024);
} }
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -89,8 +89,6 @@
if (c->addr == addr) if (c->addr == addr)
break; break;
} }
if (c == NULL)
return;
c->val = val; c->val = val;
} }
@ -219,33 +217,3 @@
return bprintf("%d", v & 0xff); return bprintf("%d", v & 0xff);
} }
#endif #endif
const char *
vol_perc_pw(const char *sink)
{
FILE *fp;
char buf[64], cmd[64];
double v;
if (esnprintf(cmd, sizeof(cmd), "wpctl get-volume %s", sink) < 0)
return NULL;
if (!(fp = popen(cmd, "r"))) {
warn("popen '%s':", cmd);
return NULL;
}
if (!fgets(buf, sizeof(buf), fp)) {
pclose(fp);
return NULL;
}
pclose(fp);
if (strstr(buf, "[MUTED]"))
return "mute";
if (sscanf(buf, "Volume: %lf", &v) != 1)
return NULL;
return bprintf("%d%%", (int)(v * 100 + 0.5));
}

Binary file not shown.

View File

@ -26,16 +26,24 @@
static char resp[4096]; static char resp[4096];
static char * static char *
findattr(int attr, const char *p, const char *e, size_t *len) findattr(int attr, char *p, char *e, size_t *len)
{ {
while (p < e) {
struct nlattr nla; struct nlattr nla;
size_t alen;
while ((size_t)(e-p) >= sizeof(nla)) {
memcpy(&nla, p, sizeof(nla)); memcpy(&nla, p, sizeof(nla));
if (nla.nla_len < NLA_HDRLEN)
return NULL;
if (nla.nla_type == attr) { if (nla.nla_type == attr) {
*len = nla.nla_len - NLA_HDRLEN; p += NLA_HDRLEN;
return (char *)(p + NLA_HDRLEN); *len = nla.nla_len-NLA_HDRLEN;
return (size_t)(e-p)>=*len?p:NULL;
} }
p += NLA_ALIGN(nla.nla_len); alen = NLA_ALIGN(nla.nla_len);
if ((size_t)(e-p) < alen)
return NULL;
p += alen;
} }
return NULL; return NULL;
} }
@ -89,10 +97,9 @@
} }
if ((size_t)r <= sizeof(ctrl)) if ((size_t)r <= sizeof(ctrl))
return 0; return 0;
p = findattr(CTRL_ATTR_FAMILY_ID, resp + sizeof(ctrl), resp + r, &len); p = findattr(CTRL_ATTR_FAMILY_ID, resp+sizeof(ctrl), resp+r, &len);
if (p && len == 2) if (p && len == 2)
memcpy(&id, p, 2); memcpy(&id, p, 2);
return id; return id;
} }
@ -110,11 +117,11 @@
} }
if (strcmp(ifr.ifr_name, interface) != 0) { if (strcmp(ifr.ifr_name, interface) != 0) {
strcpy(ifr.ifr_name, interface); strcpy(ifr.ifr_name, interface);
}
if (ioctl(ifsock, SIOCGIFINDEX, &ifr) != 0) { if (ioctl(ifsock, SIOCGIFINDEX, &ifr) != 0) {
warn("ioctl 'SIOCGIFINDEX':"); warn("ioctl 'SIOCGIFINDEX':");
return -1; return -1;
} }
}
return ifr.ifr_ifindex; return ifr.ifr_ifindex;
} }
@ -165,12 +172,11 @@
return NULL; return NULL;
} }
if ((size_t)r <= NLMSG_HDRLEN + GENL_HDRLEN) if ((size_t)r <= NLMSG_HDRLEN+GENL_HDRLEN)
return NULL; return NULL;
p = findattr(NL80211_ATTR_SSID, resp + NLMSG_HDRLEN + GENL_HDRLEN, resp + r, &len); p = findattr(NL80211_ATTR_SSID, resp+NLMSG_HDRLEN+GENL_HDRLEN, resp+r, &len);
if (p) if (p)
p[len] = 0; p[len] = 0;
return p; return p;
} }
@ -182,9 +188,8 @@
uint16_t fam = nl80211fam(); uint16_t fam = nl80211fam();
ssize_t r; ssize_t r;
size_t len; size_t len;
char req[NLMSG_HDRLEN + GENL_HDRLEN + NLA_HDRLEN + NLA_ALIGN(4)] = {0}, *p = req, *e; char req[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(4)] = {0}, *p = req, *e;
int idx = ifindex(interface); int idx = ifindex(interface);
if (idx < 0) { if (idx < 0) {
fprintf(stderr, "interface %s not found\n", interface); fprintf(stderr, "interface %s not found\n", interface);
return NULL; return NULL;
@ -204,17 +209,16 @@
}, sizeof(struct genlmsghdr)); }, sizeof(struct genlmsghdr));
p += GENL_HDRLEN; p += GENL_HDRLEN;
memcpy(p, &(struct nlattr){ memcpy(p, &(struct nlattr){
.nla_len = NLA_HDRLEN + 4, .nla_len = NLA_HDRLEN+4,
.nla_type = NL80211_ATTR_IFINDEX, .nla_type = NL80211_ATTR_IFINDEX,
}, sizeof(struct nlattr)); }, sizeof(struct nlattr));
p += NLA_HDRLEN; p += NLA_HDRLEN;
memcpy(p, &idx, 4); memcpy(p, &(uint32_t){idx}, 4);
if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) {
warn("send 'AF_NETLINK':"); warn("send 'AF_NETLINK':");
return NULL; return NULL;
} }
*strength = 0; *strength = 0;
while (1) { while (1) {
r = recv(nlsock, resp, sizeof(resp), 0); r = recv(nlsock, resp, sizeof(resp), 0);
@ -224,11 +228,9 @@
} }
if ((size_t)r < sizeof(hdr)) if ((size_t)r < sizeof(hdr))
return NULL; return NULL;
for (p = resp; p != resp+r && (size_t)(resp+r-p) >= sizeof(hdr); p = e) {
for (p = resp; p != resp + r && (size_t)(resp + r-p) >= sizeof(hdr); p = e) {
memcpy(&hdr, p, sizeof(hdr)); memcpy(&hdr, p, sizeof(hdr));
e = resp + r - p < hdr.nlmsg_len ? resp + r : p + hdr.nlmsg_len; e = resp+r-p<hdr.nlmsg_len?resp+r:p+hdr.nlmsg_len;
if (!*strength && hdr.nlmsg_len > NLMSG_HDRLEN+GENL_HDRLEN) { if (!*strength && hdr.nlmsg_len > NLMSG_HDRLEN+GENL_HDRLEN) {
p += NLMSG_HDRLEN+GENL_HDRLEN; p += NLMSG_HDRLEN+GENL_HDRLEN;
p = findattr(NL80211_ATTR_STA_INFO, p, e, &len); p = findattr(NL80211_ATTR_STA_INFO, p, e, &len);
@ -238,7 +240,7 @@
snprintf(strength, sizeof(strength), "%d", RSSI_TO_PERC(*p)); snprintf(strength, sizeof(strength), "%d", RSSI_TO_PERC(*p));
} }
if (hdr.nlmsg_type == NLMSG_DONE) if (hdr.nlmsg_type == NLMSG_DONE)
return *strength ? strength : NULL; return *strength?strength:NULL;
} }
} }
} }

Binary file not shown.

View File

@ -66,8 +66,5 @@ static const char unknown_str[] = "n/a";
*/ */
static const struct arg args[] = { static const struct arg args[] = {
/* function format argument */ /* function format argument */
{ wifi_perc, " wifi %s%% |", "wlan0" }, { datetime, "%s", "%F %T" },
{ battery_perc, " bat %s%% |", "BAT0" },
{ vol_perc_pw, " vol %s |", "@DEFAULT_AUDIO_SINK@" },
{ datetime, " %s", "%F %T" },
}; };

View File

@ -1,70 +0,0 @@
/* See LICENSE file for copyright and license details. */
/* interval between updates (in ms) */
const unsigned int interval = 1000;
/* text to show if no value can be retrieved */
static const char unknown_str[] = "n/a";
/* maximum output string length */
#define MAXLEN 2048
/*
* function description argument (example)
*
* battery_perc battery percentage battery name (BAT0)
* NULL on OpenBSD/FreeBSD
* battery_remaining battery remaining HH:MM battery name (BAT0)
* NULL on OpenBSD/FreeBSD
* battery_state battery charging state battery name (BAT0)
* NULL on OpenBSD/FreeBSD
* cat read arbitrary file path
* cpu_freq cpu frequency in MHz NULL
* cpu_perc cpu usage in percent NULL
* datetime date and time format string (%F %T)
* disk_free free disk space in GB mountpoint path (/)
* disk_perc disk usage in percent mountpoint path (/)
* disk_total total disk space in GB mountpoint path (/)
* disk_used used disk space in GB mountpoint path (/)
* entropy available entropy NULL
* gid GID of current user NULL
* hostname hostname NULL
* ipv4 IPv4 address interface name (eth0)
* ipv6 IPv6 address interface name (eth0)
* kernel_release `uname -r` NULL
* keyboard_indicators caps/num lock indicators format string (c?n?)
* see keyboard_indicators.c
* keymap layout (variant) of current NULL
* keymap
* load_avg load average NULL
* netspeed_rx receive network speed interface name (wlan0)
* netspeed_tx transfer network speed interface name (wlan0)
* num_files number of files in a directory path
* (/home/foo/Inbox/cur)
* ram_free free memory in GB NULL
* ram_perc memory usage in percent NULL
* ram_total total memory size in GB NULL
* ram_used used memory in GB NULL
* run_command custom shell command command (echo foo)
* swap_free free swap in GB NULL
* swap_perc swap usage in percent NULL
* swap_total total swap size in GB NULL
* swap_used used swap in GB NULL
* temp temperature in degree celsius sensor file
* (/sys/class/thermal/...)
* NULL on OpenBSD
* thermal zone on FreeBSD
* (tz0, tz1, etc.)
* uid UID of current user NULL
* up interface is running interface name (eth0)
* uptime system uptime NULL
* username username of current user NULL
* vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer)
* NULL on OpenBSD/FreeBSD
* wifi_essid WiFi ESSID interface name (wlan0)
* wifi_perc WiFi signal in percent interface name (wlan0)
*/
static const struct arg args[] = {
/* function format argument */
{wifi_essid, "%s", "wlan0"}, {wifi_perc, " %s%% |", "wlan0"}, {battery_perc, " bat %s%%", "BAT0"}, {battery_state, "%s |", "BAT0"}, {vol_perc_pw, " vol %s |", "@DEFAULT_AUDIO_SINK@"}, {datetime, " %s", "%F %T"},
};

View File

@ -1,5 +1,5 @@
# slstatus version # slstatus version
VERSION = 1.1 VERSION = 1.0
# customize below to fit your system # customize below to fit your system

BIN
slstatus

Binary file not shown.

View File

@ -79,7 +79,6 @@ const char *username(const char *unused);
/* volume */ /* volume */
const char *vol_perc(const char *card); const char *vol_perc(const char *card);
const char *vol_perc_pw(const char *sink);
/* wifi */ /* wifi */
const char *wifi_essid(const char *interface); const char *wifi_essid(const char *interface);

Binary file not shown.

17
util.c
View File

@ -139,20 +139,3 @@ pscanf(const char *path, const char *fmt, ...)
return (n == EOF) ? -1 : n; return (n == EOF) ? -1 : n;
} }
int
lscanf(FILE *fp, const char *key, const char *fmt, void *res)
{
int n;
char line[256];
n = -1;
while (fgets(line, sizeof(line), fp))
if (strncmp(line, key, strlen(key)) == 0) {
n = sscanf(line + strlen(key), fmt, res);
break;
}
rewind(fp);
return (n == 1) ? 1 : -1;
}

2
util.h
View File

@ -1,6 +1,5 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
extern char buf[1024]; extern char buf[1024];
@ -15,4 +14,3 @@ int esnprintf(char *str, size_t size, const char *fmt, ...);
const char *bprintf(const char *fmt, ...); const char *bprintf(const char *fmt, ...);
const char *fmt_human(uintmax_t num, int base); const char *fmt_human(uintmax_t num, int base);
int pscanf(const char *path, const char *fmt, ...); int pscanf(const char *path, const char *fmt, ...);
int lscanf(FILE *fp, const char *key, const char *fmt, void *res);

BIN
util.o

Binary file not shown.