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)
This commit is contained in:
Tomas Mraz 2013-06-11 20:30:29 +02:00
parent 7dcaab4a06
commit b1659a4269
4 changed files with 374 additions and 1 deletions

View File

@ -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 <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#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);

View File

@ -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 <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

View File

@ -0,0 +1,27 @@
From 5ac31751adfa31c5e5e316afc2f800037bd1cdca Mon Sep 17 00:00:00 2001
From: Tomas Mraz <tmraz@fedoraproject.org>
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

View File

@ -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 <tmraz@redhat.com> - 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 <rel-eng@lists.fedoraproject.org> - 1.4.10-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild