/*------------------------------------------------------------------------
                         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 <stdlib.h>
#include <assert.h>
#include <time.h>
#include <tcl.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;
                  } 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);
     }
     free(self);
  }
/*-----------------------------------------------------------------------*/
  static int CronTask(void *pData)
  {
     pCron self = (pCron)pData;
     
     if(!self)
     {
        return 0;
     }

     if(time(NULL) > self->tNext)
     {
         SCInvoke(self->pCon,pServ->pSics,self->pCommand);
         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;
     char pBueffel[512];

     /* only managers may do this */
     if(!SCMatchRights(pCon,usMugger))
     {
        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 */
     Arg2Text(argc-2,&argv[2],pBueffel,511);

     /* create data structure and install task */
     pNew = (pCron)malloc(sizeof(Cron));
     if(!pNew)
     {
        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;
     }
     pNew->pCon->iDummy = 1;
     pNew->iIntervall = iVal;
     pNew->pCommand = strdup(pBueffel);
     pNew->tNext = 0;
     pNew->iEnd = 1;

     TaskRegister(pServ->pTasker,
                  CronTask,
                  CronSignal,
                  KillCron,
                  pNew,
                  1);
      SCSendOK(pCon);
      return 1;
  }
