From: Tomas Mraz Date: Tue, 21 Jun 2011 18:26:38 +0000 (+0200) Subject: Check orphaned crontabs for adoption. X-Git-Tag: cronie1.4.8~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8b407876f276f96914111bd9954f21f627db7b11;p=cronie Check orphaned crontabs for adoption. --- diff --git a/src/cron.c b/src/cron.c index df45f44..7dc2958 100644 --- a/src/cron.c +++ b/src/cron.c @@ -307,6 +307,7 @@ int main(int argc, char *argv[]) { * clock. Classify the change into one of 4 cases. */ timeDiff = timeRunning - virtualTime; + check_orphans(&database); #if defined WITH_INOTIFY if (inotify_enabled) { check_inotify_database(&database); diff --git a/src/database.c b/src/database.c index d1d97ed..b0f2254 100644 --- a/src/database.c +++ b/src/database.c @@ -93,12 +93,81 @@ check_open(const char *tabname, const char *fname, const char *uname, return (crontab_fd); } +static orphan *orphans; + +static void +free_orphan(orphan *o) { + free(o->tabname); + free(o->fname); + free(o->uname); + free(o); +} + +void +check_orphans(cron_db *db) { + orphan *prev_orphan = NULL; + orphan *o = orphans; + + while (o != NULL) { + if (getpwnam(o->uname) != NULL) { + orphan *next = o->next; + + if (prev_orphan == NULL) { + orphans = next; + } else { + prev_orphan->next = next; + } + + process_crontab(o->uname, o->fname, o->tabname, + db, NULL); + + /* process_crontab could have added a new orphan */ + if (prev_orphan == NULL && orphans != next) { + prev_orphan = orphans; + } + free_orphan(o); + o = next; + } else { + prev_orphan = o; + o = o->next; + } + } +} + +static void +add_orphan(const char *uname, const char *fname, const char *tabname) { + orphan *o; + + o = calloc(1, sizeof(*o)); + if (o == NULL) + return; + + if (uname) + if ((o->uname=strdup(uname)) == NULL) + goto cleanup; + + if (fname) + if ((o->fname=strdup(fname)) == NULL) + goto cleanup; + + if (tabname) + if ((o->tabname=strdup(tabname)) == NULL) + goto cleanup; + + o->next = orphans; + orphans = o; + return; + +cleanup: + free_orphan(o); +} + static void 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; + user *u = NULL; time_t mtime; int crond_crontab = (fname == NULL) && (strcmp(tabname, SYSCRONTAB) != 0); @@ -111,6 +180,8 @@ process_crontab(const char *uname, const char *fname, const char *tabname, /* file doesn't have a user in passwd file. */ log_it(uname, getpid(), "ORPHAN", "no passwd entry", 0); + add_orphan(uname, fname, tabname); + goto next_crontab; } @@ -119,6 +190,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname, Debug(DLOAD, ("\t%s:", fname)) + if (old_db != NULL) u = find_user(old_db, fname, crond_crontab ? tabname : NULL); /* find user in old_db */ if (u != NULL) { diff --git a/src/funcs.h b/src/funcs.h index afecedd..aee4a99 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -39,7 +39,8 @@ void set_cron_uid(void), acquire_daemonlock(int), skip_comments(FILE *), log_it(const char *, PID_T, const char *, const char *, int), - log_close(void); + log_close(void), + check_orphans(cron_db *); #if defined WITH_INOTIFY void set_cron_watched(int ), set_cron_unwatched(int ), diff --git a/src/structs.h b/src/structs.h index fec5186..16cd180 100644 --- a/src/structs.h +++ b/src/structs.h @@ -57,6 +57,13 @@ typedef struct _user { security_context_t scontext; /* SELinux security context */ } user; +typedef struct _orphan { + struct _orphan *next; /* link */ + char *uname; + char *fname; + char *tabname; +} orphan; + typedef struct _cron_db { user *head, *tail; /* links */ time_t mtime; /* last modtime on spooldir */