cronie/cronie-1.1-inotify-fixes.patch
Tomáš Mráz 45564281bb - fix setting keycreate context
- unify logging a bit
- cleanup some warnings and fix a typo in TZ code
- 450993 improve and fix inotify support
2008-06-18 21:21:24 +00:00

883 lines
25 KiB
Diff

diff -up cronie-1.1/src/cron.c.inotify-fixes cronie-1.1/src/cron.c
--- cronie-1.1/src/cron.c.inotify-fixes 2008-06-18 22:49:02.000000000 +0200
+++ cronie-1.1/src/cron.c 2008-06-18 23:15:15.000000000 +0200
@@ -47,48 +47,56 @@ static int timeRunning, virtualTime, c
static long GMToff;
#if defined WITH_INOTIFY
-int wd1, wd2, wd3, wd4;
-void
-set_cron_watched(int fd) {
- pid_t pid = getpid();
-
- wd1 = inotify_add_watch(fd, CRONDIR, IN_MODIFY | IN_DELETE | IN_CREATE | IN_ATTRIB);
- if (wd1 < 0)
- log_it("CRON", pid, "This directory can't be watched", CRONDIR, errno);
+#define NUM_WATCHES 3
- wd2 = inotify_add_watch(fd, RH_CROND_DIR, IN_MODIFY | IN_DELETE | IN_CREATE | IN_ATTRIB);
- if (wd2 < 0)
- log_it("CRON", pid, "This directory can't be watched", RH_CROND_DIR, errno);
+int wd[NUM_WATCHES];
+const char *watchpaths[NUM_WATCHES] = { SPOOL_DIR, RH_CROND_DIR, SYSCRONTAB };
- wd3 = inotify_add_watch(fd, SYSCRONTAB, IN_MODIFY | IN_DELETE | IN_CREATE | IN_ATTRIB);
- if (wd3 < 0)
- log_it("CRON", pid, "This file can't be watched", SYSCRONTAB, errno);
+void
+set_cron_unwatched(int fd) {
+ int i;
+
+ for (i = 0; i < sizeof(wd)/sizeof(wd[0]); ++i) {
+ if (wd[i] < 0) {
+ inotify_rm_watch(fd, wd[i]);
+ wd[i] = -1;
+ }
+ }
+}
- wd4 = inotify_add_watch(fd, "/var/spool/cron/", IN_MODIFY | IN_DELETE | IN_CREATE | IN_ATTRIB);
- if (wd4 < 0)
- log_it("CRON", pid, "This directory can't be watched", "/var/spool/cron", errno);
+void
+set_cron_watched(int fd) {
+ pid_t pid = getpid();
+ int i;
- if (wd1 <0 || wd2<0 || wd3<0 || wd4<0) {
+ if (fd < 0) {
inotify_enabled = 0;
- log_it("CRON", pid, "INFO", "running without inotify support", 0);
+ return;
}
- else
- inotify_enabled = 1;
-}
-void
-set_cron_unwatched(int fd) {
- int ret1, ret2, ret3, ret4;
+ for (i = 0; i < sizeof(wd)/sizeof(wd[0]); ++i) {
+ int w;
+
+ w = inotify_add_watch(fd, watchpaths[i],
+ IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVED_TO | IN_MOVED_FROM | IN_MOVE_SELF | IN_DELETE);
+ if (w < 0) {
+ if (wd[i] != -1) {
+ log_it("CRON", pid, "This directory or file can't be watched", watchpaths[i], errno);
+ log_it("CRON", pid, "INFO", "running without inotify support", 0);
+ }
+ inotify_enabled = 0;
+ set_cron_unwatched(fd);
+ return;
+ }
+ wd[i] = w;
+ }
- if (wd1 >= 0)
- ret1 = inotify_rm_watch(fd, wd1);
- if (wd2 >= 0)
- ret2 = inotify_rm_watch(fd, wd2);
- if (wd3 >= 0)
- ret3 = inotify_rm_watch(fd, wd3);
- if (wd4 >= 0)
- ret4 = inotify_rm_watch(fd, wd4);
+ if (!inotify_enabled) {
+ log_it("CRON", pid, "INFO", "running with inotify support", 0);
+ }
+
+ inotify_enabled = 1;
}
#endif
@@ -110,12 +118,8 @@ main(int argc, char *argv[]) {
int fd;
char *cs;
pid_t pid = getpid();
-
#if defined WITH_INOTIFY
- int fildes;
- fildes = inotify_init();
- if (fildes < 0)
- log_it("CRON", pid, "INFO", "Inotify init failed", errno);
+ int i;
#endif
ProgramName = argv[0];
@@ -146,9 +150,6 @@ main(int argc, char *argv[]) {
acquire_daemonlock(0);
set_cron_uid();
-#if defined WITH_INOTIFY
- set_cron_watched(fildes);
-#endif
set_cron_cwd();
if (putenv("PATH="_PATH_DEFPATH) < 0) {
@@ -191,10 +192,7 @@ main(int argc, char *argv[]) {
if (fd != STDERR)
(void) close(fd);
}
- if (inotify_enabled)
- log_it("CRON", getpid(), "STARTUP INOTIFY", PACKAGE_VERSION, 0);
- else
- log_it("CRON", getpid(), "STARTUP", PACKAGE_VERSION, 0);
+ log_it("CRON", getpid(), "STARTUP", PACKAGE_VERSION, 0);
break;
default:
/* parent process should just die */
@@ -202,18 +200,28 @@ main(int argc, char *argv[]) {
}
}
+ pid = getpid();
acquire_daemonlock(0);
database.head = NULL;
database.tail = NULL;
- if (inotify_enabled) {
+ database.mtime = (time_t) 0;
+
+ load_database(&database);
+
#if defined WITH_INOTIFY
- load_inotify_database(&database, fildes);
-#endif
- }
- else {
- database.mtime = (time_t) 0;
- load_database(&database);
+ for (i = 0; i < sizeof(wd)/sizeof(wd[0]); ++i) {
+ /* initialize to negative number other than -1
+ * so an eventual error is reported for the first time
+ */
+ wd[i] = -2;
}
+
+ fd = inotify_init();
+ if (fd < 0)
+ log_it("CRON", pid, "INFO", "Inotify init failed", errno);
+ set_cron_watched(fd);
+#endif
+
set_time(TRUE);
run_reboot_jobs(&database);
timeRunning = virtualTime = clockTime;
@@ -246,12 +254,17 @@ main(int argc, char *argv[]) {
timeDiff = timeRunning - virtualTime;
if (inotify_enabled) {
#if defined WITH_INOTIFY
- check_inotify_database(&database, fildes);
+ check_inotify_database(&database, fd);
#endif
}
- else
+ else {
load_database(&database);
-
+#if defined WITH_INOTIFY
+ /* try reinstating the watches */
+ set_cron_watched(fd);
+#endif
+ }
+
/* shortcut for the most common case */
if (timeDiff == 1) {
virtualTime = timeRunning;
@@ -275,7 +288,7 @@ main(int argc, char *argv[]) {
* minute until caught up.
*/
Debug(DSCH, ("[%ld], normal case %d minutes to go\n",
- (long)getpid(), timeDiff))
+ (long)pid, timeDiff))
do {
if (job_runqueue())
sleep(10);
@@ -297,7 +310,7 @@ main(int argc, char *argv[]) {
* housekeeping.
*/
Debug(DSCH, ("[%ld], DST begins %d minutes to go\n",
- (long)getpid(), timeDiff))
+ (long)pid, timeDiff))
/* run wildcard jobs for current minute */
find_jobs(timeRunning, &database, TRUE, FALSE);
@@ -323,7 +336,7 @@ main(int argc, char *argv[]) {
* change until we are caught up.
*/
Debug(DSCH, ("[%ld], DST ends %d minutes to go\n",
- (long)getpid(), timeDiff))
+ (long)pid, timeDiff))
find_jobs(timeRunning, &database, TRUE, FALSE);
break;
default:
@@ -332,7 +345,7 @@ main(int argc, char *argv[]) {
* jump virtual time, and run everything
*/
Debug(DSCH, ("[%ld], clock jumped\n",
- (long)getpid()))
+ (long)pid))
virtualTime = timeRunning;
find_jobs(timeRunning, &database, TRUE, TRUE);
}
@@ -353,14 +366,13 @@ main(int argc, char *argv[]) {
sigchld_reaper();
}
}
- /* here stay ifdef, because some of the watches can be used even
- * if inotify is disabled
- */
+
#if defined WITH_INOTIFY
- set_cron_unwatched(fildes);
+ if (inotify_enabled)
+ set_cron_unwatched(fd);
- if (fildes >= 0 && close(fildes) < 0)
- log_it("CRON", pid, "INFO", "Inotify can't remove watches", errno);
+ if (fd >= 0 && close(fd) < 0)
+ log_it("CRON", pid, "INFO", "Inotify close failed", errno);
#endif
}
diff -up cronie-1.1/src/database.c.inotify-fixes cronie-1.1/src/database.c
--- cronie-1.1/src/database.c.inotify-fixes 2008-06-18 22:49:02.000000000 +0200
+++ cronie-1.1/src/database.c 2008-06-18 22:49:02.000000000 +0200
@@ -32,14 +32,10 @@
/* reasonable guess as to size of 1024 events */
#define BUF_LEN (1024 * (EVENT_SIZE + 16))
-#if defined WITH_INOTIFY
-/* state say if we change the crontable */
-#define RELOAD 1
-void unlink_inotify_database(cron_db *, cron_db , int);
-#endif
+void overwrite_database(cron_db *, cron_db *);
static void process_crontab(const char *, const char *,
- const char *, struct stat *,
+ const char *,
cron_db *, cron_db *);
static int not_a_crontab( DIR_T *dp );
@@ -48,10 +44,9 @@ static int not_a_crontab( DIR_T *dp );
static void max_mtime( char *dir_name, struct stat *max_st );
/* record max mtime of any file under dir_name in max_st */
-#if defined WITH_INOTIFY
int
check_open(const char *tabname, const char *fname, const char *uname,
- struct passwd *pw) {
+ struct passwd *pw, time_t *mtime) {
struct stat statbuf;
int crontab_fd;
pid_t pid = getpid();
@@ -60,12 +55,13 @@ check_open(const char *tabname, const ch
log_it(uname, pid, "CAN'T OPEN", tabname, errno);
return(-1);
}
+ if (fstat(crontab_fd, &statbuf) < OK) {
+ log_it(uname, pid, "STAT FAILED", tabname, errno);
+ close(crontab_fd);
+ return(-1);
+ }
+ *mtime = statbuf.st_mtime;
if (PermitAnyCrontab == 0) {
- if (fstat(crontab_fd, &statbuf) < OK) {
- log_it(uname, pid, "STAT FAILED", tabname, errno);
- close(crontab_fd);
- return(-1);
- }
if (!S_ISREG(statbuf.st_mode)) {
log_it(uname, pid, "NOT REGULAR", tabname, 0);
close(crontab_fd);
@@ -92,12 +88,12 @@ check_open(const char *tabname, const ch
}
void
-process_inotify_crontab(const char *uname, const char *fname, const char *tabname,
- cron_db *new_db, cron_db *old_db, int fd, int state) {
+process_crontab(const char *uname, const char *fname, const char *tabname,
+ cron_db *new_db, cron_db *old_db) {
struct passwd *pw = NULL;
int crontab_fd = -1;
user *u;
- struct stat statbuf;
+ time_t mtime;
int crond_crontab = (fname == NULL) && (strcmp(tabname, SYSCRONTAB) != 0);
if (fname == NULL) {
@@ -111,43 +107,42 @@ process_inotify_crontab(const char *unam
goto next_crontab;
}
+ if ((crontab_fd = check_open(tabname, fname, uname, pw, &mtime)) == -1)
+ goto next_crontab;
+
Debug(DLOAD, ("\t%s:", fname))
- u = find_user(old_db, fname, crond_crontab ? tabname : NULL ); /* goes only through database in memory */
- /* in first run is database empty. Check permission when -p ISN'T used. */
- if (u == NULL) {
- if ((crontab_fd = check_open(tabname, fname, uname, pw)) == -1)
- goto next_crontab;
- }
- else { /* second and other runs */
+ u = find_user(old_db, fname, crond_crontab ? tabname : NULL ); /* find user in old_db */
+
+ if (u != NULL) {
/* if crontab has not changed since we last read it
- * in, then we can just use our existing entry.
- */
- /* 6 because we want string reload or none */
- if (state != RELOAD) {
+ * in, then we can just use our existing entry.
+ */
+ if (u->mtime == mtime) {
Debug(DLOAD, (" [no change, using old data]"))
unlink_user(old_db, u);
link_user(new_db, u);
goto next_crontab;
}
- /* before we fall through to the code that will reload
- * the user, let's deallocate and unlink the user in
- * the old database. This is more a point of memory
- * efficiency than anything else, since all leftover
- * users will be deleted from the old database when
- * we finish with the crontab...
- */
- if ((crontab_fd = check_open(tabname, fname, uname, pw)) == -1)
- goto next_crontab;
+ /* before we fall through to the code that will reload
+ * the user, let's deallocate and unlink the user in
+ * the old database. This is more a point of memory
+ * efficiency than anything else, since all leftover
+ * users will be deleted from the old database when
+ * we finish with the crontab...
+ */
Debug(DLOAD, (" [delete old data]"))
unlink_user(old_db, u);
free_user(u);
- Debug(DSCH, ("RELOAD %s\n", tabname))
+ log_it(fname, getpid(), "RELOAD", tabname, 0);
}
- u = load_user(crontab_fd, pw, uname, fname, tabname); /* touch the disk */
- if (u != NULL)
+
+ u = load_user(crontab_fd, pw, uname, fname, tabname); /* read the file */
+ if (u != NULL) {
+ u->mtime = mtime;
link_user(new_db, u);
+ }
next_crontab:
if (crontab_fd != -1) {
@@ -156,57 +151,7 @@ process_inotify_crontab(const char *unam
}
}
-void
-load_inotify_database(cron_db *old_db, int fd) {
- cron_db new_db;
- DIR_T *dp;
- DIR *dir;
- pid_t pid = getpid();
-
- new_db.head = new_db.tail = NULL;
- process_inotify_crontab("root", NULL, SYSCRONTAB, &new_db, old_db, fd, RELOAD);
-
- /* RH_CROND_DIR /etc/cron.d */
- if (!(dir = opendir(RH_CROND_DIR))) {
- log_it("CRON", pid, "OPENDIR FAILED", RH_CROND_DIR, errno);
- (void) exit(ERROR_EXIT);
- }
- while (NULL != (dp = readdir(dir))) {
- char tabname[MAXNAMLEN+1];
-
- if (not_a_crontab(dp))
- continue;
-
- if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
- continue;
-
- process_inotify_crontab("root", NULL, tabname, &new_db, old_db, fd, RELOAD);
- }
- closedir(dir);
- /* SPOOL_DIR */
- if (!(dir = opendir(SPOOL_DIR))) {
- log_it("CRON", pid, "OPENDIR FAILED", SPOOL_DIR, errno);
- (void) exit(ERROR_EXIT);
- }
-
- while (NULL != (dp = readdir(dir))) {
- char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
-
- if (not_a_crontab(dp))
- continue;
-
- strncpy(fname, dp->d_name, MAXNAMLEN);
-
- if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/'))
- continue;
-
- process_inotify_crontab(fname, fname, tabname, &new_db, old_db, fd, RELOAD);
- }
- closedir(dir);
-
- unlink_inotify_database(old_db, new_db, fd);
-}
-
+#if defined WITH_INOTIFY
void
check_inotify_database(cron_db *old_db, int fd) {
cron_db new_db;
@@ -218,7 +163,7 @@ check_inotify_database(cron_db *old_db,
char buf[BUF_LEN];
pid_t pid = getpid();
- time.tv_sec = 1;
+ time.tv_sec = 0;
time.tv_usec = 0;
FD_ZERO(&rfds);
@@ -226,110 +171,83 @@ check_inotify_database(cron_db *old_db,
retval = select(fd + 1, &rfds, NULL, NULL, &time);
if (retval == -1) {
- log_it("CRON", pid, "INOTIFY", "select failed", errno);
+ if (errno != EINTR)
+ log_it("CRON", pid, "INOTIFY", "select failed", errno);
+ return;
}
else if (FD_ISSET(fd, &rfds)) {
new_db.head = new_db.tail = NULL;
- if (read(fd, buf, sizeof(buf)) == -1)
- log_it("CRON", pid, "INOTIFY", "read failed", errno);
- process_inotify_crontab("root", NULL, SYSCRONTAB, &new_db, old_db, fd, RELOAD);
+ while ((retval=read(fd, buf, sizeof(buf))) == -1 && errno == EINTR);
- if (!(dir = opendir(RH_CROND_DIR))) {
- log_it("CRON", pid, "OPENDIR FAILED", RH_CROND_DIR, errno);
- (void) exit(ERROR_EXIT);
+ if (retval == 0) {
+ /* this should not happen as the buffer is large enough */
+ errno = ENOMEM;
}
- while (NULL != (dp = readdir(dir))) {
- char tabname[MAXNAMLEN+1];
-
- if (not_a_crontab(dp))
- continue;
- if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
- continue;
- process_inotify_crontab("root", NULL, tabname, &new_db, old_db, fd, RELOAD);
- }
- closedir(dir);
-
- if (!(dir = opendir(SPOOL_DIR))) {
- log_it("CRON", pid, "OPENDIR FAILED", SPOOL_DIR, errno);
+ if (retval <= 0) {
+ log_it("CRON", pid, "INOTIFY", "read failed", errno);
+ /* something fatal must have occured we have no other reasonable
+ * way how to handle this failure than exit.
+ */
(void) exit(ERROR_EXIT);
}
- while (NULL != (dp = readdir(dir))) {
- char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
+
+ /* we must reinstate the watches here - TODO reinstate only watches
+ * which get IN_IGNORED event
+ */
+ set_cron_watched(fd);
- if (not_a_crontab(dp))
- continue;
+ /* TODO: parse the events and read only affected files */
- strncpy(fname, dp->d_name, MAXNAMLEN);
+ process_crontab("root", NULL, SYSCRONTAB, &new_db, old_db);
- if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, dp->d_name, '/'))
- continue;
- process_inotify_crontab(fname, fname, tabname, &new_db, old_db, fd, RELOAD);
- }
- closedir(dir);
- }
- else {
- new_db.head = new_db.tail = NULL;
- process_inotify_crontab("root", NULL, SYSCRONTAB, &new_db, old_db, fd, !RELOAD);
if (!(dir = opendir(RH_CROND_DIR))) {
log_it("CRON", pid, "OPENDIR FAILED", RH_CROND_DIR, errno);
- (void) exit(ERROR_EXIT);
+ } else {
+ while (NULL != (dp = readdir(dir))) {
+ char tabname[MAXNAMLEN+1];
+
+ if (not_a_crontab(dp))
+ continue;
+
+ if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
+ continue;
+ process_crontab("root", NULL, tabname, &new_db, old_db);
+ }
+ closedir(dir);
}
- while (NULL != (dp = readdir(dir))) {
- char tabname[MAXNAMLEN+1];
-
- if (not_a_crontab(dp))
- continue;
-
- if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
- continue;
- process_inotify_crontab("root", NULL, tabname, &new_db, old_db, fd, !RELOAD);
- }
- closedir(dir);
-
if (!(dir = opendir(SPOOL_DIR))) {
log_it("CRON", pid, "OPENDIR FAILED", SPOOL_DIR, errno);
- (void) exit(ERROR_EXIT);
- }
+ } else {
+ while (NULL != (dp = readdir(dir))) {
+ char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
- while (NULL != (dp = readdir(dir))) {
- char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
+ if (not_a_crontab(dp))
+ continue;
- if (not_a_crontab(dp))
- continue;
+ strncpy(fname, dp->d_name, MAXNAMLEN);
- strncpy(fname, dp->d_name, MAXNAMLEN);
-
- if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/'))
- continue;
-
- process_inotify_crontab(fname, fname, tabname, &new_db, old_db, fd, !RELOAD);
+ if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, dp->d_name, '/'))
+ continue;
+ process_crontab(fname, fname, tabname, &new_db, old_db);
+ }
+ closedir(dir);
}
- closedir(dir);
- }
- FD_CLR(fd, &rfds);
-
- unlink_inotify_database(old_db, new_db, fd);
-}
-void
-unlink_inotify_database(cron_db *old_db, cron_db new_db, int fd) {
- user *u, *nu;
- /* whatever's left in the old database is now junk.
- */
- Debug(DLOAD, ("unlinking old database:\n"))
- for (u = old_db->head; u != NULL; u = nu) {
- Debug(DLOAD, ("\t%s\n", u->name))
- nu = u->next;
- unlink_user(old_db, u);
- free_user(u);
+ /* 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).
+ */
+ endpwent();
+ }
+ else {
+ /* just return as no db reload is needed */
+ return;
}
- /* overwrite the database control block with the new one.
- */
- *old_db = new_db;
- Debug(DLOAD, ("load_database is done\n"))
+ overwrite_database(old_db, &new_db);
+ Debug(DLOAD, ("check_inotify_database is done\n"))
}
/*void
@@ -358,12 +276,29 @@ read_dir(char *dir_name, cron_db *new_db
#endif
void
+overwrite_database(cron_db *old_db, cron_db *new_db) {
+ user *u, *nu;
+ /* whatever's left in the old database is now junk.
+ */
+ Debug(DLOAD, ("unlinking old database:\n"))
+ for (u = old_db->head; u != NULL; u = nu) {
+ Debug(DLOAD, ("\t%s\n", u->name))
+ nu = u->next;
+ unlink_user(old_db, u);
+ free_user(u);
+ }
+
+ /* overwrite the database control block with the new one.
+ */
+ *old_db = *new_db;
+}
+
+void
load_database(cron_db *old_db) {
struct stat statbuf, syscron_stat, crond_stat;
cron_db new_db;
DIR_T *dp;
DIR *dir;
- user *u, *nu;
pid_t pid = getpid();
Debug(DLOAD, ("[%ld] load_database()\n", (long)pid))
@@ -374,22 +309,22 @@ load_database(cron_db *old_db) {
*/
if (stat(SPOOL_DIR, &statbuf) < OK) {
log_it("CRON", pid, "STAT FAILED", SPOOL_DIR, errno);
- (void) exit(ERROR_EXIT);
+ statbuf.st_mtime = 0;
+ } else {
+ /* As pointed out in Red Hat bugzilla 198019, with modern Linux it
+ * is possible to modify a file without modifying the mtime of the
+ * containing directory. Hence, we must check the mtime of each file:
+ */
+ max_mtime(SPOOL_DIR, &statbuf);
}
-
- /* As pointed out in Red Hat bugzilla 198019, with modern Linux it
- * is possible to modify a file without modifying the mtime of the
- * containing directory. Hence, we must check the mtime of each file:
- */
- max_mtime(SPOOL_DIR, &statbuf);
if (stat(RH_CROND_DIR, &crond_stat) < OK) {
log_it("CRON", pid, "STAT FAILED", RH_CROND_DIR, errno);
- (void) exit(ERROR_EXIT);
+ crond_stat.st_mtime = 0;
+ } else {
+ max_mtime(RH_CROND_DIR, &crond_stat);
}
- max_mtime(RH_CROND_DIR, &crond_stat);
-
/* track system crontab file
*/
if (stat(SYSCRONTAB, &syscron_stat) < OK)
@@ -420,27 +355,24 @@ load_database(cron_db *old_db) {
new_db.head = new_db.tail = NULL;
if (syscron_stat.st_mtime)
- process_crontab("root", NULL, SYSCRONTAB, &syscron_stat,
- &new_db, old_db);
+ process_crontab("root", NULL, SYSCRONTAB, &new_db, old_db);
if (!(dir = opendir(RH_CROND_DIR))) {
log_it("CRON", pid, "OPENDIR FAILED", RH_CROND_DIR, errno);
- (void) exit(ERROR_EXIT);
- }
-
- while (NULL != (dp = readdir(dir))) {
- char tabname[MAXNAMLEN+1];
+ } else {
+ while (NULL != (dp = readdir(dir))) {
+ char tabname[MAXNAMLEN+1];
- if ( not_a_crontab( dp ) )
- continue;
+ if ( not_a_crontab( dp ) )
+ continue;
- if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
- continue; /* XXX log? */
+ if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
+ continue; /* XXX log? */
- process_crontab("root", NULL, tabname,
- &crond_stat, &new_db, old_db);
+ process_crontab("root", NULL, tabname, &new_db, old_db);
+ }
+ closedir(dir);
}
- 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
@@ -449,24 +381,22 @@ load_database(cron_db *old_db) {
if (!(dir = opendir(SPOOL_DIR))) {
log_it("CRON", pid, "OPENDIR FAILED", SPOOL_DIR, errno);
- (void) exit(ERROR_EXIT);
- }
-
- while (NULL != (dp = readdir(dir))) {
- char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
+ } else {
+ while (NULL != (dp = readdir(dir))) {
+ char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
- if ( not_a_crontab( dp ) )
- continue;
+ if ( not_a_crontab( dp ) )
+ continue;
- strncpy(fname, dp->d_name, MAXNAMLEN);
+ strncpy(fname, dp->d_name, MAXNAMLEN);
- if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/'))
- continue; /* XXX log? */
+ if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/'))
+ continue; /* XXX log? */
- process_crontab(fname, fname, tabname,
- &statbuf, &new_db, old_db);
+ process_crontab(fname, fname, tabname, &new_db, old_db);
+ }
+ closedir(dir);
}
- closedir(dir);
/* if we don't do this, then when our children eventually call
* getpwnam() in do_command.c's child_process to verify MAILTO=,
@@ -474,19 +404,7 @@ load_database(cron_db *old_db) {
*/
endpwent();
- /* whatever's left in the old database is now junk.
- */
- Debug(DLOAD, ("unlinking old database:\n"))
- for (u = old_db->head; u != NULL; u = nu) {
- Debug(DLOAD, ("\t%s\n", u->name))
- nu = u->next;
- unlink_user(old_db, u);
- free_user(u);
- }
-
- /* overwrite the database control block with the new one.
- */
- *old_db = new_db;
+ overwrite_database(old_db, &new_db);
Debug(DLOAD, ("load_database is done\n"))
}
@@ -527,100 +445,6 @@ find_user(cron_db *db, const char *name,
return (u);
}
-static void
-process_crontab(const char *uname, const char *fname, const char *tabname,
- struct stat *statbuf, cron_db *new_db, cron_db *old_db)
-{
- struct passwd *pw = NULL;
- int crontab_fd = OK - 1;
- user *u;
- int crond_crontab = (fname == NULL) && (strcmp(tabname, SYSCRONTAB) != 0);
- pid_t pid = getpid();
-
- if (fname == NULL) {
- /* must be set to something for logging purposes.
- */
- fname = "*system*";
- } else if ((pw = getpwnam(uname)) == NULL) {
- /* file doesn't have a user in passwd file.
- */
- log_it(fname, pid, "ORPHAN", "no passwd entry", 0);
- goto next_crontab;
- }
-
- if ((crontab_fd = open(tabname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < OK) {
- /* crontab not accessible?
- */
- log_it(fname, pid, "CAN'T OPEN", tabname, errno);
- goto next_crontab;
- }
-
- if (fstat(crontab_fd, statbuf) < OK) {
- log_it(fname, pid, "FSTAT FAILED", tabname, errno);
- goto next_crontab;
- }
-
- if ( PermitAnyCrontab == 0 )
- {
- if (!S_ISREG(statbuf->st_mode)) {
- log_it(fname, pid, "NOT REGULAR", tabname, 0);
- goto next_crontab;
- }
- if ((statbuf->st_mode & 07533) != 0400) {
- log_it(fname, pid, "BAD FILE MODE", tabname, 0);
- goto next_crontab;
- }
- if (statbuf->st_uid != ROOT_UID && (pw == NULL ||
- statbuf->st_uid != pw->pw_uid || strcmp(uname, pw->pw_name) != 0)) {
- log_it(fname, pid, "WRONG FILE OWNER", tabname, 0);
- goto next_crontab;
- }
- if (pw && statbuf->st_nlink != 1) {
- log_it(fname, pid, "BAD LINK COUNT", tabname, 0);
- goto next_crontab;
- }
- }
-
- Debug(DLOAD, ("\t%s:", fname))
-
- u = find_user(old_db, fname, crond_crontab ? tabname : NULL );
-
- if (u != NULL) {
- /* if crontab has not changed since we last read it
- * in, then we can just use our existing entry.
- */
- if (u->mtime == statbuf->st_mtime) {
- Debug(DLOAD, (" [no change, using old data]"))
- unlink_user(old_db, u);
- link_user(new_db, u);
- goto next_crontab;
- }
-
- /* before we fall through to the code that will reload
- * the user, let's deallocate and unlink the user in
- * the old database. This is more a point of memory
- * efficiency than anything else, since all leftover
- * users will be deleted from the old database when
- * we finish with the crontab...
- */
- Debug(DLOAD, (" [delete old data]"))
- unlink_user(old_db, u);
- free_user(u);
- log_it(fname, pid, "RELOAD", tabname, 0);
- }
- u = load_user(crontab_fd, pw, uname, fname, tabname);
- if (u != NULL) {
- u->mtime = statbuf->st_mtime;
- link_user(new_db, u);
- }
-
- next_crontab:
- if (crontab_fd >= OK) {
- Debug(DLOAD, (" [done]\n"))
- close(crontab_fd);
- }
-}
-
static int not_a_crontab( DIR_T *dp )
{
int len;
@@ -660,11 +484,10 @@ static void max_mtime( char *dir_name, s
DIR * dir;
DIR_T *dp;
struct stat st;
- pid_t pid = getpid();
if (!(dir = opendir(dir_name))) {
- log_it("CRON", pid, "OPENDIR FAILED", dir_name, errno);
- (void) exit(ERROR_EXIT);
+ max_st->st_mtime = 0;
+ return;
}
while (NULL != (dp = readdir(dir)))