#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);
}