/
umud/DOC/
umud/DOC/examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
/*
	Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

#ifndef	lint
static	char	RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/cron.c,v 1.2 91/07/31 23:23:22 mjr Exp $";
#endif

/* configure all options BEFORE including system stuff. */
#include	"config.h"

/*
#define	CRON_DEBUG
*/


#ifdef	NOSYSTYPES_H
#include	<types.h>
#else
#include	<sys/types.h>
#endif

#include	"mud.h"

typedef struct	kron	{
	int	jobid;
	time_t	interv;
	time_t	last;
	int	runcnt;
	char	*who;
	char	*aswho;
	char	*cmd;
	struct	kron	*nxt;
} Kron;


static	Kron	*crontab;
static	int	curjobid = 0;


cron_run(now)
time_t	now;
{
	Kron	*k;
	Kron	*p;

	k = p = crontab;

#ifdef	CRON_DEBUG
	printf("running cron - quantum is %d\n",cron_quantum);
#endif

	while(k != (Kron *)0) {
		if(now - k->last >= k->interv) {
#ifdef	CRON_DEBUG
			printf("trigger %s runs %s\n",k->who,k->cmd);
#endif
			if(cache_check(k->who))
				(void)run(k->who,k->aswho,k->cmd,0,0,1);
			k->last = now;

			if(k->runcnt != -1)
				k->runcnt--;

		}

		if(k->runcnt == 0) {

			if(k == crontab)
				crontab = k->nxt;
			else
				p->nxt = k->nxt;

			if(k->cmd != (char *)0)
				free((mall_t)k->cmd);
			if(k->aswho != (char *)0)
				free((mall_t)k->aswho);
			if(k->who != (char *)0)
				free((mall_t)k->who);
			p = k;
			free((mall_t)k);
			k = p->nxt;
			continue;
		}

		p = k;
		k = k->nxt;
	}
	return(0);
}





static	int
cron_add(interv,runcnt,cmd,who,aswho)
time_t	interv;
int	runcnt;
char	*cmd;
char	*who;
char	*aswho;
{
	static	char	*allerr = "cannot allocate cron structure\n";
	Kron	*k;

	if(cmd == (char *)0 || who == (char *)0 || aswho == (char *)0 ||
		*cmd == '\0' || *who == '\0' || *aswho == '\0')
		return(1);

	if((k = (Kron *)malloc(sizeof(Kron))) == (Kron *)0) {
		logf(allerr,(char *)0);
		return(-1);
	}

	k->interv = interv;
	time(&k->last);
	k->runcnt = runcnt;

	k->who = (char *)malloc((unsigned)(strlen(who) + 1));
	if(k->who == (char *)0) {
		logf(allerr,(char *)0);
		return(-1);
	}
	strcpy(k->who,who);

	k->aswho = (char *)malloc((unsigned)(strlen(aswho) + 1));
	if(k->aswho == (char *)0) {
		logf(allerr,(char *)0);
		return(-1);
	}
	strcpy(k->aswho,aswho);

	k->cmd = (char *)malloc((unsigned)(strlen(cmd) + 1));
	if(k->cmd == (char *)0) {
		logf(allerr,(char *)0);
		return(-1);
	}
	strcpy(k->cmd,cmd);

	k->nxt = crontab;
	crontab = k;
	k->jobid = curjobid++;
	return(k->jobid);
}





static	int
lowest_quant()
{
	Kron	*k;
	int	lowest = 3600;

	for(k = crontab;k != (Kron *)0; k = k->nxt)
		if(k->interv < lowest)
			lowest = k->interv < CRONQUANT ? CRONQUANT : k->interv;
	return(lowest);
}





static	int
cron_del(jobid,who)
int	jobid;
char	*who;
{
	Kron	*k;
	Kron	*p;

	k = p = crontab;

	while(k != (Kron *)0) {
		if(k->jobid == jobid) {
			int	squant;

			squant = k->interv;
			if(k == crontab)
				crontab = k->nxt;
			else
				p->nxt = k->nxt;

			if(k->cmd != (char *)0)
				free((mall_t)k->cmd);
			if(k->aswho != (char *)0)
				free((mall_t)k->aswho);
			if(k->who != (char *)0)
				free((mall_t)k->who);
			free((mall_t)k);
			if(squant == cron_quantum) {
				cron_quantum = lowest_quant();
#ifdef	CRON_DEBUG
				printf("new cron quantum %d\n",cron_quantum);
#endif
			}
			return(0);
		}
		p = k;
		k = k->nxt;
	}
	return(1);
}





static	void
cron_list(who)
char	*who;
{
	Kron	*k;
	char	pbuf[80];

	k = crontab;

	while(k != (Kron *)0) {
		sprintf(pbuf,"id# %d, every %d sec., ",k->jobid,k->interv);
		say(who,pbuf,(char *)0);

		if(k->runcnt != -1) {
			sprintf(pbuf,"%d runs, ",k->runcnt);
			say(who,pbuf,(char *)0);
		}

		sprintf(pbuf,"(%s/%s): %-30s\n",k->who,k->aswho,k->cmd);
		say(who,pbuf,(char *)0);
		k = k->nxt;
	}
}



/* ARGSUSED */
cmd__cronconfig(ac,av,who,aswho)
int	ac;
char	*av[];
char	*who;
char	*aswho;
{
	/* define an event */
	if(!strcmp(av[1],"defevent")) {
		int	eid;
		int	iv;
		int	rc = -1; /* repeat forever */

		char	*twho;
		char	*taswho;

		if(ac < 4) {
			logf("usage: defevent interval macro [who] [aswho] [count]\n",(char *)0);
			return(1);
		}


		if((iv = atoi(av[2])) < CRONQUANT) {
			logf("event interval is too short\n",(char *)0);
			iv = CRONQUANT;
		}

		if(iv < cron_quantum) {
			cron_quantum = iv;
#ifdef	CRON_DEBUG
			printf("new cron quantum %d\n",cron_quantum);
#endif
		}

		twho = who;
		if(ac > 4)
			twho = av[4];

		taswho = who;
		if(ac > 5)
			taswho = av[5];

		if(ac > 6)
			rc = atoi(av[6]);

		eid = cron_add(iv,rc,av[3],twho,taswho);

		if(eid < 0) {
			logf("event not added\n",(char *)0);
			return(1);
		}
		logf("added event: ",av[3],"\n",(char *)0);
		return(0);
	}


	/* UNdefine an event */
	if(!strcmp(av[1],"undefevent")) {
		if(ac != 3) {
			logf("usage: undefevent event-id\n",(char *)0);
			return(1);
		}

		if(cron_del(atoi(av[2]),who)) {
			logf("no such event: ",av[2],"\n",(char *)0);
			return(1);
		}

		logf("undefined event ",av[2],"\n",(char *)0);
		return(0);
	}

	if(!strcmp(av[1],"list")) {
		cron_list(who);
		return(0);
	}

	if(!strcmp(av[1],"help")) {
		say(who,av[0]," undefevent event-id\n",(char *)0);
		say(who,av[0]," defevent interval macro [who] [aswho] [count]\n",(char *)0);
		say(who,av[0]," list\n",(char *)0);
		return(0);
	}
	
	logf("_cronconfig: I don't understand ",av[1],"\n",(char *)0);
	return(1);
}