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