AlloyMUSH-1.1/conf/
AlloyMUSH-1.1/misc/
AlloyMUSH-1.1/scripts/
AlloyMUSH-1.1/vms/
/* 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);
}