#!/usr/bin/perl
# 
# $Revision: 1.2 $
# Copyright 2012 Teleflora.
#
# The script edits the line calling the lpr command in the
# Daisy dodayend.sh, proute.sh, and pdayend.sh scripts.
#

use strict;
use warnings;
use Getopt::Long;
use POSIX;
use File::Basename;

my $CVS_REVISION = '$Revision: 1.2 $';
my $PROGNAME = basename($0);

#
# Command line options
#
my $HELP = 0;
my $VERSION = 0;
my @CONVERT = ();
my @CONVERT_DEF = ("dodayend.sh", "pdayend.sh", "proute.sh");
my $DEBUG = 0;
my $DRY_RUN = 0;

#
# Alternate os and root for testing.
#
my $ALTROOT = "";
my $ALTOS = "";

#
# Global variables.
#
my $TIMESTAMP = "";

#
# Constants.
#

my $LOGFILENAME = "RTI-Patches.log";

# Exit status values
my $EXIT_OK = 0;
my $EXIT_ERROR = -1;
my $EXIT_COMMAND_LINE = 1;
my $EXIT_DAISY_DB_DIRS = 2;
my $EXIT_CONVERTEES = 3;


GetOptions(
	"help" => \$HELP,
	"version" => \$VERSION,
	"debug" => \$DEBUG,
	"dry-run" => \$DRY_RUN,
	"convert:s" => \@CONVERT,
	"altroot:s" => \$ALTROOT,
) || die "Error: invalid command line option, exiting...\n";


# --version
if ($VERSION) {
    print("$PROGNAME $CVS_REVISION\n");
    exit($EXIT_OK);
}

# --help
if ($HELP) {
    print("$PROGNAME $CVS_REVISION\n");
    usage();
    exit($EXIT_OK);
}

#
# The default Daisy database directory and the logfile location
# depend on the alternative root command line option.
#
my $POSDIR = "$ALTROOT/d/daisy";
my $LOGDIR = "$POSDIR/log";
my $LOGFILE = "$LOGDIR/$LOGFILENAME";

unless (-d $POSDIR) {
    print("The default Daisy directory does not exist: $POSDIR\n");
    exit($EXIT_ERROR);
}

unless (-d $LOGDIR) {
    print("The directory for the log file does not exist: $LOGDIR\n");
    exit($EXIT_ERROR);
}


sub main
{
    my $exit_status = 0;
    my @convertee_paths = ();

    loginfo("Begin Daisy LPR Fixup Script $0\[$$\]");

    $exit_status = process_command_line(\@convertee_paths);
    if ($exit_status == 0) {
	lpr_fixup(@convertee_paths);
    }

    loginfo("End Daisy LPR Fixup Script with exit status: $exit_status");

    return($exit_status);
}


#######
#### Functions
#######


sub usage
{
    print("Usage:\n");
    print("$PROGNAME --version\n");
    print("$PROGNAME --help\n");
    print("$PROGNAME --convert=list\n");
    print("$PROGNAME --debug\n");
    print("$PROGNAME --dry-run\n");
    print("\n");
}


#
# Deal with the command line.
#
# Return
#   $daisy_db_dirs - reference to list of daisy deb dirs
#   $convertee_paths - reference to list of file paths to convert
#   0 on success, non-zero on error
#
sub process_command_line
{
    my ($convertee_paths) = @_;

    my @daisy_db_dirs = ();

    # first, prepare a list of one or more daisy db dirs
    if (defined($ARGV[0])) {
	my $arg = $ALTROOT . $ARGV[0];
	if (is_daisy_db_dir($arg)) {
	    push(@daisy_db_dirs, $arg);
	}
	else {
	    showerror("Not a Daisy database dir: $ARGV[0]");
	    return($EXIT_DAISY_DB_DIRS);
	}
    }
    else {
	@daisy_db_dirs = get_daisy_db_dirs();
    }

    unless (@daisy_db_dirs) {
	showerror("Can't find any Daisy database dirs");
	return($EXIT_DAISY_DB_DIRS);
    }

    if ($DEBUG) {
	print "list of daisy db dirs: <@daisy_db_dirs>\n";
    }

    # then, convert a list of files to their paths
    my @convertees = (@CONVERT) ? @CONVERT : @CONVERT_DEF;

    if ($DEBUG) {
	print "list of convertees: <@convertees>\n";
    }

    @{$convertee_paths} = get_convertee_paths(\@daisy_db_dirs, \@convertees);

    if ($DEBUG) {
	print "list of convertee paths: <@{$convertee_paths}>\n";
    }

    unless (@{$convertee_paths}) {
	showerror("No files found to convert");
	return($EXIT_CONVERTEES);
    }

    return(0);
}


sub is_daisy_db_dir
{
    my ($daisy_top_level) = @_;

    my $return_val = 0;

    # must be a directory
    if (-d $daisy_top_level) {

	# skip old daisy dirs
	if ($daisy_top_level !~ /.+-\d{12}$/) {

	    # must contain the magic files
	    if (-e "$daisy_top_level/flordat.tel" && -e "$daisy_top_level/control.dsy") {

		# must be daisy 8.0+
		if (-d "$daisy_top_level/bin") {

		    $return_val = 1;

		}
	    }
	}
    }

    return($return_val);
}


#
# Return a list of verified Daisy database dirs.  Remember, there can be
# more than one daisy database dir!
#
sub get_daisy_db_dirs
{
    my @daisy_db_dirs = ();
    my $daisy_tree_top = $ALTROOT . "/d";

    # test all the files in the daisy top level
    my @daisy_toplevels = glob("$daisy_tree_top/*");

    for my $daisy_toplevel (@daisy_toplevels) {
	if (is_daisy_db_dir($daisy_toplevel)) {
	    push(@daisy_db_dirs, $daisy_toplevel);
	}
    }

    return(@daisy_db_dirs);
}


sub get_convertee_paths
{
    my ($daisy_db_dirs,  $convertees) = @_;

    my @convertee_paths = ();

    foreach my $daisy_db_dir (@{$daisy_db_dirs}) {
	foreach my $convertee (@{$convertees}) {
	    # non-numbered file
	    if (-e "$daisy_db_dir/$convertee") {
		push(@convertee_paths, "$daisy_db_dir/$convertee");
	    }

	    # possible numbered files
	    my ($basename) = $convertee =~ /^(.*)\.[^.]*$/;
	    foreach (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) {
		if (-e "$daisy_db_dir/${basename}${_}.sh") {
		    push(@convertee_paths, "$daisy_db_dir/${basename}${_}.sh");
		}
	    }
	}
    }

    return(@convertee_paths);
}


sub lpr_fixup
{
    my (@convertee_paths) = @_;

    foreach my $convertee (@convertee_paths) {
	if (-e $convertee) {
	    if ($DRY_RUN) {
		print("dry run: converting: $convertee\n");
		next;
	    }
	    open(OLD, "<", $convertee);
	    open(NEW, ">", "$convertee.$$");
	    while (<OLD>) {
		if (/^(\s*)lpr(\s+)-P(\s+)printer(\d+)(\s+)(\S+)(\s*)$/) {
		    my $prefix = $1;
		    my $number = $4;
		    my $file = $6;
		    if ($file ne "ff.txt") {
			$_ = "$prefix" . "unix2dos < $file | lpr -l -P printer" . "$number\n";
		    }
		}
		print NEW;
	    }
	    close(OLD);
	    close(NEW);

	    if (-s "$convertee.$$") {
		system("chmod --reference=$convertee $convertee.$$");
		system("chown --reference=$convertee $convertee.$$");
		system("rm -f $convertee");
		system("mv $convertee.$$ $convertee");
	    }

	    loginfo("converted: $convertee");
	}
    }
}


sub showerror
{
	my $message = $_[0];

	print("$message\n");
	return(logerror($message));
}


#
# Log an info message to the logfile.
#
sub loginfo
{
        my $message = $_[0];
	return(logit("<I>: $message"));
}

#
# Log an error message to the logfile.
#
sub logerror
{
        my $message = $_[0];
	return(logit("<E>: $message"));
}

#
# Log an error to the logfile.
#
sub logit
{
        my $message = $_[0];
        my $timestamp = "";

        chomp ($message);
        $timestamp = strftime("%Y-%m-%d %H:%M:%S", localtime());

        open(LOGFILE, '>>', $LOGFILE);
                print LOGFILE "$timestamp $message\n";
        close LOGFILE;


        return "";
}


exit(main());


__END__

=pod

=head1 NAME

dsy-lpr-fixup.pl - edit lpr lines in daisy scripts


=head1 VERSION

This documenation refers to version 1.1.


=head1 USAGE

dsy-lpr-fixup.pl

dsy-lpr-fixup.pl B<--version>

dsy-lpr-fixup.pl B<--help>

dsy-lpr-fixup.pl B<--convert=list>


=head1 OPTIONS

=over 4

=item B<--version>

Output the version number of the script and exit.

=item B<--help>

Output a short help message and exit.

=item B<--convert=list>

The list of files to convert.
The list may specify one or more comma separated file names.
Allowed names are "dodayend.sh", "pdayend.sh", and "proute.sh".

=back


=head1 DESCRIPTION

This script patches the "lpr" lines in the "dodayend.sh", "pdayend.sh", and
"proute.sh" scripts.
Actually, for each of these three scripts, there can be up to 11 different
instances of the script.
The instances are differenctiated by a number in the filename or the lack thereof.
Thus, each of the scripts may appear as "filename", followed by a single digit or
if only one instance then no digit, followed by the suffix ".sh".
For example, there may be 3 instances of the "dodayend" script with names
"dodayend.sh", "dodayend1.sh", and "dodayend2.sh".
If all three instances exist in a Daisy database dir,
then all three will be patched.
When listing file names to convert with the "--convert" option,
file names with the number suffix should not be specified.

All lpr lines in the file are modified.
The definition of an "lpr line" is one that begins with "lpr"
(possibly with leading white space).
The modfication simply runs the input file through the
"unix2dos" command before handing it off to the "lpr" command.
The printer that the file is being sent to is not changed.
Note, there may be many "lpr lines" in any given file.

So, for example, lines of the form:

    lpr -P printerN file

will be changed to lines like this:

    unix2dos < file | lpr -l -P printerN


=head1 EXAMPLES

=over 4

=item B<$ dsy-lpr-fixup.pl>

This command will convert the three scripts, "dodayend.sh", "pdayend.sh", and
"proute.sh" in all Daisy database dirs found

=item B<$ dsy-lpr-fixup.pl /d/daisy>

This command will convert the three scripts, "dodayend.sh", "pdayend.sh", and
"proute.sh" in just the default Daisy database dir "/d/daisy".

=item B<$ dsy-lpr-fixup.pl --convert=dodayend.sh>

This command will convert only the script "dodayend.sh".

=item B<$ dsy-lpr-fixup.pl --convert=dodayend.sh,pdayend.sh,proute.sh>

This command will convert only the three scripts "dodayend.sh", "pdayend.sh", and
"proute.sh".

=item B<$ dsy-lpr-fixup.pl --convert=dodayend.sh /d/store2>

This command will convert only the script "dodayend.sh" in just the
Daisy database dir "/d/store2".


=head1 FILES

=over 4

=item B<dodayend.sh>

=item B<pdayend.sh>

=item B<proute.sh>

=item B</d/daisy/log/RTI-Patches.log>

The log file that log entries are written to.

=back


=head1 DIAGNOSTICS

=over 4

=item Exit status 0

Successful completion or when the "--version" and "--help"
command line options are specified.

=item Exit status 1

Command line error.

=item Exit status 2

If the specified or implied Daisy database directory does not exist.

=item Exit status 3

If the specified list of files to convert does not exist.

=item Exit status -1

This is a general error including:
(1) the Daisy default directory does not exist.
(2) the directory for the log file location does not exist.

=back


=head1 SEE ALSO

install-daisy.pl

=cut
