#! /usr/local/bin/perl
# $Id: urlscript,v 1.9 1998/05/10 20:06:13 queinnec Exp $
# This perl script acts as a client of a DMeroon site. It reads a
# local URLscript file (or standard input stream), sends it to the
# site for evaluation and displays the output on its stdout stream.

$default_port = 56423;

$usage = 'Usage: urlscript.prl [hostname[:port]] [file] 
Send an URLscript program to a DMeroon server, exits with the DMeroon
errorcode. Shell variables may appear in the URLscript program and are
substituted before being sent to the DMeroon server.  By default,
hostname is "localhost" and port is ' . $default_port . ' If file is
not mentioned, stdin is accumulated until EOF then sent.
Traditionally, URLscript files do have a .dms extension.  
--- (C) <Christian.Queinnec@lip6.fr> $Revision: 1.9 $.  ';

$text = '';

select(STDOUT);  $| = 1;

# Check if there are two arguments.

if ( @ARGV == 2 ) {
    ($hostport, $file) = @ARGV;
    if ( -f "$file" ) {
        $text = `cat $file`;
    } else {
        die "No such script file: $file\n";
    }
} elsif ( @ARGV == 1 ) {
    ($hostport) = @ARGV;
    $file = $hostport;
    if ( -f "$file" ) {
        $hostport = "localhost:$default_port";
        $text = `cat $file`;
    } else {
        while ( <STDIN> ) {
            $text = $text . $_;
        }
    }
} elsif ( @ARGV == 0 ) {
    $hostport = "localhost:$default_port";
    while ( <STDIN> ) {
        $text = $text . $_;
    }
} else {
    die $usage;
}

# Decode the first argument into an host and a port.

$_ = "$hostport:$default_port";
if ( /^([^:]*)::?(\d+)/ ) {
    $host = $1;
    $port = $2;
} else {
    die "Cannot decode host[:port] \"$hostport\"";
}

# Substitute shell variables. They may be written $name or ${name}.

foreach $variable ( keys %ENV ) {
    my($value) = $ENV{$variable};
    $text =~ s/\$\{$variable\}/$value/sg;
    $text =~ s/\$$variable/$value/sg;
}

# Fetch constants AF_INET, SOCK_STREAM and IPPROTO_TCP.
# First define the usual default, then try to require the system-dependent
# file then set the target variables. 

sub SOCK_STREAM {1;}
sub AF_INET     {2;}
sub IPPROTO_TCP {6;}

require "sys/socket.ph"
    || print STDERR "Cannot find sys/socket.ph, hope defaults are good!";

$sock_stream = &SOCK_STREAM;     # often 1 (2 on Solaris)
$af_inet     = &AF_INET;         # Often 2
$tcp         = &IPPROTO_TCP;     # often 6

$timeout = 15;

# Be sure to kill this client in absence of connection.

sub catch_alarm {
    die "No answer for $timeout seconds.\n";
}
$SIG{'ALRM'} = 'exit';
alarm($timeout);

# Connect to the DMeroon server.

socket(REQUEST, $af_inet, $sock_stream, $tcp)
    || die "Cannot create socket:\n $!";

$sockaddr = 'S n a4 x8';

$thisaddr = ((gethostbyname($host))[4]);

$sck = pack($sockaddr, $af_inet, $port, $thisaddr);

connect(REQUEST, $sck)
    || die "Cannot connect socket:\n $!";

select(REQUEST); $| = 1;

# The script is sent, prefixed by a word imposing the protocol and 
# suffixed with a marker telling its the end.

print REQUEST "URLscript\r\n", $text, "\0\0\r\n";

$return_code = 0;

while ( <REQUEST> ) {
    print STDOUT;
    $return_code = $1 if /<!-- URLscript error *(\d+) *-->/;
}

close(REQUEST)
    || die "Cannot close socket:\n $!";

exit($return_code);

# end of urlscript.prl
