/* game.c */ #include <ctype.h> #include <fcntl.h> #include <string.h> #ifdef XENIX #include <sys/signal.h> #else #include <signal.h> #include <sys/wait.h> #endif /* xenix */ #include <sys/time.h> #include <sys/types.h> #include "config.h" #include "db.h" #include "externs.h" #include "interface.h" #include "match.h" #ifdef MEM_CHECK #include "mem_check.h" #endif #ifdef USE_NALLOC #include "nalloc.h" NALLOC *glurp; #endif /* declarations */ char dumpfile[200]; static int epoch = 0; int reserved; int depth = 0; /* excessive recursion prevention */ extern dbref cplr; extern char ccom[]; void fork_and_dump(); void dump_database(); extern void exec(); /* * used to allocate storage for temporary stuff, cleared before command * execution */ void do_dump(player) 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() { 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 void do_purge(player) dbref player; { if (Wizard(player)) { FIX; notify(player, "Purge complete."); } else notify(player, "Sorry, you are a mortal."); } void dest_info(thing, tt) 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(player, msg) 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, 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, '^', ':', msg); /* unlike normal @listen, don't pass the message on */ } /* now check for multi listeners */ } depth--; } void do_shutdown(player) 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."); } } #ifdef XENIX /* rename hack!!! */ 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 tmpfl[2048]; FILE *f; extern int unlink(); sprintf(tmpfl, "%s.#%d#", dumpfile, epoch - 1); unlink(tmpfl); /* nuke our predecessor */ sprintf(tmpfl, "%s.#%d#", dumpfile, epoch); #ifdef DBCOMP if ((f = popen(tprintf("compress >%s", tmpfl), "w")) != NULL) { db_write(f); pclose(f); if (rename(tmpfl, dumpfile) < 0) perror(tmpfl); } else perror(tmpfl); #ifdef USE_MAILER sprintf(tmpfl, "maildb.Z.#%d#", epoch - 1); unlink(tmpfl); sprintf(tmpfl, "maildb.Z.#%d#", epoch); if (mdb_top > 0) if ((f = popen(tprintf("compress >%s", tmpfl), "w")) != NULL) { dump_mail(f); pclose(f); if (rename(tmpfl, "maildb.Z") < 0) perror(tmpfl); } else perror(tmpfl); #endif #else if ((f = fopen(tmpfl, "w")) != NULL) { db_write(f); fclose(f); 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, "w")) != NULL) { db_write(f); fclose(f); if (rename(tmpfl, "maildb") < 0) perror(tmpfl); } else perror(tmpfl); #endif #endif } void panic(message) 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, "w")) == NULL) { perror("CANNOT OPEN PANIC FILE, YOU LOSE:"); _exit(135); } else { fprintf(stderr, "DUMPING: %s\n", panicfile); db_write(f); fclose(f); fprintf(stderr, "DUMPING: %s (done)\n", panicfile); _exit(136); } } void dump_database() { epoch++; fprintf(stderr, "DUMPING: %s.#%d#\n", dumpfile, epoch); dump_database_internal(); fprintf(stderr, "DUMPING: %s.#%d# (done)\n", dumpfile, epoch); } static int reaper() { #ifdef XENIX int status; wait(&status); #else union wait my_stat; while (wait3(&my_stat, WNOHANG, 0) > 0) ; #endif return 0; } void fork_and_dump() { int child; epoch++; fprintf(stderr, "CHECKPOINTING: %s.#%d#\n", dumpfile, epoch); #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 */ close(reserved); /* get that file descriptor back */ #ifdef CONCENTRATOR #ifndef XENIX signal(SIGCHLD, SIG_DFL); #else signal(SIGCLD, SIG_DFL); #endif /* XENIX */ #endif /* CONCENTRATOR */ dump_database_internal(); #ifndef NO_FORK _exit(0); /* !!! */ #else /* NO FORK */ reserved = open("/dev/null", O_RDWR); #ifdef CONCENTRATOR #ifndef XENIX signal(SIGCHLD, (void *) reaper); #else signal(SIGCLD, (void *) reaper); #endif /* XENIX */ #endif /* CONCENTRATOR */ #endif /* NO_FORK */ } else if (child < 0) { perror("fork_and_dump: fork()"); } } void do_restart() { 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(infile, outfile) const char *infile; const char *outfile; { FILE *f; int a; extern void init_timer(); depth = 0; #ifdef USE_NALLOC glurp = na_open(sizeof(char)); #endif for (a = 0; a < 10; a++) wptr[a] = NULL; #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 */ 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 = popen("uncompress <maildb.Z", "r")) == NULL) mail_init(); #else if ((f = fopen("maildb", "r")) == 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 */ /* initialize random number generator */ srandom(getpid()); /* set up dumper */ strcpy(dumpfile, outfile); init_timer(); #ifndef XENIX signal(SIGCHLD, (void *)reaper); #else /* xenix */ signal(SIGCLD, (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 */ 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; char *p; char tbuf1[BUFFER_LEN]; for (a = 1; a < MAX_ARG; a++) { if(arge[a]) { #ifdef USE_NALLOC na_unalloc(glurp, arge[a]); #else free((char *) arge[a]); #endif #ifdef MEM_CHECK del_check("process_comm_args"); #endif } p = parse_up(&rest, ','); if(p) { #ifdef USE_NALLOC strcpy((arge[a] = (char *) na_ualloc(glurp, strlen(p)+1)), p); #else strcpy((arge[a] = (char *)malloc(strlen(p)+1)), p); #endif #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); #ifdef USE_NALLOC na_unalloc(glurp, arge[a]); strcpy((arge[a] = (char *) na_ualloc(glurp, strlen(buff) + 1)), buff); #else free((char *)arge[a]); strcpy((arge[a] = (char *)malloc(strlen(buff)+1)), buff); #endif } return (arge); } #define arg2 do_argtwo(player,rest,cause,buff) #define argv do_argbee(player,rest,cause,arge,buff) void process_command(player, command, cause) 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 */ void do_poor(), do_version(), do_dolist(), do_config(); extern void wait_que(); #ifdef USE_NALLOC na_clear(glurp); #endif 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) */ srandom((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(*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) { 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); } 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++; r = parse_up(&arg1, '='); /* first delimiter is ='s */ if(r) { if(arge[0]) { #ifdef USE_NALLOC na_unalloc(glurp, arge[0]); #else free((char *)arge[0]); #endif #ifdef MEM_CHECK del_check("process_comm_args"); #endif } #ifdef USE_NALLOC strcpy((arge[0] = (char *) na_ualloc(glurp, strlen(r)+1)), r); #else strcpy((arge[0] = (char *)malloc(strlen(r)+1)), r); #endif #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); #ifdef USE_NALLOC na_unalloc(glurp, arge[0]); strcpy((arge[0] = (char *) na_ualloc(glurp, strlen(r) + 1)), r); #else free((char *)arge[0]); strcpy((arge[0] = (char *)malloc(strlen(r)+1)), r); #endif } 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]) { #ifdef USE_NALLOC na_unalloc(glurp, arge[a]); #else free((char *) arge[a]); #endif #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); 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); 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]) { #ifdef USE_NALLOC na_unalloc(glurp, (char *) arge[a]); #else free((char *) arge[a]); #endif #ifdef MEM_CHECK del_check("process_comm_args"); #endif arge[a] = NULL; } } } /* match a list of things */ int list_check(thing, player, type, end, str) dbref thing, player; char type, 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); } int alias_list_check(thing, command, type) 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; } int quick_alias_check(loc, command, type) 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(thing) 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(thing) 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(thing) 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); } void do_poor(player, arg1) 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); } void do_version(player) dbref player; { notify(player,tprintf("The code running is %s",VERSION)); } void do_dolist(player, inlist, command, cause) dbref player, cause; char *inlist, *command; { 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); } } void do_config(player) 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 CONCENTRATOR notify(player, "Concentrator is enabled."); #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