/*------------------------------------------------------------------------ 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 added more functionality: list, stop, count ------------------------------------------------------------------------*/ #include #include #include #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; typedef enum {cron_list, cron_stop, cron_count} CronFunc; typedef struct { SConnection *pCon; CronFunc func; char *cmd; int cnt; } 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 tm; char datim[24]; 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) { SCPrintf(self->pCon, eLogError, "sicscron script '%s' stopped", self->pCommand); self->iEnd = 0; return 0; } SCPrintf(self->pCon, eLogError, "ERROR in sicscron script '%s': %s", self->pCommand, pTcl->result); } if (self->iEnd == 2) { /* dolater command */ self->iEnd = 0; return 0; } self->tNext += self->iInterval; if (now > self->tNext) self->tNext = now; } if (self->iEnd <= 0) { tm = *localtime(&now); strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); SCPrintf(self->pCon, eLog, "crontask'%s' terminating at %s", self->pCommand, datim); } 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 == CRONFUNC) { data = pSigData; switch (data->func) { case cron_list: tm = *localtime(&self->tNext); strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); if (self->iInterval < 0) { SCPrintf(data->pCon, eLog, "%s %s", datim, self->pCommand); } else { SCPrintf(data->pCon, eLog, "%s %8d %s", datim, self->iInterval, self->pCommand); } break; case cron_stop: if (strcmp(data->cmd, self->pCommand) == 0) { self->iEnd = 0; data->cnt++; } break; case cron_count: if (strcmp(data->cmd, self->pCommand) == 0) { data->cnt++; } break; } } } /*-----------------------------------------------------------------------*/ 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) { data.func = cron_list; SCPrintf(pCon, eLog, "Date Time Interval Command"); data.pCon = pCon; TaskSignal(pServ->pTasker, CRONFUNC, &data); return 1; } if (argc > 2 && strcasecmp(argv[1], "stop") == 0) { data.func = cron_stop; data.cmd = argv[2]; data.cnt = 0; TaskSignal(pServ->pTasker, CRONFUNC, &data); SCPrintf(pCon, eValue, "%d cron jobs stopped", data.cnt); return 1; } if (argc > 2 && strcasecmp(argv[1], "count") == 0) { data.func = cron_count; data.cmd = argv[2]; data.cnt = 0; TaskSignal(pServ->pTasker, CRONFUNC, &data); SCPrintf(pCon, eValue, "%d", data.cnt); return 1; } /* enough arguments? */ if (argc < 3) { SCPrintf(pCon, eError, "ERROR: usage: %s