/* queue.c */
#include "config.h"
/*
* This file is part of TeenyMUD II.
* Copyright(C) 1993, 1994, 1995 by Jason Downs.
* All rights reserved.
*
* TeenyMUD II is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TeenyMUD II is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file 'COPYING'); if not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif /* HAVE_STRING_H */
#include <ctype.h>
#include "conf.h"
#include "teeny.h"
#include "commands.h"
#include "externs.h"
/* The TeenyMUD command queue system, inspired by MUSH. */
/* command queue structure. */
struct cque {
int player; /* object running command. */
int cause; /* object causing the command. */
int flags; /* special operators. */
time_t when; /* when to run command. */
int obj; /* object to use as a semaphore. */
char *cmd; /* what to run. */
int eargc; /* exec argument count. */
char **eargv; /* exec arguments. */
struct cque *next;
struct cque *prev;
};
/* iterative queue structure. */
struct ique {
int player; /* object running command. */
int cause; /* object causing the command. */
char *var; /* variable to update. */
char *val; /* value of variable. */
char *cmd; /* what to run. */
int eargc; /* exec argument count. */
char **eargv; /* exec arguments. */
struct ique *next;
struct ique *prev;
};
/* the queue list */
static struct cque *gqueue = (struct cque *)NULL;
static struct ique *iqueue = (struct ique *)NULL;
/* add something to the iterative queue. */
void queue_iadd(player, cause, var, val, command, eargc, eargv)
int player, cause;
char *var, *val, *command;
int eargc;
char *eargv[];
{
struct ique *new;
int owner, check;
if(mudconf.enable_money) {
if((get_int_elt(player, OWNER, &owner) == -1)
|| (get_int_elt(owner, QUEUE, &check) == -1)) {
logfile(LOG_ERROR, "queue_iadd: bad database reference.\n");
return;
}
if(check >= mudconf.queue_commands) {
if(!can_afford(owner, cause, mudconf.queue_cost, 1))
return;
if(set_int_elt(owner, QUEUE, 0) == -1) {
logfile(LOG_ERROR, "queue_iadd: couldn't reset queue count on #%d\n",
owner);
return;
}
} else {
if(set_int_elt(owner, QUEUE, ++check) == -1) {
logfile(LOG_ERROR, "queue_iadd: couldn't reset queue count on #%d\n",
owner);
return;
}
}
}
/* make the entry. */
new = (struct ique *)ty_malloc(sizeof(struct ique), "queue_iadd");
new->player = player;
new->cause = cause;
new->var = (char *)ty_strdup(var, "queue_iadd");
new->val = (char *)ty_strdup(val, "queue_iadd");
new->cmd = (char *)ty_strdup(command, "queue_iadd");
new->eargc = eargc;
new->eargv = eargv;
new->next = (struct ique *)NULL;
/* add it to the queue. */
if(iqueue == (struct ique *)NULL) {
new->prev = new;
iqueue = new;
} else {
/* add it to the tail. */
new->prev = iqueue->prev;
(iqueue->prev)->next = new;
iqueue->prev = new;
}
}
/* add something to the command queue. */
void queue_add(player, cause, delay, sema, command, eargc, eargv)
int player, cause, delay, sema;
char *command;
int eargc;
char *eargv[];
{
struct cque *new;
int owner, check;
if((command == (char *)NULL) || (command[0] == '\0'))
return;
if(mudconf.enable_money) {
if((get_int_elt(player, OWNER, &owner) == -1)
|| (get_int_elt(owner, QUEUE, &check) == -1)) {
logfile(LOG_ERROR, "queue_add: bad database reference.\n");
return;
}
if(check >= mudconf.queue_commands) {
if(!can_afford(owner, cause, mudconf.queue_cost, 1))
return;
if(set_int_elt(owner, QUEUE, 0) == -1) {
logfile(LOG_ERROR, "queue_add: couldn't reset queue count on #%d\n",
owner);
return;
}
} else {
if(set_int_elt(owner, QUEUE, ++check) == -1) {
logfile(LOG_ERROR, "queue_add: couldn't reset queue count on #%d\n",
owner);
return;
}
}
}
/* make the entry. */
new = (struct cque *)ty_malloc(sizeof(struct cque), "queue_add");
new->player = player;
new->cause = cause;
new->flags = 0;
new->when = (delay >= 0) ? mudstat.now + delay : -1;
new->obj = sema;
new->cmd = (char *)ty_strdup(command, "queue_add");
new->eargc = eargc;
new->eargv = eargv;
new->next = (struct cque *)NULL;
/* add it to the queue */
if(gqueue == (struct cque *)NULL) {
new->prev = new;
gqueue = new;
} else {
/* add it to the tail. */
new->prev = gqueue->prev;
(gqueue->prev)->next = new;
gqueue->prev = new;
}
}
/* do count things off the top of the queue(s). */
void queue_run(count)
int count;
{
register struct cque *curr, *next;
register struct ique *icurr, *inext;
int sema, owner;
/* optimization. */
if((gqueue == (struct cque *)NULL) && (iqueue == (struct ique *)NULL)) {
return;
}
/* command queue. */
curr = gqueue;
while(count && (curr != (struct cque *)NULL)) {
if((curr->when >= 0) && (curr->when <= mudstat.now)) { /* run it */
/* if it's went HALT or no longer exists, just drain it. */
if(!isHALT(curr->player) && exists_object(curr->player))
handle_cmds(curr->player, curr->cause, curr->cmd, curr->eargc,
curr->eargv);
/* update semaphore count */
if(curr->obj != -1) {
if((get_int_elt(curr->obj, SEMAPHORES, &sema) == -1)
|| (set_int_elt(curr->obj, SEMAPHORES, --sema) == -1)) {
logfile(LOG_ERROR,
"queue_run: failed to update semaphore count on #%d\n",
curr->obj);
}
}
/* remove it. */
if(curr == gqueue) {
if(curr->next == (struct cque *)NULL) { /* only thing here. */
gqueue = (struct cque *)NULL;
next = (struct cque *)NULL;
} else {
(curr->next)->prev = curr->prev;
gqueue = curr->next;
next = curr->next;
}
} else {
if(curr->next == (struct cque *)NULL) { /* last thing here. */
(curr->prev)->next = (struct cque *)NULL;
gqueue->prev = curr->prev;
next = (struct cque *)NULL;
} else {
(curr->next)->prev = curr->prev;
(curr->prev)->next = curr->next;
next = curr->next;
}
}
ty_free((VOID *)curr->cmd);
free_argv(curr->eargc, curr->eargv);
ty_free((VOID *)curr->eargv);
ty_free((VOID *)curr);
count--;
curr = next;
} else
curr = curr->next;
}
/* iterative queue. */
icurr = iqueue;
while(count && (icurr != (struct ique *)NULL)) {
/* if it's went HALT, or no longer exists, just drain it. */
if(!isHALT(icurr->player) && exists_object(icurr->player)) {
/* set the variable. */
if(icurr->var != (char *)NULL) {
if(get_int_elt(icurr->player, OWNER, &owner) == -1) {
logfile(LOG_ERROR, "queue_run: couldn't get owner of #%d.\n",
icurr->player);
break;
}
if(icurr->val != (char *)NULL) {
var_set(owner, icurr->var, icurr->val);
} else {
var_delete(owner, icurr->var);
}
}
/* do the command. */
if(icurr->cmd != (char *)NULL) {
handle_cmds(icurr->player, icurr->cause, icurr->cmd, icurr->eargc,
icurr->eargv);
}
}
if(icurr == iqueue) { /* only thing here. */
if(icurr->next == (struct ique *)NULL) {
iqueue = (struct ique *)NULL;
inext = (struct ique *)NULL;
} else {
(icurr->next)->prev = icurr->prev;
iqueue = icurr->next;
inext = icurr->next;
}
} else {
if(icurr->next == (struct ique *)NULL) { /* last thing here. */
(icurr->prev)->next = (struct ique *)NULL;
iqueue->prev = icurr->prev;
inext = (struct ique *)NULL;
} else {
(icurr->next)->prev = icurr->prev;
(icurr->prev)->next = icurr->next;
inext = icurr->next;
}
}
ty_free((VOID *)icurr->var);
ty_free((VOID *)icurr->val);
ty_free((VOID *)icurr->cmd);
free_argv(icurr->eargc, icurr->eargv);
ty_free((VOID *)icurr->eargv);
ty_free((VOID *)icurr);
count--;
icurr = inext;
}
}
/* run 'semaphores' off the queue. */
VOID do_notify(player, cause, switches, argone, argtwo)
int player, cause, switches;
char *argone, *argtwo;
{
int obj, count, ocount, ran, sema;
register struct cque *curr, *next;
char *ptr;
if((argone == (char *)NULL) || (argone[0] == '\0')) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Notify what?", NOT_QUIET);
return;
}
if((argtwo == (char *)NULL) || (argtwo[0] == '\0')) {
count = 1;
ocount = 1;
} else {
count = (int)strtol(argtwo, &ptr, 10);
if(ptr == argtwo) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "I don't understand that count.",
NOT_QUIET);
return;
}
if(count == 0) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Nothing to do.", NOT_QUIET);
return;
}
ocount = count; /* save a copy */
}
obj = resolve_object(player, cause, argone,
(!(switches & CMD_QUIET) ? RSLV_EXITS|RSLV_NOISY
: RSLV_EXITS));
if(obj == -1)
return;
curr = gqueue;
ran = 0;
while(((switches & NOTIFY_ALL) || count) && (curr != (struct cque *)NULL)) {
if(curr->obj == obj) { /* run */
/* if it's went HALT, or no longer exists, just drain it. */
if(!(switches & NOTIFY_DRAIN) && !isHALT(curr->player)
&& exists_object(curr->player)) {
handle_cmds(curr->player, curr->cause, curr->cmd, curr->eargc,
curr->eargv);
ran++;
}
/* remove it. */
if(curr == gqueue) {
if(curr->next == (struct cque *)NULL) { /* only thing here. */
gqueue = (struct cque *)NULL;
next = (struct cque *)NULL;
} else {
curr->next->prev = curr->prev;
gqueue = curr->next;
next = curr->next;
}
} else {
if(curr->next == (struct cque *)NULL) { /* last thing here. */
curr->prev->next = (struct cque *)NULL;
gqueue->prev = curr->prev;
next = (struct cque *)NULL;
} else {
curr->next->prev = curr->prev;
curr->prev->next = curr->next;
next = curr->next;
}
}
ty_free((VOID *)curr->cmd);
free_argv(curr->eargc, curr->eargv);
ty_free((VOID *)curr->eargv);
ty_free((VOID *)curr);
count--;
curr = next;
} else
curr = curr->next;
}
if((ran == 0) && !(switches & NOTIFY_DRAIN) && !(switches & NOTIFY_ALL)) {
/* fix up the semaphore count, this was a 'future' notify */
ran = ocount;
}
/* update semaphore count */
if(get_int_elt(obj, SEMAPHORES, &sema) == -1) {
notify_bad(player);
return;
}
sema = (switches & NOTIFY_DRAIN) ? 0 : sema - ran;
if(set_int_elt(obj, SEMAPHORES, sema) == -1) {
notify_bad(player);
return;
}
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Notified.", NOT_QUIET);
}
/* queue related command handlers. */
VOID do_halt(player, cause, switches, arg)
int player, cause, switches;
char *arg;
{
int victim;
char buff[MEDBUFFSIZ], *name;
register struct cque *curr, *next;
register struct ique *icurr, *inext;
if(switches & HALT_ALL) { /* expunge the queue(s). */
if(!(switches & CMD_QUIET)) {
int wflags[FLAGS_LEN];
bzero((VOID *)wflags, sizeof(wflags));
if(get_str_elt(player, NAME, &name) == -1)
name = "???";
snprintf(buff, sizeof(buff), "System halted by %s.", name);
tcp_wall(wflags, buff, -1);
}
/* poof */
for(curr = gqueue; curr != (struct cque *)NULL; curr = next) {
next = curr->next;
ty_free((VOID *)curr->cmd);
free_argv(curr->eargc, curr->eargv);
ty_free((VOID *)curr->eargv);
ty_free((VOID *)curr);
}
gqueue = (struct cque *)NULL;
for(icurr = iqueue; icurr != (struct ique *)NULL; icurr = inext) {
inext = icurr->next;
ty_free((VOID *)icurr->var);
ty_free((VOID *)icurr->val);
ty_free((VOID *)icurr->cmd);
free_argv(icurr->eargc, icurr->eargv);
ty_free((VOID *)icurr->eargv);
ty_free((VOID *)icurr);
}
iqueue = (struct ique *)NULL;
} else {
/* we just do a flag set, yawn. */
victim = resolve_object(player, cause, arg,
(!(switches & CMD_QUIET) ? RSLV_NOISY|RSLV_EXITS
: RSLV_EXITS));
if(victim == -1)
return;
if(!controls(player, cause, victim)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if(setHALT(victim) == -1) {
notify_bad(player);
return;
}
}
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Halted.", NOT_QUIET);
}
VOID do_semaphore(player, cause, switches, argone, argtwo)
int player, cause, switches;
char *argone, *argtwo;
{
int delay, obj, sema;
char *ptr, *nptr;
if((argone == (char *)NULL) || (argone[0] == '\0')
|| (argtwo == (char *)NULL) || (argtwo[0] == '\0')) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You must specify an object and a command.", NOT_QUIET);
return;
}
for(ptr = argone; *ptr && (*ptr != '/'); ptr++);
if(*ptr == '/') {
*ptr++ = '\0';
delay = (int)strtol(ptr, &nptr, 10);
if(nptr == ptr) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You must specify delay by number.", NOT_QUIET);
return;
}
} else
delay = -1;
obj = resolve_object(player, cause, argone,
(!(switches & CMD_QUIET) ? RSLV_NOISY|RSLV_EXITS
: RSLV_EXITS));
if(obj == -1)
return;
if(!controls(player, cause, obj) && !isLINK_OK(obj)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if(get_int_elt(obj, SEMAPHORES, &sema) == -1) {
notify_bad(player);
return;
}
if(sema < 0) {
/* fake out the queue */
queue_add(player, cause, 1, -1, argtwo, 0, (char **)NULL);
} else {
queue_add(player, cause, delay, obj, argtwo, 0, (char **)NULL);
}
sema++;
if(set_int_elt(obj, SEMAPHORES, sema) == -1) {
notify_bad(player);
return;
}
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Queued.", NOT_QUIET);
}
VOID do_wait(player, cause, switches, argone, argtwo)
int player, cause, switches;
char *argone, *argtwo;
{
int obj, owner;
time_t delay;
char *ptr;
if((argone == (char *)NULL) || (argone[0] == '\0')
|| (argtwo == (char *)NULL) || (argtwo[0] == '\0')) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You must specify a delay and a command.", NOT_QUIET);
return;
}
delay = (int)strtol(argone, &ptr, 10);
if(!isdigit(argone[0])) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You must specify delay by number.", NOT_QUIET);
return;
}
parse_time(argone, &delay);
if(*ptr == '/') { /* optional object. */
ptr++;
obj = resolve_object(player, cause, ptr,
(!(switches & CMD_QUIET) ? RSLV_NOISY|RSLV_EXITS
: RSLV_EXITS));
if(obj == -1)
return;
if(!controls(player, cause, obj)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if(!isGOD(player) && isGOD(obj)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if(get_int_elt(player, OWNER, &owner) == -1) {
notify_bad(player);
return;
}
if((obj == owner) && !isINHERIT(player) && !isINHERIT(owner)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
/* Swab the cause, just like @force. */
queue_add(obj, obj, (int)delay, -1, argtwo, 0, (char **)NULL);
} else
queue_add(player, cause, (int)delay, -1, argtwo, 0, (char **)NULL);
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Queued.", NOT_QUIET);
}
VOID do_ps(player, cause, switches, arg)
int player, cause, switches;
char *arg;
{
int searchfor, powner, cowner;
register struct cque *curr;
char buff[MEDBUFFSIZ];
if(switches & PS_ALL) {
searchfor = -1;
} else {
if((arg == (char *)NULL) || (arg[0] == '\0')) {
searchfor = player;
} else {
searchfor = resolve_object(player, cause, arg,
(!(switches & CMD_QUIET)
? RSLV_NOISY|RSLV_EXITS : RSLV_EXITS));
if(searchfor == -1)
return;
}
}
if((searchfor != -1) && !controls(player, cause, searchfor)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if((switches & PS_OWNED)
&& (get_int_elt(searchfor, OWNER, &searchfor) == -1)) {
notify_bad(player);
return;
}
/* dump the appropiate queue. */
notify_player(player, cause, player, "Command Queue:", 0);
if((searchfor != -1) && !(switches & PS_OWNED)) {
for(curr = gqueue; curr != (struct cque *)NULL; curr = curr->next) {
if(((switches & PS_CAUSE) && (curr->cause == searchfor))
|| (!(switches & PS_CAUSE) && (curr->player == searchfor))) {
snprintf(buff, sizeof(buff), "%s[->#%d]: ",
display_name(player, cause, curr->player), curr->cause);
strncat(buff, curr->cmd, sizeof(buff) - strlen(buff) - 1);
buff[MEDBUFFSIZ-1] = '\0';
notify_player(player, cause, player, buff, 0);
}
}
} else {
for(curr = gqueue; curr != (struct cque *)NULL; curr = curr->next) {
if((get_int_elt(curr->cause, OWNER, &cowner) == -1)
|| (get_int_elt(curr->player, OWNER, &powner) == -1))
continue;
if((searchfor == -1)
|| ((switches & PS_CAUSE) && (cowner == searchfor))
|| (!(switches & PS_CAUSE) && (powner == searchfor))) {
snprintf(buff, sizeof(buff), "%s[->#%d]: ",
display_name(player, cause, curr->player), curr->cause);
strncat(buff, curr->cmd, sizeof(buff) - strlen(buff) - 1);
buff[MEDBUFFSIZ - 1] = '\0';
notify_player(player, cause, player, buff, 0);
}
}
}
notify_player(player, cause, player, "***End of list***", 0);
}
VOID do_force(player, cause, switches, argone, argtwo)
int player, cause, switches;
char *argone, *argtwo;
{
int obj, owner;
if ((argone == (char *)NULL) || (argone[0] == '\0')
|| (argtwo == (char *)NULL) || (argtwo[0] == '\0')) {
notify_player(player, cause, player, "Force who to do what?", NOT_QUIET);
return;
}
obj = resolve_object(player, cause, argone,
(!(switches & CMD_QUIET) ? RSLV_NOISY : 0));
if(obj == -1)
return;
if (!controls(player, cause, obj)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if (isGOD(obj) && !isGOD(player)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You can't force God to do anything!", NOT_QUIET);
return;
}
/* You can't force your owner unless you're set INHERIT. */
if(get_int_elt(player, OWNER, &owner) == -1) {
notify_bad(player);
return;
}
if((owner == obj) && !isINHERIT(player) && !isINHERIT(owner)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if(isROBOT(obj)) { /* deliver the TinyMUD message only to robots. */
char *name, buf[MEDBUFFSIZ];
if(get_str_elt(player, NAME, &name) == -1)
name = "???";
snprintf(buf, sizeof(buf), "You sense that %s is forcing you to %s",
name, argtwo);
notify_player(obj, cause, player, buf, NOT_QUIET);
}
/* As per MUSH, this command resets the cause. */
handle_cmds(obj, obj, argtwo, 0, (char **)NULL);
if(!(switches & CMD_QUIET) && !isQUIET(obj))
notify_player(player, cause, player, "Ok.", NOT_QUIET);
}
VOID do_trigger(player, cause, switches, argc, argv)
int player, cause, switches, argc;
char *argv[];
{
int obj, aflags, asource, eargc;
char *atr, **eargv;
if(argc < 2) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Trigger what?", NOT_QUIET);
return;
}
obj = resolve_object(player, cause, argv[0],
(!(switches & CMD_QUIET) ? RSLV_NOISY|RSLV_EXITS
: RSLV_EXITS));
if(obj == -1)
return;
if(!controls(player, cause, obj)) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Permission denied.", NOT_QUIET);
return;
}
if(attr_get_parent(obj, argv[1], &atr, &aflags, &asource) == -1) {
notify_bad(player);
return;
}
if(atr == (char *)NULL) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "No such attribute.", NOT_QUIET);
return;
}
/* queue it up. */
argc -= 2;
argv += 2;
if(argc > 0) {
eargv = (char **)ty_malloc(sizeof(char *) * argc, "do_trigger");
for(eargc = 0; eargc < argc; eargc++) {
eargv[eargc] = ty_strdup(argv[eargc], "do_trigger");
}
} else {
eargc = 0;
eargv = (char **)NULL;
}
queue_add(obj, player, 1, -1, atr, eargc, eargv);
if(!(switches & CMD_QUIET))
notify_player(player, cause, player, "Triggered.", NOT_QUIET);
}
/* iterate over a list. */
VOID do_foreach(player, cause, switches, argone, argtwo)
int player, cause, switches;
char *argone, *argtwo;
{
char *ptr, *var, *lptr, *val;
if((argone == (char *)NULL) || (argone[0] == '\0')
|| (argtwo == (char *)NULL) || (argtwo[0] == '\0')) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You can't foreach without a list.", NOT_QUIET);
return;
}
argone = parse_slash(argone, &var);
if(var == (char *)NULL) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You must specify a variable name.", NOT_QUIET);
return;
}
if(argone[0] == '\0') {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"You must specify a list.", NOT_QUIET);
return;
}
/* the command parser doesn't parse this! */
if(!(switches & ARG_FEXEC))
lptr = exec(player, cause, player, argone, 0, 0, (char **)NULL);
else
lptr = argone;
ptr = (char *)NULL;
while((val = slist_next(lptr, &ptr)) != (char *)NULL)
queue_iadd(player, cause, var, val, argtwo, 0, (char **)NULL);
if(!(switches & ARG_FEXEC))
ty_free((VOID *)lptr);
}
VOID do_case(player, cause, switches, argc, argv)
int player, cause, switches, argc;
char *argv[];
{
register int idx = 1;
register int done = 0;
register int top = argc - 1;
char *lptr;
if(argc < 3) {
if(!(switches & CMD_QUIET))
notify_player(player, cause, player,
"How can you case on that?", NOT_QUIET);
return;
}
/* the command parser doesn't parse this! */
if(!(switches & ARG_FEXEC))
lptr = exec(player, cause, player, argv[0], 0, 0, (char **)NULL);
else
lptr = argv[0];
while(1) {
if((idx == top) && !done) { /* default */
queue_add(player, cause, 1, -1, argv[idx], 0, (char **)NULL);
break;
} else if(idx >= top) /* simply done */
break;
if(quick_wild(argv[idx], lptr)) {
/* queue this up */
if(idx < top) {
queue_add(player, cause, 1, -1, argv[idx+1], 0, (char **)NULL);
done++;
}
if(switches & CASE_FIRST) /* all done */
break;
}
idx += 2;
}
if(!(switches & ARG_FEXEC))
ty_free((VOID *)lptr);
}