Last active
February 19, 2019 03:01
-
-
Save sug0/a54c9aa406b231ffa91777e95b6e8171 to your computer and use it in GitHub Desktop.
Cron alternative that will run in your shitter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <time.h> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include <signal.h> | |
| #include <sys/wait.h> | |
| /* configurable constants */ | |
| #define TIME_MAX 2 | |
| #define LOG_FILE "/root/logs/sched.log" | |
| enum check_fields { | |
| CHK_MIN, | |
| CHK_HOUR, | |
| CHK_BOTH_HM | |
| }; | |
| /* sleep for 1 minute -- don't change this */ | |
| struct timespec sleep_amt = {60, 0}; | |
| /* our scheduled tasks to run */ | |
| struct { | |
| const char *cmd; | |
| time_t last; | |
| int n_times; | |
| struct { | |
| int chk_fields; | |
| int tm_hour; | |
| int tm_min; | |
| } times[TIME_MAX]; /* increasing order of time */ | |
| } cron_tasks[] = { | |
| /* update void-packages git repo */ | |
| { | |
| "cd $HOME/void-packages; git pull", | |
| 0, 1, {{CHK_BOTH_HM, 0, 0}} | |
| }, | |
| /* update system packages */ | |
| { | |
| "xbps-install -Suy", | |
| 0, 2, {{CHK_BOTH_HM, 0, 0}, {CHK_BOTH_HM, 12, 0}} | |
| }, | |
| }; | |
| inline int chk_min(struct tm *tm, int i, int ti) | |
| { | |
| return tm->tm_min == cron_tasks[i].times[ti].tm_min; | |
| } | |
| inline int chk_hr(struct tm *tm, int i, int ti) | |
| { | |
| return tm->tm_hour == cron_tasks[i].times[ti].tm_hour; | |
| } | |
| inline int zero_min(struct tm *tm) | |
| { | |
| return tm->tm_min == 0; | |
| } | |
| int will_exec_task(time_t *t, int i) | |
| { | |
| *t = time(NULL); | |
| if (*t - cron_tasks[i].last < 20) | |
| return 0; | |
| int ti; | |
| struct tm *tm = localtime(t); | |
| for (ti = 0; ti < cron_tasks[i].n_times; ti++) { | |
| switch (cron_tasks[i].times[ti].chk_fields) { | |
| case CHK_HOUR: | |
| if (zero_min(tm) && chk_hr(tm, i, ti)) | |
| goto yes; | |
| case CHK_MIN: | |
| if (chk_min(tm, i, ti)) | |
| goto yes; | |
| case CHK_BOTH_HM: | |
| if (chk_hr(tm, i, ti) && chk_min(tm, i, ti)) | |
| goto yes; | |
| } | |
| } | |
| return 0; | |
| yes: | |
| cron_tasks[i].last = *t; | |
| return 1; | |
| } | |
| inline const char *task(int i) | |
| { | |
| return cron_tasks[i].cmd; | |
| } | |
| void run(int fd, time_t t, const char *cmd) | |
| { | |
| if (fd != -1) | |
| dprintf(fd, "%lu\t%s\n", t, cmd); | |
| if (fork() == 0) | |
| execlp("sh", "sh", "-c", cmd, NULL); | |
| } | |
| void handle_sigchld(int signo) | |
| { | |
| (void)signo; | |
| wait(NULL); | |
| } | |
| void handle_sigterm(int signo) | |
| { | |
| (void)signo; | |
| exit(0); | |
| } | |
| int main(void) | |
| { | |
| if (getuid() != 0) | |
| return 1; | |
| if (signal(SIGCHLD, handle_sigchld) == SIG_ERR) | |
| return 2; | |
| if (signal(SIGTERM, handle_sigterm) == SIG_ERR) | |
| return 3; | |
| int i; | |
| time_t t; | |
| const int n_tasks = sizeof(cron_tasks)/sizeof(cron_tasks[0]); | |
| for (;;) { | |
| int fd = open(LOG_FILE, O_WRONLY|O_CREAT|O_APPEND); | |
| for (i = 0; i < n_tasks; i++) { | |
| if (will_exec_task(&t, i)) | |
| run(fd, t, task(i)); | |
| } | |
| close(fd); | |
| nanosleep(&sleep_amt, NULL); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment