/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
#ifndef lint
static char RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/cron.c,v 1.7 92/05/17 23:32:39 mjr Exp $";
#endif
/* configure all options BEFORE including system stuff. */
#include "config.h"
/*
#define CRON_DEBUG
*/
/* define this prototype here to avoid extern/static conflict */
static int lowest_quant();
#ifdef NOSYSTYPES_H
#include <types.h>
#else
#include <sys/types.h>
#endif
#include "mud.h"
#include "vars.h"
/* flags for cron entries */
#define KRON_CMD 01 /* is macro */
#define KRON_U 02 /* is U-code */
#define KRON_BILL 04 /* bill owner for call */
typedef struct kron {
int jobid;
time_t interv;
time_t last;
int runcnt;
int flgs;
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;
int squant = -1;
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)) {
if(k->flgs & KRON_U) {
parser_setinput(k->cmd);
if(parser_compile(k->who)) {
run_setactor(k->who);
(void)parser_run(k->who,k->aswho,0,(char **)0);
}
} else
if(k->flgs & KRON_CMD) {
(void)run(k->who,k->aswho,k->cmd,0,0,1);
}
}
k->last = now;
if(k->runcnt != -1)
k->runcnt--;
#ifdef COMBAT
/* debit the guy some action points */
if(k->flgs & KRON_BILL) {
int vat;
if(ut_getnum(k->who,var_action,&vat) < 0 ||
(vat - (2000 / k->interv) <= 0)) {
k->runcnt = 0;
#ifdef CRON_DEBUG
printf("expire %s action %s\n",k->who,k->cmd);
#endif
} else {
vat -= (2000 / k->interv);
ut_setnum(k->who,k->who,var_action,vat);
}
}
#endif
}
if(k->runcnt == 0) {
if(k == crontab)
crontab = k->nxt;
else
p->nxt = k->nxt;
if(squant == -1)
squant = k->interv;
else {
if(k->interv < squant)
squant = k->interv;
}
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;
}
if(squant != -1 && squant <= cron_quantum) {
cron_quantum = lowest_quant();
#ifdef CRON_DEBUG
printf("new cron quantum %d\n",cron_quantum);
#endif
}
return(0);
}
static int
cron_add(interv,runcnt,cmd,who,aswho,flg)
time_t interv;
int runcnt;
char *cmd;
char *who;
char *aswho;
int flg;
{
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->flgs = flg;
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,pf)
int jobid;
char *who;
int pf;
{
Kron *k;
Kron *p;
k = p = crontab;
while(k != (Kron *)0) {
if(k->jobid == jobid) {
int squant;
if(!pf && strcmp(who,k->who)) {
say(who,"Permission denied.\n",(char *)0);
return(UERR_PERM);
}
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
}
say(who,"Event deleted.\n",(char *)0);
return(UERR_NONE);
}
p = k;
k = k->nxt;
}
say(who,"Unknown event.\n",(char *)0);
return(UERR_NOMATCH);
}
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") || !strcmp(av[1],"defUevent")) {
int eid;
int iv;
int rc = -1; /* repeat forever */
char *twho;
char *taswho;
int flg = 0;
if(!strcmp(av[1],"defUevent"))
flg |= KRON_U;
else
flg |= KRON_CMD;
if(ac < 4) {
logf("usage: defevent interval macro [who] [aswho] [count]\n",(char *)0);
return(UERR_ARGCNT);
}
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,flg);
if(eid < 0) {
logf("event not added\n",(char *)0);
return(UERR_FATAL);
}
logf("added event: ",av[3],"\n",(char *)0);
return(UERR_NONE);
}
/* UNdefine an event */
if(!strcmp(av[1],"undefevent")) {
if(ac != 3) {
logf("usage: undefevent event-id\n",(char *)0);
return(UERR_ARGCNT);
}
return(cron_del(atoi(av[2]),who,1));
}
if(!strcmp(av[1],"list")) {
cron_list(who);
return(UERR_NONE);
}
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(UERR_NONE);
}
logf("_cronconfig: I don't understand ",av[1],"\n",(char *)0);
return(UERR_BADPARM);
}
#ifdef COMBAT
/* ARGSUSED */
cmd__crondel(ac,av,who,aswho)
int ac;
char *av[];
char *who;
char *aswho;
{
return(cron_del(atoi(av[1]),who,0));
}
/* ARGSUSED */
cmd__cronlist(ac,av,who,aswho)
int ac;
char *av[];
char *who;
char *aswho;
{
Kron *k;
char pbuf[80];
int got = 0;
for(k = crontab; k != (Kron *)0; k = k->nxt) {
if(strcmp(who,k->who))
continue;
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,": %-30s\n",k->cmd);
say(who,pbuf,(char *)0);
got++;
}
if(!got)
say(who,"No cron entries.\n",(char *)0);
return(UERR_NONE);
}
/* ARGSUSED */
cmd__cron(ac,av,who,aswho)
int ac;
char *av[];
char *who;
char *aswho;
{
int eid;
int iv;
int rc = -1; /* repeat forever */
char *twho;
int flg = 0;
if(!strcmp(av[0],"_Ucron"))
flg |= KRON_U|KRON_BILL;
else
flg |= KRON_CMD|KRON_BILL;
if(ac < 3) {
say(who,"usage: ",av[0]," second-count command [repeats] [object-actor]\n",(char *)0);
return(UERR_ARGCNT);
}
if((iv = atoi(av[1])) < CRONQUANT) {
logf("event interval is too short\n",(char *)0);
iv = CRONQUANT;
}
twho = who;
if(ac > 4)
twho = av[4];
if(!ut_isobjown(aswho,twho) && !ut_flagged(aswho,var_wiz)) {
say(who,"You do not own ",ut_name(twho),".\n",(char *)0);
return(UERR_PERM);
}
if(ac > 3)
rc = atoi(av[3]);
if(iv < cron_quantum) {
cron_quantum = iv;
#ifdef CRON_DEBUG
printf("new cron quantum %d\n",cron_quantum);
#endif
}
eid = cron_add(iv,rc,av[2],twho,twho,flg);
if(eid < 0) {
say(who,"Event not added.\n",(char *)0);
return(UERR_FATAL);
} else {
char fubb[MAXOID];
say(who,"Added event ",itoa(eid,fubb),".\n",(char *)0);
eval_cmd_returnint(eid);
return(UERR_NONE);
}
}
#endif