#!/usr/bin/perl -w
##############################################################################
#
# Print billing management system - configuration script, version 4.1.2
#
# Copyright (C) 2002, 2003 Daniel Franklin
#
# This program is distributed under the terms of the GNU General Public
# License Version 2.
#
# This interactive configuration script generates a printbillrc and printcap
# file based on your preferences and operating system configuration.
#
##############################################################################

use POSIX;
use Printbill::printbill_pcfg;

# Turn on autoflush

$|=1;
umask 022;

$version = "4.1.2";
$date = localtime;
$locale_values = localeconv ();
$sysname = (uname)[0];

# Try to parse any existing printbillrc file - this contains the defaults.
# Anything which is supposed to be in there but which isn't is set here.

%defaults = ();

if (-r "/etc/printbill/printbillrc") {
	%defaults = pcfg ("/etc/printbill/printbillrc");
}

# Those that default to "none" either have no sensible default, or the
# default can be worked out automatically.

$defaults{'colourspace'} = 'mono' if (!defined $defaults{'colourspace'} || $defaults{'colourspace'} eq "unconfigured");
$defaults{'price_per_percent_black'} = 'none' if (!defined $defaults{'price_per_percent_black'} || $defaults{'price_per_percent_black'} eq "unconfigured");
$defaults{'price_per_percent_colour'} = 'none' if (!defined $defaults{'price_per_percent_colour'} || $defaults{'price_per_percent_colour'} eq "unconfigured");
$defaults{'price_per_page'} = 'none' if (!defined $defaults{'price_per_page'} || $defaults{'price_per_page'} eq "unconfigured");
$defaults{'response_method'} = 'none' if (!defined $defaults{'response_method'} || $defaults{'response_method'} eq "unconfigured");
$defaults{'estimated_total_percent_black'} = 'none' if (!defined $defaults{'estimated_total_percent_black'} || $defaults{'estimated_total_percent_black'} eq "unconfigured");
$defaults{'estimated_total_percent_colour'} = 'none' if (!defined $defaults{'estimated_total_percent_colour'} || $defaults{'estimated_total_percent_colour'} eq "unconfigured");
$defaults{'prog_path'} = 'none' if (!defined $defaults{'prog_path'} || $defaults{'prog_path'} eq "unconfigured");
$defaults{'admin_prog_path'} = 'none' if (!defined $defaults{'admin_prog_path'} || $defaults{'admin_prog_path'} eq "unconfigured");
$defaults{'dpi'} = '100' if (!defined $defaults{'dpi'} || $defaults{'dpi'} eq "unconfigured");
$defaults{'gs'} = 'none' if (!defined $defaults{'gs'} || $defaults{'gs'} eq "unconfigured");
$defaults{'lpr'} = 'none' if (!defined $defaults{'lpr'} || $defaults{'lpr'} eq "unconfigured");
$defaults{'gnuplot'} = 'none' if (!defined $defaults{'gnuplot'} || $defaults{'gnuplot'} eq "unconfigured");
$defaults{'smbclient'} = 'none' if (!defined $defaults{'smbclient'} || $defaults{'smbclient'} eq "unconfigured");
$defaults{'printbilld_user'} = 'none' if (!defined $defaults{'printbilld_user'} || $defaults{'printbilld_user'} eq "unconfigured");
$defaults{'printbilld_group'} = 'none' if (!defined $defaults{'printbilld_group'} || $defaults{'printbilld_group'} eq "unconfigured");
$defaults{'web_user'} = 'none' if (!defined $defaults{'web_user'} || $defaults{'web_user'} eq "unconfigured");
$defaults{'mta'} = '/usr/sbin/sendmail' if (!defined $defaults{'mta'} || $defaults{'mta'} eq "unconfigured");
$defaults{'admin_mail'} = 'root@localhost' if (!defined $defaults{'admin_mail'} || $defaults{'admin_mail'} eq "unconfigured");
$defaults{'retry_interval'} = '1' if (!defined $defaults{'retry_interval'} || $defaults{'retry_interval'} eq "unconfigured");
$defaults{'printcap'} = '/etc/printcap' if (!defined $defaults{'printcap'} || $defaults{'printcap'} eq "unconfigured");
$defaults{'verbosity'} = 'HIGH' if (!defined $defaults{'verbosity'} || $defaults{'verbosity'} eq "unconfigured");
$defaults{'currency_symbol'} = $locale_values -> {'currency_symbol'} if (!defined $defaults{'currency_symbol'} || $defaults{'currency_symbol'} eq "unconfigured");
$defaults{'bill_max_processes'} = '5' if (!defined $defaults{'bill_max_processes'} || $defaults{'bill_max_processes'} eq "unconfigured");
$defaults{'nice'} = 'none' if (!defined $defaults{'nice'} || $defaults{'nice'} eq "unconfigured");
$defaults{'bill_nicethreshold'} = '1000000' if (!defined $defaults{'bill_nicethreshold'} || $defaults{'bill_nicethreshold'} eq "unconfigured");
$defaults{'small_bill_niceness'} = '0' if (!defined $defaults{'small_bill_niceness'} || $defaults{'small_bill_niceness'} eq "unconfigured");
$defaults{'large_bill_niceness'} = '10' if (!defined $defaults{'large_bill_niceness'} || $defaults{'large_bill_niceness'} eq "unconfigured");
$defaults{'quote_generation_niceness'} = '19' if (!defined $defaults{'quote_generation_niceness'} || $defaults{'quote_generation_niceness'} eq "unconfigured");
$defaults{'admin_cgi'} = '/cgi-bin/webpqadmin.pl' if (!defined $defaults{'admin_cgi'} || $defaults{'admin_cgi'} eq "unconfigured");
$defaults{'check_cgi'} = '/cgi-bin/webpqcheck.pl' if (!defined $defaults{'check_cgi'} || $defaults{'check_cgi'} eq "unconfigured");
$defaults{'web_header'} = '/etc/printbill/web_header' if (!defined $defaults{'web_header'} || $defaults{'web_header'} eq "unconfigured");
$defaults{'web_footer'} = '/etc/printbill/web_footer' if (!defined $defaults{'web_footer'} || $defaults{'web_footer'} eq "unconfigured");
$defaults{'web_message_text'} = '/etc/printbill/web_message_text' if (!defined $defaults{'web_message_text'} || $defaults{'web_message_text'} eq "unconfigured");
$defaults{'extra_quota_message'} = '/etc/printbill/extra_quota_message' if (!defined $defaults{'extra_quota_message'} || $defaults{'extra_quota_message'} eq "unconfigured");
$defaults{'admin_form_type'} = 'LONG' if (!defined $defaults{'admin_form_type'} || $defaults{'admin_form_type'} eq "unconfigured");
$defaults{'graph_png_output_dir'} = '/var/www/printbill' if (!defined $defaults{'graph_png_output_dir'} || $defaults{'graph_png_output_dir'} eq "unconfigured");
$defaults{'png_url'} = '/printbill' if (!defined $defaults{'png_url'} || $defaults{'png_url'} eq "unconfigured");

if ($sysname eq "FreeBSD") {
	$defaults{'db_home'} = '/var/db/printbill' if (!defined $defaults{'db_home'} || $defaults{'db_home'} eq "unconfigured");
} else {
	$defaults{'db_home'} = '/var/lib/printbill' if (!defined $defaults{'db_home'} || $defaults{'db_home'} eq "unconfigured");
}

if (!defined $defaults{'filter'} || $defaults{'filter'} eq "unconfigured") {
	if (-x '/etc/magicfilter/psonly600-filter') {
		$defaults{'filter'} = '/etc/magicfilter/psonly600-filter';
	} elsif (-x '/usr/local/libexec/magicfilter/psonly600-filter') {
		$defaults{'filter'} = '/usr/local/libexec/magicfilter/psonly600-filter';
	} else {
		$defaults{'filter'} = 'none';
	}
}

# Fallback in case the user has no explicit locale

if (!defined $defaults{'currency_symbol'}) {
	$defaults{'currency_symbol'} = '$';
}

# tests whether a given number is real (e.g. 0, -123, 123.321, .123, 123.)

sub isreal {
	my ($arg) = shift;
	return ($arg =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/);
}

print "\n\nConfiguring printbill\n=====================\n\n";

print "$0\n\nis an interactive program for configuring printbill. It will not over-write
any existing settings, rather at the end it will generate two files -
printcap.new and printbillrc.new - which you may then install as
/etc/printcap and /etc/printbill/printbillrc. Please note that before
running this program you should have already set up /etc/printcap and be
able to print. Also note: files are written at the end, you may ctrl-c at
any time to abort.\n";

# Find the binaries

$params{'lpr'} = `which lpr`;

if ($? >> 8) {
	print 'Can\'t find "lpr". Enter the full path: ';
	$params{'lpr'} = <STDIN>;
} else {
	chomp $params{'lpr'};
}

# We don't care about gnuplot. If the user wants it he/she can install it later
$params{'gnuplot'} = `which gnuplot`;

if ($? >> 8) {
	print "\nCan't find gnuplot - stats plotting won't work (install gnuplot and re-run 
$0 if desired)\n";
	delete $params{'gnuplot'};
} else {
	chomp $params{'gnuplot'};
}

$params{'nice'} = `which nice`;

if ($? >> 8) {
	print 'Can\'t find "nice". Enter the full path: ';
	$params{'nice'} = <STDIN>;
} else {
	chomp $params{'nice'};
}

$params{'gs'} = `which gs`;

if ($? >> 8) {
	print 'Can\'t find "gs". Enter the full path: ';
	$params{'gs'} = <STDIN>;
} else {
	chomp $params{'gs'};
}

$params{'smbclient'} = `which smbclient`;

if ($? >> 8) {
	$params{'smbclient'} = 'none';
} else {
	chomp $params{'smbclient'};
}

# Figure out UID of print daemon. By default, we will make this the same for
# printbilld.

if ($sysname eq "Linux") {
	$params{'printbilld_user'} = `ps h -C lpd -o user,cmd | cut -f 1 -d ' ' | grep --invert-match root | head -1`;
} elsif ($sysname eq "FreeBSD") {
	$params{'printbilld_user'} = `ps -c -a -x -o user,command | grep lpd | cut -f 1 -d ' ' | grep --invert-match root | head -1`;
}

if ($? >> 8) {
	print 'lpd doesn\'t appear to be running.';
	$params{'printbilld_user'} = '';
} else {
	chomp $params{'printbilld_user'};
}

while ($params{'printbilld_user'} eq '') {
	print "\nWhat username do you want to run printbilld under? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	$id = getpwnam ($tmp);
	
	if (!defined $id) {
		print "Invalid username. Try again...\n";
	} else {
		$params{'printbilld_user'} = $tmp;
	}
}

while (!defined $params{'printbilld_group'}) {
	if ($defaults{'printbilld_group'} ne "none") {
		print "\nWhat group do you want to run printbilld under? [$defaults{'printbilld_group'}] ";
	} else {
		print "\nWhat group do you want to run printbilld under? ";
	}
	
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($defaults{'printbilld_group'} ne "none" && $tmp eq "") {
		$params{'printbilld_group'} = $defaults{'printbilld_group'};
	} else {
		$id = getgrnam ($tmp);
	
		if (!defined $id) {
			print "Invalid groupname. Try again...\n";
		} else {
			$params{'printbilld_group'} = $tmp;
		}
	}
}

# Now we configure everything that couldn't be figured out automatically...

print "\nConfiguring miscellaneous settings\n==================================\n\n";

print "Path for printbill databases [$defaults{'db_home'}]: ";
$params{'db_home'} = <STDIN>;
chomp $params{'db_home'};
	
if ($params{'db_home'} eq '') {
	$params{'db_home'} = $defaults{'db_home'};
}

$defaults{'cookieroot'} = "$defaults{'db_home'}/cookies" if (!defined $defaults{'cookieroot'} || $defaults{'cookieroot'} eq "unconfigured");
$defaults{'stats_path'} = "$defaults{'db_home'}/stats" if (!defined $defaults{'stats_path'} || $defaults{'stats_path'} eq "unconfigured");

$params{'dpi'} = '';

while ($params{'dpi'} eq '') {
	print "\nResolution (dpi) used for billing calculation? [$defaults{'dpi'}] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'dpi'} = $defaults{'dpi'};
	} elsif (isdigit ($tmp) && $tmp > 0) {
		$params{'dpi'} = $tmp;
		
		if ($params{'dpi'} > 600) {
			print "\n\nWarning! $params{'dpi'} dpi is a *very* high resolution (much higher than necessary). 
The DPI setting is only used to estimate the percentage coverage, not for 
actual printing, so a lower value (say 100) is fine (and much, much faster :-)\n\n";
		}
	} else {
		print "That's not a valid positive integer. Try again.\n";
	}
}

# See where we installed pqm - since this script should be run post-inst

$params{'admin_prog_path'} = `dirname \`which printbilld\``;
$params{'prog_path'} = `dirname \`which pqcheck\``;

chomp $params{'admin_prog_path'};
chomp $params{'prog_path'};

$params{'filter'} = '';

while ($params{'filter'} eq '') {
	print "\nOptional anything-to-postscript print filter? [$defaults{'filter'}] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'filter'} = $defaults{'filter'};
	} elsif (! -x $tmp) {
		print "Can't find \"$tmp\"\n";
	} else {
		$params{'filter'} = $tmp;
	}
}

$params{'mta'} = '';

while ($params{'mta'} eq '') {
	print "\nMail transport agent? [$defaults{'mta'}] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		if (-x $defaults{'mta'}) {
			$params{'mta'} = $defaults{'mta'};
		} else {
			print "Can't find $defaults{'mta'} - default is not usable.\n";
		}
	} elsif (! -x $tmp) {
		print "Can't find \"$tmp\"\n";
	} else {
		$params{'mta'} = $tmp;
	}
}

$params{'admin_mail'} = '';

print "\nAdministrator e-mail address? [$defaults{'admin_mail'}] ";
$tmp = <STDIN>;
chomp $tmp;
	
if ($tmp eq '') {
	$params{'admin_mail'} = $defaults{'admin_mail'};
} else {
	$params{'admin_mail'} = $tmp;
}

$params{'printcap'} = '';

while ($params{'printcap'} eq '') {
	print "\nLocation of printcap file? [$defaults{'printcap'}] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		if (-r $defaults{'printcap'}) {
			$params{'printcap'} = $defaults{'printcap'};
		} else {
			print "Can\'t find $defaults{'printcap'} - default is not usable\n";
		}
	} elsif (! -r $tmp) {
		print "Can't find \"$tmp\"\n";
	} else {
		$params{'printcap'} = $tmp;
	}
}

$params{'currency_symbol'} = '';

while ($params{'currency_symbol'} eq '') {
	print "\nLocal currency symbol [$defaults{'currency_symbol'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp ne '') {
		$params{'currency_symbol'} = $tmp;
	} else {
		$params{'currency_symbol'} = $defaults{'currency_symbol'};
	}
}

$params{'verbosity'} = '';

if ($defaults{'verbosity'} eq "HIGH") {
	$default = "h";
} else {
	$default = "l";
}

while ($params{'verbosity'} eq '') {
	print "\nHigh or low syslog verbosity? (h/l) [$default] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq "h" || ($tmp eq '' && $default eq "h")) {
		$params{'verbosity'} = "HIGH";
	} elsif ($tmp eq "l" || ($tmp eq '' && $default eq "l")) {
		$params{'verbosity'} = "LOW";
	} else {
		print "Come on... all I want is a little high (h) or low (l)!\n";
	}
}

$do_stats = 'y';

while ($do_stats eq '') {
	print "\nCollect statistics? (y/n) [$default] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq "y" || ($tmp eq '' && $default eq "y")) {
		$do_stats = "TRUE";
	} elsif ($tmp eq "n" || ($tmp eq '' && $default eq "n")) {
		$do_stats = "FALSE";
	} else {
		print "Come on... all I want is a little yes (y) or no (n)!\n";
	}
}

if ($do_stats eq 'TRUE') {
	$params{'stats_path'} = '';

	while ($params{'stats_path'} eq '') {
		print "\nPath for statistics output ? [$defaults{'stats_path'}] ";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq '') {
			$params{'stats_path'} = $defaults{'stats_path'};
		} elsif (! -d $tmp) {
			print "Can't find directory \"$tmp\"\n";
		} else {
			$params{'stats_path'} = $tmp;
		}
	}
}

print "\nSetting up defaults\n===================\n\n";

print "The following parameters are used unless over-ridden by subsequent
printer-specific options. If you have only one printer (or only one kind of
printer), this is the only time you need to set this up.\n";

$params{'colourspace'} = '';

if ($defaults{'colourspace'} eq "mono") {
	$default = "m";
} elsif ($defaults{'colourspace'} eq "cmyk" || $defaults{'colourspace'} eq "colour") {
	$default = "k";
} elsif ($defaults{'colourspace'} eq "cmy") {
	$default = "c";
} elsif ($defaults{'colourspace'} eq "pagecount") {
	$default = "p";
}

while ($params{'colourspace'} eq '') {
	print "\nMono, CMYK colour (4-colour), CMY colour (3-colour), or pagecount-only billing? (m|k|c|p) [$default] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq "k" || ($tmp eq '' && $default eq "k")) {
		$params{'colourspace'} = "cmyk";
	} elsif ($tmp eq "c" || ($tmp eq '' && $default eq "c")) {
		$params{'colourspace'} = "cmy";
	} elsif ($tmp eq "m" || ($tmp eq '' && $default eq "m")) {
		$params{'colourspace'} = "mono";
	} elsif ($tmp eq "p" || ($tmp eq '' && $default eq "p")) {
		$params{'colourspace'} = "pagecount";
	} else {
		print "Type m, k, c or p, how hard can it be?!?! Try again.\n";
	}
}

if ($params{'colourspace'} ne "cmy" && $params{'colourspace'} ne "pagecount") {
	$black_cartridge_cost = '';

	while ($black_cartridge_cost eq '') {
		print "\nReplacement black cartridge cost? $params{'currency_symbol'}";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq '') {
			print "No default value for this parameter.\n";
		} elsif (&isreal ($tmp)) {
			$black_cartridge_cost = $tmp;
		} else {
			print "That's not a valid floating point number. Try again.\n";
		}
	}

	$black_cartridge_pages = '';

	while ($black_cartridge_pages eq '') {
		print "\nEstimated page count for new black cartridge? ";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq '') {
			print "No default value for this parameter.\n";
		} elsif (isdigit ($tmp) && $tmp > 0) {
			$black_cartridge_pages = $tmp;
		} else {
			print "That's not a valid positive integer. Try again.\n";
		}
	}

	$black_cartridge_page_coverage = '';

	while ($black_cartridge_page_coverage eq '') {
		print "\nQuoted % coverage per page for new black cartridge? [5] ";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq '') {
			$black_cartridge_page_coverage = 5;
		} elsif (isreal ($tmp) && $tmp > 0) {
			$black_cartridge_page_coverage = $tmp;
		} else {
			print "That's not a valid positive integer. Try again.\n";
		}
	}

	$params{'estimated_total_percent_black'} = $black_cartridge_page_coverage * $black_cartridge_pages;
	$params{'price_per_percent_black'} = $black_cartridge_cost / $params{'estimated_total_percent_black'};
}

if ($params{'colourspace'} eq "colour" || $params{'colourspace'} eq "cmyk" || $params{'colourspace'} eq "cmy") {
	$colour_cartridge_cost = '';

	while ($colour_cartridge_cost eq '') {
		print "\nReplacement colour cartridge cost? $params{'currency_symbol'}";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq '') {
			print "No default value for this parameter.\n";
		} elsif (&isreal ($tmp)) {
			$colour_cartridge_cost = $tmp;
		} else {
			print "That's not a valid floating point number. Try again.\n";
		}
	}

	$colour_cartridge_pages = '';

	while ($colour_cartridge_pages eq '') {
		print "\nEstimated page count for new colour cartridge? ";
		$tmp = <STDIN>;
		chomp $tmp;
		
		if ($tmp eq '') {
			print "No default value for this parameter.\n";
		} elsif (isdigit ($tmp) && $tmp > 0) {
			$colour_cartridge_pages = $tmp;
		} else {
			print "That's not a valid positive integer. Try again.\n";
		}
	}

	$colour_cartridge_page_coverage = '';

	while ($colour_cartridge_page_coverage eq '') {
		print "\nQuoted % coverage per page for new colour cartridge? [5] ";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq '') {
			$colour_cartridge_page_coverage = 5;
		} elsif (isreal ($tmp) && $tmp > 0) {
			$colour_cartridge_page_coverage = $tmp;
		} else {
			print "That's not a valid positive integer. Try again.\n";
		}
	}

	$params{'estimated_total_percent_colour'} = $colour_cartridge_page_coverage * $colour_cartridge_pages;
	$params{'price_per_percent_colour'} = $colour_cartridge_cost / $params{'estimated_total_percent_colour'};
}

$params{'price_per_page'} = '';

while ($params{'price_per_page'} eq '') {
	print "\nPer-page paper cost? $params{'currency_symbol'}";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		print "No default value for this parameter.\n";
	} elsif (&isreal ($tmp)) {
		$params{'price_per_page'} = $tmp;
	} else {
		print "That's not a valid floating point number. Try again.\n";
	}
}

# Modify an existing entry in /etc/printcap for use with printbill?
# - Do they use the defaults? If not, prompt for specifics

print "\nPrinter configuration\n=====================\n\n";

print "This is the most important part of the configuration process. Here you add
printers to /etc/printcap for use with printbill, or modify existing entries
to that effect.\n";

$printcap_text = `/bin/cat $params{'printcap'}`;

if (! -x "$params{'admin_prog_path'}/printbill") {
	die "$0: where is the printbill script? Not here, where it should be: \"$params{'admin_prog_path'}/printbill\"\n";
}

if (! -x "$params{'admin_prog_path'}/printbilld") {
	die "$0: where is the printbilld daemon? Not here, where it should be: \"$params{'admin_prog_path'}/printbilld\"\n";
}

if (! -x "$params{'admin_prog_path'}/printbill_printer") {
	die "$0: where is the printbill_printer script? Not here, where it should be: \"$params{'admin_prog_path'}/printbill_printer\"\n";
}

$printcap_text =~ s/#.*//g;
$printcap_text =~ s/\n+\s*:\s*/:/g;
$printcap_text =~ s/\n+//;
$printcap_text =~ s/\n+/\n/g;
$printcap_text =~ s/:\\*:/:/g;
$printcap_text =~ s/:\n/\n/g;

@printers = split ("\n", $printcap_text);

%pparamhash = ();

foreach $printer (@printers) {
	@pparams = split (":", $printer);
	$printername = $pparams [0];

# We only care about printers not currently using printbill...
	
	if ($printer !~ /.*printbill.*/) {
		foreach $pparam (@pparams) {
			@line = split ("=", $pparam);

			if ($#line == 1) {
				$var = $line [0];
				$val = $line [1];
				$pparamhash{$printername}{$var} = $val;
			}	
		}
	}
}

# pparamhash should now contain all of the essential information in the
# printcap file.

foreach $key (sort keys (%pparamhash)) {
	$printername = $key;
	$printername =~ s/\|.*//;

	$valid = 0;

	while (! $valid) {
		print "\nHow do you want to use printbill with \"$printername\"?\n([N]ot at all | [b]ill | [l]azybill | [a]ccount only) ";

		$yesno = <STDIN>;
		chomp $yesno;
	
		if ($yesno eq "a" || $yesno eq "b" || $yesno eq "l") {
			$valid = 1;
			$valid2 = 0;
			$filtertype = $yesno;
			
			while (! $valid2) {
				print "\nDo you want to use the default printer parameters? (y/n) ";
				$yesno = <STDIN>;
				chomp $yesno;
				
				if ($yesno eq "y") {
					$valid2 = 1;
				} elsif ($yesno eq "n") {
					$valid2 = 1;


					$printers{$printername}{'colourspace'} = '';
					
					if ($defaults{'colourspace'} eq "mono") {
						$default = "m";
					} elsif ($defaults{'colourspace'} eq "cmyk" || $defaults{'colourspace'} eq "colour") {
						$default = "k";
					} elsif ($defaults{'colourspace'} eq "cmy") {
						$default = "c";
					} elsif ($defaults{'colourspace'} eq "pagecount") {
						$default = "p";
					}

					while ($printers{$printername}{'colourspace'} eq '') {
						print "\nMono, CMYK colour (4-colour), CMY colour (3-colour), or pagecount-only billing? (m|k|c|p) [$default] ";

						$tmp = <STDIN>;
						chomp $tmp;
	
						if ($tmp eq "k" || ($tmp eq '' && $default eq "k")) {
							$printers{$printername}{'colourspace'} = "cmyk";
						} elsif ($tmp eq "c" || ($tmp eq '' && $default eq "c")) {
							$printers{$printername}{'colourspace'} = "cmy";
						} elsif ($tmp eq "m" || ($tmp eq '' && $default eq "m")) {
							$printers{$printername}{'colourspace'} = "mono";
						} elsif ($tmp eq "p" || ($tmp eq '' && $default eq "p")) {
							$printers{$printername}{'colourspace'} = "pagecount";
						} else {
							print "Type m, k, c or p, how hard can it be?!?! Try again.\n";
						}
					}
					
					if ($printers{$printername}{'colourspace'} ne "cmy" && $printers{$printername}{'colourspace'} ne "pagecount") {
						$black_cartridge_cost = '';
						
						while ($black_cartridge_cost eq '') {
							print "\nReplacement black cartridge cost? $params{'currency_symbol'}";
							$tmp = <STDIN>;
							chomp $tmp;
						
							if ($tmp eq '') {
								print "No default value for this parameter.\n";
							} elsif (&isreal ($tmp)) {
								$black_cartridge_cost = $tmp;
							} else {
								print "That's not a valid floating point number. Try again.\n";
							}
						}
					
						$black_cartridge_pages = '';
					
						while ($black_cartridge_pages eq '') {
							print "\nEstimated page count for new black cartridge? ";
							$tmp = <STDIN>;
							chomp $tmp;
						
							if ($tmp eq '') {
								print "No default value for this parameter.\n";
							} elsif (isdigit ($tmp) && $tmp > 0) {
								$black_cartridge_pages = $tmp;
							} else {
								print "That's not a valid positive integer. Try again.\n";
							}
						}
					
						$black_cartridge_page_coverage = '';
					
						while ($black_cartridge_page_coverage eq '') {
							print "\nQuoted % coverage per page for new black cartridge? [5] ";
							$tmp = <STDIN>;
							chomp $tmp;
						
							if ($tmp eq '') {
								$black_cartridge_page_coverage = 5;
							} elsif (isreal ($tmp) && $tmp > 0) {
								$black_cartridge_page_coverage = $tmp;
							} else {
								print "That's not a valid positive integer. Try again.\n";
							}
						}
						
						$printers{$printername}{'estimated_total_percent_black'} = $black_cartridge_page_coverage * $black_cartridge_pages;
						$printers{$printername}{'price_per_percent_black'} = $black_cartridge_cost / $printers{$printername}{'estimated_total_percent_black'};
					}
					
					if ($printers{$printername}{'colourspace'} eq "colour" || $printers{$printername}{'colourspace'} eq "cmyk" || $printers{$printername}{'colourspace'} eq "cmy") {
						$colour_cartridge_cost = '';
					
						while ($colour_cartridge_cost eq '') {
							print "\nReplacement colour cartridge cost? $params{'currency_symbol'}";
							$tmp = <STDIN>;
							chomp $tmp;
						
							if ($tmp eq '') {
								print "No default value for this parameter.\n";
							} elsif (&isreal ($tmp)) {
								$colour_cartridge_cost = $tmp;
							} else {
								print "That's not a valid floating point number. Try again.\n";
							}
						}
					
						$colour_cartridge_pages = '';
					
						while ($colour_cartridge_pages eq '') {
							print "\nEstimated page count for new colour cartridge? ";
							$tmp = <STDIN>;
							chomp $tmp;
							
							if ($tmp eq '') {
								print "No default value for this parameter.\n";
							} elsif (isdigit ($tmp) && $tmp > 0) {
								$colour_cartridge_pages = $tmp;
							} else {
								print "That's not a valid positive integer. Try again.\n";
							}
						}
					
						$colour_cartridge_page_coverage = '';
					
						while ($colour_cartridge_page_coverage eq '') {
							print "\nQuoted % coverage per page for new colour cartridge? [5] ";
							$tmp = <STDIN>;
							chomp $tmp;
						
							if ($tmp eq '') {
								$colour_cartridge_page_coverage = 5;
							} elsif (isreal ($tmp) && $tmp > 0) {
								$colour_cartridge_page_coverage = $tmp;
							} else {
								print "That's not a valid positive integer. Try again.\n";
							}
						}
					
						$printers{$printername}{'estimated_total_percent_colour'} = $colour_cartridge_page_coverage * $colour_cartridge_pages;
						$printers{$printername}{'price_per_percent_colour'} = $colour_cartridge_cost / $printers{$printername}{'estimated_total_percent_colour'};
					}
					
					$printers{$printername}{'price_per_page'} = '';
					
					while ($printers{$printername}{'price_per_page'} eq '') {
						print "\nPer-page paper cost? $params{'currency_symbol'}";
						$tmp = <STDIN>;
						chomp $tmp;
						
						if ($tmp eq '') {
							print "No default value for this parameter.\n";
						} elsif (&isreal ($tmp)) {
							$printers{$printername}{'price_per_page'} = $tmp;
						} else {
							print "That's not a valid floating point number. Try again.\n";
						}
					}
				}				
			}

# Construct the new printer entry and/or modify the old one

			if ($filtertype eq "b") {
				$newprintername = $printername . "_real|Real print queue for $printername (don't print to this)";
				%{$newpparamhash{$newprintername}} = %{$pparamhash{$key}};
				$newpparamhash{$newprintername}{'achk'} = "true";
				$newpparamhash{$newprintername}{'as'} = "|$params{admin_prog_path}/printbill_printer";
				$newpparamhash{$newprintername}{'sd'} .= "_real";

				$shortnewprintername = $printername . "_real";
				$pparamhash{$key}{'achk'} = "true";
				$pparamhash{$key}{'as'} = "|$params{admin_prog_path}/printbill --type bill --printbill_secondary $shortnewprintername";
				$pparamhash{$key}{'lp'} = "/dev/null";
				delete $pparamhash{$key}{'if'};
				delete $pparamhash{$key}{'of'};
			} elsif ($filtertype eq "a") {
				$pparamhash{$key}{'achk'} = "true";
				$pparamhash{$key}{'as'} = "|$params{admin_prog_path}/printbill --type account";
			} elsif ($filtertype eq "l") {
				$pparamhash{$key}{'achk'} = "true";
				$pparamhash{$key}{'as'} = "|$params{admin_prog_path}/printbill --type lazybill";
			}
		} elsif ($yesno eq "n") {
			$valid = 1;
			print "OK... ignoring\n";
		}
	}
}

if (!scalar (%pparamhash)) {
	print "\nNo unconfigured printers found in /etc/printcap...\n";
}

$want_web_interface = '';

while ($want_web_interface eq '') {
	print "\nDo you want to use the web management interface? (y/n) [y] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq "y" || $tmp eq '') {
		$want_web_interface = "y";
	} elsif ($tmp eq "n") {
		$want_web_interface = "n";
	} else {
		print "Come on... all I want is a little yes or no!\n";
	}
}

if ($want_web_interface eq "y") {
	print "\nWeb interface parameters\n========================\n\n";
	
	$params{'admin_form_type'} = '';

	if ($defaults{'admin_form_type'} eq "LONG") {
		$default = "l";
	} else {
		$default = "s";
	}

	while ($params{'admin_form_type'} eq '') {
		print "Short or long administrative form? (l/s) [$default] ";
		$tmp = <STDIN>;
		chomp $tmp;
	
		if ($tmp eq "l" || ($tmp eq '' && $default eq "l")) {
			$params{'admin_form_type'} = "LONG";
		} elsif ($tmp eq "s" || ($tmp eq '' && $default eq "s")) {
			$params{'admin_form_type'} = "SHORT";
		} else {
			print "Come on... all I want is a little LONG (l) or SHORT (s)!\n";
		}
	}

	if ($do_stats) {
		print "Enter the absolute filesystem path for storage of PNG images [$defaults{'graph_png_output_dir'}] ";
		$params{'graph_png_output_dir'} = <STDIN>;
		chomp $params{'graph_png_output_dir'};
		
		if ($params{'graph_png_output_dir'} eq "") {
			$params{'graph_png_output_dir'} = $defaults{'graph_png_output_dir'}
		}
		
		print "Enter the document-root-relative path for PNG images [$defaults{'png_url'}]: ";
		$params{'png_url'} = <STDIN>;
		chomp $params{'png_url'};

		if ($params{'png_url'} eq "") {
			$params{'png_url'} = $defaults{'png_url'}
		}
	}

# Figure out the UID of web server. It could be either apache or httpd.

	if ($sysname eq "Linux") {
		$params{'web_user'} = `ps h -C apache,httpd -o user,cmd | cut -f 1 -d ' ' | grep --invert-match root | head -1`;
	} elsif ($sysname eq "FreeBSD") {
		$params{'web_user'} = `ps -c -a -x -o user,command | grep \'httpd\\\|apache\' | cut -f 1 -d ' ' | grep --invert-match root | head -1`;
	}

	if ($? >> 8) {
		print 'Apache doesn\'t appear to be running.';
		$params{'web_user'} = '';
	} else {
		chomp $params{'web_user'};
	}

	while ($params{'web_user'} eq '') {
		print "\nWhat username does apache normally run as? ";
		$tmp = <STDIN>;
		chomp $tmp;
	
		`id $tmp &> /dev/null`;
	
		if ($? >> 8) {
			print "Invalid username. Try again...\n";
		} else {
			$params{'web_user'} = $tmp;
		}
	}

	$params{'admin_cgi'} = "/cgi-bin/webpqadmin.pl";
	$params{'check_cgi'} = "/cgi-bin/webpqcheck.pl";
	$params{'cookieroot'} = "$params{'db_home'}/cookies";
	$params{'web_header'} = "/etc/printbill/web_header";
	$params{'web_footer'} = "/etc/printbill/web_footer";
	$params{'web_message_text'} =  "/etc/printbill/web_message_text";
	$params{'extra_quota_message'} = "/etc/printbill/extra_quota_message";
}

print "\nProcessing parameters\n=====================\n\n";

print "These are the various parameters which control job processing. In general,
the defaults should work - where in doubt, consult the man page printibillrc
(5) which fully documents the function of each parameter.\n";

$params{'bill_max_processes'} = 0;

while ($params{'bill_max_processes'} == 0) {
	print "\nMax number of concurrent processes (suggested > 1 to prevent hogging) [$defaults{'bill_max_processes'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'bill_max_processes'} = $defaults{'bill_max_processes'};
	} elsif (isdigit ($tmp) && $tmp > 0) {
		$params{'bill_max_processes'} = $tmp;
	} else {
		print "That's not a valid positive integer. Try again.\n";
	}
}

$params{'bill_nicethreshold'} = -1;

while ($params{'bill_nicethreshold'} == -1) {
	print "\nNice threshold (jobs > threshold bytes are niced more) [$defaults{'bill_nicethreshold'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'bill_nicethreshold'} = $defaults{'bill_nicethreshold'};
	} elsif (isdigit ($tmp) && $tmp >= 0) {
		$params{'bill_nicethreshold'} = $tmp;
	} else {
		print "That's not a valid threshold. Try again.\n";
	}
}

$params{'small_bill_niceness'} = -1;

while ($params{'small_bill_niceness'} == -1) {
	print "\nNiceness for small jobs (defined via the threshold) [$defaults{'small_bill_niceness'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'small_bill_niceness'} = $defaults{'small_bill_niceness'};
	} elsif (isdigit ($tmp) && $tmp >= 0 && $tmp <= 19) {
		$params{'small_bill_niceness'} = $tmp;
	} else {
		print "That's not a valid niceness. Try again.\n";
	}
}

$params{'large_bill_niceness'} = -1;

while ($params{'large_bill_niceness'} == -1) {
	print "\nNiceness for large jobs (defined via the threshold) [$defaults{'large_bill_niceness'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'large_bill_niceness'} = $defaults{'large_bill_niceness'};
	} elsif (isdigit ($tmp) && $tmp >= 0 && $tmp <= 19) {
		$params{'large_bill_niceness'} = $tmp;
	} else {
		print "That's not a valid niceness. Try again.\n";
	}
}

$params{'quote_generation_niceness'} = -1;

while ($params{'quote_generation_niceness'} == -1) {
	print "\nNiceness for quote processes [$defaults{'quote_generation_niceness'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'quote_generation_niceness'} = $defaults{'quote_generation_niceness'};
	} elsif (isdigit ($tmp) && $tmp >= 0 && $tmp <= 19) {
		$params{'quote_generation_niceness'} = $tmp;
	} else {
		print "That's not a valid niceness. Try again.\n";
	}
}

$params{'retry_interval'} = 0;

while ($params{'retry_interval'} == 0) {
	print "\nRetry interval in seconds [$defaults{'retry_interval'}]? ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq '') {
		$params{'retry_interval'} = $defaults{'retry_interval'};
	} elsif (isdigit ($tmp) && $tmp > 0) {
		$params{'retry_interval'} = $tmp;
	} else {
		print "That's not a valid positive integer. Try again.\n";
	}
}

print "\nResponse methods\n================\n\n";

print "These are the various alternative user-notification methods available. When
a user requests a quote via printquote, they can receive their quote in a
variety of ways.\n";

$want_mail_response = '';

if ($defaults{'response_method'} =~ "mail") {
	$default = "y";
} else {
	$default = "n";
}

while ($want_mail_response eq '') {
	print "\nE-mail response? (y/n) [$default] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq "y" || ($tmp eq '' && $default eq "y")) {
		$want_mail_response = "y";
	} elsif ($tmp eq "n" || ($tmp eq '' && $default eq "n")) {
		$want_mail_response = "n";
	} else {
		print "Come on... all I want is a little yes or no!\n";
	}
}

$want_smbclient_response = '';

if ($defaults{'response_method'} =~ "smbclient" && $params{'smbclient'} ne '') {
	$default = "y";
} else {
	$default = "n";
}

while ($want_smbclient_response eq '' && $params{'smbclient'} ne '') {
	print "\nSmbclient (winpopup message) response? (y/n) [$default] ";
	$tmp = <STDIN>;
	chomp $tmp;
	
	if ($tmp eq "n" || ($tmp eq '' && $default eq "n")) {
		$want_smbclient_response = "n";
	} elsif ($tmp eq "y" || ($tmp eq '' && $default eq "y")) {
		$want_smbclient_response = "y";
	} else {
		print "Come on... all I want is a little yes (y) or no (n)!\n";
	}
}

if ($want_mail_response eq "y") {
	$params{'response_method'} = "mail";
}

if ($want_smbclient_response eq "y") {
	if ($want_mail_response eq "y") {
		$params{'response_method'} .= ", smbclient";
	} else {
		$params{'response_method'} = "smbclient";
	}
}

if ($want_mail_response eq "n" && $want_smbclient_response eq "n") {
	$params{'response_method'} = "none";
}

open PRINTCAP, ">printcap.new";

print PRINTCAP "# Printcap created by $0 version $version [$date]\n\n";

foreach $key (sort keys %pparamhash) {
	$entry = "$key:\\\n";
	
	foreach $ekey (sort keys %{$pparamhash{$key}}) {
		$entry .= "\t:$ekey=$pparamhash{$key}{$ekey}:\\\n";
	}
	
	chop $entry;
	chop $entry;
	
	print PRINTCAP "$entry\n\n";
}

foreach $key (sort keys %newpparamhash) {
	print PRINTCAP "# Added by $0\n";
	$entry = "$key:\\\n";
	
	foreach $ekey (sort keys %{$newpparamhash{$key}}) {
		$entry .= "\t:$ekey=$newpparamhash{$key}{$ekey}:\\\n";
	}
	
	chop $entry;
	chop $entry;
	
	print PRINTCAP "$entry\n\n";
}

close PRINTCAP;

tie %confighash, "Printbill::PTDB_File", "printbillrc.new", "FALSE" or
	die "$0: cannot create database file: $!\n";
	
%confighash = %params;
	
untie %confighash;

if (scalar (%printers)) {
	if (! -d "printers") {
		mkdir "printers", 0755 or
			die "$0: cannot create \"printers\" directory: $!\n";
	}

	foreach $key (sort keys %printers) {
		tie %pcfghash, "Printbill::PTDB_File", "printers/$key", "FALSE" or
			die "$0: cannot create database file: $!\n";
	
		%pcfghash = %{$printers{$key}};
	
		untie %pcfghash;
	}
}

print "\nConfiguration complete\n======================\n";
print "New printcap written to printcap.new\n";
print "New printbillrc written to printbillrc.new\n";
print "New printer configuration files written out in printers/*\n\n" if (scalar %printers);
