/* dbmcmds.c */
#include "copyright.h"
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include "teeny.h"
#include "dbm.h"
void text_dump2();
void putlock2();
#ifdef COMPRESS
extern char *uncompress();
#endif
extern int atoi();
/*
* Implements the other db manager commands.
*/
struct nuked {
int obj;
struct nuked *next;
};
int lists_handle(z, ex, req)
char *z;
char *ex;
char *req;
{
register int i;
int loc;
int flags;
/* first we nuke all the lists in the db. what fun.. */
printf("Spamming...\n");
for (i = 0; i < db_top(); i++) {
if (!exists_object(i))
continue;
if (set_int_elt(i, EXITS, -1) == -1)
printf("Object #%d has a bad exits pointer.\n", i);
if (set_int_elt(i, CONTENTS, -1) == -1)
printf("Object #%d has a bad contents pointer.\n", i);
if (set_int_elt(i, NEXT, -1) == -1)
printf("Object #%d has a bad next pointer.\n", i);
}
/* now we rebuild everything. loc had better have been correct... */
printf("Rebuilding...\n");
for (i = 0; i < db_top(); i++) {
if (!exists_object(i))
continue;
if (get_int_elt(i, LOC, &loc) == -1) {
printf("Object #%d has a bad location reference. Destroy it.\n", i);
continue;
}
if (get_int_elt(i, FLAGS, &flags) == -1) {
printf("Object #%d has a bad flags reference. Destroy it.\n", i);
continue;
}
switch (flags & TYPE_MASK) {
case TYP_THING:
case TYP_PLAYER:
list_add(i, loc, CONTENTS_LIST);
break;
case TYP_EXIT:
list_add(i, loc, EXITS_LIST);
break;
case TYP_ROOM:
list_add(i, loc, ROOMS_LIST);
break;
default:
printf("Object #%d has a bad type. Destroy it.\n", i);
}
}
printf("Done.\n");
}
int pur_handle(p, ex, req)
char *p;
atom *ex;
int *req;
{
int i;
int flags;
int ptr; /* home, dest or dropto */
struct nuked *nuked_list = NULL;
struct nuked *tmp, *nuked_this;
printf("Purging.\n");
/* Make one pass over the db killing stuff, and keeping track */
/* of what's been killed so far. */
for (i = 0; i < db_top(); i++) {
if (exists_object(i) && eval_expr(i, ex, *req)) {
recycle_obj(i, &nuked_list);
nuked_this = (struct nuked *)
ty_malloc(sizeof(struct nuked), "purge");
nuked_this->next = nuked_list;
nuked_this->obj = i;
nuked_list = nuked_this;
}
}
/* Another pass over the DB, checking destinations, and */
/* Handling them as best we can. Reset homes to 0 and */
/* simply unlink exits/rooms pointed at nuked things. */
for (i = 0; i < db_top(); i++) {
if (!exists_object(i))
continue;
/* This depends heavily on the fact that */
/* Destination, Home, and DropTo are all */
/* The same element of an object. */
if (get_int_elt(i, DESTINATION, &ptr) == -1)
goto dropthru;
/* See if the destination has been nuked. */
for (tmp = nuked_list; tmp != NULL; tmp = tmp->next) {
if (tmp->obj == ptr)
break;
}
if (tmp == NULL)
continue;
/* If we get here, the dest HAS been nuked. */
if (get_int_elt(i, FLAGS, &flags) == -1)
goto dropthru;
switch (flags & TYPE_MASK) {
case TYP_PLAYER:
if (set_int_elt(i, DESTINATION, STARTING_LOC) == -1)
goto dropthru;
break;
case TYP_THING:
{
int home, owner;
if (get_int_elt(i, OWNER, &owner) == -1)
goto dropthru;
if (get_int_elt(owner, HOME, &home) == -1)
goto dropthru;
if (set_int_elt(i, HOME, home) == -1)
goto dropthru;
}
break;
case TYP_ROOM:
case TYP_EXIT:
if (set_int_elt(i, DESTINATION, -1) == -1)
goto dropthru;
break;
}
}
free_nuked_list(nuked_list);
return (0);
dropthru:
printf("Bad DB reference in 2nd pass at object %d\n", i);
free_nuked_list(nuked_list);
return (-1);
}
free_nuked_list(nk)
struct nuked *nk;
{
struct nuked *tmp;
if (nk == NULL) {
return;
}
do {
tmp = nk->next;
free((char *) nk);
nk = tmp;
} while (tmp != NULL);
}
int cho_handle(p, ex, req)
char *p;
atom *ex;
int *req;
{
int i, newowner;
while (isspace(*p))
p++;
if (*p++ != '#') {
printf("Invalid object number for new owner.\n");
return (0);
}
newowner = atoi(p);
printf("Chowning selected objects to #%d\n", newowner);
for (i = 0; i < db_top(); i++) {
if (exists_object(i) && eval_expr(i, ex, *req)) {
if (set_int_elt(i, OWNER, newowner) == -1) {
printf("Bad object ref at %d\n", i);
return (-1);
}
}
}
return (0);
}
int sum_handle(p, ex, req)
char *p;
atom *ex;
int *req;
{
int i;
char *name;
int owner;
char *ownername;
int flags;
char *q, ch = '\0', work[BUFFSIZ];
for (i = 0; i < db_top(); i++) {
if (exists_object(i) && eval_expr(i, ex, *req)) {
/* Summarize the data for this guy */
if (get_str_elt(i, NAME, &name) == -1) {
printf("DB error at object #%d\n", i);
continue;
}
if (get_int_elt(i, OWNER, &owner) == -1) {
printf("DB error at object #%d\n", i);
continue;
}
if (get_str_elt(owner, NAME, &ownername) == -1) {
printf("DB error at object #%d\n", owner);
continue;
}
if (get_int_elt(i, FLAGS, &flags) == -1) {
printf("DB error at object #%d\n", i);
continue;
}
/* We've got the data. Write it out. */
if (isplayer(i)) {
for (q = name; *q && *q != ' '; q++);
ch = *q;
*q = '\0';
}
printf("(#%d) Name: %s\n", i, name);
if (ch)
*q = ch;
if (isplayer(owner)) {
for (q = ownername; *q && *q != ' '; q++);
ch = *q;
*q = '\0';
}
switch (flags & TYPE_MASK) {
case TYP_EXIT:
strcpy(work, "E/");
break;
case TYP_ROOM:
strcpy(work, "R/");
break;
case TYP_PLAYER:
strcpy(work, "P/");
break;
case TYP_THING:
strcpy(work, "T/");
break;
default:
strcpy(work, "U/");
}
if (flags & GOD)
strcat(work, "G");
if (flags & WIZARD)
strcat(work, "W");
if (flags & ROBOT)
strcat(work, "R");
if (flags & LINK_OK)
strcat(work, "L");
if (flags & JUMP_OK)
strcat(work, "J");
if (flags & ABODE)
strcat(work, "A");
if (flags & HAVEN)
strcat(work, "H");
if (flags & DARK)
strcat(work, "D");
printf("Flags: %s(%d) Owner: %s\n", work, flags,
ownername);
if (ch)
*q = ch;
}
}
}
/*
* First pass of recycling. This does one object.
*/
recycle_obj(obj, nuke_list)
int obj;
struct nuked **nuke_list; /* So we can add things to it. */
{
int loc, flags, next, list;
struct nuked *tmp;
if (obj == 0) {
printf("Cannot recycle object Zero.\n");
return;
}
#if STARTING_LOC != 0
if (obj == STARTING_LOC) {
printf("Cannot recycle player start.\n");
return;
}
#endif /* STARTING_LOC != 0 */
if (get_int_elt(obj, FLAGS, &flags) == -1)
goto bomb;
if (get_int_elt(obj, LOC, &loc) == -1)
goto bomb;
switch (flags & TYPE_MASK) {
case TYP_PLAYER: /* Get the player off the contents list. */
/* Otherwise it's just like a room. */
list_drop(obj, loc, 1);
case TYP_ROOM:
/* Destroy all the exits in room/carried by player */
if (get_int_elt(obj, EXITS, &list) == -1)
goto bomb;
while (list != -1) {
if (get_int_elt(list, NEXT, &next) == -1)
goto bomb;
tmp = (struct nuked *) ty_malloc(sizeof(struct nuked),
"recycle_obj");
tmp->next = *nuke_list;
*nuke_list = tmp;
tmp->obj = list;
destroy_obj(list);
list = next;
}
/* Try to send room contents/player inventory home. */
if (get_int_elt(obj, CONTENTS, &list) == -1)
goto bomb;
while (list != -1) {
if (get_int_elt(list, NEXT, &next) == -1)
goto bomb;
send_home(list, obj);
list = next;
}
/* Now nuke everything left -- i.e. stuff homed here */
if (get_int_elt(obj, CONTENTS, &list) == -1)
goto bomb;
while (list != -1) {
if (get_int_elt(list, NEXT, &next) == -1)
goto bomb;
tmp = (struct nuked *) ty_malloc(sizeof(struct nuked),
"recycle_obj");
tmp->next = *nuke_list;
*nuke_list = tmp;
tmp->obj = list;
destroy_obj(list);
list = next;
}
/* nuke the room/player itself. */
destroy_obj(obj);
break;
case TYP_EXIT:
list_drop(obj, loc, 0);
destroy_obj(obj);
break;
case TYP_THING:
list_drop(obj, loc, 1);
destroy_obj(obj);
break;
default:
printf("Eeek! Unknown object type!\n");
return;
}
return;
bomb:
printf("Something bad happened. Good luck.\n");
return;
}
int fix_handle()
{
int i, list, loc, flags;
int total = 0;
printf("Scanning the database...\n");
for (i = 0; i < db_top(); i++) {
if (!exists_object(i))
continue;
/* loop through the exits list first.. */
if (get_int_elt(i, EXITS, &list) == -1)
goto bomb;
while (list != -1) {
if (get_int_elt(list, LOC, &loc) == -1)
goto bomb;
if (loc != i) {
if (set_int_elt(list, LOC, i) == -1)
goto bomb;
total++;
}
if (get_int_elt(list, NEXT, &list) == -1)
goto bomb;
}
/* now do the contents list. this is slightly more complex.. */
if (get_int_elt(i, CONTENTS, &list) == -1)
goto bomb;
while (list != -1) {
int next;
if (get_int_elt(list, NEXT, &next) == -1)
goto bomb;
if (get_int_elt(list, FLAGS, &flags) == -1)
goto bomb;
if ((flags & TYPE_MASK) == TYP_EXIT) {
if (get_int_elt(list, LOC, &loc) == -1)
goto bomb;
if (loc != i) {
if (set_int_elt(list, LOC, i) == -1)
goto bomb;
}
total++;
list_drop(list, i, 1);
list_add(list, i, 0);
if (set_int_elt(list, DESTINATION, -1) == -1)
goto bomb;
}
list = next;
}
/* all done with that sucker... */
}
printf("Scan done. %d exits fixed.\n", total);
return (0);
bomb:
printf("Database corrupt. Scan aborted.\n");
return (-1);
}
/*
* Utility funtions.
*
*/
/* Sends an object home */
send_home(obj, loc)
int obj;
int loc;
{
int home;
if (get_int_elt(obj, HOME, &home) == -1) {
printf("Object #%d has a bad home reference.\n", obj);
return;
}
list_drop(obj, loc, CONTENTS_LIST); /* Drop it from contents list here */
if (!exists_object(home)) {
home = STARTING_LOC; /* Fake it, eh? */
}
if (set_int_elt(obj, LOC, home) == -1) {
printf("Could not set location for object #%d.\n", obj);
return;
}
list_add(obj, home, CONTENTS_LIST);
}