Skip to content

Instantly share code, notes, and snippets.

@sug0
Last active February 19, 2019 03:01
Show Gist options
  • Select an option

  • Save sug0/a54c9aa406b231ffa91777e95b6e8171 to your computer and use it in GitHub Desktop.

Select an option

Save sug0/a54c9aa406b231ffa91777e95b6e8171 to your computer and use it in GitHub Desktop.
Cron alternative that will run in your shitter.
#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