commit - 41845009e0bf65a06ac9a5cb667e62cdfe939dfc
commit + 9277f37fbd9ab2abf0a46c4c294f322c7b2c70be
blob - 6503128fa94d82c7b7bf817f2407056390a81c09
blob + 1fdcb99d4bf543892bcd66104fe535fb027405f3
--- Makefile
+++ Makefile
SRC_ST = st/st.c st/x.c
HDR_ST = st/arg.h st/st.h st/win.h st/config.h master.h
+SRC_BS = bedstatus/bedstatus.c
+HDR_BS = bedstatus/bedstatus.h \
+ bedstatus/unsupported.c \
+ bedstatus/openbsd.c
+
SRC_DMENU = dmenu/dmenu.c dmenu/drw.c dmenu/util.c
HDR_DMENU = dmenu/arg.h dmenu/config.h dmenu/drw.h dmenu/util.h master.h
@mkdir -p bin
${CC} -o $@ ${SRC_ST} ${CFLAGS} `pkg-config --cflags --libs fontconfig freetype2 x11 xft xrender` -lm -lutil
-bin/bedstatus: bedstatus/bedstatus.c
+bin/bedstatus: ${SRC_BS} ${HDR_BS}
@mkdir -p bin
${CC} -o $@ bedstatus/bedstatus.c ${CFLAGS} `pkg-config --cflags --libs x11`
blob - 3acfb46c3c44b48560b003bf074c13bbcb708694
blob + fedc672f5da002f3fd3467776189563f404e5df7
--- bedstatus/bedstatus.c
+++ bedstatus/bedstatus.c
-#include <sys/types.h>
-#include <machine/apmvar.h>
-#include <sys/signal.h>
-#include <sys/sched.h>
-#include <sys/sysctl.h>
-#include <sys/ioctl.h>
-#include <sys/sensors.h>
#include <X11/Xlib.h>
#include <unistd.h>
-#include <string.h>
-#include <stdint.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
-#include <fcntl.h>
#include <time.h>
#include <err.h>
-#define MAXSENSORS 16
-#define CPUSPEEDHISTLEN 3
+#ifdef __OpenBSD__
+# include "openbsd.c"
+#else
+# include "unsupported.c"
+#endif
-static int power_sensors[MAXSENSORS];
-static int cputemp_sensor = -1;
-static int num_power_sensors = 0;
+#define SYM_CPU "\uf2db "
+#define SYM_RAM "\uf538 "
+#define SYM_BAT_CHARGING "\uf5e7 "
+#define SYM_BAT_EMPTY "\uf244 "
+#define SYM_BAT_LOW "\uf243 "
+#define SYM_BAT_HALF "\uf242 "
+#define SYM_BAT_HIGH "\uf241 "
+#define SYM_BAT_FULL "\uf240 "
-struct cpu_usage {
- struct cpustats new;
- struct cpustats old;
- struct cpustats diffs;
-};
+static size_t pos;
+static char buf[256];
-static int num_cpu (void)
+static void append (const char *fmt, ...)
{
- const int mib[] = { CTL_HW, HW_NCPU };
- int ncpu = 0;
- size_t size = sizeof ncpu;
+ va_list ap;
+ int n;
+
+ if (pos >= sizeof (buf))
+ return;
- if (sysctl (mib, 2, &ncpu, &size, NULL, 0) < 0)
- return 1;
+ va_start (ap, fmt);
+ n = vsnprintf (buf + pos, sizeof (buf) - pos, fmt, ap);
+ va_end (ap);
- return ncpu;
+ if (n > 0)
+ pos += n;
}
-static int64_t percentages (struct cpustats *out, struct cpu_usage *cpu)
+static void format_cpu (const struct status *st)
{
- int64_t total_change = 0;
+ if (!st->has_cpu_usage && !st->has_cpu_speed && !st->has_cpu_temp)
+ return;
- for (int i = 0; i < 6; ++i) {
- int64_t change = cpu->new.cs_time[i] - cpu->old.cs_time[i];
- if (change < 0)
- change = INT64_MAX - cpu->old.cs_time[i] - cpu->new.cs_time[i];
-
- cpu->diffs.cs_time[i] = change;
- total_change += change;
- cpu->old.cs_time[i] = cpu->new.cs_time[i];
- }
-
- if (total_change == 0)
- total_change = 1;
+ append ("[CPU " SYM_CPU);
- for (int i = 0; i < 6; ++i) {
- out->cs_time[i] = (cpu->diffs.cs_time[i] * 1000 + total_change / 2) / total_change;
+ if (st->has_cpu_usage) {
+ append ("%d%%", st->cpu_usage);
+ if (st->has_cpu_speed || st->has_cpu_temp)
+ append (" (");
}
- return total_change;
-}
+ if (st->has_cpu_speed) {
+ append ("%d MHz", st->cpu_speed);
-static int cpuspeed (void)
-{
- static int history[CPUSPEEDHISTLEN];
- const int mib[2] = { CTL_HW, HW_CPUSPEED };
- int speed, sum = 0;
- size_t len = sizeof speed;
+ if (st->has_cpu_temp)
+ append ("/");
+ }
- if (sysctl (mib, 2, &speed, &len, NULL, 0) == -1)
- return -1;
+ if (st->has_cpu_temp)
+ append ("%d°C", st->cpu_temp);
- memmove (history + 1, history, (CPUSPEEDHISTLEN - 1) * sizeof *history);
- history[0] = speed;
+ if (st->has_cpu_usage && (st->has_cpu_speed || st->has_cpu_temp))
+ append (")");
- for (int i = 0; i < CPUSPEEDHISTLEN; ++i)
- sum += history[i];
-
- return sum / CPUSPEEDHISTLEN;
+ append ("] ");
}
-static int64_t read_sensor (int id, int type, int n)
+static void format_ram (const struct status *st)
{
- const int mib[5] = { CTL_HW, HW_SENSORS, id, type, n };
- struct sensor sensor;
- size_t len = sizeof sensor;
- int ret;
-
- ret = sysctl (mib, 5, &sensor, &len, NULL, 0);
-
- return (ret == -1 || sensor.status & SENSOR_FINVALID) ? -1 : sensor.value;
-}
-
-static const char *cpu (int ncpu, struct cpu_usage *cpus)
-{
- static char buffer[64];
- uint64_t sum = 0;
- int64_t temp;
- int usage, speed;
-
- for (int i = 0; i < ncpu; ++i) {
- const int mib[] = { CTL_KERN, KERN_CPUSTATS, i };
- struct cpustats tmp;
- size_t size = sizeof tmp;
-
- if (sysctl (mib, 3, &cpus[i].new, &size, NULL, 0) < 0)
- continue;
-
- percentages (&tmp, &cpus[i]);
- sum += 1000 - tmp.cs_time[5];
- }
-
- usage = sum / ncpu / 10;
- speed = cpuspeed ();
- temp = cputemp_sensor != -1 ? read_sensor (cputemp_sensor, SENSOR_TEMP, 0) : -1;
-
- if (temp != -1) {
- temp = (temp - 273150000) / 1000000;
- snprintf (buffer, sizeof buffer, "%d%% (%d MHz/%d°C)", (int)usage, speed, (int)temp);
- } else {
- snprintf (buffer, sizeof buffer, "%d%% (%d MHz)", (int)usage, speed);
- }
- return buffer;
-}
-
-static const char *ram (void)
-{
+ uint64_t bytes;
struct unit {
const char *s;
- unsigned long long u;
+ uint64_t u;
} units[] = {
{ "PiB", 1ull << 50 },
{ "TiB", 1ull << 40 },
{ "KiB", 1ull << 10 },
{ NULL, 0 },
};
- const int mib[] = { CTL_VM, VM_UVMEXP };
- struct uvmexp uvmexp;
- size_t size = sizeof uvmexp;
- uint64_t bytes;
- static char buffer[10];
- if (sysctl (mib, 2, &uvmexp, &size, NULL, 0) < 0)
- return "N/A";
+ if (!st->has_mem_usage)
+ return;
- bytes = ((uint64_t)uvmexp.active << (uvmexp.pageshift - 10)) * 1024;
+ append ("[RAM " SYM_RAM);
- for (const struct unit *u = units; u->s != NULL; ++u) {
+ bytes = st->mem_usage;
+
+ for (const struct unit *u = units; u-> s != NULL; ++u) {
if (bytes < u->u)
continue;
const unsigned raw = bytes * 100 / u->u;
if (raw >= 10000) {
- snprintf (buffer, sizeof buffer, "%u %s", raw / 100, u->s);
+ append ("%u", raw / 100);
} else if (raw >= 1000) {
- snprintf (buffer, sizeof buffer, "%u.%u %s", raw / 100, raw / 10 % 10, u->s);
+ append ("%u.%u", raw / 100, raw / 10 % 10);
} else {
- snprintf (buffer, sizeof buffer, "%u.%02u %s", raw / 100, raw % 100, u->s);
+ append ("%u.%02u", raw / 100, raw % 100);
}
- return buffer;
+
+ append (" %s", u->s);
+ goto done;
}
- snprintf (buffer, sizeof buffer, "%u B", (unsigned)bytes);
- return buffer;
+
+ append ("%u B", (unsigned)bytes);
+
+done:
+ append ("] ");
}
-static void bat (int fd, const char **bat_sym, unsigned *bat_perc, const char **bat_time)
+static void format_bat (const struct status *st)
{
- static char buffer[32];
- struct apm_power_info info;
-
- if (fd < 0 || ioctl (fd, APM_IOC_GETPOWER, &info) != 0) {
- *bat_sym = "N/A";
- *bat_perc = 0;
- *bat_time = "N/A";
+ if (!st->has_bat_charging && !st->has_bat_perc && !st->has_bat_rem && !st->has_power)
return;
- }
- *bat_perc = info.battery_life;
+ append ("[BAT ");
- if (info.minutes_left != (u_int)-1) {
- size_t pos = 0;
- unsigned minutes = info.minutes_left;
- const static struct unit {
+ if (!st->has_bat_charging && st->has_bat_perc) {
+ if (st->bat_perc < 25) {
+ append (SYM_BAT_EMPTY);
+ } else if (st->bat_perc < 50) {
+ append (SYM_BAT_LOW);
+ } else if (st->bat_perc < 75) {
+ append (SYM_BAT_HALF);
+ } else if (st->bat_perc < 99) {
+ append (SYM_BAT_HIGH);
+ } else {
+ append (SYM_BAT_FULL);
+ }
+ } else {
+ append (SYM_BAT_CHARGING);
+ }
+
+ if (st->has_bat_perc) {
+ append ("%d%%", st->bat_perc);
+
+ if (st->has_bat_rem || st->has_power)
+ append (" (");
+ }
+
+ if (st->has_bat_rem) {
+ unsigned rem = st->bat_rem;
+ struct unit {
char c;
unsigned v;
} units[] = {
- { .c = 'd', 24 * 60 },
- { .c = 'h', 60 },
- { .c = 'm', 1 },
- { .c = '\0', 0 },
+ { 'd', 24 * 60 },
+ { 'h', 60 },
+ { 'm', 1 },
+ { '\0', 0 },
};
for (size_t i = 0; units[i].v != 0; ++i) {
const struct unit u = units[i];
- if (minutes >= u.v) {
- pos += snprintf (buffer + pos, sizeof buffer - pos, "%u%c", minutes / u.v, u.c);
- minutes %= u.v;
- }
- }
- buffer[pos] = '\0';
- *bat_time = buffer;
- } else {
- *bat_time = "N/A";
- }
- switch (info.ac_state) {
- case APM_AC_OFF:
- case APM_AC_UNKNOWN:
- case APM_AC_BACKUP:
- if (info.battery_life < 25) {
- *bat_sym = "\uf244";
- } else if (info.battery_life < 50) {
- *bat_sym = "\uf243";
- } else if (info.battery_life < 75) {
- *bat_sym = "\uf242";
- } else if (info.battery_life < 99) {
- *bat_sym = "\uf241";
- } else {
- *bat_sym = "\uf240";
+ if (rem < u.v)
+ continue;
+
+ append ("%u%c", rem / u.v, u.c);
+ rem %= u.v;
}
- break;
- case APM_AC_ON:
- *bat_sym = "\uf5e7";
- break;
+
+ if (st->has_power)
+ append ("/");
}
-}
-static void find_sensors (void)
-{
- for (int i = 0; i < MAXSENSORS; ++i) {
- const int mib[3] = { CTL_HW, HW_SENSORS, i };
- struct sensordev dev;
- size_t sdlen = sizeof dev;
+ if (st->has_power) {
+ unsigned pwr = st->power;
- if (sysctl (mib, 3, &dev, &sdlen, NULL, 0) == -1)
- continue;
+ append ("%u.%02uW", pwr / 1000, pwr % 1000 / 10);
+ }
- if (dev.maxnumt[SENSOR_WATTS] > 0) {
- power_sensors[num_power_sensors++] = i;
- }
+ if (st->has_bat_perc && (st->has_bat_rem || st->has_power))
+ append (")");
- if (dev.maxnumt[SENSOR_TEMP] > 0
- && memcmp (dev.xname, "cpu", 3) == 0
- && cputemp_sensor == -1) {
- cputemp_sensor = i;
- }
- }
+ append ("] ");
}
-static const char *power (void)
+static void format_time (void)
{
- static char power[32];
- int64_t total = 0;
+ struct tm *tm;
+ time_t t;
- if (num_power_sensors == 0)
- return "";
+ t = time (NULL);
+ tm = localtime (&t);
+ strftime (buf + pos, sizeof (buf) - pos, "%a %F %T", tm);
+}
- for (int i = 0; i < num_power_sensors; ++i) {
- const int mib[5] = { CTL_HW, HW_SENSORS, power_sensors[i], SENSOR_WATTS, 0 };
- struct sensor sensor;
- size_t slen = sizeof sensor;
+static void format_status (const struct status *st)
+{
+ format_cpu (st);
+ format_ram (st);
+ format_bat (st);
+ format_time ();
+}
- if (sysctl (mib, 5, &sensor, &slen, NULL, 0) == -1)
- continue;
-
- if (sensor.flags & SENSOR_FINVALID)
- continue;
-
- total += sensor.value;
- }
-
- const int sub = total / 10000;
- snprintf (power, sizeof power, "/%d.%02uW", sub / 100, sub % 100);
- return power;
-}
-
int main (int argc, char *argv[])
{
- int ncpu;
- struct cpu_usage *cpus;
- unsigned long root;
- char status[256];
Display *dpy;
- int fd_apm, screen;
+ int screen;
+ unsigned long root;
(void)argv;
-
+
if (argc != 1) {
puts ("bedstatus-" VERSION);
return 1;
screen = XDefaultScreen (dpy);
root = XRootWindow (dpy, screen);
- ncpu = num_cpu ();
- cpus = calloc (ncpu, sizeof (struct cpu_usage));
- fd_apm = open ("/dev/apm", O_RDONLY);
- find_sensors ();
+ init_backend ();
while (1) {
- const char *bat_sym, *bat_time;
- unsigned bat_perc;
- time_t t;
- struct tm *tm;
+ struct status st;
- bat (fd_apm, &bat_sym, &bat_perc, &bat_time);
+ update_status (&st);
+ pos = 0;
+ format_status (&st);
- const int num = snprintf (
- status,
- sizeof status,
- "[CPU \uf2db %s] [RAM \uf538 %s] [BAT %s %u%% (%s%s)] ",
- cpu (ncpu, cpus),
- ram (),
- bat_sym,
- bat_perc,
- bat_time,
- power ()
- );
-
- t = time (NULL);
- tm = localtime (&t);
- strftime (status + num, sizeof status - num, "%a %F %T", tm);
- status[sizeof status - 1] = '\0';
-
- XStoreName (dpy, root, status);
+ XStoreName (dpy, root, buf);
XFlush (dpy);
sleep (1);
}
blob - /dev/null
blob + 6891c83045156ca5af5caae2655d2e91d4de622b (mode 644)
--- /dev/null
+++ bedstatus/bedstatus.h
+#ifndef FILE_BEDSTATUS_H
+#define FILE_BEDSTATUS_H
+#include <stdbool.h>
+#include <stdint.h>
+
+#define E(t, n) t n; bool has_##n
+struct status {
+ E(int, cpu_usage); // CPU Usage in %
+ E(int, cpu_speed); // CPU Frequency in MHz
+ E(int, cpu_temp); // CPU Temperature in DegC
+ E(uint64_t, mem_usage); // RAM Usage in Bytes
+ E(int, bat_perc); // Battery Level in %
+ E(int, bat_rem); // Remaining Battery Life in Minutes
+ E(bool, bat_charging); // Is the AC connected?
+ E(int, power); // Power Drain in Milli-Watts
+};
+#undef E
+
+void init_backend (void);
+void update_status (struct status *);
+
+#endif // FILE_BEDSTATUS_H
blob - /dev/null
blob + 96977840c0c93594325c70eef65b19dac5605338 (mode 644)
--- /dev/null
+++ bedstatus/openbsd.c
+#include <sys/types.h>
+#include <machine/apmvar.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/sched.h>
+#include <sys/time.h>
+#include <sys/sensors.h>
+#include <uvm/uvm_param.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include "bedstatus.h"
+
+#define MAXSENSORS 16
+
+struct cpu_usage {
+ struct cpustats new, old, diffs;
+};
+
+static int ncpu = 1;
+static struct cpu_usage *cpus;
+static int apm_fd = -1;
+static int cputemp_sensor = -1;
+static int num_power_sensors = 0;
+static int power_sensors[MAXSENSORS];
+
+static bool read_sensor (struct sensor *sen, int which, int what)
+{
+ const int mib[5] = { CTL_HW, HW_SENSORS, which, what, 0 };
+ size_t len = sizeof (*sen);
+
+ return sysctl (mib, 5, sen, &len, NULL, 0) != -1;
+}
+
+static int64_t percentages (struct cpustats *out, struct cpu_usage *cpu)
+{
+ int64_t total_change = 0;
+
+ for (int i = 0; i < 6; ++i) {
+ int64_t change = cpu->new.cs_time[i] - cpu->old.cs_time[i];
+ if (change < 0)
+ change = INT64_MAX - cpu->old.cs_time[i] - cpu->new.cs_time[i];
+
+ cpu->diffs.cs_time[i] = change;
+ total_change += change;
+ cpu->old.cs_time[i] = cpu->new.cs_time[i];
+ }
+
+ if (total_change == 0)
+ total_change = 1;
+
+ for (int i = 0; i < 6; ++i) {
+ out->cs_time[i] = (cpu->diffs.cs_time[i] * 1000 + total_change / 2) / total_change;
+ }
+
+ return total_change;
+}
+
+
+static bool cpu_usage (int *usage)
+{
+ uint64_t sum = 0;
+
+ for (int i = 0; i < ncpu; ++i) {
+ const int mib[3] = { CTL_KERN, KERN_CPUSTATS, i };
+ struct cpustats tmp;
+ size_t len = sizeof (tmp);
+
+ if (sysctl (mib, 3, &cpus[i].new, &len, NULL, 0) < 0)
+ continue;
+
+ percentages (&tmp, &cpus[i]);
+ sum += 1000 - tmp.cs_time[5];
+ }
+
+ *usage = sum / ncpu / 10;
+ return true;
+}
+
+static bool cpu_speed (int *speed)
+{
+ const int mib[2] = { CTL_HW, HW_CPUSPEED };
+ size_t len = sizeof (*speed);
+
+ return sysctl (mib, 2, speed, &len, NULL, 0) != -1;
+}
+
+static bool cpu_temp (int *temp)
+{
+ struct sensor sen;
+
+ if (!read_sensor (&sen, cputemp_sensor, SENSOR_TEMP) || sen.status & SENSOR_FINVALID)
+ return false;
+
+ *temp = (sen.value - 273150000) / 1000000;;
+
+ return true;
+}
+
+static bool mem_usage (uint64_t *usage)
+{
+ const int mib[2] = { CTL_VM, VM_UVMEXP };
+ struct uvmexp uvm;
+ size_t len = sizeof (uvm);
+
+ if (sysctl (mib, 2, &uvm, &len, NULL, 0) == -1)
+ return false;
+
+ *usage = (uint64_t)uvm.active << uvm.pageshift;
+
+ return true;
+}
+
+static void bat (struct status *st)
+{
+ struct apm_power_info info;
+
+ if (apm_fd < 0 || ioctl (apm_fd, APM_IOC_GETPOWER, &info) != 0)
+ return;
+
+ st->has_bat_perc = true;
+ st->bat_perc = info.battery_life;
+
+ if (info.minutes_left != (u_int)-1) {
+ st->has_bat_rem = true;
+ st->bat_rem = info.minutes_left;
+ }
+
+ switch (info.ac_state) {
+ case APM_AC_ON:
+ st->has_bat_charging = true;
+ st->bat_charging = true;
+ break;
+ case APM_AC_OFF:
+ case APM_AC_BACKUP:
+ st->has_bat_charging = true;
+ st->bat_charging = false;
+ break;
+ }
+}
+
+static bool power (int *milliwatts)
+{
+ struct sensor sen;
+ int64_t total = 0;
+
+ if (num_power_sensors == 0)
+ return false;
+
+ for (int i = 0; i < num_power_sensors; ++i) {
+ if (!read_sensor (&sen, power_sensors[i], SENSOR_WATTS))
+ continue;
+
+ total += sen.value;
+ }
+
+ *milliwatts = total / 1000;
+ return true;
+}
+
+void init_backend (void)
+{
+ const int mib_ncpu[2] = { CTL_HW, HW_NCPU };
+ size_t len = sizeof (ncpu);
+
+ sysctl (mib_ncpu, 2, &ncpu, &len, NULL, 0);
+ cpus = calloc (ncpu, sizeof (struct cpu_usage));
+
+ apm_fd = open ("/dev/apm", O_RDONLY);
+
+ for (int i = 0; i < MAXSENSORS; ++i) {
+ const int mib[3] = { CTL_HW, HW_SENSORS, i};
+ struct sensordev dev;
+
+ len = sizeof (dev);
+
+ if (sysctl (mib, 3, &dev, &len, NULL, 0) == -1)
+ continue;
+
+ if (dev.maxnumt[SENSOR_WATTS] > 0) {
+ power_sensors[num_power_sensors++] = i;
+ }
+
+ if (dev.maxnumt[SENSOR_TEMP] > 0 && memcmp (dev.xname, "cpu", 3) == 0 && cputemp_sensor == -1) {
+ cputemp_sensor = i;
+ }
+ }
+}
+
+void update_status (struct status *st)
+{
+ memset (st, 0, sizeof (*st));
+ st->has_cpu_usage = cpu_usage (&st->cpu_usage);
+ st->has_cpu_temp = cpu_temp (&st->cpu_temp);
+ st->has_cpu_speed = cpu_speed (&st->cpu_speed);
+ st->has_mem_usage = mem_usage (&st->mem_usage);
+ bat (st);
+ st->has_power = power (&st->power);
+}
blob - /dev/null
blob + a359db9cc9fa1311553b9e6c1cc80688acbc4d3f (mode 644)
--- /dev/null
+++ bedstatus/unsupported.c
+#include <string.h>
+#include "bedstatus.h"
+
+void init_backend (void)
+{
+}
+
+void update_status (struct status *st)
+{
+ memset (st, 0, sizeof (&st));
+}