ports/140621: Add support for /etc/cron.d and /usr/local/etc/cron.d in sysutils/isc-cron port
Benjamin Lee
ben at b1c1l1.com
Tue Nov 17 03:00:13 UTC 2009
>Number: 140621
>Category: ports
>Synopsis: Add support for /etc/cron.d and /usr/local/etc/cron.d in sysutils/isc-cron port
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Tue Nov 17 03:00:12 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: Benjamin Lee
>Release: 7.2-RELEASE
>Organization:
>Environment:
FreeBSD eclipse.b1c1l1.com 7.2-RELEASE-p4 FreeBSD 7.2-RELEASE-p4 #0: Fri Oct 2 12:21:39 UTC 2009 root at i386-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC i386
>Description:
The attached patch is an enhancement for the sysutils/isc-cron port. It enables searching and parsing the /etc/cron.d and /usr/local/etc/cron.d directories for additional crontab files.
>How-To-Repeat:
>Fix:
Patch attached with submission follows:
diff -ruN isc-cron.orig/Makefile isc-cron/Makefile
--- isc-cron.orig/Makefile 2009-10-19 16:07:29.320158000 -0700
+++ isc-cron/Makefile 2009-11-16 18:43:53.000000000 -0800
@@ -25,6 +25,15 @@
MAN5= crontab.5
MAN8= cron.8
+OPTIONS= \
+ CROND "Enable cron.d support" Off
+
+.include <bsd.port.pre.mk>
+
+.if defined(WITH_CROND)
+EXTRA_PATCHES+= ${FILESDIR}/opt-patch-cron.d
+.endif
+
do-extract:
${MKDIR} ${WRKSRC}
cd ${WRKSRC} && ${SH} ${DISTDIR}/${DISTNAME}
@@ -41,4 +50,4 @@
post-install:
${CAT} ${PKGMESSAGE}
-.include <bsd.port.mk>
+.include <bsd.port.post.mk>
diff -ruN isc-cron.orig/files/opt-patch-cron.d isc-cron/files/opt-patch-cron.d
--- isc-cron.orig/files/opt-patch-cron.d 1969-12-31 16:00:00.000000000 -0800
+++ isc-cron/files/opt-patch-cron.d 2009-11-16 18:43:53.000000000 -0800
@@ -0,0 +1,153 @@
+diff -ru isc-cron-4.1.orig/FEATURES isc-cron-4.1/FEATURES
+--- FEATURES 2009-10-01 17:40:45.000000000 -0700
++++ FEATURES 2009-10-08 17:22:22.000000000 -0700
+@@ -82,3 +82,8 @@
+ act this way and do the more reasonable thing, which is (IMHO) to "or"
+ the various field-matches together. In that sense this cron may not
+ be completely similar to some AT&T crons.
++
++-- If they exist, the /etc/cron.d/ and /usr/local/etc/cron.d/ directories
++ are parsed like the cron spool directory, except that the files in it
++ are not user-specific and are therefore read with /etc/crontab syntax
++ (the user is specified explicitly in the 6th column).
+diff -ru isc-cron-4.1.orig/cron.8 isc-cron-4.1/cron.8
+--- cron.8 2009-10-01 17:40:45.000000000 -0700
++++ cron.8 2009-10-08 17:08:21.000000000 -0700
+@@ -39,7 +39,8 @@
+ searches /var/cron/tabs for crontab files which are named after accounts in
+ /etc/passwd; crontabs found are loaded into memory.
+ .I Cron
+-also searches for /etc/crontab which is in a different format (see
++also searches for /etc/crontab and the files in the /etc/cron.d/ and
++/usr/local/etc/cron.d/ directories, which are in a different format (see
+ .IR crontab (5)).
+ .I Cron
+ then wakes up every minute, examining all stored crontabs, checking each
+diff -ru isc-cron-4.1.orig/database.c isc-cron-4.1/database.c
+--- database.c 2009-10-01 17:40:45.000000000 -0700
++++ database.c 2009-10-08 17:20:53.000000000 -0700
+@@ -36,7 +36,7 @@
+
+ void
+ load_database(cron_db *old_db) {
+- struct stat statbuf, syscron_stat;
++ struct stat statbuf, syscron_stat, crond_stat, usrcrond_stat;
+ cron_db new_db;
+ DIR_T *dp;
+ DIR *dir;
+@@ -53,6 +53,16 @@
+ (void) exit(ERROR_EXIT);
+ }
+
++ if (stat(CROND_DIR, &crond_stat) < OK) {
++ log_it("CRON", getpid(), "STAT FAILED", CROND_DIR);
++ (void) exit(ERROR_EXIT);
++ }
++
++ if (stat(USRCROND_DIR, &usrcrond_stat) < OK) {
++ log_it("CRON", getpid(), "STAT FAILED", USRCROND_DIR);
++ (void) exit(ERROR_EXIT);
++ }
++
+ /* track system crontab file
+ */
+ if (stat(SYSCRONTAB, &syscron_stat) < OK)
+@@ -65,7 +75,9 @@
+ * 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 == TMAX(usrcrond_stat.st_mtime,
++ TMAX(crond_stat.st_mtime,
++ TMAX(statbuf.st_mtime, syscron_stat.st_mtime)))) {
+ Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n",
+ (long)getpid()))
+ return;
+@@ -76,13 +88,73 @@
+ * 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 = TMAX(usrcrond_stat.st_mtime,
++ TMAX(crond_stat.st_mtime,
++ TMAX(statbuf.st_mtime, syscron_stat.st_mtime)));
+ new_db.head = new_db.tail = NULL;
+
+ if (syscron_stat.st_mtime)
+ process_crontab("root", NULL, SYSCRONTAB, &syscron_stat,
+ &new_db, old_db);
+
++ if (!(dir = opendir(CROND_DIR))) {
++ log_it("CRON", getpid(), "OPENDIR FAILED", CROND_DIR);
++ (void) exit(ERROR_EXIT);
++ }
++
++ while (NULL != (dp = readdir(dir))) {
++ char fname[MAXNAMLEN+1],
++ tabname[MAXNAMLEN+1];
++
++ /* avoid file names beginning with ".". this is good
++ * because we would otherwise waste two guaranteed calls
++ * to getpwnam() for . and .., and there shouldn't be
++ * hidden files in here anyway. Also ignore files beginning
++ * with '#' and ending with '~'.
++ */
++ if (dp->d_name[0] == '.' ||
++ dp->d_name[0] == '#' ||
++ dp->d_name[strlen(dp->d_name) - 1] == '~')
++ continue;
++
++ (void) strncpy(fname, dp->d_name, MAXNAMLEN);
++ snprintf(tabname, MAXNAMLEN+1, "%s/%s", CROND_DIR, fname);
++
++ process_crontab("root", NULL, tabname,
++ &crond_stat, &new_db, old_db);
++ }
++ closedir(dir);
++
++
++ if (!(dir = opendir(USRCROND_DIR))) {
++ log_it("CRON", getpid(), "OPENDIR FAILED", USRCROND_DIR);
++ (void) exit(ERROR_EXIT);
++ }
++
++ while (NULL != (dp = readdir(dir))) {
++ char fname[MAXNAMLEN+1],
++ tabname[MAXNAMLEN+1];
++
++ /* avoid file names beginning with ".". this is good
++ * because we would otherwise waste two guaranteed calls
++ * to getpwnam() for . and .., and there shouldn't be
++ * hidden files in here anyway. Also ignore files beginning
++ * with '#' and ending with '~'.
++ */
++ if (dp->d_name[0] == '.' ||
++ dp->d_name[0] == '#' ||
++ dp->d_name[strlen(dp->d_name) - 1] == '~')
++ continue;
++
++ (void) strncpy(fname, dp->d_name, MAXNAMLEN);
++ snprintf(tabname, MAXNAMLEN+1, "%s/%s", USRCROND_DIR, fname);
++
++ process_crontab("root", NULL, tabname,
++ &usrcrond_stat, &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 -ru isc-cron-4.1.orig/pathnames.h isc-cron-4.1/pathnames.h
+--- pathnames.h 2009-10-01 17:40:45.000000000 -0700
++++ pathnames.h 2009-10-08 17:45:34.000000000 -0700
+@@ -48,6 +48,9 @@
+ */
+ #define SPOOL_DIR "tabs"
+
++#define CROND_DIR "/etc/cron.d"
++#define USRCROND_DIR "/usr/local/etc/cron.d"
++
+ /* cron allow/deny file. At least cron.deny must
+ * exist for ordinary users to run crontab.
+ */
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list