* `LICENSE' that comes with the fcron source distribution.
*/
- /* $Id: database.c,v 1.75 2005-02-26 15:13:00 thib Exp $ */
+ /* $Id: database.c,v 1.76 2005-06-11 22:52:02 thib Exp $ */
#include "fcron.h"
}
+int
+switch_timezone(const char *orig_tz, const char* dest_tz)
+/* check if we have already switched to dest_tz timezone, otherwise do it */
+/* If dest_tz is NULL, this function does nothing */
+/* Returns 1 if this function has switched the timezone, 0 otherwise */
+{
+ char *current_tz = getenv("TZ");
+ if ( dest_tz != NULL &&
+ (current_tz == NULL || strcmp(dest_tz, current_tz) != 0)) {
+ setenv("TZ", dest_tz, 1);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void
+switch_back_timezone(const char *orig_tz)
+/* if orig_tz is NULL, unsets TZ
+ * otherwise, sets TZ to orig_tz */
+{
+ if ( orig_tz == NULL)
+ unsetenv("TZ");
+ else
+ setenv("TZ", orig_tz, 1);
+}
+
+
time_t
mktime_no_dst(struct tm *t)
/* same as mktime(), but without daylight saving time (dst) change adjustment
* Unfortunately, the behaviour of mktime() with
* tm_isdst set to -1 depends on the unix you run.
* In other word, it wouldn't be portable. */
+/*
+ * WARNING : the content of t has to be valide (for instance, 0<=t->tm_hour<=23,
+ * etc)
+ */
{
struct tm t2;
time_t ti1;
struct tm *ft;
struct tm ftime;
time_t begin_of_cur_int, end_of_cur_int = 0;
-
+ int tz_changed = 0;
+
+ /* Switch to another timezone if necessary. */
+ /* If line should be scheduled in a different time zone
+ * (ie. cl_tz != NULL),
+ * switch to that timezone now, do the calculations,
+ * and switch back to the local timezone at the end
+ * of the function. */
+ tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz);
+
/* handle timezone differences */
begin_of_cur_int = line->cl_nextexe - (line->cl_file->cf_tzdiff*3600);
lavg_array[lavg_num].l_until = end_of_cur_int;
clear_run_if_late(line->cl_option);
}
+
+ if ( tz_changed > 0 )
+ switch_back_timezone(orig_tz_envvar);
}
else
lavg_array[lavg_num].l_until =
if (debug_opt)
set_wday(ftime);
debug(" %s beginning of next period %d/%d/%d wday:%d %02d:%02d "
- "(tzdiff=%d)", line->cl_shell, (ftime->tm_mon + 1),
+ "(tzdiff=%d, timezone=%s)", line->cl_shell, (ftime->tm_mon + 1),
ftime->tm_mday, (ftime->tm_year + 1900), ftime->tm_wday,
- ftime->tm_hour, ftime->tm_min, line->cl_file->cf_tzdiff);
+ ftime->tm_hour, ftime->tm_min, line->cl_file->cf_tzdiff,
+ (line->cl_tz != NULL)? line->cl_tz : "localtime");
return;
}
}
}
- debug(" %s %s %d/%d/%d wday:%d %02d:%02d (tzdiff=%d)",line->cl_shell,
+ debug(" %s %s %d/%d/%d wday:%d %02d:%02d (tzdiff=%d, timezone=%s)",
+ line->cl_shell,
(option == STD) ? "first non matching" : "end of interval",
(ftime->tm_mon + 1), ftime->tm_mday, (ftime->tm_year + 1900),
ftime->tm_wday, ftime->tm_hour, ftime->tm_min,
- line->cl_file->cf_tzdiff);
+ line->cl_file->cf_tzdiff,
+ (line->cl_tz != NULL)? line->cl_tz : "localtime");
return;
}
}
time_t basetime;
struct tm *ft;
struct tm ftime;
+ int tz_changed = 0;
basetime = (option & FROM_CUR_NEXTEXE) ? line->cl_nextexe : now ;
+ /* Switch to another timezone if necessary. */
+ /* If line should be scheduled in a different time zone
+ * (ie. cl_tz != NULL),
+ * switch to that timezone now, do the calculations,
+ * and switch back to the local timezone at the end
+ * of the function. */
+ tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz);
+
if ( is_td(line->cl_option) ) {
time_t nextexe = 0;
set_cl_nextexe:
/* set cl_nextexe (handle the timezone differences) */
+ /* NOTE : the output of mktime does not depend on the timezone,
+ * hence, nextexe is correct even if option timezone is used. */
nextexe = mktime_no_dst(&ftime);
if ( is_random(line->cl_option) ) {
time_t intend_int;
debug(" cmd: %s begin int exec %d/%d/%d wday:%d %02d:%02d "
- "(tzdiff=%d)", line->cl_shell, (ftime.tm_mon + 1),
+ "(tzdiff=%d, timezone=%s)", line->cl_shell, (ftime.tm_mon + 1),
ftime.tm_mday, (ftime.tm_year + 1900), ftime.tm_wday,
- ftime.tm_hour, ftime.tm_min, line->cl_file->cf_tzdiff);
+ ftime.tm_hour, ftime.tm_min, line->cl_file->cf_tzdiff,
+ (line->cl_tz != NULL)? line->cl_tz : "localtime");
memcpy(&intend, &ftime, sizeof(intend));
goto_non_matching(line, &intend, END_OF_INTERVAL);
memcpy(&ftime, ft, sizeof(ftime));
}
send_msg_fd_debug(info_fd, " cmd: %s next exec %d/%d/%d wday:%d "
- "%02d:%02d (tzdiff=%d w/ sys time)", line->cl_shell,
+ "%02d:%02d (tzdiff=%d, timezone=%s)", line->cl_shell,
(ftime.tm_mon + 1), ftime.tm_mday,
(ftime.tm_year + 1900), ftime.tm_wday,
ftime.tm_hour, ftime.tm_min,
- line->cl_file->cf_tzdiff);
+ line->cl_file->cf_tzdiff,
+ (line->cl_tz != NULL)? line->cl_tz : "system's");
}
/*
if ( line->cl_nextexe <= now ) {
error("BUG ??? Fcron thinks the next exe time of %s is %ld, "
"hence before now (%ld). To avoid infinite loop, nextexe"
- " will be set at now+5s.");
+ " will be set at now+5s.", line->cl_shell, line->cl_nextexe);
line->cl_nextexe = now + 5;
}
-
}
else {
/* this is a job based on system up time */
insert_nextexe(line);
+ if ( tz_changed > 0 )
+ switch_back_timezone(orig_tz_envvar);
+
}
struct tm *ft = NULL;
struct tm ftime, last_nextexe;
char set_next_exe_opt = 0;
+ int tz_changed = 0;
/* // */
debug(" set_next_exe_notrun : %s %d", line->cl_shell, context);
/* // */
+
+ /* Switch to another timezone if necessary. */
+ /* If line should be scheduled in a different time zone
+ * (ie. cl_tz != NULL),
+ * switch to that timezone now, do the calculations,
+ * and switch back to the local timezone at the end
+ * of the function. */
+ tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz);
+
if (context == SYSDOWN) {
/* handle timezone differences */
previous_period = line->cl_nextexe - (line->cl_file->cf_tzdiff * 3600);
mail_notrun(line, context, &last_nextexe);
}
+ if ( tz_changed > 0 )
+ switch_back_timezone(orig_tz_envvar);
+
}
void
int pid = 0;
FILE *mailf = 0;
struct tm *time2 = NULL, time;
+ int tz_changed = 0;
switch ( pid = fork() ) {
case -1:
return;
}
+ /* Switch to another timezone if necessary. */
+ /* If line should be scheduled in a different time zone
+ * (ie. cl_tz != NULL),
+ * switch to that timezone now, do the calculations,
+ * and switch back to the local timezone at the end
+ * of the function. */
+ tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz);
+
if ( context == QUEUE_FULL )
time2 = localtime(&now);
else
switch ( context ) {
case SYSDOWN:
fprintf(mailf, "Line %s has not run since and including "
- "%d/%d/%d wday:%d %02d:%02d\ndue to system's down state.\n",
+ "%d/%d/%d wday:%d %02d:%02d (timezone=%s)\n"
+ "due to system's down state.\n",
line->cl_shell, (since->tm_mon + 1), since->tm_mday,
(since->tm_year + 1900), since->tm_wday, since->tm_hour,
- since->tm_min);
+ since->tm_min, (line->cl_tz)? line->cl_tz : "system's");
fprintf(mailf, "It will be next executed at %d/%d/%d wday:"
"%d %02d:%02d\n", (time.tm_mon + 1), time.tm_mday,
(time.tm_year+1900), time.tm_wday, time.tm_hour, time.tm_min);
break;
case LAVG:
fprintf(mailf, "Line %s has not run since and including "
- "%d/%d/%d wday:%d %02d:%02d\n", line->cl_shell,
- (since->tm_mon + 1), since->tm_mday, (since->tm_year + 1900),
- since->tm_wday, since->tm_hour, since->tm_min);
+ "%d/%d/%d wday:%d %02d:%02d (timezone=%s)\n",
+ line->cl_shell, (since->tm_mon + 1), since->tm_mday,
+ (since->tm_year + 1900), since->tm_wday, since->tm_hour,
+ since->tm_min, (line->cl_tz)? line->cl_tz : "system's");
fprintf(mailf, "due to a too high system load average or "
"too many lavg-serial jobs.\n");
fprintf(mailf, "It will be next executed at %d/%d/%d "
- "wday:%d %02d:%02d\n", (time.tm_mon + 1), time.tm_mday,
- (time.tm_year+1900), time.tm_wday, time.tm_hour, time.tm_min);
+ "wday:%d %02d:%02d (timezone=%s)\n", (time.tm_mon + 1),
+ time.tm_mday, (time.tm_year+1900), time.tm_wday, time.tm_hour,
+ time.tm_min, (line->cl_tz)? line->cl_tz : "system's");
break;
case QUEUE_FULL:
fprintf(mailf,"Line %s couldn't be added to lavg or serial queue which"
- " is full ( %d/%d/%d wday:%d %02d:%02d ).\n", line->cl_shell,
- (time.tm_mon + 1), time.tm_mday, (time.tm_year + 1900),
- time.tm_wday, time.tm_hour, time.tm_min);
+ " is full ( %d/%d/%d wday:%d %02d:%02d (timezone=%s)).\n",
+ line->cl_shell, (time.tm_mon + 1), time.tm_mday,
+ (time.tm_year + 1900), time.tm_wday, time.tm_hour, time.tm_min,
+ (line->cl_tz)? line->cl_tz : "system's");
fprintf(mailf, "Consider using options lavgonce, until, strict, "
"serialonce and/or fcron's option -m.\n");
fprintf(mailf, "Note that job %s has not run.\n", line->cl_shell);
launch_mailer(line, mailf);
/* we should not come here : launch_mailer does not return */
- error("mail_notrun : launch_mailer failed");
+ die("mail_notrun : launch_mailer failed");
}
* `LICENSE' that comes with the fcron source distribution.
*/
- /* $Id: fileconf.c,v 1.74 2004-07-11 18:08:08 thib Exp $ */
+ /* $Id: fileconf.c,v 1.75 2005-06-11 22:50:41 thib Exp $ */
#include "fcrontab.h"
default_line.cl_file = cf;
default_line.cl_runas = strdup2(runas);
default_line.cl_mailto = strdup2(runas);
+ default_line.cl_tz = NULL;
set_default_opt(default_line.cl_option);
if ( debug_opt )
free(default_line.cl_runas);
free(default_line.cl_mailto);
+ free(default_line.cl_tz);
if ( ! need_correction )
return OK;
}
/* global options for a file */
+
if ( strcmp(opt_name, "tzdiff") == 0 ) {
char negative = 0;
fprintf(stderr, " Opt : \"%s\" (-)%d\n", opt_name, i);
}
-
/* options related to a line (or a set of lines) */
+
+ else if ( strcmp(opt_name, "timezone") == 0 ) {
+ char buf[50];
+ bzero(buf, sizeof(buf));
+
+ if( ! in_brackets )
+ Handle_err;
+
+ i = 0;
+ while ( *ptr != ')' && i + 1 < sizeof(buf) )
+ buf[i++] = *ptr++;
+
+ if ( strcmp(buf, "\0") == 0 ) {
+ Flush(cl->cl_tz);
+ }
+ else {
+ Set(cl->cl_tz, buf);
+ }
+ if (debug_opt)
+ fprintf(stderr, " Opt : \"%s\" \"%s\"\n", opt_name, cl->cl_tz);
+ }
+
+
else if(strcmp(opt_name, "s") == 0 || strcmp(opt_name, "serial") == 0){
if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL )
Handle_err;
bzero(cl, sizeof(cl_t));
Set(cl->cl_runas, runas);
Set(cl->cl_mailto, runas);
+ Flush(cl->cl_tz);
set_default_opt(cl->cl_option);
}
if (debug_opt)
memcpy(cl, &default_line, sizeof(cl_t));
cl->cl_runas = strdup2(default_line.cl_runas);
cl->cl_mailto = strdup2(default_line.cl_mailto);
+ if ( cl->cl_tz != NULL )
+ cl->cl_tz = strdup2(default_line.cl_tz);
cl->cl_first = -1; /* 0 is a valid value, so we have to use -1 to detect unset */
/* skip the @ */
/* read a run freq number plus a normal fcron line */
{
cl_t *cl = NULL;
- unsigned int i = 0;
+ int i = 0;
Alloc(cl, cl_t);
memcpy(cl, &default_line, sizeof(cl_t));
cl->cl_runas = strdup2(default_line.cl_runas);
cl->cl_mailto = strdup2(default_line.cl_mailto);
+ if ( cl->cl_tz != NULL )
+ cl->cl_tz = strdup2(default_line.cl_tz);
/* set cl_remain if not specified */
if ( *ptr == '&' ) {
" skipping line.\n", file_name, line);
goto exiterr;
}
- cl->cl_runfreq = i;
+ cl->cl_runfreq = (unsigned short) i;
}
}
else if ( isalnum( (int) *ptr) )
memcpy(cl, &default_line, sizeof(cl_t));
cl->cl_runas = strdup2(default_line.cl_runas);
cl->cl_mailto = strdup2(default_line.cl_mailto);
+ if ( cl->cl_tz != NULL )
+ cl->cl_tz = strdup2(default_line.cl_tz);
/* skip the % */
ptr++;
free(line->cl_shell);
free(line->cl_mailto);
free(line->cl_runas);
+ free(line->cl_tz);
free(line);
}
break ;