pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/****************************************************************************
 ** Eradicated Worlds to Eradicated Worlds 2, user database conversion 
 ** utility.
 ** Author: Marty
 **************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <gdbm.h>

/**************************************************************************
 ** Global types definitions.
 **************************************************************************/
typedef struct dlongint {
  long b3; long b2; long b1;
} DoubleLongInt;

typedef struct longint {
  long h; long l;
} LongInt;
 
/****************************************************************************
 ** Data required for old database
 ****************************************************************************/ 
typedef DoubleLongInt  OLD_PFLAGS;
typedef long int OLD_SFLAGS;
typedef LongInt  OLD_MFLAGS;
typedef long int OLD_QFLAGS;

#define OLD_TITLE_LEN   55               /* Max. length of a players title */
#define OLD_PROMPT_LEN  20               /* Max. length of the prompt */
#define OLD_PNAME_LEN   12               /* Max. length of a player-name */
#define OLD_PASSWD_LEN  16               /* Max chars of passwd + 1 */
#define OLD_MAX_EMAIL_LEN    128		/* max chars in email address */

typedef struct _OLD_PERSONA {
    char	p_name[OLD_PNAME_LEN+1];
    char        p_title[OLD_TITLE_LEN+1];
    char	p_email[OLD_MAX_EMAIL_LEN+1];
    char        p_passwd[OLD_PASSWD_LEN];
    long int    p_home;
    int		p_score;
    int		p_strength;
    int         p_damage;
    int         p_armor;
    OLD_SFLAGS	p_sflags;
    OLD_PFLAGS	p_pflags;
    OLD_PFLAGS	p_mask;
    OLD_QFLAGS  p_quests;
    int		p_vlevel;
    int		p_level;
    time_t      p_last_on;
    int         p_wimpy;
    long int    p_id;
} OLD_PERSONA;

/******************************************************************************
 ** Data for new database 
 ******************************************************************************/
typedef DoubleLongInt  	NEW_PFLAGS;
typedef DoubleLongInt  	NEW_SFLAGS;
typedef LongInt		NEW_QFLAGS;

#define NEW_TITLE_LEN   	55               /* Max. length of a players title */
#define NEW_PROMPT_LEN  	80               /* Max. length of the prompt */
#define NEW_PNAME_LEN   	12               /* Max. length of a player-name */
#define NEW_PASSWD_LEN  	16               /* Max chars of passwd + 1 */
#define NEW_MAX_EMAIL_LEN   128		 /* max chars in email address */

typedef struct _NEW_PERSONA {
    char 	p_idname[NEW_PNAME_LEN+1];
    char	p_name[NEW_PNAME_LEN+1];
    char        p_title[NEW_TITLE_LEN+1];
    char	p_email[NEW_MAX_EMAIL_LEN+1];
    char        p_passwd[NEW_PASSWD_LEN];
    char 	p_prompt[NEW_PROMPT_LEN+1];
    long int    p_home;
    int		p_score;
    int		p_strength;
    int         p_damage;
    int         p_armor;
    NEW_SFLAGS	p_sflags;
    NEW_PFLAGS	p_pflags;
    NEW_PFLAGS	p_mask;
    NEW_QFLAGS  p_quests;
    int		p_vlevel;
    int		p_level;
    time_t      p_last_on;
    int         p_wimpy;
    long int    p_id;
    int         p_pager;
    /* Unused now, for future expantions */
    NEW_SFLAGS      spareset1;
    NEW_SFLAGS      spareset2;
    int         p_killed;
    int         p_died;
    int         p_questpoints;          /* Spell points */
    int         p_losses;
    int         spareint5;
} NEW_PERSONA;

/****************************************************************************
 ** Data required for flags, since not all flags are on the same place.
 ****************************************************************************/
static int questtable[] = {
0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 
10, 11, 12, 13, 14, 15, 16, 17, 19, 23, 
25, 18, 22, 26, 24, -1, -1, -1, -1, -1,
-1, -1 
};

static int pflagtable[] = {
0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
10, -1, -1, -1, -1, -1, 34, 24, 22, 23, 	/* 19 */
25, 38, 65, 48, 40, 53, 43, 45, 66, 68, 
33, 51, 55, 57, 36, 16, 17, 49, 32, 30, 	/* 39 */
26, 72, 52, 54, 60, 35, 46, 61, 70, 39, 
28, 71, 47, 63, 59, 67, 37, 31, 44, 41,		/* 59 */
29, 42, 58, 27, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,		/* 79 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,		/* 89 */
-1, -1, -1, -1, -1, -1				/* 95 */
};

static int sflagtable[] = {
0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, -1, 29,
34, 33, -1, -1, -1, -1, -1, -1, -1, -1
};

static int QuestPoints[] = {
	3,	2,	2,	2,	3,	2,	2,	1,
	2,	1,	2,	3,	2,	3,	1,	2,
	3,	3,	4,	2,	1,	3,	2,	2,
	5,	2,	3,	4,	3,	4,
};

#define xtstbit(W,V)	((W) & (1<<(V)))

/* Standard DoubleLongInt stuff */
void setdbit(NEW_PFLAGS *f, int bit)
{  if (bit >= 64)
     f->b3 |= (1 << (bit-64));
   else if (bit >= 32)
     f->b2 |= (1 << (bit-32));
   else
     f->b1 |= (1 << bit);
}

int tstdbit(DoubleLongInt *f, int b)
{  if (b >= 64)
     return xtstbit(f->b3,b);
   else if (b >= 32)
     return xtstbit(f->b2,b);
   else
     return xtstbit(f->b1,b);
}

void convert_quests(NEW_QFLAGS *n, OLD_QFLAGS *o,int *qp)
{ int i;

  n->h = n->l = 0;
  for (i = 0; i < 32; i++)
  {   if (questtable[i] != -1 && xtstbit(*o,i)) 
      {   n->l |= (1 << questtable[i]);
          (*qp) += QuestPoints[(questtable[i])];
      }
  }
}

void convert_pflags(NEW_PFLAGS *n, OLD_PFLAGS *o)
{  int i;

   n->b1 = n->b2 = n->b3 = 0;

   for (i = 0; i < 96; i++)
   {  if (pflagtable[i] != -1 && tstdbit(o,i))
        setdbit(n,pflagtable[i]);
   }
}

void convert_sflags(NEW_SFLAGS *n, OLD_SFLAGS *o)
{  int i;
  
   n->b3 = n->b2, n->b1 = 0;
 
   for (i=0; i < 32; i++)
   {  if (sflagtable[i] != -1 && xtstbit(*o,i))
         setdbit(n,i);
   }
}

void old_to_new(OLD_PERSONA *o, NEW_PERSONA *n)
{  /* Take old fields over */
   strncpy(n->p_name,o->p_name,NEW_PNAME_LEN+1);
   strcpy(n->p_idname,n->p_name);
   strncpy(n->p_title,o->p_title,NEW_TITLE_LEN+1);
   strncpy(n->p_email,o->p_email,NEW_MAX_EMAIL_LEN+1);
   strncpy(n->p_passwd,o->p_passwd,NEW_PASSWD_LEN+1);
   n->p_id = o->p_id;
   n->p_wimpy = o->p_wimpy;
   n->p_last_on = o->p_last_on;
   n->p_level = o->p_level;
   n->p_vlevel = o->p_vlevel;
   n->p_score = o->p_score;
   n->p_strength = o->p_strength;
   n->p_damage = o->p_damage;
   n->p_armor = o->p_armor;
   n->p_home = 0;	/* Can't take over the old home loc */
   n->p_sflags.b1 = n->p_sflags.b2 = n->p_sflags.b3 = 0;
   n->p_questpoints = 0;
   convert_quests(&n->p_quests,&o->p_quests,&n->p_questpoints);
   convert_pflags(&n->p_pflags,&o->p_pflags);
   convert_pflags(&n->p_mask,&o->p_mask);
   convert_sflags(&n->p_sflags, &o->p_sflags);

   /* FIll in new fields */
   strcpy(n->p_prompt,"&+BEW&+W>&* ");
   n->p_killed = 0;
   n->p_died = 0;
   n->p_losses = 0;
   n->spareint5 = 0;
   n->p_pager = 24;
   n->spareset1.b1 = n->spareset1.b2 = n->spareset1.b3 = 0;
   n->spareset2.b1 = n->spareset2.b2 = n->spareset2.b3 = 0;
}

int main(void)
{  GDBM_FILE oldf;
   GDBM_FILE newf;
   OLD_PERSONA o;
   NEW_PERSONA n;

   datum old_key;
   datum old_next;
   datum old_data;
   datum new_key;
   datum new_data;

   int i=0;

   oldf = gdbm_open("uaf_rand",sizeof(OLD_PERSONA),GDBM_READER,S_IRUSR|S_IWUSR,NULL);
   if (oldf == NULL)
   {  printf("Error opening old database file (not in this directory?)\n");
      exit(1);
   }

   newf = gdbm_open("users_data",sizeof(NEW_PERSONA),GDBM_WRCREAT,S_IRUSR|S_IWUSR,NULL);
   if (newf == NULL)
   {  printf("Error opening new database (FS full?)\n");
      exit(2);
   }

   old_key = gdbm_firstkey(oldf);

   while (old_key.dptr != NULL)
   {   old_data = gdbm_fetch(oldf,old_key);
       bcopy(old_data.dptr,&o,sizeof(OLD_PERSONA));
       
       if (o.p_name != '\0')
       {  old_to_new(&o,&n);
          new_key.dptr = n.p_idname;
          new_key.dsize = strlen(n.p_idname) + 1;
          new_data.dptr = (char *)&n;
          new_data.dsize = sizeof(NEW_PERSONA) + 1;
          gdbm_store(newf,new_key, new_data, GDBM_REPLACE);
          printf("Player %s converted.\n",n.p_idname);
          i++;
       }

       old_next = gdbm_nextkey(oldf,old_key);
       if (old_key.dptr != NULL)
          free(old_key.dptr);
       if (old_data.dptr != NULL)
          free(old_data.dptr);

       old_key = old_next;
   }
   gdbm_reorganize(newf);
   gdbm_close(oldf);
   gdbm_close(newf);
   printf("Converted %d users\n",i);
   printf("Wizards may need a pflagreset, since there are new flags that weren't in\n"
          "the old one.\n");
   return 0;
}