/* Copyright 1993 - Matti Aarnio, Turku University, Turku, Finland
   This will be free software, but only when it is finished.

   The way the Zmailer uses DBM entries is by using strings with
   their terminating NULL as keys, and as data..  Thus the length
   is strlen(string)+1, not strlen(string) !
*/

#include "hostenv.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_NDBM
#include <ndbm.h>
#else
#ifdef HAVE_GDBM
#include <gdbm.h>
#else
	error:error:Only NDBM and GDBM supported! (NDBM primarily)
#endif
#endif

#define PROG "makendbm"

#include <errno.h>	/* This (usually) defines the following 3.. */
     /* extern int errno;
	extern char *sys_errlist[];
	extern int sys_nerr; */

extern char *strchr();

extern void create_dbase();

void
usage(prog,err,errno)
char *prog, *err;
int errno;
{
  fprintf(stderr,"Usage: %s database.name [infilename|-]\n",prog);
  fprintf(stderr,"  If no infilename is defined, database.name is assumed.\n");
#ifdef HAVE_NDBM
  fprintf(stderr,"  (NDBM appends  .pag, and .dir  into actual db file names..)\n");
#else /* GDBM.. */
  fprintf(stderr,"  (GDBM DOES NOT append .pag, nor .dir  into actual db file names..)\n");
#endif
  fprintf(stderr," Error now: %s",err);
  if (errno > 0 && errno < sys_nerr)
    fprintf(stderr,", errno=%d (%s)",errno,sys_errlist[errno]);
  fprintf(stderr,"\n");
  exit (1);
}

int
main(argc,argv)
int argc;
char *argv[];
{
  char *dbasename = NULL;
  FILE *infile = NULL;
#ifdef HAVE_NDBM
  DBM *dbmfile;
#else
  GDBM_FILE dbmfile;
#endif

  if (argc < 2) usage(argv[0],"too few arguments",0);
  if (argc > 3) usage(argv[0],"too many arguments",0);
  dbasename = argv[1];

  if (argc == 3) {
    if (strcmp(argv[2],"-")==0)
      infile = stdin;
    else
      infile = (FILE*)fopen(argv[2],"r");
  } else
    infile = (FILE*)fopen(argv[1],"r");

  if (infile == NULL) usage(argv[0],"bad infile",errno);

#ifdef HAVE_NDBM
  dbmfile = dbm_open(dbasename, O_RDWR|O_CREAT|O_TRUNC, 0644);
#else
  /* Play loose .. don't do syncs while writing */
  dbmfile = gdbm_open(dbasename, 0, GDBM_NEWDB|GDBM_FAST, 0644);
#endif
  if (dbmfile == NULL)
    usage(argv[0],"Can't open dbase file",errno);


  create_dbase(infile,dbmfile);

  dbm_close(dbmfile);

  return 0;
}

void
create_dbase(infile,dbmfile)
FILE *infile;
#ifdef HAVE_NDBM
DBM *dbmfile;
#else
GDBM_FILE dbmfile;
#endif
{
	char linebuf[2048];
	char *s, *t;
	datum dat;
	datum key;

	while (!feof(infile) && !ferror(infile) && !dbm_error(dbmfile)) {
	  *linebuf = 0;
	  fgets(linebuf,sizeof(linebuf)-1,infile);
	  if (*linebuf == 0) break; /* Last! */
	  s = (char *)strchr(linebuf,'\n');
	  if (s) *s = 0; /* Zap \n from the end -- if it exists.. */
	  if (*linebuf == '#') continue; /* Comment! */

	  /* Scan first white-space separated token, point its start with t! */
	  t = linebuf;
	  while (*t == '\t' || *t == ' ') ++t;

	  if (*t == 0) continue; /* Blank line! */

	  s = t;
	  while (*s && *s != '\t' && *s != ' ') ++s;
	  if (*s) {
	    *s = 0; /* Found end of input token, put 0 there, and look if
		       there is some data on this line! */
	    ++s;
	    while (*s && (*s == '\t' || *s == ' ')) ++s;
	    /* Point to begin of data after separating white space! */
	  }


	  key.dptr  = t;
	  key.dsize = strlen(t)+1;
	  dat.dptr  = s;
	  dat.dsize = strlen(s)+1;

#ifdef HAVE_NDBM
	  if (dbm_store(dbmfile, key, dat, DBM_INSERT) != 0)
#else
	  if (gdbm_store(dbmfile, key, dat, GDBM_INSERT) != 0)
#endif
	  {
	    fprintf(stderr,"Key: `%s' is duplicate!\n",t);
	  }
	}
}
