diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e99cca0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +beastie diff --git a/beastie.c b/beastie.c index 746e19c..5e7b26a 100644 --- a/beastie.c +++ b/beastie.c @@ -1,5 +1,5 @@ /* beastie - minimal system info */ -#define VERSION "dev" +#define VERSION "0.1.0" #include #include #include @@ -75,12 +75,18 @@ mem_str(char *buf, size_t len) snprintf(buf, len, "%luM / %luM", used_mb, total_mb); } -/* read cpu model string */ +/* read cpu model string, stripping " @ " suffix */ static void cpu_str(char *buf, size_t len) { size_t sz = len; - if (sysctlbyname("hw.model", buf, &sz, NULL, 0) == 0) return; + if (sysctlbyname("hw.model", buf, &sz, NULL, 0) == 0) { + char *at = strstr(buf, " CPU"); + if (at) *at = '\0'; + at = strstr(buf, " @"); + if (at) *at = '\0'; + return; + } snprintf(buf, len, "unknown"); } @@ -137,6 +143,49 @@ kernel_ident(char *buf, size_t len) snprintf(buf, len, "unknown"); } +/* detect wm name via _NET_SUPPORTING_WM_CHECK / _NET_WM_NAME, + * falling back to process name scanning if xprop is unavailable */ +static void +wm_str(char *buf, size_t len) +{ + if (!getenv("DISPLAY")) { snprintf(buf, len, "none"); return; } + + /* try xprop first */ + FILE *f = popen( + "id=$(xprop -root _NET_SUPPORTING_WM_CHECK 2>/dev/null | awk '{print $NF}');" + "[ -n \"$id\" ] && xprop -id \"$id\" _NET_WM_NAME 2>/dev/null" + " | awk -F '\"' 'NF>1{print $2; exit}'", + "r"); + if (f) { + char tmp[64] = {0}; + fgets(tmp, sizeof(tmp), f); + pclose(f); + size_t tl = strlen(tmp); + if (tl && tmp[tl-1] == '\n') tmp[tl-1] = '\0'; + if (tmp[0]) { snprintf(buf, len, "%s", tmp); return; } + } + + /* xprop unavailable or returned nothing -- scan process list */ + static const char *wms[] = { + "dwm", "openbox", "i3", "bspwm", "xmonad", "awesome", + "fluxbox", "icewm", "jwm", "herbstluftwm", "spectrwm", + "cwm", "fvwm", "fvwm3", "mwm", "twm", "xfwm4", + "kwin_x11", "kwin_wayland", "mutter", "marco", + "compiz", "enlightenment", "sawfish", "pekwm", + NULL + }; + for (int i = 0; wms[i]; i++) { + char cmd[128]; + snprintf(cmd, sizeof(cmd), "pgrep -x '%s' >/dev/null 2>&1", wms[i]); + if (system(cmd) == 0) { + snprintf(buf, len, "%s", wms[i]); + return; + } + } + + snprintf(buf, len, "unknown"); +} + int main(int argc, char *argv[]) { @@ -200,24 +249,8 @@ main(int argc, char *argv[]) } const char *term = termbuf; - /* detect x server vendor via xdpyinfo to avoid linking against libX11 */ - char wmbuf[64] = "none"; - if (getenv("DISPLAY")) { - FILE *xdpy = popen("xdpyinfo 2>/dev/null | grep 'vendor string' | awk '{print $3}'", "r"); - if (xdpy) { - char vendor[64] = {0}; - fgets(vendor, sizeof(vendor), xdpy); - pclose(xdpy); - size_t vl = strlen(vendor); - if (vl && vendor[vl-1] == '\n') vendor[vl-1] = '\0'; - if (vendor[0]) - snprintf(wmbuf, sizeof(wmbuf), "dwm (on %s)", vendor); - else - snprintf(wmbuf, sizeof(wmbuf), "dwm"); - } else { - snprintf(wmbuf, sizeof(wmbuf), "dwm"); - } - } + char wmbuf[64] = {0}; + wm_str(wmbuf, sizeof(wmbuf)); const char *wm = wmbuf; /* build info lines from modules[] */ @@ -238,12 +271,17 @@ main(int argc, char *argv[]) user, uts.nodename); ilines[ni] = ibufs[ni]; ni++; break; - case MOD_OS: + case MOD_OS: { + char rel[64]; + snprintf(rel, sizeof(rel), "%s", uts.release); + char *dash = strchr(rel, '-'); + if (dash) *dash = '\0'; snprintf(ibufs[ni], sizeof(ibufs[0]), COLOR_LABEL "os " COLOR_RESET " %s %s", - uts.sysname, uts.release); + uts.sysname, rel); ilines[ni] = ibufs[ni]; ni++; break; + } case MOD_KERNEL: snprintf(ibufs[ni], sizeof(ibufs[0]), COLOR_LABEL "kernel" COLOR_RESET " %s", kid);