/* game.c */
/* $Id: game.c,v 1.39 1993/12/19 01:20:59 nils Exp $ */
int ndisrooms;
#if defined(SYSV) || defined(AIX_UNIX) || defined(SYSV_MAYBE)
#define vfork fork
#endif
#define my_exit exit
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#ifdef __STDC__
#include <stdlib.h>
#endif
#ifdef XENIX
#include <sys/signal.h>
#else
#include <signal.h>
#include <sys/wait.h>
#endif /* xenix */
#include "nalloc.h"
#include "db.h"
#include "config.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#include "credits.h"
#include "admin.h"
/* declarations */
char dumpfile[200];
static int epoch = 0;
int reserved;
int depth=0; /* excessive recursion prevention */
extern dbref cplr;
int unsafe=0;
/* used to allocate storage for temporary stuff, cleared before command
execution */
NALLOC *glurp;
void do_dump(player)
dbref player;
{
if(power(player, POW_DB)) {
notify(player, "Dumping...");
fork_and_dump();
} else {
notify(player, "Sorry, you are in a no dumping zone.");
}
}
extern char ccom[1024];
/* print out stuff into error file */
void report()
{
char repbuf[5000];
/* fprintf(stderr,"Command:%s depth:%d\n",ccom,depth);fflush(stderr);
if ((cplr>0) && (cplr<db_top))
fprintf(stderr,"Player #%d location #%d\n",cplr,db[cplr].location);
fflush(stderr);*/
log_error("*** Reporting position ***");
sprintf(repbuf,"Depth: %d Command: %s",depth,ccom);
log_error(repbuf);
sprintf(repbuf,"Player: %d location: %d",cplr,db[cplr].location);
log_error(repbuf);
log_error("**************************");
}
#ifdef DESTROY
void do_purge(player)
dbref player;
{
if (power(player, POW_DB))
{
fix_free_list();
notify(player,"Purge complete.");
}
else
notify(player,"@purge is a restricted command.");
}
/* this is where des_info points */
void dest_info(thing,tt)
dbref thing;
dbref tt;
{
char buff[1024];
if (thing==NOTHING) {
if (db[tt].name) {
sprintf(buff,"You own a disconnected room, %s(#%d)",db[tt].name,tt);
notify(db[tt].owner,buff);
} else {
report();
log_error("no name for room");
}
return;
}
switch(Typeof(thing))
{
case TYPE_ROOM: /* Tell all players room has gone away */
notify_in(thing, 0, tprintf("%s, %s",
"The floor disappears under your feet",
"you fall through NOTHINGness and then:"));
break;
case TYPE_PLAYER: /* Show them where they arrived */
enter_room(thing,HOME);
break;
}
}
#endif
dbref speaker=NOTHING;
void notify_nopup(player,msg)
dbref player;
char *msg;
{
static char buff[2148],*d;
if(player<0 || player>=db_top)
return;
if(depth++>7) {
depth--;
return;
}
if (db[player].owner != player) {
strcpy(buff,msg);
if (*(d=atr_get(player,A_LISTEN)) &&
wild_match(d,buff)) {
if (speaker!=player)
did_it(speaker,player,0,NULL,0,NULL,A_AHEAR);
else
did_it(speaker,player,0,NULL,0,NULL,A_AMHEAR);
did_it(speaker,player,0,NULL,0,NULL,A_AAHEAR);
/* also pass the message on */
/* Note: not telling player protects against two forms of recursion */
/* player doesn't tell itself (as container) or as contents */
/* using teleport it is possible to create a recursive loop */
/* but this will be terminated when the depth variable exceeds 30 */
if (db[speaker].location != player)
notify_in(player,player,buff);
}
/* now check for multi listeners */
if (speaker!=player)
atr_match (player, speaker, '!', msg);
}
depth--;
}
void notify(player,msg)
dbref player;
char *msg;
{
static char buff[2148];
if ((player<0) || (player>=db_top))
return;
if (depth++>7) {
depth--;
return;
}
switch(Typeof(player)) {
case TYPE_PLAYER:
raw_notify(player,msg);
default:
if (db[player].flags & PUPPET) {
sprintf(buff,"%s> %s",db[player].name,msg);
raw_notify(db[player].owner,buff);
}
notify_nopup(player,msg);
}
depth--;
}
/* special notify, if puppet && owner is in same room don't relay */
void snotify(player,msg)
dbref player;
char *msg;
{
if ((db[player].owner!=player) && (db[player].flags & PUPPET)
&& (db[player].location==db[db[player].owner].location))
notify_nopup(player,msg);
else
notify(player,msg);
}
static void notify_except P((dbref, dbref, char *));
static void notify_except(first,exception,msg)
dbref first;
dbref exception;
char *msg;
{
if(first == NOTHING) return;
DOLIST (first, first) {
if (/*((db[first].flags & TYPE_MASK) == TYPE_PLAYER ||
((db[first].flags & PUPPET) && (Typeof(first)==TYPE_THING)))
&&*/ first != exception) {
snotify (first, msg);
}
}
}
void notify_in(room, exception, msg)
dbref room, exception;
char *msg;
{
dbref z;
DOZONE(z, room)
notify(z,msg);
if (room == NOTHING) return;
if (room != exception)
snotify(room, msg);
notify_except(db[room].contents, exception, msg);
notify_except(db[room].exits, exception, msg);
}
void do_shutdown(player, arg1)
dbref player;
char *arg1;
{
extern int exit_status;
if (strcmp(arg1, MUSE_NAME)) {
if (!*arg1)
notify(player,"You must specify the name of the muse you wish to shutdown.");
else
notify(player,tprintf("This is %s, not %s.",MUSE_NAME, arg1));
return;
}
log_sensitive(tprintf("Shutdown attempt by %s",unparse_object(player,player)));
if(power(player, POW_SHUTDOWN)) {
log_important(tprintf("SHUTDOWN: by %s", unparse_object(player, player)));
shutdown_flag = 1;
exit_status = 0;
#ifdef USE_RWHO
rwhocli_shutdown();
#endif
} else {
notify(player, "@shutdown is a restricted command.");
}
}
void do_reboot(player, arg1)
dbref player;
char *arg1;
{
extern int exit_status;
if (strcmp(arg1, MUSE_NAME)) {
if (!*arg1)
notify(player,"You must specify the name of the muse you wish to reboot.");
else
notify(player,tprintf("This is %s, not %s.",MUSE_NAME, arg1));
return;
}
log_sensitive(tprintf("Reboot attempt by %s", unparse_object(player, player)));
if(power(player, POW_SHUTDOWN)) {
log_important(tprintf("REBOOT: by %s", unparse_object(player, player)));
shutdown_flag = 1;
exit_status = 1;
#ifdef USE_RWHO
rwhocli_shutdown();
#endif
} else {
notify(player, "@reboot is a restricted command.");
}
}
#ifdef XENIX
/* rename hack!!! */
void rename(s1,s2)
char *s1;
char *s2;
{
char buff[300];
sprintf(buff,"mv %s %s",s1,s2);
system(buff);
}
#endif
static void dump_database_internal()
{
char tmpfile[2048];
FILE *f;
sprintf(tmpfile, "%s.#%d#", dumpfile, epoch - 1);
unlink(tmpfile); /* nuke our predecessor */
sprintf(tmpfile, "%s.#%d#", dumpfile, epoch);
#ifdef DBCOMP
if((f = popen(tprintf("../bin/mycompress >%s",tmpfile), "w")) != NULL) {
db_write(f);
if((pclose(f) == 123) ||
(rename(tmpfile, dumpfile) < 0)) {
no_dbdump();
perror(tmpfile);
}
}
else {
no_dbdump();
perror(tmpfile);
}
#else
if ( (f = fopen(tmpfile,"w")) != NULL ) {
db_write(f);
fclose(f);
if ( rename(tmpfile,dumpfile) < 0 ) {
perror(tmpfile);
no_dbdump();
}
}
else {
no_dbdump();
perror(tmpfile);
}
#endif
}
void panic(message)
char *message;
{
char panicommand_loge[2048];
FILE *f;
int i;
sprintf(panicommand_loge,"PANIC!! %s",message); /* kludge! */
log_error(panicommand_loge); /* reuse panicommand_loge later! yay! */
#ifdef SYSV_IO
punt_all();
#endif
report();
/* turn off signals */
for(i = 0; i < NSIG; i++) {
signal(i, SIG_IGN);
}
/* shut down interface */
emergency_shutdown();
/* dump panic file */
sprintf(panicommand_loge, "%s.PANIC", dumpfile);
if((f = fopen(panicommand_loge, "w")) == NULL) {
perror("CANNOT OPEN PANIC FILE, YOU LOSE");
exit_nicely(136);
} else {
log_io(tprintf("DUMPING: %s", panicommand_loge));
db_write(f);
fclose(f);
log_io(tprintf("DUMPING: %s (done)", panicommand_loge));
exit_nicely(136);
}
}
void dump_database()
{
epoch++;
log_io(tprintf("DUMPING: %s.#%d#", dumpfile, epoch));
dump_database_internal();
log_io(tprintf("DUMPING: %s.#%d# (done)", dumpfile, epoch));
}
void free_database()
{
/* free all the objects, and everything. for malloc debugging. */
int i;
for (i=0; i<db_top; i++) {
free (db[i].name);
if (db[i].parents)
free(db[i].parents);
if (db[i].children)
free(db[i].children);
if (db[i].pows)
free(db[i].pows);
if (db[i].atrdefs) {
struct atrdef *j, *next=NULL;
for (j=db[i].atrdefs; j; j=next) {
next = j->next;
free(j->a.name);
free(j);
}
}
if (db[i].list) {
ALIST *j, *next=NULL;
for (j=db[i].list; j; j=next) {
next = AL_NEXT(j);
free(j);
}
}
}
bigfree(db);
}
void fork_and_dump()
{
int child;
static char buf[100] = "";
/* first time through only, setup dump message */
if ( *buf == '\0' )
#ifdef USE_VFORK
sprintf(buf, "%s Database saved. Sorry for the lag.",MUSE_NAME);
#else
#ifdef NOISY_DUMP
sprintf(buf,
"Saving %s DataBase. Response will be slow for a few minutes.",
MUSE_NAME);
#endif
#endif
#ifdef USE_SPACE
dump_space();
#endif
epoch++;
log_io(tprintf("CHECKPOINTING: %s.#%d#", dumpfile, epoch));
#ifdef NOISY_DUMP
for(i = 0; i < db_top; i++)
if( Typeof(i) == TYPE_PLAYER && ! (db[i].flags & PLAYER_NO_WALLS) )
notify(i, buf);
#endif
#ifndef NO_FORK
# ifdef USE_VFORK
child = vfork();
# else /* USE_VFORK */
child = fork();
if ( child == -1 )
child=vfork(); /* not enough memory! or something.. */
# endif /* USE_VFORK */
#else /* NO FORK */
child=0;
#endif /* NO_FORK */
if(child == 0) {
/* in the child */
close(reserved); /* get that file descriptor back */
dump_database_internal();
#ifndef NO_FORK
_exit(0);
#else /* NO FORK */
reserved=open("/dev/null",O_RDWR,664);
#endif /* NO_FORK */
}
else if(child < 0) {
perror("fork_and_dump: fork()");
no_dbdump();
}
}
void no_dbdump()
{
do_broadcast(1,"Database save failed. Please take appropriate precautions.","");
}
static signal_type reaper (i)
int i;
{
#if defined(XENIX) || defined(SYSV) || defined(AIX_UNIX) || defined(SYSV_MAYBE)
int status;
wait(&status);
#else
union wait stat;
while(wait3(&stat, WNOHANG, 0) > 0);
#endif
#ifdef void_signal_type
return;
#else
return 0;
#endif
}
void do_restart()
{
dbref thing;
char *s;
FILE *f;
f=fopen("nostartup","r");
if (f) {
fclose(f);
return; /* don't do startup stuff */
}
for(thing=0;thing<db_top;thing++)
if (!(db[thing].flags & GOING) && *(s=atr_get(thing,A_STARTUP)))
parse_que(thing,s,thing);
}
int init_game(infile,outfile)
char *infile;
char *outfile;
{
FILE *f;
int a;
depth=0;
glurp=na_open(NULL);
for(a=0;a<10;a++)
wptr[a]=NULL;
/* reserved=open("/dev/null",O_RDWR); #JMS# */
#ifdef DBCOMP
if((f = popen(tprintf("uncompress <%s",infile),"r")) == NULL)
return -1;
#else
if ((f=fopen(infile,"r"))==NULL)
return -1;
#endif
/* ok, read it in */
log_important(tprintf("LOADING: %s", infile));
fflush(stdout);
db_set_read(f);
log_important(tprintf("LOADING: %s (done)", infile));
/* everything ok */
/* initialize random number generator */
srand(getpid());
/* set up dumper */
strcpy(dumpfile,outfile);
init_timer();
#ifndef XENIX
signal(SIGCHLD, reaper);
#else /* xenix */
signal(SIGCLD,reaper);
#endif
return 0;
}
/* use this only in process
_command */
#define Matched(string) { if(!string_prefix((string), command)) goto bad; }
/* the two versions of argument parsing */
char *do_argtwo(player,rest,cause,buff)
dbref player;
char *rest;
dbref cause;
char *buff;
{
exec(&rest,buff,player,cause,0);
return(buff);
}
char **do_argbee(player,rest,cause,arge,buff)
dbref player;
char *rest;
dbref cause;
char *arge[];
char *buff;
{
int a;
for(a=1;a<MAX_ARG;a++)
arge[a]= (char *) parse_up(&rest,',');
/* rest of delimiters are ,'s */
for(a=1;a<MAX_ARG;a++)
if (arge[a]) {
exec(&arge[a],buff,player,cause,0);
strcpy(arge[a]=(char *)na_alloc(glurp,strlen(buff)+1),buff);
}
return(arge);
}
#define arg2 do_argtwo(player,rest,cause,buff)
#define argv do_argbee(player,rest,cause,arge,buff)
#ifdef NEW_COMMANDS
#endif /* NEW_COMMANDS */
#ifdef LOG_COMMANDS
FILE *command_log;
#endif
void process_command(player,command,cause)
dbref player;
char *command;
dbref cause;
{
char *arg1;
char *q; /* utility */
char *p; /* utility */
/* char args[MAX_ARG][1*/
char buff[1024],buff2[1024];
char *arge[MAX_ARG]; /* pointers to arguments (null for empty) */
char unp[1024]; /* unparsed command */
char pure[1024]; /* totally unparsed command */
char pure2[1024];
char *rest, *temp;
int match, z=NOTHING;
dbref zon;
/* general form command arg0=arg1,arg2...arg10 */
int slave=IS(player,TYPE_PLAYER,PLAYER_SLAVE);
int is_direct=0;
if (cause == NOTHING) {
is_direct = 1;
cause = player;
};
inc_pcmdc(); /* increment command stats */
temp=command;
/* skip leading space */
while(*temp && (*temp==' ')) temp++;
/* skip firsts word */
while(*temp && (*temp!=' ')) temp++;
/* skip leading space */
if (*temp)
temp++;
strcpy(pure,temp);
while(*temp && (*temp!='=')) temp++;
if (*temp)
temp++;
strcpy(pure2,temp);
func_zerolev();
na_clear(glurp);
depth=0;
if(command == 0) abort();
/* Access the player */
Access(player);
if (player == GOD && cause != GOD)
return;
/* robustify player */
if((player < 0) || (player >= db_top)
){
log_error(tprintf("process_command: bad player %d", player));
return;
}
if (((db[player].flags & GOING) ||
(db[player].flags & HAVEN)) && Typeof(player)!=TYPE_PLAYER)
{
notify(db[player].owner,
tprintf("Attempt to execute command by halted object #%d",player));
return;
}
speaker=player;
#ifdef LOG_COMMANDS
{
static short counter;
if(command_log==NULL) {
command_log=fopen("logs/commands","w");
setbuf(command_log, NULL);
}
if(command_log==NULL) command_log=stderr;
if(db[player].location < 0 || db[player].location >= db_top) {
fprintf(command_log, "COMMAND from %s(%d) in #%d(ACK!): %s\n",
db[player].name, player, db[player].location, command);
log_error(tprintf("illegal location: player %d location %d",player,db[player].location));
return;
}
fprintf(command_log, "COMMAND from %s(%d) in %s(%d): %s\n",
db[player].name, player,
db[db[player].location].name, db[player].location,
command);
fflush(command_log);
if(counter++>100) {
counter=0;
if(command_log!=stderr)
fclose(command_log);
command_log=NULL;
unlink("logs/commands~");
rename("logs/commands","logs/commands~");
}
}
#endif /* LOG_COMMANDS */
if((db[player].flags & PUPPET) && (db[player].flags & DARK)) {
char buf[2000];
sprintf(buf,"%s>> %s",db[player].name,command);
raw_notify(db[player].owner,buf);
}
/* eat leading whitespace */
while(*command && isspace(*command)) command++;
/* eat extra white space */
q = p = command;
while(*p) {
/* scan over word */
while(*p && !isspace(*p)) *q++ = *p++;
/* smash spaces */
while(*p && isspace(*++p));
if(*p) *q++ = ' '; /* add a space to separate next word */
}
/* terminate */
*q = '\0';
/* important home checking comes first! */
if (strcmp(command,"home")==0)
{
do_move(player,command);
#ifdef LOG_COMMANDS
if(command_log) {
fputc('.',command_log);
fflush(command_log);
}
#endif
return;
}
if (!slave && try_force(player,command)) /*||
((Typeof(player)!=TYPE_PLAYER) && (Typeof(player)!=TYPE_THING)))*/ {
#ifdef LOG_COMMANDS
if(command_log) {
fputc('.',command_log);
fflush(command_log);
}
#endif
return;
}
/* check for single-character commands */
if(*command == SAY_TOKEN) {
do_say(player, command+1, NULL);
} else if(*command == POSE_TOKEN) {
do_pose(player, command+1, NULL, 0);
} else if(*command == NOSP_POSE) {
do_pose(player, command+1, NULL, 1);
} else if(*command == COM_TOKEN) {
do_com(player, "", command+1);
} else if(can_move(player, command)) {
/* command is an exact match for an exit */
do_move(player, command);
} else
{
strcpy(unp,command);
/* parse arguments */
/* 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++;
arge[0]=(char *)parse_up(&arg1,'='); /* first delimiter is ='s */
rest=arg1; /* either arg2 or argv */
if (arge[0])
exec(&arge[0],buff2,player,cause,0);
arg1=(arge[0]) ? buff2 : "";
if (slave)
switch(command[0]) {
case 'l':
Matched("look");
do_look_at(player,arg1);
break;
}
else
switch(command[0]) {
case '+':
switch(command[1]) {
case 'a':
case 'A':
Matched("+away");
do_away(player, arg1);
break;
case 'c':
case 'C':
switch (command[2]) {
case 'o':
case 'O':
case '\0':
Matched("+com");
do_com(player,arg1,arg2);
break;
case 'm':
case 'M':
Matched("+cmdav");
do_cmdav(player);
break;
case 'h':
case 'H':
Matched("+channel");
do_channel(player,arg1);
break;
default: goto bad;
}
break;
case 'e':
case 'E':
Matched("+edit");
do_editfile(player,arg1);
break;
case 'h':
case 'H':
Matched("+haven");
do_haven(player, arg1);
break;
case 'i':
case 'I':
Matched("+idle");
do_idle(player, arg1);
break;
case 'l':
case 'L':
switch (command[2]) {
case 'a':
case 'A':
Matched("+laston");
do_laston(player, arg1);
break;
case 's':
case 'S':
Matched("+ls");
do_ls(player, arg1);
break;
default: goto bad;
}
break;
case 'm':
case 'M':
switch(command[2]) {
case 'a':
case 'A':
Matched("+mail");
do_mail(player,arg1,arg2);
break;
case 'k':
case 'K':
Matched("+mkdir");
do_mkdir(player, arg1);
break;
default: goto bad;
}
break;
case 'u':
case 'U':
Matched("+uptime");
do_uptime(player);
break;
case 'v':
case 'V':
Matched("+version");
do_version(player);
break;
default:
goto bad;
}
break;
case '@':
switch(command[1]) {
case 'a':
case 'A':
switch(command[2]) {
case 'd':
case 'D':
Matched("@addparent");
do_addparent (player, arg1, arg2);
break;
case 'l':
case 'L':
Matched("@allquota");
do_allquota(player, arg1);
break;
case 'n':
case 'N':
Matched("@announce");
do_announce(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'b':
case 'B':
switch(command[2]) {
case 'r':
case 'R':
Matched("@broadcast");
do_broadcast(player, arg1, arg2);
break;
case 'o':
case 'O':
Matched("@boot");
do_boot(player, arg1);
break;
default:
goto bad;
}
break;
case 'c':
case 'C':
/* chown, create */
switch(command[2]) {
case 'h':
case 'H':
if ( strcmp(command, "@chownall") == 0 )
do_chownall(player, arg1, arg2);
else {
switch (command[3]) {
case 'o':
case 'O':
Matched("@chown");
do_chown(player, arg1, arg2);
break;
case 'e':
case 'E':
Matched("@check");
do_check (player, arg1);
break;
default: goto bad;
}
}
break;
case 'r':
case 'R':
Matched("@create");
do_create(player, arg1, atol(arg2));
break;
case 't':
case 'T':
Matched("@ctrace");
do_ctrace(player);
break;
case 'l':
case 'L':
switch(command[3]) {
case 'a':
case 'A':
Matched("@class");
do_class(player, arg1, arg2);
break;
case 'o':
case 'O':
Matched("@clone");
do_clone(player,arg1,arg2);
break;
default:
goto bad;
}
break;
case 's':
case 'S':
Matched("@cset");
do_set(player,arg1,arg2,1);
break;
case 'y':
case 'Y':
Matched("@cycle");
do_cycle(player,arg1,argv);
break;
default:
goto bad;
}
break;
case 'd':
case 'D':
/* describe, dig, or dump */
switch(command[2]) {
case 'b':
case 'B':
switch (command[3]) {
case 'c':
Matched("@dbck");
do_dbck(player);
break;
case 't':
Matched("@dbtop");
do_dbtop(player,arg1);
break;
default: goto bad;
}
break;
case 'e':
case 'E':
#ifdef DESTROY
if (strcmp("@destroy",command)==0)
{
do_destroy(player,arg1);
}
else
#endif /* DESTROY */
switch (command[3]) {
case 'c':
case 'C':
Matched("@decompile");
do_decompile (player, arg1, arg2);
break;
case 's':
case 'S':
Matched("@describe");
do_describe(player, arg1, arg2);
break;
case 'f':
case 'F':
Matched("@defattr");
do_defattr(player, arg1, arg2);
break;
case 'l':
case 'L':
Matched("@delparent");
do_delparent (player, arg1, arg2);
break;
default: goto bad;
}
break;
case 'i':
case 'I':
Matched("@dig");
do_dig(player, arg1,argv);
break;
case 'u':
case 'U':
Matched("@dump");
do_dump(player);
break;
default:
goto bad;
}
break;
case 'f':
/* fail, find, or force */
switch(command[2]) {
case 'a':
case 'A':
Matched("@fail");
do_fail(player, arg1, arg2);
break;
case 'i':
case 'I':
Matched("@find");
do_find(player, arg1);
break;
case 'o':
case 'O':
if (string_prefix ("@foreach", command) && strlen(command)>4) {
Matched("@foreach");
do_foreach(player, arg1, arg2, cause);
break;
}
Matched("@force");
do_force(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'e':
case 'E':
switch(command[2]) {
case 'c':
case 'C':
Matched("@echo");
do_echo(player,arg1,arg2,0);
break;
case 'd':
case 'D':
Matched("@edit");
do_edit(player,arg1,argv);
break;
case 'm':
case 'M':
switch(command[3]) {
case 'i':
case 'I':
Matched("@emit");
do_emit(player,arg1,arg2,0);
break;
case 'p':
case 'P':
Matched("@empower");
do_empower(player,arg1,arg2);
break;
default: goto bad;
}
break;
#ifdef EXEC
case 'x':
case 'X':
Matched("@exec");
do_exec(player,arg1,arg2);
break;
#endif
default:
goto bad;
}
break;
case 'g':
case 'G':
Matched("@giveto");
do_giveto(player,arg1,arg2);
break;
case 'h':
case 'H': /* removes all queued commands by your objects */
/* halt or hide */
switch(command[2]) {
case 'a':
case 'A':
Matched("@halt");
do_halt(player,arg2);
break;
case 'i': /* hides player name from WHO */
case 'I':
Matched("@hide");
do_hide(player);
break;
default:
goto bad;
}
break;
case 'l':
case 'L':
/* lock or link */
switch(command[2]) {
case 'i':
case 'I':
Matched("@link");
do_link(player, arg1, arg2);
break;
/* case 'o':
case 'O':
Matched("@lock");
do_lock(player, arg1, arg2);
break; */
default:
goto bad;
}
break;
case 'm':
case 'M':
switch(command[2]) {
case 'i':
case 'I':
Matched("@misc"); /* miscelanious functions */
do_misc(player,arg1,arg2);
break;
case 'a':
case 'A':
Matched("@mailhuh");
if(!power(player,POW_DB)) goto bad;
do_mailhuh(player);
break;
default: goto bad;
}
break;
case 'n':
case 'N':
/* @name, @newpassword, or @nuke */
switch(command[2]) {
case 'a':
case 'A':
Matched("@name");
do_name(player, arg1, arg2, is_direct);
break;
case 'c':
case 'C':
Matched("@ncset");
do_set(player, arg1, pure2, 1);
break;
case 'e':
case 'E':
switch(command[3]) {
case 'c':
case 'C':
Matched("@necho");
do_echo(player,pure,NULL,1);
break;
case 'w':
if(strcmp(command, "@newpassword")) goto bad;
do_newpassword(player, arg1, arg2);
break;
case 'm':
case 'M':
Matched("@nemit");
do_emit(player,pure,NULL,1);
break;
default:
goto bad;
}
break;
case 'u':
if(string_compare(command, "@nuke")) goto bad;
do_nuke(player, arg1);
break;
case 'o':
case 'O':
Matched("@nopow_class");
do_nopow_class(player, arg1, arg2);
break;
case 'p':
case 'P':
switch(command[3]) {
case 'e':
case 'E':
Matched("@npemit");
do_general_emit(player, arg1, pure, 4);
break;
case 'a':
case 'A':
Matched("@npage");
do_page(player, arg1, pure2);
break;
default:
goto bad;
}
break;
case 's':
case 'S':
Matched("@nset");
do_set(player, arg1, pure2, is_direct);
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
switch(command[2]) {
case 'e':
case 'E':
Matched("@oemit");
do_general_emit(player, arg1, arg2, 2);
break;
case 'f':
case 'F':
Matched("@ofail");
do_ofail(player, arg1, arg2);
break;
case 'p':
case 'P':
Matched("@open");
do_open(player, arg1, arg2,NOTHING);
break;
case 's':
case 'S':
Matched("@osuccess");
do_osuccess(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'p':
case 'P':
switch(command[2])
{
case 'a':
case 'A':
Matched("@password");
do_password(player, arg1, arg2);
break;
case 'b':
case 'B':
Matched("@pbreak");
do_pstats(player, arg1);
break;
case 'C':
case 'c':
Matched("@pcreate");
do_pcreate(player, arg1, arg2);
break;
case 'e':
case 'E':
Matched("@pemit");
do_general_emit(player, arg1, arg2, 0);
break;
case 'O':
case 'o':
switch(command[3]) {
case 'o':
case 'O':
Matched("@Poor");
do_poor(player,arg1);
break;
case 'w':
case 'W':
Matched("@powers");
do_powers(player,arg1);
break;
default: goto bad;
}
break;
case 'S':
case 's':
Matched("@ps");
do_queue(player);
break;
#ifdef DESTROY
case 'u':
case 'U':/* force room destruction */
Matched("@purge");
do_purge(player);
break;
#endif /* DESTROY */
default:
goto bad;
}
break;
case 'q':
case 'Q':
Matched("@quota");
do_quota(player, arg1, arg2);
break;
case 'r':
case 'R':
switch(command[2]) {
case 'e':
case 'E':
switch(command[3]) {
case 'b':
case 'B':
Matched("@reboot");
do_reboot(player, arg1);
break;
case 'g':
case 'G':
if(!string_compare(command, "@register_purge"))
do_register_purge(player);
else
goto bad;
break;
case 'm':
case 'M':
Matched("@remit");
do_general_emit(player,arg1,arg2,1);
break;
default: goto bad;
}
break;
case 'O':
case 'o':
Matched("@robot");
do_robot(player,arg1,arg2);
break;
#ifdef USE_RWHO
case 'W':
case 'w':
Matched("@rwho");
do_rwho(player,arg1);
break;
#endif
default:
goto bad;
}
break;
case 's':
case 'S':
/* set, shutdown, success */
switch(command[2]) {
/* case 'a':
case 'A': * !!! wizard only safe command !!! *
if (!power(player, TYPE_ADMIN))
goto bad;
unsafe=0;
break; */
case 'e':
case 'E':
/* patched to add 'search' command */
switch(command[3]) {
case 'a':
case 'A':
Matched("@search");
do_search(player, arg1, arg2);
break;
case 't':
case 'T':
Matched("@set");
do_set(player, arg1, arg2, is_direct);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
switch(command[3]) {
case 'u':
if(strcmp(command, "@shutdown")) goto bad;
do_shutdown(player, arg1);
break;
case 'o':
case 'O':
Matched("@showhash");
do_showhash(player,arg1);
break;
default:
goto bad;
}
break;
case 't': case 'T':
Matched("@stats");
do_stats(player, arg1);
break;
case 'u':
case 'U':
Matched("@success");
do_success(player, arg1, arg2); break;
case 'w':
case 'W':
switch(command[3]) {
case 'e':
case 'E':
Matched("@sweep");
do_sweep(player, pure);
break;
case 'i':
case 'I':
Matched("@switch");
do_switch(player,arg1,argv,cause);
break;
default:
goto bad;
}
break;
default:
goto bad;
}
break;
case 't':
case 'T':
switch(command[2]) {
case 'e':
case 'E':
switch(command[3]) {
case 'l':
case 'L':
case '\0':
Matched("@teleport");
do_teleport(player, arg1, arg2);
break;
case 'x':
case 'X':
Matched("@text");
do_text(player, arg1, arg2);
break;
default: goto bad;
}
break;
case 'r':
case 'R':
switch(command[3]) {
case 'i':
case 'I':
case '\0':
Matched("@trigger");
do_trigger(player,arg1,argv);
break;
case '_':
Matched("@tr_as");
do_trigger_as(player,arg1,argv);
break;
default: goto bad;
};
break;
default:
goto bad;
}
break;
case 'u':
case 'U':
switch(command[2]) {
case 'l':
case 'L':
Matched("@ulink");
do_ulink(player, arg1);
break;
case 'n':
case 'N':
switch(command[3]) {
case 'd':
case 'D':
switch(command[4]) {
case 'e':
case 'E':
switch(command[5]) {
case 's':
case 'S':
Matched("@undestroy");
do_undestroy(player, arg1);
break;
case 'f':
case 'F':
Matched ("@undefattr");
do_undefattr (player, arg1);
break;
default: goto bad;
}
break;
default: goto bad;
}
break;
case 'l':
case 'L':
switch(command[4]) {
case 'i':
case 'I':
Matched("@unlink");
do_unlink(player, arg1);
break;
case 'o':
case 'O':
Matched("@unlock");
do_unlock(player, arg1);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
Matched("@unhide");
do_unhide(player);
break;
case 'z':
case 'Z':
Matched("@unzlink");
do_unzlink(player, arg1);
break;
default: goto bad;
}
break;
case 'p':
case 'P':
Matched("@upfront");
do_upfront(player,arg1,arg2);
break;
default: goto bad;
}
break;
case 'w':
case 'W':
if(strcmp(command, "@wall")==0) {
do_announce(player, arg1, arg2);
break;
}
if(strcmp(command, "@whereis")==0) {
do_whereis(player, arg1);
break;
}
if ( strcmp(command, "@wipeout") == 0 ) {
do_wipeout(player, arg1, arg2);
break;
}
Matched("@wait");
wait_que(player,atoi(arg1),arg2,cause);
break;
case 'z':
case 'Z':
switch(command[2]) {
case 'e':
case 'E':
Matched("@zemit");
do_general_emit(player, arg1, arg2, 3);
break;
case 'l':
case 'L':
Matched("@zlink");
do_zlink(player, arg1, arg2);
break;
default: goto bad;
}
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, arg2);
break;
case 'o':
case 'O':
Matched("goto");
do_move(player, arg1);
break;
case 'r':
case 'R':
Matched("gripe");
do_gripe(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
Matched("help");
do_help(player, arg1, "help", HELPINDX, HELPTEXT, NULL);
break;
case 'i':
case 'I':
Matched("inventory");
do_inventory(player);
break;
case 'j':
case 'J':
Matched("join");
do_join(player, arg1);
break;
#ifdef KILL_MIN_COST
case 'k':
case 'K':
Matched("kill");
do_kill(player, arg1, atol(arg2));
break;
#endif
case 'l':
case 'L':
switch(command[1])
{
case 'o':
case 'O':
case '\0': /* patch allow 'l' command to do a 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':
switch(command[1]) {
case 'o':
case 'O':
switch(command[2]) {
case 'n':
case 'N':
Matched("money");
do_money(player, arg1, arg2);
break;
case 'v':
case 'V':
Matched("move");
do_move(player, arg1);
break;
default:
goto bad;
}
break;
default:
goto bad;
}
break;
case 'n':
case 'N':
/* news */
if(string_compare(command, "news")) goto bad;
/* do_news(player, arg1);*/
do_help(player, arg1, "news", NEWSINDX, NEWSTEXT, A_ANEWS);
break;
case 'p':
case 'P':
switch(command[1]) {
case 'a':
case 'A':
case '\0':
Matched("page");
do_page(player, arg1,arg2);
break;
case 'o':
case 'O':
Matched("pose");
do_pose(player,arg1,arg2,0);
break;
default:
goto bad;
}
break;
case 'r':
case 'R':
switch(command[1]) {
case 'e':
case 'E':
Matched("read"); /* undocumented alias for look at */
do_look_at(player, arg1);
break;
#ifdef USE_RWHO_DUMP
case 'w':
case 'W':
Matched("rwho");
dump_rusers(player,arg1,arg2);
break;
#endif
default:
goto bad;
}
break;
case 's':
case 'S':
/* say, "score" */
switch(command[1]) {
case 'a':
case 'A':
Matched("say");
do_say(player, arg1, arg2);
break;
case 'c':
case 'C':
Matched("score");
/* notify(player, "Note: This command will soon dissapear.");
notify(player, " Please start using the command: 'money'.");
notify(player, " ");*/
do_score(player);
notify(player, "Warning: this command may dissapear in the future.");
notify(player,"Please start using the 'money' command.");
break;
case 'l':
case 'L':
Matched("slay");
do_slay(player, arg1);
break;
case 'u':
case 'U':
Matched("summon");
do_summon(player,arg1);
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 'u':
case 'U':
Matched("use");
do_use(player,arg1);
break;
case 'w':
case 'W':
switch(command[1]) {
case 'h':
case 'H':
switch(command[2]) {
case 'i':
case 'I':
case '\0':
Matched("whisper");
do_whisper(player,arg1,arg2);
break;
case 'o':
case 'O':
Matched("who");
dump_users(player,arg1,arg2,NULL);
break;
default:
goto bad;
}
break;
case '\0':
do_whisper(player, arg1, arg2);
break;
default:
goto bad;
}
break;
#ifdef USE_SPACE /* Commands installed by Michael Majere */
case '!':
switch(command[1]) {
case 'b':
case 'B':
Matched("!boot");
do_spaceboot(player);
break;
case 'c':
case 'C':
switch(command[2]) {
case 'o':
case 'O':
switch(command[3]) {
case 'n':
case 'N':
Matched("!cont");
do_spacecont(player);
break;
case 'm':
case 'M':
Matched("!comevent");
do_comevent(player,arg1,argv);
break;
default:
goto bad;
}
break;
default:
goto bad;
}
break;
case 'd':
case 'D':
switch(command[2]) {
case 'a':
case 'A':
Matched("!data");
do_spacedata(player, arg1);
break;
case 'o':
case 'O':
Matched("!dock");
do_spacedock(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'e':
case 'E':
switch(command[2]) {
case 'n':
case 'N':
Matched("!enter");
do_spaceenter(player, arg1);
break;
case 'x':
case 'X':
Matched("!exit");
do_spaceexit(player, arg1);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
switch(command[2]) {
case 'a':
case 'A':
Matched("!halt");
do_spacehalt(player);
break;
case 'e':
case 'E':
Matched("!help");
do_spacehelp(player);
break;
case 'y':
case 'Y':
Matched("!hyper");
do_spacehyper(player, arg1);
break;
default:
goto bad;
}
break;
case 's':
case 'S':
Matched("!senevent");
do_senevent(player, arg1, argv);
break;
case 'v':
case 'V':
Matched("!visevent");
do_visevent(player, arg1, argv);
break;
case 'w':
case 'W':
Matched("!worm");
do_spaceworm(player, arg1, argv);
break;
default:
goto bad;
}
break;
#endif /* USE_SPACE */
default:
goto bad;
bad:
if (!slave && test_set(player,command,arg1,arg2, is_direct)) {
#ifdef LOG_COMMANDS
if(command_log) {
fputc('.',command_log);
fflush(command_log);
}
#endif
return;
}
/* try matching user defined functions before chopping */
match = list_check(db[db[player].location].contents,player,'$',unp)
|| list_check(db[player].contents,player,'$',unp)
|| atr_match(db[player].location,player,'$',unp)
|| list_check(db[db[player].location].exits,player,'$',unp);
DOZONE(zon, player)
match = list_check(z = zon,player,'$',unp) || match;
if (!match) {
notify(player, "Huh? (Type \"help\" for help.)");
#ifdef LOG_FAILED_COMMANDS
if(!controls(player, db[player].location, POW_MODIFY) &&
!controls(player, get_zone_first(player), POW_MODIFY) &&
*atr_get(get_zone_first(player),A_HUHTO)) {
static char buf[2000];
sprintf(buf,"%05dFrom %s(%d) in %s(%d) zone %s(%d): %s",
get_zone_first(player), /* %05dFrom */
db[player].name, player, /*%s(%d) in */
db[db[player].location].name, /*%s(*/
db[player].location, /* %d) zone */
db[get_zone_first(player)].name, get_zone_first(player),/* %s(%d): */
unp /* %s */);
log_huh(buf);
}
#endif /* LOG_FAILED_COMMANDS */
}
break;
}
}
{int a;for(a=0;a<10;a++)wptr[a]=NULL;}
#ifdef LOG_COMMANDS
if(command_log) {
fputc('.',command_log);
fflush(command_log);
}
#endif
}
/* get a player's or object's zone */
dbref get_zone_first(player)
dbref player;
{
int depth = 10;
dbref location;
for (location = player; depth && location!=NOTHING; depth--, location = db[location].location) {
if (db[location].zone == NOTHING && (Typeof(location)==TYPE_THING
|| Typeof(location)==TYPE_ROOM)
&& location != 0 && location != db[0].zone)
db[location].zone = db[0].zone;
if (location == db[0].zone)
return db[0].zone;
else if (db[location].zone != NOTHING)
return db[location].zone;
}
return db[0].zone;
}
dbref get_zone_next(player)
dbref player;
{
if (db[player].zone == NOTHING && player != db[0].zone)
return db[0].zone;
return db[player].zone;
}
int list_check(thing,player,type,str)
dbref thing,player;
int type;
char *str;
{
int match=0;
while(thing!=NOTHING) {
/* only a player can match on him/herself */
if (((thing == player) && (Typeof(thing) != TYPE_PLAYER)) ||
((thing != player) && (Typeof(thing) == TYPE_PLAYER))) {
thing=db[thing].next;
} else {
if (atr_match(thing,player,type,str))
match=1;
thing=db[thing].next;
}
}
return(match);
}
/* routine to check attribute list for wild card matches of certain
type and queue them */
int atr_match(thing,player,type,str)
dbref thing,player;
int type; /* must be symbol not affected by compress */
char *str; /* string to match */
{
struct all_atr_list *ptr;
int match=0;
for(ptr=all_attributes(thing);ptr;ptr=ptr->next)
if ((ptr->type!=0) && !(ptr->type->flags & AF_LOCK) &&
(*ptr->value==type)) {
/* decode it */
char buff[1024];
char *s, *p;
strncpy(buff,uncompress(ptr->value),1024);
/* search for first un escaped : */
for(s=buff+1;*s && (*s!=':');s++);
if (!*s)
continue;
*s++=0;
if (*s == '/') { /* locked attribute */
p = ++s;
while(*s && (*s != '/')) {
if (*s == '[') while (*s && (*s != ']')) s++;
s++;
}
if (!*s) continue;
*s++ = '\0';
if (!eval_boolexp(player, thing, p, get_zone_first(player))) continue;
}
if (wild_match(buff+1,str)) {
match = 1;
if(!eval_boolexp(player,thing,atr_get(thing,A_ULOCK),get_zone_first(player)))
did_it(player,thing,A_UFAIL,NULL,A_OUFAIL,NULL,A_AUFAIL);
else parse_que(thing,s,player);
}
}
return(match);
}
int Live_Player(thing)
dbref thing;
{
if ((Typeof(thing)==TYPE_PLAYER) && (db[thing].flags & PLAYER_CONNECT)) {
return(1);
} else {
return(0); }
}
int Live_Puppet(thing)
dbref thing;
{
if (db[thing].flags&PUPPET &&
(IS(thing, TYPE_PLAYER, PLAYER_CONNECT)
|| IS(db[thing].owner, TYPE_PLAYER, PLAYER_CONNECT))) {
return(1);
} else {
return(0); }
}
int Listener(thing)
dbref thing;
{
/* ALIST *ptr; */
struct all_atr_list *ptr;
ATTR *type;
char *s;
/* if (((Typeof(thing)==TYPE_PLAYER) && (db[thing].flags & PLAYER_CONNECT))
|| (db[thing].flags & PUPPET))
return(1);
for(ptr=db[thing].list;ptr;ptr=AL_NEXT(ptr)) {*/
for(ptr=all_attributes(thing); ptr; ptr=ptr->next) {
/* type=AL_TYPE(ptr);
s=AL_STR(ptr);*/
type = ptr->type;
s = ptr->value;
if (!type)
continue;
if (type==A_LISTEN)
return(1);
if ((*s=='!') && !(type->flags & AF_LOCK))
return(1);
}
return(0);
}
int Commer(thing)
dbref thing;
{
/* ALIST *ptr; */
struct all_atr_list *ptr;
ATTR *type;
char *s;
/* if (((Typeof(thing)==TYPE_PLAYER) && (db[thing].flags & PLAYER_CONNECT))
|| (db[thing].flags & PUPPET))
return(1);
for(ptr=db[thing].list;ptr;ptr=AL_NEXT(ptr)) {*/
for(ptr=all_attributes(thing); ptr; ptr=ptr->next) {
/* type=AL_TYPE(ptr);
s=AL_STR(ptr);*/
type = ptr->type;
s = ptr->value;
if (!type)
continue;
if (*s=='$')
return(1);
}
return(0);
}
int Hearer(thing)
dbref thing;
{
if (Live_Player(thing) || Live_Puppet(thing) || Listener(thing)) {
return(1);
} else {
return(0); }
}
int Active(thing)
dbref thing;
{
if (Live_Player(thing) || Live_Puppet(thing) || Listener(thing) ||
Commer(thing)) {
return(1);
} else {
return(0); }
}
#undef Matched
void exit_nicely(int i)
{
remove_muse_pid();
#ifdef MALLOCDEBUG
mnem_writestats();
#endif
exit(i);
}
/* End game.c */