TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include "db.h"
#include "externs.h"
#include "config.h"
#include "powers.h"

void do_force(OBJ *player, char *what, char *command)
{
  OBJ *victim;
  
  if(!(victim = match_object(player, what, NOTYPE)))
    return;
  
  if(is_root(victim))
  {
    notify(player, "You can't force root!!");
    return;
  }

  if(Typeof(victim) == TYPE_PLAYER && player != victim)
    log_force(tprintf("%s executed: @force %s=%s",
      unparse_object(player, player), what, command));

  process_command(NULL, victim, command, player);
}

void do_stats(OBJ *player, char *arg)
{
  OBJ *who, *o;
  char *p;
  int total, players, things, rooms, exits, pseudo_exits;

  total = players = things = rooms = exits = pseudo_exits = 0;

  if(!*arg)
    who = NULL;
  else
  {
    who = match_object(player, arg, TYPE_PLAYER);
    if(!who)
    {
      notify(player, no_match(arg));
      return;
    }
  }

  for(o = player_list;o;o = o->next)
  {
    if(who && who->owner != player)
      continue;
    players++;
    total++;
  }
  for(o = thing_list;o;o = o->next)
  {
    if(who && who->owner != player)
      continue;
    things++;
    total++;
  }
  for(o = room_list;o;o = o->next)
  {
    if(who && who->owner != player)
      continue;
    if(*(p = atr_get(o, "North")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "South")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "East")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "West")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "Northeast")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "Northwest")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "Southeast")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    if(*(p = atr_get(o, "Southwest")))
      if(match_dbref(p, TYPE_ROOM))
        pseudo_exits++;
    rooms++;
    total++;
  }
  for(o = exit_list;o;o = o->next)
  {
    if(who && who->owner != player)
      continue;
    exits++;
    total++;
  }

  if(!who)
    notify(player,
      tprintf("|+W|%s Database Breakdown:", config.maze_name));
  else
    notify(player, tprintf("|+W|%s database breakdown for %s:",
      config.maze_name, unparse_object(player, who)));
  notify(player,
    tprintf("|+C|%7d |+B|Total Objects", total));
  notify(player, tprintf("|+C|%7d |+B|Player%s",
    players, check_plural(players, "", "s")));
  notify(player, tprintf("|+C|%7d |+B|Thing%s",
    things, check_plural(things, "", "s")));
  notify(player, tprintf("|+C|%7d |+B|Room%s",
    rooms, check_plural(rooms, "", "s")));
  notify(player, tprintf("|+C|%7d |+B|Exit%s",
    exits, check_plural(exits, "", "s")));
  notify(player, tprintf("|+C|%7d |+B|Pseudo Exit%s",
    pseudo_exits, check_plural(pseudo_exits, "", "s")));
}

void do_pbreak(OBJ *player)
{
  OBJ *o;
  int num;
  int num_in_class[NUM_CLASSES];

  for(num = 0;num < NUM_CLASSES;num++)
    num_in_class[num] = 0;

  num = 0;

  for(o = player_list;o;o = o->next)
  {
    num_in_class[get_class(o)]++;
    num++;
  }

  notify(player, tprintf("|+W|%s Player Breakdown:", config.maze_name));
  notify(player, tprintf("|+C|%7d |+B|Players", num));

  for(num = 0;num < NUM_CLASSES;num++)
    notify(player, tprintf("|+C|%7d |+B|%ss",
      num_in_class[num], class_to_name(num)));
}

void do_wipeout(OBJ *player, char *arg1, char *arg2)
{
  OBJ *victim, *o;
  int type;
  
  log_sensitive(tprintf("%s tries @wipeout %s=%s",
    unparse_object(player, player), arg1, arg2));
  
  victim = match_object(player, arg1, TYPE_PLAYER);
  if(!victim)
  {
    notify(player, no_match(arg1));
    return;
  }
  if(!controls(player, victim, POW_MODIFY))
  {
    notify(player, perm_denied());
    return;
  }
  if(string_prefix("objects", arg2))
    type = TYPE_THING;
  else if(string_prefix("rooms", arg2))
    type = TYPE_ROOM;
  else if(string_prefix("exits", arg2))
    type = TYPE_EXIT;
  else if(!strcmp("all", arg2))
    type = NOTYPE;
  else
  {
    notify(player, "Please specify one of: objects, rooms, exits");
    return;
  }

  if(type & TYPE_THING)
    for(o = thing_list;o;o = o->next)
      if(o->owner == victim)
        destroy_obj(o);
  if(type & TYPE_ROOM)
    for(o = room_list;o;o = o->next)
      if(o->owner == victim)
        destroy_obj(o);
  if(type & TYPE_EXIT)
    for(o = exit_list;o;o = o->next)
      if(o->owner == victim)
        destroy_obj(o);

  switch(type)
  {
    case TYPE_THING:
      notify(player, "Wiped out all objects.");
      notify(victim,
        tprintf("All your objects have been destroyed by %s.",
        unparse_object(victim, player)));
    break;
  case TYPE_ROOM:
    notify(player, "Wiped out all rooms.");
    notify(victim, tprintf("All your rooms have been destroyed by %s.",
      unparse_object(victim, player)));
    break;
  case TYPE_EXIT:
    notify(player, "Wiped out all exits.");
    notify(victim, tprintf("All your exits have been destroyed by %s.",
      unparse_object(victim, player)));
    break;
  case NOTYPE:
    notify(player, "Wiped out everything.");
    notify(victim,
      tprintf("Everything you owned has been destroyed by %s.",
        unparse_object(victim, player)));
    break;
  }
}

void do_chownall(OBJ *player, char *arg1, char *arg2)
{
  OBJ *playerA, *playerB;
  OBJ *o;

  log_sensitive(tprintf("%s tries @chownall %s=%s",
    unparse_object(player, player), arg1, arg2));
  playerA = match_object(player, arg1, TYPE_PLAYER);
  if(!playerA)
  {
    notify(player, no_match(arg1));
    return;
  }
  playerB = match_object(player, arg2, TYPE_PLAYER);
  if(!playerB)
  {
    notify(player, no_match(arg2));
    return;
  }

  if(playerA == playerB)
  {
    notify(player, "That's silly!");
    return;
  }

  for(o = thing_list;o;o = o->next)
    if(o->owner == playerA)
      o->owner = playerB;
  for(o = room_list;o;o = o->next)
    if(o->owner == playerA)
      o->owner = playerB;
  for(o = exit_list;o;o = o->next)
    if(o->owner == playerA)
      o->owner = playerB;

  notify(player, "Ownership changed.");
}

void do_newpassword(OBJ *player, char *arg1, char *password)
{
  OBJ *victim;
  
  if(!power(player, POW_NEWPASS))
  {
    notify(player, perm_denied());
    return;
  }

  victim = match_object(player, arg1, TYPE_PLAYER);
  if(!victim)
  {
    notify(player, no_match(arg1));
    return;
  }

  if(!*password || !ok_password(password))
  {
    notify(player, "Bad password.");
    return;
  }

  if(is_root(victim))
  {
    notify(player, perm_denied());
    return;
  }

  if(player == victim)
  {
    notify(player, "You must @password to change your own password.");
    return;
  }

  atr_add(victim, "PASSWORD", crypt(password, "XX"));
  notify(player, "Password changed.");
  log_sensitive(tprintf("%s(%d) executed: @newpassword %s",
    name(player), player->dbref, unparse_object(victim, victim)));
  notify(victim, tprintf("Your password has been changed by %s.",
   unparse_object(victim, player)));
}

void do_boot(OBJ *player, char *arg, char *reason)
{
  OBJ *victim;

  if(!power(player, POW_BOOT))
  {
    notify(player, perm_denied());
    return;
  }

  if(!(victim = match_object(player, arg, TYPE_PLAYER)))
  {
    notify(player, no_match(arg));
    return;
  }

  if(is_root(victim) || !controls(player, victim, POW_BOOT))
  {
    notify(player, perm_denied());
    return;
  }

/* Make sure they're actually connected */
  if(!is_connected_raw(victim))
  {
    notify(player, tprintf("%s isn't connected.", name(victim)));
    return;
  }

  if(!*reason)
  {
    notify(player, "You must specify a reason for booting someone.");
    return;
  }

/* Notify people */
  notify(player, tprintf("%s - Booted.", name(victim)));
  log_sensitive(tprintf("%s(#%d) executed: @boot %s(#%d). Reason: %s",
    player->name, player->dbref, victim->name, victim->dbref, reason));
  notify(victim, tprintf("You have been booted by %s.\nReason: %s",
    unparse_object(victim, player), reason));
  boot_off(victim);
}

void do_dboot(OBJ *player, char *arg1, char *reason)
{
  DDATA *d;
  int toboot;

  if(!power(player, POW_BOOT))
  {
    notify(player, perm_denied());
    return;
  }

  if(!isdigit(*arg1))
  {
    notify(player, "Bad descriptor.");
    return;
  }
  
  toboot = atoi(arg1);
  
  for(d = descriptor_list;d;d = d->next)
    if(d->descriptor == toboot)
      break;
  
  if(!d)
  {
    notify(player, "Unable to find specified descriptor.");
    return;
  }
  
  if(!*reason)
  {
    notify(player, "You must specify a reason for booting someone.");
    return;
  }

  if(check_state(d, STATE_CONNECTED))
  {
    if(!controls(player, d->player, POW_BOOT))
    {
      notify(player, perm_denied());
      return;
    }

    log_sensitive(tprintf("%s(#%d) executes: @dboot %d (player %s(#%d)). Reason: %s",
      player->name, player->dbref, toboot,
      d->player->name, d->player->dbref, reason));
    notify(player,
      tprintf("Descriptor %d (player %s) - Booted.",
      toboot, unparse_object(player, d->player)));
    shutdownsock(d);
  }
  else
  {
    log_sensitive(tprintf("%s(#%d) executes: @dboot %d (unconnected from host %s). Reason: %s",
      player->name, player->dbref, toboot, d->addr, reason));
    notify(player, tprintf("Descriptor %d - Booted.", toboot));
    shutdownsock(d);
  }
}
  
void do_su(OBJ *player, char *arg1, char *arg2)
{
  OBJ *thing;
  DDATA *d;

  thing = match_object(player, arg1, TYPE_PLAYER);
  if(!thing)
  {
    notify(player, no_match(arg1));
    return;
  }

  if(is_root(thing))
  {
    notify(player, "You can't @su to root!");
    return;
  }

  if(player == thing)
  {
    notify(player, "You can't @su to yourself.");
    return;
  }

  if(!*arg2 && !controls(player, thing, POW_MODIFY))
  {
    notify(player, perm_denied());
    return;
  }
  else
  {
    if(!check_password(thing, arg2))
    {
      notify(player, perm_denied());
      return;
    }
  }

  for(d = descriptor_list;d;d = d->next)
    if(check_state(d, STATE_CONNECTED) && d->player == player)
      break;

  if(!d)
  {
    notify(player, "Only connected players can use @su!");
    return;
  }

  announce_disconnect(d);
  d->player = thing;
  announce_connect(d);
}

void do_gethost(OBJ *player, char *arg1)
{
  OBJ *who;
  DDATA *d;

  if(!power(player, POW_HOST))
  {
    notify(player, perm_denied());
    return;
  }

  who = match_object(player, arg1, TYPE_PLAYER);
  if(!who)
  {
    notify(player, no_match(arg1));
    return;
  }

  for(d = descriptor_list;d;d = d->next)
    if(check_state(d, STATE_CONNECTED) && d->player == who)
      notify(player, tprintf("Site for %s: %s@%s", 
        unparse_object(who, who), d->user, d->addr));
}

void do_listconnections(OBJ *player)
{
  DDATA *d;

  if(!power(player, POW_HOST))
  {
    notify(player, perm_denied());
    return;
  }

  for(d = descriptor_list;d;d = d->next)
    if(check_state(d, STATE_CONNECTED))
      notify(player,
        tprintf("%s |+M|- |+B|Descriptor: |+W|%d |+M|- |+B|Host: |+W|%s@%s",
        unparse_object(player, d->player), d->descriptor, d->user, d->addr));
    else
      notify(player,
        tprintf("|+C|Not Connected |+M|- |+B|Descriptor: |+W|%d |+M|- |+B|Host: |+W|%s@%s",
        d->descriptor, d->user, d->addr));
}

void do_botspot(OBJ *player, char *arg)
{
  OBJ *victim;
  DDATA *d, *d2, *dprev = NULL;

  if(!power(player, POW_SECURITY))
  {
    notify(player, perm_denied());
    return;
  }

  if(!*arg)
    victim = player;
  else
  {
    victim = match_object(player, arg, TYPE_PLAYER);
    if(!victim)
    {
      notify(player, no_match(arg));
      return;
    }
  }

  for(d = descriptor_list;d;d = d->next)
  {
    if(!check_state(d, STATE_CONNECTED))
      continue;
    if(d->player == victim)
      break;
    dprev = d;
  }

  if(!d)
  {
    notify(player, "You may only use this command on connected players.");
    return;
  }

/* Find the last descriptor in the list */
  for(d2 = descriptor_list;d2->next;d2 = d2->next);

  if(d == d2)
  {
    notify(player, tprintf("%s already has the botspot!", name(victim)));
    return;
  }

  if(dprev)
    dprev->next = d->next;
  else
    descriptor_list = descriptor_list->next;

  d2->next = d;
  d->next = NULL;

  log_sensitive(tprintf("%s gave %s the botspot!",
    unparse_object(player, player), name(victim)));

  notify(player, tprintf("%s now has the botspot.", name(victim)));
  if(player != victim)
    notify(victim, tprintf("%s gave you the botspot.", name(player)));
}

void do_admin(OBJ *player)
{
  int i, j;
  OBJ *plyr, *temp;
  OBJ **list = NULL;
  int ctr = 0;
  char idle_str[256];
  DDATA *d;

  for(plyr = player_list;plyr;plyr = plyr->next)
  {
    if(is_root(plyr) || get_class(plyr) <= CLASS_CITIZEN)
      continue;

    if(!ctr)
      list = (OBJ **)stack_alloc(sizeof(OBJ *), 0, 0);
    else
      list = (OBJ **)stack_realloc_tmp(list, sizeof(OBJ *)*(ctr+1));
    list[ctr++] = plyr;
  }

  if(!ctr)
  {
    notify(player,
      tprintf("|+W|There are no admins on %s.", config.maze_name));
    return;
  }

  for(i = 0;i < ctr-1;++i)
    for(j = i+1;j < ctr;++j)
      if(get_class(list[i]) < get_class(list[j]))
      {
        temp = list[i];
        list[i] = list[j];
        list[j] = temp;
      }

  notify(player, tprintf("|+B|.%s.", my_string("-", 50)));
  notify(player, tprintf("|+B|||+W|%s|+B||",
    my_center(tprintf("%s Staff Members", config.maze_name), 50)));
  notify(player, tprintf("|+B||%s|", my_string("-", 50)));
  notify(player,
    tprintf("|+B|||+W|%s|+B|||+W| Rank  |+B|||+W| Online? |+B|||+W| Idle |+B||",
    my_center("Name", 25)));
  notify(player, tprintf("|+B||%s|-------|%s|------|",
    my_string("-", 25), my_string("-", 9)));

/* List the players */
  for(i = 0;i < ctr;++i)
  {
    plyr = list[i];

    if(!is_connected(player, plyr))
      strcpy(idle_str, "N/A");
    else
    {
      if(!(d = is_idle(plyr)))
        strcpy(idle_str, "No");
      else
        strcpy(idle_str, time_format(now-d->last_time, 1));
    }

    notify(player,
      tprintf("|+B|| %s|+B|||+C| %s |+B|||+C|%s|+B|||+C|%s|+B||",
      my_ljust(name(plyr), 24),
      short_class_to_name(get_class(plyr)),
      (is_connected(player, plyr))?"   YES   ":"   NO    ",
      my_center(idle_str, 6)));
  }

  notify(player, tprintf("|+B|`%s'", my_string("-", 50)));
}