#!perl -W
use strict;
use Fcntl;
my $VERSION = 0.01;

# dbconvert - a program to convert xDBM files to xDBM files of other 
# formats
use Getopt::Long;

sub help {
	print <<EOH;
Usage: $0 -i INPUT_FORMAT -o OUTPUT_FORMAT INFILE OUTFILE [OPTIONS]
Convert xDBM files from INPUT_FORMAT to OUTPUT_FORMAT.

  -i, --input-format	set input format
  -o, --output-format	set output format
  -V, --version		display version
  -?, --help		display this help and exit

Report bugs to <sam124\@operamail.com>.
EOH
	exit 0;
}
sub version {
	print "dbconvert version 1.0\n";
	print "Written by Samuel Lauber\n";
	exit 0;
}

my $input_format;
my $output_format;
my @filenames;

sub parse_options {
	my ($version, $help, $input_format_, $output_format_);
	GetOptions(
'version|V',		=> \$version,
'help|?',		=> \$help,
'input_format|i=s',	=> \$input_format_,
'output_format|o=s',	=> \$output_format_,
	);
	if (not defined($input_format_)) {
		die "Please specify an input format\n";
	}
	help() if ($help);
	version() if ($version);
	if ($input_format_ eq "DBM") {
		$input_format = 1;
	} elsif ($input_format_ eq "ODBM") {
		$input_format = 2;
	} elsif ($input_format_ eq "NDBM") {
		$input_format = 3;
	} elsif ($input_format_ eq "SDBM") {
		$input_format = 4;
	} elsif ($input_format_ eq "GDBM") {
		$input_format = 5;
	} elsif ($input_format_ eq "") {
		die "Please specify an input format!\n";
	} else {
	  die <<EOD;
I don't know what input format you are talking about.  You said you 
wanted $input_format_ format.  I don't know about that.  You either 
misspelled the name, or entered a format I don't support.  I support 
DBM, ODBM, NDBM, SDBM, and GDBM.  If there is a Perl module for that 
format, you can try adding it to the list of input formats in this file.  
EOD
	}

	if (not defined($output_format_)) {
		die "Please specify an output format\n";
	}
	if ($output_format_ eq "DBM") {
		$output_format = 1;
	} elsif ($output_format_ eq "ODBM") {
		$output_format = 2;
	} elsif ($output_format_ eq "NDBM") {
		$output_format = 3;
	} elsif ($output_format_ eq "SDBM") {
		$output_format = 4;
	} elsif ($output_format_ eq "GDBM") {
		$output_format = 5;
	} elsif ($output_format_ eq "") {
		die "Please specify an output format!\n";
	} else {
	  die <<EOD;
I don't know what output format you are talking about.  You said you 
wanted $output_format_ format.  I don't know about that.  You either 
misspelled the name, or entered a format I don't support.  I support 
DBM, ODBM, NDBM, SDBM, and GDBM.  If there is a Perl module for that 
format, you can try adding it to the list of output formats in this file.  
EOD
	}
	if ($input_format == $output_format) {
		warn "input format and output format are the same\n";
		# simple copy will suffice
		open IFH, "<$ARGV[0]";
		open OFH, ">$ARGV[1]";
		print OFH $_ foreach <IFH>;
		exit 0;
	}
	@filenames = @ARGV;
	if ($#ARGV != 1) {
		print STDERR "Please specify input AND output file\n";
		help;
	}
}
parse_options;
my $what_input_format;
# We need this because GDBM has incompatible calling conventions.
my $input_call_flags;
my $output_call_flags;

if ($input_format == 1) {
	require DB_File or die "DBM support unavalible\n";
	$what_input_format = "DB_File";
	# UNTESTED
	$input_call_flags = O_RDONLY;
} elsif ($input_format == 2) {
	require ODBM_File or die "ODBM support unavalible\n";
	$what_input_format = "ODBM_File";
	$input_call_flags = O_RDONLY;
} elsif ($input_format == 3) {
	require SDBM_File or die "SDBM support unavalible\n";
	$what_input_format = "SDBM_File";
	$input_call_flags = O_RDONLY;
} elsif ($input_format == 4) {
	require NDBM_File or die "NDBM support unavalible\n";
	$what_input_format = "NDBM_File";
	$input_call_flags = O_RDONLY;
} elsif ($input_format == 5) {
	require GDBM_File or die "GDBM support unavalible\n";
	$what_input_format = "GDBM_File";
	$input_call_flags = \&GDBM_READER;
}
my $what_output_format;
if ($output_format == 1) {
	require DB_File or die "DBM support unavalible\n";
	$what_output_format = "DB_File";
	# UNTESTED
	$output_call_flags = O_WRONLY|O_CREAT;
} elsif ($output_format == 2) {
	require ODBM_File or die "ODBM support unavalible\n";
	$what_output_format = "ODBM_File";
	$output_call_flags = O_WRONLY|O_CREAT;
} elsif ($output_format == 3) {
	require SDBM_File or die "SDBM support unavalible\n";
	$what_output_format = "SDBM_File";
	$output_call_flags = O_WRONLY|O_CREAT;
} elsif ($output_format == 4) {
	require NDBM_File or die "NDBM support unavalible\n";
	$what_output_format = "NDBM_File";
	$output_call_flags = O_WRONLY|O_CREAT;
} elsif ($output_format == 5) {
	require GDBM_File or die "GDBM support unavalible\n";
	$what_output_format = "GDBM_File";
	$output_call_flags = \&GDBM_WRCREAT;
}
my %input_hash;
my %output_hash;
tie %input_hash, $what_input_format, $ARGV[0], $input_call_flags, 0666;
tie %output_hash, $what_output_format, $ARGV[1], $output_call_flags, 0666;
%output_hash = %input_hash;
untie %input_hash;
untie %output_hash;

=head1 NAME

dbconvert - a program for converting between DBM formats

=head1 SYNOPSIS

Usually you call it this way:

/path/to/dbconvert -i WhateverDBM -o WhateverDBM Input Output

The standard GNU B<--help> and B<--version> flags are supported.

=head1 WHY?

On Unix, there are several diffrent DBM formats.  There have also been 
Perl modules made for each of those.  However, all of these formats are 
incompatible!  C<dbconvert> handles the problem.  It will safely copy 
data from one format to another, thanks to Perl's C<tie> facility.  

=head1 PREREQUISITES

This script requires C<strict>.  You will also need one or more of C<DB_File>, 
C<NDBM_File>, C<SDBM_File>, C<ODBM_File>, or C<GDBM_File>.  C<GDBM_File> 
is recommended, because it is the only DBM module (other then Berkley 
DB) that supports arbitary-length data.  It also requires C<Fcntl>.  

=pod README

dbconvert converts DBM databases from one format to another.  

=pod OSNAMES

any

=pod COREQUISITES

DB_File
NDBM_File
SDBM_File
ODBM_File
GDBM_File

=pod SCRIPT CATEGORIES

CPAN : Administrative

=head1 BUGS

Pretty much all of this is untested.  If someone wants to test it, test 
it!  

=cut
