#! /usr/local/bin/perl -w
#
# mimecast - given a stream of MIME separated items, streams them to all
#            incoming connections, making sure each one starts on a whole item
#
# Copyright 2000, 2001 Michael Constant
#

use IO::Socket;
use Fcntl;
use Errno;
use Getopt::Std;
use Tie::RefHash;

$0 =~ s|.*/||;

getopts "hvp:", \%options;
die <<EOF unless ($port = $options{p}) && !$options{h};
usage: $0 -p port [-v]
       -p: specific port to listen on
       -v: verbose mode
EOF

$verbose = 1 if $options{v};

$header = "HTTP/1.0 200 OK\n";
$header .= <> until $header =~ /\n\n/;
$header =~ /boundary=(\S+)/ and $/ = "\n--$1\n"
    or die "can't find MIME boundary; perhaps we need a real MIME parser\n";

$SIG{PIPE} = "IGNORE";

$listen = new IO::Socket::INET Listen => 128, LocalPort => $port;
fcntl $listen, F_SETFL, O_NONBLOCK or die "fcntl: $!\n";

tie %buffer, "Tie::RefHash";

while (<>) {
    $buffer{$client} = $header while $client = $listen->accept;
    die "accept: $!\n" unless $!{EAGAIN};

    for $client (keys %buffer) {
	$buffer{$client} = $_ if $buffer{$client} eq "";

	$written = syswrite $client, $buffer{$client};
	unless (defined $written || $!{EAGAIN}) {
	    warn "dropping client: syswrite: $!\n" if $verbose;
	    delete $buffer{$client};
	    next;
	}

	substr($buffer{$client}, 0, $written) = "" if $written;
    }
}
