Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37039506
en ru br
ALT Linux repos
S:4.1.20060426-alt10.3
5.0: 4.1.20060426-alt6
4.1: 4.1.20060426-alt4
4.0: 4.1.20060426-alt4
3.0: 4.1.20040916-alt2

Group :: System/Servers
RPM: vixie-cron

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: vixie-cron-4.1.20040916-owl-crond.patch
Download


diff -uprk.orig vixie-cron-4.1.20040916.orig/usr.sbin/cron/cron.8 vixie-cron-4.1.20040916/usr.sbin/cron/cron.8
--- vixie-cron-4.1.20040916.orig/usr.sbin/cron/cron.8	2004-12-18 19:06:54 +0300
+++ vixie-cron-4.1.20040916/usr.sbin/cron/cron.8	2004-12-18 19:07:55 +0300
@@ -181,6 +181,8 @@ logs via
 .Bl -tag -width "/var/spool/cron/.sock" -compact
 .It Pa /etc/crontab
 system crontab file
+.It Pa /etc/cron.d
+directory containing system crontab files
 .It Pa /var/spool/at
 directory containing
 .Xr at 1
diff -uprk.orig vixie-cron-4.1.20040916.orig/usr.sbin/cron/database.c vixie-cron-4.1.20040916/usr.sbin/cron/database.c
--- vixie-cron-4.1.20040916.orig/usr.sbin/cron/database.c	2004-06-22 07:15:33 +0400
+++ vixie-cron-4.1.20040916/usr.sbin/cron/database.c	2004-12-18 19:12:53 +0300
@@ -32,6 +32,18 @@ static char const rcsid[] = "$OpenBSD: d
 
 #define HASH(a,b) ((a)+(b))
 
+struct spooldir {
+	char *path;
+	char *uname;
+	char *fname;
+};
+
+static struct spooldir spools[] = {
+	{SPOOL_DIR, NULL, NULL},
+	{"/etc/cron.d", "root", "*system*"},
+	{NULL, NULL, NULL}
+};
+
 static	void		process_crontab(const char *, const char *,
 					const char *, struct stat *,
 					cron_db *, cron_db *);
@@ -44,22 +56,27 @@ load_database(cron_db *old_db) {
 	DIR *dir;
 	user *u, *nu;
 
-	Debug(DLOAD, ("[%ld] load_database()\n", (long)getpid()))
+	struct spooldir *p = spools;
+	time_t maxtime;
 
-	/* before we start loading any data, do a stat on SPOOL_DIR
-	 * 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) {
-		log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
-		(void) exit(ERROR_EXIT);
-	}
+	Debug(DLOAD, ("[%ld] load_database()\n", (long)getpid()))
 
 	/* track system crontab file
 	 */
 	if (stat(SYSCRONTAB, &syscron_stat) < OK)
 		syscron_stat.st_mtime = 0;
 
+	maxtime = syscron_stat.st_mtime;
+	while (p->path) {
+		if (stat(p->path, &statbuf) < OK) {
+			log_it("CRON", getpid(), "STAT FAILED", p->path);
+			(void) exit(ERROR_EXIT);
+		}
+		if (statbuf.st_mtime > maxtime)
+			maxtime = statbuf.st_mtime;
+		p++;
+	}
+
 	/* if spooldir's mtime has not changed, we don't need to fiddle with
 	 * the database.
 	 *
@@ -67,7 +84,7 @@ 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 == HASH(statbuf.st_mtime, syscron_stat.st_mtime)) {
+	if (old_db->mtime == maxtime) {
 		Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n",
 			      (long)getpid()))
 		return;
@@ -78,46 +95,56 @@ 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 = HASH(statbuf.st_mtime, syscron_stat.st_mtime);
+	new_db.mtime = maxtime;
 	new_db.head = new_db.tail = NULL;
 
 	if (syscron_stat.st_mtime) {
-		process_crontab(ROOT_USER, NULL, SYSCRONTAB, &syscron_stat,
+		process_crontab(ROOT_USER, "*system*", 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];
-
-		/* 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 (strlcpy(fname, dp->d_name, sizeof fname) >= sizeof fname)
-			continue;	/* XXX log? */
-
-		if (snprintf(tabname, sizeof tabname, "%s/%s", SPOOL_DIR, fname) >=
-			sizeof(tabname))
-			continue;	/* XXX log? */
-
-		process_crontab(fname, fname, tabname,
-				&statbuf, &new_db, old_db);
-	}
-	closedir(dir);
-
+	p = spools;
+ 	while (p->path) {
+ 		if (!(dir = opendir(p->path))) {
+ 			log_it("CRON", getpid(), "OPENDIR FAILED", p->path);
+ 			(void) exit(ERROR_EXIT);
+ 		}
+ 
+ 		while (NULL != (dp = readdir(dir))) {
+ 			char	fname[MAXNAMLEN+1], tabname[MAXPATHLEN];
+ 
+ 			/* Don't try to parse any files containing a dot ('.')
+ 			 * or ending with a tilde ('~'). This catches the case
+			 * of '.' and '..', as well as preventing the parsing
+			 * of many editor files, temporary files and those
+			 * saved by RPM package upgrades.
+ 			 */
+ 			if ( !dp->d_name[0] /* Shouldn't happen */ || 
+ 			      strchr(dp->d_name, '.') ||
+ 			      dp->d_name[strlen(dp->d_name)-1] == '~')
+ 				continue;
+
+			if (strlcpy(fname, dp->d_name, sizeof fname) >= sizeof fname)
+				continue;	/* XXX log? */
+ 
+			if (snprintf(tabname, sizeof tabname, "%s/%s", p->path, fname) >=
+				sizeof(tabname))
+				continue;	/* XXX log? */
+
+ 			process_crontab(p->uname ? p->uname : fname,
+ 					p->fname ? p->fname : fname,
+ 					tabname,
+ 					&statbuf, &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.
+  		 */
+  
+ 		p++;
+  	}
+	
 	/* if we don't do this, then when our children eventually call
 	 * getpwnam() in do_command.c's child_process to verify MAILTO=,
 	 * they will screw us up (and v-v).
@@ -180,19 +207,34 @@ process_crontab(const char *uname, const
 {
 	struct passwd *pw = NULL;
 	int crontab_fd = OK - 1;
+	struct stat lstatbuf;
 	user *u;
 
-	if (fname == NULL) {
-		/* must be set to something for logging purposes.
-		 */
-		fname = "*system*";
-	} else if ((pw = getpwnam(uname)) == NULL) {
+	if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
 		/* file doesn't have a user in passwd file.
-		 */
+		 * 		 */
 		log_it(fname, getpid(), "ORPHAN", "no passwd entry");
 		goto next_crontab;
 	}
 
+	if (lstat(tabname, &lstatbuf) < OK) {
+		log_it(fname, getpid(), "CAN'T LSTAT", tabname);
+		goto next_crontab;
+	}
+	if (!S_ISREG(lstatbuf.st_mode)) {
+		log_it(fname, getpid(), "NOT REGULAR", tabname);
+		goto next_crontab;
+	}
+	if ((!pw && (lstatbuf.st_mode & 07533) != 0400) ||
+	    (pw && (lstatbuf.st_mode & 07577) != 0400)) {
+		log_it(fname, getpid(), "BAD FILE MODE", tabname);
+		goto next_crontab;
+	}
+	if (lstatbuf.st_nlink != 1) {
+		log_it(fname, getpid(), "BAD LINK COUNT", tabname);
+		goto next_crontab;
+	}
+
 	if ((crontab_fd = open(tabname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < OK) {
 		/* crontab not accessible?
 		 */
@@ -208,7 +250,8 @@ process_crontab(const char *uname, const
 		log_it(fname, getpid(), "NOT REGULAR", tabname);
 		goto next_crontab;
 	}
-	if ((statbuf->st_mode & 07577) != 0400) {
+	if ((!pw && (statbuf->st_mode & 07533) != 0400) ||
+	    (pw && (statbuf->st_mode & 07577) != 0400)) {
 		log_it(fname, getpid(), "BAD FILE MODE", tabname);
 		goto next_crontab;
 	}
@@ -221,6 +264,11 @@ process_crontab(const char *uname, const
 		log_it(fname, getpid(), "BAD LINK COUNT", tabname);
 		goto next_crontab;
 	}
+	if (lstatbuf.st_dev != statbuf->st_dev ||
+			lstatbuf.st_ino != statbuf->st_ino) {
+		log_it(fname, getpid(), "FILE CHANGED DURING OPEN", tabname);
+		goto next_crontab;
+	}
 
 	Debug(DLOAD, ("\t%s:", fname))
 	u = find_user(old_db, fname);
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin