/* override.c
* code for overriding commands and functions
*/
#include "copyright.h"
#include "autoconf.h"
#include "externs.h"
#include "command.h"
#include "functions.h"
static int FDECL(contains, (char *, char *));
static void FDECL(ovr_list, (dbref, dbref, int));
/* split_token: Get next token from string as null-term string. String is
* destructively modified.
*/
static char *
split_token(sp, sep)
char **sp, sep;
{
char *str, *save;
save = str = *sp;
if (!str) {
*sp = NULL;
return NULL;
}
while (*str && (*str != sep))
str++;
if (*str) {
*str++ = '\0';
if (sep == ' ') {
while (*str == sep)
str++;
}
} else {
str = NULL;
}
*sp = str;
return save;
}
/* do_override: override a command or function
* Alloy [2-25-96]
*/
void
do_override(player, cause, key, arg1, arg2)
dbref player, cause;
int key;
char *arg1, *arg2;
{
CMDENT *cmd;
FUN *func;
char *what, *name, *atr, *buff, *t, *newbuff, *nbp, *sav;
dbref object;
int attr, abort = 0, clear = 0;
/* can't have local user functions yet */
if (key & OVR_FUNCTION) key |= OVR_GLOBAL;
/* set what and object correctly for the override type */
if (key & OVR_GLOBAL) {
if (!Good_obj(mudconf.master_room)) {
notify_quiet(player,
"You must enable the master room to use @override/global.");
return;
}
what = arg1;
object = mudconf.master_room;
} else {
if (!arg1 || !*arg1) {
notify_quiet(player, "Override where?");
return;
}
what = arg2;
init_match(player, arg1, TYPE_ZONE);
match_everything(0);
object = noisy_match_result();
if (!Good_obj(object)) {
return;
} else if (!isZone(object)) {
notify_quiet(player,
"You must specify a zone in which to override.");
return;
}
}
/* maybe they want to list */
if (!what || !*what) {
if (key & OVR_GLOBAL)
notify(player, "Overridden globally:");
else
notify(player, tprintf("Overridden in %s:",
unparse_object(player, object, 0)));
ovr_list(player, object, 0);
ovr_list(player, object, 1);
return;
}
/* no, so match the command or function */
if (*what == NOT_TOKEN) {
clear = 1;
what++;
}
for (t = what; *t; t++)
*t = ToLower(*t);
key &= ~OVR_GLOBAL;
if (key == OVR_CMD) {
attr = A_OVR_CMD;
cmd = (CMDENT *) hashfind(what, &mudstate.command_htab);
if (!cmd) {
notify_quiet(player, "No such command.");
return;
}
name = cmd->cmdname;
/* make sure they don't override @override! */
if (!string_compare(cmd->cmdname, "@override")) {
notify_quiet(player, "You can't override the @override command!");
return;
}
} else {
attr = A_OVR_FUNC;
func = (FUN *) hashfind(what, &mudstate.func_htab);
if (!func) {
notify_quiet(player, "No such function.");
return;
}
name = (char *) func->name;
}
/* now stick it in the attribute */
atr = atr_get_raw(object, attr);
sav = nbp = buff = alloc_lbuf("do_override.buff");
safe_str(atr, buff, &nbp);
nbp = newbuff = alloc_lbuf("do_override.newbuff");
if (!clear) {
while (t = split_token(&buff, ' ')) {
if (!string_compare(t, name)) abort = 1;
if (nbp != newbuff) safe_chr(' ', newbuff, &nbp);
safe_str(t, newbuff, &nbp);
}
if (nbp != newbuff) safe_chr(' ', newbuff, &nbp);
safe_str(name, newbuff, &nbp);
} else {
abort = 1;
while (t = split_token(&buff, ' ')) {
if (!string_compare(t, name)) {
abort = 0;
} else {
if (nbp != newbuff) safe_chr(' ', newbuff, &nbp);
safe_str(t, newbuff, &nbp);
}
}
}
free_lbuf(sav);
if (abort) {
notify_quiet(player,
tprintf("That has %s been overridden.", clear ? "not" : "already"));
return;
}
atr_add_raw(object, attr, newbuff);
free_lbuf(newbuff);
notify(player, clear ? "Overridden." : "Enabled.");
}
/* is_overridden: should this builtin command/function be ignored? */
int
is_overridden(player, cmd, type)
dbref player;
char *cmd;
int type;
{
char *atr, c[SBUF_SIZE], *p;
dbref loc;
strcpy(c, cmd);
for (p = c; *p; p++)
*p = ToLower(*p);
loc = Location(player);
if (Good_obj(loc) && Good_obj(Zone(loc))) {
atr = atr_get_raw(Zone(loc), type);
if (atr && *atr && contains(atr, c)) return 1;
}
loc = mudconf.master_room;
if (!Good_obj(loc)) return 0;
atr = atr_get_raw(loc, type);
if (!atr || !*atr) return 0;
return contains(atr, c);
}
/* contains: does str contain item? */
static int
contains(str, item)
char *str, *item;
{
char *buff, *t, *sav;
int count = 0;
if (!str || !*str) return 0;
t = sav = buff = alloc_lbuf("contains");
safe_str(str, buff, &t);
do {
t = split_token(&buff, ' ');
if (!string_compare(t, item)) count++;
} while (buff);
free_lbuf(sav);
return count;
}
/* ovr_list: list functions/commands that are overridden */
static void
ovr_list(player, loc, func)
dbref player, loc;
int func;
{
char *atr, *out, *p, *t;
p = out = alloc_lbuf("ovr_list.out");
safe_str(func ? " Functions: " : " Commands: ", out, &p);
atr = atr_get_raw(loc, func ? A_OVR_FUNC : A_OVR_CMD);
if (!atr || !*atr)
safe_str((char *) "(none)", out, &p);
else
safe_str(atr, out, &p);
notify(player, out);
free_lbuf(out);
}