Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 2009 02:53:04 GMT
From:      Benjamin Lee <ben@b1c1l1.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   ports/140621: Add support for /etc/cron.d and /usr/local/etc/cron.d in sysutils/isc-cron port
Message-ID:  <200911170253.nAH2r4Qn029255@www.freebsd.org>
Resent-Message-ID: <200911170300.nAH30Cjt032497@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911170253.nAH2r4Qn029255>