/* $Header: /belch_a/users/rearl/tinymuck/src/RCS/game.c,v 1.15 90/09/28 12:21:03 rearl Exp $ */
/*
* $Log: game.c,v $
* Revision 1.15 90/09/28 12:21:03 rearl
* Added logging of interactive player commands.
*
* Revision 1.14 90/09/16 04:42:11 rearl
* Preparation code added for disk-based MUCK.
*
* Revision 1.13 90/09/15 22:20:04 rearl
* Fixed non-GOD_PRIV problem.
*
* Revision 1.12 90/09/13 06:22:31 rearl
* Added optional argument to @dump for changing the dumpfile in emergencies.
*
* Revision 1.11 90/09/10 02:19:54 rearl
* Fixed a possible bug in database checkpointing, minimized
* command-line space-smashing.
*
* Revision 1.10 90/09/01 05:57:55 rearl
* Fixed bugs in macro dumpfile.
*
* Revision 1.9 90/08/27 03:24:52 rearl
* Disk-based MUF source code, added environment support code.
*
* Revision 1.8 90/08/11 04:00:20 rearl
* *** empty log message ***
*
* Revision 1.7 90/08/05 14:43:34 rearl
* One more silly bug fixed in the command handler.
*
* Revision 1.6 90/08/02 18:55:04 rearl
* Fixed some calls to logging functions.
*
* Revision 1.5 90/07/30 00:11:07 rearl
* Added @owned command.
*
* Revision 1.4 90/07/29 17:34:05 rearl
* Fixed bug in = once and for all, also some bugs hiding in the command
* processing switch.
*
* Revision 1.3 90/07/21 16:32:23 casie
* more log calls added
*
* Revision 1.2 90/07/21 01:43:51 casie
* added support for logging.
*
* Revision 1.1 90/07/19 23:03:33 casie
* Initial revision
*
*
*/
#include "copyright.h"
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>
#include "db.h"
#include "params.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#include "strings.h"
#include "patchlevel.h"
/* declarations */
static char *dumpfile = 0;
static int epoch = 0;
static int alarm_triggered = 0;
static int alarm_block = 0;
static void fork_and_dump(void);
void dump_database(void);
#include <sys/time.h>
void do_dump(dbref player, const char *newfile)
{
char buf[BUFFER_LEN];
if(Wizard(player)) {
alarm_triggered = 1;
if (*newfile
#ifdef GOD_PRIV
&& God(player)
#endif /* GOD_PRIV */
) {
strcpy(dumpfile, newfile);
sprintf(buf, "Dumping to file %s...", dumpfile);
} else {
sprintf(buf, "Dumping...");
}
notify(player, buf);
} else {
notify(player, "Permission denied.");
}
}
void do_shutdown(dbref player)
{
if(Wizard(player)) {
log_status("SHUTDOWN: by %s\n", unparse_object(player, player));
shutdown_flag = 1;
} else {
notify(player, "Your delusions of grandeur have been duly noted.");
log_status("ILLEGAL SHUTDOWN: tried by %s\n", unparse_object(player, player));
}
}
/* should be void, but it's defined as int */
static void alarm_handler(int x)
{
x = x; /* just so it dont complain */
alarm_triggered = 1;
if(!alarm_block) {
fork_and_dump();
}
}
static void dump_database_internal(void)
{
char tmpfile[2048];
FILE *f;
sprintf(tmpfile, "%s.#%d#", dumpfile, epoch - 1);
(void) unlink(tmpfile); /* nuke our predecessor */
sprintf(tmpfile, "%s.#%d#", dumpfile, epoch);
if((f = fopen(tmpfile, "w")) != NULL) {
db_write(f);
fclose(f);
if(rename(tmpfile, dumpfile) < 0) perror(tmpfile);
} else {
perror(tmpfile);
}
/* Write out the macros */
sprintf(tmpfile, "%s.#%d#", MACRO_FILE, epoch - 1);
(void) unlink(tmpfile);
sprintf(tmpfile, "%s.#%d#", MACRO_FILE, epoch);
if((f = fopen(tmpfile, "w")) != NULL) {
macrodump(macrotop, f);
fclose(f);
if (rename(tmpfile, MACRO_FILE) < 0) perror(tmpfile);
} else {
perror(tmpfile);
}
}
void panic(const 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 */
/* emergency_shutdown();*/
/* emergency_warn();*/ /* who cares... lets not tell'm. >:) */
/* dump panic file */
sprintf(panicfile, "%s.PANIC", dumpfile);
if((f = fopen(panicfile, "w")) == NULL) {
perror("CANNOT OPEN PANIC FILE, YOU LOSE");
#ifdef NOCOREDUMP
#else /* !NOCOREDUMP */
signal(SIGIOT, SIG_DFL);
#endif /* NOCOREDUMP */
} else {
log_status("DUMPING: %s\n", panicfile);
fprintf(stderr, "DUMPING: %s\n", panicfile);
db_write(f);
fclose(f);
log_status("DUMPING: %s (done)\n", panicfile);
fprintf(stderr, "DUMPING: %s (done)\n", panicfile);
#ifdef NOCOREDUMP
#else /* !NOCOREDUMP */
signal(SIGIOT, SIG_DFL);
#endif /* NOCOREDUMP */
}
execl("./restart", "restart", NULL, NULL); /* try and restart it... */
#ifdef NOCOREDUMP
_exit(136);
#else
signal(SIGIOT,SIG_DFL);
abort();
#endif
}
void dump_database(void)
{
epoch++;
log_status("DUMPING: %s.#%d#\n", dumpfile, epoch);
dump_database_internal();
log_status("DUMPING: %s.#%d# (done)\n", dumpfile, epoch);
}
static void fork_and_dump(void)
{
int child;
epoch++;
log_status("CHECKPOINTING: %s.#%d#\n", dumpfile, epoch);
#ifdef USE_VFORK
child = vfork();
#else /* USE_VFORK */
child = fork();
#endif /* USE_VFORK */
if(child == 0) {
/* in the child */
close(0); /* get that file descriptor back */
dump_database_internal();
_exit(0); /* !!! */
} else if(child < 0) {
perror("fork_and_dump: fork()");
}
/* in the parent */
/* reset alarm */
alarm_triggered = 0;
alarm(DUMP_INTERVAL);
}
dbref global_trigger;
static void reaper(int x)
{
union wait stat;
x = x; /* so it dont complain */
while(wait3(&stat, WNOHANG, 0) > 0);
}
time_t startup_time;
int init_game(const char *infile, const 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((char *)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);
/* everything ok */
fclose(f);
/* initialize random number generator */
srandom(getpid());
/* set up dumper */
if(dumpfile) free((void *) dumpfile);
dumpfile = alloc_string(outfile);
signal(SIGALRM, (void *) alarm_handler);
signal(SIGHUP, (void *) alarm_handler);
signal(SIGCHLD, (void *) reaper);
alarm_triggered = 0;
alarm(DUMP_INTERVAL);
/* set up uptime */
return 0;
}
/* use this only in process_command */
#define Matched(string) { if(!string_prefix((string), command)) goto bad; }
void process_command(dbref player, const char *commie, dbref cause,
int no_prog)
{
char *arg1;
char *arg2;
char *full_command;
char *p; /* utility */
char *command;
char commbuff[BUFFER_LEN];
char pbuf[BUFSIZ];
char xbuf[BUFSIZ];
{
int a;
for(a = 0; a < 10; a++)
wptr[a] = NULL;
}
if (commie == 0) abort();
strcpy(commbuff, commie); command = commbuff;
global_trigger = player;
global_cause = cause;
/* robustify player */
if(player < 0 || player >= db_top ||
((Typeof(player) != TYPE_PLAYER)&&(Typeof(player)!=TYPE_THING))) {
log_status("process_command: bad player %d\n", player);
return;
}
if(Typeof(player) == TYPE_EXIT || Typeof(player) == TYPE_ROOM)
player = OWNER(player);
#ifdef LOG_COMMANDS
if (!(FLAGS(player) & INTERACTIVE) || DBFETCH(player)->run)
log_command("%s(%d) in %s(%d):%s %s\n", NAME(player), (int) player,
NAME(DBFETCH(player)->location),
(int) DBFETCH(player)->location,
(FLAGS(player) & INTERACTIVE) ?
" [interactive]" : " ", command);
else
log_command("%s(%d) in %s(%d):[editor] %s\n",NAME(player),(int) player,
NAME(DBFETCH(player)->curr_prog),
(int) DBFETCH(player)->curr_prog,
command);
#endif /* LOG_COMMANDS */
if(FLAGS(player)&PUPPET && Typeof(player) != TYPE_PLAYER) {
sprintf(pbuf, "%s>> %s", NAME(player), command);
notify_internal(DBFETCH(player)->owner, pbuf);
}
/* block dump to prevent db inconsistencies from showing up */
alarm_block = 1;
if (FLAGS(player) & INTERACTIVE && !no_prog) {
interactive(player, command);
return;
}
/* eat leading whitespace */
while(*command && isspace(*command)) command++;
/* check for single-character commands */
if(*command == SAY_TOKEN) {
sprintf(pbuf,"say %s", command+1);
command = &pbuf[0];
} else if((*command == POSE_TOKEN) || *command == ';') {
sprintf(pbuf, "pose %s", command+1);
command = &pbuf[0];
} else if(*command == '#') {
sprintf(pbuf,"@force %s", command);
command = &pbuf[0];
}
if(can_move(player, command)) {
/* command is an exact match for an exit */
do_move(player, command);
*match_args = 0;
} else {
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++;
arg1 = check_arg(arg1, player, cause);
arg2 = check_arg(arg2, player, cause);
switch(command[0]) {
case '@':
switch(command[1]) {
case '@':
Matched("@@"); /* does nothing, useful for commenting */
break;
case 'a':
case 'A':
/* @action, @attach */
switch(command[2]) {
case 'a':
case 'A':
Matched("@aahear");
do_attr(player,"Aahear",arg1,arg2);
break;
case 'c':
case 'C':
switch(command[3]) {
case 'o':
case 'O':
Matched("@aconnect");
do_attr(player, "Aconnect", arg1, arg2);
break;
case 't':
case 'T':
Matched("@action");
do_action(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'd':
case 'D':
switch(command[3]) {
case 'e':
case 'E':
Matched("@adesc");
do_attr(player, "Adesc", arg1, arg2);
break;
case 'r':
case 'R':
Matched("@adrop");
do_attr(player,"Adrop", arg1, arg2);
break;
default:
goto bad;
}
break;
case 'E':
case 'e':
Matched("@aenter");
do_attr(player, "Aenter", arg1, arg2);
break;
case 'f':
case 'F':
Matched("@afail");
do_attr(player, "Afail", arg1, arg2);
break;
case 'h':
case 'H':
Matched("@ahear");
do_attr(player, "Ahear", arg1, arg2);
break;
case 'k':
case 'K':
Matched("@akill");
do_attr(player, "Akill", arg1, arg2);
break;
case 'l':
case 'L':
Matched("@aleave");
do_attr(player, "Aleave", arg1, arg2);
break;
case 'm':
case 'M':
Matched("@amhear");
do_attr(player, "Amhear", arg1, arg2);
break;
case 'p':
case 'P':
Matched("@apay");
do_attr(player, "Apay", arg1, arg2);
break;
case 's':
case 'S':
Matched("@asucc");
do_attr(player, "Asucc", arg1, arg2);
break;
case 't':
case 'T':
Matched("@attach");
do_attach(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'b':
case 'B':
Matched("@boot");
do_boot(player, arg1);
break;
case 'c':
case 'C':
/* chown, create */
switch(command[2]) {
case 'h':
case 'H':
Matched("@chown");
do_chown(player, arg1, arg2);
break;
case 'o':
case 'O':
Matched("@cost");
do_attr(player, "Cost", arg1, arg2);
break;
case 'r':
case 'R':
Matched("@create");
do_create(player, arg1, atoi(arg2));
break;
default:
goto bad;
}
break;
case 'd':
case 'D':
/* describe, dig, or dump */
switch(command[2]) {
case 'b':
case 'B':
do_dboot(player, arg1);
break;
case 'e':
case 'E':
Matched("@describe");
do_attr(player, "Desc", arg1, arg2);
break;
case 'i':
case 'I':
Matched("@dig");
do_dig(player, arg1, arg2);
break;
case 'r':
case 'R':
Matched("@drop");
do_attr(player, "Drop", arg1, arg2);
break;
case 'u':
case 'U':
Matched("@dump");
do_dump(player, full_command);
break;
default:
goto bad;
}
break;
case 'e':
case 'E':
switch(command[2]) {
case 'd':
case 'D':
Matched("@edit");
do_edit(player, arg1);
break;
case 'n':
case 'N':
Matched("@enter");
do_attr(player, "Enter", arg1, arg2);
break;
default: goto bad;
} break;
case 'f':
case 'F':
/* fail, field, find, or force */
switch(command[2]) {
case 'a':
case 'A':
Matched("@fail");
do_attr(player, "Fail", arg1, arg2);
break;
case 'i':
case 'I':
switch(command[3]) {
case 'e':
case 'E':
Matched("@field");
do_field(player, arg1, arg2, cause);
break;
case 'n':
case 'N':
Matched("@find");
do_find(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
Matched("@force");
do_force(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
Matched("@halt");
do_halt(player, arg1);
break;
case 'i':
case 'I':
Matched("@idesc");
do_attr(player, "Idesc", arg1, arg2);
break;
case 'k':
case 'K':
Matched("@kill");
do_attr(player, "Kill", arg1, arg2);
break;
case 'l':
case 'L':
/* lock or link */
switch(command[2]) {
case 'e':
case 'E':
Matched("@leave");
do_attr(player, "Leave", arg1, arg2);
break;
case 'i':
case 'I':
switch(command[3]) {
case 'n':
case 'N':
Matched("@link");
do_link(player, arg1, arg2);
break;
case 's':
case 'S':
if(!string_compare(command,"@list")) {
Matched("@list");
match_and_list(player, arg1, arg2);
} else {
Matched("@listen");
do_attr(player, "Listen", arg1, arg2);
}
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
Matched("@lock");
do_lock(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'n':
case 'N':
/* @name or @newpassword */
switch(command[2]) {
case 'a':
case 'A':
Matched("@name");
do_name(player, arg1, arg2);
break;
case 'e':
case 'E':
if(strcmp(command, "@newpassword")) goto bad;
do_newpassword(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
switch(command[2]) {
case 'c':
case 'C':
Matched("@oconnect");
do_attr(player, "Oconnect", arg1, arg2);
break;
case 'd':
case 'D':
switch(command[3]) {
case 'e':
case 'E':
Matched("@odesc");
do_attr(player, "Odesc", arg1, arg2);
break;
case 'i':
case 'I':
Matched("@odisconnect");
do_attr(player, "Odisconnect", arg1, arg2);
break;
case 'r':
case 'R':
Matched("@odrop");
do_attr(player, "Odrop", arg1, arg2);
break;
default:
goto bad;
}
break;
case 'e':
case 'E':
Matched("@oenter");
do_attr(player, "Oenter", arg1, arg2);
break;
case 'f':
case 'F':
Matched("@ofail");
do_attr(player, "Ofail", arg1, arg2);
break;
case 'k':
case 'K':
Matched("@okill");
do_attr(player, "Okill", arg1, arg2);
break;
case 'l':
case 'L':
Matched("@oleave");
do_attr(player, "Oleave", arg1, arg2);
break;
case 'p':
case 'P':
switch(command[3]) {
case 'e':
case 'E':
Matched("@open");
do_open(player, arg1, arg2);
break;
case 'a':
case 'A':
Matched("@opay");
do_attr(player, "Opay", arg1, arg2);
break;
default: goto bad;
}
break;
case 's':
case 'S':
Matched("@osuccess");
do_attr(player, "Osucc", arg1, arg2);
break;
case 'w':
case 'W':
Matched("@owned");
do_owned(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'p':
case 'P':
switch(command[2])
{
case 'a':
case 'A':
switch(command[3]) {
case 's':
case 'S':
Matched("@password");
do_password(player, arg1, arg2);
break;
case 'y':
Matched("@pay");
do_attr(player, "Pay", arg1, arg2);
break;
default: goto bad;
} break;
case 'c':
case 'C':
Matched("@pcreate");
do_pcreate(player, arg1, arg2);
break;
case 'r':
case 'R':
Matched("@prog");
do_prog(player, arg1);
break;
case 's':
case 'S':
Matched("@ps");
do_ps(player, arg1);
break;
default:
goto bad;
}
break;
case 'r':
case 'R':
switch(command[2]) {
#ifdef RECYCLE
case 'e':
case 'E':
Matched("@recycle");
do_recycle(player, arg1);
break;
#endif /* RECYCLE */
case 's':
case 'S':
if(strcmp(command, "@rst")) goto bad;
do_restart(player);
break;
default: goto bad;
}
break;
case 's':
case 'S':
/* set, shutdown, success */
switch(command[2]) {
case 'e':
case 'E':
switch(command[3]) {
case 't':
case 'T':
Matched("@set");
do_set(player, arg1, arg2);
break;
case 'x':
case 'X':
Matched("@sex");
do_attr(player, "Sex", arg1, arg2);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
if(strcmp(command, "@shutdown")) goto bad;
do_shutdown(player);
break;
case 't':
case 'T':
switch(command[3]) {
case 'a':
case 'A':
switch(command[4]) {
case 't':
case 'T':
Matched("@stats");
do_stats(player, arg1);
break;
case 'r':
case 'R':
Matched("@startup");
do_attr(player, "Startup", arg1, arg2);
break;
default: goto bad;
} break;
default: goto bad;
} break;
case 'u':
case 'U':
Matched("@success");
do_attr(player, "Succ", arg1, arg2);
break;
case 'w':
case 'W':
switch(command[3]) {
case 'a':
case 'A':
Matched("@swap");
do_swap(player, arg1, arg2);
break;
case 'i':
case 'I':
Matched("@switch");
do_switch(player, arg1, arg2, cause);
break;
default:
goto bad;
}
break;
default:
goto bad;
}
break;
case 't':
case 'T':
switch(command[2]) {
case 'e':
case 'E':
Matched("@teleport");
do_teleport(player, arg1, arg2);
break;
case 'o':
case 'O':
if(strcmp(command, "@toad")) goto bad;
do_toad(player, arg1, arg2);
break;
case 'r':
case 'R':
switch(command[3]) {
case 'a':
case 'A':
Matched("@trace");
do_trace(player, arg1, atoi(arg2));
break;
case 'i':
case 'I':
Matched("@trigger");
do_trigger(player, arg1, arg2);
break;
default: goto bad;
}
break;
default:
goto bad;
}
break;
case 'u':
case 'U':
switch(command[2]) {
case 'n':
case 'N':
if(string_prefix(command, "@unli")) {
do_unlink(player, arg1);
} else if(string_prefix(command, "@unlo")) {
do_unlock(player, arg1);
} else {
goto bad;
}
break;
case 'p':
case 'P':
Matched("@uptime");
do_uptime(player);
break;
default: goto bad;
} break;
case 'v':
case 'V': /* v? fields */
if(command[3]) {
Matched("@version");
do_version(player);
}
else {
char buf[3];
if(tolower(command[2])<'a' || tolower(command[2])>'z')
goto bad;
strcpy(buf,"V?");
buf[1] = tolower(command[2]);
do_attr(player, buf, arg1, arg2);
}
break;
case 'w':
case 'W':
if(!strcmp(command, "@wall"))
do_wall(player, full_command);
else {
Matched("@wait");
do_wait(player,arg1,arg2);
}
break;
default:
goto bad;
}
break;
case 'd':
case 'D':
Matched("drop");
do_drop(player, arg1);
break;
case 'e':
case 'E':
switch(command[1]) {
case 'x':
case 'X':
Matched("examine");
do_examine(player, arg1);
break;
case 'n':
case 'N':
Matched("enter");
do_enter(player,arg1);
break;
default: goto bad;
} break;
case 'g':
case 'G':
/* get, give, go, or gripe */
switch(command[1]) {
case 'e':
case 'E':
Matched("get");
do_get(player, arg1);
break;
case 'i':
case 'I':
Matched("give");
do_give(player, arg1, atoi(arg2));
break;
case 'o':
case 'O':
Matched("goto");
do_move(player, arg1);
break;
case 'r':
case 'R':
Matched("gripe");
do_gripe(player, full_command);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
Matched("help");
do_help(player);
break;
case 'i':
case 'I':
Matched("inventory");
do_inventory(player);
break;
case 'k':
case 'K':
Matched("kill");
do_kill(player, arg1, atoi(arg2));
break;
case 'l':
case 'L':
switch(command[1]) {
case 'o':
case 'O':
case '\0': /* so just 'l' is look */
Matched("look");
do_look_at(player, arg1);
break;
case 'e':
case 'E':
Matched("leave");
do_leave(player);
break;
default: goto bad;
}
break;
case 'm':
case 'M':
if (string_prefix(command, "move")) {
do_move(player, arg1);
break;
} else {
if (string_compare(command, "man"))
goto bad;
do_man(player);
}
break;
case 'n':
case 'N':
/* news */
if(string_compare(command, "news")) goto bad;
do_news(player);
break;
case 'p':
case 'P':
switch(command[1]) {
case 'a':
case 'A':
Matched("page");
do_page(player, arg1, arg2);
break;
case 'o':
case 'O':
Matched("pose");
do_pose(player, full_command);
break;
case 'u':
case 'U':
Matched("put");
do_drop(player, arg1);
break;
default:
goto bad;
}
break;
case 'r':
case 'R':
Matched("read"); /* undocumented alias for look at */
do_look_at(player, arg1);
break;
case 's':
case 'S':
/* say, "score" */
switch(command[1]) {
case 'a':
case 'A':
Matched("say");
do_say(player, full_command);
break;
case 'c':
case 'C':
Matched("score");
do_score(player);
break;
default:
goto bad;
}
break;
case 't':
case 'T':
switch(command[1]) {
case 'a':
case 'A':
Matched("take");
do_get(player, arg1);
break;
case 'h':
case 'H':
Matched("throw");
do_drop(player, arg1);
break;
default:
goto bad;
}
break;
case 'w':
case 'W':
Matched("whisper");
do_whisper(player, arg1, arg2);
break;
default:
bad:
{
char bebuf[BUFFER_LEN];
if(*full_command)
sprintf(bebuf, "%s %s", command, full_command);
else
sprintf(bebuf, "%s", command);
if(!check_mushact(player, bebuf)) {
notify(player, "Huh? (Type \"help\" for help.)");
#ifdef LOG_FAILED_COMMANDS
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);
}
#endif /* LOG_FAILED_COMMANDS */
}
}
break;
}
if(arg1) free(arg1);
if(arg2) free(arg2); /* check_arg */
}
/* unblock alarms */
alarm_block = 0;
if(alarm_triggered) {
fork_and_dump();
}
}
#undef Matched
int do_act(dbref what, const char *command, dbref player)
{
int res = 0, loog;
const char *y;
static char x[4]= "v_\0";
if(Halted(what))
return 0;
for(x[1] = 'a'; x[1] <= 'z' && !res; x[1]++) {
if(y = get_attr(what, x)) { /* We can try this. */
if(*y == '$' && index(y, ':')) { /* yay. we really can try this. */
static char yy[BUFFER_LEN];
strcpy(yy, y + 1);
*index(yy, ':') ='\0';
if(wild_match(yy, command)) {
res++;
trigobj(what, 1 + index(yy, '\0'), player);
}
}
}
}
for(loog = 0; loog < 10; loog++)
wptr[loog] = NULL;
return res;
}
int check_mushact(dbref player, const char *command)
{
dbref first;
int res = 0;
puts("player contents");
for(first = DBFETCH(player)->contents; first != NOTHING;
first = DBFETCH(first)->next)
if(Typeof(first) == TYPE_THING)
res += do_act(first, command, player);
puts("location contents");
if(DBFETCH(player)->location != NOTHING)
for(first = DBFETCH(DBFETCH(player)->location)->contents; first != NOTHING;
first = DBFETCH(first)->next)
if(Typeof(first) == TYPE_THING)
res += do_act(first, command, player);
puts("Done.");
return res;
}
dbref global_cause;
int do_restart(dbref who)
{
if(!Wizard(who)) {
notify(who, "Permission denied.");
return 0;
}
kill(getpid(), 15); /* cause automatic restart. */
return 0;
}
int do_uptime(dbref who)
{
int x = time(NULL) - startup_time;
sprintf(buf, "up %d days, %02d:%02d:%02d",
x/(60*60*24), (x/(60*60))%24, (x/60)%60,x%60);
notify(who, buf);
return 0;
}
int do_version(dbref who)
{
sprintf(buf, "Version: %s", VERSION_STRING);
notify(who, buf);
return 0;
}