#include <exec/types.h>
#include <exec/nodes.h>

#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/semaphores.h>
#include <dos/rdargs.h>
#include <dos/notify.h>
#include <dos/dostags.h>
#include <dos/datetime.h>
#include <rexx/rxslib.h>
#include <rexx/errors.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>

#include <clib/exec_protos.h>
extern struct ExecBase *SysBase;
#include <pragmas/exec_lib.h>

#include <clib/dos_protos.h>
extern struct DosLibrary *DOSBase;
#include <pragmas/dos_lib.h>

#include <clib/rexxsyslib_protos.h>
extern struct RxsLib *RexxSysBase;
#include <pragmas/rexxsyslib_lib.h>

#include <clib/icon_protos.h>
extern struct Library *IconBase;
#include <pragmas/icon_lib.h>

#include <clib/timer_protos.h>
extern struct timerequest TimerIO;
#define TimerBase (TimerIO.tr_node.io_Device)
#include <pragmas/timer_lib.h>

#include <clib/alib_protos.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <dos.h>	/* for __emit() prototype */

#define SECSINDAY (86400)

/* this struct holds a system time in a way we can easily use it */
typedef struct {
	ULONG st_tvsecs;	/* as returned by the timer device */
	UWORD st_Year;
	UWORD st_Month;
	UWORD st_Day;
	UWORD st_Hour;
	UWORD st_Min;
	UWORD st_Sec;
	UBYTE st_DOW;
} SystemTime_t;

struct CyberNode {
	struct Node	cn_Node;
#define cn_Name cn_Node.ln_Name
	STRPTR		cn_Command;
	STRPTR		cn_ReDirIn;
	STRPTR		cn_ReDirOut;
	STRPTR		cn_ReDirErr;
	STRPTR		cn_CustomShell;
	STRPTR		cn_SendToUser;
	ULONG		cn_Stack;
	BYTE		cn_Priority;
	UBYTE		cn_DayOfWeek;
	UWORD		cn_Month;
	ULONG		cn_Day;
	ULONG		cn_Hour;
	ULONG		cn_HiMin;
	ULONG		cn_LoMin;
	UBYTE		cn_ObeyQueue;
	UBYTE		cn_Flags;
};

/* these are the possible values for the flags in cn_Flags */
#define CNB_NOLOG   0		/* don't to log when running the command */
#define CNB_REXX    1		/* start command as a rexx script */
#define CNB_CRONTAB 2		/* node was generated by an entry in crontab
				 * file */
#define CNB_SYSSH   3		/* use system shell instead of user shell */
#define CNB_OUTAPP  4		/* append to output redirection instead of
				   overwrite */
#define CNB_ERRAPP  5		/* append to error redirection instead of
				   overwrite */
#define CNB_EXECONE 6		/* run job once and then delete it */
#define CNB_DELAYED 7		/* queued job was delayed due to queue limits */

#define CNF_NOLOG   (1L << CNB_NOLOG)
#define CNF_REXX    (1L << CNB_REXX)
#define CNF_CRONTAB (1L << CNB_CRONTAB)
#define CNF_SYSSH   (1L << CNB_SYSSH)
#define CNF_OUTAPP  (1L << CNB_OUTAPP)
#define CNF_ERRAPP  (1L << CNB_ERRAPP)
#define CNF_EXECONE (1L << CNB_EXECONE)
#define CNF_DELAYED (1L << CNB_DELAYED)

struct JobQueue {
	ULONG	jq_Max;
	ULONG	jq_Cur;
};

struct SystemECdata {
	UWORD	jobNo;
	UBYTE	queueNo;
	UBYTE	flags;
};

/*
 * here we have prototypes for all functions contained in or used by this
 * file
 */
struct CyberNode *ParseEvent(STRPTR);
void ParseBits(ULONG *, STRPTR);
void UnParseBits(ULONG *, STRPTR, int, int);
UWORD GetJobNum(void);
void FreeJobNum(UWORD);
void __stdargs Log(STRPTR, ...);
void __stdargs MySPrintf(STRPTR, STRPTR, ...);
int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg);
void ReadCronTab(void);
BOOL GetARexxLib(void);
void FreeARexxLib(void);
void __stdargs ErrorMsg(char *fmt, ...);
void MyExit(int);
void FreeEvents(BOOL);
STRPTR WBtoCLIargs(struct WBStartup *WBMsg);
void StartSystemJob(struct CyberNode *cn);
void StartRexxJob(struct CyberNode *cn);
int __saveds __asm EndSystemJob(register __d0 int rc, register __d1 struct SystemECData *data);
void GetSystemTime(SystemTime_t *st);
void ScanForJobs(void);
void HandleRexxEvents(void);
struct CyberNode *FindEvent(STRPTR name);
BPTR SetupSendMail(STRPTR cmdName, STRPTR userName);

extern void DoMsg(struct RexxMsg *, APTR, int, int);

void   rx_Shutdown(void);
STRPTR rx_Version(void);
void   rx_Suspend(void);
void   rx_Resume(void);
int    rx_NewEventFile(STRPTR);
void   rx_CloseEventFile(void);
int    rx_AddEvent(STRPTR);
int    rx_DeleteRexxEvent(STRPTR);
int    rx_DeleteEvent(STRPTR);
void   rx_PurgeRexxEvents(void);
STRPTR rx_ShowEvent(STRPTR);
STRPTR rx_ListEvents(void);
STRPTR rx_ShowStatus(void);
int    rx_NewLogFile(STRPTR);
void   rx_CloseLogFile(void);
int    rx_SetQueueMax(STRPTR);
int    rx_GetQueueMax(STRPTR);
