#!/usr/bin/perl -Tw

use Socket;
use Carp;
use POSIX;

use constant REQ_CONNECT	=> 1;
use constant REQ_DISCONNECT	=> 2;
use constant REQ_REDIAL		=> 3;
use constant REQ_FETCHMAIL	=> 4;
use constant REQ_STATUS		=> 5;

use constant RSP_SUCCESS	=> 1;
use constant RSP_FAILURE	=> 2;
use constant RSP_UNKNOWN	=> 3;
use constant RSP_CONNECTED	=> 4;
use constant RSP_NOTCONNECTED	=> 5;
use constant RSP_ALREADYRUNNING	=> 6;
use constant RSP_NOTRUNNING	=> 7;

sub logmsg
{
	open(LOG, ">>ppp_server.log");
	print LOG "$0 $$: @_ at ", scalar localtime, "\n";
	close(LOG);
}

$pid = fork;
exit if $pid;
die "Couldn't fork: $!" unless defined($pid);

POSIX::setsid()
    or die "Can't start a new session: $!";

$time_to_die = 0;

sub signal_handler {
    $time_to_die = 1;
}

$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler;
# trap or ignore $SIG{PIPE}

until ($time_to_die)
{
	my $port = shift || 2345;
	my $proto = getprotobyname('tcp');
	socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
	setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
				or die "setsockopt: $!";
	bind(Server, sockaddr_in($port, INADDR_ANY)) or die "bind: $!";
	listen(Server, SOMAXCONN) or die "listen: $!";

	logmsg "server started on port $port";

	my $paddr;

	$ENV{PATH} = "/bin,/usr/bin,/usr/sbin";

	for ( ; $paddr = accept(Client,Server); close Client)
	{
		my($port, $iaddr) = sockaddr_in($paddr);
		my $name = gethostbyaddr($iaddr, AF_INET);
		$return = undef();

		logmsg "connection from $name [", inet_ntoa($iaddr), "] at port $port";

		chomp($response = <Client>);

		if($response == REQ_CONNECT)
		{
			if(!system("/bin/ps cx | /usr/bin/grep ppp") / 256)
			{
				$return = RSP_ALREADYRUNNING;
				logmsg "REQ_CONNECT request failed (already running)";
			}
			elsif(!system("/usr/sbin/ppp -auto beeb") / 256)
			{
			$return = RSP_SUCCESS;
				logmsg "REQ_CONNECT request succeeded";
			} else {
				$return = RSP_FAILURE;
				logmsg "REQ_CONNECT request failed";
			}
		}
		elsif($response == REQ_DISCONNECT)
		{
			if(!system("/bin/ps cx | /usr/bin/grep ppp") / 256)
			{
				if(!system("/usr/bin/killall ppp") / 256)
				{
					$return = RSP_SUCCESS;
					logmsg "REQ_DISCONNECT request succeeded";
				} else {
					$return = RSP_FAILURE;
					logmsg "REQ_DISCONNECT request failed";
				}
			} else {
				$return = RSP_NOTRUNNING;
				logmsg "REQ_DISCONNECT request failed (not running)";
			}
		}
		elsif($response == REQ_REDIAL)
		{
			if(!system("/bin/ps cx | /usr/bin/grep ppp") / 256)
			{
				if(!system("/usr/bin/killall -INT ppp"))
				{
					$return = RSP_SUCCESS;
					logmsg "REQ_REDIAL request succeeded";
				} else {
					$return = RSP_FAILURE;
					logmsg "REQ_REDIAL request failed";
				}
			} else {
				$return = RSP_NOTRUNNING;
				logmsg "REQ_REDIAL request failed (not running)";
			}
		}
		elsif($response == REQ_FETCHMAIL)
		{
			if(!system("/bin/ps cx | /usr/bin/grep fetchmail") / 256)
			{
				if(!system("/usr/bin/killall -USR1 fetchmail"))
				{
					$return = RSP_SUCCESS;
					logmsg "REQ_FETCHMAIL request succeeded";
				} else {
					$return = RSP_FAILURE;
					logmsg "REQ_FETCHMAIL request failed";
				}
			} else {
				$return = RSP_NOTRUNNING;
				logmsg "REQ_FETCHMAIL request failed (not running)";
			}
		}
		elsif($response == REQ_STATUS)
		{
			if(!system("/bin/ps cx | /usr/bin/grep ppp") / 256)
			{
				$return = RSP_CONNECTED;
				logmsg "REQ_STATUS requested (returned RSP_CONNECTED)";
			} else {
				$return = RSP_NOTCONNECTED;
				logmsg "REQ_STATUS requested (returned RSP_NOTCONNECTED)";
			}
		}

		print Client $return, "\n";
	}
}
