Mercurial > repo
diff interps/clc-intercal/inst/bin/theft-server @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interps/clc-intercal/inst/bin/theft-server Sun Dec 09 19:30:08 2012 +0000 @@ -0,0 +1,221 @@ +#!/usr/bin/perl -w + +eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' + if 0; # not running under some shell + +# INTERNET (INTERcal NETworking) server + +# This file is part of CLC-INTERCAL + +# Copyright (c) 2007-2008 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. See files README and COPYING in the distribution. + +require 5.005; + +use strict; +use Socket; +use Getopt::Long; + +use Language::INTERCAL::Server '1.-94.-2'; + +use vars qw($VERSION $PERVERSION); +($VERSION) = ($PERVERSION = "CLC-INTERCAL/Base bin/theft-server 1.-94.-2") =~ /\s(\S+)$/; + +my ($PERVNUM) = $PERVERSION =~ /\s(\S+)$/; + +if (defined &Getopt::Long::Configure) { + Getopt::Long::Configure qw(no_ignore_case auto_abbrev permute bundling); +} else { + $Getopt::Long::ignorecase = 0; + $Getopt::Long::autoabbrev = 1; + $Getopt::Long::order = $Getopt::Long::PERMUTE; + $Getopt::Long::bundling = 1; +} + +my $port = undef; +my $debug = 0; +my $linger = 600; # time we hang around + +GetOptions( + 'port|p=i' => \$port, + 'debug|d!' => \$debug, + 'linger|l=i' => \$linger, +) or usage(); + +defined $port or die "Must specify --port\n"; + +unless ($debug) { + close STDIN; + close STDOUT; + close STDERR; + my $pid = fork; + defined $pid or die "Cannot fork(): $!\n"; + $pid and exit 0; + if (open(TTY, '<', '/dev/tty')) { + eval { + require 'ioctl.ph'; + my $x; + ioctl(TTY, &TIOCNOTTY, $x); + }; + close TTY; + } + $SIG{HUP} = 'IGNORE'; + $SIG{TSTP} = 'IGNORE'; + $SIG{INT} = 'IGNORE'; +} + +my $server = Language::INTERCAL::Server->new(); +$server->tcp_listen(\&_open, \&_line, \&_close, undef, $port); +$server->udp_listen($port); +$debug and $server->debug; + +$debug and print STDERR time, ": Opened TCP and UDP sockets on port $port\n"; +my $socket_bitmap = ''; +my %pids = (); +my %ports = (); +my %ids = (); + +while ($server->connections || $linger == 0 || time < $server->active + $linger) { + my $timeout = $server->connections || $linger == 0 + ? undef + : ($server->active + $linger); + $server->progress($timeout); +} +$debug and print STDERR time, ": Exiting server\n"; +exit 0; + +sub _open { + my ($id, $sockhost, $peerhost, $close) = @_; + my $local = $peerhost eq '127.0.0.1'; + $ids{$id} = [$local, undef, undef]; + "200 INTERNET on $sockhost (CLC-INTERCAL $PERVNUM)"; +} + +sub _line { + my ($server, $id, $close, $line) = @_; + exists $ids{$id} + or return "598 Internal error: missing ID"; + my ($local, $pid, $port) = @{$ids{$id}}; + $line =~ s/^\s+//; + if ($local && $line =~ /^VICTIM\s+(\d+)\s+ON\s+PORT\s+(\d+)/i) { + my $new_pid = $1; + my $new_port = $2; + if (defined $pid || defined $port) { + return '530 You have already issued a VICTIM command'; + } elsif ($new_pid == 0) { + return '531 That was an invalid PID'; + } elsif (exists $pids{$new_pid}) { + return '532 I already know about that PID'; + } elsif ($new_port > 65535 || $new_port == 0) { + return '533 That was an invalid PORT'; + } elsif (exists $ports{$new_port}) { + return '534 I already know about that PORT'; + } else { + $ids{$id}[1] = $new_pid; + $ids{$id}[2] = $new_port; + $pids{$new_pid} = $new_port; + $ports{$new_port} = $id; + return "230 Welcome $new_pid:$new_port!"; + } + } + if ($line =~ /^CASE\s+PID/i) { + my @pids = map { "$_ ON PORT $pids{$_}" } keys %pids; + my $num = @pids || 'no'; + my $es = @pids == 1 ? '' : 'es'; + return ( + "210 We have $num process$es running", + @pids, + '.', + ); + } + if ($line =~ /^CASE\s+PORT\s+(\d+)/i) { + if (exists $pids{$1}) { + return "220 $pids{$1} is the port you need"; + } else { + return "520 No such PID"; + } + } + if ($line =~ /^THANKS/i) { + $$close = 1; + return '240 You are welcome'; + } + return '590 Command not understood'; +} + +sub _close { + my ($id) = @_; + exists $ids{$id} or return; + my ($local, $pid, $port) = @{$ids{$id}}; + defined $pid and delete $pids{$pid}; + defined $port and delete $ports{$port}; + delete $ids{$id}; +} + +sub usage { + (my $p = $0) =~ s#^.*/##; + die "Usage: $p [--port=PORT] [--debug] [--linger-TIME]\n"; +} + +__END__ + +=pod + +=head1 NAME + +theft-server - CLC-INTERCAL networking + +=head1 SYNOPSIS + +B<theft-server> --port=I<port> [options] + +=head1 DESCRIPTION + +The B<theft-server> mediates the communication between two CLC-INTERCAL +programs with the I<internet> extension. It keeps a list of process IDs +running on the current computer so it can provide lists of processes which +can be engaged in INTERcal NETworking; it also responds to broadcasts +allowing other CLC-INTERCAL programs on the LAN to know there is something +happening on this computer. + +Under normal conditions, the B<theft-server> is started automatically +by a CLC-INTERCAL programs with the I<internet> extension (unless one +is already running, of course!) because the extension cannot operate +without a server on the local computer. However, it is possible to +start one manually, for example from a F</etc/init.d> or F</etc/rc.d>. + +If the program is started automatically, it uses defaults for all its +configuration; when started manually, it accepts the following options: + +=over 4 + +=item B<-p>I<port> / B<--port>=I<port> + +Uses the given I<port> (number or service name) for communications, +instead of using the default one from a configuration file. + +=item B<-l>I<seconds> / B<--linger>=I<seconds> + +Waits the specified time for a connection, then exit. The default is +600 (10 minutes). The timeout applies when the program starts and also +when all existing connections are closed. This allows the program to +be started on demand by CLC-INTERCAL programs, and to automatically +exit when no longer required (unless more programs start up during +the timeout). + +This function is disabled by setting the timeout to 0 (i.e. B<-l>I<0>); +for example, if starting the server from F</etc/init.d> or equivalent +one would disable the timeout. + +=item B<-d> / B<--debug> + +Tells everything it's doing (on Standard Error). Also, prevents the +program from detaching from the current terminal and going into the +background. + +=head1 BUGS + +IPv6 is not yet implemented. +