/*
#ident "@(#)smail/pd/pathalias:RELEASE-3_2_0_115:makedb.c,v 1.14 2003/03/27 18:57:05 woods Exp"
 */

/*
 * pathalias -- by steve bellovin, as told to peter honeyman
 */
#ifndef lint
static char	*sccsid = "@(#)makedb.c	9.1 87/10/04";
static char	*rcsid = "@(#)smail/pd/pathalias:RELEASE-3_2_0_115:makedb.c,v 1.14 2003/03/27 18:57:05 woods Exp";
#endif /* lint */

#include "defs.h"				/* Smail-3 */

#include <stdio.h>

#include "config.h"

#if defined(UNIX_SYS5) || defined(POSIX_OS) || defined(USE_FCNTL)
# include <fcntl.h>
#else
# if defined(UNIX_BSD)
#  include <sys/file.h>
# endif
#endif
#ifdef __GLIBC__
# include <sys/file.h>
#endif

#include "smailport.h"

#include "dbm_compat.h"

#if defined(HAVE_DBM) && !defined(HAVE_NDBM)
static int dbfile __P((char *));
static int dbcreat __P((char *));
#else
# define dbfile(f)	(0)
# define dbcreat(f,s)	(0)
#endif

static void makedb __P((char *));
static void perror_ __P((char *));

char *Ofile = ALIASDB, *ProgName;

#define USAGE "%s [-o dbmname] [-a] [file ...]\n"

/* silly ANSI C warning avoidance... */
int main __P((int, char **));

int
main(argc, argv)
	int argc;
	char *argv[];
{	char *ofptr;
	int c, append = 0;
	extern int optind;
	extern char *optarg;

	ProgName = argv[0];
	while ((c = getopt(argc, argv, "o:a")) != EOF)
		switch(c) {
		case 'o':	/* dbm output file */
			Ofile = optarg;
			break;

		case 'a':	/* append mode */
			append++;
			break;

		default:
			fprintf(stderr, USAGE, ProgName);
			exit(EX_USAGE);
			break;
		}


	if ((ofptr = rindex(Ofile, '/')) != 0)
		ofptr++;
	else
		ofptr = Ofile;
#if defined(ANSI_C) && !defined(NO_SIZE_T_STRLEN)
	if (strlen(ofptr) > (size_t)10)
#endif
	{
		ofptr[10] = 0;
		fprintf(stderr, "%s: using %s for dbm output\n", ProgName, Ofile);
	}

	if (append == 0 && dbfile(Ofile) != 0) {
		perror_(Ofile);
		exit(EX_IOERR);
	}

	if (dbminit(Ofile) < 0) {
		perror_(Ofile);
		exit(EX_IOERR);
	}

	if (optind == argc)
		makedb((char *) 0);
	else for ( ; optind < argc; optind++)
		makedb(argv[optind]);

	dbmclose();

	exit(EX_OK);
}

#if defined(HAVE_DBM) && !defined(HAVE_NDBM)
static int
dbfile(dbf)
	char *dbf;
{
	return (dbcreat(dbf, "dir") != 0 || dbcreat(dbf, "pag") != 0);
}

static int
dbcreat(dbf, suffix)
	char *dbf, *suffix;
{	char buf[BUFSIZ];
	int fd;

	(void) sprintf(buf, "%s.%s", dbf, suffix);
	if ((fd = creat(buf, 0666)) < 0)
		return(-1);
	(void) close(fd);
	return(0);
}
#endif

static void
makedb(ifile)
	char *ifile;
{	char line[BUFSIZ];
	datum key, val;

	if (ifile && (freopen(ifile, "r", stdin) == NULL)) {
		perror_(ifile);
		return;
	}

	/*
	 * keys and values are 0 terminated.  this wastes time and (disk) space,
	 * but does lend simplicity and backwards compatibility.
	 */
	key.dptr = line;
	while (fgets(line, sizeof(line), stdin) != NULL) {
		char *op, *end;

		end = line + strlen(line);
		end[-1] = 0;	/* kill newline, stuff null terminator */
		op = index(line, '\t');
		if (op != 0) {
			*op++ = 0;
			key.dsize = op - line;		/* 0 terminated */
			val.dptr = op;
			val.dsize = end - op;		/* 0 terminated */
		} else {
			key.dsize = end - line;		/* 0 terminated */
			val.dptr = "\0";		/* why must i do this? */
			val.dsize = 1;
		}
		if (store(key, val) < 0)
			perror_(Ofile);
	}
}

static void
perror_(str)
	char	*str;
{
	fprintf(stderr, "%s: ", ProgName);
	perror(str);
}
