/* sanity.c */
#include "config.h"
/*
* This file is part of TeenyMUD II.
* Copyright(C) 1993, 1994 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.
*
*/
#include <stdio.h>
#include <sys/types.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 <varargs.h>
#include "conf.h"
#include "teeny.h"
#include "teenydb.h"
#include "gnu/getopt.h"
#include "externs.h"
#if defined(HAVE_DOPRNT) && !defined(HAVE_VPRINTF)
#define vfprintf(_s, _f, _a) _doprnt(_f, _a, _s)
#endif
static char usage[] =
"Usage: %s -g <gdbm file> -d <db file>\n";
#define USAGE(s) (fprintf(stderr, usage, s))
void check_location(object)
int object;
{
int loc, list;
if (get_int_elt(object, LOC, &loc) == -1) {
printf("#%d has no location element.\n", object);
return;
}
if (!exists_object(loc) || !has_contents(loc) ||
(isroom(object) && !isroom(loc))) {
printf("#%d has an invalid location (#%d).\n", object, loc);
return;
}
if (object == loc) {
printf("#%d has a looping location.\n", object);
return;
}
switch (Typeof(object)) {
case TYP_ROOM:
if (get_int_elt(loc, ROOMS, &list) == -1) {
printf("#%d has no rooms list.\n", loc);
return;
}
break;
case TYP_EXIT:
if (get_int_elt(loc, EXITS, &list) == -1) {
printf("#%d has no exits list.\n", loc);
return;
}
break;
default:
if (get_int_elt(loc, CONTENTS, &list) == -1) {
printf("#%d has no contents list.\n", loc);
return;
}
}
if (!member(object, list)) {
printf("#%d has location #%d, but isn't in contents/exits/rooms list.\n",
object, loc);
return;
}
}
void check_contents(object)
int object;
{
int list;
int depth = 10000;
if (get_int_elt(object, CONTENTS, &list) == -1) {
printf("#%d has no contents list.\n", object);
return;
}
if (!has_contents(object) && (list != -1)) {
printf("#%d shouldn't have a contents list, but does.\n", object);
return;
}
while (list != -1) {
if (isroom(list) || isexit(list)) {
printf("#%d has #%d (a %s) in its contents list.\n", object, list,
isroom(list) ? "room" : "exit");
}
if (get_int_elt(list, NEXT, &list) == -1) {
printf("#%d has no next reference.\n", list);
return;
}
depth--;
if (depth < 0) {
printf("#%d has a looping contents list.\n", object);
return;
}
}
}
void check_exits(object)
int object;
{
int list;
int depth = 10000;
if (get_int_elt(object, EXITS, &list) == -1) {
printf("#%d has no exits list.\n", object);
return;
}
if (!has_exits(object) && (list != -1)) {
printf("#%d shouldn't have an exits list, but does.\n", object);
return;
}
while (list != -1) {
if (!isexit(list)) {
printf("#%d has #%d (which isn't an exit) in its exits list.\n", object,
list);
}
if (get_int_elt(list, NEXT, &list) == -1) {
printf("#%d has no next reference.\n", list);
return;
}
depth--;
if (depth < 0) {
printf("#%d has a looping exits list.\n", object);
return;
}
}
}
void check_rooms(object)
int object;
{
int list;
int depth = 10000;
if (has_rooms(object)) {
if (get_int_elt(object, ROOMS, &list) == -1) {
printf("#%d has no rooms list.\n", object);
return;
}
while (list != -1) {
if (!isroom(list)) {
printf("#%d has #%d (which isn't a room) in its rooms list.\n", object,
list);
}
if (get_int_elt(list, NEXT, &list) == -1) {
printf("#%d has no next reference.\n", list);
return;
}
depth--;
if (depth < 0) {
printf("#%d has a looping rooms list.\n", object);
return;
}
}
}
}
void check_homedropto(object)
int object;
{
int home;
if (!has_home(object) && !has_dropto(object))
return;
if (get_int_elt(object, HOME, &home) == -1) {
printf("#%d has no home/dropto element.\n", object);
return;
}
if (((home != -1) && (home != -3) && !exists_object(home)) ||
(exists_object(home) && isexit(home))) {
printf("#%d has an invalid home/dropto (#%d).\n", object, home);
return;
}
if ((home == -3) && !isroom(object) && !isexit(object)) {
printf("#%d has an invalid home (-3).\n", object);
return;
}
if (home == object) {
printf("#%d has a looping home/dropto.\n", object);
return;
}
}
void check_owner(object)
int object;
{
int owner;
if (get_int_elt(object, OWNER, &owner) == -1) {
printf("#%d has no owner element.\n", object);
return;
}
if ((!exists_object(owner) || !isplayer(owner)) ||
(isplayer(object) && !isplayer(owner))) {
printf("#%d has an invalud owner (#%d).\n", object, owner);
return;
}
}
void check_parent(object)
int object;
{
int parent;
if (get_int_elt(object, PARENT, &parent) == -1) {
printf("#%d has no parent element.\n", object);
return;
}
if ((parent != -1) && !exists_object(parent)) {
printf("#%d has an invalud parent (#%d).\n", object, parent);
return;
}
}
void check_name(object)
int object;
{
char *name;
if (get_str_elt(object, NAME, &name) == -1) {
printf("#%d has no name element.\n", object);
return;
}
if (!name || !*name) {
printf("#%d has a null name.\n", object);
return;
}
}
void check_quota(object)
int object;
{
int quota;
if (get_int_elt(object, QUOTA, "a) == -1) {
printf("#%d has a bad quota element.\n", object);
return;
}
if ((quota != 0) && !has_quota(object)) {
printf("#%d has a quota of %d, but isn't a player.\n", object, quota);
return;
}
if ((quota != STARTING_QUOTA) && has_quota(object))
printf("#%d has a quota of %d objects.\n", object, quota);
}
void check_pennies(object)
int object;
{
int pennies;
if (has_pennies(object)) {
if (get_int_elt(object, PENNIES, &pennies) == -1) {
printf("#%d has a bad pennies element.\n", object);
return;
}
if ((pennies < 0) || (pennies > mudconf.max_pennies))
printf("#%d has %d pennies.\n", object, pennies);
}
}
int main(argc, argv)
int argc;
char **argv;
{
int ch, obj, loc;
char *gdbm_file = (char *) 0;
char *db_file = (char *) 0;
extern char *optarg;
extern int opterr;
opterr = 0;
while ((ch = getopt(argc, argv, "g:d:")) != -1) {
switch (ch) {
case 'g': /* gdbm */
gdbm_file = optarg;
break;
case 'd': /* db */
db_file = optarg;
break;
default:
USAGE(argv[0]);
exit(-1);
}
}
if ((gdbm_file == (char *) 0) || (db_file == (char *) 0)) {
fputs("You must specify both -g and -d arguments.\n", stderr);
USAGE(argv[0]);
exit(-1);
}
#ifdef SUNMALLOC
init_malloc();
#endif /* SUNMALLOC */
cache_init(40960L, 0, 0);
if (open_dbmfile(gdbm_file, TEENY_DBMFAST) != 0) {
(void) fprintf(stderr, "Couldn't open gdbm file %s\n", gdbm_file);
exit(-1);
}
if (database_read(db_file) != 0) {
(void) fprintf(stderr, "Couldn't read database file %s\n", db_file);
exit(-1);
}
init_ptable();
/* do it to it */
for (obj = 0; obj < mudstat.total_objects; obj++) {
if (main_index[obj] == (struct dsc *) 0) {
printf("#%d is garbage.\n", obj);
continue;
}
check_location(obj);
check_exits(obj);
check_contents(obj);
check_rooms(obj);
check_homedropto(obj); /* does home and dropto */
check_owner(obj);
check_parent(obj);
check_quota(obj);
check_pennies(obj);
check_name(obj);
DSC_FLAGS(main_index[obj]) &= ~MARKED;
cache_trim();
}
#if 0
/* scan for rooms with no entrances */
for (obj = 0; obj < mudstat.total_objects; obj++) {
if ((main_index[obj] == (struct dsc *) 0) || !ExitP(main_index[obj]) ||
(DSC_DESTINATION(main_index[obj]) < 0) ||
(get_int_elt(obj, LOC, &loc) == -1) ||
(loc == DSC_DESTINATION(main_index[obj])))
continue;
DSC_FLAGS(main_index[DSC_DESTINATION(main_index[obj])]) |= MARKED;
}
for (obj = 0; obj < mudstat.total_objects; obj++) {
if ((main_index[obj] == (struct dsc *) 0) || !RoomP(main_index[obj]))
continue;
if (!(DSC_FLAGS(main_index[obj]) & MARKED))
printf("#%d is a room with no entrances.\n", obj);
}
#endif
fflush(stdout);
cache_flush();
close_dbmfile();
if (database_write(db_file) == -1)
fputs("Error writing database file.\n", stderr);
return (0);
}
/* extra routines */
/* VARARGS */
void log_error(va_alist)
va_dcl
{
char *format;
va_list args;
va_start(args);
format = (char *) va_arg(args, char *);
(void) vfprintf(stderr, format, args);
va_end(args);
}
/* VARARGS */
void panic(va_alist)
va_dcl
{
char *format;
va_list args;
va_start(args);
format = (char *) va_arg(args, char *);
(void) vfprintf(stderr, format, args);
va_end(args);
exit(1);
}