cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
#include <sys/file.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <errno.h>
#include <malloc.h>
#include "pflags.h"
#include "kernel.h"
#include "sflags.h"
#include "mflags.h"
#include "eflags.h"
#include "clone.h"
#include "nflags.h"
#include "uaf.h"
#include "mobile.h"
#include "flags.h"
#include "exit.h"
#include "sendsys.h"
#include "mud.h"
#include "bprintf.h"
#include "wizlist.h"
#include "bootstrap.h"
#include "log.h"
#include "parse.h"
#include "locations.h"
#include "quests.h"
#include "utils.h"
#include "cflags.h"
#include "levels.h"
#include "stdlib.h"
#include "objsys.h"
#include "fight.h"

extern int errno;
time_t time (time_t * v);

extern char *levnam(int lev, int class, Boolean sex);

#define UAF_VERSION 6                /* increment to add changes         */
#define NUM_ENT     55               /* number of variables to save/load */
#define LLEN        256              /* max length of a pfile line       */
#define TOKEN_LEN   11               /* Length of space before value     */
#define NOVAL      (long int *) 0
#define INT         0
#define CHAR        1
#define PTR         2

typedef struct __iorec {
  short int type;            /* Type of value: int char ptr */
  char *token;               /* Name of text token */
  char **sval;               /* String value to load */
  long int *ival;            /* Integer to load */
} IORec;

Boolean save_load_plr(PERSONA *d, char *player, Boolean save, Boolean new) {
  int i;
  FILE *fptr = NULL;
  IORec *pptr = NULL;
  char *token = NULL;
  char file[256], line[256], *nptr, *value;

  IORec p_rec[NUM_ENT] = {

    /* arrays */

    {CHAR, "Title",       (char **) &(d->player.ptitle),    NOVAL},
    {CHAR, "Passwd",      (char **) &(d->player.passwd),    NOVAL},
    {CHAR, "Username",    (char **) &(d->rplr.usrname),     NOVAL},
    {CHAR, "LastHost",    (char **) &(d->rplr.hostname),    NOVAL},

    /* pointers to char */

    {PTR,  "Awaymsg",     &(d->player.awaymsg),             NOVAL},
    {PTR,  "Prompt",      &(d->player.prompt),              NOVAL},
    {PTR,  "Setin",       &(d->player.setin),               NOVAL},
    {PTR,  "Setout",      &(d->player.setout),              NOVAL},
    {PTR,  "Setmin",      &(d->player.setmin),              NOVAL},
    {PTR,  "Setmout",     &(d->player.setmout),             NOVAL},
    {PTR,  "Setvin",      &(d->player.setvin),              NOVAL},
    {PTR,  "Setvout",     &(d->player.setvout),             NOVAL},
    {PTR,  "Setqin",      &(d->player.setqin),              NOVAL},
    {PTR,  "Setqout",     &(d->player.setqout),             NOVAL},
    {PTR,  "Setsit",      &(d->player.setsit),              NOVAL},
    {PTR,  "Setstand",    &(d->player.setstand),            NOVAL},
    {PTR,  "Setsum",      &(d->player.setsum),              NOVAL},
    {PTR,  "Setsin",      &(d->player.setsumin),            NOVAL},
    {PTR,  "Setsout",     &(d->player.setsumout),           NOVAL},

    /* integers */

    {INT,  "PLines",      NULL,                (long *) &d->player.pager.len},
    {INT,  "CarryCap",    NULL,                (long *) &d->player.pcarry},
    {INT,  "Score",       NULL,                (long *) &d->ublock.pscore},
    {INT,  "Strength",    NULL,                (long *) &d->ublock.pstr},
    {INT,  "Damage",      NULL,                (long *) &d->ublock.pdam},
    {INT,  "Armor",       NULL,                (long *) &d->ublock.parmor},
    {INT,  "Visibility",  NULL,                (long *) &d->ublock.pvis},
    {INT,  "Level",       NULL,                (long *) &d->ublock.plev},
    {INT,  "Wimpy",       NULL,                (long *) &d->ublock.pwimpy},
    {INT,  "Magic",       NULL,                (long *) &d->player.pmagic},
    {INT,  "Channel",     NULL,                (long *) &d->player.pchannel},
    {INT,  "Killed",      NULL,                (long *) &d->player.pkilled},
    {INT,  "Died",        NULL,                (long *) &d->player.pdied},
    {INT,  "Coins",       NULL,                (long *) &d->player.coins},
    {INT,  "Class",       NULL,                (long *) &d->ublock.class},

    /* long ints */

    {INT,  "FirstOn",     NULL,                     &d->player.first_on},
    {INT,  "TimeOn",      NULL,                     &d->player.time_on},
    {INT,  "MortalTime",  NULL,                     &d->player.mortal_time},
    {INT,  "WizTime",     NULL,                     &d->player.wiz_time},
    {INT,  "SpellsH",     NULL,                     &d->ublock.pspells.h},
    {INT,  "SpellsL",     NULL,                     &d->ublock.pspells.l},
    {INT,  "NFlags",      NULL,                     &d->ublock.pnflags},
    {INT,  "Home",        NULL,                     &d->ublock.phome},
    {INT,  "LastOn",      NULL,                     &d->player.last_on},
    {INT,  "ID",          NULL,                     &d->ublock.id},
    {INT,  "EFlagsH",     NULL,                     &d->ublock.peflags.h},
    {INT,  "EFlagsL",     NULL,                     &d->ublock.peflags.l},
    {INT,  "SFlagsH",     NULL,                     &d->ublock.psflags.h},
    {INT,  "SFlagsL",     NULL,                     &d->ublock.psflags.l},
    {INT,  "PFlagsU",     NULL,                     &d->ublock.pflags.u},
    {INT,  "PFlagsH",     NULL,                     &d->ublock.pflags.h},
    {INT,  "PFlagsL",     NULL,                     &d->ublock.pflags.l},
    {INT,  "MaskU",       NULL,                     &d->ublock.pmask.u},
    {INT,  "MaskH",       NULL,                     &d->ublock.pmask.h},
    {INT,  "MaskL",       NULL,                     &d->ublock.pmask.l},
    {INT,  "QFlags",      NULL,                     &d->player.pquests}};

  if (!valid_fname(player) && (save || new)) {
    bprintf("Sorry, that name has illegal characters.\n");
    return(False);
  }

  for (nptr = player; *nptr; nptr++)
    if (isalpha(*nptr))
      *nptr = tolower(*nptr);
  *player = toupper(*player);
  sprintf(file, "%s/%c/%s", TEXT_PFILES_BASE, *player, player);

  if (save) {
    if (access(file, F_OK) && !new)  /* player zapped */
      return(False);
    else if (!(fptr = FOPEN(file, "w"))) {
      mudlog("UAF: Cannot store %s", file);
      return(False);
    }

    for (pptr = p_rec ; pptr < p_rec + NUM_ENT ; pptr++) {
      if (pptr->type == INT && *(pptr->ival))
        fprintf(fptr, "%-11s%ld\n", pptr->token, *(pptr->ival));
      else if (pptr->type == CHAR && *(pptr->sval))
        fprintf(fptr, "%-11s%s\n", pptr->token, (char *) pptr->sval);
      else if (pptr->type == PTR && *(pptr->sval))
        fprintf(fptr, "%-11s%s\n", pptr->token, *(pptr->sval));
    }
    store_parts(fptr, d);

    for (i = 0 ; i < NUM_STORE_SLOTS ; i++)
      if (d->rplr.storage[i] != -1)
        fprintf(fptr, "Storage    %s\n", oname(d->rplr.storage[i]));
  }
  else {                                        /* load */
    memset(d, 0, sizeof(PERSONA));
    if (!(fptr = FOPEN(file, "r"))) {
      if (!access(file, F_OK))
        mudlog("UAF: Cannot load %s", file);
      return(False);
    }

    strcpy(d->ublock.pname, player);

    for (i = 0 ; i < NUM_STORE_SLOTS ; i++)
      d->rplr.storage[i] = -1;

    while (!feof(fptr)) {
      fgets(line, LLEN, fptr);

      if (strlen(line) < TOKEN_LEN + 1) {
        mudlog("UAF: Error in player record %s", player);
        continue;
      }
      line[strlen(line) - 1] = 0;
      
      token = line;
      value = line + TOKEN_LEN;

      if (!strncmp(token, "Bodyparts", 9))
        load_parts(value, d);

      else if (!strncmp(token, "Storage", 7)) {
        for (i = 0 ; i < NUM_STORE_SLOTS ; i++)    /* free storage slot */
          if (d->rplr.storage[i] == -1) {
            d->rplr.storage[i] = fobn(value);
            break;
          }
      }
      else {                                                     /* table */
        for (pptr = p_rec ; pptr < p_rec + NUM_ENT ; pptr++)
          if (!strncmp(pptr->token, token, strlen(pptr->token))) {
            if (pptr->type == INT)
              *(pptr->ival) = atol(value);
            else if (pptr->type == CHAR)
              strcpy((char *) pptr->sval, value);
            else if (pptr->type == PTR)
              *(pptr->sval) = COPY(value);
            break;
          }
        if (pptr == p_rec + NUM_ENT)
          mudlog("UAF: Unknown token in %s: %s", player, token);
      } 
    }
  }

  FCLOSE(fptr);
  return(True);
}

void pers2player (PERSONA * d, int plx) {
  int i;

  memcpy(&ublock[plx], &(d->ublock), sizeof(UBLOCK_REC));
  memcpy(&players[plx], &(d->player), sizeof(PLAYER_REC));

  if (plev(plx) < LVL_WIZARD)
    setpvis(plx, 0);

  pangry(plx) = -1; 

  for (i = 0 ; i < NUM_STORE_SLOTS ; i++) {
    rplrs[plx].storage[i] = -1;
    if (d->rplr.storage[i] != -1)
      clone_object(d->rplr.storage[i], -1, NULL, plx, CARRIED_BY);
  }

  reset_armor(False, plx);
  set_player_parts(plx);
  players[plx].resfd = -1;
  oldscore(plx) = pscore(plx);
  pfighting(plx) = -1;
  phelping(plx) = -1;
  is_conn(plx) = True;
}

void player2pers (PERSONA *d, time_t *last_on, int plx)
{
  if (plx < max_players) {
    memcpy(&(d->player), &players[plx], sizeof(PLAYER_REC));
    memcpy(&(d->rplr), &rplrs[plx], sizeof(RPLR_REC));
  }
  memcpy(&(d->ublock), &ublock[plx], sizeof(UBLOCK_REC));

  if (last_on != NULL) {
    d->player.last_on = *last_on;
    if (rplrs[plx].logged_on) {
      d->player.time_on += *last_on - rplrs[plx].logged_on;
      if (plev(plx) < LVL_WIZARD)
        d->player.mortal_time += *last_on - rplrs[plx].logged_on;
    }
  }
}

void get_gender (char *gen) {
  Boolean ok = False;
  Boolean female = False;
  PERSONA d;

  if (gen == NULL)
    replace_input_handler (get_gender);
  else if (*gen == 'M' || *gen == 'm')
    ok = True;
  else if (*gen == 'F' || *gen == 'f')
    ok = female = True;
  else
    bprintf ("M or F");

  if (ok) {
    if (OPERATOR (pname (mynum))) {
      setplev (mynum, LVL_CREATOR);
      sprintf (ptitle (mynum), "%%s the %s", player_level(mynum));
      setpstr (mynum, pmaxstrength (LVL_CREATOR));
      setpscore (mynum, levels[wlevel(LVL_CREATOR)]);
      update_wizlist (pname (mynum), wlevel(LVL_CREATOR));
    }
    else {
      setplev (mynum, 1);
      sprintf (ptitle (mynum), "%%s the %s", player_level(mynum));
      setpstr (mynum, 40);
    }
    setpwimpy (mynum, 25);
    mob_id (mynum) = id_counter++;
    setpdam (mynum, 8);

    if (female)
      ssetflg (mynum, SFL_FEMALE);
    set_xpflags (plev (mynum), &(pflags (mynum)), &(pmask (mynum)));
    setppager (mynum, 24);

    if (female)
      xsetbit (d.ublock.psflags.l, SFL_FEMALE);

    /* defaults */
    ssetflg(mynum, SFL_AUTOEXIT);
    ssetflg(mynum, SFL_HEARBACK);
    ssetflg(mynum, SFL_NEWSTYLE);
    psetflg(mynum, PFL_ABERCHAT);
    nsetflg(mynum, NFL_ENGLISH);
    set_player_parts(mynum);
    set_vital(mynum);
    reset_armor(False, mynum);

    player2pers (&d, &global_clock, mynum);
    d.player.first_on = players[mynum].first_on = global_clock;

    newuaf (&d);
    save_id_counter ();
    do_motd (NULL);
  } 
  else {
    bprintf ("\n");
    strcpy (cur_player->cprompt, "Sex (M/F) : ");
  }
}

void saveother (void)
{
  int p;
  static PERSONA d;

  if (EMPTY (item1))
    p = mynum;
  else {
    if ((p = pl1) == -1) {
      bprintf ("Cannot find player.\n");
      return;
    }
    if (plev (mynum) < LVL_WIZARD && p != mynum) {
      bprintf ("You cannot save another player!\n");
      return;
    }
  }

  if (aliased(p)) {
    bprintf ("Not while aliased.\n");
    return;
  }
  player2pers (&d, &global_clock, p);
  putuaf (&d);

  if (p != mynum)
    sendf (mynum, "&+M[%s Saved]\n", pname (p));
  else
    bprintf ("&+M[Player Saved]\n", pname (mynum));
}

void saveme (Boolean silent)
{
  static PERSONA d;

  if (aliased(real_mynum)) {
    bprintf ("Not while aliased.\n");
    return;
  }
  player2pers (&d, &global_clock, mynum);
  putuaf (&d);
  if (!silent) bprintf ("&+M[Player Saved]\n");
}

void saveallcom (void)
{
  static PERSONA d;
  int i;

  if (plev (mynum) < LVL_WIZARD) {
    erreval ();
    return;
  }
  for (i = 0; i < max_players; ++i) {
    if (is_in_game (i)) {
      if (aliased(i));
      else {
        player2pers (&d, &global_clock, i);
        putuaf (&d);
      }
    }
  }

  bprintf ("&+M[Saved All Players]\n");
  send_msg (DEST_ALL, MODE_QUIET, LVL_WIZARD, LVL_MAX, mynum, NOBODY,
              "&+B[&+CSaveall &*by &+W\001p%s\003&+B]\n", pname (mynum));
}

char *ipname (int plr)
{
  static char name[30];

  sprintf (name, "\001p%s\003", pname (plr));
  return name;
}

char *build_setin (int type, char *notused, char *s, char *n, char *d, char *v){
  char *p, *q, *r;
  char temp[SETIN_MAX];
  static char buff[SETIN_MAX + PNAME_LEN * 2];  /* allows for 2 victims */

  if(s == NULL) {
    switch(type) {
    default:
        mudlog("Unknown type passed to build_setin: %d!", type);
        return NULL;
    case SETIN_SETIN:
        strcpy(temp, DEFAULT_SETIN);
        break;
    case SETIN_SETOUT:
        strcpy(temp, DEFAULT_SETOUT);
        break;
    case SETIN_SETMIN:
        strcpy(temp, DEFAULT_SETMIN);
        break;
    case SETIN_SETMOUT:
        strcpy(temp, DEFAULT_SETMOUT);
        break;
    case SETIN_SETVIN:
        strcpy(temp, DEFAULT_SETVIN);
        break;
    case SETIN_SETVOUT:
        strcpy(temp, DEFAULT_SETVOUT);
        break;
    case SETIN_SETQIN:
        strcpy(temp, DEFAULT_SETQIN);
        break;
    case SETIN_SETQOUT:
        strcpy(temp, DEFAULT_SETQOUT);
        break;
    case SETIN_SETSIT:
        strcpy(temp, DEFAULT_SETSIT);
        break;
    case SETIN_SETSTAND:
        strcpy(temp, DEFAULT_SETSTAND);
        break;
    case SETIN_SETSUM:
        strcpy(temp, DEFAULT_SETSUM);
        break;
    case SETIN_SETSUMIN:
        strcpy(temp, DEFAULT_SETSUMIN);
        break;
    case SETIN_SETSUMOUT:
        strcpy(temp, DEFAULT_SETSUMOUT);
        break;
    }
    s = temp;
  }

  for (p = buff, q = s; *q;) {
    if (*q != '%')
      *p++ = *q++;
    else {
      switch (*++q) {
      case 'n':
        if (n)
          sprintf(p, "\001p%s\003", n);
          p += strlen(n) + 3;
        break;
      case 'v':
        if (v)
          sprintf(p, "\001p%s\003", v);
          p += strlen(v) + 3;
        break;
      case 'd':
        if (d)
          for (r = d; *r;)
            *p++ = *r++;
        break;
      case 'N':
        for (r = xname (n); *r != 0;)
          *p++ = *r++;
        break;
      case 'f':
        for (r = (psex (mynum) ? "her" : "his"); *r != 0;)
          *p++ = *r++;
        break;
      case 'F':
        for (r = (psex (mynum) ? "her" : "him"); *r != 0;)
          *p++ = *r++;
        break;
      case 0:
        --q;
        break;
      default:
        *p++ = *q;
      }
      ++q;
    }
  }
  if (p[-1] == '\n')
    --p;
  *p = 0;
  return buff;
}

Boolean getuafinfo (char *name) {
  PERSONA d;
  Boolean b;

  b = getuaf (name, &d);
  if (b) {
    pers2player (&d, mynum);
    setpname (mynum, d.ublock.pname);
  }
  return b;
}

int deluaf(char *name) {
  char *nptr, file[256];

  if (!valid_fname(name)) {
    bprintf("Player name contains illegal characters.\n");
    return(1);
  }

  for (nptr = name; *nptr; nptr++)
    if (isalpha(*nptr))
      *nptr = tolower(*nptr);

  *name = toupper(*name);
  sprintf(file, "%s/%c/%s", TEXT_PFILES_BASE, *name, name);

  if (unlink(file) == -1)
    return(1);
  return(0);
}