Hi..
I'm trying to write a Perl program for networking. It's a sort of dummy-inetd. I removed inetd from my system, because I doesn't really suits my needs. Now, I'm using hoywayd to download my e-mail, and it's fully based on inetd.
So I started writing a wrapper-script in Perl. (also as excercise) This is what I got so far: everything is working, but the program terminates when I close the first connection.
Is there anyone with a little UNIX networking experience able to help me?
I've seen some pieces of code with 'vec' and 'select', but I didn't understand those system calls. The secoond time, the accept() call seams to fail.
Code:
#!/usr/bin/perl -w
$0='hotwayd-server';
my $listen_address = '127.0.0.1';
my $listen_port = '1100';
use strict;
use IO::Socket::INET;
use POSIX qw(:sys_wait_h setsid);
my $INET_EOL = '\015\012';
# -----------------------------------------------
# Start the server socket
my $server = new IO::Socket::INET(
LocalAddr => $listen_address,
LocalPort => $listen_port,
Proto => 'tcp',
Timeout => undef,
Reuse => 1,
Listen => 5,
)
or
die "hotwayd-server: couldn't spawn server: $!\n";
# -----------------------------------------------
# Action to be taken on shutdown:
sub clean_up
{
$server->close() if defined $server;
}
# -----------------------------------------------
# Daemonize
sub daemonize()
{
open(STDIN, '/dev/null') or die "Can't read /dev/null: $!";
open(STDOUT, '>/dev/null') or die "Can't write to /dev/null: $!";
open(STDERR, '>/tmp/hotwayd-server.log') or die "Can't write to /tmp/hotwayd-server.log: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid() or die "Can't start a new session: $!";
}
# -----------------------------------------------
# Create PID file, fork into background.
# Handle shutdown
#$SIG{'INT'} = \&clean_up;
#$SIG{'TERM'} = \&clean_up;
#$SIG{'QUIT'} = \&clean_up;
#$SIG{'__DIE__'} = \&clean_up;
# -----------------------------------------------
# Reading exit status of child processes.
# We need to read the exit status of terminating child processes,
# so the kernel can clean-up this last piece of process-information
# from the process-table. (or the child will remain a zombie until we die)
sub REAPER
{
# Perform a wait for every child.
my $child_pid;
do
{
my $child_pid = waitpid(-1, WNOHANG);
}
while(defined $child_pid && $child_pid > 0);
$SIG{'CHLD'} = \&REAPER; # set again (still loathe sysV)
}
$SIG{'CHLD'} = \&REAPER;
# -----------------------------------------------
# Wait for incoming connections
$server->autoflush(1);
$server->listen();
daemonize();
while(my $socket = $server->accept())
{
# Fork the client
my $child = fork();
if(! defined $child)
{
# Still in parent, unable to fork
print $socket "-ERR unable to open session: $!!$INET_EOL";
$socket->close();
die "hotwayd-server: unable to fork child: $!\n";
}
elsif($child == 0)
{
# Inside child process.
# dup the socket handels to STDIN and STDOUT in child process
local *SOCKET_HANDLE;
*SOCKET_HANDLE = *$socket;
open(STDIN, "<&*SOCKET_HANDLE") or die "hotwayd-server: unable to dup socket to STDIN: $!\n";
open(STDOUT, ">&*SOCKET_HANDLE") or die "hotwayd-server: unable to dup socket to STDOUT: $!\n";
# leave STDERR untouched
# Run the hotwayd program
exec('/opt/hotwayd/sbin/hotwayd');
die "hotwayd-server: unable to exec: $!\n";
# Never goes beyond this line...
}
}
clean_up();