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