/* convertdb.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. * */ #include <stdio.h> #include <sys/types.h> #ifdef HAVE_STRING_H #include <string.h> #else #include <strings.h> #endif /* HAVE_STRING_H */ #include <time.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif /* HAVE_STDLIB_H */ #ifdef HAVE_UNISTD_H #include <unistd.h> #endif /* HAVE_UNISTD_H */ #include "conf.h" #include "teeny.h" #include "teenydb.h" #include "textdb.h" #include "ptable.h" #include "sha/sha_wrap.h" #include "gnu/getopt.h" #include "externs.h" extern int errno; static void print_version _ANSI_ARGS_((void)); static void print_help _ANSI_ARGS_((void)); static void upgrade_database _ANSI_ARGS_((int, int, int)); static void create_startup _ANSI_ARGS_((void)); enum text_state { TEXT_NONE, TEXT_READ, TEXT_WRITE }; static char *progname; static struct option const getopt_options[] = { { "configuration", required_argument, 0, 'c' }, { "filter-garbage", no_argument, 0, 'G' }, { "input-file", required_argument, 0, 'i' }, { "initialize-db", no_argument, 0, 's' }, { "output-file", required_argument, 0, 'o' }, { "nonstandard", no_argument, 0, 'C' }, { "xibo-compat", no_argument, 0, 'X' }, { "use-existing-root", no_argument, 0, 'e' }, { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, { NULL, 0, 0, '\0' } }; extern const char teenymud_version[]; static void print_version() { fprintf(stderr, "This is the TeenyMUD Database Conversion System, version %s\n", teenymud_version); } static void print_help() { print_version(); fputs("Choose from the following:\n", stderr); fputs("-c, --configuration\tspecify configuration file\n", stderr); fputs("-e, --use-existing-root\tforce use of existing root room\n", stderr); fputs("-G, --filter-garbage\tdo not write garbage objects\n", stderr); fputs("-i, --input-file\tspecify input file\n", stderr); fputs("-o, --output-file\tspecify output file\n", stderr); fputs("-s, --initialze-db\tcreate a new database\n", stderr); fputs("-C, --nonstandard\tenable nonstandard compatibility\n", stderr); fputs("-X, --xibo-compat\tenable 1.3 compatibility\n", stderr); fputs("-h, --help\t\tprint this help message\n", stderr); fputs("-v, --version\t\tprint the version number\n", stderr); } int main(argc, argv) int argc; char **argv; { int ch, read_version, read_flags, read_total; int dash_c = 0, one_three = 0, use_existing = 0; int startup = 0; int output_flags = OUTPUT_FLAGS; enum text_state state = TEXT_NONE; char *conf_file = (char *) NULL; char *text_in = (char *) NULL; char *text_out = (char *) NULL; char buffer[BUFFSIZ]; FILE *text; progname = ty_basename(argv[0]); opterr = 0; while ((ch = getopt_long(argc, argv, "c:i:o:esCXGhv", getopt_options, (int *)0)) != -1) { switch (ch) { case 'h': print_help(); exit(0); case 'v': print_version(); exit(0); case 's': startup++; break; case 'e': use_existing++; break; case 'c': /* config file */ conf_file = optarg; break; case 'i': if (text_out != (char *) NULL) { fprintf(stderr, "%s: You may only specify one of -i or -o.\n", progname); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } text_in = optarg; state = TEXT_READ; break; case 'o': if (text_in != (char *) NULL) { fprintf(stderr, "%s: You may only specify one of -i or -o.\n", progname); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } text_out = optarg; state = TEXT_WRITE; break; case 'C': /* ancient -C database format */ dash_c++; break; case 'X': /* Xibo database format(tm) */ one_three++; break; case 'G': output_flags |= DB_GFILTER; break; default: fprintf(stderr, "%s: bad option -- %c\n", progname, ch); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } } if (startup && (state != TEXT_NONE)) { fprintf(stderr, "%s: You cannot initialize a text database!\n", progname); exit(0); } if (conf_file == (char *) NULL) { fprintf(stderr, "%s: You must specify a configuration file.\n", progname); exit(0); } if (dash_c && (state != TEXT_READ)) { fprintf(stderr, "%s: You may only specify -C while reading a database.\n", progname); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } if (one_three && (state != TEXT_READ)) { fprintf(stderr, "%s: You may only specify -X while reading a database.\n", progname); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } if ((output_flags & DB_GFILTER) && (state != TEXT_WRITE)) { fprintf(stderr, "%s: You may only specify -G while writing a database.\n", progname); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } /* works just like the MUD, now. */ mudstat.status = MUD_COLD; time(&mudstat.now); if(conf_init(conf_file) == -1) exit(-1); /* first things first. */ if(chdir(mudconf.chdir_path) != 0) { fprintf(stderr, "%s: chdir [%s] failed: %s, continuing...\n", progname, mudconf.chdir_path, strerror(errno)); } cache_init(); fprintf(stderr, "TeenyMUD %s database conversion system.\n", teenymud_version); fprintf(stdout, "TeenyMUD %s is Copyright(C) 1993, 1994, 1995 Jason Downs.\n", teenymud_version); fputs("TeenyMUD is free software and comes with absolutely no warranty.\n", stdout); fprintf(stderr, "Read configuration for %s.\n", mudconf.name); if(startup) create_startup(); /* This is all self-contained. */ switch (state) { case TEXT_READ: if ((text = fopen(text_in, "r")) == NULL) { fprintf(stderr, "Couldn't open %s for read, %s\n", text_in, strerror(errno)); exit(-1); } if (dbmfile_init(mudconf.dbm_file, TEENY_DBMFAST) != 0) { fprintf(stderr, "Couldn't open dbm file %s.\n", mudconf.dbm_file); exit(-1); } fputs("Looking at your database...\n", stderr); if(text_version(text, &read_version, &read_flags, &read_total) == -1){ fputs("Aborting.\n", stderr); exit(-1); } if(read_version >= 0) { /* TeenyMUD */ if(read_version == 0) { /* might really be version 5 */ if (!dash_c) { fputs("Hmmm. Your database appears to be a very old format.\n", stderr); fputs("Was it created by the old TeenyMUD 1.1-C server? [n] ", stderr); fflush(stderr); if(fgets(buffer, BUFFSIZ, stdin) == (char *)NULL) { fputs("Aborting.\n", stderr); exit(-1); } if((buffer[0] == 'y') || (buffer[0] == 'Y')) read_version = 5; } else read_version = 5; } else if((read_version < 5) && (read_version > 0)){/* might be 1.3 */ if (!one_three) { fputs("Hmmm. Your database appears to be an old format,\n", stderr); fputs("and I can't tell if it was created by TeenyMUD 1.2,\n", stderr); fputs("or TeenyMUD 1.3. Which one is it? [1.3] ", stderr); fflush(stderr); if(fgets(buffer, BUFFSIZ, stdin) == (char *)NULL) { fputs("Aborting.\n", stderr); exit(-1); } if(!strchr(buffer, '2')){ read_flags |= DB_SITE; read_flags |= DB_ARRIVE; } } else { read_flags |= DB_SITE; read_flags |= DB_ARRIVE; } } if((read_version > 9) && (read_version < 20)) { /* 1.3 */ read_version -= 10; read_flags |= DB_SITE; read_flags |= DB_ARRIVE; } if((read_version < 5) && !(read_flags & DB_SITE)) { fputs("Hmm, looks like a pre-1.3 TeenyMUD database.\n", stderr); } else if((read_version < 5) && (read_flags & DB_SITE)) { fputs("Hmm, looks like a TeenyMUD 1.3 database.\n", stderr); } else if(read_version == 5) { fputs("Hmm, looks like a TeenyMUD 1.1-C database.\n", stderr); } else if(read_version < 200) { fputs("Hmm, looks like a TeenyMUD 1.4 or TeenyMUSK database.\n", stderr); } else if(read_version < 300) { fputs("Hmm, looks like a TeenyMUD 2.0a database.\n", stderr); } else { fputs("Hmm, looks like a TeenyMUD 2.0 database.\n", stderr); } } else { /* Something else. */ if(read_version == -1) fputs("Hmm, looks like a TinyMUD database. Buh.\n", stderr); } fputs("Loading text database", stderr); fflush(stderr); if(text_load(text, read_version, read_flags, read_total) == -1) { fputs("Load of text database failed. Aborting.\n", stderr); exit(-1); } fclose(text); fprintf(stderr, "Loaded text database version %d.", read_version); if (read_flags & DB_SITE) fputs(" [SITE]", stderr); if (read_flags & DB_ARRIVE) fputs(" [ARRIVE]", stderr); if (read_flags & DB_DESTARRAY) fputs(" [DESTARRAY]", stderr); if (read_flags & DB_PARENTS) fputs(" [PARENTS]", stderr); if (read_flags & DB_IMMUTATTRS) fputs(" [IMMUTATTRS]", stderr); fputc('\n', stderr); if (read_version < 300) upgrade_database(read_version, read_flags, use_existing); break; case TEXT_WRITE: if ((text = fopen(text_out, "w")) == NULL) { fprintf(stderr, "Couldn't open %s for write.\n", text_out); exit(-1); } fputs("Writing text database", stderr); fflush(stderr); if (dbmfile_open(mudconf.dbm_file, TEENY_DBMFAST|TEENY_DBMREAD) != 0) { fprintf(stderr, "Couldn't open dbm file %s\n", mudconf.dbm_file); exit(-1); } if (database_read(mudconf.db_file) != 0) { fprintf(stderr, "Couldn't read database file %s\n", mudconf.db_file); exit(-1); } ptable_init(); text_dump(text, OUTPUT_VERSION, output_flags); fclose(text); break; default: fprintf(stderr, "%s: You must specify one of either -i or -o.\n", progname); fprintf(stderr, "%s: Use '%s --help' for a complete list of options.\n", progname, progname); exit(0); } cache_flush(); dbmfile_close(); if (database_write(mudconf.db_file) == -1) fputs("Error writing database file.\n", stderr); return (0); } static void upgrade_database(read_version, read_flags, use_existing) int read_version, read_flags, use_existing; { register int i; int default_loc; int newloc = 0; default_loc = mudconf.root_location; if ((read_version < 100) && !use_existing) { char ibuff[16]; fputs("Create a new room to be the root? [Ny] ", stderr); fflush(stderr); if(fgets(ibuff, sizeof(ibuff), stdin) != (char *)NULL) { if((ibuff[0] == 'y') || (ibuff[0] == 'Y')) { default_loc = create_obj(TYP_ROOM); if(default_loc == -1) { fprintf(stderr, "Couldn't create root room. Aborting!\n"); return; } if((set_str_elt(default_loc, NAME, "Root Room") == -1) || (set_int_elt(default_loc, OWNER, mudconf.player_god) == -1)) { fprintf(stderr, "Couldn't set root room name or owner. Aborting!\n"); return; } stamp(default_loc, STAMP_MODIFIED); newloc++; fprintf(stderr, "Created a root room with object #%d.\n", default_loc); fputs("(Be sure to put this object number in your configuration.)\n", stderr); } } if((read_version < 100) && !newloc) { if (!exists_object(default_loc) || !isROOM(default_loc)) { fprintf(stderr, "Illegal default room location (#%d), reseting to #0.\n", default_loc); default_loc = 0; } if (!exists_object(default_loc) || !isROOM(default_loc)) { fprintf(stderr, "Illegal default room location (#%d). Fatal error.\n", default_loc); exit(-1); } fprintf(stderr, "Using object #%d as the root room.\n", default_loc); } fputs("Upgrading the database...", stderr); fflush(stderr); if(read_version < 0) { /* TinyMUD. */ /* Figure out exit locations... Augh. */ int list, next; for (i = 0; i < mudstat.total_objects; i++) { if ((main_index[i] == (struct dsc *)NULL) || (DSC_TYPE(main_index[i]) == TYP_EXIT)) continue; /* Check the contents list. */ if(get_int_elt(i, CONTENTS, &list) == -1) { fprintf(stderr, "Database error on #%d.\n", i); return; } while(list != -1) { if(_exists_object(list)) { next = DSC_NEXT(main_index[list]); if(Typeof(list) == TYP_EXIT) { list_drop(list, i, CONTENTS); list_add(list, i, EXITS); } list = next; } else { fprintf(stderr, "Database error on #%d.\n", i); return; } } /* Check the exits list. */ if(get_int_elt(i, EXITS, &list) == -1) { fprintf(stderr, "Database error on #%d.\n", i); return; } while(list != -1) { if(_exists_object(list)) { if(set_int_elt(list, LOC, i) == -1) { fprintf(stderr, "Database error on #%d.\n", list); return; } list = DSC_NEXT(main_index[list]); } else { fprintf(stderr, "Database error on #%d.\n", i); return; } } } } if (read_version < 100) { for (i = 0; i < mudstat.total_objects; i++) { if ((main_index[i] == (struct dsc *)NULL) || (DSC_TYPE(main_index[i]) != TYP_ROOM)) continue; DSC_NEXT(main_index[i]) = -1; list_add(i, default_loc, ROOMS); if(set_int_elt(i, LOC, default_loc) == -1) { fprintf(stderr, "Database error on #%d.\n", i); return; } } } fputs("Done.\n", stderr); fflush(stderr); } else if((read_version == 200) || (read_version < 0)) { int loc; fprintf(stderr, "Recycling %s...", ((read_version == 200) ? "programs" : "garbage")); fflush(stderr); for (i = 0; i < mudstat.total_objects; i++) { if (main_index[i] == NULL) continue; switch(DSC_TYPE(main_index[i])){ case TYP_PLAYER: case TYP_EXIT: case TYP_THING: case TYP_ROOM: break; default: if(get_int_elt(i, LOC, &loc) != -1) { if(_exists_object(loc)) list_drop(i, loc, CONTENTS); destroy_obj(i); } } } fputs("Done.\n", stderr); } } static void create_startup() { int room, wiz; if (dbmfile_init(mudconf.dbm_file, 0) != 0) { fprintf(stderr, "%s: Couldn't upen dbm file %s\n", progname, mudconf.dbm_file); exit(0); } initialize_db(16); mudstat.slack = 16; room = create_obj(TYP_ROOM); wiz = create_obj(TYP_PLAYER); if ((set_str_elt(room, NAME, "Limbo") == -1) || (set_str_elt(wiz, NAME, "Wizard") == -1) || (attr_add(wiz, PASSWORD, cryptpwd("potrzebie"), PASSWORD_FLGS) == -1) || (set_int_elt(wiz, NEXT, -1) == -1) || (set_int_elt(room, NEXT, -1) == -1) || (set_int_elt(wiz, LOC, room) == -1) || (set_int_elt(room, LOC, room) == -1) || (set_int_elt(room, CONTENTS, wiz) == -1) || (set_int_elt(wiz, HOME, room) == -1) || (set_int_elt(room, OWNER, wiz) == -1) || (set_int_elt(wiz, OWNER, wiz) == -1)) { fprintf(stderr, "%s: Something bad happened.\n", progname); exit(0); } stamp(room, STAMP_MODIFIED); stamp(wiz, STAMP_MODIFIED); cache_flush(); dbmfile_close(); if (database_write(mudconf.db_file) == -1) fprintf(stderr, "%s: Error writing the database.\n", progname); else fprintf(stderr, "Database initialized.\n"); exit(0); }