diff --git a/cronie-1.4.10-copy-env.patch b/cronie-1.4.10-copy-env.patch new file mode 100644 index 0000000..dda8133 --- /dev/null +++ b/cronie-1.4.10-copy-env.patch @@ -0,0 +1,172 @@ +diff -up cronie-1.4.10/src/env.c.copy-env cronie-1.4.10/src/env.c +--- cronie-1.4.10/src/env.c.copy-env 2012-11-27 08:32:13.000000000 +0100 ++++ cronie-1.4.10/src/env.c 2013-06-11 17:41:08.533094913 +0200 +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "globals.h" + #include "funcs.h" +@@ -67,7 +68,7 @@ char **env_copy(char **envp) { + return (p); + } + +-char **env_set(char **envp, char *envstr) { ++char **env_set(char **envp, const char *envstr) { + int count, found; + char **p, *envtmp; + +@@ -112,6 +113,47 @@ char **env_set(char **envp, char *envstr + return (p); + } + ++int env_set_from_environ(char ***envpp) { ++ static const char *names[] = { ++ "LANG", ++ "LC_CTYPE", ++ "LC_NUMERIC", ++ "LC_TIME", ++ "LC_COLLATE", ++ "LC_MONETARY", ++ "LC_MESSAGES", ++ "LC_PAPER", ++ "LC_NAME", ++ "LC_ADDRESS", ++ "LC_TELEPHONE", ++ "LC_MEASUREMENT", ++ "LC_IDENTIFICATION", ++ "LC_ALL", ++ "LANGUAGE", ++ NULL ++ }; ++ const char **name; ++ char **procenv; ++ ++ for (procenv = environ; *procenv != NULL; ++procenv) { ++ for (name = names; *name != NULL; ++name) { ++ size_t namelen; ++ ++ namelen = strlen(*name); ++ if (strncmp(*name, *procenv, namelen) == 0 ++ && (*procenv)[namelen] == '=') { ++ char **tmpenv; ++ ++ tmpenv = env_set(*envpp, *procenv); ++ if (tmpenv == NULL) ++ return FALSE; ++ *envpp = tmpenv; ++ } ++ } ++ } ++ return TRUE; ++} ++ + /* The following states are used by load_env(), traversed in order: */ + enum env_state { + NAMEI, /* First char of NAME, may be quote */ +diff -up cronie-1.4.10/src/funcs.h.copy-env cronie-1.4.10/src/funcs.h +--- cronie-1.4.10/src/funcs.h.copy-env 2012-11-27 10:22:14.000000000 +0100 ++++ cronie-1.4.10/src/funcs.h 2013-06-11 17:08:36.462019472 +0200 +@@ -67,6 +67,7 @@ int load_database(cron_db *), + swap_uids(void), + swap_uids_back(void), + load_env(char *, FILE *), ++ env_set_from_environ(char ***envpp), + cron_pclose(FILE *), + glue_strings(char *, size_t, const char *, const char *, char), + strcmp_until(const char *, const char *, char), +@@ -81,7 +82,7 @@ char *env_get(const char *, char **), + *first_word(const char *, const char *), + **env_init(void), + **env_copy(char **), +- **env_set(char **, char *); ++ **env_set(char **, const char *); + + user *load_user(int, struct passwd *, const char *, const char *, const char *), + *find_user(cron_db *, const char *, const char *); +diff -up cronie-1.4.10/src/user.c.copy-env cronie-1.4.10/src/user.c +--- cronie-1.4.10/src/user.c.copy-env 2012-11-27 08:32:13.000000000 +0100 ++++ cronie-1.4.10/src/user.c 2013-06-11 17:34:51.000000000 +0200 +@@ -63,7 +63,7 @@ load_user (int crontab_fd, struct passwd + FILE *file; + user *u; + entry *e; +- int status, save_errno = errno; ++ int status = TRUE, save_errno = 0; + char **envp = NULL, **tenvp; + + if (!(file = fdopen(crontab_fd, "r"))) { +@@ -84,26 +84,24 @@ load_user (int crontab_fd, struct passwd + if (((u->name = strdup(fname)) == NULL) + || ((u->tabname = strdup(tabname)) == NULL)) { + save_errno = errno; +- free_user(u); +- u = NULL; + goto done; + } + +- + /* init environment. this will be copied/augmented for each entry. + */ + if ((envp = env_init()) == NULL) { + save_errno = errno; +- free_user(u); +- u = NULL; ++ goto done; ++ } ++ ++ if (env_set_from_environ(&envp) == FALSE) { ++ save_errno = errno; + goto done; + } + + #ifdef WITH_SELINUX + if (get_security_context(pw == NULL ? NULL : uname, + crontab_fd, &u->scontext, tabname) != 0) { +- free_user (u); +- u = NULL; + goto done; + } + #endif +@@ -111,15 +109,10 @@ load_user (int crontab_fd, struct passwd + */ + while ((status = load_env (envstr, file)) >= OK) { + switch (status) { +- case ERR: +- save_errno = errno; +- free_user(u); +- u = NULL; +- goto done; + case FALSE: + FileName = tabname; + e = load_entry(file, log_error, pw, envp); +- if (e) { ++ if (e) { + e->next = u->crontab; + u->crontab = e; + } +@@ -127,16 +120,18 @@ load_user (int crontab_fd, struct passwd + case TRUE: + if ((tenvp = env_set (envp, envstr)) == NULL) { + save_errno = errno; +- free_user(u); +- u = NULL; + goto done; + } +- envp = tenvp; +- break; ++ envp = tenvp; ++ break; + } + } + + done: ++ if (status == TRUE) { ++ free_user(u); ++ u = NULL; ++ } + if (envp) + env_free(envp); + fclose(file); diff --git a/cronie-1.4.10-random-delay.patch b/cronie-1.4.10-random-delay.patch new file mode 100644 index 0000000..b746691 --- /dev/null +++ b/cronie-1.4.10-random-delay.patch @@ -0,0 +1,163 @@ +diff --git a/man/crontab.5 b/man/crontab.5 +index 740e393..bfc8414 100644 +--- a/man/crontab.5 ++++ b/man/crontab.5 +@@ -143,6 +143,13 @@ specifications of the particular security context. For more information, + see + .BR crontab (1)\ -s\ option. + .PP ++The ++.I RANDOM_DELAY ++variable allows delaying job startups by random amount of minutes with ++upper limit specified by the variable. The random scaling factor is ++determined during the cron daemon startup so it remains constant for ++the whole run time of the daemon. ++.PP + The format of a cron command is similar to the V7 standard, with a number + of upward-compatible extensions. Each line has five time-and-date fields + followed by a +diff --git a/src/cron.c b/src/cron.c +index 6fd0c31..ec4ace7 100644 +--- a/src/cron.c ++++ b/src/cron.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #ifdef WITH_INOTIFY + # include +@@ -202,6 +203,9 @@ int main(int argc, char *argv[]) { + char *cs; + pid_t pid = getpid(); + long oldGMToff; ++ struct timeval tv; ++ struct timezone tz; ++ char buf[256]; + + if ((ProgramName=strrchr(argv[0], '/')) == NULL) { + ProgramName = argv[0]; +@@ -298,6 +302,15 @@ int main(int argc, char *argv[]) { + } + + pid = getpid(); ++ ++ /* obtain a random scaling factor for RANDOM_DELAY */ ++ if (gettimeofday(&tv, &tz) != 0) ++ tv.tv_usec = 0; ++ srandom(pid + tv.tv_usec); ++ RandomScale = random() / (double)RAND_MAX; ++ snprintf(buf, sizeof(buf), "RANDOM_DELAY will be scaled with factor %d%% if used.", (int)(RandomScale*100)); ++ log_it("CRON", pid, "INFO", buf, 0); ++ + acquire_daemonlock(0); + database.head = NULL; + database.tail = NULL; +@@ -508,8 +521,6 @@ static void run_reboot_jobs(cron_db * db) { + + static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long vGMToff) { + char *orig_tz, *job_tz; +- time_t virtualSecond = vtime * SECONDS_PER_MINUTE; +- time_t virtualGMTSecond = virtualSecond - vGMToff; + struct tm *tm; + int minute, hour, dom, month, dow; + user *u; +@@ -542,11 +553,7 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v + } while (0) + + orig_tz = getenv("TZ"); +- maketime(NULL, orig_tz); + +- Debug(DSCH, ("[%ld] tick(%d,%d,%d,%d,%d) %s %s\n", +- (long) getpid(), minute, hour, dom, month, dow, +- doWild ? " " : "No wildcard", doNonWild ? " " : "Wildcard only")); + /* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the + * first and fifteenth AND every Sunday; '* * * * Sun' will run *only* + * on Sundays; '* * 1,15 * *' will run *only* the 1st and 15th. this +@@ -561,6 +568,8 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v + uname = e->pwd->pw_name; + /* check if user exists in time of job is being run f.e. ldap */ + if (getpwnam(uname) != NULL) { ++ time_t virtualSecond = (vtime - e->delay) * SECONDS_PER_MINUTE; ++ time_t virtualGMTSecond = virtualSecond - vGMToff; + job_tz = env_get("CRON_TZ", e->envp); + maketime(job_tz, orig_tz); + /* here we test whether time is NOW */ +diff --git a/src/entry.c b/src/entry.c +index e9142f5..fa69524 100644 +--- a/src/entry.c ++++ b/src/entry.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #include "bitstring.h" + #include "funcs.h" +@@ -97,6 +98,7 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw, + char cmd[MAX_COMMAND]; + char envstr[MAX_ENVSTR]; + char **tenvp; ++ char *p; + + Debug(DPARS, ("load_entry()...about to eat comments\n")); + +@@ -297,6 +299,20 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw, + } + memset(e->pwd->pw_passwd, 0, strlen(e->pwd->pw_passwd)); + ++ p = env_get("RANDOM_DELAY", envp); ++ if (p) { ++ char *endptr; ++ long val; ++ ++ errno = 0; /* To distinguish success/failure after call */ ++ val = strtol(p, &endptr, 10); ++ if (errno != 0 || val < 0 || val > 24*60) { ++ log_it("CRON", getpid(), "ERROR", "bad value of RANDOM_DELAY", 0); ++ } else { ++ e->delay = val * RandomScale; ++ } ++ } ++ + /* copy and fix up environment. some variables are just defaults and + * others are overrides. + */ +diff --git a/src/env.c b/src/env.c +index 1ebea62..3ad8bf7 100644 +--- a/src/env.c ++++ b/src/env.c +@@ -130,6 +130,7 @@ int env_set_from_environ(char ***envpp) { + "LC_IDENTIFICATION", + "LC_ALL", + "LANGUAGE", ++ "RANDOM_DELAY", + NULL + }; + const char **name; +diff --git a/src/globals.h b/src/globals.h +index 4370974..e957c9a 100644 +--- a/src/globals.h ++++ b/src/globals.h +@@ -81,6 +81,7 @@ XTRN char MailCmd[MAX_COMMAND]; + XTRN char cron_default_mail_charset[MAX_ENVSTR]; + XTRN int EnableClustering; + XTRN int ChangePath; ++XTRN double RandomScale; + + #if DEBUGGING + XTRN int DebugFlags INIT(0); +diff --git a/src/structs.h b/src/structs.h +index 200d20d..272777a 100644 +--- a/src/structs.h ++++ b/src/structs.h +@@ -41,6 +41,7 @@ typedef struct _entry { + bitstr_t bit_decl(month, MONTH_COUNT); + bitstr_t bit_decl(dow, DOW_COUNT); + int flags; ++ int delay; + #define MIN_STAR 0x01 + #define HR_STAR 0x02 + #define DOM_STAR 0x04 diff --git a/cronie-1.4.10-use-setenv.patch b/cronie-1.4.10-use-setenv.patch new file mode 100644 index 0000000..ddbfbbb --- /dev/null +++ b/cronie-1.4.10-use-setenv.patch @@ -0,0 +1,27 @@ +From 5ac31751adfa31c5e5e316afc2f800037bd1cdca Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Thu, 6 Jun 2013 20:13:26 +0200 +Subject: [PATCH] Do not use putenv with string literal. + +--- + src/cron.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cron.c b/src/cron.c +index 9974887..08d0812 100644 +--- a/src/cron.c ++++ b/src/cron.c +@@ -244,8 +244,8 @@ int main(int argc, char *argv[]) { + check_spool_dir(); + + if (ChangePath) { +- if (putenv("PATH=" _PATH_DEFPATH) < 0) { +- log_it("CRON", pid, "DEATH", "can't putenv PATH", ++ if (setenv("PATH", _PATH_DEFPATH, 1) < 0) { ++ log_it("CRON", pid, "DEATH", "can't setenv PATH", + errno); + exit(1); + } +-- +1.7.7.6 + diff --git a/cronie.spec b/cronie.spec index a3f6374..5194d16 100644 --- a/cronie.spec +++ b/cronie.spec @@ -6,11 +6,14 @@ Summary: Cron daemon for executing programs at set times Name: cronie Version: 1.4.10 -Release: 4%{?dist} +Release: 5%{?dist} License: MIT and BSD and ISC and GPLv2 Group: System Environment/Base URL: https://fedorahosted.org/cronie Source0: https://fedorahosted.org/releases/c/r/cronie/%{name}-%{version}.tar.gz +Patch1: cronie-1.4.10-use-setenv.patch +Patch2: cronie-1.4.10-copy-env.patch +Patch3: cronie-1.4.10-random-delay.patch Requires: dailyjobs @@ -82,6 +85,9 @@ is not used as the system init process. %prep %setup -q +%patch1 -p1 -b .setenv +%patch2 -p1 -b .copy-env +%patch3 -p1 -b .random-delay %build %configure \ @@ -215,6 +221,11 @@ exit 0 %attr(0755,root,root) %{_initrddir}/crond %changelog +* Tue Jun 11 2013 Tomáš Mráz - 1.4.10-5 +- add support for RANDOM_DELAY - delaying job startups +- pass some environment variables to processes (LANG, etc.) (#969761) +- do not use putenv() with string literals (#971516) + * Wed Feb 13 2013 Fedora Release Engineering - 1.4.10-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild