Files
sics/sicscron.c
Ferdi Franceschini 6921d0426c PSI UPDATE
r1724 | ffr | 2007-03-27 07:56:13 +1000 (Tue, 27 Mar 2007) | 2 lines
2012-11-15 13:10:21 +11:00

214 lines
5.4 KiB
C

/*------------------------------------------------------------------------
S I C S C R O N
A cron like command facility for SICS which allows to repeat a command
at given time intervals.
copyright: see copyright.h
Mark Koennecke, November 1999
modified to give more error output: Mark Koennecke, December 2010
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "macro.h"
#include "fortify.h"
#include "sics.h"
#include "splitter.h"
#include "sicscron.h"
#include "commandlog.h"
typedef struct {
int iInterval;
time_t tNext;
char *pCommand;
SConnection *pCon;
int iEnd;
Statistics *stat;
} Cron, *pCron;
typedef struct {
SConnection *pCon;
int dolater;
} CronListData;
/*------------------------------------------------------------------------*/
static void KillCron(void *pData)
{
pCron self = (pCron) pData;
if (!self) {
return;
}
if (self->pCommand) {
free(self->pCommand);
}
if (self->pCon) {
SCDeleteConnection(self->pCon);
}
if (self->stat) {
StatisticsKill(self->stat);
}
free(self);
}
/*-----------------------------------------------------------------------*/
static int CronTask(void *pData)
{
Statistics *old;
pCron self = (pCron) pData;
int iRet;
Tcl_Interp *pTcl = pServ->pSics->pTcl;
time_t now;
struct tm *nowtm;
char buffer[1024];
if (!self) {
return 0;
}
now = time(NULL);
if (now >= self->tNext) {
MacroPush(self->pCon);
old = StatisticsBegin(self->stat);
iRet = Tcl_Eval(pTcl, self->pCommand);
StatisticsEnd(old);
MacroPop();
if (iRet != TCL_OK) {
if (strcmp(pTcl->result, "stop") == 0) {
snprintf(buffer,1024,"sicscron script '%s' stopped",
self->pCommand);
SCPrintf(self->pCon, eLogError, buffer);
WriteToCommandLog("SICSCRON:", buffer);
self->iEnd = 0;
return 0;
}
snprintf(buffer,1024,"ERROR in sicscron script '%s': %s", self->pCommand, pTcl->result);
SCPrintf(self->pCon, eLogError,buffer);
WriteToCommandLog("SICSCRON:", buffer);
}
if (self->iEnd == 2) { /* dolater command */
self->iEnd = 0;
return 0;
}
self->tNext += self->iInterval;
if (now > self->tNext)
self->tNext = now;
}
/* printf("CronTask return: %d\n", self->iEnd > 0);*/
if(self->iEnd <= 0){
snprintf(buffer,1024,"crontask terminating at %s on %d", ctime(&now), self->iEnd);
WriteToCommandLog("SICSCRON", buffer);
}
return self->iEnd > 0;
}
/*-----------------------------------------------------------------------*/
static void CronSignal(void *pData, int iID, void *pSigData)
{
pCron self = (pCron) pData;
int *iInt;
struct tm tm;
char datim[24];
CronListData *data;
if (iID == SICSINT) {
iInt = (int *) pSigData;
if (*iInt == eEndServer) {
self->iEnd = 0;
}
}
if (iID == CRONLIST) {
data = pSigData;
if (self->iEnd == 2 && data->dolater) {
tm = *localtime(&self->tNext);
strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm);
SCPrintf(data->pCon, eLog, "%s %s", datim, self->pCommand);
} else if (self->iEnd == 1 && !data->dolater) {
tm = *localtime(&self->tNext);
strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm);
SCPrintf(data->pCon, eLog, "%s %8d %s", datim,
self->iInterval, self->pCommand);
}
}
}
/*-----------------------------------------------------------------------*/
int MakeCron(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pCron pNew = NULL;
int iVal, iRet, rights;
char *cmd;
CronListData data;
/* need user priv. */
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
if (argc == 2 && strcasecmp(argv[1], "list") == 0) {
if (strcasecmp(argv[0], "dolater") == 0) {
data.dolater = 1;
SCPrintf(pCon, eError, "Date Time Command");
} else {
data.dolater = 0;
SCPrintf(pCon, eError, "Date Time Interval Command");
}
data.pCon = pCon;
TaskSignal(pServ->pTasker, CRONLIST, &data);
return 1;
}
/* enough arguments? */
if (argc < 3) {
SCPrintf(pCon, eError, "ERROR: usage: %s <interval> <script>", argv[0]);
return 0;
}
/* interpret first argument as interval in seconds */
iRet = Tcl_GetInt(pSics->pTcl, argv[1], &iVal);
if (iRet != TCL_OK) {
SCWrite(pCon, "ERROR: failed to convert interval argument to int",
eError);
return 0;
}
/* concatenate the rest to the command */
cmd = Arg2Tcl(argc - 2, &argv[2], NULL, 0);
/* create data structure and install task */
pNew = (pCron) malloc(sizeof(Cron));
if (!pNew || !cmd) {
SCWrite(pCon, "ERROR: out of memory in sicscron", eError);
return 0;
}
pNew->pCon = SCCreateDummyConnection(pSics);
if (!pNew->pCon) {
SCWrite(pCon, "ERROR: out of memory in sicscron", eError);
return 0;
}
rights = SCGetRights(pCon);
if (rights > usMugger) {
/* transfer the rights to the dummy connection */
SCSetRights(pNew->pCon, rights);
}
pNew->pCommand = cmd;
pNew->tNext = time(NULL) + iVal;
if (strcasecmp(argv[0], "dolater") == 0) {
pNew->iInterval = -1;
pNew->iEnd = 2;
} else {
pNew->iInterval = iVal;
pNew->iEnd = 1;
}
pNew->stat = StatisticsNew(cmd);
TaskRegister(pServ->pTasker, CronTask, CronSignal, KillCron, pNew, 1);
SCSendOK(pCon);
return 1;
}