/*------------------------------------------------------------------------ S I C S C R O N A cron like command facility for SICS which allows to repeat a command at given time intervalls. copyright: see copyright.h Mark Koennecke, November 1999 ------------------------------------------------------------------------*/ #include #include #include #include "macro.h" #include "fortify.h" #include "sics.h" #include "splitter.h" #include "sicscron.h" typedef struct { int iIntervall; 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; if(!self) { return 0; } if(time(NULL) > 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; } self->tNext = time(NULL) + self->iIntervall; } return self->iEnd; } /*-----------------------------------------------------------------------*/ 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) { SCWrite(pCon,"ERROR: not enough arguments to sicscron",eError); return 0; } /* interpret first argument as intervall in seconds */ iRet = Tcl_GetInt(pSics->pTcl,argv[1],&iVal); if(iRet != TCL_OK) { SCWrite(pCon,"ERROR: failed to convert intervall 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->iIntervall = iVal; pNew->pCommand = cmd; pNew->tNext = 0; pNew->iEnd = 1; pNew->stat = StatisticsNew(cmd); TaskRegister(pServ->pTasker, CronTask, CronSignal, KillCron, pNew, 1); SCSendOK(pCon); return 1; }