untermud/DOC/
untermud/DOC/U/
untermud/DOC/U/U-examples/
untermud/DOC/internals/
untermud/DOC/wizard/
untermud/MISC/
untermud/MISC/dbchk/
untermud/RWHO/
untermud/RWHO/rwhod/
/*
    Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

/* configure all options BEFORE including system stuff. */
#include    "config.h"
#include    "mud.h"

#ifdef WIN32
#include    "getopt.h"
#endif

extern char *optarg;
extern int optind;
extern int opterr;

#ifdef  DB_DIRHASH
extern int dhdb_init ();
extern int dhdb_travstart ();
extern int dhdb_traverse ();
extern int dhdb_travend ();
extern Obj *dhdb_get ();
extern int dhdb_close ();
extern int dhdb_backup ();
#endif

#ifdef  DB_DBMFILE
extern int dddb_init ();
extern int dddb_travstart ();
extern int dddb_traverse ();
extern int dddb_travend ();
extern Obj *dddb_get ();
extern int dddb_close ();
extern int dddb_backup ();
#endif

#ifdef  DB_GDBMFILE
extern int dgdb_init ();
extern int dgdb_travstart ();
extern int dgdb_traverse ();
extern int dgdb_travend ();
extern Obj *dgdb_get ();
extern int dgdb_close ();
extern int dgdb_backup ();
#endif

int usage ();
int setexpr (char *s);
int checkexpr (char *nam, Obj * op);

int main (int ac, char **av)
{
  int (*initin) () = 0;
  int (*travstart) () = 0;
  int (*trav) () = 0;
  int (*travclose) () = 0;
  Obj *(*objget) () = 0;
  int (*closer) () = 0;
  int (*backup) () = 0;
  char obuf[MAXOID];
  char *outfile = (char *) 0;
  Obj *op;

  FILE *out = stdout;
  char typ = '\0';
  char *fdir = (char *) 0;
  char *cexp = (char *) 0;
  int cnt = 0;
  int vflg = 0;
  int lflg = 0;
  int Bflg = 0;
  int bflg = 0;
  int x;

  while ((x = getopt (ac, av, "Bb:c:o:f:hdgvl")) != EOF) {
    switch (x) {

    case 'o':
      outfile = optarg;
      break;


    case 'b':
      bflg = atoi (optarg);
      if (bflg <= 0) {
        fprintf (stderr, "%s not a valid size\n", optarg);
        exit (1);
      }
      break;

    case 'B':
      Bflg = 1;
      break;

#ifdef  DB_DIRHASH
    case 'h':
      initin = dhdb_init;
      travstart = dhdb_travstart;
      trav = dhdb_traverse;
      travclose = dhdb_travend;
      objget = dhdb_get;
      closer = dhdb_close;
      backup = dhdb_backup;
      typ = 'h';
      break;
#endif


#ifdef  DB_DBMFILE
    case 'd':
      initin = dddb_init;
      travstart = dddb_travstart;
      trav = dddb_traverse;
      travclose = dddb_travend;
      objget = dddb_get;
      closer = dddb_close;
      backup = dddb_backup;
      typ = 'd';
      break;
#endif


#ifdef  DB_GDBMFILE
    case 'g':
      initin = dgdb_init;
      travstart = dgdb_travstart;
      trav = dgdb_traverse;
      travclose = dgdb_travend;
      objget = dgdb_get;
      closer = dgdb_close;
      backup = dgdb_backup;
      typ = 'g';
      break;
#endif


    case 'c':
      cexp = optarg;
      break;


    case 'f':
      fdir = optarg;
      break;


    case 'v':
      vflg++;
      break;


    case 'l':
      lflg++;
      break;


    case '?':
    default:
      exit (usage ());
    }
  }

  if (initin == 0) {
    fprintf (stderr, "what kind of database is this?\n");
    exit (1);
  }

  if (fdir != (char *) 0) {
#ifdef  DB_DIRHASH
    if (typ == 'h') {
      dhdb_sethpath (fdir);
      if (bflg)
        dhdb_sethsiz (bflg);
    }
#endif
#ifdef  DB_DBMFILE
    if (typ == 'd') {
      dddb_setfile (fdir);
      if (bflg)
        dddb_setbsiz (bflg);
    }
#endif
#ifdef  DB_GDBMFILE
    if (typ == 'g')
      dgdb_setfile (fdir);
#endif
  }


  /* compile expression and check syntax */
  if (cexp != (char *) 0 && setexpr (cexp))
    exit (1);


  /* open database */
  if ((*initin) ()) {
    fprintf (stderr, "cannot initialize db layer\n");
    exit (1);
  }


  /* backup mode/setup output */
  if (Bflg) {
    if (outfile == (char *) 0) {
      fprintf (stderr, "backup requires an output filename\n");
      exit (1);
    }
    /* do backup and exit */
    if ((*backup) (outfile)) {
      fprintf (stderr, "cannot backup db\n");
      exit (1);
    }
    exit (0);
  } else {
    if (outfile != (char *) 0) {
      if ((out = fopen (outfile, "wb")) == (FILE *) 0) {
        perror (outfile);
        exit (1);
      }
    }
  }



  /* ready traverse */
  if ((*travstart) ()) {
    fprintf (stderr, "cannot start db traverse\n");
    exit (1);
  }

  /* traverse */
  while ((*trav) (obuf)) {
    tmp_sync ();
    if ((op = (*objget) (obuf)) == (Obj *) 0) {
      fprintf (stderr, "WARNING: cannot get object %s\n", obuf);
      continue;
    }

    if (cexp != (char *) 0 && checkexpr (obuf, op) == 0) {
      if (vflg)
        fprintf (stderr, "-> %s\n", obuf);
      objfree (op);
      continue;
    }

    /* list only */
    if (lflg) {
      fprintf (out, "%s\n", obuf);
      cnt++;
      objfree (op);
      continue;
    }

    oiftoFILE (op, out, obuf);
    objfree (op);
    if (vflg)
      fprintf (stderr, "+> %s\n", obuf);
    cnt++;
  }


  if ((*travclose) ()) {
    fprintf (stderr, "cannot cleanly shut down db traverse\n");
    exit (1);
  }


  if ((*closer) ()) {
    fprintf (stderr, "cannot cleanly close db\n");
    exit (1);
  }

  fprintf (stderr, "dumped %d objects\n", cnt);
  exit (0);
}



int usage ()
{
  fprintf (stderr,
    "usage: dumpdb -d|h|g [db type] [-f datapath] [-o outfile]\n");
  return (1);
}