/* 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 */