scron

simple cron daemon
git clone git://git.2f30.org/scron
Log | Files | Refs | README | LICENSE

commit 981a9bc6275358bb6086d72268d4939062377c45
parent 14af07d106cc15fa0f7258fd1e4d1432ffe4269e
Author: Ari Malinen <ari.malinen@gmail.com>
Date:   Fri, 27 Jun 2014 16:52:28 +0300

modularized code, sepport for range of time in crontab

Diffstat:
MLICENSE | 37+++++++++++++++++--------------------
MMakefile | 6+++---
MREADME | 8+++++---
Mcrond.c | 132+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mcrontab | 1-
5 files changed, 111 insertions(+), 73 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -1,23 +1,21 @@ -Copyright (c) 2014, Ari Malinen -All rights reserved. +MIT/X Consortium License -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +© 2014 Ari Malinen <ari.malinen@gmail.com> -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile @@ -1,12 +1,12 @@ -CFLAGS+=-std=c99 -Wall -Wextra -pedantic +CFLAGS+=-std=c99 -Wall -pedantic all: crond -install: crond +install: all mkdir -p ${DESTDIR}/sbin mkdir -p ${DESTDIR}/etc/init.d install -m 755 crond ${DESTDIR}/sbin/ - install -m 755 init.d/crond ${DESTDIR}/etc/init.d/ + install -m 755 crond.init ${DESTDIR}/etc/init.d/crond install -m 644 crontab ${DESTDIR}/etc/ uninstall: diff --git a/README b/README @@ -6,6 +6,7 @@ features Schedule tasks. Single daemon, config and initscript. Log to stdout and syslog. +No mail support. usage ----- @@ -14,7 +15,8 @@ usage: crond [options] -d daemon -f <file> config file -config ------- +example config +-------------- # tm_min, tm_hour, tm_mday, tm_mon, tm_wday, command -0 5 * * * updatedb +0 5 * * * updatedb # 06:00 every day +29 4 * * 1-5 emerge --sync # 5:30 every weekday diff --git a/crond.c b/crond.c @@ -1,5 +1,5 @@ -#include <stdio.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <ctype.h> #include <time.h> @@ -47,14 +47,89 @@ void arg(int argc, char *argv[]) { } } -int main(int argc, char *argv[]) { - char line[LEN+1]; - char *endptr, *col; - int y, x; - int status, entry; +int parsecolumn(char *col, int y, int x) { + int entry, entry2; + char *endptr, *endptr2; time_t t; struct tm *tm; + + t = time(NULL); + tm = localtime(&t); + + if (x >= 0 && x <= 4) { + endptr = ""; + entry = strtol(col, &endptr, 0); + if (!strcmp("*", col)) { + return 0; + } else if (*endptr == '-') { + endptr++; + endptr2 = ""; + entry2 = strtol(endptr, &endptr2, 0); + if (*endptr2 != '\0' || entry2 < 0 || entry2 > 59) { + fprintf(stderr, "error: %s line %d column %d\n", config, y+1, x+1); + syslog(LOG_NOTICE, "error: %s line %d column %d", config, y+1, x+1); + return 1; + } else if ((x == 0 && entry <= tm->tm_min && entry2 >= tm->tm_min) || + (x == 1 && entry <= tm->tm_hour && entry2 >= tm->tm_hour) || + (x == 2 && entry <= tm->tm_mday && entry2 >= tm->tm_mday) || + (x == 3 && entry <= tm->tm_mon && entry2 >= tm->tm_mon) || + (x == 4 && entry <= tm->tm_wday && entry2 >= tm->tm_wday)) { + return 0; + } + } else if (*endptr != '\0' || entry < 0 || entry > 59) { + fprintf(stderr, "error: %s line %d column %d\n", config, y+1, x+1); + syslog(LOG_NOTICE, "error: %s line %d column %d", config, y+1, x+1); + return 1; + } else if ((x == 0 && entry == tm->tm_min) || + (x == 1 && entry == tm->tm_hour) || + (x == 2 && entry == tm->tm_mday) || + (x == 3 && entry == tm->tm_mon) || + (x == 4 && entry == tm->tm_wday)) { + return 0; + } + } + + return 1; +} + +void runjob(char *cmd) { + time_t t; pid_t pid; + + t = time(NULL); + + pid = fork(); + if (pid < 0) { + fprintf(stderr, "error: failed to fork job: %s time: %s", cmd, ctime(&t)); + syslog(LOG_NOTICE, "error: failed to fork job: %s", cmd); + } else if (pid == 0) { + printf("run: %s pid: %d time: %s", cmd, (int) getpid(), ctime(&t)); + syslog(LOG_NOTICE, "run: %s pid: %d", cmd, (int) getpid()); + execl("/bin/sh", "/bin/sh", "-c", cmd, (char *) NULL); + fprintf(stderr, "error: job failed: %s time: %s\n", cmd, ctime(&t)); + syslog(LOG_NOTICE, "error: job failed: %s", cmd); + exit(EXIT_FAILURE); + } +} + +void checkreturn(void) { + int status; + time_t t; + pid_t pid; + + t = time(NULL); + + while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { + printf("complete: pid %d, return: %d time: %s", (int) pid, status, ctime(&t)); + syslog(LOG_NOTICE, "complete: pid: %d return: %d", (int) pid, status); + } +} + +int main(int argc, char *argv[]) { + int y, x; + char line[LEN+1]; + char *col; + time_t t; FILE *fp; openlog(argv[0], LOG_CONS | LOG_PID, LOG_LOCAL1); @@ -64,8 +139,6 @@ int main(int argc, char *argv[]) { while (1) { t = time(NULL); sleep(60 - t % 60); - t = time(NULL); - tm = localtime(&t); if ((fp = fopen(config, "r")) == NULL) { fprintf(stderr, "error: cant read %s\n", config); @@ -80,50 +153,17 @@ int main(int argc, char *argv[]) { strtok(line, "\n"); for (x = 0, col = strtok(line,"\t"); col; x++, col = strtok(NULL, "\t")) { - if (x >= 0 && x <= 4) { - endptr = ""; - entry = strtol(col, &endptr, 0); - if (!strcmp("*", col)) - continue; - else if (!strcmp("", col) || !isdigit(col[0]) || - *col < 0 || *col > 59 || *endptr != '\0') { - fprintf(stderr, "error: %s line %d column %d\n", config, y+1, x+1); - syslog(LOG_NOTICE, "error: %s line %d column %d", config, y+1, x+1); - } else if ((x == 0 && entry == tm->tm_min) || - (x == 1 && entry == tm->tm_hour) || - (x == 2 && entry == tm->tm_mday) || - (x == 3 && entry == tm->tm_mon) || - (x == 4 && entry == tm->tm_wday)) - continue; - } - - if (x == 5) { - pid = fork(); - if (pid < 0) { - fprintf(stderr, "error: failed to fork job: %s", col); - syslog(LOG_NOTICE, "error: failed to fork job: %s", col); - } else if (pid == 0) { - printf("run: %s pid: %d time: %s", col, (int) getpid(), ctime(&t)); - syslog(LOG_NOTICE, "run: %s pid: %d", col, (int) getpid()); - - execl("/bin/sh", "/bin/sh", "-c", col, (char *) NULL); - - fprintf(stderr, "error: job failed: %s", col); - syslog(LOG_NOTICE, "error: job failed: %s", col); - return 1; - } - } + if (!parsecolumn(col, y, x)) + continue; + else if (x == 5) + runjob(col); break; } } fclose(fp); - - while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { - printf("complete: pid %d, return: %d time: %s", (int) pid, status, ctime(&t)); - syslog(LOG_NOTICE, "complete: pid: %d return: %d", (int) pid, status); - } + checkreturn(); } closelog(); diff --git a/crontab b/crontab @@ -1,2 +1 @@ # tm_min, tm_hour, tm_mday, tm_mon, tm_wday, command -0 5 * * * updatedb