Module Name:    src
Committed By:   christos
Date:           Wed Oct 12 16:39:48 UTC 2011

Modified Files:
        src/external/bsd/cron/dist: cron.8 database.c pathnames.h

Log Message:
process files in /etc/cron.d/


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/external/bsd/cron/dist/cron.8 \
    src/external/bsd/cron/dist/database.c \
    src/external/bsd/cron/dist/pathnames.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/cron/dist/cron.8
diff -u src/external/bsd/cron/dist/cron.8:1.3 src/external/bsd/cron/dist/cron.8:1.4
--- src/external/bsd/cron/dist/cron.8:1.3	Sat May  8 07:55:01 2010
+++ src/external/bsd/cron/dist/cron.8	Wed Oct 12 12:39:48 2011
@@ -1,8 +1,8 @@
-.\"	$NetBSD: cron.8,v 1.3 2010/05/08 11:55:01 wiz Exp $
+.\"	$NetBSD: cron.8,v 1.4 2011/10/12 16:39:48 christos Exp $
 .\"
 .\" Id: cron.8,v 1.8 2004/01/23 19:03:32 vixie Exp
 .\"
-.Dd May 5, 2010
+.Dd October 12, 2011
 .Dt CRON 8
 .Os
 .Sh NAME
@@ -33,6 +33,40 @@ also searches for
 .Pa /etc/crontab
 which is in a different format (see
 .Xr crontab 5 ) .
+Finally
+.Nm
+looks for crontabs in
+.Pa /etc/cron.d
+if it exists, and executes each file as a crontab.
+.Pp
+When
+.Nm
+looks in a directory for crontabs (either in
+.Pa /var/cron/tabs
+or
+.Pa /etc/cron.d )
+it will not process files that:
+.Bl -dash -compact -offset indent
+.It
+Start with a 
+.Sq \&. 
+or a
+.Sq # .
+.It
+End with a
+.Sq ~ 
+or with
+.Dq .rpmsave ,
+.Dq .rpmorig ,
+or
+.Dq .rpmnew .
+.It
+Are of zero length.
+.It
+Their length is greater than
+.Dv MAXNAMLEN .
+.El
+.Pp
 .Nm
 then wakes up every minute, examining all stored crontabs, checking each
 command to see if it should be run in the current minute.
@@ -57,7 +91,9 @@ Additionally,
 .Nm
 checks each minute to see if its spool directory's modtime (or the modtime
 on
-.Pa /etc/crontab )
+.Pa /etc/crontab 
+or
+.Pa /etc/cron.d )
 has changed, and if it has,
 .Nm
 will then examine the modtime on all crontabs and reload those which have
@@ -131,7 +167,9 @@ Naturally this is not relevant if cron w
 .Nm
 spool directory
 .It Pa /etc/crontab
-system crontab
+system crontab file
+.It Pa /etc/cron.d/
+system crontab directory
 .It Pa /var/log/cron
 log file for cron events
 .El
Index: src/external/bsd/cron/dist/database.c
diff -u src/external/bsd/cron/dist/database.c:1.3 src/external/bsd/cron/dist/database.c:1.4
--- src/external/bsd/cron/dist/database.c:1.3	Thu Jul 15 16:04:14 2010
+++ src/external/bsd/cron/dist/database.c	Wed Oct 12 12:39:48 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: database.c,v 1.3 2010/07/15 20:04:14 christos Exp $	*/
+/*	$NetBSD: database.c,v 1.4 2011/10/12 16:39:48 christos Exp $	*/
 
 /* Copyright 1988,1990,1993,1994 by Paul Vixie
  * All rights reserved
@@ -25,7 +25,7 @@
 #if 0
 static char rcsid[] = "Id: database.c,v 1.7 2004/01/23 18:56:42 vixie Exp";
 #else
-__RCSID("$NetBSD: database.c,v 1.3 2010/07/15 20:04:14 christos Exp $");
+__RCSID("$NetBSD: database.c,v 1.4 2011/10/12 16:39:48 christos Exp $");
 #endif
 #endif
 
@@ -40,13 +40,87 @@ static	void		process_crontab(const char 
 					const char *, struct stat *,
 					cron_db *, cron_db *);
 
+static void
+process_dir(const char *dname, struct stat *st, int sys, cron_db *new_db,
+    cron_db *old_db)
+{
+	DIR *dir;
+	DIR_T *dp;
+
+	/* 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.
+	 */
+	if (!(dir = opendir(dname))) {
+		log_it("CRON", getpid(), "OPENDIR FAILED", dname);
+		(void) exit(ERROR_EXIT);
+	}
+
+	while (NULL != (dp = readdir(dir))) {
+		char	fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
+		size_t i, len;
+		/*
+		 * Homage to...
+		 */
+		static const char *junk[] = {
+			".rpmsave", ".rpmorig", ".rpmnew",
+		};
+
+		/* 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 (in the non system case).
+		 */
+		if (dp->d_name[0] == '.')
+			continue;
+
+		/* ignore files starting with # ... */
+		if (dp->d_name[0] == '#')
+			continue;
+		
+		len = strlen(dp->d_name);
+
+		/* ... or too big or to small ... */
+		if (len == 0 || len >= sizeof(fname)) {
+			log_it(dp->d_name, getpid(), "ORPHAN",
+			    "name too short or long");
+			continue;
+		}
+
+		/* ... or ending with ~ ... */
+		if ((dp->d_name[len - 1] == '~'))
+			continue;
+
+		(void)strlcpy(fname, dp->d_name, sizeof(fname));
+		
+		/* ... or look leftover crap */
+		for (i = 0; i < __arraycount(junk); i++) {
+			char *p;
+			if ((p = strstr(fname, junk[len])) != NULL &&
+			    p[strlen(junk[len]) - 1] == '\0')
+				break;
+		}
+		if (i != __arraycount(junk))
+			continue;
+
+		if (!glue_strings(tabname, sizeof tabname, dname, fname, '/')) {
+			log_it(fname, getpid(), "ORPHAN",
+			    "could not glue strings");
+			continue;
+		}
+
+		process_crontab(sys ? "root" : fname, sys ? "*system*" :
+				fname, tabname, st, new_db, old_db);
+	}
+	(void)closedir(dir);
+}
+
 void
 load_database(cron_db *old_db) {
-	struct stat statbuf, syscron_stat;
+	struct stat spool_stat, syscron_stat, crond_stat;
 	cron_db new_db;
-	DIR_T *dp;
-	DIR *dir;
 	user *u, *nu;
+	time_t new_mtime;
 
 	Debug(DLOAD, ("[%ld] load_database()\n", (long)getpid()));
 
@@ -54,11 +128,16 @@ load_database(cron_db *old_db) {
 	 * so that if anything changes as of this moment (i.e., before we've
 	 * cached any of the database), we'll see the changes next time.
 	 */
-	if (stat(SPOOL_DIR, &statbuf) < OK) {
+	if (stat(SPOOL_DIR, &spool_stat) < OK) {
 		log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
 		(void) exit(ERROR_EXIT);
 	}
 
+	/* track system crontab directory
+	 */
+	if (stat(CROND_DIR, &crond_stat) < OK)
+		crond_stat.st_mtime = 0;
+
 	/* track system crontab file
 	 */
 	if (stat(SYSCRONTAB, &syscron_stat) < OK)
@@ -71,7 +150,9 @@ load_database(cron_db *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)) {
+	new_mtime = TMAX(crond_stat.st_mtime, TMAX(spool_stat.st_mtime,
+	    syscron_stat.st_mtime));
+	if (old_db->mtime == new_mtime) {
 		Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n",
 			      (long)getpid()));
 		return;
@@ -82,45 +163,17 @@ load_database(cron_db *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 = new_mtime;
 	new_db.head = new_db.tail = NULL;
 
 	if (syscron_stat.st_mtime)
 		process_crontab("root", NULL, SYSCRONTAB, &syscron_stat,
 				&new_db, old_db);
 
-	/* 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.
-	 */
-	if (!(dir = opendir(SPOOL_DIR))) {
-		log_it("CRON", getpid(), "OPENDIR FAILED", SPOOL_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 also because user names
-		 * starting with a period are just too nasty to consider.
-		 */
-		if (dp->d_name[0] == '.')
-			continue;
-
-		if (strlen(dp->d_name) >= sizeof fname)
-			continue;	/* XXX log? */
-		(void)strlcpy(fname, dp->d_name, sizeof(fname));
-		
-		if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR,
-				  fname, '/'))
-			continue;	/* XXX log? */
+	if (crond_stat.st_mtime)
+		process_dir(CROND_DIR, &crond_stat, 1, &new_db, old_db);
 
-		process_crontab(fname, fname, tabname,
-				&statbuf, &new_db, old_db);
-	}
-	(void)closedir(dir);
+	process_dir(SPOOL_DIR, &spool_stat, 0, &new_db, old_db);
 
 	/* if we don't do this, then when our children eventually call
 	 * getpwnam() in do_command.c's child_process to verify MAILTO=,
Index: src/external/bsd/cron/dist/pathnames.h
diff -u src/external/bsd/cron/dist/pathnames.h:1.3 src/external/bsd/cron/dist/pathnames.h:1.4
--- src/external/bsd/cron/dist/pathnames.h:1.3	Wed May 19 08:50:49 2010
+++ src/external/bsd/cron/dist/pathnames.h	Wed Oct 12 12:39:48 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: pathnames.h,v 1.3 2010/05/19 12:50:49 christos Exp $	*/
+/*	$NetBSD: pathnames.h,v 1.4 2011/10/12 16:39:48 christos Exp $	*/
 
 /* Copyright 1993,1994 by Paul Vixie
  * All rights reserved
@@ -86,6 +86,8 @@
 			/* what editor to use if no EDITOR or VISUAL
 			 * environment variable specified.
 			 */
+			/* system V cron dir */
+#define	CROND_DIR	"/etc/cron.d"
 #if defined(_PATH_VI)
 # define EDITOR _PATH_VI
 #else

Reply via email to