[comp.lang.perl] 'shipit': another toy for the toolbox

merlyn@iwarp.intel.com (Randal Schwartz) (03/27/90)

I needed to send something to another BSD-like Unix site recently, and
it turned out to be larger than the mailer would allow.  Knowing that
they had uudecode and uncompress, and dreading the idea of splitting a
lot of mixed text and binary up into shars (and needing only the
slightest excuse to spend some time hacking yet another Perl tool), I
came up with the 'shipit' utility.

Shipit takes a username and tar spec, and tars those files together,
compresses the resulting archive, splits that compressed image into
sections which when uuencoded will fit into a predefined target
bytesize.  It then prepends a header telling the reciever what to do:
namely, take each mail message, pump it through uudecode, cat the
resulting files collectively through uncompress, feeding *that* into a
tar 'x' to get the original data.  (Maybe I should have called this
program 'rube'? :-)

Anyway, here it is for your enjoyment:

================================================== snip snip
#!/local/merlyn/bin/perl

# usage: shipit user tar-spec...

$msgsize = int((32000-2000)/1.35);
$TMP = "/usr/tmp/shipit.$$";
$| = 1;

$user = shift;

system "tar cf - @ARGV | compress >$TMP";

$totalbytes = (stat($TMP))[7];

open(TMP) || die "Cannot open $TMP ($!)";
unlink($TMP);

$totalmsgs = int(($totalbytes+$msgsize-1)/$msgsize);

$arcid = sprintf("shipit%d",time);

for $msgno (1..$totalmsgs) {
	read(TMP,$bytes,$msgsize);
	unless (fork) { # child: mail
		unless(open(STDIN,"-|")) { #child child: perl processing
			unless(open(STDIN,"-|")) { #child^3: uuencode
				unless(open(STDIN,"-|")) { #child^4: print data
					print $bytes;
					exit 0;
				}
				exec 'uuencode',
					sprintf("%s.tar.Z.%03d",$arcid,$msgno);
				die "Cannot exec uuencode ($!)";
			}
			print <<"HEAD";
This is part $msgno of a $totalmsgs-part shipit(TM :-) archive.
To extract, run each message through uudecode, then enter:
	cat $arcid.tar.Z.* | uncompress | tar xvf -
HEAD
			print while ($_ = <STDIN>);
			exit 0;
		}
		exec '/bin/mail', $user;
		die "Cannot exec mail ($!)";
	}
	wait;
}
close(TMP);
exit 0;
================================================== snip snip

As an example, here's shipit as a shipit archive:

This is part 1 of a 1-part shipit(TM :-) archive.
To extract, run each message through uudecode, then enter:
	cat shipit638496913.tar.Z.* | uncompress | tar xvf -
begin 666 shipit638496913.tar.Z.001
M'YV0<]"D@9.&#H"#"!,J7,BPH<.'$"-*1 BBXHV+( !4E!%CAHV,%4'$H$$#
M9,B3%6%HI&$#1HP;-6S$@%%2Y,R6&F6X</%BYXN 8>24>2$FC9N? @D:G,BT
MJ=.G4*-*G4JUJM6K6+-JW<JUJ]>O8,.*'4NVK-FS:-.J7<NVK=NW<./*G4NW
GKMV[>//JW<NWK]^_@ ,+'DRXL.'#B!,K7LRXL>/'D"-+GDRYLN6#
 
end

Enjoy.

Notice the smiley face in the following sig.  Where does it go? :-)

$_=q(q-q:!print "Just another Perl hacker," :-) ;-7 while$_=eval
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/