dmuck0.15-beta/docs/muf/
dmuck0.15-beta/game/
dmuck0.15-beta/game/logs/
dmuck0.15-beta/game/muf/
dmuck0.15-beta/game/muf/text/
#include "copyright.h"
#include "config.h"

#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/times.h>

#include "db.h"
#include "params.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#include "mush.h"

/* declarations */
static char *dumpfile = 0, buf[BUFFER_LEN];
static int alarm_PANIC = 0;
static int last_dump = 0;

#ifdef HAVE_DRAND48 
void srand48(long);
#endif

#ifdef MUSH
dbref speaker = NOTHING;
#endif

/* funct (player, a, b, line) */
/* where the command line is "command a = b" */
#ifdef MUSH
typedef struct
{
  char *name;
  void (*function)(dbref, char *, char *, char *);
  int flag1,
      flag2,
      flag3;
} game_command;
#else
typedef struct
{
  char *name;
  void (*function)(dbref, char *, char *, char *);
  int flag;
} game_command;
#endif

void time_keeper(void);
void fork_and_dump(void);
void dump_database(void);
void clear_args(char *one, char *two, char *three);

/* more hacks, let them dump a lachesis file... */
static int dump_lachesis = 0;

void do_dump(__DO_PROTO)
{
  if(Wizard(player))
  {
    /* more hacks to dump a lachesis db */
    if (arg2 && !strcmp(arg2, "lachesis")) 
    {
      dump_lachesis = 1;
      notify(player, player, "Switching to Lachesis format.");
    }

    if (*arg1
#ifdef GOD_PRIV
        && God(player)
#endif /* GOD_PRIV */
        )
    {
      strcpy(dumpfile, arg1);
      sprintf(buf, "Dumping to file %s...", arg1);
      notify(player, player, buf);
    }
    last_dump = 0;
    notify(player, player, "Dumped the DB to disk.");
  }
  else notify(player, player, "Sorry, you are in a no dumping zone.");
}

void do_shutdown(__DO_PROTO)
{
  descriptor_data *d;
  if(FLAGS(player) &
#ifdef GOD_PRIV
    GOD)
#else /* !GOD_PRIV */
    WIZARD)
#endif /* GOD_PRIV */
  {
    sprintf (buf, "%s has issued a shutdown.", unparse_name(player));
    for(d = descriptor_list; d; d = d->next)
    {
      queue_string(d, buf);
      queue_write(d, "\r\n", 2);
    }
    log_status("SHUTDOWN: by %s\n", unparse_object(player, player));
    shutdown_flag = 1;
  }
  else
  {
    notify(player, player, "Your delusions of grandeur have been duly noted.");
    log_status("ILLEGAL SHUTDOWN: tried by %s\n",
      unparse_object(player, player));
  }
}

int epoch = 0;

static void dump_database_internal()
{
  char tpfile[248];
  FILE *f;
  descriptor_data *d;
  int i=0;
  
  sprintf(tpfile, "%s.#%d#", dumpfile, epoch - 1);
  (void) unlink(tpfile);               /* nuke our predecessor */
  
  sprintf(tpfile, "%s.#%d#", dumpfile, epoch);
  
#ifdef USE_DBP
  if(o_db_sync)
     dbp_sync();
  else
     dbp_flush();

   dbp_lock();
#endif

  if((f = fopen(tpfile, "w")) != NULL)
  {
    dump_lachesis ? db_write_lachesis(f) : db_write(f);
    dump_lachesis = 0;
    fclose(f);
    if(rename(tpfile, dumpfile) < 0) perror(tpfile);
  }
  else perror(tpfile);

#ifdef USE_DBP
   dbp_unlock();
#endif

  /* Write out the macros */
  sprintf(tpfile, "%s.#%d#", MACRO_FILE, epoch - 1);
  unlink(tpfile);
  
  sprintf(tpfile, "%s.#%d#", MACRO_FILE, epoch);
  
  if((f = fopen(tpfile, "w")) != NULL)
  {
    macrodump(macrotop, f);
    fclose(f);
    if (rename(tpfile, MACRO_FILE) < 0) perror(tpfile);
  }
  else perror(tpfile);
}

void panic(char *message)
{
  char panicfile[2048];
  FILE *f;
  int i;
  
  log_status("PANIC: %s\n", message);
  fprintf(stderr, "PANIC: %s\n", message);
  
  /* turn off signals */
  for(i = 0; i < NSIG; i++) signal(i, SIG_IGN);
  
  /* shut down interface */
  close_sockets();

#ifdef USE_DBP
  dbp_disable();
#endif
  
  /* dump panic file */
  sprintf(panicfile, "%s.PANIC", dumpfile);
  if((f = fopen(panicfile, "w")) == NULL)
  {
    perror("CANNOT OPEN PANIC FILE, YOU LOSE");
#ifdef NOCOREDUMP
    _exit(135);
#else /* !NOCOREDUMP */
    signal(SIGIOT, SIG_DFL);
    abort();
#endif /* NOCOREDUMP */
  }
  else
  {
#ifndef USE_DBP
    log_status("DUMPING: %s\n", panicfile);
    fprintf(stderr, "DUMPING: %s\n", panicfile);
    dump_lachesis ? db_write_lachesis(f) : db_write(f);
    dump_lachesis = 0;
    fclose(f);
    log_status("DUMPING: %s (done)\n", panicfile);
    fprintf(stderr, "DUMPING: %s (done)\n", panicfile);
#else  
    fclose(f);
    unlink(panicfile);
#endif  /*  USE_DBP */
#ifdef NOCOREDUMP
    _exit(136);
#else /* !NOCOREDUMP */
    signal(SIGIOT, SIG_DFL);
    abort();
#endif /* NOCOREDUMP */
  }
}

void dump_database()
{
  epoch++;
  
  log_status("DUMPING: %s.#%d#\n", dumpfile, epoch);
  dump_database_internal();
  log_status("DUMPING: %s.#%d# (done)\n", dumpfile, epoch);
}

void time_keeper()
{
  static int last_rwho = 0;
  static int last_setup = 0;
  static int current_time = 0;
  char uid[20];
  descriptor_data *d;

  if (!last_setup)
  {
    last_setup = 1;
    last_dump = time((long *)NULL);
    last_rwho = time((long *)NULL);
    autostart_frames();
  }

  current_time = time((long *)NULL);

  run_frames();

  if ((current_time - last_dump) > DUMP_INTERVAL || alarm_PANIC == 1)
  {
    alarm_PANIC = 0;
    fork_and_dump();
  }

if(o_rwho) {
  if ((current_time - last_rwho) > RWHO_INTERVAL)
  {
    rwhocli_pingalive();
/*  Active user profile */
    profile_users();
    for(d = descriptor_list; d; d = d->next)
    {
      if (d->connected && (d->player != NOTHING))
      {
        sprintf(uid, "%d", d->player);
        rwhocli_userlogin(uid, unparse_name(d->player), d->connected_at);
      }
    }
    last_rwho = time((long *)NULL);
  }
 }
}

void fork_and_dump()
{
  int child;
  epoch++;
  last_dump = time((long *)NULL);

  log_status("CHECKPOINTING: %s.#%d#\n", dumpfile, epoch);
#ifdef NOFORK
    dump_database_internal();
#else
 if(o_notify_wiz) {
  notify_wizards("Doing a forked DB dump.  Delays should be minimal.");
  }
#ifdef USE_VFORK
  child = vfork();
#else /* USE_VFORK */
  child = fork();
#endif /* USE_VFORK */
  if(child == 0)
  {
#ifdef USE_DBP
    dbp_disable();
#endif
    close(0);           /* get that file descriptor back */
    dump_database_internal();
    _exit(0);           /* !!! */
  }
#ifdef USE_DBP
  else if (child > 0)
  {
    /* flush the cache to disk */
    dbp_sync();
  }
#endif
  else if(child < 0) perror("fork_and_dump: fork()");
 
#endif
}

static RETSIGTYPE reaper()
{
#ifdef HAVE_UNION_WAIT
union wait stat;
#else
int	stat;
#endif

#ifdef HAVE_WAIT3
       while (wait3(&stat, WNOHANG, NULL) > 0);
#else
       wait(&stat);
#endif

#ifdef AIX370
  /* RESET the signal handler for AIX370 */
  /* This may not be the best place to put this. */
  signal(SIGCHLD, reaper);
  /* test modification by WOZ Jul 3 18:48 PDT 1991 */
#endif

  return ;
}

int init_game(char *infile, char *outfile)
{
  FILE *f;
  
  if ((f = fopen(MACRO_FILE, "r")) == NULL)
    log_status("INIT: Macro storage file %s is tweaked.\n", MACRO_FILE);
  else
  {
    macroload(f);
    fclose(f);
  }

  if((f = fopen(infile, "r")) == NULL) return -1;
  
  /* ok, read it in */
  log_status("LOADING: %s\n", infile);
  fprintf(stderr, "LOADING: %s\n", infile);
  if(db_read(f) < 0) return -1;
  log_status("LOADING: %s (done)\n", infile);
  fprintf(stderr, "LOADING: %s (done)\n", infile);
  fclose(f);

  /* everything ok */
  
  /* initialize random number generator */
  srandom(getpid());

#ifdef USE_DBP
  fprintf(stderr, "Calling dbp_enable()\n");
  if (dbp_enable(infile))
  {
    fprintf(stderr, "Error in enable.\n");
    exit(2);
  }
#endif


#ifdef HAVE_DRAND48 
  srand48(getpid());
#endif
  
  /* set up dumper */
  if(dumpfile) free(dumpfile);
  dumpfile = dup_string(outfile);
  signal(SIGCHLD, reaper);
  
  return 0;
}
#ifdef MUSH
game_command command_array[] =
{
  {"@aahear",      do_mush_prop_set, 2, 0, 0},
  {"@aclone",      do_mush_prop_set, 2, 0, 0},
  {"@aconnect",    do_mush_prop_set, 2, 0, 0},
  {"@action",      do_action, 1, 0, 0},
  {"@adeath",      do_mush_prop_set, 2, 0, 0},
  {"@adescribe",   do_mush_prop_set, 2, 0, 0},
  {"@adisconnect", do_mush_prop_set, 2, 0, 0},
  {"@adrop",       do_mush_prop_set, 2, 0, 0},
  {"@aefail",      do_mush_prop_set, 2, 0, 0},
  {"@aenter",      do_mush_prop_set, 2, 0, 0},
  {"@afailure",    do_mush_prop_set, 2, 0, 0},
  {"@ahear",       do_mush_prop_set, 2, 0, 0},
  {"@aleave",      do_mush_prop_set, 2, 0, 0},
  {"@amhear",      do_mush_prop_set, 2, 0, 0},
  {"@amove",       do_mush_prop_set, 2, 0, 0},
  {"@apayment",    do_mush_prop_set, 2, 0, 0},
  {"@asuccess",    do_mush_prop_set, 2, 0, 0},
  {"@atport",      do_mush_prop_set, 2, 0, 0},
  {"@attach",      do_attach, 1, 1, 0},
  {"@ause",        do_mush_prop_set, 2, 0, 0},
  {"@away",        do_mush_prop_set, 2, 0, 0},
  {"@backlinks",   do_backlinks, 1, 0, 0},
  {"@backlocks",   do_backlocks, 1, 0, 0},
  {"@boot",        do_boot, 1, 0, 0},
  {"@charges",     do_mush_prop_set, 2, 0, 0},
  {"@chown",       do_chown, 1, 1, 0},
  {"@comment",     do_mush_prop_set, 2, 0, 0},
  {"@contents",    do_contents, 1, 1, 0},
  {"@cost",        do_mush_prop_set, 2, 0, 0},
  {"@create",      do_create, 1, 1, 0},
  {"@death",       do_mush_prop_set, 2, 0, 0},
  {"@describe",    do_describe, 1, 0, 0},
  {"@destroy",     do_recycle, 1, 0, 0},
  {"@dig",         do_dig, 1, 1, 0},
  {"@drop",        do_drop_message, 1, 0, 0},
  {"@dump",        do_dump, 0, 0, 0},
  {"@ealias",      do_mush_prop_set, 2, 0, 0},
  {"@earthquake",  do_earthquake, 0, 0, 0},
  {"@edit",        do_edit, 0, 0, 0},
  {"@efail",       do_mush_prop_set, 2, 0, 0},
  {"@enter",       do_mush_prop_set, 2, 0, 0},
  {"@examine",     do_at_examine, 1, 0, 0},
  {"@exits",       do_exits, 1, 0, 0},
  {"@fail",        do_fail, 1, 0, 0},
  {"@filter",      do_mush_prop_set, 2, 0, 0},
  {"@find",        do_find, 1, 0, 0},
  {"@flags",       do_list_flags, 0, 0, 0},
#ifdef USE_DBP
  {"@flush",       do_db_flush, 0, 0, 0},
#endif
  {"@force",       do_force, 1, 1, 0},
  {"@go",          do_go, 1, 0, 0},
  {"@haven",       do_mush_prop_set, 2, 0, 0},
  {"@idescribe",   do_mush_prop_set, 2, 0, 0},
  {"@idle",        do_mush_prop_set, 2, 0, 0},
  {"@infilter",    do_mush_prop_set, 2, 0, 0},
  {"@inprefix",    do_mush_prop_set, 2, 0, 0},
  {"@kill",        do_pidkill, 0, 0, 0},
  {"@lalias",      do_mush_prop_set, 2, 0, 0},
  {"@leave",       do_mush_prop_set, 2, 0, 0},
  {"@link",        do_link, 1, 1, 0},
  {"@list",        do_mlist, 0, 0, 0},
  {"@logins",      do_login, 0, 0, 0},
  {"@move",        do_mush_prop_set, 2, 0, 0},
  {"@mset",        do_mset, 1, 0, 0},
  {"@name",        do_name, 1, 0, 0},
  {"@newpassword", do_newpassword, 0, 0, 0},
  {"@odeath",      do_mush_prop_set, 2, 0, 0},
  {"@odescribe",   do_mush_prop_set, 2, 0, 0},
  {"@odrop",       do_odrop, 1, 0, 0},
  {"@oefail",      do_mush_prop_set, 2, 0, 0},
  {"@oenter",      do_mush_prop_set, 2, 0, 0},
  {"@ofail",       do_ofail, 1, 0, 0},
  {"@oleave",      do_mush_prop_set, 2, 0, 0},
  {"@omove",       do_mush_prop_set, 2, 0, 0},
  {"@opayment",    do_mush_prop_set, 2, 0, 0},
  {"@open",        do_open, 1, 1, 0},
  {"@osuccess",    do_osuccess, 1, 0, 0},
  {"@otport",      do_mush_prop_set, 2, 0, 0},
  {"@ouse",        do_mush_prop_set, 2, 0, 0},
  {"@owned",       do_owned, 1, 1, 0},
  {"@oxenter",     do_mush_prop_set, 2, 0, 0},
  {"@oxleave",     do_mush_prop_set, 2, 0, 0},
  {"@oxtport",     do_mush_prop_set, 2, 0, 0},
  {"@parameter",   do_parameter_set, 0, 0, 0},
  {"@password",    do_password, 0, 0, 0},
  {"@payment",     do_mush_prop_set, 2, 0, 0},
  {"@pcreate",     do_pcreate, 0, 0, 0},
  {"@permissions", do_perms, 1, 1, 0},
  {"@prefix",      do_mush_prop_set, 2, 0, 0},
  {"@program",     do_program, 0, 0, 0},
  {"@properties",  do_properties, 1, 1, 0},
  {"@ps",          do_ps, 0, 0, 0},
  {"@queue",       do_mush_prop_set, 2, 0, 0},
  {"@recycle",     do_recycle, 1, 0, 0},
  {"@reset",       do_reset, 0, 0, 0},
  {"@rquota",      do_mush_prop_set, 2, 0, 0},
  {"@runout",      do_mush_prop_set, 2, 0, 0},
  {"@semaphore",   do_mush_prop_set, 2, 0, 0},
  {"@set",         do_set, 1, 0, 0},
  {"@sex",         do_mush_prop_set, 2, 0, 0},
  {"@shutdown",    do_shutdown, 0, 0, 0},
  {"@startup",     do_mush_prop_set, 2, 0, 0},
  {"@stats",       do_stats, 1, 0, 0},
  {"@success",     do_success, 1, 0, 0},
  {"@suid",        do_player_setuid, 1, 0, 0},
#ifdef USE_DBP
  {"@synchronize", do_db_sync, 0, 0, 0},
#endif
#ifdef HOWARD
  {"@sys",         do_load, 0, 0, 0},
#endif
  {"@teleport",    do_teleport, 1, 1, 0},
  {"@toad",        do_toad, 0, 0, 0},
  {"@tport",       do_mush_prop_set, 2, 0, 0},
  {"@trace",       do_trace, 0, 0, 0},
  {"@trimdb",      do_trimdb, 0, 0, 0},
  {"@uncompile",   do_uncompile, 0, 0, 0},
  {"@unlink",      do_unlink, 1, 0, 0},
  {"@use",         do_mush_prop_set, 2, 0, 0},
  {"@version", do_version, 0, 0, 0},
  {"@wall",    do_wall, 0, 0, 1},
  {"drop",         do_drop, 1, 0, 0},
  {"examine",      do_examine, 1, 1, 0},
#ifdef HOWARD
  {"fortune",      do_fortune, 0, 0, 0},
#endif
  {"get",          do_get, 1, 0, 0},
  {"give",         do_give, 1, 1, 0},
  {"goto",         do_move, 0, 1, 0},
#ifndef HOWARD
  {"gripe",        do_gripe, 0, 0, 1},
#endif
  {"help",         do_help, 0},
  {"inventory",    do_inventory, 0, 0, 0},
  {"kill",         do_kill, 1, 1, 0},
  {"look",         do_look_at, 1, 0, 0},
  {"man",          do_man, 0, 0, 0},
  {"move",         do_move, 0, 0, 1},
  {"news",         do_news, 0, 0, 0},
  {"page",         do_page, 1, 1, 0},
  {"pose",         do_pose, 0, 0, 1},
  {"put",          do_drop, 1, 0, 0},
  {"read",         do_look_at, 1, 0, 0},
  {"rob",          do_rob, 1, 1, 0},
  {"say",          do_say, 0, 0, 1},
  {"score",        do_score, 0, 0, 0},
  {"take",         do_get, 1, 0, 0},
  {"throw",        do_drop, 1, 0, 0},
  {"whisper",      do_whisper, 1, 1, 0},
  {"xprops",       do_xqueue, 0, 0, 0},
  {"zprops",       do_prop_load, 1, 1, 0}
};
#else
game_command command_array[] =
{
  {"@action",      do_action, 0},
  {"@attach",      do_attach, 1},
  {"@backlinks",   do_backlinks, 1},
  {"@backlocks",   do_backlocks, 1},
  {"@boot",        do_boot, 1},
  {"@chown",       do_chown, 1},
  {"@contents",    do_contents, 1},
  {"@create",      do_create, 1},
  {"@describe",    do_describe, 0},
  {"@dig",         do_dig, 1},
  {"@drop",        do_drop_message, 1},
  {"@dump",        do_dump, 0},
  {"@earthquake",  do_earthquake, 0},
  {"@edit",        do_edit, 0},
  {"@examine",     do_at_examine, 1},
  {"@exits",       do_exits, 1},
  {"@fail",        do_fail, 0},
  {"@find",        do_find, 1},
  {"@flags",       do_list_flags, 0},
  {"@force",       do_force, 1},
  {"@go",          do_go, 1},
  {"@kill",        do_pidkill, 0},
  {"@link",        do_link, 1},
  {"@list",        do_mlist, 0},
  {"@lock",        do_lock, 0},
  {"@logins",      do_login, 0},
  {"@name",        do_name, 0},
  {"@newpassword", do_newpassword, 0},
  {"@odrop",       do_odrop, 0},
  {"@ofail",       do_ofail, 0},
  {"@open",        do_open, 1},
  {"@osuccess",    do_osuccess, 0},
  {"@owned",       do_owned, 1},
  {"@parameter",   do_parameter_set, 0},
  {"@password",    do_password, 0},
  {"@pcreate",     do_pcreate, 0},
  {"@permissions", do_perms, 1},
  {"@program",     do_program, 0},
  {"@properties",  do_properties, 1},
  {"@ps",          do_ps, 0},
  {"@recycle",     do_recycle, 1},
  {"@reset",       do_reset, 0},
  {"@set",         do_set, 0},
  {"@shutdown",    do_shutdown, 0},
  {"@stats",       do_stats, 1},
  {"@stuid",        do_player_setuid, 1},
  {"@success",     do_success, 0},
  {"@sys",         do_load, 0},
  {"@teleport",    do_teleport, 1},
  {"@toad",        do_toad, 1},
  {"@trace",       do_trace, 0},
  {"@trimdb",      do_trimdb, 0},
  {"@uncompile",   do_uncompile, 0},
  {"@unlink",      do_unlink, 1},
  {"@unlock",      do_unlock, 1},
  {"@user",        do_player_setuid, 1},
  {"@version",     do_version, 0},
  {"@wall",        do_wall, 1},
  {"drop",         do_drop, 1},
  {"examine",      do_examine, 1},
  {"fortune",      do_fortune, 0},
  {"get",          do_get, 1},
  {"give",         do_give, 1},
  {"goto",         do_move, 1},
  {"gripe",        do_gripe, 1},
  {"help",         do_help, 0},
  {"inventory",    do_inventory, 0},
  {"kill",         do_kill, 1},
  {"look",         do_look_at, 1},
  {"man",          do_man, 0},
  {"move",         do_move, 1},
  {"news",         do_news, 0},
  {"page",         do_page, 1},
  {"pose",         do_pose, 1},
  {"put",          do_drop, 1},
  {"read",         do_look_at, 1},
  {"rob",          do_rob, 1},
  {"say",          do_say, 1},
  {"score",        do_score, 0},
  {"take",         do_get, 1},
  {"throw",        do_drop, 1},
  {"whisper",      do_whisper, 1}
};
#endif

void process_command(dbref player, char *command, dbref cause)
{
  char *arg1, *arg2, *full_command, *p; 
  char *m1, *m2, *mfull;
  char pbuf[BUFSIZ], xbuf[BUFSIZ];
  char hold1[BUFFER_LEN], hold2[BUFFER_LEN], hold3[BUFFER_LEN];
  char mush_buffer[BUFSIZ +3];
  int command_num, i, count, flag=1;
  frame *fr;
  
  if (!command) abort();

  if(player < 0 || player >= db_top)
  {
    log_status("process_command: bad player %d\n", player);
    return;
  }

if(o_log_commands) {
  if (!(FLAGS(player) & INTERACTIVE))
    log_command("%s(%ld) in %s(%ld):%s %s\n", NAME(player), player,
      NAME(DBFETCH(player)->location),
      DBFETCH(player)->location,
      (FLAGS(player) & INTERACTIVE) ?
      " [interactive]" : " ", command);
 }
  
#ifdef MUSH
  /* Halted objects can't execute commands */
  if ((Typeof(player) != TYPE_PLAYER) && Halted(player)) {
    notify(OWNER(player), OWNER(player),
	   tprintf("Attempt to execute command by halted object #%ld", player));
    return;
  }

  /* Check for Verbose objects and notify */
  if (Typeof(player) != TYPE_PLAYER && Verbose(player))
    notify_nolisten(OWNER(player), tprintf("%s(#%ld)] %s", 
                   unparse_name(player), player, command));

  /* Make sure the location of the object is good */
  if (!GoodObject(Location(player)))
    notify(OWNER(player), OWNER(player),
	   tprintf("Invalid location on command execution: %s(#%d)",
		   unparse_name(player), player));
#endif
  
  /* Only players can go Interactive. */
  if (FLAGS(player) & INTERACTIVE) {
    if(Typeof(player) != TYPE_PLAYER) {
      notify(OWNER(player), OWNER(player), tprintf("%s is interactive!", 
             NAME(player)));
      log_status("%s(%ld) is INTERACTIVE\n", NAME(player), player);
      FLAGS(player) &= ~INTERACTIVE;
      DBDIRTY(player);
    } else
      interactive(player, command);
    return;
  }

#ifdef MUSH
   speaker = player;   /* MUSH listeners */
   strcpy(mush_buffer, command);
#endif

  /* eat leading whitespace */
  while(*command && isspace(*command)) command++;
  
  /* check for single-character commands */
  if ((*command == SAY_TOKEN) || (*command == SAY_TOKEN_TWO))
  {
    sprintf(pbuf, "say %s", command + 1);
    command = pbuf;
  }
  else if ((*command == POSE_TOKEN) || (*command == POSE_TOKEN_TWO))
  {
    sprintf(pbuf, "pose %s", command + 1);
    command = pbuf;
  }
#ifdef MUSH
  else if (*command == '&')
  {
    sprintf(pbuf, "@mset %s", command + 1);
    command = pbuf;
  }
#endif
  
  if ((can_move(player, command)) && ((*command != '!') || (!Wizard(player))))
  {
    /* command is an exact match for an exit */
    if (*command == '!') command++;
    do_move(player, "", "", command);
    *match_args = 0;
  }
  else
  {
    if (*command == '!') command++;
    if (*command == '.') *command = '@';
    full_command = strcpy(xbuf, command);
    for (; *full_command && !isspace(*full_command); full_command++);
    if (*full_command) full_command++;
    
    /* find arg1 -- move over command word */
    for(arg1 = command; *arg1 && !isspace(*arg1); arg1++);
    /* truncate command */
    if(*arg1) *arg1++ = '\0';
    
    /* move over spaces */
    while(*arg1 && isspace(*arg1)) arg1++;
    
    /* find end of arg1, start of arg2 */
    for(arg2 = arg1; *arg2 && *arg2 != ARG_DELIMITER; arg2++);
    
    /* truncate arg1 */
    for(p = arg2 - 1; p >= arg1 && isspace(*p); p--) *p = '\0';
    
    /* go past delimiter if present */
    if(*arg2) *arg2++ = '\0';
    while(*arg2 && isspace(*arg2)) arg2++;

    for (command_num = 0;
      (command_num < sizeof(command_array) / sizeof(game_command)) &&
      (stringn_compare(command, command_array[command_num].name,
      strlen(command)) > 0); command_num++);


    if ((command_num < sizeof(command_array) / sizeof(game_command)) &&
      (!stringn_compare(command, command_array[command_num].name,
      strlen(command))) &&
      (((command_num + 1 >= sizeof(command_array) / sizeof(game_command)) ||
      (stringn_compare(command, command_array[command_num + 1].name,
      strlen(command))))))
    {
#ifdef MUSH
      if(command_array[command_num].flag1 == 1)  {
         strcpy(hold1, arg1);
         m1 = exec(cause, hold1, player, EV_STRIP | EV_FCHECK);
       } else m1 = dup_it(arg1);

      if(command_array[command_num].flag2)  {
         strcpy(hold2, arg2);
         m2 = exec(cause, hold2, player, EV_STRIP | EV_FCHECK);
       } else m2 = dup_it(arg2);

      if(command_array[command_num].flag3)  {
         strcpy(hold3, full_command);
         mfull = exec(cause, hold3, player, EV_STRIP | EV_FCHECK);
       } else mfull = dup_it(full_command);

      if(command_array[command_num].flag1 == 2)  
         (*command_array[command_num].function)(player, m1, m2, 
           command_array[command_num].name);
      else
         (*command_array[command_num].function)(player, m1, m2, mfull);

         clear_args(m1, m2, mfull);
         return;
#else
      (*command_array[command_num].function)(player, arg1, arg2, full_command);
         return;
#endif
     }

#ifdef MUSH  /* Hook into the MUSH command parser */
      if(mush_parse(player, mush_buffer, cause)) return;
#endif /* MUSH */

 if(o_muffail) {
      i = DBFETCH(GLOBAL_ENVIRONMENT)->exits;
      DOLIST (i, i)
      {
        if (!strcmp(DBFETCH(i)->name, "do_fail") && (FLAGS(i) & WIZARD))
        {
          for (count = 0; count < DBFETCH(i)->sp.exit.ndest; count++)
          {
            if (Typeof(DBFETCH(i)->sp.exit.dest[count]) == TYPE_PROGRAM)
            {
              fr = new_frame(player, DBFETCH(i)->sp.exit.dest[count], i,
		DBFETCH(player)->location, 1);
	      run_frame(fr, 1);
	      if (fr && (fr->status != STATUS_SLEEP)) free_frame(fr);
              flag = 0;
            }
          }
        } 
      }
    }
       if(flag) notify(player, player, "Huh?  (Type \"help\" for help.)");

 if (o_log_huhs) {
      if(!controls(player, DBFETCH(player)->location))
        log_status("HUH from %s(%d) in %s(%d)[%s]: %s %s\n",
          NAME(player), player, NAME(DBFETCH(player)->location),
          DBFETCH(player)->location,
          NAME(OWNER(DBFETCH(player)->location)), command,
          full_command);
    }
  }
}

#ifdef MUSH
void clear_args(char *one, char *two, char *three)
{
   if(one) free(one);
   if(two) free(two);
   if(three) free(three);
}
#endif

void do_list_commands(__DO_PROTO)
{
  int i;
  char buff[BUFFER_LEN];
  char *bp;
  bp = buff;

    safe_str("Builtins:", buff, &bp);
    for (i = 0; i < sizeof(command_array) / sizeof(game_command); i++) {
    safe_chr(' ', buff, &bp);
    safe_str(command_array[i].name, buff, &bp);
  }
  *bp = '\0';

  notify(player, player, buff);
}