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:
M | LICENSE | | | 37 | +++++++++++++++++-------------------- |
M | Makefile | | | 6 | +++--- |
M | README | | | 8 | +++++--- |
M | crond.c | | | 132 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
M | crontab | | | 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