pomo/spt.c

171 lines
3.1 KiB
C
Raw Normal View History

2015-11-28 13:08:54 +00:00
/* See LICENSE file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#ifdef NOTIFY
2015-11-28 13:08:54 +00:00
#include <libnotify/notify.h>
#endif /* NOTIFY */
2015-11-28 13:08:54 +00:00
#include "arg.h"
char *argv0;
/* macros */
2016-07-11 10:47:18 +00:00
#define LEN(a) (sizeof(a) / sizeof(a[0]))
2015-11-28 13:08:54 +00:00
typedef struct {
unsigned int tmr;
char *cmt;
} Timers;
2015-11-28 13:08:54 +00:00
#include "config.h"
volatile static sig_atomic_t display, suspend;
2015-11-28 13:08:54 +00:00
/* function declarations */
static void die(const char *errstr, ...);
2016-07-11 11:36:15 +00:00
static void spawn(char *cmd, char *cmt);
static void notify_send(char *cmt);
2016-10-29 04:40:54 +00:00
static void display_state(int remaining, int suspend);
static void toggle_display(int sigint);
static void toggle_suspend(int sigint);
2015-11-28 13:08:54 +00:00
static void usage(void);
/* functions implementations */
void
die(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
2016-07-11 11:36:15 +00:00
exit(1);
}
void
spawn(char *cmd, char *cmt)
{
if (fork() == 0) {
setsid();
execlp(cmd, cmd, "spt", cmt, NULL);
die("spt: execlp %s\n", cmd);
perror(" failed");
exit(0);
}
2015-11-28 13:08:54 +00:00
}
void
notify_send(char *cmt)
{
#ifdef NOTIFY
notify_init("spt");
NotifyNotification *n = notify_notification_new("spt", cmt, \
"dialog-information");
notify_notification_show(n, NULL);
g_object_unref(G_OBJECT(n));
notify_uninit();
#else
2016-07-11 10:47:18 +00:00
if (strcmp(notifycmd, "")) /* TODO: call function in config.h */
2016-07-11 11:36:15 +00:00
spawn(notifycmd, cmt);
#endif /* NOTIFY */
2015-11-28 13:08:54 +00:00
if (strcmp(notifyext, "")) /* extra commands to use */
2016-07-11 11:36:15 +00:00
spawn(notifyext, NULL);
2015-11-28 13:08:54 +00:00
}
void
2016-10-29 04:40:54 +00:00
display_state(int remaining, int suspend)
{
2016-10-29 04:40:54 +00:00
char buf[22];
2016-10-29 04:40:54 +00:00
snprintf(buf, 22, "Remaining: %02d:%02d %s\n",
remaining / 60,
remaining % 60,
(suspend) ? "" : "");
2016-07-11 11:36:15 +00:00
notify_send(buf);
display = 0;
}
2016-07-12 08:51:26 +00:00
void
toggle_display(int sigint)
{
display = 1;
}
void
toggle_suspend(int sigint)
{
suspend ^= 1;
2016-07-12 08:51:26 +00:00
}
2015-11-28 13:08:54 +00:00
void
usage(void)
{
die("usage: %s [-e notifyext] [-n notifycmd] [-v]\n", argv0);
}
int
main(int argc, char *argv[])
{
struct timespec remaining;
struct sigaction sa;
sigset_t emptymask;
int i;
2016-07-12 08:51:26 +00:00
2015-11-28 13:08:54 +00:00
ARGBEGIN {
case 'e':
notifyext = EARGF(usage());
break;
case 'n':
notifycmd = EARGF(usage());
break;
case 'v':
2016-10-28 16:43:20 +00:00
die("spt " VERSION " © 2015-2016 spt engineers, "
2015-11-28 13:08:54 +00:00
"see LICENSE for details\n");
default:
usage();
break;
} ARGEND;
/* add SIGUSR1 handler: remaining_time */
sa.sa_handler = toggle_display;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
die("cannot associate SIGUSR1 to handler\n");
/* add SIGUSR2 handler: toggle */
sa.sa_handler = toggle_suspend;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR2, &sa, NULL) == -1)
die("cannot associate SIGUSR2 to handler\n");
for (i = 0; ; i = (i + 1) % LEN(timers)) {
notify_send(timers[i].cmt);
remaining.tv_sec = timers[i].tmr;
remaining.tv_nsec = 0;
while (remaining.tv_sec) {
if (display)
2016-10-29 04:40:54 +00:00
display_state(remaining.tv_sec, suspend);
if (suspend)
sigsuspend(&emptymask);
else
if (nanosleep(&remaining, &remaining) == 0)
remaining.tv_sec = remaining.tv_nsec = 0;
}
}
2015-11-28 13:08:54 +00:00
return 0;
}