dmuck0.15-beta/docs/muf/
dmuck0.15-beta/game/
dmuck0.15-beta/game/logs/
dmuck0.15-beta/game/muf/
dmuck0.15-beta/game/muf/text/
#include "copyright.h"
#include "config.h"

#include "db.h"
#include "params.h"
#include "interface.h"
#include "externs.h"

static char buf[BUFFER_LEN];
static hash_tab player_table[PLAYER_HASH_SIZE];

typedef struct player_match
{
  char *name;
  struct player_match *next;
  dbref d;
} player_match;

static player_match *player_list = NULL, *pm, *pm_next;

dbref lookup_player(char *name)
{
  dbref player = NOTHING;
  hash_data *hd;
  char *current, *next;

  for(current = name; current; current = next)
  {
    next = (char *)strchr(current, EXIT_DELIMITER);
    if (next)
    {
      strncpy(buf, current, next - current);
      buf[next++ - current] = '\0';
    }
    else strcpy(buf, current);
    if ((hd = find_hash(buf, player_table, PLAYER_HASH_SIZE)))
      player = (player == NOTHING) ? hd->dbval : AMBIGUOUS;
  }
  return player;
}

dbref connect_player(char *name, char *password)
{
  dbref player;
  
  if((player = lookup_player(name)) == NOTHING) return NOTHING;
  if(DBFETCH(player)->sp.player.password
     && *DBFETCH(player)->sp.player.password
     && check_password(password, player)) return NOTHING;
  return player;
}

dbref create_player(char *name, char *password, dbref doer)
{
  dbref player;
  
  if(!ok_player_name(name, NOTHING) || !ok_password(password)) return NOTHING;
  if(o_taboonames) {
        if(doer == NOTHING)
           if(!ok_taboo_name(NOTHING, name, 0)) return NOTHING;
        else
           if(!ok_taboo_name(NOTHING, name, 0) && !Wizard(doer)) return NOTHING;
   }

  /* else he doesn't already exist, create him */
  player = new_object();

  /* initialize everything */
  NAME(player) = dup_string(name);
  DBSTORE(player, location, PLAYER_START);
  DBSTORE(player, link, PLAYER_START);
  add_backlinks(player);
  DBSTORE(player, nextowned, NOTHING);
#ifdef DEFAULT_PFLAGS
  DBSTORE(player, flags, TYPE_PLAYER | DEFAULT_PFLAGS);
#else /* !DEFAULT_PFLAGS */
  DBSTORE(player, flags, TYPE_PLAYER);
#endif /* DEFAULT_PFLAGS */
  DBSTORE(player, owner, player);
  DBSTORE(player, exits, NOTHING);
  DBSTORE(player, pennies, DEFAULT_PENNIES);
  DBSTORE(player, sp.player.password, dup_string(password));
  DBSTORE(player, sp.player.password,
    make_password(DBFETCH(player)->sp.player.password));
  DBSTORE(player, curr_prog, NOTHING);
  DBSTORE(player, sp.player.insert_mode, 0);
  DBSTORE(player, sp.player.pid, 0);

  /* link him to PLAYER_START */
  PUSH(player, DBFETCH(PLAYER_START)->contents);
  add_player(player);
  DBDIRTY(PLAYER_START);

  return player;
}

void do_password(__DO_PROTO)
{
  /* nuke .last property */
  add_property(player, ".last", "@password", PERMS_COREAD | PERMS_COWRITE,
    ACCESS_CO);

  if(!DBFETCH(player)->sp.player.password || check_password(arg1, player))
    notify(player, player, "Sorry");
  else if(!ok_password(arg2)) notify(player, player, "Bad new password.");
  else
  {
    free(DBFETCH(player)->sp.player.password);
    DBSTORE(player, sp.player.password, dup_string(arg2));

    DBFETCH(player)->sp.player.password =
      make_password(DBFETCH(player)->sp.player.password);

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

/* nukes all player hashtable stuff */
void clear_players()
{
  kill_hash(player_table, PLAYER_HASH_SIZE, 0);
  for(pm = player_list; pm; pm = pm_next)
  {
    pm_next = pm->next;
    free(pm->name);
    free(pm);
  }
}

void delete_player(dbref who)
{
  player_match *pm, *pm_next;
  char *current, *next;

  for(current = NAME(who); current; current = next)
  {
    next = (char *)strchr(current, EXIT_DELIMITER);
    if (next)
    {
      strncpy(buf, current, next - current);
      buf[next++ - current] = '\0';
    }
    else strcpy(buf, current);
    free_hash(buf, player_table, PLAYER_HASH_SIZE);
  }

  while(player_list && (player_list->d == who))
  {
    pm_next = player_list->next;
    free(player_list->name);
    free(player_list);
    player_list = pm_next;
  }

  pm = player_list;
  while (pm && pm->next)
  {
    while (pm && pm->next && (pm->next->d == who))
    {
      pm_next = pm->next;
      pm->next = pm_next->next;
      free(pm_next->name);
      free(pm_next);
    }
    if(pm) pm = pm->next;
  }
}

void add_player(dbref who)
{
  hash_data hd;
  char *current, *next;

  for(current = NAME(who); current; current = next)
  {
    next = (char *)strchr(current, EXIT_DELIMITER);
    if (next)
    {
      strncpy(buf, current, next - current);
      buf[next++ - current] = '\0';
    }
    else strcpy(buf, current);
/*  Will this work????? */
    if(buf[0] == '\0') return;
    pm = (player_match *)malloc(sizeof(player_match));
    pm->d = who;
    pm->name = dup_string(buf);
    pm->next = player_list;
    player_list = pm;
    hd.dbval = who;
    if(!add_hash(pm->name, hd, player_table, PLAYER_HASH_SIZE))
      panic("Out of memory");
  }
}

int awake_count(dbref player)
{
  descriptor_data *d;
  int retval = 0;
  
  if (FLAGS(player) & DARK) return 0;
  for(d = descriptor_list; d; d = d->next)
  {
    if (d->connected && d->player == player)
      retval++;
  }
  return retval;
}

void do_player_setuid(__DO_PROTO)
{
  descriptor_data *d;
  dbref new_player;

  /* nuke .last property */
  add_property(player, ".last", "@user", PERMS_COREAD | PERMS_COWRITE,
    ACCESS_CO);

  new_player = lookup_player(arg1);
  if (new_player == NOTHING)
  {
     notify(player, player, "Invalid player name. UID remains unchanged.");
     return;
   }

  if (awake_count(player) != 1)
  {
     notify(player, player,
       "Cannot set UID if you are connected more than once.");
     log_status("UID CHANGE: From %s to %s FAILED, multiple connects.\n",
        NAME(player), NAME(new_player));
     return;
  }

  if (awake_count(new_player) != 0)
  {
     notify(player, player, "Cannot set UID to that of a connected player.");
     log_status("UID CHANGE: From %s to %s FAILED, already connected.\n",
        NAME(player), NAME(new_player));
     return;
  }

  if((!DBFETCH(new_player)->sp.player.password
    || check_password(arg2, new_player))
    && !controls(player, new_player))
  {
    notify(player, player, "Permission denied.");
    log_status("UID CHANGE: From %s to %s FAILED, BAD PASSWORD!!!\n",
    NAME(player), NAME(new_player));

  }
  else
  {
    for(d = descriptor_list; d; d = d->next) 
    if (d->connected && d->player == player) d->player = new_player;
    log_status("UID CHANGE: From %s to %s, successful.\n",
      NAME(player),NAME(new_player));
    notify(new_player, new_player, "UID changed.");

 if(o_notify_wiz) {
    /* tell wizards online that someone has setuid */
    sprintf(buf, "%s has setuid to ", unparse_name(player));
    strcat(buf, unparse_name(new_player));
    strcat(buf, ".");
    notify_wizards(buf);
   }
  }
  return;
}