/* 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