commit - 3726d3ccf1e70c2d368684178c12bbd4636842df
commit + 069363286eaa434ca1bcea830ed897bd5bca9aac
blob - 15618524e6bf84d52c325faf94753adeec699edb
blob + a9fd703197692fd2ddc1345fd0b6380fe0b34cd7
--- include/statbar.h
+++ include/statbar.h
extern void read_config(void);
extern int open_command_interface(void);
extern int open_output(void);
+extern int open_timer(void);
extern void close_fifos(void);
/* Clock */
extern pid_t start_volume_process(int *pipe_fd);
+/* Timer */
+#define TIMER_STRING_SIZE 6
+
+extern pid_t start_timer_process(int *pipe_fd, int timerval_fd);
+
/* Mail */
extern char mail_string[7];
blob - 4122a3ed28669554cdf43f33d621d9c7358a2f56
blob + 92602b1f173905c829783717a73861694d3e643f
--- modules/Makefile
+++ modules/Makefile
LIB= statbar_modules
-SRCS= clock.c battery.c volume.c mail.c network.c
+SRCS= clock.c battery.c volume.c timer.c mail.c network.c
MAN=
CFLAGS += -I../include -I/usr/local/include
blob - /dev/null
blob + ed6199d3b8e92e88017d59b52f59ec2e3e5725b9 (mode 644)
--- /dev/null
+++ modules/timer.c
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <sys/_time.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include "statbar.h"
+
+static volatile sig_atomic_t should_quit = 0;
+
+static void
+signal_handler(int sig)
+{
+ if (sig == SIGTERM || sig == SIGINT) should_quit = 1;
+}
+
+pid_t
+start_timer_process(int *pipe_fd, int timerval_fd)
+{
+ pid_t pid;
+ int timer_pipe[2];
+ struct pollfd pfd;
+ int flags;
+ ssize_t n;
+ char buf[1024];
+ char *delim;
+ struct timespec init;
+ struct timespec start;
+ struct timespec cur;
+ struct timespec elapsed;
+ struct timespec display;
+ long min;
+ long sec;
+
+ if (pipe(timer_pipe) == -1)
+ {
+ perror("pipe");
+
+ return -1;
+ }
+ *pipe_fd = timer_pipe[0];
+
+ pid = fork();
+ if (pid)
+ {
+ if (pid == -1) (void)close(timer_pipe[0]);
+ (void)close(timer_pipe[1]);
+
+ return pid;
+ }
+
+ flags = fcntl(timerval_fd, F_GETFL, 0);
+ (void)fcntl(timerval_fd, F_SETFL, flags | O_NONBLOCK);
+ pfd.fd = timerval_fd;
+ pfd.events = POLLIN;
+ (void)close(timer_pipe[0]);
+ setproctitle("timer");
+ (void)puts("Timer process started");
+
+ (void)signal(SIGTERM, signal_handler);
+ (void)signal(SIGINT, signal_handler);
+
+ if (pledge("stdio", NULL) == -1)
+ {
+ perror("pledge");
+ (void)close(timer_pipe[0]);
+ (void)close(timer_pipe[1]);
+
+ _exit(1);
+ }
+
+ (void)dprintf(timer_pipe[1], "00:00");
+ while(!should_quit)
+ {
+ if (poll(&pfd, 1, INFTIM) > 0)
+ {
+ n = read(pfd.fd, buf, sizeof(buf));
+
+ if (n < 0 && errno == EAGAIN) continue;
+ }
+ delim = strchr(buf, ':');
+ if (delim)
+ {
+ *delim = '\0';
+ delim++;
+
+ min = strtol(buf, NULL, 10) * 60;
+ sec = strtol(delim, NULL, 10);
+ init.tv_sec = (time_t)(min + sec);
+ }
+ else
+ {
+ sec = strtol(buf, NULL, 10);
+ init.tv_sec = (time_t)sec;
+ }
+ init.tv_nsec = 0;
+
+ while(1)
+ {
+ n = read(pfd.fd, buf, sizeof(buf));
+
+ if (n > 0) continue;
+ if (n == 0)
+ {
+ should_quit = 1;
+
+ break;
+ }
+ if (n < 0)
+ {
+ if (errno == EAGAIN) break;
+
+ perror("read");
+ should_quit = 1;
+
+ break;
+ }
+ }
+
+ (void)clock_gettime(CLOCK_MONOTONIC, &start);
+ while(!should_quit)
+ {
+ (void)clock_gettime(CLOCK_MONOTONIC, &cur);
+ timespecsub(&cur, &start, &elapsed);
+ timespecsub(&init, &elapsed, &display);
+ if (display.tv_sec == 0)
+ {
+ (void)dprintf(timer_pipe[1], "00:00");
+
+ break;
+ }
+ else
+ {
+ (void)dprintf(timer_pipe[1], "%02jd:%02jd", (intmax_t)display.tv_sec / 60, (intmax_t)display.tv_sec % 60);
+ }
+
+ if (poll(&pfd, 1, 1000) > 0) break;
+ }
+
+ if (getppid() == 1) break;
+ }
+ (void)puts("Closing timer process");
+ (void)close(timer_pipe[1]);
+
+ _exit(0);
+}
+
blob - 2859a99ccb6eb86e9d8dbc839025bbb806b0cde4
blob + a118dc16d10119e830a3bff3a1420697a4a8e5f3
--- src/fs.c
+++ src/fs.c
static int out_rdfd;
static int out_wrfd;
static char *outpath;
+static int timer_rdfd;
+static int timer_wrfd;
+static char *timerpath;
static int
mkdir_recursive(char *path)
return open_fifo(&out_rdfd, &out_wrfd, &outpath, "/.local/state/statbarout", 1);
}
+int
+open_timer(void)
+{
+ return open_fifo(&timer_rdfd, &timer_wrfd, &timerpath, "/.local/state/statbartimer", 0);
+}
+
void
close_fifos(void)
{
(void)close(out_wrfd);
(void)remove(outpath);
free(outpath);
+ (void)close(timer_rdfd);
+ (void)close(timer_wrfd);
+ (void)remove(timerpath);
+ free(timerpath);
}
blob - c5459bffd2095a91b09ebb586437be58b169a07e
blob + c4e10c11c7a8f1e72c93899d6d35f3f2464ead8a
--- src/main.c
+++ src/main.c
#include "statbar.h"
-#define NFDS 4
+#define NFDS 5
enum clocks_e
{
int output_fd;
int batt_fd;
int vol_fd;
+ int timer_fd;
+ int timerval_fd;
int network_fd;
pid_t batt_pid;
pid_t vol_pid;
+ pid_t timer_pid;
pid_t network_pid;
unsigned char cmd;
bool network_open = false;
struct pollfd *cmd_pfd = &pfd[0];
struct pollfd *batt_pfd = &pfd[1];
struct pollfd *vol_pfd = &pfd[2];
- struct pollfd *network_pfd = &pfd[3];
+ struct pollfd *timer_pfd = &pfd[3];
+ struct pollfd *network_pfd = &pfd[4];
char battery_string[BATTERY_STRING_SIZE];
char volume_string[VOLUME_STRING_SIZE];
+ char timer_string[TIMER_STRING_SIZE];
char network_string[NETWORK_STRING_SIZE];
int i;
ssize_t n;
read_config();
(void)clock_gettime(CLOCK_BOOTTIME, &now);
normalize_clock_interval(&now, &clocks[CLOCK_CLOCK]);
+ timerval_fd = open_timer();
+ if (timer_fd == -1)
+ {
+ (void)puts("Failed to open timer FIFO");
+ return -1;
+ }
+
get_clock();
batt_pid = start_privileged_battery_process(&batt_fd, &battery_interval);
vol_pid = start_volume_process(&vol_fd);
+ timer_pid = start_timer_process(&timer_fd, timerval_fd);
network_pid = start_network_process(&network_fd);
cmd_pfd->fd = open_command_interface();
vol_pfd->fd = vol_fd;
vol_pfd->events = POLLIN;
}
+ if (timer_pid > 0)
+ {
+ timer_pfd->fd = timer_fd;
+ timer_pfd->events = POLLIN;
+ }
if (network_pid > 0)
{
network_pfd->fd = network_fd;
n = read(vol_pfd->fd, volume_string, VOLUME_STRING_SIZE);
if (n > 0) volume_string[n] = '\0';
}
+ if (timer_pfd->revents & POLLIN)
+ {
+ n = read(timer_pfd->fd, timer_string, TIMER_STRING_SIZE);
+ if (n > 0) timer_string[n] = '\0';
+ }
if (network_pfd->revents & POLLIN)
{
n = read(network_pfd->fd, network_string, NETWORK_STRING_SIZE);
if (dirty)
{
- (void)dprintf(output_fd, "%s | %s | %s | %s%s\n",
+ (void)dprintf(output_fd, "%s | %s | %s | %s | %s%s\n",
clock_string,
battery_string,
volume_string,
+ timer_string,
network_string,
mail_string);
dirty = false;
(void)puts("Closing statbar");
if (batt_pid > 0) (void)kill(batt_pid, SIGTERM);
if (vol_pid > 0) (void)kill(vol_pid, SIGTERM);
+ if (timer_pid > 0) (void)kill(timer_pid, SIGTERM);
if (network_pid > 0) (void)kill(network_pid, SIGTERM);
close_mail();
close_fifos();
blob - /dev/null
blob + a6699539d22aac30e34397bd019523431ff30094 (mode 755)
--- /dev/null
+++ stimer.sh
+#!/bin/sh
+
+STATBARTIMER=~/.local/state/statbartimer
+
+show_help()
+{
+ echo "stimer help"
+ echo "\nstimer is used to set the statbar timer widget"
+ echo "statbar must be running for this program to be useful"
+ echo "\nUsage:"
+ echo "\tstimer <time>: count down from <time> in the status bar"
+}
+
+if [ ! -p "$STATBARTIMER" ]; then
+ echo "Could not open statbar timer" > /dev/stderr
+ exit 1;
+fi
+
+if [ -z "$1" ]; then
+ show_help;
+ exit 0;
+fi
+
+echo "$1" > "$STATBARTIMER"
+