summaryrefslogtreecommitdiffstats
path: root/usr.sbin/cron
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2016-11-16 07:03:24 +0000
committerbapt <bapt@FreeBSD.org>2016-11-16 07:03:24 +0000
commit1f6a31cefa15fc288e68fd28341349da9769513b (patch)
treea6ceb18a7cc9bb1a96af1f2bfd854283fb215e4a /usr.sbin/cron
parentcbe6fc290ffa55727150015d8214b00a54fd6e97 (diff)
downloadFreeBSD-src-1f6a31cefa15fc288e68fd28341349da9769513b.zip
FreeBSD-src-1f6a31cefa15fc288e68fd28341349da9769513b.tar.gz
MFC r308139, r308157-r308158
r308139: cron(8): add support for /etc/cron.d and /usr/local/etc/cron.d For automation tools it is way easier to maintain files in directories rather than modifying /etc/crontab. The files in those directories are in the same format as /etc/crontab Reviewed by: adrian MFC after: 2 weeks Relnotes: yes Sponsored by: Gandi.net Differential Revision: https://reviews.freebsd.org/D8400 r308157: Fix typo in cron(8) date Reported by: jilles r308158: Allow symlinks to be followed in cron.d directories and fix detection of regular files on NFS Reported by: jilles
Diffstat (limited to 'usr.sbin/cron')
-rw-r--r--usr.sbin/cron/cron/cron.88
-rw-r--r--usr.sbin/cron/cron/cron.h2
-rw-r--r--usr.sbin/cron/cron/database.c49
-rw-r--r--usr.sbin/cron/cron/pathnames.h2
-rw-r--r--usr.sbin/cron/lib/misc.c6
5 files changed, 56 insertions, 11 deletions
diff --git a/usr.sbin/cron/cron/cron.8 b/usr.sbin/cron/cron/cron.8
index b765c64..1bc04bd 100644
--- a/usr.sbin/cron/cron/cron.8
+++ b/usr.sbin/cron/cron/cron.8
@@ -17,7 +17,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 21, 2016
+.Dd October 31, 2016
.Dt CRON 8
.Os
.Sh NAME
@@ -53,7 +53,11 @@ The
.Nm
utility also searches for
.Pa /etc/crontab
-which is in a different format (see
+and files in
+.Pa /etc/cron.d
+and
+.Pa /usr/local/etc/cron.d
+which are in a different format (see
.Xr crontab 5 ) .
.Pp
The
diff --git a/usr.sbin/cron/cron/cron.h b/usr.sbin/cron/cron/cron.h
index 60b2a90..a6810be 100644
--- a/usr.sbin/cron/cron/cron.h
+++ b/usr.sbin/cron/cron/cron.h
@@ -218,7 +218,7 @@ void set_cron_uid(void),
unget_char(int, FILE *),
free_entry(entry *),
skip_comments(FILE *),
- log_it(char *, int, char *, char *),
+ log_it(char *, int, char *, const char *),
log_close(void);
int job_runqueue(void),
diff --git a/usr.sbin/cron/cron/database.c b/usr.sbin/cron/cron/database.c
index 7a44d14..2b0c67b 100644
--- a/usr.sbin/cron/cron/database.c
+++ b/usr.sbin/cron/cron/database.c
@@ -44,10 +44,19 @@ load_database(old_db)
{
DIR *dir;
struct stat statbuf;
- struct stat syscron_stat;
+ struct stat syscron_stat, st;
+ time_t maxmtime;
DIR_T *dp;
cron_db new_db;
user *u, *nu;
+ struct {
+ const char *name;
+ struct stat st;
+ } syscrontabs [] = {
+ { SYSCRONTABS },
+ { LOCALSYSCRONTABS }
+ };
+ int i;
Debug(DLOAD, ("[%d] load_database()\n", getpid()))
@@ -65,6 +74,16 @@ load_database(old_db)
if (stat(SYSCRONTAB, &syscron_stat) < OK)
syscron_stat.st_mtime = 0;
+ maxmtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
+
+ for (i = 0; i < nitems(syscrontabs); i++) {
+ if (stat(syscrontabs[i].name, &syscrontabs[i].st) != -1) {
+ maxmtime = TMAX(syscrontabs[i].st.st_mtime, maxmtime);
+ } else {
+ syscrontabs[i].st.st_mtime = 0;
+ }
+ }
+
/* if spooldir's mtime has not changed, we don't need to fiddle with
* the database.
*
@@ -72,7 +91,7 @@ load_database(old_db)
* so is guaranteed to be different than the stat() mtime the first
* time this function is called.
*/
- if (old_db->mtime == TMAX(statbuf.st_mtime, syscron_stat.st_mtime)) {
+ if (old_db->mtime == maxmtime) {
Debug(DLOAD, ("[%d] spool dir mtime unch, no load needed.\n",
getpid()))
return;
@@ -83,7 +102,7 @@ load_database(old_db)
* actually changed. Whatever is left in the old database when
* we're done is chaff -- crontabs that disappeared.
*/
- new_db.mtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
+ new_db.mtime = maxmtime;
new_db.head = new_db.tail = NULL;
if (syscron_stat.st_mtime) {
@@ -92,6 +111,30 @@ load_database(old_db)
&new_db, old_db);
}
+ for (i = 0; i < nitems(syscrontabs); i++) {
+ char tabname[MAXPATHLEN];
+ if (syscrontabs[i].st.st_mtime == 0)
+ continue;
+ if (!(dir = opendir(syscrontabs[i].name))) {
+ log_it("CRON", getpid(), "OPENDIR FAILED",
+ syscrontabs[i].name);
+ (void) exit(ERROR_EXIT);
+ }
+
+ while (NULL != (dp = readdir(dir))) {
+ if (dp->d_name[0] == '.')
+ continue;
+ if (fstatat(dirfd(dir), dp->d_name, &st, 0) == 0 &&
+ !S_ISREG(st.st_mode))
+ continue;
+ snprintf(tabname, sizeof(tabname), "%s/%s",
+ syscrontabs[i].name, dp->d_name);
+ process_crontab("root", SYS_NAME, tabname,
+ &syscrontabs[i].st, &new_db, old_db);
+ }
+ closedir(dir);
+ }
+
/* we used to keep this dir open all the time, for the sake of
* efficiency. however, we need to close it in every fork, and
* we fork a lot more often than the mtime of the dir changes.
diff --git a/usr.sbin/cron/cron/pathnames.h b/usr.sbin/cron/cron/pathnames.h
index ba91bfd..fe3ebf5 100644
--- a/usr.sbin/cron/cron/pathnames.h
+++ b/usr.sbin/cron/cron/pathnames.h
@@ -62,6 +62,8 @@
/* 4.3BSD-style crontab */
#define SYSCRONTAB "/etc/crontab"
+#define SYSCRONTABS "/etc/cron.d"
+#define LOCALSYSCRONTABS "/usr/local/etc/cron.d"
/* what editor to use if no EDITOR or VISUAL
* environment variable specified.
diff --git a/usr.sbin/cron/lib/misc.c b/usr.sbin/cron/lib/misc.c
index afed07f..6a0b8ac 100644
--- a/usr.sbin/cron/lib/misc.c
+++ b/usr.sbin/cron/lib/misc.c
@@ -385,11 +385,7 @@ out: if (allow)
void
-log_it(username, xpid, event, detail)
- char *username;
- int xpid;
- char *event;
- char *detail;
+log_it(char *username, int xpid, char *event, const char *detail)
{
#if defined(LOG_FILE) || DEBUGGING
PID_T pid = xpid;
OpenPOWER on IntegriCloud