Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Build dcron
FROM alpine AS builder
COPY . /src
RUN apk add --no-cache gcc make musl-dev \
&& cd /src \
&& make \
&& make install

# Build image
FROM alpine

# Alpine includes a copy of dcron as part of busybox.
# Delete the /var/spool/cron dir and then recreate it.
RUN rm -rf /var/spool/cron \
# These are copied from the Makefiles
&& install -o root -d -m0755 -g root /var/spool/cron \
&& install -o root -d -m0755 -g root /etc/cron.d

# Copy crond and crontab
COPY --from=builder /usr/local/sbin/crond /usr/local/sbin/crond
COPY --from=builder /usr/local/bin/crontab /usr/local/bin/crontab

# Start dcron
ENTRYPOINT ["/usr/local/sbin/crond", "-C", "-f", "-L", "-"]
CMD []

# Mark /var/spool/cron as a volume so cron settings are persisted there
VOLUME /var/spool/cron

26 changes: 25 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ wanting to edit defs.h directly, try editing the DEFS line in the Makefile inste
make PREFIX=/usr CRONTAB_GROUP=users

(3) If you're using the git version, you might also want to `make man`,
to be sure the manpages are updated. This requires
to be sure the manpages are updated. This requires
[pandoc](http://johnmacfarlane.net/pandoc/).


Expand Down Expand Up @@ -117,6 +117,30 @@ Here is the superuser's crontab, created using `sudo crontab -e`:

-rw------- 0 root root 513 Jan 6 18:58 /var/spool/cron/crontabs/root

DOCKER
------

Using `dcron` with docker is rather straight forward.

To build the base image use:

docker build -t dcron dcron-source-dir

To add on any additional scripts:

cd your-project-dir
echo dcron.dockerfile <<DOCKERFILE
FROM dcron
COPY jobs /etc/crond.d/
COPY mailer /usr/local/bin/mailer
CMD ["-M", "/usr/local/bin/mailer"]
DOCKERFILE
docker build -t mycron -f dcron.dockerfile .

To run the resulting docker image:

docker run -d -v cron_data:/var/spool/cron mycron

TESTING
-------

Expand Down
3 changes: 2 additions & 1 deletion database.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,12 @@ ReadTimestamps(const char *user)
}
sec = (time_t)-1;
ptr = strptime(ptr, CRONSTAMP_FMT, &tm);
if (ptr && (*ptr == 0 || *ptr == '\n'))
if (ptr && (*ptr == 0 || *ptr == '\n')) {
/* strptime uses current seconds when seconds not specified? anyway, we don't get round minutes */
tm.tm_sec = 0;
tm.tm_isdst = -1;
sec = mktime(&tm);
}
if (sec == (time_t)-1) {
printlogf(LOG_ERR, "unable to parse timestamp (user %s job %s)\n", file->cf_UserName, line->cl_JobName);
/* we continue checking other timestamps in this CronFile */
Expand Down
4 changes: 3 additions & 1 deletion defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
#define LOCALE_LOGHEADER "%c %%s " LOG_IDENT ": "

/* Limits */
#define MAXOPEN 256 /* close fds < this limit */
#define MAXOPEN 256 /* close fds < this limit */
#define MAXLINES 256 /* max lines in non-root crontabs */
#define SMALL_BUFFER 256
#define RW_BUFFER 1024
Expand Down Expand Up @@ -169,5 +169,7 @@ typedef struct CronNotifier {
struct CronWaiter *cn_Waiter;
} CronNotifier;

extern short Quit;

#include "protos.h"

92 changes: 70 additions & 22 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ Prototype const char *Mailto;
Prototype char *TempDir;
Prototype char *TempFileFmt;

short Quit = 0;
short DebugOpt = 0;
short LogLevel = LOG_LEVEL;
short ForegroundOpt = 0;
short SyslogOpt = 1;
const char *CDir = CRONTABS;
const char *SCDir = SCRONTABS;
short CreateCronDirsOpt = 0;
const char *CDir = CRONTABS;
const char *SCDir = SCRONTABS;
const char *TSDir = CRONSTAMPS;
const char *LogFile = NULL; /* opened with mode 0600 */
const char *LogHeader = LOGHEADER;
Expand Down Expand Up @@ -72,7 +74,7 @@ main(int ac, char **av)

opterr = 0;

while ((i = getopt(ac,av,"dl:L:fbSc:s:m:M:t:")) != -1) {
while ((i = getopt(ac,av,"dl:L:fbSc:s:m:M:t:C")) != -1) {
switch (i) {
case 'l':
{
Expand Down Expand Up @@ -159,25 +161,53 @@ main(int ac, char **av)
if (*optarg != 0) SendMail = optarg;
break;
case 'm':
if (*optarg != 0) Mailto = optarg;
if (*optarg == 0) break;

for (const char *c = optarg; *c != 0; ++c) {
if (*c == '@') {
Mailto = optarg;
break;
}
}

if (Mailto == NULL && *optarg == '/') {
char *buffer = malloc(256);
FILE* file = fopen(optarg, "r");
if (file) {
size_t s = fread(buffer, 1, 256, file);
if (s < 1) {
free(buffer);
} else {
buffer[s] = 0;
Mailto = buffer;
}
fclose(file);
}
}
break;
case 'C':
CreateCronDirsOpt = 1;
break;

default:
/*
* check for parse error
*/
printf("dillon's cron daemon " VERSION "\n");
printf("crond [-s dir] [-c dir] [-t dir] [-m user@host] [-M mailer] [-S|-L [file]] [-l level] [-b|-f|-d]\n");
printf("-s directory of system crontabs (defaults to %s)\n", SCRONTABS);
printf("-c directory of per-user crontabs (defaults to %s)\n", CRONTABS);
printf("-t directory of timestamps (defaults to %s)\n", CRONSTAMPS);
printf("-m user@host where should cron output be directed? (defaults to local user)\n");
printf("-M mailer (defaults to %s)\n", SENDMAIL);
printf("-S log to syslog using identity '%s' (default)\n", LOG_IDENT);
printf("-L file log to specified file instead of syslog\n");
printf("-l loglevel log events <= this level (defaults to %s (level %d))\n", LevelAry[LOG_LEVEL], LOG_LEVEL);
printf("-b run in background (default)\n");
printf("-f run in foreground\n");
printf("-d run in debugging mode\n");
printf("crond [-s dir] [-c dir] [-t dir] [-m user@host|file] [-M mailer] [-S|-L [file]] [-l level] [-b|-f|-d]\n");
printf("-s directory of system crontabs (defaults to %s)\n", SCRONTABS);
printf("-c directory of per-user crontabs (defaults to %s)\n", CRONTABS);
printf("-t directory of timestamps (defaults to %s)\n", CRONSTAMPS);
printf("-C create per-user crontabs and timestamps directories, if they do not exists\n");
printf("-m user@host|file where should cron output be directed? (defaults to local user)\n");
printf(" if you specify a file, the email address will be read from the file.\n");
printf("-M mailer (defaults to %s)\n", SENDMAIL);
printf("-S log to syslog using identity '%s' (default)\n", LOG_IDENT);
printf("-L file log to specified file instead of syslog\n");
printf("-l loglevel log events <= this level (defaults to %s (level %d))\n", LevelAry[LOG_LEVEL], LOG_LEVEL);
printf("-b run in background (default)\n");
printf("-f run in foreground\n");
printf("-d run in debugging mode\n");
exit(2);
}
}
Expand Down Expand Up @@ -215,6 +245,19 @@ main(int ac, char **av)
exit(1);
}

if (CreateCronDirsOpt) {
if (mkdir(CDir, 0755) == -1 && errno != EEXIST) {
fdprintf(2, "failed to create %s", CDir);
perror(": ");
exit(1);
}
if (mkdir(TSDir, 0755) == -1 && errno != EEXIST) {
fdprintf(2, "failed to create %s", TSDir);
perror(": ");
exit(1);
}
}

if (ForegroundOpt == 0) {

int fd;
Expand Down Expand Up @@ -269,11 +312,12 @@ main(int ac, char **av)
/* daemon in foreground */

/* stay in existing session, but start a new process group */
if (setpgid(0,0)) {
perror("setpgid");
exit(1);
if (getsid(0) != getpid()) {
if (setpgid(0,0)) {
perror("setpgid");
exit(1);
}
}

/* stderr stays open, start SIGHUP ignoring, SIGCHLD handling */
initsignals();
}
Expand Down Expand Up @@ -305,6 +349,11 @@ main(int ac, char **av)
for (;;) {
sleep((stime + 1) - (short)(time(NULL) % stime));

if (Quit) {
fdprintf(2, "\n"); // print new line in case of Ctrl-C
break;
}

t2 = time(NULL);
dt = t2 - t1;

Expand Down Expand Up @@ -338,7 +387,7 @@ main(int ac, char **av)
SynchronizeDir(SCDir, "root", 0);
ReadTimestamps(NULL);
}
}
}
if (rescan < 60) {
CheckUpdates(CDir, NULL, t1, t2);
CheckUpdates(SCDir, "root", t1, t2);
Expand All @@ -360,6 +409,5 @@ main(int ac, char **av)
}
}
}
/* not reached */
}

29 changes: 28 additions & 1 deletion subs.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ void waitmailjob(int sig) {
/* if all children still running, child == 0 */
}

void quit(int sig) {
Quit = 1;
}

void
initsignals (void) {
struct sigaction sa;
Expand All @@ -157,6 +161,7 @@ initsignals (void) {
fdprintf(2, "failed to start SIGHUP handling, reason: %s", strerror(errno));
exit(n);
}

sa.sa_flags = SA_RESTART;
sa.sa_handler = waitmailjob;
if (sigaction (SIGCHLD, &sa, NULL) != 0) {
Expand All @@ -165,5 +170,27 @@ initsignals (void) {
exit(n);
}

}
sa.sa_flags = SA_RESTART;
sa.sa_handler = quit;
if (sigaction (SIGINT, &sa, NULL) != 0) {
n = errno;
fdprintf(2, "failed to start SIGINT handling, reason: %s", strerror(errno));
exit(n);
}

sa.sa_flags = SA_RESTART;
sa.sa_handler = quit;
if (sigaction (SIGTERM, &sa, NULL) != 0) {
n = errno;
fdprintf(2, "failed to start SIGTERM handling, reason: %s", strerror(errno));
exit(n);
}

sa.sa_flags = SA_RESTART;
sa.sa_handler = quit;
if (sigaction (SIGQUIT, &sa, NULL) != 0) {
n = errno;
fdprintf(2, "failed to start SIGQUIT handling, reason: %s", strerror(errno));
exit(n);
}
}