/* textin.c */
#include "config.h"
/*
* This file is part of TeenyMUD II.
* Copyright(C) 1993, 1994, 1995 by Jason Downs.
* All rights reserved.
*
* TeenyMUD II 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.
*
* TeenyMUD II 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 (see the file 'COPYING'); if not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*
*/
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#else /* not HAVE_ALLOCA_H */
#ifdef _AIX
#pragma alloca
#endif /* not _AIX */
#endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#include <ctype.h>
#include "conf.h"
#include "teeny.h"
#include "teenydb.h"
#include "textdb.h"
#include "sha/sha_wrap.h"
#include "externs.h"
static char gender[16];
/*
* We have to read TinyMUD objects all in one gulp, since their
* field order is so incompatible.
*/
static struct {
char name[512];
char description[512];
char fail[512];
char succ[512];
char ofail[512];
char osucc[512];
char password[512];
struct boolexp *lock;
int location;
int contents;
int exits;
int next;
int owner;
int pennies;
int flags;
} tinyobj;
static int getnumber _ANSI_ARGS_((FILE *, int, int, int, int));
static struct boolexp *unparse_oldlock _ANSI_ARGS_((int *));
static int getarray _ANSI_ARGS_((FILE *, int, int, int, int));
static struct boolexp *negate_bool _ANSI_ARGS_((struct boolexp *));
static struct boolexp *getbool_sub _ANSI_ARGS_((int, int, int));
static int getbool _ANSI_ARGS_((FILE *, int, char *, int, int));
static int getstring _ANSI_ARGS_((FILE *, int, int, int, int));
static int getstrings _ANSI_ARGS_((FILE *, int, int, int));
static int getattr _ANSI_ARGS_((FILE *, int, char *, int, int));
static int convert_aflags _ANSI_ARGS_((char *, int, int, int));
static int getattributes _ANSI_ARGS_((FILE *, int, int, int));
static int *convert_flags _ANSI_ARGS_((int, int, int));
/* ARGSUSED */
static int getnumber(in, obj, code, read_version, read_flags)
FILE *in;
int obj, code;
int read_version, read_flags;
{
int num;
char *ptr;
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
num = (int)strtol(txt_buffer, &ptr, 10);
if(ptr == txt_buffer) {
fprintf(stderr, txt_numerr, obj);
return(-1);
}
if((read_version < 100) && (code == TIMESTAMP))
num *= 60;
if(set_int_elt(obj, code, num) == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
return(0);
}
/* old RPN lock emulation code */
struct tree {
int dat;
short left, right;
};
static struct boolexp *to_bool _ANSI_ARGS_((struct tree *, int));
static struct boolexp *unparse_oldlock(lock)
int *lock;
{
int stack[64];
struct tree trees[64];
int tp;
int sp;
int count;
tp = sp = 0;
count = *lock++;
while ((*lock != -1) && count) {
switch (*lock) {
case -2:
case -3:
if (sp < 2 || tp > 63)
return ((struct boolexp *)NULL);
trees[tp].dat = *lock;
trees[tp].left = (short) (stack[--sp]);
trees[tp].right = (short) (stack[--sp]);
stack[sp++] = tp++;
break;
case -4:
if (sp < 1 || tp > 63)
return ((struct boolexp *)NULL);
trees[tp].dat = -4;
trees[tp].right = (short) (stack[--sp]);
stack[sp++] = tp++;
break;
default:
if (sp > 255 || tp > 63)
return ((struct boolexp *)NULL);
trees[tp].dat = *lock;
if (sp < 63)
stack[sp++] = tp++;
else
return ((struct boolexp *)NULL);
break;
}
lock++;
count--;
}
if (sp != 1)
return ((struct boolexp *)NULL);
return(to_bool(trees, tp -1));
}
static struct boolexp *to_bool(trees, t)
struct tree *trees;
register int t;
{
struct boolexp *ret = boolexp_alloc();
switch (trees[t].dat) {
case -2:
ret->type = BOOLEXP_AND;
ret->sub1 = to_bool(trees, trees[t].left);
ret->sub2 = to_bool(trees, trees[t].right);
if((ret->sub1 == (struct boolexp *)NULL)
|| (ret->sub2 == (struct boolexp *)NULL)) {
boolexp_free(ret);
return((struct boolexp *)NULL);
}
break;
case -3:
ret->type = BOOLEXP_OR;
ret->sub1 = to_bool(trees, trees[t].left);
ret->sub2 = to_bool(trees, trees[t].right);
if((ret->sub1 == (struct boolexp *)NULL)
|| (ret->sub2 == (struct boolexp *)NULL)) {
boolexp_free(ret);
return((struct boolexp *)NULL);
}
break;
case -4:
ret->type = BOOLEXP_NOT;
ret->sub1 = to_bool(trees, trees[t].right);
if(ret->sub1 == (struct boolexp *)NULL) {
boolexp_free(ret);
return((struct boolexp *)NULL);
}
break;
case -100:
ret->type = BOOLEXP_ATTR;
((ret->dat).atr)[0] = ty_strdup("sex", "to_bool");
((ret->dat).atr)[1] = ty_strdup("male", "to_bool");
break;
case -101:
ret->type = BOOLEXP_ATTR;
((ret->dat).atr)[0] = ty_strdup("sex", "to_bool");
((ret->dat).atr)[1] = ty_strdup("female", "to_bool");
break;
case -102:
ret->type = BOOLEXP_ATTR;
((ret->dat).atr)[0] = ty_strdup("sex", "to_bool");
((ret->dat).atr)[1] = ty_strdup("it", "to_bool");
break;
default:
if(trees[t].dat > -1) {
ret->type = BOOLEXP_CONST;
(ret->dat).thing = trees[t].dat;
} else {
boolexp_free(ret);
return((struct boolexp *)NULL);
}
break;
}
return (ret);
}
/* ARGSUSED */
static int getarray(in, obj, code, read_version, read_flags)
FILE *in;
int obj, code;
int read_version, read_flags;
{
int *array, count;
register int i;
char *ptr, *ptr2;
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
/* regardless of the database type, if it's -1, we go NULL. */
count = (int)strtol(txt_buffer, &ptr, 10);
if(ptr == txt_buffer) {
fprintf(stderr, txt_numerr, obj);
return(-1);
}
if(count == -1) {
array = (int *)NULL;
} else {
if(read_flags & DB_DESTARRAY) { /* new style */
array = (int *)alloca((count + 1) * sizeof(int));
if(array == (int *)NULL)
panic("getarray(): stack allocation failed\n");
array[0] = count;
for(i = 1; i <= count; i++) {
array[i] = (int)strtol(ptr, &ptr2, 10);
if(ptr2 == ptr) {
fprintf(stderr, txt_numerr, obj);
return(-1);
}
ptr = ptr2;
}
} else { /* count is really a single dest */
array = (int *)alloca(sizeof(int) * 2);
if(array == (int *)NULL)
panic("getarray(): stack allocation failed\n");
array[0] = 1;
array[1] = count;
}
}
if(set_array_elt(obj, code, array) == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
return(0);
}
static struct boolexp *negate_bool(curr)
struct boolexp *curr;
{
struct boolexp *new;
if(curr == (struct boolexp *)NULL)
return((struct boolexp *)NULL);
new = boolexp_alloc();
new->type = BOOLEXP_NOT;
new->sub1 = curr;
return(new);
}
static char *getbool_ptr = (char *)NULL;
/* ARGSUSED */
static struct boolexp *getbool_sub(obj, read_version, read_flags)
int obj, read_version, read_flags;
{
register struct boolexp *ret = (struct boolexp *)NULL;
char *ptr, *nptr;
if(getbool_ptr == (char *)NULL)
return((struct boolexp *)NULL);
switch(*getbool_ptr) {
case '\0':
case '\n':
return((struct boolexp *)NULL);
case '(':
ret = boolexp_alloc();
switch(*++getbool_ptr) {
case '!':
ret->type = BOOLEXP_NOT;
getbool_ptr++;
ret->sub1 = getbool_sub(obj, read_version, read_flags);
if((ret->sub1 == (struct boolexp *)NULL) || (*getbool_ptr != ')')) {
fprintf(stderr, txt_boolerr, obj);
boolexp_free(ret);
return((struct boolexp *)NULL);
}
getbool_ptr++;
return(ret);
default:
ret->sub1 = getbool_sub(obj, read_version, read_flags);
switch(*getbool_ptr) {
case '&':
ret->type = BOOLEXP_AND;
break;
case '|':
ret->type = BOOLEXP_OR;
break;
default:
ret->type = BOOLEXP_NOT;
fprintf(stderr, txt_boolerr, obj);
boolexp_free(ret);
return((struct boolexp *)NULL);
}
getbool_ptr++;
ret->sub2 = getbool_sub(obj, read_version, read_flags);
if((ret->sub1 == (struct boolexp *)NULL)
|| (ret->sub2 == (struct boolexp *)NULL) || (*getbool_ptr != ')')) {
fprintf(stderr, txt_boolerr, obj);
boolexp_free(ret);
return((struct boolexp *)NULL);
}
getbool_ptr++;
return(ret);
}
break;
case '#': /* TeenyMUD const token */
case '0': /* TinyMUD const numbers */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ret = boolexp_alloc();
ret->type = BOOLEXP_CONST;
if(*getbool_ptr == '#')
getbool_ptr++;
(ret->dat).thing = (int)strtol(getbool_ptr, &ptr, 10);
if(ptr == getbool_ptr) {
fprintf(stderr, txt_boolerr, obj);
boolexp_free(ret);
return((struct boolexp *)NULL);
}
getbool_ptr = ptr;
break;
case '~':
ret = boolexp_alloc();
ret->type = BOOLEXP_FLAG;
getbool_ptr++;
((ret->dat).flags)[0] = (int)strtol(getbool_ptr, &ptr, 10);
if((ptr == getbool_ptr) || (*ptr != '/')) {
fprintf(stderr, txt_boolerr, obj);
boolexp_free(ret);
return((struct boolexp *)NULL);
}
ptr++;
((ret->dat).flags)[1] = (int)strtol(ptr, &nptr, 10);
if(nptr == ptr) {
fprintf(stderr, txt_boolerr, obj);
boolexp_free(ret);
return((struct boolexp *)NULL);
}
getbool_ptr = nptr;
break;
case '{':
ret = boolexp_alloc();
ret->type = BOOLEXP_ATTR;
ptr = ++getbool_ptr;
for(nptr = getbool_ptr; *nptr && (*nptr != ':'); nptr++);
if(*nptr == ':')
*nptr++ = '\0';
for(getbool_ptr = nptr; *getbool_ptr && (*getbool_ptr != '}');
getbool_ptr++);
if(*getbool_ptr == '}')
*getbool_ptr++ = '\0';
((ret->dat).atr)[0] = ty_strdup(ptr, "getbool_sub");
((ret->dat).atr)[1] = ty_strdup(nptr, "getbool_sub");
break;
}
return(ret);
}
/* ARGSUSED */
static int getbool(in, obj, name, read_version, read_flags)
FILE *in;
int obj;
char *name;
int read_version, read_flags;
{
struct boolexp *ret = (struct boolexp *)NULL;
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
if(read_version > 299) {
getbool_ptr = txt_buffer;
ret = getbool_sub(obj, read_version, read_flags);
} else {
if(txt_buffer[0] != '\n') {
int work[64], size = 64;
register int i;
char *ptr, *optr;
remove_newline(txt_buffer);
for(i = 0, optr = txt_buffer; i <= size; i++) {
work[i] = (int)strtol(optr, &ptr, 10);
if(ptr == optr) {
fprintf(stderr, txt_numerr, obj);
return(-1);
}
if(i == 0)
size = work[i];
optr = ptr;
}
ret = unparse_oldlock(work);
}
}
if(ret != (struct boolexp *)NULL) {
if(attr_addlock(obj, name, ret, DEFLOCK_FLGS) == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
}
return(0);
}
/* ARGSUSED */
static int getstring(in, obj, code, read_version, read_flags)
FILE *in;
int obj, code;
int read_version, read_flags;
{
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
remove_newline(txt_buffer);
if(set_str_elt(obj, code, txt_buffer[0] ? txt_buffer : (char *)NULL) == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
return(0);
}
static char *convert_attr(obj, code, aflags)
int obj, code;
int *aflags;
{
static char tmp[27];
*aflags = DEFATTR_FLGS;
switch (code) {
case 14:
return (SUC);
case 15:
return (OSUC);
case 16:
return (FAIL);
case 17:
return (OFAIL);
case 18:
return (DESC);
case 19:
return (SEX);
case 20:
return (DROP);
case 21:
return (ODROP);
case 22:
return (ENTER);
case 23:
return (OENTER);
case 24:
return (LEAVE);
case 25:
return (OLEAVE);
case 26:
return (IDESC);
case 27:
return (ODESC);
case 28:
*aflags = SITE_FLGS;
return (SITE);
case 29:
return (KILL);
case 30:
return (OKILL);
case 31:
*aflags = PASSWORD_FLGS;
return (PASSWORD);
case 32:
return (OTELEPORT);
case 33:
return (OXTELEPORT);
case 34:
return (OXENTER);
case 35:
return (OXLEAVE);
case 36:
return (ENFAIL);
case 37:
return (OENFAIL);
default:
(void) snprintf(tmp, sizeof(tmp), "Unknown%d", code);
return (tmp);
}
}
/* ARGSUSED */
static int getstrings(in, obj, read_version, read_flags)
FILE *in;
int obj, read_version, read_flags;
{
int ret, aflags, code = 0;
char *p, *attr;
do {
if (fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
(void) fprintf(stderr, txt_eoferr, obj);
return(-1);
}
remove_newline(txt_buffer);
if (txt_buffer[0] && txt_buffer[0] != '<') {
code = (int)strtol(txt_buffer, &p, 10);
if((p == txt_buffer) || (*p != ':')) {
fprintf(stderr, txt_numerr, obj);
return(-1);
}
p++;
if (code == 1) { /* name */
ret = set_str_elt(obj, NAME, p);
} else {
attr = convert_attr(obj, code, &aflags);
ret = attr_add(obj, attr, p, aflags);
}
if (ret == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
}
} while (txt_buffer[0] != '<');
return(0);
}
/* ARGSUSED */
static int getattr(in, obj, attr, read_version, read_flags)
FILE *in;
int obj;
char *attr;
int read_version, read_flags;
{
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
remove_newline(txt_buffer);
if(txt_buffer[0]) {
if(attr_add(obj, attr, txt_buffer, DEFATTR_FLGS) == -1){
fprintf(stderr, txt_dberr, obj);
return(-1);
}
}
return(0);
}
/* ARGSUSED */
static int convert_aflags(str, flags, read_version, read_flags)
char *str;
int flags, read_version, read_flags;
{
int nflags = flags;
if (read_version < 300) {
if(strcmp(str, SITE) == 0) {
nflags = SITE_FLGS;
} else if(strcmp(str, PASSWORD) == 0) {
nflags = PASSWORD_FLGS;
} else
nflags = 0;
#if 0
/* This seems to be bogus... */
if(flags & 0x00000100)
nflags |= A_PRIVATE;
#endif
} else if (!(read_flags & DB_IMMUTATTRS)) {
/* SITE_FLAGS changed. */
if(strcmp(str, SITE) == 0)
nflags = SITE_FLGS;
}
return(nflags);
}
/* ARGSUSED */
static int getattributes(in, obj, read_version, read_flags)
FILE *in;
int obj;
int read_version, read_flags;
{
char *ptr, *nptr, *data;
char name[MAXATTRNAME+1];
int aflags, done = 0;
short atype;
while (!done) {
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
remove_newline(txt_buffer);
if(txt_buffer[0] && (txt_buffer[0] != '>')) {
if(read_version < 300) { /* pathetic format */
for(ptr = txt_buffer; *ptr && (*ptr != ':'); ptr++);
*ptr++ = '\0';
for(data = ptr; *data && (*data != ':'); data++);
*data++ = '\0';
aflags = (int)strtol(data, &nptr, 10);
if((nptr == data) || (*nptr != ':')){
fprintf(stderr, txt_numerr, obj);
return(-1);
}
aflags = convert_aflags(txt_buffer, aflags, read_version, read_flags);
nptr++;
if(attr_add(obj, txt_buffer, nptr, aflags) == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
} else { /* studly format */
ty_strncpy(name, txt_buffer, MAXATTRNAME);
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
aflags = (int)strtol(txt_buffer, &ptr, 10);
if(ptr == txt_buffer){
fprintf(stderr, txt_numerr, obj);
return(-1);
}
aflags = convert_aflags(name, aflags, read_version, read_flags);
if(read_version > 300) { /* attr type */
char *mptr;
ptr++; /* skip space */
atype = (short)strtol(ptr, &mptr, 10);
if(mptr == ptr) {
fprintf(stderr, txt_numerr, obj);
return(-1);
}
} else
atype = ATTR_STRING;
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, obj);
return(-1);
}
remove_newline(txt_buffer);
switch(atype) {
case ATTR_STRING:
if(attr_add(obj, name, txt_buffer, aflags) == -1){
fprintf(stderr, txt_dberr, obj);
return(-1);
}
break;
case ATTR_LOCK:
getbool_ptr = txt_buffer;
if(attr_addlock(obj, name,
getbool_sub(obj, read_version, read_flags),
aflags) == -1) {
fprintf(stderr, txt_dberr, obj);
return(-1);
}
break;
}
}
} else
done++;
}
return(0);
}
/* ARGSUSED */
static int *convert_flags(oflags, read_version, read_flags)
int oflags, read_version, read_flags;
{
static int nflags[FLAGS_LEN];
bzero((VOID *)nflags, sizeof(nflags));
/* convert first generation flags to 64bits */
if (read_version < 0) { /* TinyMUD */
switch(oflags & 0x7) {
case 0:
nflags[0] = TYP_ROOM;
break;
case 1:
nflags[0] = TYP_THING;
break;
case 2:
nflags[0] = TYP_EXIT;
break;
case 3:
nflags[0] = TYP_PLAYER;
break;
case 6:
nflags[0] = TYP_BAD;
break;
}
if(oflags & 0x10)
nflags[1] |= WIZARD;
if(oflags & 0x20)
nflags[1] |= LINK_OK;
if(oflags & 0x40)
nflags[1] |= DARK;
if(oflags & 0x100)
nflags[1] |= STICKY;
if(oflags & 0x200)
nflags[0] |= BUILDER;
if(oflags & 0x400)
nflags[1] |= HAVEN;
if(oflags & 0x800)
nflags[1] |= ABODE;
if(oflags & 0x4000)
nflags[0] |= ROBOT;
if(oflags & 0x8000)
nflags[0] |= CHOWN_OK;
if(oflags & 0x20000)
nflags[0] |= REVERSED_WHO;
if(oflags & 0x40000)
nflags[1] |= GOD;
switch((oflags & 0x3000) >> 12) {
case 0:
gender[0] = '\0';
break;
case 1:
strcpy(gender, "NEUTER");
break;
case 2:
strcpy(gender, "FEMALE");
break;
case 3:
strcpy(gender, "MALE");
break;
}
return(nflags);
}
if (read_version < 100) { /* 1.0 - 1.3 */
switch (oflags & 0x0003) {
case 0:
nflags[0] = TYP_PLAYER;
break;
case 1:
nflags[0] = TYP_THING;
break;
case 2:
nflags[0] = TYP_ROOM;
break;
case 3:
nflags[0] = TYP_EXIT;
break;
}
if (oflags & 0x0004)
nflags[1] |= STICKY;
if (oflags & 0x0008)
nflags[1] |= WIZARD;
if (oflags & 0x0010)
nflags[0] |= ROBOT;
if (oflags & 0x0020)
nflags[1] |= LINK_OK;
if (read_version == 5) { /* a -C database?? */
if ((oflags & 0x0040) && ((oflags & 0x003) != 3)) /* !exit */
nflags[1] |= DARK;
else if (!(oflags & 0x0040)) /* exit */
nflags[0] |= OBVIOUS;
if (oflags & 0x0080)
nflags[1] |= GOD;
if (oflags & 0x0100)
nflags[1] |= HAVEN;
if (oflags & 0x0200)
nflags[1] |= JUMP_OK;
if (oflags & 0x0400)
nflags[1] |= ABODE;
} else {
if (oflags & 0x0040)
nflags[1] |= DARK;
if (oflags & 0x0080)
nflags[1] |= HAVEN;
if (oflags & 0x0100)
nflags[1] |= JUMP_OK;
if (oflags & 0x0200)
nflags[1] |= ABODE;
if (oflags & 0x0400)
nflags[0] |= BUILDER;
}
}
/* convert second generation flags to 64bits */
/* i no longer have flag maps for anything before version 300, so */
/* there may be a few problems. */
if ((read_version >= 100) && (read_version < 301)) {
/* do types and type specific flags */
switch(oflags & 0x00000007) {
case 0: /* player */
nflags[0] = TYP_PLAYER;
if(oflags & 0x00000200)
nflags[0] |= ABODE;
if(oflags & 0x00000400)
nflags[0] |= BUILDER;
if(oflags & 0x00000800)
nflags[0] |= ENTER_OK;
if(oflags & 0x00002000)
nflags[0] |= ROBOT;
if(oflags & 0x00004000)
nflags[0] |= GUEST;
if(oflags & 0x00008000)
nflags[0] |= RETENTIVE;
if(oflags & 0x00010000)
nflags[0] |= REVERSED_WHO;
break;
case 1: /* thing */
nflags[0] = TYP_THING;
if(oflags & 0x00000200)
nflags[0] |= ABODE;
if(oflags & 0x00000400)
nflags[0] |= BUILDING_OK;
if(oflags & 0x00000800)
nflags[0] |= ENTER_OK;
if(oflags & 0x00004000)
nflags[0] |= CHOWN_OK;
if(oflags & 0x00008000)
nflags[0] |= DESTROY_OK;
if(oflags & 0x00010000)
nflags[0] |= PUPPET;
break;
case 2: /* room */
nflags[0] = TYP_ROOM;
if(oflags & 0x00000200)
nflags[0] |= ABODE;
if(oflags & 0x00000400)
nflags[0] |= BUILDING_OK;
if(oflags & 0x00000800)
nflags[0] |= ENTER_OK;
if(oflags & 0x00004000)
nflags[0] |= CHOWN_OK;
if(oflags & 0x00008000)
nflags[0] |= DESTROY_OK;
break;
case 3: /* exit */
nflags[0] = TYP_EXIT;
if(oflags & 0x00000200)
nflags[0] |= OBVIOUS;
if(oflags & 0x00000800)
nflags[0] |= EXTERNAL;
if(oflags & 0x00002000)
nflags[0] |= ACTION;
if(oflags & 0x00004000)
nflags[0] |= CHOWN_OK;
if(oflags & 0x00008000)
nflags[0] |= DESTROY_OK;
break;
default: /* program, or something */
nflags[0] = TYP_BAD;
break;
}
if(oflags & 0x00000008)
nflags[1] |= WIZARD;
if(oflags & 0x00000010)
nflags[1] |= GOD;
if(oflags & 0x00000020)
nflags[1] |= LINK_OK;
if(oflags & 0x00000080)
nflags[1] |= HAVEN;
if(oflags & 0x00000100)
nflags[1] |= JUMP_OK;
if(oflags & 0x00001000)
nflags[1] |= STICKY;
if(oflags & 0x00020000)
nflags[1] |= PARENT_OK;
if(oflags & 0x00040000)
nflags[1] |= VISUAL;
if(oflags & 0x00080000)
nflags[1] |= AUDIBLE;
if(oflags & 0x00100000)
nflags[1] |= NOSPOOF;
if(oflags & 0x00200000)
nflags[1] |= HIDDEN;
if(oflags & 0x00400000)
nflags[1] |= HALT;
if(oflags & 0x00800000)
nflags[1] |= HAS_STARTUP;
if(oflags & 0x01000000)
nflags[1] |= LISTENER;
}
if (read_version == 105) { /* gender */
if (oflags & 0x01000000) { /* male */
(void) strcpy(gender, "MALE");
}
if (oflags & 0x02000000) { /* female */
(void) strcpy(gender, "FEMALE");
}
if (oflags & 0x04000000) { /* it */
(void) strcpy(gender, "NEUTER");
}
}
return (nflags);
}
int text_load(in, read_version, read_flags, read_total)
FILE *in;
int read_version, read_flags, read_total;
{
register int i, num, type, e;
int *flags, rflags[FLAGS_LEN], ret, done = 0, garbage = 0;
char *ptr;
initialize_db(read_total + mudconf.slack);
mudstat.slack = read_total + mudconf.slack;
gender[0] = '\0';
for(i = 0, num = 0; ((read_total < 0) || (i < read_total)) && !done; i++){
if((i >= 1000) && ((i % 1000) == 0)) {
fputc('o', stderr);
fflush(stderr);
} else if((i % 100) == 0) {
fputc('.', stderr);
fflush(stderr);
}
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
switch(txt_buffer[0]){
case '#':
num = (int)strtol(txt_buffer+1, &ptr, 10);
if(ptr == (txt_buffer+1)){
fprintf(stderr, txt_numerr, i);
return(-1);
}
if(num != i) {
fprintf(stderr, "Database out of sync at object #%d.\n", num);
return(-1);
}
if(read_version >= 0) { /* TeenyMUD */
/* flags */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
rflags[0] = (int)strtol(txt_buffer, &ptr, 10);
if(ptr == txt_buffer){
fprintf(stderr, txt_numerr, i);
return(-1);
}
if(read_version > 300) {
char *nptr;
ptr++;
rflags[1] = (int)strtol(ptr, &nptr, 10);
if(nptr == ptr) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
flags = rflags;
} else
flags = convert_flags(rflags[0], read_version, read_flags);
type = (flags[0] & TYPE_MASK);
ret = create_obj(type);
if(ret != num){
fprintf(stderr, "Internal and input databases out of sync at #%d.\n",
num);
return(-1);
}
flags[1] = ((flags[1] & ~INTERNAL_FLAGS) |
(DSC_FLAG2(main_index[num]) & INTERNAL_FLAGS));
for(e = 0; e < FLAGS_LEN; e++)
(DSC_FLAGS(main_index[num]))[e] = flags[e];
if(read_version > 299) { /* sane database */
/* quota */
if(getnumber(in, num, QUOTA, read_version, read_flags) == -1)
return(-1);
/* location */
if(getnumber(in, num, LOC, read_version, read_flags) == -1)
return(-1);
/* home/dropto/destinations */
if(type != TYP_EXIT) {
if(getnumber(in, num, HOME, read_version, read_flags) == -1)
return(-1);
} else {
if(getarray(in, num, DESTS, read_version, read_flags) == -1)
return(-1);
}
/* owner */
if(getnumber(in, num, OWNER, read_version, read_flags) == -1)
return(-1);
/* contents */
if(getnumber(in, num, CONTENTS, read_version, read_flags) == -1)
return(-1);
/* exits */
if(getnumber(in, num, EXITS, read_version, read_flags) == -1)
return(-1);
/* rooms/pennies */
if(getnumber(in, num, ROOMS, read_version, read_flags) == -1)
return(-1);
/* next */
if(getnumber(in, num, NEXT, read_version, read_flags) == -1)
return(-1);
/* timestamp */
if(getnumber(in, num, TIMESTAMP, read_version, read_flags) == -1)
return(-1);
/* createstamp */
if(getnumber(in, num, CREATESTAMP, read_version, read_flags) == -1)
return(-1);
/* uses */
if(getnumber(in, num, USES, read_version, read_flags) == -1)
return(-1);
/* parent */
if(getnumber(in, num, PARENT, read_version, read_flags) == -1)
return(-1);
/* charges */
if(getnumber(in, num, CHARGES, read_version, read_flags) == -1)
return(-1);
/* semaphores */
if(getnumber(in, num, SEMAPHORES, read_version, read_flags) == -1)
return(-1);
/* cost */
if(getnumber(in, num, COST, read_version, read_flags) == -1)
return(-1);
/* queue */
if(getnumber(in, num, QUEUE, read_version, read_flags) == -1)
return(-1);
/* name */
if(getstring(in, num, NAME, read_version, read_flags) == -1)
return(-1);
if(read_version < 301) {
/* lock */
if(getbool(in, num, LOCK, read_version, read_flags) == -1)
return(-1);
/* enter lock */
if(getbool(in, num, ENLOCK, read_version, read_flags) == -1)
return(-1);
/* page lock */
if(getbool(in, num, PGLOCK, read_version, read_flags) == -1)
return(-1);
/* teleport in lock */
if(getbool(in, num, TELINLOCK, read_version, read_flags) == -1)
return(-1);
/* teleport out lock */
if(getbool(in, num, TELOUTLOCK, read_version, read_flags) == -1)
return(-1);
}
/* attributes */
if(getattributes(in, num, read_version, read_flags) == -1)
return(-1);
} else { /* insane database */
/* name (except for 1.4) */
if(read_version > 199) { /* 2.0a */
if(getstring(in, num, NAME, read_version, read_flags) == -1)
return(-1);
} else if(read_version < 100) { /* 1.x */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(txt_buffer);
if(type == TYP_PLAYER) {
for(ptr = txt_buffer; *ptr && !isspace(*ptr); ptr++);
*ptr++ = '\0';
if((set_str_elt(num, NAME, txt_buffer) == -1) ||
(attr_add(num, PASSWORD, cryptpwd(ptr), PASSWORD_FLGS) == -1)){
fprintf(stderr, txt_dberr, i);
return(-1);
}
} else {
if(set_str_elt(num, NAME, txt_buffer) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
}
/* next */
if(getnumber(in, num, NEXT, read_version, read_flags) == -1)
return(-1);
/* either site, quota, or pennies */
if((read_version < 100) && (read_flags & DB_SITE)
&& (type == TYP_PLAYER)) { /* site */
long addr;
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL){
fprintf(stderr, txt_eoferr, i);
return(-1);
}
addr = htonl(strtol(txt_buffer, &ptr, 10));
if(ptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
snprintf(txt_buffer, TXTBUFFSIZ, "%ld.%ld.%ld.%ld",
(addr >> 24) & 0xff, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
if(attr_add(num, SITE, txt_buffer, SITE_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
} else if(read_version > 99) { /* quota */
if(getnumber(in, num, QUOTA, read_version, read_flags) == -1)
return(-1);
} else if(read_version < 99) { /* pennies */
if(type == TYP_PLAYER) {
if(getnumber(in, num, PENNIES, read_version, read_flags) == -1)
return(-1);
} else {
if(skip_line(in, num) == -1)
return(-1);
}
}
/* location */
if(getnumber(in, num, LOC, read_version, read_flags) == -1)
return(-1);
/* home/dropto/destinations */
if(type != TYP_EXIT) {
if(getnumber(in, num, HOME, read_version, read_flags) == -1)
return(-1);
} else {
if(getarray(in, num, DESTS, read_version, read_flags) == -1)
return(-1);
}
/* owner */
if(getnumber(in, num, OWNER, read_version, read_flags) == -1)
return(-1);
/* 2.0a parent */
if(read_version > 199) {
if(getnumber(in, num, PARENT, read_version, read_flags) == -1)
return(-1);
}
/* contents */
if(getnumber(in, num, CONTENTS, read_version, read_flags) == -1)
return(-1);
/* exits */
if(getnumber(in, num, EXITS, read_version, read_flags) == -1)
return(-1);
/* rooms or pennies */
if(read_version > 99){
if(getnumber(in, num, ROOMS, read_version, read_flags) == -1)
return(-1);
}
/* timestamp */
if((read_version == 2) || (read_version > 3)){
if(getnumber(in, num, TIMESTAMP, read_version, read_flags) == -1)
return(-1);
} else {
if(skip_line(in, num) == -1)
return(-1);
}
/* createstamp and use count */
if(read_version > 199){
if(getnumber(in, num, CREATESTAMP, read_version, read_flags) == -1)
return(-1);
if(getnumber(in, num, USES, read_version, read_flags) == -1)
return(-1);
}
/* lock */
if(getbool(in, num, LOCK, read_version, read_flags) == -1)
return(-1);
/* 1.4 and 2.0a locks */
if(read_version > 99){
if(getbool(in, num, ENLOCK, read_version, read_flags) == -1)
return(-1);
if(getbool(in, num, PGLOCK, read_version, read_flags) == -1)
return(-1);
}
/* 2.0a locks */
if(read_version > 199) {
if(getbool(in, num, TELINLOCK, read_version, read_flags) == -1)
return(-1);
if(getbool(in, num, TELOUTLOCK, read_version, read_flags) == -1)
return(-1);
}
/* 1.x strings */
if(read_version < 100) {
/* suc/osuc or oxteleport/oteleport */
if((read_flags & DB_ARRIVE) && (type == TYP_PLAYER)){
if(getattr(in, num, OXTELEPORT, read_version, read_flags) == -1)
return(-1);
if(getattr(in, num, OTELEPORT, read_version, read_flags) == -1)
return(-1);
} else {
if(getattr(in, num, SUC, read_version, read_flags) == -1)
return(-1);
if(getattr(in, num, OSUC, read_version, read_flags) == -1)
return(-1);
}
/* fail/ofail */
if(getattr(in, num, FAIL, read_version, read_flags) == -1)
return(-1);
if(getattr(in, num, OFAIL, read_version, read_flags) == -1)
return(-1);
/* drop/odrop or kill/okill */
if(read_version > 2) {
if(getattr(in, num, (type == TYP_PLAYER) ? KILL : DROP,
read_version, read_flags) == -1)
return(-1);
if(getattr(in, num, (type == TYP_PLAYER) ? OKILL : ODROP,
read_version, read_flags) == -1)
return(-1);
}
/* oxtel/otel */
if(read_version == 5) {
if(getattr(in, num, OXTELEPORT, read_version, read_flags) == -1)
return(-1);
if(getattr(in, num, OTELEPORT, read_version, read_flags) == -1)
return(-1);
}
/* desc */
if(getattr(in, num, DESC, read_version, read_flags) == -1)
return(-1);
/* sex */
if(getattr(in, num, SEX, read_version, read_flags) == -1)
return(-1);
/* address */
if(read_version == 5) {
if(getattr(in, num, "Address", read_version, read_flags) == -1)
return(-1);
}
} else if(read_version < 200) { /* 1.4 strings */
if(getstrings(in, num, read_version, read_flags) == -1)
return(-1);
} else { /* 2.0a attributes */
if(getattributes(in, num, read_version, read_flags) == -1)
return(-1);
}
}
} else if(read_version < 0) { /* TinyMUD */
char *nptr;
/* Snarf up the object data. */
/* Name. */
if(fgets(tinyobj.name, sizeof(tinyobj.name), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.name);
/* Description. */
if(fgets(tinyobj.description,
sizeof(tinyobj.description), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.description);
/* Location. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.location = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Contents. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.contents = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Exits. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.exits = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Next. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.next = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Lock. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
getbool_ptr = txt_buffer;
tinyobj.lock = getbool_sub(i, read_version, read_flags);
/* Fail. */
if(fgets(tinyobj.fail, sizeof(tinyobj.fail), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.fail);
/* Success. */
if(fgets(tinyobj.succ, sizeof(tinyobj.succ), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.succ);
/* OFail. */
if(fgets(tinyobj.ofail, sizeof(tinyobj.ofail), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.ofail);
/* OSuccess. */
if(fgets(tinyobj.osucc, sizeof(tinyobj.osucc), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.osucc);
/* Owner. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.owner = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Pennies. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.pennies = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Flags. */
if(fgets(txt_buffer, TXTBUFFSIZ, in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
tinyobj.flags = (int)strtol(txt_buffer, &nptr, 10);
if(nptr == txt_buffer) {
fprintf(stderr, txt_numerr, i);
return(-1);
}
/* Password. */
if(fgets(tinyobj.password,
sizeof(tinyobj.password), in) == (char *)NULL) {
fprintf(stderr, txt_eoferr, i);
return(-1);
}
remove_newline(tinyobj.password);
/* Do some conversions. */
if(tinyobj.flags & 0x8)
tinyobj.lock = negate_bool(tinyobj.lock);
/* Process flags and create the object. */
flags = convert_flags(tinyobj.flags, read_version, read_flags);
type = (flags[0] & TYPE_MASK);
ret = create_obj(type);
if(ret != num){
fprintf(stderr, "Internal and input databases out of sync at #%d.\n",
num);
return(-1);
}
flags[1] = ((flags[1] & ~INTERNAL_FLAGS) |
(DSC_FLAG2(main_index[num]) & INTERNAL_FLAGS));
for(e = 0; e < FLAGS_LEN; e++)
(DSC_FLAGS(main_index[num]))[e] = flags[e];
/* Set the data. */
DSC_OWNER(main_index[num]) = tinyobj.owner;
DSC_NEXT(main_index[num]) = tinyobj.next;
switch(flags[0] & TYPE_MASK) {
case TYP_PLAYER:
case TYP_THING:
DSC_HOME(main_index[num]) = tinyobj.exits;
if((set_int_elt(num, LOC, tinyobj.location) == -1)
|| (set_int_elt(num, PENNIES, tinyobj.pennies) == -1)) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
break;
case TYP_ROOM:
DSC_DROPTO(main_index[num]) = tinyobj.location;
if(set_int_elt(num, EXITS, tinyobj.exits) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
break;
case TYP_EXIT:
if(tinyobj.location != -1) {
int iptr[2];
iptr[0] = 1;
iptr[1] = tinyobj.location;
if(set_array_elt(num, DESTS, iptr) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
break;
}
if(set_str_elt(num, NAME, tinyobj.name) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
if(tinyobj.description[0]) {
if(attr_add(num, DESC, tinyobj.description, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
if(tinyobj.fail[0]) {
if(attr_add(num, FAIL, tinyobj.fail, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
if(tinyobj.ofail[0]) {
if(attr_add(num, OFAIL, tinyobj.ofail, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
if(tinyobj.succ[0]) {
if(attr_add(num, SUC, tinyobj.succ, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
if(tinyobj.osucc[0]) {
if(attr_add(num, OSUC, tinyobj.osucc, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
if(tinyobj.password[0]) {
if(attr_add(num, PASSWORD, cryptpwd(tinyobj.password),
PASSWORD_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
if(tinyobj.lock != (struct boolexp *)NULL) {
if(attr_addlock(num, LOCK, tinyobj.lock, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
}
stamp(num, STAMP_USED);
}
if(gender[0]) {
if(attr_add(num, SEX, gender, DEFATTR_FLGS) == -1) {
fprintf(stderr, txt_dberr, i);
return(-1);
}
gender[0] = '\0';
}
break;
case '@': /* garbage */
garbage++;
mudstat.total_objects++;
main_index[i] = (struct dsc *)NULL;
break;
case '*': /* the end */
done++;
break;
default:
fprintf(stderr, "Database format error near object #%d.\n", i);
return(-1);
}
if((i % 100) == 0)
cache_trim();
}
mudstat.garbage_count += garbage;
fputc('\n', stderr);
fflush(stderr);
return(0);
}