Files
sics/sicscron.c

178 lines
4.3 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
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "macro.h"
#include "fortify.h"
#include "sics.h"
#include "splitter.h"
#include "sicscron.h"
typedef struct {
int iInterval;
time_t tNext;
char *pCommand;
SConnection *pCon;
int iEnd;
Statistics *stat;
} Cron, *pCron;
/*------------------------------------------------------------------------*/
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;
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) {
SCPrintf(self->pCon, eStatus,
"ERROR in sicscron script: %s", pTcl->result);
self->iEnd = 0;
return 0;
}
if (self->iEnd == 2) { /* dolater command */
self->iEnd = 0;
return 0;
}
self->tNext += self->iInterval;
if (now > self->tNext) self->tNext = now + 1;
}
return self->iEnd > 0;
}
/*-----------------------------------------------------------------------*/
static void CronSignal(void *pData, int iID, void *pSigData)
{
pCron self = (pCron)pData;
int *iInt;
if(iID == SICSINT)
{
iInt = (int *)pSigData;
if(*iInt >= eEndServer)
{
self->iEnd = 0;
}
}
}
/*-----------------------------------------------------------------------*/
int MakeCron(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pCron pNew = NULL;
int iVal, iRet, rights;
char *cmd;
/* need user priv. */
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
/* enough arguments? */
if(argc < 3)
{
SCPrintf(pCon,eError,"ERROR: not enough arguments to %s", 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->iInterval = iVal;
pNew->pCommand = cmd;
pNew->tNext = time(NULL) + iVal;
if (strcasecmp(argv[0], "dolater") == 0) {
pNew->iEnd = 2;
} else {
pNew->iEnd = 1;
}
pNew->stat = StatisticsNew(cmd);
TaskRegister(pServ->pTasker,
CronTask,
CronSignal,
KillCron,
pNew,
1);
SCSendOK(pCon);
return 1;
}