/* $Header: /cvsroot/fbmuck/fbmuck/src/wiz.c,v 1.32 2005/06/06 12:57:17 winged Exp $ */ #include "copyright.h" #include "config.h" /* Wizard-only commands */ #include <stdio.h> #ifndef WIN32 # include <sys/resource.h> #endif #ifndef MALLOC_PROFILING # ifndef HAVE_MALLOC_H # include <stdlib.h> # else # include <malloc.h> # endif #endif #include "db.h" #include "props.h" #include "params.h" #include "tune.h" #include "interface.h" #include "match.h" #include "externs.h" #include "fbstrings.h" void do_teleport(int descr, dbref player, const char *arg1, const char *arg2) { dbref victim; dbref destination; const char *to; struct match_data md; /* get victim, destination */ if (*arg2 == '\0') { victim = player; to = arg1; } else { init_match(descr, player, arg1, NOTYPE, &md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); match_player(&md); if ((victim = noisy_match_result(&md)) == NOTHING) { return; } to = arg2; } /* get destination */ init_match(descr, player, to, TYPE_PLAYER, &md); match_possession(&md); match_me(&md); match_here(&md); match_home(&md); match_absolute(&md); match_registered(&md); if (Wizard(OWNER(player))) { match_neighbor(&md); match_player(&md); } switch (destination = match_result(&md)) { 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 = PLAYER_HOME(victim); if (parent_loop_check(victim, destination)) destination = PLAYER_HOME(OWNER(victim)); break; case TYPE_THING: destination = THING_HOME(victim); if (parent_loop_check(victim, destination)) { destination = PLAYER_HOME(OWNER(victim)); if (parent_loop_check(victim, destination)) { destination = (dbref) 0; } } break; case TYPE_ROOM: destination = GLOBAL_ENVIRONMENT; break; case TYPE_PROGRAM: destination = OWNER(victim); break; default: destination = tp_player_start; /* caught in the next * switch anyway */ break; } default: switch (Typeof(victim)) { case TYPE_PLAYER: if (!controls(player, victim) || !controls(player, destination) || !controls(player, getloc(victim)) || (Typeof(destination) == TYPE_THING && !controls(player, getloc(destination)))) { notify(player, "Permission denied."); break; } if (Typeof(destination) != TYPE_ROOM && Typeof(destination) != TYPE_THING) { notify(player, "Bad destination."); break; } if (!Wizard(victim) && (Typeof(destination) == TYPE_THING && !(FLAGS(destination) & VEHICLE))) { notify(player, "Destination object is not a vehicle."); break; } if (parent_loop_check(victim, destination)) { notify(player, "Objects can't contain themselves."); break; } notify(victim, "You feel a wrenching sensation..."); enter_room(descr, victim, destination, DBFETCH(victim)->location); notify(player, "Teleported."); break; case TYPE_THING: if (parent_loop_check(victim, destination)) { notify(player, "You can't make a container contain itself!"); break; } case TYPE_PROGRAM: if (Typeof(destination) != TYPE_ROOM && Typeof(destination) != TYPE_PLAYER && Typeof(destination) != TYPE_THING) { notify(player, "Bad destination."); break; } if (!((controls(player, destination) || can_link_to(player, NOTYPE, destination)) && (controls(player, victim) || controls(player, DBFETCH(victim)->location)))) { notify(player, "Permission denied."); break; } /* check for non-sticky dropto */ if (Typeof(destination) == TYPE_ROOM && DBFETCH(destination)->sp.room.dropto != NOTHING && !(FLAGS(destination) & STICKY)) destination = DBFETCH(destination)->sp.room.dropto; if (tp_thing_movement && (Typeof(victim) == TYPE_THING)) { enter_room(descr, victim, destination, DBFETCH(victim)->location); } 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; case TYPE_GARBAGE: notify(player, "That object is in a place where magic cannot reach it."); break; default: notify(player, "You can't teleport that."); break; } break; } return; } int blessprops_wildcard(dbref player, dbref thing, const char *dir, const char *wild, int blessp) { char propname[BUFFER_LEN]; char wld[BUFFER_LEN]; char buf[BUFFER_LEN]; char buf2[BUFFER_LEN]; char *ptr, *wldcrd = wld; PropPtr propadr, pptr; int i, cnt = 0; int recurse = 0; strcpy(wld, wild); i = strlen(wld); if (i && wld[i - 1] == PROPDIR_DELIMITER) strcatn(wld, sizeof(wld), "*"); for (wldcrd = wld; *wldcrd == PROPDIR_DELIMITER; wldcrd++) ; if (!strcmp(wldcrd, "**")) recurse = 1; for (ptr = wldcrd; *ptr && *ptr != PROPDIR_DELIMITER; ptr++) ; if (*ptr) *ptr++ = '\0'; propadr = first_prop(thing, (char *) dir, &pptr, propname); while (propadr) { if (equalstr(wldcrd, propname)) { snprintf(buf, sizeof(buf), "%s%c%s", dir, PROPDIR_DELIMITER, propname); if (!Prop_System(buf) && ((!Prop_Hidden(buf) && !(PropFlags(propadr) & PROP_SYSPERMS)) || Wizard(OWNER(player)))) { if (!*ptr || recurse) { cnt++; if (blessp) { set_property_flags(thing, buf, PROP_BLESSED); snprintf(buf2, sizeof(buf2), "Blessed %s", buf); } else { clear_property_flags(thing, buf, PROP_BLESSED); snprintf(buf2, sizeof(buf2), "Unblessed %s", buf); } notify(player, buf2); } if (recurse) ptr = "**"; cnt += blessprops_wildcard(player, thing, buf, ptr, blessp); } } propadr = next_prop(pptr, propadr, propname); } return cnt; } void do_unbless(int descr, dbref player, const char *what, const char *propname) { dbref victim; struct match_data md; char buf[BUFFER_LEN]; int cnt; if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) { notify(player, "Only Wizard players may use this command."); return; } if (!propname || !*propname) { notify(player, "Usage is @unbless object=propname."); return; } /* get victim */ init_match(descr, player, what, NOTYPE, &md); match_everything(&md); if ((victim = noisy_match_result(&md)) == NOTHING) { return; } if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } cnt = blessprops_wildcard(player, victim, "", propname, 0); snprintf(buf, sizeof(buf), "%d propert%s unblessed.", cnt, (cnt == 1)? "y" : "ies"); notify(player, buf); } void do_bless(int descr, dbref player, const char *what, const char *propname) { dbref victim; struct match_data md; char buf[BUFFER_LEN]; int cnt; if (force_level) { notify(player, "Can't @force an @bless."); return; } if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) { notify(player, "Only Wizard players may use this command."); return; } if (!propname || !*propname) { notify(player, "Usage is @bless object=propname."); return; } /* get victim */ init_match(descr, player, what, NOTYPE, &md); match_everything(&md); if ((victim = noisy_match_result(&md)) == NOTHING) { return; } if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } cnt = blessprops_wildcard(player, victim, "", propname, 1); snprintf(buf, sizeof(buf), "%d propert%s blessed.", cnt, (cnt == 1)? "y" : "ies"); notify(player, buf); } void do_force(int descr, dbref player, const char *what, char *command) { dbref victim, loc; struct match_data md; assert(what != NULL); assert(command != NULL); assert(player > 0); if (force_level) { notify(player, "Can't force from within a force."); return; } if (!tp_zombies && (!Wizard(player) || Typeof(player) != TYPE_PLAYER)) { notify(player, "Zombies are not enabled here."); return; #ifdef DEBUG } else { notify(player, "[debug] Zombies are not enabled for nonwizards -- force succeeded."); #endif } /* get victim */ init_match(descr, player, what, NOTYPE, &md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); match_player(&md); if ((victim = noisy_match_result(&md)) == NOTHING) { #ifdef DEBUG notify(player, "[debug] do_force: unable to find your target!"); #endif /* DEBUG */ return; } if (Typeof(victim) != TYPE_PLAYER && Typeof(victim) != TYPE_THING) { notify(player, "Permission Denied -- Target not a player or thing."); return; } #ifdef GOD_PRIV if (God(victim)) { notify(player, "You cannot force God to do anything."); return; } #endif /* GOD_PRIV */ /* if (!controls(player, victim)) { * notify(player, "Permission denied."); * return; * } */ if (!Wizard(player) && !(FLAGS(victim) & XFORCIBLE)) { notify(player, "Permission denied: forced object not @set Xforcible."); return; } if (!Wizard(player) && !test_lock_false_default(descr, player, victim, "@/flk")) { notify(player, "Permission denied: Object not force-locked to you."); return; } loc = getloc(victim); if (!Wizard(player) && Typeof(victim) == TYPE_THING && loc != NOTHING && (FLAGS(loc) & ZOMBIE) && Typeof(loc) == TYPE_ROOM) { notify(player, "Sorry, but that's in a no-puppet zone."); return; } if (!Wizard(OWNER(player)) && Typeof(victim) == TYPE_THING) { const char *ptr = NAME(victim); char objname[BUFFER_LEN], *ptr2; if ((FLAGS(player) & ZOMBIE)) { notify(player, "Permission denied -- you cannot use zombies."); return; } if (FLAGS(victim) & DARK) { notify(player, "Permission denied -- you cannot force dark zombies."); return; } for (ptr2 = objname; *ptr && !isspace(*ptr);) *(ptr2++) = *(ptr++); *ptr2 = '\0'; if (lookup_player(objname) != NOTHING) { notify(player, "Puppet cannot share the name of a player."); return; } } log_status("FORCED: %s(%d) by %s(%d): %s\n", NAME(victim), victim, NAME(player), player, command); /* force victim to do command */ force_prog=NOTHING; /* Technically, force_level must be 0 at this point, regardless. */ force_level++; process_command(dbref_first_descr(victim), victim, command); force_level--; force_prog=NOTHING; } void do_stats(dbref player, const char *name) { int rooms; int exits; int things; int players; int programs; int garbage = 0; int total; int altered = 0; int oldobjs = 0; #ifdef DISKBASE int loaded = 0; int changed = 0; #endif time_t currtime = time(NULL); dbref i; dbref owner=NOTHING; char buf[BUFFER_LEN]; if (!Wizard(OWNER(player)) && (!name || !*name)) { snprintf(buf, sizeof(buf), "The universe contains %d objects.", db_top); notify(player, buf); } else { total = rooms = exits = things = players = programs = 0; if (name != NULL && *name != '\0') { owner = lookup_player(name); if (owner == NOTHING) { notify(player, "I can't find that player."); return; } if (!Wizard(OWNER(player)) && (OWNER(player) != owner)) { notify(player, "Permission denied."); return; } for (i = 0; i < db_top; i++) { #ifdef DISKBASE if ((OWNER(i) == owner) && DBFETCH(i)->propsmode != PROPS_UNLOADED) loaded++; if ((OWNER(i) == owner) && DBFETCH(i)->propsmode == PROPS_CHANGED) changed++; #endif /* count objects marked as changed. */ if ((OWNER(i) == owner) && (FLAGS(i) & OBJECT_CHANGED)) altered++; /* if unused for 90 days, inc oldobj count */ if ((OWNER(i) == owner) && (currtime - DBFETCH(i)->ts.lastused) > tp_aging_time) oldobjs++; switch (Typeof(i)) { case TYPE_ROOM: if (OWNER(i) == owner) total++, rooms++; break; case TYPE_EXIT: if (OWNER(i) == owner) total++, exits++; break; case TYPE_THING: if (OWNER(i) == owner) total++, things++; break; case TYPE_PLAYER: if (i == owner) total++, players++; break; case TYPE_PROGRAM: if (OWNER(i) == owner) total++, programs++; break; } } } else { for (i = 0; i < db_top; i++) { #ifdef DISKBASE if (DBFETCH(i)->propsmode != PROPS_UNLOADED) loaded++; if (DBFETCH(i)->propsmode == PROPS_CHANGED) changed++; #endif /* count objects marked as changed. */ if (FLAGS(i) & OBJECT_CHANGED) altered++; /* if unused for 90 days, inc oldobj count */ if ((currtime - DBFETCH(i)->ts.lastused) > tp_aging_time) oldobjs++; switch (Typeof(i)) { case TYPE_ROOM: total++; rooms++; break; case TYPE_EXIT: total++; exits++; break; case TYPE_THING: total++; things++; break; case TYPE_PLAYER: total++; players++; break; case TYPE_PROGRAM: total++; programs++; break; case TYPE_GARBAGE: total++; garbage++; break; } } } notify_fmt(player, "%7d room%s %7d exit%s %7d thing%s", rooms, (rooms == 1) ? " " : "s", exits, (exits == 1) ? " " : "s", things, (things == 1) ? " " : "s"); notify_fmt(player, "%7d program%s %7d player%s %7d garbage", programs, (programs == 1) ? " " : "s", players, (players == 1) ? " " : "s", garbage); notify_fmt(player, "%7d total object%s %7d old & unused", total, (total == 1) ? " " : "s", oldobjs); #ifdef DISKBASE if (Wizard(OWNER(player))) { notify_fmt(player, "%7d proploaded object%s %7d propchanged object%s", loaded, (loaded == 1) ? " " : "s", changed, (changed == 1) ? "" : "s"); } #endif #ifdef DELTADUMPS { char buf[BUFFER_LEN]; struct tm *time_tm; time_t lasttime = (time_t) get_property_value(0, "_sys/lastdumptime"); #ifndef WIN32 time_tm = localtime(&lasttime); #else time_tm = uw32localtime(&lasttime); #endif (void) format_time(buf, 40, "%a %b %e %T %Z", time_tm); notify_fmt(player, "%7d unsaved object%s Last dump: %s", altered, (altered == 1) ? "" : "s", buf); } #endif } } void do_boot(dbref player, const char *name) { dbref victim; char buf[BUFFER_LEN]; if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) { notify(player, "Only a Wizard player can boot someone off."); return; } if ((victim = lookup_player(name)) == NOTHING) { notify(player, "That player does not exist."); return; } if (Typeof(victim) != TYPE_PLAYER) { notify(player, "You can only boot players!"); } #ifdef GOD_PRIV else if (God(victim)) { notify(player, "You can't boot God!"); } #endif /* GOD_PRIV */ else { notify(victim, "You have been booted off the game."); if (boot_off(victim)) { log_status("BOOTED: %s(%d) by %s(%d)\n", NAME(victim), victim, NAME(player), player); if (player != victim) { snprintf(buf, sizeof(buf), "You booted %s off!", NAME(victim)); notify(player, buf); } } else { snprintf(buf, sizeof(buf), "%s is not connected.", NAME(victim)); notify(player, buf); } } } void do_toad(int descr, dbref player, const char *name, const char *recip) { dbref victim; dbref recipient; dbref stuff; char buf[BUFFER_LEN]; if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) { notify(player, "Only a Wizard player can turn a person into a toad."); return; } if ((victim = lookup_player(name)) == NOTHING) { notify(player, "That player does not exist."); return; } if (!*recip) { /* FIXME: Make me a tunable parameter! */ recipient = GOD; } else { if ((recipient = lookup_player(recip)) == NOTHING || recipient == victim) { notify(player, "That recipient does not exist."); return; } } if (Typeof(victim) != TYPE_PLAYER) { notify(player, "You can only turn players into toads!"); #ifdef GOD_PRIV } else if (!(God(player)) && (TrueWizard(victim))) { #else } else if (TrueWizard(victim)) { #endif notify(player, "You can't turn a Wizard into a toad."); } else { /* we're ok */ /* do it */ send_contents(descr, victim, HOME); dequeue_prog(victim, 0); /* Dequeue the programs that the player's running */ for (stuff = 0; stuff < db_top; stuff++) { if (OWNER(stuff) == victim) { switch (Typeof(stuff)) { case TYPE_PROGRAM: dequeue_prog(stuff, 0); /* dequeue player's progs */ if (TrueWizard(recipient)) { FLAGS(stuff) &= ~(ABODE | WIZARD); SetMLevel(stuff, 1); } case TYPE_ROOM: case TYPE_THING: case TYPE_EXIT: OWNER(stuff) = recipient; DBDIRTY(stuff); break; } } if (Typeof(stuff) == TYPE_THING && THING_HOME(stuff) == victim) { /* FIXME: Set a tunable "lost and found" area! */ THING_SET_HOME(stuff, tp_player_start); } } if (PLAYER_PASSWORD(victim)) { free((void *) PLAYER_PASSWORD(victim)); PLAYER_SET_PASSWORD(victim, 0); } /* notify people */ notify(victim, "You have been turned into a toad."); snprintf(buf, sizeof(buf), "You turned %s into a toad!", NAME(victim)); notify(player, buf); log_status("TOADED: %s(%d) by %s(%d)\n", NAME(victim), victim, NAME(player), player); /* reset name */ delete_player(victim); snprintf(buf, sizeof(buf), "A slimy toad named %s", NAME(victim)); free((void *) NAME(victim)); NAME(victim) = alloc_string(buf); DBDIRTY(victim); boot_player_off(victim); /* Disconnect the toad */ if (PLAYER_DESCRS(victim)) { free(PLAYER_DESCRS(victim)); PLAYER_SET_DESCRS(victim, NULL); PLAYER_SET_DESCRCOUNT(victim, 0); } ignore_remove_from_all_players(victim); ignore_flush_cache(victim); FREE_PLAYER_SP(victim); ALLOC_THING_SP(victim); THING_SET_HOME(victim, PLAYER_HOME(player)); FLAGS(victim) = (FLAGS(victim) & ~TYPE_MASK) | TYPE_THING; OWNER(victim) = player; /* you get it */ SETVALUE(victim, 1); /* don't let him keep his immense wealth */ } } void do_newpassword(dbref player, const char *name, const char *password) { dbref victim; char buf[BUFFER_LEN]; if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) { notify(player, "Only a Wizard player can newpassword someone."); return; } else if ((victim = lookup_player(name)) == NOTHING) { notify(player, "No such player."); } else if (*password != '\0' && !ok_password(password)) { /* Wiz can set null passwords, but not bad passwords */ notify(player, "Bad password"); #ifdef GOD_PRIV } else if (God(victim)) { notify(player, "You can't change God's password!"); return; } else { if (TrueWizard(victim) && !God(player)) { notify(player, "Only God can change a wizard's password."); return; } #else /* GOD_PRIV */ } else { #endif /* GOD_PRIV */ /* it's ok, do it */ set_password(victim, password); DBDIRTY(victim); notify(player, "Password changed."); snprintf(buf, sizeof(buf), "Your password has been changed by %s.", NAME(player)); notify(victim, buf); log_status("NEWPASS'ED: %s(%d) by %s(%d)\n", NAME(victim), victim, NAME(player), player); } } void do_pcreate(dbref player, const char *user, const char *password) { dbref newguy; char buf[BUFFER_LEN]; if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) { notify(player, "Only a Wizard player can create a player."); return; } newguy = create_player(user, password); if (newguy == NOTHING) { notify(player, "Create failed."); } else { log_status("PCREATED %s(%d) by %s(%d)\n", NAME(newguy), newguy, NAME(player), player); snprintf(buf, sizeof(buf), "Player %s created as object #%d.", user, newguy); notify(player, buf); } } #ifdef DISKBASE extern long propcache_hits; extern long propcache_misses; #endif void do_serverdebug(int descr, dbref player, const char *arg1, const char *arg2) { if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } if (!*arg1) { notify(player, "Usage: @dbginfo [cache|guitest|misc]"); return; } #ifdef DISKBASE if (string_prefix(arg1, "cache")) { notify(player, "Cache info:"); diskbase_debug(player); } else #endif if (string_prefix(arg1, "guitest")) { do_post_dlog(descr, arg2); } notify(player, "Done."); } long max_open_files(void); /* from interface.c */ void do_usage(dbref player) { int pid, psize; #ifdef HAVE_GETRUSAGE struct rusage usage; #endif if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } #ifndef NO_USAGE_COMMAND pid = getpid(); #ifdef HAVE_GETRUSAGE psize = getpagesize(); getrusage(RUSAGE_SELF, &usage); #endif notify_fmt(player, "Compiled on: %s", UNAME_VALUE); notify_fmt(player, "Process ID: %d", pid); notify_fmt(player, "Max descriptors/process: %ld", max_open_files()); #ifdef HAVE_GETRUSAGE notify_fmt(player, "Performed %d input servicings.", usage.ru_inblock); notify_fmt(player, "Performed %d output servicings.", usage.ru_oublock); notify_fmt(player, "Sent %d messages over a socket.", usage.ru_msgsnd); notify_fmt(player, "Received %d messages over a socket.", usage.ru_msgrcv); notify_fmt(player, "Received %d signals.", usage.ru_nsignals); notify_fmt(player, "Page faults NOT requiring physical I/O: %d", usage.ru_minflt); notify_fmt(player, "Page faults REQUIRING physical I/O: %d", usage.ru_majflt); notify_fmt(player, "Swapped out of main memory %d times.", usage.ru_nswap); notify_fmt(player, "Voluntarily context switched %d times.", usage.ru_nvcsw); notify_fmt(player, "Involuntarily context switched %d times.", usage.ru_nivcsw); notify_fmt(player, "User time used: %d sec.", usage.ru_utime.tv_sec); notify_fmt(player, "System time used: %d sec.", usage.ru_stime.tv_sec); notify_fmt(player, "Pagesize for this machine: %d", psize); notify_fmt(player, "Maximum resident memory: %ldk", (long) (usage.ru_maxrss * (psize / 1024))); notify_fmt(player, "Integral resident memory: %ldk", (long) (usage.ru_idrss * (psize / 1024))); #endif /* HAVE_GETRUSAGE */ #else /* NO_USAGE_COMMAND */ notify(player, "Sorry, this server was compiled with NO_USAGE_COMMAND."); #endif /* NO_USAGE_COMMAND */ } void do_muf_topprofs(dbref player, char *arg1) { struct profnode { struct profnode *next; dbref prog; double proftime; double pcnt; long comptime; long usecount; } *tops = NULL; struct profnode *curr = NULL; int nodecount = 0; char buf[BUFFER_LEN]; dbref i = NOTHING; int count = atoi(arg1); time_t current_systime = time(NULL); if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } if (!string_compare(arg1, "reset")) { for (i = db_top; i-->0; ) { if (Typeof(i) == TYPE_PROGRAM) { PROGRAM_SET_PROFTIME(i, 0, 0); PROGRAM_SET_PROFSTART(i, current_systime); PROGRAM_SET_PROF_USES(i, 0); } } notify(player, "MUF profiling statistics cleared."); return; } if (count < 0) { notify(player, "Count has to be a positive number."); return; } else if (count == 0) { count = 10; } for (i = db_top; i-->0; ) { if (Typeof(i) == TYPE_PROGRAM && PROGRAM_CODE(i)) { struct profnode *newnode = (struct profnode *)malloc(sizeof(struct profnode)); struct timeval tmpt = PROGRAM_PROFTIME(i); newnode->next = NULL; newnode->prog = i; newnode->proftime = tmpt.tv_sec; newnode->proftime += (tmpt.tv_usec / 1000000.0); newnode->comptime = current_systime - PROGRAM_PROFSTART(i); newnode->usecount = PROGRAM_PROF_USES(i); if (newnode->comptime > 0) { newnode->pcnt = 100.0 * newnode->proftime / newnode->comptime; } else { newnode->pcnt = 0.0; } if (!tops) { tops = newnode; nodecount++; } else if (newnode->pcnt < tops->pcnt) { if (nodecount < count) { newnode->next = tops; tops = newnode; nodecount++; } else { free(newnode); } } else { if (nodecount >= count) { curr = tops; tops = tops->next; free(curr); } else { nodecount++; } if (!tops) { tops = newnode; } else if (newnode->pcnt < tops->pcnt) { newnode->next = tops; tops = newnode; } else { for (curr = tops; curr->next; curr = curr->next) { if (newnode->pcnt < curr->next->pcnt) { break; } } newnode->next = curr->next; curr->next = newnode; } } } } notify(player, " %CPU TotalTime UseCount Program"); while (tops) { curr = tops; snprintf(buf, sizeof(buf), "%10.3f %10.3f %9ld %s", curr->pcnt, curr->proftime, curr->usecount, unparse_object(player, curr->prog)); notify(player, buf); tops = tops->next; free(curr); } snprintf(buf, sizeof(buf), "Profile Length (sec): %5ld %%idle: %5.2f%% Total Cycles: %5lu", (current_systime-sel_prof_start_time), ((double)(sel_prof_idle_sec+(sel_prof_idle_usec/1000000.0))*100.0)/ (double)((current_systime-sel_prof_start_time)+0.01), sel_prof_idle_use); notify(player,buf); notify(player, "*Done*"); } void do_mpi_topprofs(dbref player, char *arg1) { struct profnode { struct profnode *next; dbref prog; double proftime; double pcnt; long comptime; long usecount; } *tops = NULL; struct profnode *curr = NULL; int nodecount = 0; char buf[BUFFER_LEN]; dbref i = NOTHING; int count = atoi(arg1); time_t current_systime = time(NULL); if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } if (!string_compare(arg1, "reset")) { for (i = db_top; i-->0; ) { if (DBFETCH(i)->mpi_prof_use) { DBFETCH(i)->mpi_prof_use = 0; DBFETCH(i)->mpi_proftime.tv_usec = 0; DBFETCH(i)->mpi_proftime.tv_sec = 0; } } mpi_prof_start_time = current_systime; notify(player, "MPI profiling statistics cleared."); return; } if (count < 0) { notify(player, "Count has to be a positive number."); return; } else if (count == 0) { count = 10; } for (i = db_top; i-->0; ) { if (DBFETCH(i)->mpi_prof_use) { struct profnode *newnode = (struct profnode *)malloc(sizeof(struct profnode)); newnode->next = NULL; newnode->prog = i; newnode->proftime = DBFETCH(i)->mpi_proftime.tv_sec; newnode->proftime += (DBFETCH(i)->mpi_proftime.tv_usec / 1000000.0); newnode->comptime = current_systime - mpi_prof_start_time; newnode->usecount = DBFETCH(i)->mpi_prof_use; if (newnode->comptime > 0) { newnode->pcnt = 100.0 * newnode->proftime / newnode->comptime; } else { newnode->pcnt = 0.0; } if (!tops) { tops = newnode; nodecount++; } else if (newnode->pcnt < tops->pcnt) { if (nodecount < count) { newnode->next = tops; tops = newnode; nodecount++; } else { free(newnode); } } else { if (nodecount >= count) { curr = tops; tops = tops->next; free(curr); } else { nodecount++; } if (!tops) { tops = newnode; } else if (newnode->pcnt < tops->pcnt) { newnode->next = tops; tops = newnode; } else { for (curr = tops; curr->next; curr = curr->next) { if (newnode->pcnt < curr->next->pcnt) { break; } } newnode->next = curr->next; curr->next = newnode; } } } } notify(player, " %CPU TotalTime UseCount Object"); while (tops) { curr = tops; snprintf(buf, sizeof(buf), "%10.3f %10.3f %9ld %s", curr->pcnt, curr->proftime, curr->usecount, unparse_object(player, curr->prog)); notify(player, buf); tops = tops->next; free(curr); } snprintf(buf, sizeof(buf), "Profile Length (sec): %5ld %%idle: %5.2f%% Total Cycles: %5lu", (current_systime-sel_prof_start_time), (((double)sel_prof_idle_sec+(sel_prof_idle_usec/1000000.0))*100.0)/ (double)((current_systime-sel_prof_start_time)+0.01), sel_prof_idle_use); notify(player,buf); notify(player, "*Done*"); } void do_all_topprofs(dbref player, char *arg1) { struct profnode { struct profnode *next; dbref prog; double proftime; double pcnt; long comptime; long usecount; short type; } *tops = NULL; struct profnode *curr = NULL; int nodecount = 0; char buf[BUFFER_LEN]; dbref i = NOTHING; int count = atoi(arg1); time_t current_systime = time(NULL); if (!Wizard(OWNER(player))) { notify(player, "Permission denied."); return; } if (!string_compare(arg1, "reset")) { for (i = db_top; i-->0; ) { if (DBFETCH(i)->mpi_prof_use) { DBFETCH(i)->mpi_prof_use = 0; DBFETCH(i)->mpi_proftime.tv_usec = 0; DBFETCH(i)->mpi_proftime.tv_sec = 0; } if (Typeof(i) == TYPE_PROGRAM) { PROGRAM_SET_PROFTIME(i, 0, 0); PROGRAM_SET_PROFSTART(i, current_systime); PROGRAM_SET_PROF_USES(i, 0); } } sel_prof_idle_sec = 0; sel_prof_idle_usec = 0; sel_prof_start_time = current_systime; sel_prof_idle_use = 0; mpi_prof_start_time = current_systime; notify(player, "All profiling statistics cleared."); return; } if (count < 0) { notify(player, "Count has to be a positive number."); return; } else if (count == 0) { count = 10; } for (i = db_top; i-->0; ) { if (DBFETCH(i)->mpi_prof_use) { struct profnode *newnode = (struct profnode *)malloc(sizeof(struct profnode)); newnode->next = NULL; newnode->prog = i; newnode->proftime = DBFETCH(i)->mpi_proftime.tv_sec; newnode->proftime += (DBFETCH(i)->mpi_proftime.tv_usec / 1000000.0); newnode->comptime = current_systime - mpi_prof_start_time; newnode->usecount = DBFETCH(i)->mpi_prof_use; newnode->type = 0; if (newnode->comptime > 0) { newnode->pcnt = 100.0 * newnode->proftime / newnode->comptime; } else { newnode->pcnt = 0.0; } if (!tops) { tops = newnode; nodecount++; } else if (newnode->pcnt < tops->pcnt) { if (nodecount < count) { newnode->next = tops; tops = newnode; nodecount++; } else { free(newnode); } } else { if (nodecount >= count) { curr = tops; tops = tops->next; free(curr); } else { nodecount++; } if (!tops) { tops = newnode; } else if (newnode->pcnt < tops->pcnt) { newnode->next = tops; tops = newnode; } else { for (curr = tops; curr->next; curr = curr->next) { if (newnode->pcnt < curr->next->pcnt) { break; } } newnode->next = curr->next; curr->next = newnode; } } } if (Typeof(i) == TYPE_PROGRAM && PROGRAM_CODE(i)) { struct profnode *newnode = (struct profnode *)malloc(sizeof(struct profnode)); struct timeval tmpt = PROGRAM_PROFTIME(i); newnode->next = NULL; newnode->prog = i; newnode->proftime = tmpt.tv_sec; newnode->proftime += (tmpt.tv_usec / 1000000.0); newnode->comptime = current_systime - PROGRAM_PROFSTART(i); newnode->usecount = PROGRAM_PROF_USES(i); newnode->type = 1; if (newnode->comptime > 0) { newnode->pcnt = 100.0 * newnode->proftime / newnode->comptime; } else { newnode->pcnt = 0.0; } if (!tops) { tops = newnode; nodecount++; } else if (newnode->pcnt < tops->pcnt) { if (nodecount < count) { newnode->next = tops; tops = newnode; nodecount++; } else { free(newnode); } } else { if (nodecount >= count) { curr = tops; tops = tops->next; free(curr); } else { nodecount++; } if (!tops) { tops = newnode; } else if (newnode->pcnt < tops->pcnt) { newnode->next = tops; tops = newnode; } else { for (curr = tops; curr->next; curr = curr->next) { if (newnode->pcnt < curr->next->pcnt) { break; } } newnode->next = curr->next; curr->next = newnode; } } } } notify(player, " %CPU TotalTime UseCount Type Object"); while (tops) { curr = tops; snprintf(buf, sizeof(buf), "%10.3f %10.3f %9ld%5s %s", curr->pcnt, curr->proftime, curr->usecount, curr->type?"MUF":"MPI",unparse_object(player, curr->prog)); notify(player, buf); tops = tops->next; free(curr); } snprintf(buf, sizeof(buf), "Profile Length (sec): %5ld %%idle: %5.2f%% Total Cycles: %5lu", (current_systime-sel_prof_start_time), ((double)(sel_prof_idle_sec+(sel_prof_idle_usec/1000000.0))*100.0)/ (double)((current_systime-sel_prof_start_time)+0.01), sel_prof_idle_use); notify(player,buf); notify(player, "*Done*"); } void do_memory(dbref who) { if (!Wizard(OWNER(who))) { notify(who, "Permission denied."); return; } #ifndef NO_MEMORY_COMMAND # ifdef HAVE_MALLINFO { struct mallinfo mi; mi = mallinfo(); notify_fmt(who, "Total allocated from system: %6dk", (mi.arena / 1024)); notify_fmt(who, "Number of non-inuse chunks: %6d", mi.ordblks); notify_fmt(who, "Small block count: %6d", mi.smblks); notify_fmt(who, "Small block mem alloced: %6dk", (mi.usmblks / 1024)); notify_fmt(who, "Small block memory free: %6dk", (mi.fsmblks / 1024)); #ifdef HAVE_STRUCT_MALLINFO_HBLKS notify_fmt(who, "Number of mmapped regions: %6d", mi.hblks); #endif notify_fmt(who, "Total memory mmapped: %6dk", (mi.hblkhd / 1024)); notify_fmt(who, "Total memory malloced: %6dk", (mi.uordblks / 1024)); notify_fmt(who, "Mem allocated overhead: %6dk", ((mi.arena - mi.uordblks) / 1024)); notify_fmt(who, "Memory free: %6dk", (mi.fordblks / 1024)); #ifdef HAVE_STRUCT_MALLINFO_KEEPCOST notify_fmt(who, "Top-most releasable chunk size:%6dk", (mi.keepcost / 1024)); #endif #ifdef HAVE_STRUCT_MALLINFO_TREEOVERHEAD notify_fmt(who, "Memory free overhead: %6dk", (mi.treeoverhead / 1024)); #endif #ifdef HAVE_STRUCT_MALLINFO_GRAIN notify_fmt(who, "Small block grain: %6d", mi.grain); #endif #ifdef HAVE_STRUCT_MALLINFO_ALLOCATED notify_fmt(who, "Mem chunks alloced:%6d", mi.allocated); #endif } # endif /* HAVE_MALLINFO */ #endif /* NO_MEMORY_COMMAND */ #ifdef MALLOC_PROFILING notify(who, " "); CrT_summarize(who); CrT_summarize_to_file("malloc_log", "Manual Checkpoint"); #endif notify(who, "Done."); }