#!/usr/bin/perl -w

# Create dd/sh distribution

# This file is part of CLC-INTERCAL

# Copyright (c) 2006 Claudio Calvelli, all rights reserved.

# CLC-INTERCAL is copyrighted software. However, permission to use, modify,
# and distribute it is granted provided that the conditions set out in the
# licence agreement are met. The principal points are:

# * No charge can be made for distributing CLC-INTERCAL under any conditions.
#   This condition does not apply to payment of copying/distribution expenses
#   provided that no handling or other charge is added to such expenses.

# * The author cannot accept any liability whatsoever for any damage caused
#   by the software, directly or indirectly. No warranty of any kind can be
#   offered. Using the software in a way which causes any form of damage is
#   expressely prohibited.

# * In addition, the author's details shall not be entered into any mailing
#   list or public directory, without the author's written permission.

# * CLC-INTERCAL can be redistributed only under an identical licence
#   agreement. Any modified or derived work must also be covered by the
#   same identical agreement as the original work.

# See the file "licence.iacc" in the software installation directory (or the
# distribution, if the software has not been installed) for a full licence
# agreement. Please note that, this being an INTERCAL licence agreement, you
# must submit a text file to "licence.iacc", which will agree to it only if
# the text file happened to contain the correct licence agreement. See the
# README file in the distribution for more details.

use strict;

use vars qw($PERVERSION $VERSION);
$PERVERSION = "CLC-INTERCAL Makefile.PL 1.-94.-7";
($VERSION) = $PERVERSION =~ /(\S+)$/;

@ARGV == 3 or die "Usage: makeddshdist FILELIST DISTFILE VERSION\n";
my ($manifest, $distfile, $version) = @ARGV;
$version eq $VERSION or die "Perversion mismatch\n";

open(MANIFEST, $manifest) or die "$manifest: $!\n";
my @files = ();
my $delim = "EOF";
while (<MANIFEST>) {
    chomp;
    my $x = -s $_ or die "$_: $!\n";
    push @files, [$_, $x];
    open (FILE, $_);
    local $/ = undef;
    my $f = <FILE>;
    $delim .= 'X' while $f =~ /$delim/;
    close FILE;
}
close MANIFEST;

my $header = <<EOF;
#!/bin/sh

# THIS DD/SH PROGRAM IS A SELF-UNPACKING ARCHIVE - JUST RUN IT WITH:
#	sh $distfile
# NOTE THAT THE PROGRAM ASSUMES THAT ITS OWN SOURCE CODE IS SEEKABLE: IF
# RUNNING FROM A COMPRESSED DISTRIBUTION UNCOMPRESS FIRST

PERVERSION="CLC-INTERCAL distribution $VERSION"
VERSION=`dd bs=26 skip=1 2>/dev/null <<E
\$PERVERSION
E
`

dd 2>/dev/null <<E
Unpacking CLC-INTERCAL \$VERSION...
E

exec 3<"\$0"
dd of=/dev/null bs=XXXXXXXX count=1 <&3 2>/dev/null

EOF

my %path_made = ();
for my $f (@files) {
    my ($name, $size) = @$f;
    $name = 'CLC-INTERCAL-$VERSION/' . $name;
    my @name = split('/+', $name);
    pop @name;
    my $dir = '';
    while (@name) {
	$dir .= '/' if $dir ne '';
	$dir .= shift @name;
	next if exists $path_made{$dir};
	$header .= "dd 2>/dev/null <<E\n";
	$header .= "$dir/\n";
	$header .= "E\n";
	$header .= "mkdir \"$dir\"\n";
	$path_made{$dir} = 1;
    }
    $header .= "dd 2>/dev/null <<E\n";
    $header .= "$name\n";
    $header .= "E\n";
    $header .= "dd of=\"$name\" bs=$size count=1 <&3 2>&1 | grep -v '[0-9] record'\n";
    $header .= "\n";
}

$header .= "exit 0\n\ndd of=/dev/null 2>/dev/null <<$delim\n";

my $n = length($header);
$n .= ' ' x (8 - length($n));
$header =~ s/XXXXXXXX/$n/;

open(DEST, "> $distfile") or die "$distfile: $!\n";

print DEST $header or die "$distfile: $!\n";

for my $f (@files) {
    my ($name, $size) = @$f;
    open(NAME, $name) or die "$name: $!\n";
    my $b;
    my $sz = 0;
    while (read NAME, $b, 4096) {
	print DEST $b or die "$distfile: $!\n";
	$sz += length($b);
    }
    close NAME;
    $sz == $size or die "$name: size $size -> $sz\n";
}

print DEST "$delim\n" or die "$distfile: $!\n";
close DEST or die "$distfile: $!\n";

