#!/afs/athena/contrib/perl/perl
#
# Combine split uuencoded files into a single data stream with
# e-mail garbage removed and pipe into uudecode. The uuencoded
# files must be in the correct order on the command line - in
# particular the first file must contain the "begin" line and
# the last file must contain the "end" line.
#
# WARNING: this code relies on uuencode putting out all lines
# of the form "M[61 ASCII characters]\n" for every line of the
# file except the last few before the "end" line. If you come
# across a uuencoded file that doesn't do this, you'll need to
# modify the code to handle it.
#
# DISCLAIMER: You use this code at your own risk. Also, don't
# take this is as a sterling example of Perl programming. Corrections
# and improvements welcome. You may do whatever you like with this
# code as long as you leave in some reminder of who the original
# culprit^H^H^H^H^H^H^Hauthor was.
#
# Usage: uumerge filename [filename...]
# Requires Perl 3.0 - my copy is at patchlevel 18
#
# Dave Mack csu@alembic.ACS.COM
#
# TODO: modify to allow more than one collection of files on
#	command line.
#
# KNOWN BUGS: 
#
# If some bozo puts a line beginning with "M" in the body of one
# of the intermediate/last chunks, uumerge will assume that uuencoded
# part starts there.
#
# If the last chunk only contains the last two or three lines of
# the uuencoded file (the ones that don't start with "M"), uumerge
# will die.
#
# CHANGES
#
# PATCH 1:
# It appears that some versions of uudecode are too stupid to skip
# past the lines preceding the "begin" line, so feeding a one-part
# uuencoded file to uumerge will bomb.
#
if ($#ARGV < 0 ) {
	print "Usage: uumerge filename [filename...]\n";
	exit 1;
}

$| = 1;
# open a pipe into uudecode
open(DECO,"|uudecode") || die "Can't pipe into uudecode\n";

# if we only have one file, pump it straight into uudecode and die
if ( $#ARGV == 0 ) {
	open(FIRST,"<$ARGV[0]") || die "Can't open $ARGV[0] for input\n";

	while ( <FIRST> ) {
		# skip past everything before the "begin" line
		next unless /^begin [0-9]/;
		last;
	}
	die "$ARGV[0] doesn't contain \"begin\"\n" if eof(FIRST);
	
	print DECO $_; # the begin line

	while ( <FIRST> ) {
		print DECO $_ unless /^end/;
		if ( /^end/ ) {
			print DECO $_;
			last;
		}
		die "$ARGV[0] doesn't contain \"end\"\n" if eof(FIRST);
	}

	# done with file
	close(FIRST);
	exit 0;
}

# process the first file - make sure we have a "begin" line

open(FIRST,"<$ARGV[0]") || die "Can't open $ARGV[0] for input\n";

while ( <FIRST> ) {
	# skip past everything before the "begin" line
	next unless /^begin [0-9]/;
	last;
}
die "First file on command line doesn't contain \"begin\"\n" if eof(FIRST);
	
print DECO $_; # the begin line

# the remaining "real" uuencoded lines in this file should begin with "M"
while ( <FIRST> ) {
	if ( /^M/ ) {
		print DECO $_;
	}
	else {
		last;
	}
}

# done with the first file
close(FIRST);

# do all except the last file
$maxindex = $#ARGV;
$curr = 1;

while ( $curr < $maxindex ) {
	open(CURR,"<$ARGV[$curr]") || die "Can't open $ARGV[$curr]\n";
	# skip the header junk
	while ( <CURR> ) {
		next unless /^$/;
		last;
	}
	# at the body of the message - start looking for /^M/
	while ( <CURR> ) {
		next unless /^M/;
		last;
	}
	die "$ARGV[$curr] isn't a uuencoded file\n" if eof(CURR);
	# OK, we're at the start of the good stuff (probably)
	print DECO $_;
	while ( <CURR> ) {
		if (/^M/) {
			print DECO $_;
		}
		else {
			last;
		}
	}
	# done with current file
	close(CURR);
	$curr++;
}

# time to do the last file in the set
$curr = $maxindex;
open(CURR,"<$ARGV[$curr]") || die "Can't open $ARGV[$curr]\n";
# skip the header junk
while ( <CURR> ) {
	next unless /^$/;
	last;
}
# at the body of the message - start looking for /^M/
while ( <CURR> ) {
	next unless /^M/;
	last;
}
# OK, we're at the start of the good stuff (probably)
print DECO $_;
while ( <CURR> ) {
	print DECO $_ unless /^end/;
	if ( /^end/ ) {
		print DECO $_;
		last;
	}
	die "Last file on command line doesn't contain \"end\"\n" if eof(CURR);
}
# done with final file
close(CURR);
# close the pipe to uudecode and exit
close(DECO);
exit(0);
