/* game.c */ #include "os.h" #include "config.h" #include "db.h" #include "externs.h" #include "interface.h" #include "match.h" #ifdef MEM_CHECK #include "mem_check.h" #endif /* declarations */ char dumpfile[200]; static int epoch = 0; int depth = 0; /* excessive recursion prevention */ static int list_check (dbref thing, dbref player, int type, int end, char *str); static int alias_list_check (dbref thing, const char *command, char *type); static int quick_alias_check (dbref loc, const char *command, char *type); static void do_poor(dbref player, char *arg1); static void do_version(dbref player); static void do_dolist(dbref player, char *inlist, char *command, dbref cause); static void do_config(dbref player); /* * used to allocate storage for temporary stuff, cleared before command * execution */ void do_dump (dbref player) { time_t tt; tt = time ((time_t *) 0); if (Wizard (player)) { notify (player, "Dumping..."); fprintf (stderr, "** DUMP ** done by %s(#%d) at %s", db[player].name, player, ctime (&tt)); fork_and_dump (); } else { notify (player, "Sorry, you are in a no dumping zone."); } } /* print out stuff into error file */ void report (void) { fprintf (stderr, "****REPORT TRACE!****\n\tCommand:%s\tdepth:%d\n", ccom, depth); fflush (stderr); if ((cplr > 0) && (cplr <= db_top)) fprintf (stderr, "\tPlayer #%d\n\tlocation #%d\n", cplr, db[cplr].location); fflush (stderr); } #ifdef DESTROY static void do_purge (dbref player) { if (Wizard (player)) { FIX; notify (player, "Purge complete."); } else notify (player, "Sorry, you are a mortal."); } void dest_info (dbref thing, dbref tt) { if (thing == NOTHING && !Floating (tt)) { if (db[tt].name) { notify (db[tt].owner, tprintf ("You own a disconnected room, %s(#%d)", db[tt].name, tt)); } else fprintf (stderr, "ERROR: no name for room\n"); return; } switch (Typeof (thing)) { case TYPE_ROOM: /* Tell all players room has gone away */ notify_except (db[thing].contents, 0, "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 /* DESTROY */ dbref speaker = NOTHING; void notify (dbref player, const char *msg) { ATTR *d; char tbuf1[BUFFER_LEN]; if ((player < 0) || (player >= db_top)) return; if (depth++ > 7) { depth--; return; } switch (Typeof (player)) { case TYPE_PLAYER: raw_notify (player, msg); break; case TYPE_THING: if (db[player].flags & THING_PUPPET && (db[player].location != db[db[player].owner].location || speaker == player)) { sprintf (tbuf1, "%s> %s", db[player].name, msg); raw_notify (db[player].owner, tbuf1); } d = atr_get (player, "LISTEN"); if (d) { sprintf (tbuf1, "%s", uncompress (d->value)); if (wild_match (tbuf1, (char*)msg)) { if (speaker != player) did_it (speaker, player, 0, NULL, 0, NULL, "AHEAR", NOTHING); else did_it (speaker, player, 0, NULL, 0, NULL, "AMHEAR", NOTHING); did_it (speaker, player, 0, NULL, 0, NULL, "AAHEAR", NOTHING); /* 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 (!member (speaker, db[player].contents)) { if ((Typeof (player) == TYPE_THING) && (db[player].flags & THING_PUPPET)) { notify_except2 (db[player].contents, player, db[player].owner, msg); } else { notify_except (db[player].contents, player, msg); } } } } else { /* if there is no listen, check for ^ listen patterns */ /* these are like AHEAR - object cannot trigger itself */ if (speaker != player) atr_comm_match (player, player, '^', ':', (char*)msg); /* unlike normal @listen, don't pass the message on */ } /* now check for multi listeners */ } depth--; } void do_shutdown (dbref player) { if (Wizard (player)) { raw_broadcast (0, "GAME: Shutdown by %s", db[player].name); fprintf (stderr, "SHUTDOWN: by %s\n", unparse_object (player, player)); fflush (stderr); /* This will create a file used to check if a restart should occur */ #ifdef AUTORESTART system ("touch NORESTART"); #endif shutdown_flag = 1; } else { notify (player, "Your delusions of grandeur have been duly noted."); } } static void dump_database_internal (void) { char tmpfl[2048]; FILE *f; sprintf (tmpfl, "%s.#%d#", dumpfile, epoch - 1); #ifdef _MSC_VER remove (tmpfl); /* nuke our predecessor */ #else unlink (tmpfl); /* nuke our predecessor */ #endif sprintf (tmpfl, "%s.#%d#", dumpfile, epoch); #ifdef DBCOMP if ((f = (FILE*)popen (tprintf ("gzip >%s", tmpfl), "w")) != NULL) { db_write (f); pclose (f); #ifdef WIN32 #ifdef _MSC_VER remove (dumpfile); #else unlink (dumpfile); #endif #endif if (rename (tmpfl, dumpfile) < 0) perror (tmpfl); } else perror (tmpfl); #ifdef USE_MAILER sprintf (tmpfl, "maildb.Z.#%d#", epoch - 1); #ifdef _MSC_VER remove (tmpfl); #else unlink (tmpfl); #endif sprintf (tmpfl, "maildb.Z.#%d#", epoch); if (mdb_top > 0) if ((f = (FILE*)popen (tprintf ("gzip >%s", tmpfl), "w")) != NULL) { dump_mail (f); pclose (f); #ifdef WIN32 #ifdef _MSC_VER remove ("maildb.Z"); #else unlink ("maildb.Z"); #endif #endif if (rename (tmpfl, "maildb.Z") < 0) perror (tmpfl); } else perror (tmpfl); #endif #else if ((f = fopen (tmpfl, "wb")) != NULL) { db_write (f); fclose (f); #ifdef WIN32 #ifdef _MSC_VER remove (dumpfile); #else unlink (dumpfile); #endif #endif if (rename (tmpfl, dumpfile) < 0) perror (tmpfl); } else perror (tmpfl); #ifdef USE_MAILER sprintf (tmpfl, "maildb.#%d#", epoch - 1); unlink (tmpfl); sprintf (tmpfl, "maildb.#%d#", epoch); if ((f = fopen (tmpfl, "wb")) != NULL) { db_write (f); fclose (f); #ifdef WIN32 #ifdef _MSC_VER remove ("maildb"); #else unlink ("maildb"); #endif #endif if (rename (tmpfl, "maildb") < 0) perror (tmpfl); } else perror (tmpfl); #endif #endif } void panic (const char *message) { char panicfile[2048]; FILE *f; int i; fprintf (stderr, "PANIC: %s\n", message); report (); /* turn off signals */ for (i = 0; i < NSIG; i++) { signal (i, SIG_IGN); } /* shut down interface */ emergency_shutdown (); /* dump panic file */ sprintf (panicfile, "%s.PANIC", dumpfile); if ((f = fopen (panicfile, "wb")) == NULL) { perror ("CANNOT OPEN PANIC FILE, YOU LOSE:"); WIN32CLEANUP _exit (135); } else { fprintf (stderr, "DUMPING: %s\n", panicfile); db_write (f); fclose (f); fprintf (stderr, "DUMPING: %s (done)\n", panicfile); WIN32CLEANUP _exit (136); } } void dump_database (void) { epoch++; fprintf (stderr, "DUMPING: %s.#%d#\n", dumpfile, epoch); dump_database_internal (); fprintf (stderr, "DUMPING: %s.#%d# (done)\n", dumpfile, epoch); } #ifndef WIN32 static int reaper (void) { int stat; while (wait3 (&stat, WNOHANG, 0) > 0); return 0; } #endif void fork_and_dump (void) { #ifndef WIN32 int child; #endif epoch++; fprintf (stderr, "CHECKPOINTING: %s.#%d#\n", dumpfile, epoch); #ifndef WIN32 #ifndef NO_FORK #ifdef USE_VFORK raw_broadcast (0, "GAME: Dumping. The game will freeze for a few minutes."); child = vfork (); #else /* USE_VFORK */ child = fork (); #endif /* USE_VFORK */ #else /* NO FORK */ raw_broadcast (0, "GAME: Dumping. The game will freeze for a few minutes."); child = 0; #endif /* NO_FORK */ if (child == 0) { /* in the child */ #endif // WIN32 dump_database_internal (); #ifndef WIN32 #ifndef NO_FORK _exit (0); /* !!! */ #endif /* NO_FORK */ } else if (child < 0) { perror ("fork_and_dump: fork()"); } #endif // WIN32 } static void do_restart (void) { dbref thing; ATTR *s; for (thing = 0; thing < db_top; thing++) if (!(db[thing].flags & GOING) && (s = atr_get (thing, "STARTUP"))) { char *r = safe_uncompress (s->value); parse_que (thing, r, thing); free (r); } } int init_game (const char *infile, const char *outfile) { FILE *f; int a; depth = 0; for (a = 0; a < 10; a++) wptr[a] = NULL; #ifdef DBCOMP if ((f = (FILE*)popen (tprintf ("gzip -d < %s", infile), "r")) == NULL) return -1; #else if ((f = fopen (infile, "rb")) == NULL) return -1; #endif /* ok, read it in */ fprintf (stderr, "LOADING: %s\n", infile); printf ("READING...\n"); fflush (stdout); if (db_read (f) < 0) { fprintf (stderr, "ERROR LOADING\n"); return -1; } printf ("READ\n"); fflush (stdout); fprintf (stderr, "LOADING: %s (done)\n", infile); /* everything ok */ #ifdef DBCOMP pclose (f); #else fclose (f); #endif #ifdef USE_MAILER /* read mail database */ #ifdef DBCOMP if ((f = (FILE*)popen ("gzip -d <maildb.Z", "r")) == NULL) mail_init (); #else if ((f = fopen ("maildb", "rb")) == NULL) mail_init (); #endif /* okay, read it in */ else { fprintf (stderr, "LOADING: maildb.Z\n"); printf ("READING...\n"); fflush (stdout); load_mail (f); printf ("READ\n"); fflush (stdout); fprintf (stderr, "LOADING: maildb.Z (done)\n"); } /* everything okay */ #ifdef DBCOMP pclose (f); #else fclose (f); #endif #endif /* USE_MAILER */ #ifndef WIN32 /* initialize random number generator */ OS_SRAND (getpid ()); #endif /* set up dumper */ strcpy (dumpfile, outfile); init_timer (); #ifndef WIN32 signal (SIGCHLD, (void *) reaper); #endif /* everything else ok restart all robots */ do_restart (); return 0; } /* * use this only in process_command */ #define Matched(string) { if(!string_prefix((string), command)) goto bad; } /* the two versions of argument parsing */ static char *do_argtwo (dbref player, char *rest, dbref cause, char *buff) { exec (&rest, buff, player, cause, 0); return (buff); } static char **do_argbee (dbref player, char *rest, dbref cause, char **arge, char *buff) { int a; char *p; char tbuf1[BUFFER_LEN]; for (a = 1; a < MAX_ARG; a++) { if (arge[a]) { free ((char *) arge[a]); #ifdef MEM_CHECK del_check ("process_comm_args"); #endif } p = parse_up (&rest, ','); if (p) { strcpy ((arge[a] = (char *) malloc (strlen (p) + 1)), p); #ifdef MEM_CHECK add_check ("process_comm_args"); #endif } else arge[a] = NULL; } /* rest of delimiters are ,'s */ for (a = 1; a < MAX_ARG; a++) if (arge[a]) { strcpy (tbuf1, arge[a]); p = tbuf1; exec (&p, buff, player, cause, 0); free ((char *) arge[a]); strcpy ((arge[a] = (char *) malloc (strlen (buff) + 1)), buff); } return (arge); } #define arg2 do_argtwo(player,rest,cause,buff) #define argv do_argbee(player,rest,cause,arge,buff) void process_command (dbref player, char *command, dbref cause) { char *arg1; int a; char *q; /* utility */ char *p; /* utility */ char *r; char buff[BUFFER_LEN], buff2[BUFFER_LEN], buff3[BUFFER_LEN]; char *arge[MAX_ARG]; /* pointers to arguments (null for empty) */ char unp[BUFFER_LEN]; /* unparsed command */ char oldarg1[BUFFER_LEN]; char *rest; /* general form command arg0=arg1,arg2...arg10 */ int gagged = 0; char temp[BUFFER_LEN]; /* utility */ int i; /* utility */ for (a = 0; a < MAX_ARG; a++) arge[a] = NULL; depth = 0; if (command == 0) { fprintf (stderr, "ERROR: No command!!!"); return; } /* just to have fun, let's reinit the random number gen (with the time) */ OS_SRAND ((int) time ((time_t *) 0)); if (God (player) && !God (cause)) return; /* robustify player */ if ((player < 0) || (player >= db_top)) { fprintf (stderr, "ERROR: bad player %d in process_command\n", player); return; } gagged = IS (db[player].owner, TYPE_PLAYER, PLAYER_GAGGED); /* Access the player */ Access (player); if ((db[player].flags & GOING) || ((Typeof (player) != TYPE_PLAYER) && (db[player].flags & HALT))) { notify (db[player].owner, tprintf ("Attempt to execute command by halted object #%d", player)); return; } /* The following check is removed due to a security hole it causes! */ /* if player is an exit or room execute command as owner */ /* if ((Typeof(player) == TYPE_ROOM) || (Typeof(player) == TYPE_EXIT)) player = db[player].owner; */ speaker = player; #ifdef LOG_COMMANDS fprintf (stderr, "COMMAND from %s(%d) in %s(%d): %s\n", (player == NOTHING ? "NOTHING" : db[player].name), player, (db[player].location == NOTHING ? "NOTHING" : db[db[player].location].name), db[player].location, command); #endif /* LOG_COMMANDS */ /* log all commands from suspect players */ if (Suspect (player)) { fprintf (stderr, "SUSPECT %s(#%d) in %s(#%d): %s\n", (player == NOTHING ? "NOTHING" : db[player].name), player, (db[player].location == NOTHING ? "NOTHING" : db[db[player].location].name), db[player].location, command); } /* eat leading whitespace */ while (*command && isspace ((int)*command)) command++; /* eat extra white space */ q = p = command; while (*p) { /* scan over word */ while (*p && !isspace ((int)*p)) *q++ = *p++; /* smash spaces */ while (*p && isspace ((int)*++p)); if (*p) *q++ = ' '; /* add a space to separate next word */ } /* terminate */ *q = '\0'; /* important home checking comes first! */ if (strcmp (command, "home") == 0) { if (Typeof (player) == TYPE_EXIT || Typeof (player) == TYPE_ROOM) return; do_move (player, command, 0); return; } if (!gagged && try_force (player, command)) return; /* check for single-character commands */ if (*command == SAY_TOKEN && !gagged) { do_say (player, command + 1, NULL); } else if (*command == POSE_TOKEN && !gagged) { do_pose (player, command + 1, NULL, 0); } else if (*command == SEMI_POSE_TOKEN && !gagged) { do_pose (player, command + 1, NULL, 1); /* now check if command is an exact match for an exit in the room */ } else if (can_move (player, command)) { if (Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) return; do_move (player, command, 0); } else { strcpy (unp, command); /* parse arguments */ /* find arg1 */ /* move over command word */ for (arg1 = command; *arg1 && !isspace ((int)*arg1); arg1++); /* truncate command */ if (*arg1) *arg1++ = '\0'; /* move over spaces */ while (*arg1 && isspace ((int)*arg1)) arg1++; r = parse_up (&arg1, '='); /* first delimiter is ='s */ if (r) { if (arge[0]) { free ((char *) arge[0]); #ifdef MEM_CHECK del_check ("process_comm_args"); #endif } strcpy ((arge[0] = (char *) malloc (strlen (r) + 1)), r); #ifdef MEM_CHECK add_check ("process_comm_args"); #endif } rest = arg1; /* either arg2 or argv */ if (arge[0]) { /* Let's unfutz the news/help commands, shall we? */ strcpy (oldarg1, arge[0]); strcpy (buff3, arge[0]); r = buff3; exec (&r, buff2, player, cause, 0); free ((char *) arge[0]); strcpy ((arge[0] = (char *) malloc (strlen (r) + 1)), r); } else { oldarg1[0] = '\0'; } arg1 = ((char *) arge[0]) ? (char *) buff2 : (char *) ""; if (!gagged && test_set (player, command, arg1, arg2)) { /* let's free up all that nice memory, shall we? */ for (a = 0; a < MAX_ARG; a++) { if (arge[a]) { free ((char *) arge[a]); #ifdef MEM_CHECK del_check ("process_comm_args"); #endif } } return; } switch (command[0]) { case '@': switch (command[1]) { case 'a': case 'A': if (!string_compare (command, "@allhalt")) { do_allhalt (player); break; } switch (command[2]) { #ifdef QUOTA case 'l': case 'L': Matched ("@allquota"); do_allquota (player, arg1); break; #endif /* QUOTA */ case 't': case 'T': if (string_prefix ("@atrlock", command)) { do_atrlock (player, arg1, arg2); } else { Matched ("@atrchown"); do_atrchown (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': switch (command[3]) { case 'o': case 'O': if (!string_compare (command, "@chownall")) { do_chownall (player, arg1, arg2); break; } else { if (gagged) break; Matched ("@chown"); do_chown (player, arg1, arg2); break; } case 'z': case 'Z': if (!string_compare (command, "@chzoneall")) { do_chzoneall (player, arg1, arg2); break; } else { if (gagged) break; Matched ("@chzone"); do_chzone (player, arg1, arg2); break; } } break; case 'o': case 'O': Matched ("@config"); do_config (player); break; case 'r': case 'R': if (gagged) break; Matched ("@create"); do_create (player, arg1, atol (arg2)); break; case 'l': case 'L': if (gagged) break; Matched ("@clone"); do_clone (player, arg1); break; default: goto bad; } break; case 'd': case 'D': /* dbck, dig, or dump */ switch (command[2]) { #ifdef DESTROY case 'b': case 'B': Matched ("@dbck"); do_dbck (player); break; #endif case 'E': case 'e': switch (command[3]) { case 'c': case 'C': Matched ("@decompile"); do_decompile (player, arg1); break; #ifdef DESTROY case 's': case 'S': Matched ("@destroy"); do_destroy (player, arg1, 0); break; #endif /* DESTROY */ default: goto bad; } break; case 'i': case 'I': if (gagged) break; Matched ("@dig"); do_dig (player, arg1, argv); break; case 'o': case 'O': switch (command[3]) { #ifdef AT_DOING case 'i': case 'I': if (gagged) break; if (Typeof (player) != TYPE_PLAYER) break; Matched ("@doing"); do_doing (player, arg1, arg2); break; #endif case 'l': case 'L': Matched ("@dolist"); do_dolist (player, arg1, arg2, cause); break; } break; case 'u': case 'U': Matched ("@dump"); do_dump (player); break; default: goto bad; } break; case 'E': case 'e': switch (command[2]) { case 'd': case 'D': if (gagged) break; Matched ("@edit"); do_edit (player, arg1, argv); break; case 'l': case 'L': if (gagged) break; Matched ("@elock"); do_lock (player, arg1, arg2, ENTERLOCK); break; case 'm': case 'M': if (gagged) break; Matched ("@emit"); do_emit (player, arg1, arg2); break; case 'n': case 'N': if (gagged) break; Matched ("@entrances"); do_entrances (player, arg1); break; case 'u': case 'U': if (gagged) break; Matched ("@eunlock"); do_unlock (player, arg1, ENTERLOCK); break; default: goto bad; } break; case 'F': case 'f': /* find, or force */ switch (command[2]) { case 'i': case 'I': if (gagged) break; Matched ("@find"); do_find (player, arg1); break; case 'o': case 'O': if (gagged) break; Matched ("@force"); do_force (player, arg1, arg2); break; default: goto bad; } break; case 'g': case 'G': if (gagged) break; Matched ("@gedit"); do_gedit (player, arg1, argv); break; case 'h': case 'H': /* halt */ Matched ("@halt"); do_halt1 (player, arg1, arg2); break; case 'l': case 'L': /* lock or link */ switch (command[2]) { case 'e': case 'E': if (gagged) break; Matched ("@lemit"); do_lemit (player, arg1, arg2); break; case 'i': case 'I': if (gagged) break; if (string_prefix ("@link", command)) { do_link (player, arg1, arg2); break; } else { Matched ("@listmotd"); do_motd (player, 3, "", ""); break; } case 'o': case 'O': if (gagged) break; if (string_prefix ("@login", command)) { do_login (player, arg1); break; } else { Matched ("@lock"); do_lock (player, arg1, arg2, BASICLOCK); break; } default: goto bad; } break; case 'm': case 'M': /* @mail, @motd */ switch (command[2]) { #ifdef USE_MAILER case 'a': case 'A': if (gagged) break; Matched ("@mail"); do_mail (player, arg1, arg2); break; #endif case 'o': case 'O': if (gagged) break; Matched ("@motd"); do_motd (player, 1, arg1, arg2); break; default: goto bad; } break; case 'n': case 'N': /* @name, @newpassword */ switch (command[2]) { case 'a': case 'A': if (gagged) break; Matched ("@name"); do_name (player, arg1, arg2); break; case 'e': case 'E': if (strcmp (command, "@newpassword")) goto bad; do_newpassword (player, arg1, arg2); break; #ifdef DESTROY case 'u': if (gagged) break; Matched ("@nuke"); do_destroy (player, arg1, 1); break; #endif default: goto bad; } break; case 'o': case 'O': /* @oemit, @open */ switch (command[2]) { case 'e': case 'E': if (gagged) break; Matched ("@oemit"); do_oemit (player, arg1, arg2); break; case 'p': case 'P': if (gagged) break; Matched ("@open"); do_open (player, arg1, argv); break; default: goto bad; } break; case 'p': case 'P': switch (command[2]) { case 'a': case 'A': Matched ("@password"); do_password (player, arg1, arg2); break; #ifdef WCREAT case 'C': case 'c': Matched ("@pcreate"); do_pcreate (player, arg1, arg2); break; #endif case 'E': case 'e': if (gagged) break; Matched ("@pemit"); do_pemit (player, arg1, arg2); break; case 'O': case 'o': switch (command[3]) { case 'l': case 'L': Matched ("@poll"); do_poll (player, arg1, arg2); break; case 'o': case 'O': if (strcmp (command, "@poor")) goto bad; do_poor (player, arg1); break; default: goto bad; } break; case 'S': case 's': Matched ("@ps"); do_queue (player, arg1); break; #ifdef DESTROY case 'u': case 'U': Matched ("@purge"); do_purge (player); break; #endif /* DESTROY */ default: goto bad; } break; #ifdef QUOTA case 'q': case 'Q': Matched ("@quota"); do_quota (player, arg1, ""); break; #endif /* QUOTA */ case 'r': case 'R': switch (command[2]) { case 'e': case 'E': if (gagged) break; if (string_prefix ("@remit", command)) { do_remit (player, arg1, arg2); } else { Matched ("@rejectmotd"); do_motd (player, 4, arg1, arg2); } break; #ifdef ROYALTY_FLAG case 'w': case 'W': if (string_prefix ("@rwall", command)) { do_wizwall (player, arg1, arg2, 1, 1); } else if (string_prefix ("@rwallpose", command)) { do_wizwall (player, arg1, arg2, 1, 2); } else if (string_prefix ("@rwallemit", command)) { do_wizwall (player, arg1, arg2, 1, 3); } else goto bad; break; #endif } break; case 's': case 'S': /* set, shutdown, success */ switch (command[2]) { 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': if (gagged) break; Matched ("@set"); do_set (player, 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': Matched ("@stats"); do_stats (player, arg1); break; case 'w': case 'W': switch (command[3]) { case 'e': case 'E': Matched ("@sweep"); do_sweep (player, arg1); break; case 'i': case 'I': if (gagged) break; Matched ("@switch"); do_switch (player, arg1, argv, cause); break; default: goto bad; } break; #ifdef QUOTA case 'q': case 'Q': Matched ("@squota"); do_quota (player, arg1, arg2); break; #endif /* QUOTA */ default: goto bad; } break; case 't': case 'T': switch (command[2]) { case 'e': case 'E': if (gagged) break; Matched ("@teleport"); do_teleport (player, arg1, arg2); break; case 'r': case 'R': if (gagged) break; Matched ("@trigger"); do_trigger (player, arg1, argv); break; case 'O': case 'o': if (strcmp (command, "@toad")) goto bad; do_toad (player, arg1); break; default: goto bad; } break; case 'u': case 'U': switch (command[2]) { case 'l': case 'L': if (gagged) break; Matched ("@ulock"); do_lock (player, arg1, arg2, USELOCK); break; case 'n': case 'N': switch (command[4]) { case 'i': case 'I': if (gagged) break; Matched ("@unlink"); do_unlink (player, arg1); break; case 'o': case 'O': if (gagged) break; Matched ("@unlock"); do_unlock (player, arg1, BASICLOCK); break; default: goto bad; } break; case 's': case 'S': if (gagged) break; Matched ("@use-does"); sprintf (buff3, "%s/does", arg1); do_trigger (player, buff3, argv); break; case 'u': case 'U': if (gagged) break; Matched ("@uunlock"); do_unlock (player, arg1, USELOCK); break; default: goto bad; } break; case 'v': case 'V': if (string_prefix ("@version", command)) { do_version (player); } break; case 'w': case 'W': switch (command[2]) { case 'a': case 'A': if (string_prefix ("@wait", command)) { wait_que (player, atoi (arg1), arg2, cause); } else if (string_prefix ("@wall", command)) { Matched ("@wall"); do_wall (player, arg1, arg2, 1); } else if (string_prefix ("@wallpose", command)) { do_wall (player, arg1, arg2, 2); } else if (string_prefix ("@wallemit", command)) { do_wall (player, arg1, arg2, 3); } else goto bad; break; #ifdef PLAYER_LOCATE case 'h': case 'H': if (gagged) break; Matched ("@whereis"); do_whereis (player, arg1); break; #endif /* PLAYER_LOCATE */ case 'i': case 'I': if (string_prefix ("@wizwall", command)) { do_wizwall (player, arg1, arg2, 0, 1); } else if (string_prefix ("@wizmotd", command)) { do_motd (player, 2, arg1, arg2); } else if (string_prefix ("@wizpose", command)) { do_wizwall (player, arg1, arg2, 0, 2); } else if (string_prefix ("@wizemit", command)) { do_wizwall (player, arg1, arg2, 0, 3); } else goto bad; break; default: goto bad; } break; case 'z': case 'Z': if (gagged) break; Matched ("@zemit"); do_zemit (player, arg1, arg2); break; default: goto bad; } break; case 'b': case 'B': Matched ("brief"); do_examine (player, arg1, 1); break; case 'd': case 'D': if (Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) break; Matched ("drop"); do_drop (player, arg1); break; case 'e': case 'E': switch (command[1]) { case 'X': case 'x': case '\0': Matched ("examine"); do_examine (player, arg1, 0); break; case 'N': case 'n': if (Typeof (player) == TYPE_EXIT || Typeof (player) == TYPE_ROOM) break; 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': if (gagged || Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) break; Matched ("get"); do_get (player, arg1); break; case 'i': case 'I': if (gagged) break; Matched ("give"); do_give (player, arg1, arg2); break; case 'o': case 'O': if (Typeof (player) == TYPE_EXIT || Typeof (player) == TYPE_ROOM) break; Matched ("goto"); do_move (player, arg1, 0); break; case 'r': case 'R': if (gagged) break; Matched ("gripe"); do_gripe (player, arg1, arg2); break; default: goto bad; } break; case 'h': case 'H': Matched ("help"); do_help (player, oldarg1); break; case 'i': case 'I': Matched ("inventory"); do_inventory (player); break; case 'k': case 'K': if (gagged) break; Matched ("kill"); do_kill (player, arg1, atol (arg2), 0); break; 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': if (Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) break; Matched ("leave"); do_leave (player); break; default: goto bad; } break; case 'm': case 'M': if (Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) break; Matched ("move"); do_move (player, arg1, 0); break; case 'n': case 'N': /* news */ if (string_compare (command, "news")) goto bad; do_news (player, oldarg1); break; case 'p': case 'P': if (gagged) break; Matched ("page"); do_page (player, arg1, arg2); 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': if (gagged) break; Matched ("say"); do_say (player, arg1, arg2); break; case 'c': case 'C': Matched ("score"); do_score (player); break; case 'l': case 'L': Matched ("slay"); do_kill (player, arg1, 0, 1); break; default: goto bad; } break; case 't': case 'T': switch (command[1]) { case 'a': case 'A': if (gagged || Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) break; Matched ("take"); do_get (player, arg1); break; case 'h': case 'H': if (Typeof (player) == TYPE_ROOM || Typeof (player) == TYPE_EXIT) break; Matched ("throw"); do_drop (player, arg1); break; default: goto bad; } break; case 'w': case 'W': if (gagged) break; Matched ("whisper"); do_whisper (player, arg1, arg2); break; case 'u': case 'U': if (gagged) break; Matched ("use"); do_use (player, arg1); break; default: bad: /* try matching enter aliases */ if ((i = alias_list_check (db[getloc (player)].contents, unp, "EALIAS")) != -1) { sprintf (temp, "#%d", i); do_enter (player, temp); return; } /* if that didn't work, try matching leave aliases */ if ((Typeof (db[player].location) != TYPE_ROOM) && (quick_alias_check (db[player].location, unp, "LALIAS"))) { do_leave (player); return; } /* try matching user defined functions before chopping */ a = 0; if (!gagged) { if (getloc (player) != NOTHING) { a += list_check (db[getloc (player)].contents, player, '$', ':', unp); if (getloc (player) != player) a += atr_comm_match (getloc (player), player, '$', ':', unp); } if (getloc (player) != player) a += list_check (db[player].contents, player, '$', ':', unp); /* try matching commands on area zone object if nothing is matched */ if ((!a) && (getzone (db[player].location) != NOTHING)) a += atr_comm_match (getzone (db[player].location), player, '$', ':', unp); /* try matching commands on your zone object if nothing is matched */ if ((!a) && (getzone (player) != NOTHING) && (getzone (db[player].location) != getzone (player))) a += atr_comm_match (getzone (player), player, '$', ':', unp); #ifdef DO_GLOBALS /* check global exits only if no other commands are matched */ if ((!a) && (getloc (player) != MASTER_ROOM)) { if (global_exit (player, unp)) { if ((Typeof (player) == TYPE_ROOM) || (Typeof (player) == TYPE_EXIT)) return; else { do_move (player, unp, 1); return; } } else /* global user-defined commands checked if all else fails. */ /* May match more than one command in the master room. */ a += list_check (db[MASTER_ROOM].contents, player, '$', ':', unp); } #endif } if (!a) { notify (player, "Huh? (Type \"help\" for help.)"); #ifdef LOG_FAILED_COMMANDS if (!controls (player, getloc (player)) { fprintf (stderr, "HUH from %s(%d) in %s(%d)[%s]: %s %s\n", db[player].name, player, db[getloc (player)].name, getloc (player); db[db[getloc (player)].owner].name, command, reconstruct_message (arg1, arg2));} #endif /* LOG_FAILED_COMMANDS */ } break;} } for (a = 0; a < MAX_ARG; a++) { if (arge[a]) { free ((char *) arge[a]); #ifdef MEM_CHECK del_check ("process_comm_args"); #endif arge[a] = NULL; } } } /* match a list of things */ static int list_check (dbref thing, dbref player, int type, int end, char *str) { int match = 0; while (thing != NOTHING) { if (atr_comm_match (thing, player, type, end, str)) match = 1; thing = db[thing].next; } return (match); } static int alias_list_check (dbref thing, const char *command, char *type) { ATTR * a; char alias[BUFFER_LEN]; while (thing != NOTHING) { a = atr_get (thing, type); if (a) { strcpy (alias, uncompress (a->value)); if (!string_compare (alias, command)) return thing; /* matched an alias */ } thing = db[thing].next; } return -1; } static int quick_alias_check (dbref loc, const char *command, char *type) { ATTR * a; char alias[BUFFER_LEN]; a = atr_get (loc, type); if (a) { strcpy (alias, uncompress (a->value)); return (!string_compare (alias, command)); } else return 0; } int Hearer (dbref thing) { ALIST * ptr; if (((Typeof (thing) == TYPE_PLAYER) && (db[thing].flags & PLAYER_CONNECT)) || ((Typeof (thing) == TYPE_THING) && (db[thing].flags & THING_PUPPET))) return (1); for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) { if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), "LISTEN")) return 1; } return (0); } int Commer (dbref thing) { ALIST * ptr; for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) { if (!AL_BAD (ptr)) { if (*AL_STR (ptr) == '$') return (1); } } return (0); } int Listener (dbref thing) { ALIST * ptr; for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) { if (!AL_BAD (ptr)) { if (*AL_STR (ptr) == '^') return (1); } } return (0); } static void do_poor (dbref player, char *arg1) { int amt = atoi (arg1); dbref a; if (!God (player)) return; for (a = 0; a < db_top; a++) if (Typeof (a) == TYPE_PLAYER) s_Pennies (a, amt); } static void do_version (dbref player) { notify (player, tprintf ("The code running is %s", VERSION)); } static void do_dolist (dbref player, char *inlist, char *command, dbref cause) { char *list, *first, *rest, *fix1, *fix2; char buff[BUFFER_LEN], tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN]; tbuf2[0] = tbuf1[0] = '\0'; strcpy (tbuf2, inlist); strcpy (tbuf1, pronoun_substitute (cause, tbuf2, player)); list = tbuf1; while (first = parse_up (&list, ' ')) { fix1 = buff; fix2 = command; while (*fix2) { rest = first; while (*fix2 && (*fix2 != NUMBER_TOKEN)) *fix1++ = *fix2++; if ((*fix2 == NUMBER_TOKEN) && (*(fix2 + 1) == NUMBER_TOKEN)) { fix2++; fix2++; while (rest && *rest) *fix1++ = *rest++; } else *fix1++ = *fix2++; } *fix1 = '\0'; strcpy (tbuf2, pronoun_substitute (cause, buff, player)); parse_que (player, tbuf2, cause); } } static void do_config (dbref player) { notify (player, "----- MUSH CONFIGURATION -----"); #ifdef RESTRICTED_BUILDING #ifdef FREE_OBJECTS notify (player, "Players without a BUILDER bit can only create objects."); #else notify (player, "Players without a BUILDER bit cannot build anything."); #endif #endif #ifdef QUOTA notify (player, "Quota restrictions are in effect."); #endif #ifdef LOG_COMMANDS notify (player, "All commands are being logged."); #endif #ifdef LOG_FAILED_COMMANDS notify (player, "Commands which produce a " Huh ? " are being logged."); #endif #ifdef NO_FORK notify (player, "Forking is disabled. Game will freeze during dumps."); #endif #ifdef USE_MAILER notify (player, "The built-in MUSH mailing system is being used."); #endif #ifdef LOCKOUT notify (player, "Site lockout is enabled."); #endif #ifdef WCREAT notify (player, "Player registration is in effect."); #endif #ifdef DESTROY notify (player, "Object recycling is enabled."); #endif #ifdef FLAGS_ON_EXAMINE notify (player, "Expanded flag list is shown on examines."); #endif #ifdef FULL_INVIS notify (player, "Dark players/objects show up as Someone/Something."); #endif #ifdef PLAYER_LOCATE notify (player, "The location of players not set UNFINDABLE can be found."); #endif #ifdef AT_DOING notify (player, "Doing polls are enabled."); #endif #ifdef ROYALTY_FLAG notify (player, "The ROYALTY flag is enabled."); #endif #ifdef INHERIT_FLAG notify (player, "The INHERIT flag is enabled."); #endif #ifdef DO_GLOBALS notify (player, tprintf ("The master room is #%d.", MASTER_ROOM)); #endif #ifdef GUEST_RESTRICT notify (player, tprintf ("The guest player is #%d.", GUEST_PLAYER)); #endif #ifdef IDLE_TIMEOUT notify (player, tprintf ("The inactivity limit is %d minutes.", INACTIVITY_LIMIT)); #endif notify (player, "----- BUILDING COSTS -----"); notify (player, tprintf ("Object creation....%d", OBJECT_COST)); notify (player, tprintf ("Room creation......%d", ROOM_COST)); notify (player, tprintf ("Exit creation......%d", EXIT_COST)); notify (player, tprintf ("Linking............%d", LINK_COST)); notify (player, tprintf ("Queue deposit......%d", QUEUE_COST)); notify (player, tprintf ("Quota per object...%d", QUOTA_COST)); notify (player, "----- COMMAND COSTS -----"); notify (player, tprintf ("@find..............%d", FIND_COST)); notify (player, tprintf ("page...............%d", PAGE_COST)); notify (player, tprintf ("kill base cost.....%d", KILL_BASE_COST)); notify (player, tprintf ("kill minimum cost..%d", KILL_MIN_COST)); notify (player, tprintf ("kill insurance.....%d", KILL_BONUS)); } #undef Matched