diff options
| author | pml68 <contact@pml68.dev> | 2025-09-16 21:48:56 +0200 |
|---|---|---|
| committer | pml68 <contact@pml68.dev> | 2025-09-16 22:15:01 +0200 |
| commit | fd3a7cc487ad5dc36d99ccf46f9e3c6461687f99 (patch) | |
| tree | e1627f8ea07510d06a99ea55f275ae3b6e1919a7 /slstatus/components | |
| parent | chore: bump dwm and dmenu versions (diff) | |
| download | suckless-setup-fd3a7cc487ad5dc36d99ccf46f9e3c6461687f99.tar.gz | |
chore: sync slstatus with upstream
Diffstat (limited to 'slstatus/components')
| -rw-r--r-- | slstatus/components/ip.c | 26 | ||||
| -rw-r--r-- | slstatus/components/keymap.c | 4 | ||||
| -rw-r--r-- | slstatus/components/ram.c | 61 | ||||
| -rw-r--r-- | slstatus/components/wifi.c | 258 |
4 files changed, 268 insertions, 81 deletions
diff --git a/slstatus/components/ip.c b/slstatus/components/ip.c index 9476549..2cdad46 100644 --- a/slstatus/components/ip.c +++ b/slstatus/components/ip.c @@ -1,6 +1,7 @@ /* See LICENSE file for copyright and license details. */ #include <ifaddrs.h> #include <netdb.h> +#include <net/if.h> #include <stdio.h> #include <string.h> #if defined(__OpenBSD__) @@ -59,3 +60,28 @@ ipv6(const char *interface) { return ip(interface, AF_INET6); } + +const char * +up(const char *interface) +{ + struct ifaddrs *ifaddr, *ifa; + + if (getifaddrs(&ifaddr) < 0) { + warn("getifaddrs:"); + return NULL; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; + + if (!strcmp(ifa->ifa_name, interface)) { + freeifaddrs(ifaddr); + return ifa->ifa_flags & IFF_UP ? "up" : "down"; + } + } + + freeifaddrs(ifaddr); + + return NULL; +} diff --git a/slstatus/components/keymap.c b/slstatus/components/keymap.c index f8a2a47..22224f3 100644 --- a/slstatus/components/keymap.c +++ b/slstatus/components/keymap.c @@ -29,8 +29,8 @@ get_layout(char *syms, int grp_num) int grp; layout = NULL; - tok = strtok(syms, "+:"); - for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) { + tok = strtok(syms, "+:_"); + for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:_")) { if (!valid_layout_or_variant(tok)) { continue; } else if (strlen(tok) == 1 && isdigit(tok[0])) { diff --git a/slstatus/components/ram.c b/slstatus/components/ram.c index 15c4b74..bf71dcf 100644 --- a/slstatus/components/ram.c +++ b/slstatus/components/ram.c @@ -11,36 +11,45 @@ ram_free(const char *unused) { uintmax_t free; + FILE *fp; - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n", - &free, &free, &free) != 3) + if (!(fp = fopen("/proc/meminfo", "r"))) return NULL; + if (lscanf(fp, "MemFree:", "%ju kB", &free) != 1) { + fclose(fp); + return NULL; + } + + fclose(fp); return fmt_human(free * 1024, 1024); } const char * ram_perc(const char *unused) { - uintmax_t total, free, buffers, cached; + uintmax_t total, free, buffers, cached, shmem, sreclaimable; int percent; + FILE *fp; + + if (!(fp = fopen("/proc/meminfo", "r"))) + return NULL; - 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) + 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) return NULL; - percent = 100 * ((total - free) - (buffers + cached)) / total; + percent = 100 * (total - free - buffers - cached - sreclaimable + shmem) / total; return bprintf("%d", percent); } @@ -59,18 +68,24 @@ const char * ram_used(const char *unused) { - uintmax_t total, free, buffers, cached, used; + uintmax_t total, free, buffers, cached, used, shmem, sreclaimable; + FILE *fp; + + if (!(fp = fopen("/proc/meminfo", "r"))) + return NULL; - 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) + 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); - used = (total - free - buffers - cached); + used = total - free - buffers - cached - sreclaimable + shmem; return fmt_human(used * 1024, 1024); } #elif defined(__OpenBSD__) diff --git a/slstatus/components/wifi.c b/slstatus/components/wifi.c index 4543d32..23af201 100644 --- a/slstatus/components/wifi.c +++ b/slstatus/components/wifi.c @@ -15,86 +15,232 @@ (2 * (rssi + 100))) #if defined(__linux__) - #include <limits.h> - #include <linux/wireless.h> + #include <stdint.h> + #include <net/if.h> + #include <linux/netlink.h> + #include <linux/genetlink.h> + #include <linux/nl80211.h> + + static int nlsock = -1; + static uint32_t seq = 1; + static char resp[4096]; + + static char * + findattr(int attr, const char *p, const char *e, size_t *len) + { + while (p < e) { + struct nlattr nla; + memcpy(&nla, p, sizeof(nla)); + if (nla.nla_type == attr) { + *len = nla.nla_len - NLA_HDRLEN; + return (char *)(p + NLA_HDRLEN); + } + p += NLA_ALIGN(nla.nla_len); + } + return NULL; + } - #define NET_OPERSTATE "/sys/class/net/%s/operstate" + static uint16_t + nl80211fam(void) + { + static const char family[] = "nl80211"; + static uint16_t id; + ssize_t r; + size_t len; + char ctrl[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(sizeof(family))] = {0}, *p = ctrl; + + if (id) + return id; + + memcpy(p, &(struct nlmsghdr){ + .nlmsg_len = sizeof(ctrl), + .nlmsg_type = GENL_ID_CTRL, + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_seq = seq++, + .nlmsg_pid = 0, + }, sizeof(struct nlmsghdr)); + p += NLMSG_HDRLEN; + memcpy(p, &(struct genlmsghdr){ + .cmd = CTRL_CMD_GETFAMILY, + .version = 1, + }, sizeof(struct genlmsghdr)); + p += GENL_HDRLEN; + memcpy(p, &(struct nlattr){ + .nla_len = NLA_HDRLEN+sizeof(family), + .nla_type = CTRL_ATTR_FAMILY_NAME, + }, sizeof(struct nlattr)); + p += NLA_HDRLEN; + memcpy(p, family, sizeof(family)); + + if (nlsock < 0) + nlsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); + if (nlsock < 0) { + warn("socket 'AF_NETLINK':"); + return 0; + } + if (send(nlsock, ctrl, sizeof(ctrl), 0) != sizeof(ctrl)) { + warn("send 'AF_NETLINK':"); + return 0; + } + r = recv(nlsock, resp, sizeof(resp), 0); + if (r < 0) { + warn("recv 'AF_NETLINK':"); + return 0; + } + if ((size_t)r <= sizeof(ctrl)) + return 0; + p = findattr(CTRL_ATTR_FAMILY_ID, resp + sizeof(ctrl), resp + r, &len); + if (p && len == 2) + memcpy(&id, p, 2); + + return id; + } + + static int + ifindex(const char *interface) + { + static struct ifreq ifr; + static int ifsock = -1; + + if (ifsock < 0) + ifsock = socket(AF_UNIX, SOCK_DGRAM, 0); + if (ifsock < 0) { + warn("socket 'AF_UNIX':"); + return -1; + } + if (strcmp(ifr.ifr_name, interface) != 0) { + strcpy(ifr.ifr_name, interface); + if (ioctl(ifsock, SIOCGIFINDEX, &ifr) != 0) { + warn("ioctl 'SIOCGIFINDEX':"); + return -1; + } + } + return ifr.ifr_ifindex; + } const char * - wifi_perc(const char *interface) + wifi_essid(const char *interface) { - int cur; - size_t i; - char *p, *datastart; - char path[PATH_MAX]; - char status[5]; - FILE *fp; - - if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0) - return NULL; - if (!(fp = fopen(path, "r"))) { - warn("fopen '%s':", path); + uint16_t fam = nl80211fam(); + ssize_t r; + size_t len; + char req[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(4)] = {0}, *p = req; + int idx = ifindex(interface); + if (!fam) { + fprintf(stderr, "nl80211 family not found\n"); return NULL; } - p = fgets(status, 5, fp); - fclose(fp); - if (!p || strcmp(status, "up\n") != 0) + if (idx < 0) { + fprintf(stderr, "interface %s not found\n", interface); return NULL; + } - if (!(fp = fopen("/proc/net/wireless", "r"))) { - warn("fopen '/proc/net/wireless':"); + memcpy(p, &(struct nlmsghdr){ + .nlmsg_len = sizeof(req), + .nlmsg_type = fam, + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_seq = seq++, + .nlmsg_pid = 0, + }, sizeof(struct nlmsghdr)); + p += NLMSG_HDRLEN; + memcpy(p, &(struct genlmsghdr){ + .cmd = NL80211_CMD_GET_INTERFACE, + .version = 1, + }, sizeof(struct genlmsghdr)); + p += GENL_HDRLEN; + memcpy(p, &(struct nlattr){ + .nla_len = NLA_HDRLEN+4, + .nla_type = NL80211_ATTR_IFINDEX, + }, sizeof(struct nlattr)); + p += NLA_HDRLEN; + memcpy(p, &(uint32_t){idx}, 4); + + if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { + warn("send 'AF_NETLINK':"); return NULL; } - - for (i = 0; i < 3; i++) - if (!(p = fgets(buf, sizeof(buf) - 1, fp))) - break; - - fclose(fp); - if (i < 2 || !p) + r = recv(nlsock, resp, sizeof(resp), 0); + if (r < 0) { + warn("recv 'AF_NETLINK':"); return NULL; + } - if (!(datastart = strstr(buf, interface))) + if ((size_t)r <= NLMSG_HDRLEN + GENL_HDRLEN) return NULL; + p = findattr(NL80211_ATTR_SSID, resp + NLMSG_HDRLEN + GENL_HDRLEN, resp + r, &len); + if (p) + p[len] = 0; - datastart = (datastart+(strlen(interface)+1)); - sscanf(datastart + 1, " %*d %d %*d %*d\t\t %*d\t " - "%*d\t\t%*d\t\t %*d\t %*d\t\t %*d", &cur); - - /* 70 is the max of /proc/net/wireless */ - return bprintf("%d", (int)((float)cur / 70 * 100)); + return p; } const char * - wifi_essid(const char *interface) + wifi_perc(const char *interface) { - static char id[IW_ESSID_MAX_SIZE+1]; - int sockfd; - struct iwreq wreq; - - memset(&wreq, 0, sizeof(struct iwreq)); - wreq.u.essid.length = IW_ESSID_MAX_SIZE+1; - if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", - interface) < 0) - return NULL; + static char strength[4]; + struct nlmsghdr hdr; + uint16_t fam = nl80211fam(); + ssize_t r; + size_t len; + char req[NLMSG_HDRLEN + GENL_HDRLEN + NLA_HDRLEN + NLA_ALIGN(4)] = {0}, *p = req, *e; + int idx = ifindex(interface); - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return NULL; - } - wreq.u.essid.pointer = id; - if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) { - warn("ioctl 'SIOCGIWESSID':"); - close(sockfd); + if (idx < 0) { + fprintf(stderr, "interface %s not found\n", interface); return NULL; } - close(sockfd); - - if (!strcmp(id, "")) + memcpy(p, &(struct nlmsghdr){ + .nlmsg_len = sizeof(req), + .nlmsg_type = fam, + .nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP, + .nlmsg_seq = seq++, + .nlmsg_pid = 0, + }, sizeof(struct nlmsghdr)); + p += NLMSG_HDRLEN; + memcpy(p, &(struct genlmsghdr){ + .cmd = NL80211_CMD_GET_STATION, + .version = 1, + }, sizeof(struct genlmsghdr)); + p += GENL_HDRLEN; + memcpy(p, &(struct nlattr){ + .nla_len = NLA_HDRLEN + 4, + .nla_type = NL80211_ATTR_IFINDEX, + }, sizeof(struct nlattr)); + p += NLA_HDRLEN; + memcpy(p, &idx, 4); + + if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { + warn("send 'AF_NETLINK':"); return NULL; + } - return id; + *strength = 0; + while (1) { + r = recv(nlsock, resp, sizeof(resp), 0); + if (r < 0) { + warn("recv 'AF_NETLINK':"); + return NULL; + } + if ((size_t)r < sizeof(hdr)) + return NULL; + + for (p = resp; p != resp + r && (size_t)(resp + r-p) >= sizeof(hdr); p = e) { + memcpy(&hdr, p, sizeof(hdr)); + e = resp + r - p < hdr.nlmsg_len ? resp + r : p + hdr.nlmsg_len; + + if (!*strength && hdr.nlmsg_len > NLMSG_HDRLEN+GENL_HDRLEN) { + p += NLMSG_HDRLEN+GENL_HDRLEN; + p = findattr(NL80211_ATTR_STA_INFO, p, e, &len); + if (p) + p = findattr(NL80211_STA_INFO_SIGNAL_AVG, p, e, &len); + if (p && len == 1) + snprintf(strength, sizeof(strength), "%d", RSSI_TO_PERC(*p)); + } + if (hdr.nlmsg_type == NLMSG_DONE) + return *strength ? strength : NULL; + } + } } #elif defined(__OpenBSD__) #include <net/if.h> |
