commit 1157627b862a560c1fc5bc7187ec0b77bd75d146 from: Brett Fisher date: Fri Jun 12 03:37:54 2026 UTC bxnet.c, config.def.h, bxbarrc.lua, Makefile: Implement C helper for network interface status. - Create bxnet to monitor /sys/class/net/ for active interfaces. - Implement kernel-level detection for WiFi and Ethernet. - Define network state icons in config.def.h. - Update Makefile to build the new helper binary. commit - 0c5cb071191e1ef383a3460f0ffd8356692e4913 commit + 1157627b862a560c1fc5bc7187ec0b77bd75d146 blob - 5d2fc8e15b42e88ca7161f818e2d0e78ac4758e2 blob + 6efe31da62cbed8fe0aed6abb85dd8e3df8ccf02 --- Makefile +++ Makefile @@ -10,7 +10,7 @@ CFLAGS = -std=c11 -pedantic -Wall -Wextra $(shell pkg- LDFLAGS = LDLIBS = $(shell pkg-config --libs xft x11) -all: bxbar bxinfo +all: bxbar bxinfo bxnet bxbar: bxbar.o $(CC) $(LDFLAGS) -o $@ bxbar.o $(LDLIBS) @@ -24,19 +24,25 @@ bxbar.o: bxbar.c config.h bxinfo: bxinfo.o $(CC) -o $@ bxinfo.o -lX11 +bxnet: bxnet.o + $(CC) -o $@ bxnet.o -lX11 + clean: rm -f bxbar bxbar.o rm -f bxinfo bxinfo.o + rm -f bxnet bxnet.o install: install -d $(DESTDIR)$(PREFIX)/bin install -m 755 bxbar $(DESTDIR)$(PREFIX)/bin/bxbar install -m 755 bxinfo $(DESTDIR)$(PREFIX)/bin/bxinfo + install -m 755 bxnet $(DESTDIR)$(PREFIX)/bin/bxnet install -m 755 bxbarrc.lua $(DESTDIR)$(PREFIX)/bin/bxbarrc.lua uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/bxbar rm -f $(DESTDIR)$(PREFIX)/bin/bxinfo + rm -f $(DESTDIR)$(PREFIX)/bin/bxnet rm -f $(DESTDIR)$(PREFIX)/bin/bxbarrc.lua .PHONY: all clean install uninstall blob - 8fa6c143e0075ca003d757ad1ba6f17179818ac2 blob + 2f76ebb2abc7bd4924b30f1350d2cd0a8d5396e9 --- bxbarrc.lua +++ bxbarrc.lua @@ -76,6 +76,14 @@ local function get_battery(bat_path) return "[" .. bar .. "] " .. cap .. "%" .. charging end +local function get_network() + local h = io.popen("bxnet", "r") + if not h then return "--/--" end + local status = h:read("*l") + h:close() + return status or "--/--" +end + -- Discover battery path once at startup local bat_path = find_battery_path() @@ -84,9 +92,10 @@ while true do local ws, title = get_x11_info() local dt = os.date("%Y-%m-%d %a %H:%M") local bat = bat_path and get_battery(bat_path) or "" + local net = get_network() local left = ws .. " " .. title - local right = bat .. " " .. dt + local right = net .. " " .. bat .. " " .. dt io.write(left .. string.char(1) .. right .. "\n") io.flush() blob - 7d3a78ec662265c9b3363c03bbc80f79e8b96c43 blob + 9ca29e1d98c28da7af66269bdd54a7f44f0d19d2 --- config.def.h +++ config.def.h @@ -13,5 +13,10 @@ #define BG_COLOR "#000000" #define FONT "monospace:size=14" #define DELIMITER '\x01' +#define IFNAMSIZ 16 +/* Network Status Icons */ +#define NET_ETH_ICON "[---]" +#define NET_WLAN_ICON "<--->" +#define NET_NONE_ICON "--/--" #define DEBUG_LOGGING 0 blob - /dev/null blob + 1c4718aba2d64e731392d48fd0990b30ab9f47f7 (mode 644) --- /dev/null +++ bxnet.c @@ -0,0 +1,104 @@ +/* + * bxnet - A basic X network helper + * Queries /sys/class/net/ and prints the active interface status to stdout. + * See LICENSE.md and README.md for details. + */ + +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#define SYS_NET_PATH "/sys/class/net" + +static int is_dir(const char *path); + +/* Read a file and trim the trailing newline. + * Returns 1 on success, 0 on failure. */ +static int +read_sys_file(const char *path, char *buf, size_t buflen) +{ + FILE *f = fopen(path, "r"); + if (!f) return 0; + + if (!fgets(buf, buflen, f)) { + fclose(f); + return 0; + } + fclose(f); + + /* Strip trailing whitespace/newline */ + buf[strcspn(buf, "\r\n")] = '\0'; + return 1; +} + +/* Check the operstate of an interface. + * Returns 1 if "up", 0 otherwise. */ +static int +is_iface_up(const char *iface) +{ + char path[256], state[16]; + snprintf(path, sizeof(path), "%s/%s/operstate", SYS_NET_PATH, iface); + if (!read_sys_file(path, state, sizeof(state))) + return 0; + return strcmp(state, "up") == 0; +} + +/* Check if a path is a directory. + * Returns 1 if directory, 0 otherwise. */ +static int +is_dir(const char *path) +{ + struct stat st; + if (stat(path, &st) != 0) + return 0; + return S_ISDIR(st.st_mode); +} + +int +main(void) +{ + DIR *d = opendir(SYS_NET_PATH); + if (!d) { + /* If we can't even read /sys, just return the down state */ + puts(NET_NONE_ICON); + return 1; + } + + struct dirent *de; + int found_eth = 0, found_wlan = 0; + + while ((de = readdir(d)) != NULL) { + if (de->d_name[0] == '.' || strcmp(de->d_name, "lo") == 0) + continue; + + if (!is_iface_up(de->d_name)) + continue; + + /* Check for wireless/ subdirectory — kernel-level indicator of WiFi */ + char wireless_path[64]; + int iface_len = strnlen(de->d_name, IFNAMSIZ); + snprintf(wireless_path, sizeof(wireless_path), + "%s/%.*s/wireless", SYS_NET_PATH, iface_len, de->d_name); + if (is_dir(wireless_path)) { + found_wlan = 1; + } else { + /* Assume Ethernet for other "up" interfaces */ + found_eth = 1; + } + } + closedir(d); + + if (found_eth) puts(NET_ETH_ICON); + else if (found_wlan) puts(NET_WLAN_ICON); + else puts(NET_NONE_ICON); + + return 0; +} +