/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
/* 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 ();
#include <sys/types.h>
#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;
static int cron_add(time_t interv, int runcnt, char *cmd, char *who, char *aswh, int flg);
static int lowest_quant(void);
static int cron_del(int jobid, char *who, int pf);
static void cron_list(char *who);
int cron_run (time_t now)
{
Kron *k;
Kron *p;
long 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) {
log_printf (allerr, (char *) 0);
return (-1);
}
k->interv = interv;
(void) time (&k->last);
k->runcnt = runcnt;
k->who = (char *) malloc ((unsigned) (strlen (who) + 1));
if (k->who == (char *) 0) {
log_printf (allerr, (char *) 0);
return (-1);
}
strcpy (k->who, who);
k->aswho = (char *) malloc ((unsigned) (strlen (aswho) + 1));
if (k->aswho == (char *) 0) {
log_printf (allerr, (char *) 0);
return (-1);
}
strcpy (k->aswho, aswho);
k->cmd = (char *) malloc ((unsigned) (strlen (cmd) + 1));
if (k->cmd == (char *) 0) {
log_printf (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 (void)
{
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 (char *who)
{
Kron *k;
char pbuf[80];
k = crontab;
while (k != (Kron *) 0) {
snprintf (pbuf, sizeof (pbuf), "id# %d, every %d sec., ", k->jobid,
(int) k->interv);
say (who, pbuf, (char *) 0);
if (k->runcnt != -1) {
snprintf (pbuf, sizeof (pbuf), "%d runs, ", k->runcnt);
say (who, pbuf, (char *) 0);
}
snprintf (pbuf, sizeof (pbuf), "(%s/%s): %-30s\n", k->who, k->aswho,
k->cmd);
say (who, pbuf, (char *) 0);
k = k->nxt;
}
}
/* ARGSUSED */
int cmd__cronconfig (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) {
log_printf ("usage: defevent interval macro [who] [aswho] [count]\n",
(char *) 0);
return (UERR_ARGCNT);
}
if ((iv = atoi (av[2])) < CRONQUANT) {
log_printf ("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) {
log_printf ("event not added\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("added event: ", av[3], "\n", (char *) 0);
return (UERR_NONE);
}
/* UNdefine an event */
if (!strcmp (av[1], "undefevent")) {
if (ac != 3) {
log_printf ("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);
}
log_printf ("_cronconfig: I don't understand ", av[1], "\n", (char *) 0);
return (UERR_BADPARM);
}
#ifdef COMBAT
/* ARGSUSED */
int cmd__crondel (int ac, char *av[], char *who, char *aswho)
{
return (cron_del (atoi (av[1]), who, 0));
}
/* ARGSUSED */
int cmd__cronlist (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;
snprintf (pbuf, sizeof (pbuf), "id# %d, every %d sec., ", k->jobid,
(int) k->interv);
say (who, pbuf, (char *) 0);
if (k->runcnt != -1) {
snprintf (pbuf, sizeof (pbuf), "%d runs, ", k->runcnt);
say (who, pbuf, (char *) 0);
}
snprintf (pbuf, sizeof (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 */
int cmd__cron (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) {
log_printf ("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, 10), ".\n", (char *) 0);
eval_cmd_returnint (eid);
return (UERR_NONE);
}
}
#endif