cronie/cronie-1.4.10-random-delay.patch
Tomas Mraz b1659a4269 Multiple bug fixes and improvements.
- 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)
2013-06-11 20:30:29 +02:00

164 lines
5.0 KiB
Diff

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 <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <sys/time.h>
#ifdef WITH_INOTIFY
# include <sys/inotify.h>
@@ -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 <string.h>
#include <sys/types.h>
#include <unistd.h>
+#include <errno.h>
#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