mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 06:18:47 +02:00
702 lines
19 KiB
C
702 lines
19 KiB
C
/***************************************************************/
|
|
/* */
|
|
/* TRIGGER.C */
|
|
/* */
|
|
/* Routines for figuring out the trigger date of a reminder */
|
|
/* */
|
|
/* This file is part of REMIND. */
|
|
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/* */
|
|
/***************************************************************/
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
#include "types.h"
|
|
#include "expr.h"
|
|
#include "protos.h"
|
|
#include "globals.h"
|
|
#include "err.h"
|
|
|
|
#define GOT_DAY 1
|
|
#define GOT_MON 2
|
|
#define GOT_YR 4
|
|
#define GOT_WD 8
|
|
|
|
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
|
|
|
|
static int DSEYear(int dse);
|
|
static int DSEMonth(int dse);
|
|
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
|
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart);
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* NextSimpleTrig */
|
|
/* */
|
|
/* Compute the "simple" trigger date, taking into account */
|
|
/* ONLY the day of week, day, month and year components. */
|
|
/* Normally, returns -1 if the trigger has expired. As a */
|
|
/* special case, if D, M, Y [WD] are specified, returns the */
|
|
/* DSE date, regardless of whether it's expired. This is */
|
|
/* so that dates with a REP can be handled properly. */
|
|
/* */
|
|
/***************************************************************/
|
|
static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|
{
|
|
int typ = 0;
|
|
int d, m, y, j, d2, m2, y2;
|
|
|
|
*err = 0;
|
|
FromDSE(startdate, &y, &m, &d);
|
|
d2 = d;
|
|
m2 = m;
|
|
y2 = y;
|
|
|
|
if (trig->d != NO_DAY) typ |= GOT_DAY;
|
|
if (trig->m != NO_MON) typ |= GOT_MON;
|
|
if (trig->y != NO_YR) typ |= GOT_YR;
|
|
if (trig->wd != NO_WD) typ |= GOT_WD;
|
|
switch(typ) {
|
|
case 0:
|
|
return startdate;
|
|
|
|
case GOT_WD:
|
|
ADVANCE_TO_WD(startdate, trig->wd);
|
|
return startdate;
|
|
|
|
case GOT_DAY:
|
|
if (d > trig->d) {
|
|
m++;
|
|
if (m == 12) { m = 0; y++; }
|
|
}
|
|
while (trig->d > DaysInMonth(m, trig->y)) m++;
|
|
j = DSE(y, m, trig->d);
|
|
return j;
|
|
|
|
case GOT_MON:
|
|
if (m == trig->m) return startdate;
|
|
else if (m > trig->m) return DSE(y+1, trig->m, 1);
|
|
else return DSE(y, trig->m, 1);
|
|
|
|
case GOT_YR:
|
|
if (y == trig->y) return startdate;
|
|
else if (y < trig->y) return DSE(trig->y, 0, 1);
|
|
else return -1;
|
|
|
|
case GOT_DAY+GOT_MON:
|
|
if (trig->d > MonthDays[trig->m]) {
|
|
*err = E_BAD_DATE;
|
|
return -1;
|
|
}
|
|
|
|
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
|
/* Take care of Feb. 29 */
|
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
|
return DSE(y, trig->m, trig->d);
|
|
|
|
case GOT_DAY+GOT_YR:
|
|
if (y < trig->y) return DSE(trig->y, 0, trig->d);
|
|
else if (y > trig->y) return -1;
|
|
|
|
if (d > trig->d) {
|
|
m++;
|
|
if (m == 12) return -1;
|
|
}
|
|
while (trig->d > DaysInMonth(m, trig->y)) m++;
|
|
return DSE(trig->y, m, trig->d);
|
|
|
|
case GOT_MON+GOT_YR:
|
|
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
|
if (y < trig->y) return DSE(trig->y, trig->m, 1);
|
|
if (m == trig->m) return startdate;
|
|
return DSE(trig->y, trig->m, 1);
|
|
|
|
case GOT_DAY+GOT_MON+GOT_YR:
|
|
if (trig->d > DaysInMonth(trig->m, trig->y)) {
|
|
*err = E_BAD_DATE;
|
|
return -1;
|
|
}
|
|
return DSE(trig->y, trig->m, trig->d);
|
|
|
|
case GOT_YR+GOT_WD:
|
|
if (y > trig->y) return -1;
|
|
if (y < trig->y) j = DSE(trig->y, 0, 1);
|
|
else j = startdate;
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (DSEYear(j) > trig->y) return -1;
|
|
return j;
|
|
|
|
case GOT_MON+GOT_WD:
|
|
if (m == trig->m) {
|
|
j = startdate;
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (DSEMonth(j) == trig->m) return j;
|
|
}
|
|
if (m >= trig->m) j = DSE(y+1, trig->m, 1);
|
|
else j = DSE(y, trig->m, 1);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
return j; /* Guaranteed to be within the month */
|
|
|
|
case GOT_DAY+GOT_WD:
|
|
if (m !=0 || y > BASE) {
|
|
m2 = m-1;
|
|
if (m2 < 0) { y2 = y-1; m2 = 11; }
|
|
|
|
/* If there are fewer days in previous month, no match */
|
|
if (trig->d <= DaysInMonth(m2, y2)) {
|
|
j = DSE(y2, m2, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (j >= startdate) return j;
|
|
|
|
}
|
|
}
|
|
|
|
/* Try this month */
|
|
if (trig->d <= DaysInMonth(m, y)) {
|
|
j = DSE(y, m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (j >= startdate) return j;
|
|
}
|
|
|
|
/* Argh! Try next avail. month */
|
|
m2 = m+1;
|
|
if (m2 > 11) { m2 = 0; y++; }
|
|
while (trig->d > DaysInMonth(m2, y)) m2++;
|
|
j = DSE(y, m2, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
return j;
|
|
|
|
case GOT_WD+GOT_YR+GOT_DAY:
|
|
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
|
if (y > trig->y) {
|
|
j = DSE(trig->y, 11, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (j >= startdate) return j;
|
|
} else if (y < trig->y) {
|
|
j = DSE(trig->y, 0, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
return j;
|
|
} else {
|
|
/* Try last month */
|
|
if (m > 0) {
|
|
m2 = m-1;
|
|
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
|
j = DSE(trig->y, m2, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (DSEYear(j) > trig->y) return -1;
|
|
if (j >= startdate) return j;
|
|
}
|
|
}
|
|
/* Try this month */
|
|
if (trig->d <= DaysInMonth(m, trig->y)) {
|
|
j = DSE(trig->y, m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (DSEYear(j) > trig->y) return -1;
|
|
if (j >= startdate) return j;
|
|
}
|
|
|
|
/* Must be next month */
|
|
if (m == 11) return -1;
|
|
m++;
|
|
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
|
j = DSE(trig->y, m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (DSEYear(j) > trig->y) return -1;
|
|
return j;
|
|
|
|
case GOT_DAY+GOT_MON+GOT_WD:
|
|
if (trig->d > MonthDays[trig->m]) {
|
|
*err = E_BAD_DATE;
|
|
return -1;
|
|
}
|
|
/* Back up a year in case we'll cross a year boundary*/
|
|
if (y > BASE) {
|
|
y--;
|
|
}
|
|
|
|
/* Move up to the first valid year */
|
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
|
|
|
/* Try last year */
|
|
j = DSE(y, trig->m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (j >= startdate) return j;
|
|
|
|
/* Try this year */
|
|
y++;
|
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
|
j = DSE(y, trig->m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
if (j >= startdate) return j;
|
|
|
|
/* Must be next year */
|
|
y++;
|
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
|
j = DSE(y, trig->m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
return j;
|
|
|
|
case GOT_WD+GOT_MON+GOT_YR:
|
|
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
|
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
|
j = DSE(trig->y, trig->m, 1);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
return j;
|
|
} else {
|
|
j = startdate;
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
FromDSE(j, &y2, &m2, &d2);
|
|
if (m2 == trig->m) return j; else return -1;
|
|
}
|
|
|
|
case GOT_WD+GOT_DAY+GOT_MON+GOT_YR:
|
|
if (trig->d > DaysInMonth(trig->m, trig->y)) {
|
|
*err = E_BAD_DATE;
|
|
return -1;
|
|
}
|
|
j = DSE(trig->y, trig->m, trig->d);
|
|
ADVANCE_TO_WD(j, trig->wd);
|
|
return j;
|
|
|
|
default:
|
|
Eprint("NextSimpleTrig %s %d", ErrMsg[E_SWERR], typ);
|
|
*err = E_SWERR;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* DSEMonth - Given a DSE date, what's the month? */
|
|
/* */
|
|
/***************************************************************/
|
|
static int DSEMonth(int dse)
|
|
{
|
|
int y, m, d;
|
|
FromDSE(dse, &y, &m, &d);
|
|
return m;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* DSEYear - Given a DSE date, what's the year? */
|
|
/* */
|
|
/***************************************************************/
|
|
static int DSEYear(int dse)
|
|
{
|
|
int y, m, d;
|
|
FromDSE(dse, &y, &m, &d);
|
|
return y;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* GetNextTriggerDate */
|
|
/* */
|
|
/* Given a trigger, compute the next trigger date. */
|
|
/* */
|
|
/* Returns the DSE date of next trigger, -1 if */
|
|
/* expired, -2 if can't compute trigger date. */
|
|
/* */
|
|
/***************************************************************/
|
|
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart)
|
|
{
|
|
int simple, mod, omit;
|
|
|
|
/* First: Have we passed the UNTIL date? */
|
|
if (trig->until != NO_UNTIL &&
|
|
trig->until < start) {
|
|
trig->expired = 1;
|
|
return -1; /* expired */
|
|
}
|
|
|
|
/* Next: If it's an "AFTER"-type skip, back up
|
|
until we're at the start of a block of holidays */
|
|
if (trig->skip == AFTER_SKIP) {
|
|
int iter = 0;
|
|
while (iter++ <= MaxSatIter) {
|
|
*err = IsOmitted(start-1, trig->localomit, trig->omitfunc, &omit);
|
|
if (*err) return -2;
|
|
if (!omit) {
|
|
break;
|
|
}
|
|
start--;
|
|
}
|
|
if (iter > MaxSatIter) {
|
|
/* omitfunc must have returned "true" too often */
|
|
*err = E_CANT_TRIG;
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
/* Find the next simple trigger */
|
|
simple = NextSimpleTrig(start, trig, err);
|
|
|
|
/* Problems? */
|
|
if (*err || (simple == -1)) return -1;
|
|
|
|
/* Suggested starting point for next attempt */
|
|
*nextstart = simple+1;
|
|
|
|
/* If there's a BACK, back up... */
|
|
if (trig->back != NO_BACK) {
|
|
mod = trig->back;
|
|
if (mod < 0) {
|
|
simple += mod;
|
|
}
|
|
else {
|
|
int iter = 0;
|
|
int max = MaxSatIter;
|
|
if (max < mod*2) {
|
|
max = mod*2;
|
|
}
|
|
while(iter++ <= max) {
|
|
if (!mod) {
|
|
break;
|
|
}
|
|
simple--;
|
|
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
|
if (*err) return -2;
|
|
if (!omit) mod--;
|
|
}
|
|
if (iter > max) {
|
|
*err = E_CANT_TRIG;
|
|
return -2;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If there's a REP, calculate the next occurrence */
|
|
if (trig->rep != NO_REP) {
|
|
if (simple < start) {
|
|
mod = (start - simple) / trig->rep;
|
|
simple = simple + mod * trig->rep;
|
|
if (simple < start) simple += trig->rep;
|
|
}
|
|
}
|
|
|
|
/* If it's a "BEFORE"-type skip, back up */
|
|
if (trig->skip == BEFORE_SKIP) {
|
|
int iter = 0;
|
|
while(iter++ <= MaxSatIter) {
|
|
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
|
if (*err) return -2;
|
|
if (!omit) {
|
|
break;
|
|
}
|
|
simple--;
|
|
}
|
|
if (iter > MaxSatIter) {
|
|
*err = E_CANT_TRIG;
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
/* If it's an "AFTER"-type skip, jump ahead */
|
|
if (trig->skip == AFTER_SKIP) {
|
|
int iter = 0;
|
|
while (iter++ <= MaxSatIter) {
|
|
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
|
if (*err) return -2;
|
|
if (!omit) {
|
|
break;
|
|
}
|
|
simple++;
|
|
}
|
|
if (iter > MaxSatIter) {
|
|
*err = E_CANT_TRIG;
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
/* Return the date */
|
|
return simple;
|
|
}
|
|
|
|
int
|
|
AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|
{
|
|
int y, m, d;
|
|
/* If we have an AT, save the original event start */
|
|
if (tim->ttime != NO_TIME) {
|
|
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
|
|
if (tim->duration != NO_TIME) {
|
|
trig->eventduration = tim->duration;
|
|
}
|
|
}
|
|
|
|
/* Now potentially adjust */
|
|
if (r < today && r + trig->duration_days >= today) {
|
|
/* Adjust duration down */
|
|
tim->duration -= (today - r) * MINUTES_PER_DAY;
|
|
tim->duration += tim->ttime;
|
|
|
|
/* Start at midnight */
|
|
tim->ttime = 0;
|
|
|
|
/* Change trigger date to today */
|
|
r = today;
|
|
if (DebugFlag & DB_PRTTRIG) {
|
|
FromDSE(r, &y, &m, &d);
|
|
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
|
|
FileName, LineNo,
|
|
get_day_name(r % 7),
|
|
d,
|
|
get_month_name(m),
|
|
y);
|
|
if (tim->ttime != NO_TIME) {
|
|
fprintf(ErrFp, " AT %02d:%02d",
|
|
(tim->ttime / 60),
|
|
(tim->ttime % 60));
|
|
if (tim->duration != NO_TIME) {
|
|
fprintf(ErrFp, " DURATION %02d:%02d",
|
|
(tim->duration / 60),
|
|
(tim->duration % 60));
|
|
}
|
|
}
|
|
fprintf(ErrFp, "\n");
|
|
}
|
|
|
|
}
|
|
if (save_in_globals) {
|
|
SaveAllTriggerInfo(trig, tim, r, tim->ttime, 1);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* ComputeTrigger */
|
|
/* */
|
|
/* The main function. Compute the next trigger date given */
|
|
/* today's date. */
|
|
/* */
|
|
/***************************************************************/
|
|
int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
|
|
int *err, int save_in_globals)
|
|
{
|
|
int r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals, 0);
|
|
if (*err != OK) {
|
|
return r;
|
|
}
|
|
if (r == today) {
|
|
if (tim->ttime != NO_TIME) {
|
|
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
|
|
if (tim->duration != NO_TIME) {
|
|
trig->eventduration = tim->duration;
|
|
}
|
|
}
|
|
if (save_in_globals) {
|
|
SaveAllTriggerInfo(trig, tim, r, tim->ttime, 1);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
if (trig->duration_days) {
|
|
r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals, trig->duration_days);
|
|
if (*err != OK) {
|
|
return r;
|
|
}
|
|
}
|
|
r = AdjustTriggerForDuration(today, r, trig, tim, save_in_globals);
|
|
return r;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* ComputeTriggerNoAdjustDuration */
|
|
/* */
|
|
/* Compute a trigger, but do NOT adjust the time trigger */
|
|
/* duration. */
|
|
/* */
|
|
/***************************************************************/
|
|
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
|
int *err, int save_in_globals, int duration_days)
|
|
{
|
|
int nattempts = 0,
|
|
start = today - duration_days,
|
|
nextstart = 0,
|
|
y, m, d, omit,
|
|
result;
|
|
|
|
trig->expired = 0;
|
|
if (save_in_globals) {
|
|
LastTrigValid = 0;
|
|
}
|
|
|
|
/* Assume everything works */
|
|
*err = OK;
|
|
|
|
/* But check for obvious problems... */
|
|
if ((WeekdayOmits | trig->localomit) == 0x7F) {
|
|
*err = E_2MANY_LOCALOMIT;
|
|
return -1;
|
|
}
|
|
|
|
if (start < 0) {
|
|
*err = E_DATE_OVER;
|
|
return -1;
|
|
}
|
|
|
|
if (tim->duration != NO_TIME && tim->ttime == NO_TIME) {
|
|
*err = E_DURATION_NO_AT;
|
|
return -1;
|
|
}
|
|
|
|
if (trig->rep != NO_REP &&
|
|
(trig->d == NO_DAY ||
|
|
trig->m == NO_MON ||
|
|
trig->y == NO_YR)) {
|
|
Eprint("%s", ErrMsg[E_REP_FULSPEC]);
|
|
*err = E_REP_FULSPEC;
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* Save the trigger */
|
|
if (save_in_globals) {
|
|
SaveLastTrigger(trig);
|
|
}
|
|
|
|
while (nattempts++ < TRIG_ATTEMPTS) {
|
|
result = GetNextTriggerDate(trig, start, err, &nextstart);
|
|
|
|
/* If there's an error, die immediately */
|
|
if (*err) return -1;
|
|
if (result == -1) {
|
|
trig->expired = 1;
|
|
if (DebugFlag & DB_PRTTRIG) {
|
|
fprintf(ErrFp, "%s(%d): %s\n",
|
|
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/* If result is >= today, great! */
|
|
if (trig->skip == SKIP_SKIP) {
|
|
*err = IsOmitted(result, trig->localomit, trig->omitfunc, &omit);
|
|
if (*err) return -1;
|
|
} else {
|
|
omit = 0;
|
|
}
|
|
|
|
/** FIXME: Fix bad interaction with SATISFY... need to rethink!!! */
|
|
if (result+duration_days >= today &&
|
|
(trig->skip != SKIP_SKIP || !omit)) {
|
|
if (save_in_globals) {
|
|
LastTriggerDate = result; /* Save in global var */
|
|
LastTrigValid = 1;
|
|
}
|
|
if (DebugFlag & DB_PRTTRIG) {
|
|
FromDSE(result, &y, &m, &d);
|
|
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
|
|
FileName, LineNo,
|
|
get_day_name(result % 7),
|
|
d,
|
|
get_month_name(m),
|
|
y);
|
|
if (tim->ttime != NO_TIME) {
|
|
fprintf(ErrFp, " AT %02d:%02d",
|
|
(tim->ttime / 60),
|
|
(tim->ttime % 60));
|
|
if (tim->duration != NO_TIME) {
|
|
fprintf(ErrFp, " DURATION %02d:%02d",
|
|
(tim->duration / 60),
|
|
(tim->duration % 60));
|
|
}
|
|
}
|
|
fprintf(ErrFp, "\n");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* If it's a simple trigger, no point in rescanning */
|
|
if (trig->back == NO_BACK &&
|
|
trig->skip == NO_SKIP &&
|
|
trig->rep == NO_REP) {
|
|
trig->expired = 1;
|
|
if (DebugFlag & DB_PRTTRIG) {
|
|
fprintf(ErrFp, "%s(%d): %s\n",
|
|
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
|
}
|
|
if (result != -1) {
|
|
if (save_in_globals) {
|
|
LastTriggerDate = result;
|
|
LastTrigValid = 1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (trig->skip == SKIP_SKIP &&
|
|
omit &&
|
|
nextstart <= start &&
|
|
result >= start) {
|
|
nextstart = result + 1;
|
|
}
|
|
|
|
/* Keep scanning... unless there's no point in doing it.*/
|
|
if (nextstart <= start) {
|
|
if (result != -1) {
|
|
if (save_in_globals) {
|
|
LastTriggerDate = result;
|
|
LastTrigValid = 1;
|
|
}
|
|
}
|
|
trig->expired = 1;
|
|
if (DebugFlag & DB_PRTTRIG) {
|
|
fprintf(ErrFp, "%s(%d): %s\n",
|
|
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
|
}
|
|
return -1;
|
|
}
|
|
else start = nextstart;
|
|
|
|
}
|
|
|
|
/* We failed - too many attempts or trigger has expired*/
|
|
*err = E_CANT_TRIG;
|
|
return -1;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* ComputeScanStart */
|
|
/* */
|
|
/* Figure out where to start scan from by examining SCANFROM */
|
|
/* and DURATION */
|
|
/* */
|
|
/***************************************************************/
|
|
int
|
|
ComputeScanStart(int today, Trigger *trig, TimeTrig *tt)
|
|
{
|
|
int minutes, days;
|
|
|
|
/* If we don't have a time/duration, just use scanfrom */
|
|
if (tt->ttime == NO_TIME ||
|
|
tt->duration == NO_TIME) {
|
|
if (trig->scanfrom == NO_DATE) {
|
|
return today;
|
|
}
|
|
return trig->scanfrom;
|
|
}
|
|
|
|
/* Calculate time-based SCANFROM */
|
|
minutes = tt->ttime + tt->duration - 1;
|
|
|
|
/* Figure out how many days to scan backwards from */
|
|
days = minutes / MINUTES_PER_DAY;
|
|
|
|
if (trig->scanfrom != NO_DATE) {
|
|
if (trig->scanfrom <= today - days) {
|
|
return trig->scanfrom;
|
|
} else {
|
|
return today - days;
|
|
}
|
|
}
|
|
return today - days;
|
|
}
|