X-Git-Url: http://pileus.org/git/?p=lackey;a=blobdiff_plain;f=src%2Fdaemon.c;fp=src%2Fdaemon.c;h=ea61afb0fbde7befe510f52de92c29f0ed80d3e7;hp=0000000000000000000000000000000000000000;hb=d45541aeb31a0e34a2a43df0e112f1f720f80abf;hpb=7edd7d3a9f0bdaaa8df9f68a73f7c84e2b514ce6 diff --git a/src/daemon.c b/src/daemon.c new file mode 100644 index 0000000..ea61afb --- /dev/null +++ b/src/daemon.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2017 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define _POSIX_C_SOURCE 200112L + +#include +#include +#include + +#include "util.h" +#include "conf.h" +#include "date.h" +#include "cal.h" +#include "daemon.h" + +/* Config data */ +static int reminder = 15*60; +static char *command = NULL; + +/* Local data */ +static date_t old; +static date_t new; + +/* Local functions */ +static void date_str(char *str, size_t size, date_t *date) +{ + snprintf(str, size, "%04d-%02d-%02d %02d:%02d:%02d", + date->year+1, date->month+1, date->day, + date->hour, date->min, date->sec); +} + +static void notify(event_t *event) +{ + static char start_str[32]; + static char end_str[32]; + + date_t start = event->start; + date_t end = event->end; + wday_t wday = day_of_week(start.year, start.month, start.day); + + if (command) { + date_str(start_str, sizeof(start_str), &event->start); + date_str(end_str, sizeof(end_str), &event->end); + + setenv("EVENT_NAME", event->name ?: "", 1); + setenv("EVENT_DESC", event->desc ?: "", 1); + setenv("EVENT_LOC", event->loc ?: "", 1); + setenv("EVENT_START", start_str, 1); + setenv("EVENT_END", end_str, 1); + + system(command); + + unsetenv("EVENT_NAME"); + unsetenv("EVENT_DESC"); + unsetenv("EVENT_LOC"); + unsetenv("EVENT_START"); + unsetenv("EVENT_END"); + } else { + printf("%s, %s %d, %d, %02d:%02d-%02d:%02d\n", + day_to_string(wday), + month_to_string(start.month), + start.day+1, + start.year, + start.hour, start.min, + end.hour, end.min); + + if (event->name) + printf(" Name: %s\n", event->name); + if (event->loc) + printf(" Location: %s\n", event->loc); + if (event->desc) + printf(" Details: %s\n", event->desc); + } +} + +static int step(void) +{ + int delay = 24*60*60; + + debug("Polling: %02dh %02dm %02ds", + NOW.hour, NOW.min, NOW.sec); + + /* Bump timestamps */ + old = new; + new = NOW; + + /* Print notifications */ + for (event_t *cur = EVENTS; cur; cur = cur->next) { + if (compare(&cur->start, &old) < 0) + continue; + + int old_until = get_secs(&old, &cur->start); + int new_until = get_secs(&new, &cur->start); + + if (old_until > reminder && new_until <= reminder) { + debug("Notify: %s", cur->name); + notify(cur); + } + if (new_until > reminder) { + delay = new_until - reminder; + break; + } + } + + /* Return delay */ + return delay; +} + +/* Initialize */ +void daemon_init(void) +{ + old = NOW; + new = NOW; +} + +void daemon_main(void) +{ + int delay = 0; + while (1) { + date_sync(); + delay = step(); + fflush(stdout); + sleep(delay); + } +} + +void daemon_exit(void) +{ +} + +/* Config parser */ +void daemon_config(const char *group, const char *name, const char *key, const char *value) +{ + if (match(group, "daemon")) { + if (match(key, "reminder")) { + reminder = get_number(value); + } else if (match(key, "notify")) { + command = get_string(value); + } + } +} + +/* Test */ +void daemon_test(void) +{ + static event_t event0 = { + .name = "test event", + .desc = "this event is random and does not exist", + }; + static event_t event1 = { + .name = "test event", + .desc = "this event is random and does not exist", + }; + static todo_t todo = { + .name = "test todo", + .desc = "this todo is random and does not exist", + .status = 50, + }; + + EVENTS = &event0; + EVENTS->next = &event1; + TODOS = &todo; + + date_sync(); + + NOW.hour = 0; + NOW.min = 0; + NOW.sec = 0; + + event0.start = ((date_t){NOW.year, NOW.month, NOW.day, 12, 0}); + event0.end = ((date_t){NOW.year, NOW.month, NOW.day, 13, 0}); + event1.start = ((date_t){NOW.year, NOW.month, NOW.day, 14, 0}); + event1.end = ((date_t){NOW.year, NOW.month, NOW.day, 15, 0}); + todo.due = ((date_t){NOW.year, NOW.month, NOW.day, 16, 0}); + + util_init(); + + daemon_config("daemon", NULL, "reminder", "15"); + daemon_config("daemon", NULL, "notify", "lackey-notify"); + + daemon_init(); + while (NOW.day == EVENTS->start.day) { + int delay = step(); + delay = MIN(delay, rand() % (60*60)); + NOW = get_date(get_stamp(NOW)+delay); + } + daemon_exit(); +}