228 lines
4.5 KiB
C
228 lines
4.5 KiB
C
/*
|
|
* Copyright (C) 2011 Martin Willi
|
|
* Copyright (C) 2011 revosec AG
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*/
|
|
|
|
#include "certexpire_cron.h"
|
|
|
|
#include <time.h>
|
|
|
|
#include <utils/debug.h>
|
|
#include <processing/jobs/callback_job.h>
|
|
|
|
typedef struct private_certexpire_cron_t private_certexpire_cron_t;
|
|
|
|
/**
|
|
* Private data of an certexpire_cron_t object.
|
|
*/
|
|
struct private_certexpire_cron_t {
|
|
|
|
/**
|
|
* Public certexpire_cron_t interface.
|
|
*/
|
|
certexpire_cron_t public;
|
|
|
|
/**
|
|
* time when to run export job
|
|
*/
|
|
struct {
|
|
bool m[60];
|
|
bool h[24];
|
|
bool d[32];
|
|
bool my[13];
|
|
bool dw[8];
|
|
} cron;
|
|
|
|
/**
|
|
* Callback function to execute
|
|
*/
|
|
certexpire_cron_job_t job;
|
|
|
|
/**
|
|
* Data to pass to callback
|
|
*/
|
|
void *data;
|
|
};
|
|
|
|
/**
|
|
* Check if we should execute the export job
|
|
*/
|
|
static job_requeue_t check_cron(private_certexpire_cron_t *this)
|
|
{
|
|
struct tm tm;
|
|
time_t t;
|
|
|
|
t = time(NULL);
|
|
localtime_r(&t, &tm);
|
|
|
|
/* recheck every minute at second 0 */
|
|
lib->scheduler->schedule_job(lib->scheduler,
|
|
(job_t*)callback_job_create_with_prio((callback_job_cb_t)check_cron,
|
|
this, NULL, NULL, JOB_PRIO_CRITICAL), 60 - tm.tm_sec);
|
|
|
|
/* skip this minute if we had a large negative time shift */
|
|
if (tm.tm_sec <= 30)
|
|
{
|
|
if (this->cron.m[tm.tm_min] &&
|
|
this->cron.h[tm.tm_hour] &&
|
|
this->cron.d[tm.tm_mday] &&
|
|
this->cron.my[tm.tm_mon + 1] &&
|
|
(this->cron.dw[tm.tm_wday] ||
|
|
(this->cron.dw[7] && tm.tm_wday == 0)))
|
|
{
|
|
this->job(this->data);
|
|
}
|
|
}
|
|
return JOB_REQUEUE_NONE;
|
|
}
|
|
|
|
/**
|
|
* Parse a cron range component into boolean fields
|
|
*/
|
|
static void parse_ranges(bool *fields, char *label, int mi, int ma, char *range)
|
|
{
|
|
enumerator_t *enumerator;
|
|
int from, to, i;
|
|
|
|
if (streq(range, "*"))
|
|
{
|
|
for (i = mi; i <= ma; i++)
|
|
{
|
|
fields[i] = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
enumerator = enumerator_create_token(range, ",", "");
|
|
while (enumerator->enumerate(enumerator, &range))
|
|
{
|
|
switch (sscanf(range, "%d-%d", &from, &to))
|
|
{
|
|
case 1: /* single value */
|
|
if (from >= mi && from <= ma)
|
|
{
|
|
fields[from] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DBG1(DBG_CFG, "ignoring cron %s %d, out of range",
|
|
label, from);
|
|
}
|
|
break;
|
|
case 2: /* range */
|
|
if (from < mi)
|
|
{
|
|
DBG1(DBG_CFG, "cron %s out of range, shortening start "
|
|
"from %d to %d", label, from, mi);
|
|
from = mi;
|
|
}
|
|
if (to > ma)
|
|
{
|
|
DBG1(DBG_CFG, "cron %s out of range, shortening end "
|
|
"from %d to %d", label, to, ma);
|
|
to = ma;
|
|
}
|
|
for (i = from; i <= to; i++)
|
|
{
|
|
fields[i] = TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
}
|
|
DBG3(DBG_CFG, "cron job with enabled %ss:", label);
|
|
for (i = mi; i <= ma; i++)
|
|
{
|
|
if (fields[i])
|
|
{
|
|
DBG3(DBG_CFG, " %d", i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Start cron processing, if configured
|
|
*/
|
|
static void start_cron(private_certexpire_cron_t *this, char *cron)
|
|
{
|
|
enumerator_t *enumerator;
|
|
int i = 0;
|
|
|
|
enumerator = enumerator_create_token(cron, " ", " ");
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
if (!enumerator->enumerate(enumerator, &cron))
|
|
{
|
|
DBG1(DBG_CFG, "cron misses a field, using '*'");
|
|
cron = "*";
|
|
}
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
parse_ranges(this->cron.m, "minute", 0, 59, cron);
|
|
break;
|
|
case 1:
|
|
parse_ranges(this->cron.h, "hour", 0, 23, cron);
|
|
break;
|
|
case 2:
|
|
parse_ranges(this->cron.d, "day", 1, 31, cron);
|
|
break;
|
|
case 3:
|
|
parse_ranges(this->cron.my, "month", 1, 12, cron);
|
|
break;
|
|
case 4:
|
|
parse_ranges(this->cron.dw, "weekday", 0, 7, cron);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (enumerator->enumerate(enumerator, &cron))
|
|
{
|
|
DBG1(DBG_CFG, "ignoring extra fields in cron");
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
|
|
check_cron(this);
|
|
}
|
|
|
|
METHOD(certexpire_cron_t, destroy, void,
|
|
private_certexpire_cron_t *this)
|
|
{
|
|
free(this);
|
|
}
|
|
|
|
/**
|
|
* See header
|
|
*/
|
|
certexpire_cron_t *certexpire_cron_create(char *cron, certexpire_cron_job_t job,
|
|
void *data)
|
|
{
|
|
private_certexpire_cron_t *this;
|
|
|
|
INIT(this,
|
|
.public = {
|
|
.destroy = _destroy,
|
|
},
|
|
.job = job,
|
|
.data = data,
|
|
);
|
|
|
|
start_cron(this, cron);
|
|
|
|
return &this->public;
|
|
}
|