/* This software is Copyright 1989, 1990, 1992, 1993 by various individuals. Please see the accompanying file COPYRIGHT for details. */ #include "config.h" /* Wizard-only and wizard-mostly commands */ #include #include #include #include #include #include #include "db.h" #include "prims.h" #include "match.h" #include "money.h" #include "params.h" #include "externs.h" #include "property.h" #include "times-fix.h" #include "interface.h" extern time_t time_started; time_t now; extern time_t last_checkpoint; void run_global_hook(dbref player, const char *name, const char *tos, struct inst cmd) { dbref x; int i; dbref d; DOLIST(x,DBFETCH(GLOBAL_ENVIRONMENT)->sp.room.exits) { if ((FLAGS(x) & WIZARD) && !strcmp(DBFETCH(x)->name,name)) { SERIAL xser; xser = DBFETCH(x)->serial; for (i=DBFETCH(x)->sp.exit.ndest-1;i>=0;i--) { d = DBFETCH(x)->sp.exit.dest[i]; if (Typeof(d) == TYPE_PROGRAM) { struct inst cmdtmp; copyinst(&cmd,&cmdtmp); interp(player,d,x,tos,cmdtmp); if (DBFETCH(x)->serial != xser) goto out; /* break 2 */ } } } } out:; CLEAR(&cmd); } int no_teleport_zone(dbref loc) { struct propref *pr; while (1) { pr = lookup_property(loc,"_no-teleport",0); if (pr) { propref_done(pr); return(1); } loc = DBFETCH(loc)->location; if (loc == NOTHING) return(0); } } void do_teleport(dbref player, const char *arg1, const char *arg2) { dbref victim; dbref destination; const char *to; struct match_data md; SERIAL playser; /* get victim, destination */ if (*arg2 == '\0') { victim = player; to = arg1; } else { init_match(player,arg1,NOTYPE,&md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_player(&md); victim = noisy_match_result(&md); if (victim == NOTHING) return; to = arg2; } /* get destination */ init_match(player,to,TYPE_PLAYER,&md); match_here(&md); match_home(&md); match_absolute(&md); match_neighbor(&md); match_me(&md); if (Royalty(player)) match_player(&md); if (!controls(player,victim)) { notify(player,"Permission denied."); return; } destination = match_result(&md); switch (destination) { case NOTHING: notify(player,"Send it where?"); break; case AMBIGUOUS: notify(player,"I don't know which destination you mean!"); break; case HOME: switch (Typeof(victim)) { case TYPE_PLAYER: destination = DBFETCH(victim)->sp.player.home; break; case TYPE_THING: destination = DBFETCH(victim)->sp.thing.home; break; case TYPE_ROOM: destination = GLOBAL_ENVIRONMENT; break; case TYPE_PROGRAM: destination = OWNER(victim); break; default: destination = PLAYER_START; break; } /* fall through */ default: switch (Typeof(victim)) { case TYPE_PLAYER: if (!can_link_to(player,NOTYPE,destination)) { notify(player,"Permission denied."); return; } if (Typeof(destination) != TYPE_ROOM) { notify(player,"Bad destination."); break; } if ( !Royalty(player) && !( (player == victim) && (player == OWNER(destination)) && (DBFETCH(destination)->backlinks == 0) ) ) { if (no_teleport_zone(DBFETCH(victim)->location)) { if (victim == player) { notify(player,"You are in a no-teleport zone."); } else { notify(player,"That player is in a no-teleport zone."); } return; } if (no_teleport_zone(destination)) { notify(player,"Target location is in a no-teleport zone."); return; } } notify(victim,"You feel a wrenching sensation..."); playser = DBFETCH(player)->serial; enter_room(victim,destination,DBFETCH(victim)->location); if (DBFETCH(player)->serial != playser) return; notify(player,"Teleported."); break; case TYPE_THING: case TYPE_PROGRAM: if ( (Typeof(destination) != TYPE_ROOM) && (Typeof(destination) != TYPE_PLAYER) ) { notify(player,"Bad destination."); break; } if ( !Royalty(player) && !( ( controls(player,destination) || can_link_to(player,NOTYPE,destination) ) && ( controls(player,victim) || controls(player,DBFETCH(victim)->location) ) ) ) { notify(player,"Permission denied."); break; } if ( (Typeof(destination) == TYPE_ROOM) && (DBFETCH(destination)->sp.room.dropto != NOTHING) && !(FLAGS(destination) & STICKY) ) { switch (Typeof(DBFETCH(destination)->sp.room.dropto)) { case TYPE_PROGRAM: moveto(victim,destination); run_dropto(destination,DBFETCH(destination)->sp.room.dropto,victim); break; case TYPE_ROOM: case TYPE_PLAYER: moveto(victim,DBFETCH(destination)->sp.room.dropto); break; } } else { moveto(victim,destination); } notify(player,"Teleported."); break; case TYPE_ROOM: if (Typeof(destination) != TYPE_ROOM) { notify(player,"Bad destination."); break; } if ( !controls(player,victim) || !can_link_to(player,NOTYPE,destination) || (victim == GLOBAL_ENVIRONMENT) ) { notify(player,"Permission denied."); break; } if (parent_loop_check(victim,destination)) { notify(player,"Parent would create a loop."); break; } moveto(victim,destination); notify(player,"Parent set."); break; default: notify(player,"You can't teleport that."); break; } break; } } void do_force(dbref player, const char *what, char *command) { dbref victim; char buf[BUFFER_LEN]; /* get victim */ victim = lookup_player(what); if (victim == NOTHING) { notify(player,"That player does not exist."); return; } if (! PERMIT_FORCE(player,victim)) { notify(player,"You are not allowed to force that player to do anything."); return; } log_status("FORCED: %s(%d) by %s(%d): %s",NAME(victim),victim,NAME(player),player,command); sprintf(buf,"%s forced you.",NAME(player)); notify(victim,buf); process_command(victim,command); } extern int alarm_interval; extern int total_alarm_miss; extern int total_alarm_done; void do_stats(dbref player, const char *name) { int rooms; int exits; int things; int players; int programs; int daemons; int garbage; int total; int pennies; dbref i; dbref obj; struct dbref_list *drl; char buf[BUFFER_LEN]; struct tms timesstruct; struct match_data md; #ifdef NeXT extern void times(struct tms *); #endif rooms = 0; exits = 0; things = 0; players = 0; programs = 0; daemons = 0; garbage = 0; total = 0; pennies = 0; if (strlen(name)) { init_match(player,name,NOTYPE,&md); match_all_exits(&md); match_neighbor(&md); match_possession(&md); if (Royalty(player)) { match_absolute(&md); match_player(&md); } match_here(&md); match_me(&md); obj = noisy_match_result(&md); if ((obj == AMBIGUOUS) || (obj == NOTHING)) return; if (!Royalty(player) && (player != OWNER(obj))) { notify(player,"Permission denied."); return; } switch (Typeof(obj)) { case TYPE_PLAYER: for (i=obj;i!=NOTHING;i=DBFETCH(i)->nextowned) { total ++; switch (Typeof(i)) { case TYPE_ROOM: rooms ++; break; case TYPE_EXIT: exits ++; break; case TYPE_PROGRAM: programs ++; break; case TYPE_DAEMON: daemons ++; break; case TYPE_GARBAGE: garbage ++; break; case TYPE_THING: things ++; pennies += DBFETCH(i)->sp.thing.value; break; case TYPE_PLAYER: players ++; pennies += DBFETCH(i)->sp.player.pennies; break; } } sprintf(&buf[0],"Stats for %s:\n",NAME(obj)); notify(player,&buf[0]); #define FOO(what) ((what*100.0)/total),what sprintf(&buf[0]," Rooms : (%6.2f%%) %5d Exits : (%6.2f%%) %5d", FOO(rooms),FOO(exits)); notify(player,&buf[0]); sprintf(&buf[0]," Things : (%6.2f%%) %5d Programs: (%6.2f%%) %5d", FOO(things),FOO(programs)); notify(player,&buf[0]); sprintf(&buf[0]," Players : (%6.2f%%) %5d Daemons : (%6.2f%%) %5d", FOO(players),FOO(daemons)); notify(player,&buf[0]); if (TrueWizard(player)) { sprintf(&buf[0]," Garbage : (%6.2f%%) %5d Total : (100.00%%) %5d", FOO(garbage),total); } else { total -= garbage; sprintf(&buf[0]," Total : (100.00%%) %5d", total); } notify(player,&buf[0]); sprintf(&buf[0]," Total %% : (%6.2f%%) %5d", ((total*100.0)/(db_top-1)),db_top-1); notify(player,&buf[0]); #undef FOO notify(player," "); sprintf(&buf[0],"Objects valued at %d %s",pennies,(pennies==1)?PLUR_TRI); notify(player,&buf[0]); break; case TYPE_DAEMON: sprintf(&buf[0],"Launch time: %s",time_format_3(DBFETCH(obj)->sp.daemon.cycles-curtm())); notify(player,&buf[0]); } #ifdef TIMESTAMPS { time_t tt; tt = DBFETCH(obj)->time_created; sprintf(&buf[0],"CREATED : %.24s",asctime(localtime(&tt))); notify(player,&buf[0]); tt = DBFETCH(obj)->time_modified; sprintf(&buf[0],"LAST MODIFIED : %.24s",asctime(localtime(&tt))); notify(player,&buf[0]); tt = DBFETCH(obj)->time_used; sprintf(&buf[0],"LAST USED : %.24s",asctime(localtime(&tt))); notify(player,&buf[0]); } #endif switch (Typeof(obj)) { case TYPE_PLAYER: if (DBFETCH(obj)->sp.player.proglocks) { notify(player,"proglocks:"); for (drl=DBFETCH(obj)->sp.player.proglocks;drl;drl=drl->next) { notify(player,unparse_object(player,drl->object)); } sprintf(&buf[0],"[Proglock Type:%d]\n",DBFETCH(obj)->sp.player.proglock_type); notify(player,&buf[0]); } break; case TYPE_DAEMON: if (DBFETCH(obj)->sp.daemon.proglocks) { notify(player,"proglocks:"); for (drl=DBFETCH(obj)->sp.daemon.proglocks;drl;drl=drl->next) { notify(player,unparse_object(player,drl->object)); } sprintf(&buf[0],"[Proglock Type:%d]\n",DBFETCH(obj)->sp.daemon.proglock_type); notify(player,&buf[0]); } break; case TYPE_PROGRAM: if (DBFETCH(obj)->sp.program.proglocks) { notify(player,"proglocks:"); for (drl=DBFETCH(obj)->sp.program.proglocks;drl;drl=drl->next) { notify(player,unparse_object(player,drl->object)); } } break; } } else { for (i=0;isp.thing.value; break; case TYPE_PLAYER: players ++; pennies += DBFETCH(i)->sp.player.pennies; break; } } notify(player,"Universe stats:\n"); #define FOO(what) ((what*100.0)/total),what sprintf(&buf[0]," Rooms : (%6.2f%%) %5d Exits : (%6.2f%%) %5d", FOO(rooms),FOO(exits)); notify(player,&buf[0]); sprintf(&buf[0]," Things : (%6.2f%%) %5d Programs: (%6.2f%%) %5d", FOO(things),FOO(programs)); notify(player,&buf[0]); sprintf(&buf[0]," Players : (%6.2f%%) %5d Daemons : (%6.2f%%) %5d", FOO(players),FOO(daemons)); notify(player,&buf[0]); sprintf(&buf[0]," Garbage : (%6.2f%%) %5d Total : (100.00%%) %5d", FOO(garbage),total); notify(player,&buf[0]); #undef FOO notify(player," "); sprintf(&buf[0],"Objects valued at %d %s",pennies,(pennies==1)?PLUR_TRI); notify(player,&buf[0]); notify(player," "); sprintf(&buf[0],"Up since: %.24s",asctime(localtime(&time_started))); notify(player,&buf[0]); if (last_checkpoint == time_started) { sprintf(&buf[0],"Last dump: None since restart"); } else { sprintf(&buf[0],"Last dump: %.24s",asctime(localtime(&last_checkpoint))); } notify(player,&buf[0]); now = curtm(); sprintf(&buf[0],"Time: %.24s",asctime(localtime(&now))); notify(player,&buf[0]); sprintf(&buf[0],"Up time: %s",time_format_1((int)(now-time_started))); notify(player,&buf[0]); notify(player," "); times(×struct); sprintf(&buf[0],"Processor time used:%ld (in seconds)", (timesstruct.tms_utime+(long int)timesstruct.tms_cutime)/CLK_TCK); notify(player,&buf[0]); sprintf(&buf[0],"Daemon refresh rate:%d (in seconds)",alarm_interval); notify(player,&buf[0]); sprintf(&buf[0],"Refreshes:%d Misses:%d",total_alarm_done,total_alarm_miss); notify(player,&buf[0]); } } static void format_time(char *buf, unsigned int sec) { int any; any = 0; if (sec >= 86400) { sprintf(buf,"%dd",sec/86400); buf += strlen(buf); sec %= 86400; any ++; } if ((any && sec) || (sec >= 3600)) { sprintf(buf,"%dh",sec/3600); buf += strlen(buf); sec %= 3600; any ++; } if ((any && sec) || (sec >= 60)) { sprintf(buf,"%dm",sec/60); buf += strlen(buf); sec %= 60; any ++; } if (sec || !any) { sprintf(buf,"%ds",sec); } } void do_config(dbref player) { char buf[BUFFER_LEN]; if (! Royalty(player)) { notify(player,"Permission denied."); return; } notify(player,"Addpennies: " #ifdef ADDPENNIES_UNRESTRICTED "UNRESTRICTED" #endif #ifdef ADDPENNIES_CONSERVING "CONSERVING" #endif #ifdef ADDPENNIES_WIZ_ONLY "WIZ_ONLY" #endif ); notify(player,"DUMP_STYLE = " #if !DUMP(CHANGE_PID) "!" #endif "CHANGE_PID, " #if !DUMP(IN_PARENT) "!" #endif "IN_PARENT, " #if !DUMP(DOUBLE_FORK) "!" #endif "DOUBLE_FORK, " #if !DUMP(VFORK) "!" #endif "VFORK, " #if !DUMP(INLINE) "!" #endif "INLINE"); sprintf(&buf[0],"DUMP_INTERVAL = %d [",DUMP_INTERVAL); format_time(&buf[strlen(&buf[0])],DUMP_INTERVAL); strcat(&buf[0],"]"); #ifdef DUMP_WARNING_INTERVAL sprintf(&buf[strlen(&buf[0])],", DUMP_WARNING_INTERVAL" #ifndef DUMP_WARNING_MSG " (effectless - no DUMP_WARNING_MSG)" #endif " = %d [",DUMP_WARNING_INTERVAL); format_time(&buf[strlen(&buf[0])],DUMP_WARNING_INTERVAL); strcat(&buf[0],"]"); #endif notify(player,&buf[0]); #ifdef DUMP_WARNING_MSG sprintf(&buf[0],"DUMP_WARNING_MSG" #ifndef DUMP_WARNING_INTERVAL " (not used - no DUMP_WARNING_INTERVAL)" #endif ": %s",DUMP_WARNING_MSG); notify(player,&buf[0]); #else notify(player,"No DUMP_WARNING_MSG defined"); #endif #ifdef DUMP_BEGIN_MSG sprintf(&buf[0],"DUMP_BEGIN_MSG: %s",DUMP_BEGIN_MSG); notify(player,&buf[0]); #else notify(player,"No DUMP_BEGIN_MSG defined"); #endif #ifdef DUMP_END_MSG sprintf(&buf[0],"DUMP_END_MSG" #if !DUMP(INLINE) " (not used - !DUMP_INLINE)" #endif ": %s",DUMP_END_MSG); notify(player,&buf[0]); #else notify(player,"No DUMP_END_MSG defined"); #endif notify(player,"defines: " #ifndef DROP_EMPTY_LINES "!" #endif "DROP_EMPTY_LINES, " #ifndef DB_DOUBLING "!" #endif "DB_DOUBLING, " #ifndef HOSTNAMES "!" #endif "HOSTNAMES, " #ifndef REGISTRATION "!" #endif "REGISTRATION,"); notify(player," " #ifndef MUCKER_ALL "!" #endif "MUCKER_ALL, " #ifndef WIZARD_ALL "!" #endif "WIZARD_ALL, " #ifndef RESTRICTED_BUILDING "!" #endif "RESTRICTED_BUILDING, " #ifndef VALIDATE_LISTS "!" #endif "VALIDATE_LISTS,"); notify(player," " #ifndef RESET_LISTS "!" #endif "RESET_LISTS, " #ifndef MUFCONNECTS "!" #endif "MUFCONNECTS, " #ifndef ENABLE_NO_AUTOLOOK "!" #endif "ENABLE_NO_AUTOLOOK"); sprintf(&buf[0],"Initial money = %d",INITIAL_MONEY); notify(player,&buf[0]); } void do_boot(dbref player, const char *name) { dbref victim; char buf[BUFFER_LEN]; struct match_data md; init_match(player,name,TYPE_PLAYER,&md); match_neighbor(&md); match_me(&md); match_absolute(&md); match_player(&md); victim = noisy_match_result(&md); if (victim == NOTHING) victim = lookup_player(name); if (victim == NOTHING) { notify(player,"That player does not exist."); return; } if (Typeof(victim) != TYPE_PLAYER) { notify(player,"You can't boot anything but a player."); return; } if (!PERMIT_BOOT(player,victim)) { notify(player,"You are not allowed boot that player."); return; } else { sprintf(buf,"You have been booted off of the game by %s.",NAME(player)); notify(victim,buf); if (boot_off(victim)) { log_status("BOOTED: %s(%d) by %s(%d)",NAME(victim),victim,NAME(player),player); if (victim != player) { sprintf(buf,"You booted %s off!",NAME(victim)); notify(player,buf); } while (boot_off(victim)) ; } else { sprintf(buf,"%s is not connected.",NAME(victim)); notify(player,buf); } } } void do_toad(dbref player, const char *name, const char *recip) { dbref victim; dbref recipient; dbref stuff; struct dbref_list *linksto; struct dbref_list *drl; char buf[BUFFER_LEN]; victim = lookup_player(name); if (victim == NOTHING) { notify(player,"That player does not exist."); return; } /* GOD_DBREF is untoadable so that there is always a valid recipient. */ if ((victim == GOD_DBREF) || !PERMIT_TOAD(player,victim)) { notify(player,"You are not permitted to toad that player."); return; } if (victim == player) { notify(player,"You can't toad yourself!"); return; } if (! *recip) { recipient = GOD_DBREF; } else { recipient = lookup_player(recip); if (recipient == NOTHING) { notify(player,"That recipient does not exist."); return; } if (recipient == victim) { notify(player,"You can't give the results to the toaded player!"); return; } } if (Typeof(victim) != TYPE_PLAYER) { notify(player,"You can't toad anything but a player!"); return; } if (FLAGS(victim) & KEEP) { notify(player,"That player is set Keep."); return; } if (awake_count(victim) > 0) { notify(player,"That player is currently connected."); notify(player,"(This restriction is a bug workaround and will be fixed eventually!)"); return; } /* chown things to recipient, checking for a sane home location */ /* for object. XXX -- if HOME/inventory handling changes, */ /* please check this code.*/ OWNER(victim) = recipient; for ( stuff = recipient; DBFETCH(stuff)->nextowned != NOTHING; stuff = DBFETCH(stuff)->nextowned ) ; DBFETCH(stuff)->nextowned = victim; for (stuff=victim;stuff!=NOTHING;stuff=DBFETCH(stuff)->nextowned) { DBSTORE(stuff,owner,recipient); if (Typeof(stuff) != TYPE_GARBAGE) DBFETCH(recipient)->sp.player.dbrefs_owned ++; } linksto = 0; while (DBFETCH(victim)->backlinks) { stuff = DBFETCH(victim)->backlinks->object; switch (Typeof(stuff)) { case TYPE_THING: add_backlink(stuff,PLAYER_START); remove_backlinks(stuff,victim); DBSTORE(stuff,sp.thing.home,PLAYER_START); break; case TYPE_EXIT: drl = DBFETCH(victim)->backlinks; DBFETCH(victim)->backlinks = drl->next; drl->next = linksto; linksto = drl; break; case TYPE_ROOM: remove_backlinks(stuff,victim); DBSTORE(stuff,sp.room.dropto,NOTHING); break; default: panic("@toad impossible backlink"); break; } } DBFETCH(victim)->backlinks = linksto; send_contents(victim,HOME); if (DBFETCH(victim)->sp.player.password) { free(DBFETCH(victim)->sp.player.password); DBSTORE(victim,sp.player.password,0); } /* notify people */ sprintf(buf,"You have been turned into a toad by %s!",NAME(player)); notify(victim,buf); sprintf(buf,"You turned %s into a toad!",NAME(victim)); notify(player,buf); log_status("TOADED: %s(%d) by %s(%d)",NAME(victim),victim,NAME(player),player); FLAGS(victim) = TYPE_THING; DBFETCH(victim)->sp.thing.value = 1; delete_player(victim); /* reset name */ sprintf(&buf[0],"a slimy toad named %s",NAME(victim)); free(NAME(victim)); NAME(victim) = dup_string(&buf[0]); DBDIRTY(victim); while (boot_off(victim)) ; sprintf(&buf[0],"%d %d",(int)victim,(int)recipient); run_global_hook(player,"do_toad",&buf[0],makearray(1,makeinst(PROG_STRING,dup_string("@toad")))); } void do_newpassword(dbref player, const char *name, const char *password) { dbref victim; char buf[BUFFER_LEN]; set_last(player,"@newpassword"); victim = lookup_player(name); if (victim == NOTHING) { notify(player,"No such player."); return; } if (!PERMIT_NEWPASSWORD(player,victim)) { notify(player,"You are not allowed to change that player's password."); return; } else if (!ok_password(password)) { notify(player,"Bad password"); } else { if (DBFETCH(victim)->sp.player.password) free(DBFETCH(victim)->sp.player.password); DBSTORE(victim,sp.player.password,make_password(dup_string(password))); notify(player,"Password changed."); sprintf(buf,"Your password has been changed by %s.", NAME(player)); notify(victim,buf); log_status("NEWPASSWORDED: %s(%d) by %s(%d)",NAME(victim),(int)victim,NAME(player),(int)player); } } void do_newpwhash(dbref player, const char *name, const char *password) { dbref victim; char buf[BUFFER_LEN]; set_last(player,"@newpwhash"); victim = lookup_player(name); if (victim == NOTHING) { notify(player,"No such player."); return; } if (!PERMIT_NEWPASSWORD(player,victim)) { notify(player,"You are not allowed to change that player's password."); return; } if (DBFETCH(victim)->sp.player.password) free(DBFETCH(victim)->sp.player.password); DBSTORE(victim,sp.player.password,dup_string(password)); notify(player,"Password hash changed - note, cannot check for validity."); sprintf(buf,"Your password has been changed by %s.",NAME(player)); notify(victim,buf); log_status("NEWPWHASH: %s(%d) by %s(%d)",NAME(victim),(int)victim,NAME(player),(int)player); } void do_pcreate(dbref player, const char *user, const char *password) { dbref newguy; char buf[BUFSIZ]; if (!PERMIT_PCREATE(player)) { notify(player,"Permission denied."); return; } newguy = create_player(user,password); if (newguy == NOTHING) { notify(player,"Create failed."); } else { log_status("PCREATED %s(%d) by %s(%d)",NAME(newguy),(int)newguy,NAME(player),(int)player); sprintf(&buf[0],"Player %s created as object #%d.",user,newguy); notify(player,buf); sprintf(&buf[0],"%d",(int)newguy); run_global_hook(player,"do_pcreate",&buf[0],makearray(1,makeinst(PROG_STRING,dup_string("@pcreate")))); } } int dbref_list_memused(const struct dbref_list *drl) { int n; n = 0; for (;drl;drl=drl->next) n += sizeof(*drl); return(n); } int boolexp_memused(const struct boolexp *e) { if (e == TRUE_BOOLEXP) return(0); switch (e->type) { case BOOLEXP_AND: case BOOLEXP_OR: return(sizeof(*e)+boolexp_memused(e->u.dyad.sub1)+boolexp_memused(e->u.dyad.sub2)); break; case BOOLEXP_NOT: return(sizeof(*e)+boolexp_memused(e->u.monad)); break; case BOOLEXP_OBJ: return(sizeof(*e)+(e->u.obj.param?strlen(e->u.obj.param)+1:0)); break; case BOOLEXP_PROP: return(sizeof(*e)+lockprop_memused(e->u.prop)); break; } return(sizeof(*e)); /* maybe should panic? */ } static int for_list_memused(const struct for_struct *f) { int n; n = 0; for (;f;f=f->next) n += sizeof(*f); return(n); } int framestack_memused(const struct frame *f) { int n; n = 0; for (;f;f=f->next) { n += sizeof(*f) + dbref_list_memused(f->caller) + for_list_memused(f->for_loop); } return(n); } #if 0 static int lines_memused(const struct line *l) { int n; n = 0; for (;l;l=l->next) n += sizeof(*l) + strlen(l->this_line) + 1; return(n); } #endif int inst_memused(const struct inst *i) { switch (i->type) { default: return(sizeof(*i)); break; case PROG_STRING: return(sizeof(*i)+(i->data.string?strlen(i->data.string):0)+1); break; case PROG_PTR: return(sizeof(*i)+sizeof(*i->data.ptr)); break; } } int codevec_memused(const struct inst *cv, int ncv) { int n; n = 0; for (;ncv>0;ncv--,cv++) n += inst_memused(cv); return(n); } int stabvec_memused(const struct stab *sv, int nsv) { int n; n = 0; for (;nsv>0;nsv--,sv++) n += sizeof(*sv) + strlen(sv->name) + 1; return(n); } void do_memused(dbref player, const char *objname) { dbref thing; struct object *o; struct match_data md; int memused; int i; char msg[512]; init_match(player,objname,NOTYPE,&md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_player(&md); thing = noisy_match_result(&md); if (thing == NOTHING) return; if ((thing < 0) || (thing >= db_top)) { notify(player,"Out-of-range dbref: nonexistent"); return; } if (Typeof(thing) == TYPE_GARBAGE) { notify(player,"Garbage - little/no memory used"); return; } if (! controls(player,thing)) { notify(player,"Permission denied."); return; } sprintf(&msg[0],"Memory usage for %s:",unparse_object(player,thing)); notify(player,&msg[0]); o = DBFETCH(thing); notify(player,"For Bytes"); sprintf(&msg[0],"Basic dbref %d",(int)sizeof(struct object)); notify(player,&msg[0]); memused = sizeof(struct object); i = 0; i += strlen(o->name) + 1; i += str_memusage(o->description); i += str_memusage(o->fail_message); i += str_memusage(o->succ_message); i += str_memusage(o->drop_message); i += str_memusage(o->ofail); i += str_memusage(o->osuccess); i += str_memusage(o->odrop); sprintf(&msg[0],"Strings %d",i); notify(player,&msg[0]); memused += i; i = dbref_list_memused(o->backlinks); sprintf(&msg[0],"Backlinks %d",i); notify(player,&msg[0]); memused += i; i = dbref_list_memused(o->backlocks); sprintf(&msg[0],"Backlocks %d",i); notify(player,&msg[0]); memused += i; i = dbref_list_memused(o->backprops); sprintf(&msg[0],"Backprops %d",i); notify(player,&msg[0]); memused += i; i = dbref_list_memused(o->sleepers); sprintf(&msg[0],"Sleepers %d",i); notify(player,&msg[0]); memused += i; i = boolexp_memused(o->key); sprintf(&msg[0],"Lock %d",i); notify(player,&msg[0]); memused += i; i = plist_memused(o->properties); sprintf(&msg[0],"Properties %d",i); notify(player,&msg[0]); memused += i; switch (Typeof(thing)) { case TYPE_ROOM: break; case TYPE_THING: break; case TYPE_EXIT: i = o->sp.exit.ndest * sizeof(dbref); sprintf(&msg[0],"Link-tos %d",i); notify(player,&msg[0]); memused += i; break; case TYPE_PLAYER: i = strlen(o->sp.player.password) + 1; sprintf(&msg[0],"Password %d",i); notify(player,&msg[0]); memused += i; i = framestack_memused(o->sp.player.run); sprintf(&msg[0],"MUF call frames %d",i); notify(player,&msg[0]); memused += i; i = dbref_list_memused(o->sp.player.proglocks); sprintf(&msg[0],"Proglocks %d",i); notify(player,&msg[0]); memused += i; break; case TYPE_PROGRAM: i = dbref_list_memused(o->sp.program.proglocks); sprintf(&msg[0],"Proglocks %d",i); notify(player,&msg[0]); memused += i; #if 0 i = lines_memused(o->sp.program.first); sprintf(&msg[0],"Program text %d",i); notify(player,&msg[0]); memused += i; #else notify(player,"Program text not counted"); #endif if (o->sp.program.codevec) { i = codevec_memused(o->sp.program.codevec,o->sp.program.codesiz); sprintf(&msg[0],"Compiled code %d",i); notify(player,&msg[0]); memused += i; i = stabvec_memused(o->sp.program.stabvec,o->sp.program.stabsiz); sprintf(&msg[0],"Symbol table %d",i); notify(player,&msg[0]); memused += i; } else { notify(player,"Not compiled"); } break; case TYPE_DAEMON: #if 0 i = lines_memused(o->sp.daemon.first); sprintf(&msg[0],"Program text %d",i); notify(player,&msg[0]); memused += i; #else notify(player,"Program text not counted"); #endif i = framestack_memused(o->sp.daemon.run); sprintf(&msg[0],"MUF call frames %d",i); notify(player,&msg[0]); memused += i; i = dbref_list_memused(o->sp.daemon.proglocks); sprintf(&msg[0],"Proglocks %d",i); notify(player,&msg[0]); memused += i; break; case TYPE_GARBAGE: break; } sprintf(&msg[0],"TOTAL %d",memused); notify(player,&msg[0]); } void do_mfilesweep(dbref player) { DIR *d; struct direct *e; long int n; char *cp; char fn[32]; char msg[80]; if (! God(player)) { notify(player,"Permission denied."); return; } d = opendir("muf"); if (d == 0) { notify(player,"Can't open muf directory"); return; } while ((e=readdir(d))) { n = strtol(e->d_name,&cp,10); if ( (e->d_ino == 0) || (cp == e->d_name) || (cp[0] != '.') || (cp[1] != 'm') || cp[2] ) { continue; } sprintf(&fn[0],"muf/%s",e->d_name); if ((n < 0) || (n >= db_top) || (Typeof((dbref)n) != TYPE_PROGRAM)) { if (unlink(&fn[0]) < 0) { sprintf(&msg[0],"Can't remove %s: %s",&fn[0],strerror(errno)); } else { sprintf(&msg[0],"Removed %s",&fn[0]); } notify(player,&msg[0]); } } closedir(d); notify(player,"@mfilesweep done."); } void do_sortprops(dbref player) { if (! God(player)) { notify(player,"Permission denied."); return; } prop_renumber_all(); notify(player,"@sortprops done."); } void do_backprops(dbref player, const char *name) { struct match_data md; dbref obj; struct dbref_list *drl; if (! Wizard(player)) { notify(player,"Permission denied."); return; } init_match(player,name,NOTYPE,&md); match_everything(&md); obj = noisy_match_result(&md); if (obj == NOTHING) return; if ((obj < 0) || (obj >= db_top) || (Typeof(obj) == TYPE_GARBAGE)) { notify(player,"Invalid object."); return; } for (drl=DBFETCH(obj)->backprops;drl;drl=drl->next) { notify(player,unparse_object(player,drl->object)); } notify(player,"@backprops done."); }