Commit Diff


commit - 8321fa19c97a5f78ceca7ea866ca8dc18696d6ba
commit + 6a40413bfd582f7ef59dbe0a6926d7f4b5d8bf8c
blob - 2efe892c418eaadf452b8ae10c5e71e59cdd871a
blob + 29ccceaafc5b3c6e989b5075ad1ed8015cf05366
--- include/statbar.h
+++ include/statbar.h
@@ -37,11 +37,9 @@ extern void get_clock(void);
 extern void normalize_clock_interval(const struct timespec *now, struct timespec *next);
 
 /* Battery */
-extern char battery_string[11];
+#define BATTERY_STRING_SIZE 11
 
-extern bool init_battery(void);
-extern void get_battery(void);
-extern void close_battery(void);
+extern pid_t start_privileged_battery_process(int *pipe_fd, const struct timespec *timeout);
 
 /* Volume */
 extern char volume_string[11];
blob - b67ebc6adadd240baca6ee127b49b5549a39fba0
blob + 2d222454e2b6914d85b9ab08f55cfc0504a9c30c
--- modules/battery.c
+++ modules/battery.c
@@ -3,42 +3,40 @@
 #include <string.h>
 
 #include <fcntl.h>
+#include <signal.h>
 #include <unistd.h>
 #include <machine/apmvar.h>
 #include <sys/ioctl.h>
+#include <sys/time.h>
 
 #include "statbar.h"
 
-char battery_string[11];
-
 static int fd;
+static volatile sig_atomic_t should_quit = 0;
 
-bool
+int
 init_battery(void)
 {
 	fd = open("/dev/apm", O_RDONLY);
 	if (fd < 0)
 	{
-		perror("battery: open");
-		(void)strcpy(battery_string, UNKNOWN);
+		perror("open");
 
-		return false;
+		return -1;
 	}
-	get_battery();
 
-	return true;
+	return 0;
 }
 
-void
-get_battery()
+static void
+get_battery(int pipe_fd)
 {
 	struct apm_power_info pinfo;
 	char pstate[5];
 
 	if (ioctl(fd, APM_IOC_GETPOWER, &pinfo) < 0)
 	{
-		perror("battery: ioctl");
-		(void)strcpy(battery_string, UNKNOWN);
+		perror("ioctl");
 
 		return;
 	}
@@ -54,12 +52,49 @@ get_battery()
 	else
 		(void)strcpy(pstate, BATT);
 
-	(void)snprintf(battery_string, 11, "%s  %3d%%", pstate, pinfo.battery_life);
+	(void)dprintf(pipe_fd, "%s  %3d%%", pstate, pinfo.battery_life);
 }
 
-void
-close_battery(void)
+static void
+signal_handler(int sig)
 {
-	(void)close(fd);
+	if (sig == SIGTERM || sig == SIGINT) should_quit = 1;
 }
 
+pid_t
+start_privileged_battery_process(int *pipe_fd, const struct timespec *timeout)
+{
+	pid_t pid;
+	int batt_pipe[2];
+
+	if (pipe(batt_pipe) == -1)
+	{
+		perror("pipe");
+
+		return -1;
+	}
+	*pipe_fd = batt_pipe[0];
+
+	pid = fork();
+	if (pid) return pid;
+
+	if (init_battery() == -1) _exit(-1);
+
+	(void)signal(SIGTERM, signal_handler);
+	(void)signal(SIGINT, signal_handler);
+	(void)signal(SIGUSR1, signal_handler);
+
+	while(!should_quit)
+	{
+		get_battery(batt_pipe[1]);
+		(void)nanosleep(timeout, NULL);
+
+		if (getppid() == 1) break;
+	}
+	(void)puts("Closing battery pipe");
+	(void)close(batt_pipe[1]);
+	(void)close(batt_pipe[0]);
+
+	_exit(0);
+}
+
blob - 0b5d6618af30297297b0ea8774a6eb67d6f2a2f5
blob + 90a5b407848bd07d74b11f3250c4f6e348a62783
--- src/main.c
+++ src/main.c
@@ -22,7 +22,6 @@
 enum clocks_e
 {
 	CLOCK_CLOCK,
-	BATTERY_CLOCK,
 	CPUTEMP_CLOCK,
 	FANSPEED_CLOCK,
 	WEATHER_CLOCK,
@@ -74,15 +73,17 @@ install_signal_handlers(void)
 int
 main(int argc, char *argv[])
 {
-	Display *display = XOpenDisplay(NULL);
+	Display *display;
 	Window root;
 	char statbar_text[MAX_STATBAR_LEN];
 	bool dirty = true;
+	int batt_fd;
+	pid_t batt_pid;
 	unsigned char cmd;
 	struct pollfd *cmd_pfd = NULL;
+	struct pollfd *batt_pfd = NULL;
 	struct pollfd *network_pfd = NULL;
 	struct pollfd *weather_pfd = NULL;
-	bool apm_open = false;
 	bool hdl_open = false;
 	bool network_open = false;
 	struct timespec now;
@@ -95,11 +96,13 @@ main(int argc, char *argv[])
 	struct timespec fanspeed_interval = { .tv_sec = 3 };
 	struct timespec weather_interval = { .tv_sec = 1800 };
 	struct pollfd *pfd;
+	char battery_string[BATTERY_STRING_SIZE];
 	int nfds = 2; /* Start with 2 to guarantee space for the network socket and cmd interface */
 	int i;
 
 	(void)setvbuf(stdout, NULL, _IOLBF, 0);
 
+	display = XOpenDisplay(NULL);
 	if (display == NULL)
 	{
 		(void)puts("Failed to get display");
@@ -117,7 +120,6 @@ main(int argc, char *argv[])
 	read_config(&clock_interval, &battery_interval, &cputemp_interval, &fanspeed_interval);
 	(void)clock_gettime(CLOCK_BOOTTIME, &now);
 	normalize_clock_interval(&now, &clocks[CLOCK_CLOCK]);
-	timespecadd(&now, &battery_interval, &clocks[BATTERY_CLOCK]);
 	timespecadd(&now, &cputemp_interval, &clocks[CPUTEMP_CLOCK]);
 	timespecadd(&now, &fanspeed_interval, &clocks[FANSPEED_CLOCK]);
 	timespecadd(&now, &weather_interval, &clocks[WEATHER_CLOCK]);
@@ -128,12 +130,13 @@ main(int argc, char *argv[])
 	}
 
 	get_clock();
-	apm_open = init_battery();
+	batt_pid = start_privileged_battery_process(&batt_fd, &battery_interval);
 	hdl_open = init_volume(&nfds);
 	get_cputemp();
 	get_fanspeed();
 	get_initial_network_state();
 	if (weather_loc_valid) nfds++;
+	if (batt_pid > 0) nfds++;
 
 	pfd = malloc(nfds * sizeof(struct pollfd));
 	if (pfd == NULL)
@@ -151,12 +154,24 @@ main(int argc, char *argv[])
 	{
 		weather_pfd = &pfd[nfds - 3];
 		weather_pfd->fd = weather_pipe[0];
+		weather_pfd->events = POLLIN;
 		get_weather(weather_pipe[1]);
 	}
+	if (batt_pid > 0)
+	{
+		batt_pfd = &pfd[nfds - (weather_loc_valid ? 4 : 3)];
+		batt_pfd->fd = batt_fd;
+		batt_pfd->events = POLLIN;
+	}
 	if (mail_path_valid) mail_path_valid = get_mail();
 
 	fill_sndio_pfds(pfd);
-	weather_pfd->events = POLLIN;
+	if (pledge("stdio rpath cpath inet proc exec route audio", NULL) == -1)
+	{
+		perror("pledge");
+
+		goto cleanup;
+	}
 	while (!should_quit)
 	{
 		if (reload_config)
@@ -219,6 +234,8 @@ main(int argc, char *argv[])
 						break;
 				}
 			}
+			if (batt_pfd->revents & POLLIN)
+				(void)read(batt_pfd->fd, battery_string, BATTERY_STRING_SIZE);
 			if (network_pfd->revents & POLLIN)
 				read_network_socket(network_pfd->fd);
 			if (weather_pfd && (weather_pfd->revents & POLLIN))
@@ -246,13 +263,10 @@ main(int argc, char *argv[])
 		}
 
 		/* Battery */
-		if (reload_battery || (apm_open && timespeccmp(&now, &clocks[BATTERY_CLOCK], >=)))
+		if (reload_battery)
 		{
 			reload_battery = 0;
-			get_battery();
-			dirty = true;
-			while (timespeccmp(&now, &clocks[BATTERY_CLOCK], >=))
-				timespecadd(&clocks[BATTERY_CLOCK], &battery_interval, &clocks[BATTERY_CLOCK]);
+			(void)kill(batt_pid, SIGUSR1);
 		}
 
 		/* CPU Temp */
@@ -301,7 +315,7 @@ main(int argc, char *argv[])
 
 cleanup:
 	(void)puts("Closing statbar");
-	if (apm_open) close_battery();
+	if (batt_pid > 0) (void)kill(batt_pid, SIGTERM); 
 	if (hdl_open) close_volume();
 	if (network_open) (void)close(network_pfd->fd);
 	if (weather_loc_valid) close_weather();