musicmud-2.1.6/data/
musicmud-2.1.6/data/help/
musicmud-2.1.6/data/policy/
musicmud-2.1.6/data/wild/
musicmud-2.1.6/data/world/
musicmud-2.1.6/doc/
musicmud-2.1.6/src/ident/
musicmud-2.1.6/src/lua/
musicmud-2.1.6/src/lua/include/
musicmud-2.1.6/src/lua/src/lib/
musicmud-2.1.6/src/lua/src/lua/
musicmud-2.1.6/src/lua/src/luac/
/* 
 * MusicMUD - Admin module (part 2)
 * Copyright (C) 1998-2003 Abigail Brady
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 */
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>

#ifdef CONFIG_PTHREAD
#include <pthread.h>
#endif

#include "musicmud.h"
#include "verbs.h"
#include "State.h"
#include "zoneload.h"
#include "magic.h"
#include "msi.h"
#include "misc.h"
#include "Socket.h"
#include "config.h"
#include "startup.h"
#include "trap.h"
#include "flags.h"
#include "Writer.h"
#include "pflags.h"
#include "util.h"
#include "levels.h"
#include "flagnames.h"

#ifdef CONFIG_PIPE_IDENT
#include "pipe-ident.h"
#endif

#include "Library.h"

#define MODULE "admin2"

#define is_room(r) (r->get_flag(FL_ROOM))

static int object_depth(MudObject *who) {
    int level = 0;
    while (who) {
	who = who->owner;
	level++;
    }
    return level;
}


static bool verb_mudcrash(MudObject *who, int, const char **) {
  *(int *)0=0;
  return true;
}

static bool verb_magic(MudObject *, int, const char **) {
  signals_start();
  return true;
}

static void do_save(FILE *f, const char *zonename) {
  MudObject *o;
  int i;
  foreach(zones->get(zonename)->children, o, i) {
    if (!is_player(o)) {
      o->save(f);
    }
  }
}

static bool verb_shutdown(MudObject *luser, int , const char *argv[]) {
  ident::done();
  if (!streq(argv[1], "quick")) {
    log(PFL_SEEINFO, 0, "admin", "emergency zone saving started");
    struct timeval start_time;
    gettimeofday(&start_time, 0);
    FILE *meta=xopen(DATA_WORLD_EMERG, "index", "w");
    if (!meta) return true;
    int size = zones->getsize();
    for (int i=0;i<size;i++) {
	const char *id = zones->get(i)->id;
	luser->printf("Saving zone %s\n", id);
	FILE *f = xopen(DATA_WORLD_EMERG, id, "w");
	do_save(f, id);
	luser->send_data();
	fprintf(meta, "%s\n", id);
	xclose(f);
    }
    xclose(meta);
    struct timeval end_time;
    gettimeofday(&end_time, 0);
    log(PFL_SEEINFO, 0, "admin", "emergency zone saving finished");
  }

  save_var_data();

  Player *p;
  int i;
  foreach(players, p, i) {
    p->interpret("saveplayer");
    p->printf("%#s has been shut down. Goodbye.\n", THE_MUDNAME);
    p->send_data();
  }
  
  log(PFL_SEEINFO, 0, "admin", "shutdown");

  exit(1);
  return true;
}

static bool verb_savezones(MudObject *o, int , const char *[]) {
    struct timeval start_time;
    gettimeofday(&start_time, 0);
    FILE *meta=xopen_tmp(DATA_WORLD, "index", "w");
    int size = zones->getsize();

    log(PFL_SEEINFO, 0, "zone", "about to save zones");

    o->printf("Saving zones ");

    for (int eep=0;eep<size;eep++) {
	const char *id = zones->get(eep)->id;
	if (id[0] == '@') continue;

	o->printf("%s ", id);
	FILE *f = xopen_tmp(DATA_WORLD, id, "w");
	if (!f) {
	    o->printf("\nBad news : the zonefiles couldn't be saved properly. Contact an administrator.\n");
	    return true;
	}
	do_save(f, id);
	o->send_data();
	fprintf(meta, "%s\n", id);
	xclose_confirm(f, DATA_WORLD, id);
    }
    o->printf("\n");
    xclose_confirm(meta, DATA_WORLD, "index");
    struct timeval end_time;
    gettimeofday(&end_time, 0);
    
#if 0
    int64_t difference = (end_time.tv_sec - start_time.tv_sec) * 1000000 + 
	(end_time.tv_usec - start_time.tv_usec);
#endif

    save_var_data();

    log(PFL_SEEINFO, 0, "zone", "all zones saved");
    return true;
}

static bool verb_savevar(MudObject *o, int argc, const char **argv) {
  save_var_data();
  o->printf("Saved vardata and data/mudconf.\n");
  return true;
}

static bool verb_savethiszone(MudObject *o, int argc, const char **argv) {
    if (!o->owner) {
	o->printf("You are nowhere.\n");
	return true;
    }
    const char *zone = o->owner->get("zone");
    if (argc>1 && zones->get(argv[1])) {
      zone = argv[1];
    }
    if (!zone) {
	o->printf("What zone?\n");
	return true;
    }
    FILE *f = xopen_tmp(DATA_WORLD, zone, "w");
    if (!f) {
	o->printf("Bad news : the zonefile couldn't be saved properly\n"
		  "If Daz is on tell him. If not, email him at\n"
		  "dab198@zepler.org\n");
	return true;
    }
    do_save(f, zone);
    o->printf("zone %s saved.\n", zone);
    xclose_confirm(f, DATA_WORLD, zone);
    log(PFL_SEEINFO, 0, "zone", "%s saved", zone);
    return true;
}

static bool verb_rtz(MudObject *o, int argc, const char *argv[]) {
    if (!o->owner) {
	o->printf("You are nowhere.\n");
	return true;
    }
    const char *zone = o->owner->get("zone");
    if (!zone) {
	o->printf("What zone?\n");
	return true;
    }
    broadcast(!getflag(FL_NORESET) && minlev(LEV_COMMANDER),
        "^Y[^RRESET^g: ^G%s^g by %s^Y]\n", capitalise(zone).c_str(), name(o));
    doreset(zone, true);
    return true;
}

static bool verb_reset(MudObject *who, int argc, const char *argv[]) {
    if (argc < 2) {
	who->printf("reset <zonename>\n");
	return true;
    }
    if (!zones->get(argv[1]) && !streq(argv[1], "all")) {
      who->printf("You can only reset zones or 'all'\n");
      return true;
    }

    if (streq(argv[1], "all"))
      broadcast(!getflag(FL_NORESET) && minlev(LEV_COMMANDER),
        "^Y[^RRESET^g: ^GEverything^g by %s^Y]\n", name(who));
      else
	broadcast(!getflag(FL_NORESET) && minlev(LEV_COMMANDER),
        "^Y[^RRESET^g: ^G%s^g by %s^Y]\n", capitalise(argv[1]).c_str(), name(who));

    doreset(argv[1], true);
    return true;
}

static bool verb_snoop(MudObject *player, int argc, const char **argv) {
    if (argc < 2) {
      if (player->snooping.getsize()) {
	player->printf("You are snooping %W.\n", &player->snooping);
      }	else {
	player->printf("You aren't snooping anyone.\n");
      }
      return true;
    }
    MudObject *target = planet->get(argv[1]);
    if (!target) {
	player->printf("Can't find %s\n", argv[1]);
	return true;
    }

    if (player == target) {
        player->printf("Don't you know what you're doing already?!\n");
        return true;
    }
    
    if (privs_of(target) > privs_of(player)) {
      player->printf("You can't snoop %s.\n", him_or_her(target));
      return true;
    }

    if (player->snooping.get(target->id)) {
      player->desnoop(target);
      player->printf("No longer snooping %M.\n", target);
      log(PFL_SNOOP, 0, "admin", "no longer snooping %s", target->id);
    } else {
      player->snoop(target);
      player->printf("Now snooping %M.\n", target);
      log(PFL_SNOOP, 0, "admin", "snooping %s", target->id);
    }
    return true;
}

static bool verb_desnoop(MudObject *player, int, const char **) {
  MudObject *o;
  int i;
  if (!player->snooping) {
    player->printf("You aren't snooping anyone.\n");
    return true;
  }
  player->printf("No longer snooping %W.\n", &player->snooping);
  foreach((&player->snooping), o, i) {
    player->desnoop(o);
    i--;
  }
  return true;
}

static bool verb_force(MudObject *player, int argc, const char *argv[]) {
    if (!player->get_priv(PFL_FORCE) && !player->get_flag(FL_TIMER))
      {
	player->printf("You cannot do that.\n");
	return true;
      }
    if (argc<3) {
	player->printf("force <who> <what>\n");
	return true;
    }
    MudObject *target = find_object(player, argv[1]);
    if (!target) {
	player->printf("Can't find %s\n", argv[1]);
	return true;
    }
   
    if (target==player) {
	player->printf("Forcing yourself to do stuff is not a good idea.\n");
	return true;
    }
    
    if (privs_of(target)>=privs_of(player) && !player->ilc) {
 	player->printf("You can only force people of lower levels..\n");
	return true;
    }
    
    string cmd = the_rest(argc, argv, 2);

    int desnoop = 0;

    if (!player->ilc) {
      desnoop = player->snoop(target);
    }
    
    if (player->ilc) {
      target->ilc++;
    } else {
      log(PFL_SEEINFO, 0, "admin", "%s forces %s to %s", player->id, target->id, cmd.c_str());
    }

    target->interpret(cmd.c_str());
     
    if (player->ilc) {
      target->ilc--;
    }
    
    if (desnoop) {
      player->desnoop(target);
    }
    
    return true;
}

static bool verb_loadflags(MudObject *, int, const char **) {
    load_flags();
    load_pflags();
    return true;
}

static bool verb_modulelist(MudObject *player, int, const char **){
  Object *o;
  int i;

  Divert d(player, "modulelist");

  foreach(libs, o, i) {
	time_t t = o->get_int("timestamp");
    player->printf("%-40s %s", o->id, ctime(&t));
  }
  return true;

}

#include "aberchat.h"

static bool verb_reboot(MudObject *who, int, const char **) {
	
#ifdef CONFIG_PIPE_IDENT
    ident::done();
#endif
#ifdef CONFIG_THREAD
    pthread_kill_other_threads_np();
    if (fork()!=0) exit(0);
#endif
    
    char buffer[256];
    char wallace[4096];

    sprintf(buffer, VARDATA "/reboot-misc.%i", getpid());
    FILE *f = xopen(".", buffer, "w");
    if (f) {
      fprintf(f, "%i\n", (int)mud_start);
      xclose(f);
    }

    sprintf(buffer, VARDATA "/reboot-parties.%i", getpid());
    f = xopen(".", buffer, "w");
    if (f) {
      MudObject *p;
      int i;
      foreach(players, p, i) {
	if (!p->followers.getsize()) {
	  continue;
	}
	fprintf(f, "%s ", p->id);
	MudObject *o;
	int j;
	foreach((&p->followers), o, j) if (o->id[0]!='@' && !o->get_flag(FL_OBSERVED)) {
	  o->set_flag(FL_OBSERVED, 1);
	  fprintf(f, "%s ", o->id);
	}
	fprintf(f, "\n");
      }
      xclose(f);
    }

    sprintf(buffer, VARDATA "/reboot.%i", getpid());
    f = xopen(".", buffer, "w");
    
    if (aberchat_auth && aberchat_socket) {
	int fd = aberchat_socket->getfd();
	fcntl(fd, F_SETFD, false);
	while ((read(fd, wallace, 4096)) > 0) ;
	sprintf(buffer, VARDATA "/aberfd.%i", getpid());
	FILE *f2 = xopen(".", buffer, "w");
	fprintf(f2, "%i\n", fd);
	xclose(f2);
    }

    Player *p;
    int i;
    foreach(players, p, i){
      Socket *s = p->p?p->p->socket:0;
      
      if (s) {
	int fd = s->getfd();
	fcntl(fd, F_SETFD, false);
	read(fd, wallace, 4096);
	
	if (p->get_flag(FL_LOGGEDIN)) {
	  fprintf(f, "%s %i %s %i %s\n", p->id, fd, p->owner->id, 
		  (int)p->get_idle(), p->p->serialise().c_str());
	} else {
	  PersonState *ps = p->get_person_state();
	  string sps = serialise_personstate(ps);
	  fprintf(f, "%s %i %s %i %s\n%s\n", p->id, fd, p->owner->id, 
		  (int)p->get_idle(), p->p->serialise().c_str(),
		  sps.c_str());
	}
      }
#ifndef NOCOMPRESS
      if (p->p) {
	p->p->compress_off();
      }
#endif
    }
    
    xclose(f);
    log(PFL_NONE, 0, "global", "reboot begun");
    foreach(players, p, i) {
      p->interpret("save");
      p->send_data();
    }
    save_var_data();

    int port = MUD_DEFPORT;
    extern Socket *primary;
    if (primary)
      port = primary->port;
    
    msi::done();
    extern FILE *logfile;
    xclose(logfile);
    logfile = 0;
    
    Library *l;
    foreach(libs, l, i) {
      l->cleanup();
    }

    char pstr[16];
    sprintf(pstr, "%i", port);
    if (port == 6665)
      execl("./testmud", "./testmud", "-p", pstr, "-r", 0);
    else
      execl("./musicmud", "./musicmud", "-p", pstr, "-r", 0);
    who->printf("failed.\n");
    
    return true;
}

static bool verb_bans(MudObject *who, int, const char **) {
    FILE *f=xopen(VARDATA, "banned", "r");
    if (!f) {
	who->printf("Can't open %s/banned.\n", VARDATA);
	return true;
    }
    char buffer[256];
    int i=0;
    while (1) {
	fgets(buffer, 256, f);
	if (feof(f)) break;
	*strchr(buffer, '\n')=0;
	i++;
	who->printf("%s\n", buffer);
    }
    xclose(f);
    if (!i) {
	who->printf("No bans.\n");
    }
    return true;
}

static bool verb_addban(MudObject *who, int argc, const char **argv) {
    if (argc == 1) {
	who->printf("Ban which IP address?\n");
	return true;
    }
    FILE *f=xopen(VARDATA, "banned", "a");
    if (!f) {
	who->printf("Can't open %s/banned.\n", VARDATA);
	return true;
    }
    fprintf(f, "%s\n", argv[1]);
    xclose(f);
    who->printf("OK.\n");
    return true;
}

static bool verb_remban(MudObject *who, int argc, const char **argv) {
    if (argc == 1) {
	who->printf("Remove ban on who?\n");
	return true;
    }
    bool ok = false;
    FILE *i = xopen(VARDATA, "banned", "r");
    if (!i) { 
	who->printf("Can't open %s/banned.\n", VARDATA);
	return true;
    }
    FILE *o = xopen(VARDATA, "banned.tmp", "w");
    if (!o) {
	who->printf("Can't open temporary file.\n");
	return true;
    }
    while (1) {
	char buffer[256];
	fgets(buffer, sizeof buffer, i);
	if (feof(i)) break;
	*strchr(buffer, '\n')=0;
	if (streq(argv[1], buffer)) {
	    ok = true;
	} else {
	    fprintf(o, "%s\n", buffer);
	}
    }
    if (ok) {
	unlink(VARDATA "/banned");
	rename(VARDATA "/banned.tmp", VARDATA "/banned");
	who->printf("OK.\n");
    } else {
	unlink(VARDATA "/banned.tmp");
	who->printf("That IP address is not banned.\n");
    }
    xclose(o);
    xclose(i);
    return true;
}

static bool verb_fds(MudObject *who, int, const char **) {
  who->printf("%5s %-20s %-20s %5s\n", "fd", "filename", "sourcefile", "line");
  for (int l=0;l<1024;l++) {
    if (fds[l]) {
      who->printf("%5i %-20s %-20s %5i\n", 
		  l, fds[l]->get("filename"), 
		  fds[l]->get("sourcefile"), 
		  fds[l]->get_int("lineno"));
    }
  }
  return true;
}

static bool verb_zap(MudObject *who, int argc, const char **argv) {
  if (argc < 2) {
    who->printf("zap <who>\n", argv[1]);
    return true;
  }
  MudObject *what = find_object(who, argv[1]);
  if (!what) {
    who->printf("Zap who?\n");
    return true;
  }
  if (!is_player(what)) {
    who->printf("You can only zap players.\n");
    return true;
  }
  if (what->get_int("privs")>=who->get_int("privs")) {
    who->printf("I don't think so.\n");
    return true;
  }
  NewWorld tozap;
  add_storeable_eq(what, tozap);
  MudObject *o;
  int i;
  foreach((&tozap), o, i) {
    vanish(o);
  }
  dumpstuff(what, what->owner);
  what->quit = time(NULL)+2;
  what->printf("You've been destroyed by %M.\n", who);
  what->send_data();
  log(PFL_SEEINFO, 0, "admin", "%s zaps %s", who->id, what->id);

  foreach(players, o, i) 
    if (o->get_flag(FL_LOGGEDIN) && o != what)
      o->printf("You hear a warning siren in the distance.\n");

  char name[1024];
  sprintf(name, DATA_USERS "/%s", what->id);
  unlink(name);

  MudObject *scalp=clone_object(MUD_SCALP, who, NULL);
  if (scalp) {
    scalp->setf("desc", "This scalp has a small label sewn to it bearing the name '%M'.", 
		what);

    what->oprintf(avoid(who), "%#M %[combusts/combust] leaving only %M in %P's possession.\n", what, scalp, who);
    who->printf("%#M %[combusts/combust] leaving only %M in your possession.\n", what, scalp);
  } else {
    what->oprintf(avoid(who), "%#M %[combusts/combust] leaving nothing.\n", what);
    who->printf("%#M %[combusts/combust].\n", what);
  }

  return true;
}

extern void sigsegv(int);

static void do_torture(MudObject *what) {
  MudObject *o;
  int i;
  signal(SIGSEGV, &sigsegv);
  foreach(what->children, o, i) {
    do_torture(o);
  }
}

static bool verb_torture(MudObject *, int, const char **) {
  do_torture(mud);
  return true;
}

struct Domain {
    const char *domain;
    const char *dir;
    PFlag create, erase;
    const char *suffix;
} domains[] = {
{ "info", DATA_INFO, PFL_MAKEINFO, PFL_ERASEINFO, ".i" },
{ "help", DATA_HELP, PFL_MAKEHELP, PFL_ERASEHELP, ""  },
{ "policy", DATA_POLICY, PFL_MAKEPOLICY, PFL_ERASEPOLICY, "" },	
{ "files", DATA_FILES, PFL_MAKEFILE, PFL_ERASEFILE, "" },
{ "ac", DATA_ACTIONS, PFL_MAKEINFO, PFL_ERASEINFO, "" },
{ "verb", DATA_VERBS, PFL_CODER,    PFL_CODER, "" },
	{ 0 },
};

typedef struct Domain domain_t;

static domain_t *get_domain(const char *what) {
    domain_t *d = domains;
    while (d->domain) {
	if (streq(d->domain, what))
	    return d;
	d++;
    }
    return NULL;
}

static bool verb_makefile(MudObject *who, int argc, const char **argv) {
    if (argc < 3) {
	who->printf("makefile <domain> <filename>\n");
	return true;
    }
    domain_t *d = get_domain(argv[1]);
    if (!d) {
	who->printf("Can't find that domain.\n");
	return true;
    }
    if (!who->get_priv(d->create) || !is_player(who)) {
	who->printf("You can't do that now.\n");
	return true;
    }
    if (strchr(argv[2], '.') || strchr(argv[2], '/')) {
	who->printf("No.\n");
	return true;
    }
    string f = d->dir;
    f+= "/";
    f+= argv[2];
    f+= d->suffix;
    
    struct stat b;
    if (stat(f.c_str(), &b)==0) {
	who->printf("'%s' already exists. Use \"erasefile\" to erase it first.\n", f.c_str());
	return true;
    }

    FILE *fl = xopen(".", f.c_str(), "w");
    if (!fl) {
	who->printf("Can't open '%s'\n", f.c_str());
	return true;
    }
    
    Player *p = (Player *)who;
    p->push_state(new WriterState(fl));
    p->printf("Use \"**\" to finish.\n");    
    return true;
}

static bool verb_erasefile(MudObject *who, int argc, const char **argv) {
    if (argc < 3) {
	who->printf("erasefile <domain> <filename>\n");
	return true;
    }
    domain_t *d = get_domain(argv[1]);
    if (!d) {
	who->printf("Can't find that domain.\n");
	return true;
    }
    if (!who->get_priv(d->erase) || !is_player(who)) {
	who->printf("You can't do that now.\n");
	return true;
    }
    if (strchr(argv[2], '.') || strchr(argv[2], '/')) {
	who->printf("No.\n");
	return true;
    }
    string f = d->dir;
    f+= "/";
    f+= argv[2];
    f+= d->suffix;
    unlink(f.c_str());
    who->printf("Ok.\n");
    return true;
}

static bool verb_trace(MudObject *who, int argc, const char **argv) {
  MudObject *victim = 0;
  if (argc!=2) {
    who->printf("Syntax : trace <who>.\n");
    return true;
  }
  if (!is_player(who)) {
    who->printf("You are not a player.\n");
    return true;
  }
  victim = planet->get(argv[1]);
  if (!victim) {
    who->printf("No such player as %s.\n", argv[1]);
    return true;
  }
  if (!who->tracing.get(victim->id)) {
    who->trace(victim);
    who->printf("Now tracing %M.\n", victim);
  } else {
    who->detrace(victim);
    who->printf("No longer tracing %M.\n", victim);
  }
  return true;
}

static bool verb_mudcheck(MudObject *player, int argc, const char **argv) {

  Player *p=dynamic_cast<Player*>(player);
  if (!p) {
    return true;
  }

  string fn = "mc2.";
  fn += player->id;
     fn += "-0";
     FILE *badcols = xopen("tmp", fn.c_str(), "w+");

  fn = "mc2.";
  fn += player->id;
  FILE *f = xopen("tmp", fn.c_str(), "w+");
  p->file_divert(f);


  //  fn += "a";
  //  FILE *pis = xopen("tmp", fn.c_str(), "w+");

  //  fn += "2";
  //FILE *bc2 = xopen("tmp", fn.c_str(), "w+");

  MudObject *o;
  int i;
  
  foreach_alpha(planet, o, i) if (!is_player(o) && !o->get_object("cloneof") && o->id[0]!='@') {

    if (!o->get("zone")) {
      continue;
    }
#if 0
    if (o->get_int("value")!=-1 && o->get_int("cost")!=-1) {
      player->printf("%s: value %i, cost %i.\n", o->id, o->get_int("value"), o->get_int("cost"));
      //      o->set("cost", (o->get_int("value")*10)/9);
      o->unset("value");
    }
    continue;
#endif
#if 0    
    if (o->get_int("mass")!=-1) {
      player->printf("%s:%i\n", o->id, o->get_int("mass"));
    } else if (o->get_int("size")!=-1) {
      //       player->printf("%s : has size not mass.\n", o->id);
      player->printf("%s:%i\n", o->id, o->get_int("size")*100);
    continue;
#endif
#if 0
    if (!o->get_flag(FL_ROOM) && !o->get_flag(FL_QUEST) && !o->get_flag(FL_SHIP) && object_depth(o)>2
	&& !is_mobile(o) && !o->get_flag(FL_FIXED) && !o->get_flag(FL_EXIT)) {
      if (o->get_flag(FL_CONTAINER) || o->get_flag(FL_WATERTIGHT)) {

	fprintf(badcols, "stat:%s:%i:%i:%i:%i:%s:%s\n",
		o->id, o->get_int("mass", o->get_int("size")==-1?-1:o->get_int("size")*100), o->get_int("ovolume"),
		o->get_int("maxload", o->get_int("capacity")==-1?-1:o->get_int("capacity")*100), o->get_int("volume"),
		o->get("short"),
		name(o));
      } else {
	fprintf(badcols, "stat:%s:%i:%i:::%s:%s\n",
		o->id, o->get_int("mass", o->get_int("size")==-1?-1:o->get_int("size")*100), o->get_int("ovolume"),
		o->get("short"),
		name(o));
      }
    }
#endif
    if (int v=o->array_size("virt")) {
      for (int j=0;j<v;j++) {
	player->printf("%s - virt.%i (%s) exists.\n", o->id, j, o->array_get("virt", j, "short"));
      }
    }

    if (o->get_object("quarters")) {
      o->unset("quarters");
    }

    if (const char *n=name(o)) {
      if (const char *p=strstr(n, ".")) {
	if (!p[1]) {
	  player->printf("%s - fullstop in name : '%s'\n", o->id, escape_colour(n).c_str());
	}
      }

      if (strncmp(n, "a pair of", 9)==0 && !o->get_flag(FL_PLURAL)) {
	player->printf("%s - isn't plural.\n", o->id);
      }

      if (strncmp(n, "some ", 4)==0) {
	player->printf("%s - some.\n", o->id);
      }
    }

    if (!o->get_flag(FL_ROOM) && !o->get_flag(FL_QUEST) && !o->get_flag(FL_SHIP) && object_depth(o)>2) {

      const char *w = "^o";
      if (is_mobile(o)) 
	w = "^P";

      if (const char *n=name(o)) {
	if (!strstr(n, w)) {
	  player->printf("%s - badcol no %s in name : %s.\n", o->id, w, escape_colour(n).c_str());
	}
      }
      if (const char *n=o->get("short_desc")) {
	if (!strstr(n, w)) {
	  player->printf("%s - badcol no %s in short_desc : %s.\n", o->id, w, escape_colour(n).c_str());
	}
      }
    }

    if (!o->get_flag(FL_MOBILE) && !o->get_flag(FL_FIXED) && !o->get_flag(FL_ROOM) && !o->get_flag(FL_EXIT)) {
      //    o->get_int("

      if (o->get_flag(FL_CONTAINER)) {
	if (o->get_int("maxload")==-1 &&
	    o->get_int("capacity")==-1) {
	  player->printf("%s : has neither maxload nor capacity set.\n", o->id);
	}
      }

      if (o->get_int("mass")==-1 && o->get_int("size")==-1) {
	  player->printf("%s : has neither mass nor size set.\n", o->id);
#if 0
	} else {
	  if (streq(o->get("zone"), "bingo")||
	      streq(o->get("zone"), "gaz")||
	      streq(o->get("zone"), "orion")||
	      streq(o->get("zone"), "holo")||
	      streq(o->get("zone"), "orange")||
	      streq(o->get("zone"), "plett")||
	      streq(o->get("zone"), "secret")) {
	    continue;
	  }
	  set_owner(player, o);
	  p->file_undivert();
	  xclose(f);
	  return true;
#endif
	}
    }

    /* WEAPONS */
    if (o->get_int("damage")>0 && o->get_int("wtype")==-1 && !o->get_flag(FL_MOBILE)) {
      player->printf("%s : is weapon but has no wtype.\n", o->id);
    }

    /* EXITS */
    if (o->id[0]!='@') {
      if (o->get_object("link") && !o->get_flag(FL_EXIT) && !o->get_flag(FL_PARTEXIT)) {
	player->printf("%s : link but not exit.\n", o->id);
      }
      
      if (o->get("link") && !o->get_object("link")) {
	player->printf("%s : exit dangling, link is %s.\n", o->id, o->get("link"));
      }
    }

    /* MOBILES */
    if (is_mobile(o)) {
      /* NOT HAVING VARIOUS PLAYER-SPECIFIC THINGS */
      if (const char *t=o->get("title")) {
	player->printf("%s : has title %s.\n", o->id, t);
      }
      if (o->get_int("level")!=-1) {
	int l = o->get_int("level");
	player->printf("%s : has level %i.\n", o->id, l);
      }

      /* GENDER */
      const char *g = o->get("gender");
      if (g && !strchr("mfanpMFANP", g[0])) {
	player->printf("%s : has unsupported gender %s.\n", o->id, g);
      } else if (!g || !*g) {
	player->printf("%s : has no gender.\n", o->id);
      }


      /* DESCRIPTION */
      if (!o->get("desc") || streq(o->get("desc"), "A typical mobile...")) {
	player->printf("%s : missing desc\n", o->id);
      }

      /* TELLS */
      if (!player->get_flag(FL_NOTELLSPAM)) {
	if (is_mobile(o) && o->get_int("aggr", 0)==0 && !o->get_flag(FL_CANTTALK) && !o->get_flag(FL_POLICE)) {
	  if (!o->get("tell.name")) 
	    {
	      player->printf("%s : no tell.name\n", o->id);
	    }
	  if (!o->get("tell.job")) 
	    {
	      player->printf("%s : no tell.job\n", o->id);
	    }
	  if (!o->get("tell.mission")) 
	    {
	      player->printf("%s : no tell.mission\n", o->id);
	    }
	  if (!o->get("tell.follow")) 
	    {
	      player->printf("%s : no tell.follow\n", o->id);
	    }
	  if (!o->get("tell.help")) 
	    {
	      player->printf("%s : no tell.help\n", o->id);
	    }
	}
      }
    }

    /* QUEST */
    if (o->get_flag(FL_QUEST) && !o->get("mname")) {
      player->printf("%s : no mname\n", o->id);
    }
	 

    /* SHOPS */
    if (o->get_flag(FL_STORE)) {
      int max = o->array_size("shop");
      for (int i=0;i<max;i++) {
	MudObject *m = o->array_get_object("shop", i);
	if (!m) {
	  player->printf("%s : shop.%i - %s left dangling\n", o->id, i, o->array_get("shop", i));
	}
      }

      if (!o->get_object("shopmob")) {
	player->printf("%s : shopmob %s bad.\n", o->id, o->get("shopmob"));
      }

      if (!o->array_size("tele")) {
	o->array_set("tele", 0, "template_list_1");
	player->printf("%s : shop doesn't have a list as a tele-object.\n", o->id);
      }
    }

    /* BANKS */
    if (o->get_flag(FL_BANK)) {
      MudObject *bankmob=o->get_object("bankmob");
      if (!bankmob) {
	player->printf("%s : bankmob %s bad.\n", o->id, o->get("bankmob"));
      } else {
	if (bankmob->get_object("start")!=o) {
	  player->printf("%s : bankmob %s doesn't start at right place.\n", o->id, bankmob->id);
	}
      }
    }

    /* TELEOBJECTS */
    int max = o->array_size("tele");
    for (int i=0;i<max;i++) {
      MudObject *t = o->array_get_object("tele", i);
      if (t && !t->get_flag(FL_FIXED)) {
	player->printf("%s : tele.%i is non-Fixed %s.\n", o->id, i, t->id);
      }
      if (t && t->get_flag(FL_CONTAINER)) {
	player->printf("%s : tele.%i is a Container %s.\n", o->id, i, t->id);
      }
    }

    /* AUTOOBJECTS */
    max = o->array_size("auto");
    for (int i=0;i<max;i++) {
      MudObject *t = o->array_get_object("auto", i);
      if (t && t->get_flag(FL_FIXED) && !t->get_flag(FL_CONTAINER) 
	  && !t->get_flag(FL_CANSITON) && !t->get_flag(FL_CANOPEN)
	  && t->get_flag(FL_INVISIBLE)) {
    	player->printf("%s : auto.%i is Fixed, non-Container, non-CanSiton, non-CanOpen, Invisible %s.\n", o->id, i, t->id);
      }
    }

    /* ROOMS */
    if (is_room(o) && !is_mobile(o) && !is_player(o)) {
      if (!o->get("desc")) {
	player->printf("%s : missing desc\n", o->id);
      }
      if (const char *d=o->get("desc")) {
	if (strstr(d, "standing")) 
	  fprintf(badcols, "%s : %s\n", o->id, d);
      }
    }

    /* OBJECTS */
    if (!is_room(o) && !is_mobile(o) && !o->get_flag(FL_ROOM)) {
      if (o->get("wornon") && o->get_int("wornlevel")==-1) {
	player->printf("%s : doesn't have wornlevel set.\n", o->id);
      }


      if (const char *sd=o->get("short_desc")) {
	if (strchr(sd, '.')) {
	  player->printf("%s : has . in short_desc %s\n", o->id, escape_colour(sd).c_str());
	}
	const char *n = name(o);
	if (n && sd && strcasecmp(n, sd)==0) {
	  player->printf("%s : short_desc and name are the same! ('%s' and '%s')\n", 
			 o->id, sd, n);
	  o->unset("short_desc");
	}
      }
      if (const char *n=name(o)) {
	if (isupper(n[0])) {
	  player->printf("%s : capital letter starts name %s\n", o->id, n);
	}
      }

     
      /* DRINK! */
      if (o->get_flag(FL_DRINK)) {
	if (!o->get_object("empty")) {
	  player->printf("%s : doesn't have an empty set.\n", o->id);
	}
	if (!o->get_object("substance")) {
	  player->printf("%s : doesn't have a substance set.\n", o->id);
	}
      }

      /* WATERTIGHT CONTAINERS */
#if 0
      if (o->get_flag(FL_WATERTIGHT)) {
	if (o->get_int("volume")==-1) {
	  player->printf("%s : doesn't have volume set.\n", o->id);
	}
      }
#endif
    }
  }

  p->file_undivert();

    xclose(f);
    xclose(badcols);
  //  xclose(pis);
  //  xclose(bc2);

  p->spewfile("tmp", fn.c_str(), 1, argc<2?"":argv[1]);

  return true;
}

/* 
 * levellock is
 *
 *   -1 : unlocked
 *    1 : new characters aren't allowed, level1 are
 *    2 : level1 chars aren't allowed, level2 are
 */

static bool verb_levellock(MudObject *who, int argc, const char **argv) 
{
  if (argc < 2) {
    who->printf("Levellock to which level?\n");
    return true;
  }
  int current = mud->get_int("levellock");
  int to = atoi(argv[1]);
  if (!strcasecmp(argv[1], "off") || to == 0)
    to = -1;

  if (current == to) {
    if (current != -1)
      who->printf("The mud is already locked at that level.\n");
    else
      who->printf("The mud is already unlocked.\n");
    return true;
  }

  if (to > privs_of(who)) {
    who->printf("You can't lock the mud as high as that.\n");
    return true;
  }

  MudObject *smith = MUD_ANNOUNCER;

  if (to == -1) {
    log(PFL_SEEINFO, LEV_INTERNAL, "admin", "mud is declared open");

    if (smith) {
      smith->interpretf("%s The mud is now fully open!", MUD_ANNCH);
    }
  } else if (to == 1) {
    log(PFL_SEEINFO, LEV_INTERNAL, "admin", "new players are locked out");

    if (smith) {
      smith->interpretf("%s New players have been locked out.", MUD_ANNCH);
    }
  }
  else
    {
    log(PFL_SEEINFO, LEV_INTERNAL, "admin", "players lower than level %i are locked out",
	to);

    if (smith) {
      smith->interpretf("%s Players ranking %s and lower have been locked out.",
			MUD_ANNCH, long_rank(to-1));
    }
  }

  mud->set("levellock", to);
  return true;
}

#include "verbmodule.h"

void startup() {
AUTO_VERB(makefile, 5, 0, PFL_NONE);
AUTO_VERB(erasefile, 6, 0, PFL_NONE);

AUTO_VERB(torture, 4, 0, PFL_GOD);

AUTO_VERB(bans, 4, 0, PFL_BAN);
AUTO_VERB(addban, 4, 0, PFL_BAN);
AUTO_VERB(remban, 4, 0, PFL_BAN);
AUTO_VERB(fds, 3, 0, PFL_HOSTS);

AUTO_VERB(modulelist, 4, 0, PFL_NONE);

AUTO_VERB(reboot, 6, 0, PFL_CODER, VFL_OKNOOWNER);
AUTO_VERB(savezones, 5, 0, PFL_MAKE, VFL_OKNOOWNER);

AUTO_VERB(savevar, 5, 0, PFL_MAKE, VFL_OKNOOWNER);

AUTO_VERB(reset, 5, 0, PFL_RESET, VFL_OKNOOWNER);
AUTO_VERB(rtz, 3, 0, PFL_RESET);

AUTO_VERB(shutdown, 5, 0, PFL_SHUTDOWN, VFL_OKNOOWNER);

AUTO_VERB(force, 4, 0, PFL_NONE, VFL_OKNOOWNER);

AUTO_VERB(mudcheck, 5, 0, PFL_MAKE);
ADD_VERB("mudfix", 3, verb_mudcheck, 0, PFL_MAKE);

AUTO_VERB(mudcrash, 8, 0, PFL_GOD);
AUTO_VERB(magic, 5, 0, PFL_CODER);
AUTO_VERB(snoop, 5, 0, PFL_SNOOP);
AUTO_VERB(desnoop, 5, 0, PFL_SNOOP);
AUTO_VERB(loadflags, 5, 0, PFL_CODER);

AUTO_VERB(zap, 3, 0, PFL_ZAP);

AUTO_VERB(savethiszone, 5, 0, PFL_MAKE);
AUTO_VERB(trace, 5, 0, PFL_TRACE);
ADD_ALIAS(stz, 3, savethiszone);

AUTO_VERB(levellock, 6, 0, PFL_CODER);

}