#!/bin/sh
exec perl -w -x $0 "$@"
#!perl
use strict;
use Getopt::Std;
use FileHandle;
use IPC::Open3;
use IO::Select;
use POSIX;
use POSIX qw(setsid);
my $Bin = "@bindir@";
my $LibExec = "@libexecdir@";
my $init_tool = $LibExec."/ichatserver_init_tool";
my $init_tool_args = "-i";
my $VERSION = "@VERSION@";
my $config_dir = "/private/etc/jabberd";
my $config = $config_dir."/jabberd.cfg";
$config = "internal" unless (-e $config);
my $debug = 0;
my $daemon = 0;
my $select = IO::Select->new();
my ($exe) = ($0 =~ /([^\/]+)$/);
my %jobs;
my %fhs;
my @programs;
my %opts;
getopts("c:Dhb",\%opts);
&usage if exists($opts{h});
if (exists($opts{c}))
{
$config = $opts{c} if (defined($opts{c}) && ($opts{c} ne ""));
&usage() if (!defined($opts{c}) || ($opts{c} eq ""));
}
$debug = 1 if exists($opts{D});
$daemon = 1 if exists($opts{b});
$SIG{HUP} = \&Signal;
$SIG{TERM} = \&Signal;
$SIG{INT} = \&Signal;
$SIG{CHLD} = "IGNORE";
$jobs{jabberd}->{prefix} = "JBRD";
$jobs{router}->{cmd} = "$Bin/router";
$jobs{router}->{config} = "$config_dir/router.xml";
$jobs{router}->{prefix} = "ROUT";
$jobs{resolver}->{cmd} = "$Bin/resolver";
$jobs{resolver}->{config} = "$config_dir/resolver.xml";
$jobs{resolver}->{prefix} = "RSLV";
$jobs{sm}->{cmd} = "$Bin/sm";
$jobs{sm}->{config} = "$config_dir/sm.xml";
$jobs{sm}->{prefix} = "SM";
$jobs{c2s}->{cmd} = "$Bin/c2s";
$jobs{c2s}->{config} = "$config_dir/c2s.xml";
$jobs{c2s}->{prefix} = "C2S";
$jobs{s2s}->{cmd} = "$Bin/s2s";
$jobs{s2s}->{config} = "$config_dir/s2s.xml";
$jobs{s2s}->{prefix} = "S2S";
$jobs{"mu-conference"}->{cmd} = "$LibExec/mu-conference";
$jobs{"mu-conference"}->{config} = "$config_dir/muc-jcr.xml";
$jobs{"mu-conference"}->{prefix} = "MUC";
$jobs{"mu-conference"}->{args} = "";
if ($config eq "internal")
{
$programs[0] = ["router"];
$programs[1] = ["resolver"];
$programs[2] = ["sm"];
$programs[3] = ["c2s"];
$programs[4] = ["s2s"];
$programs[5] = ["mu-conference"];
}
else
{
if (!(-f $config))
{
print "ERROR: config file does not exist: $config\n";
exit(1);
}
open(CFG,$config);
while(<CFG>)
{
next if /^\ next if /^\s*$/;
my ($job,$config) = /^\s*(\S+)\s*(\S*)\s*$/;
my $cmd = $jobs{$job}->{cmd};
push(@programs,[$job,$config,$cmd]);
}
close(CFG);
}
if ($debug)
{
&debug("jabberd","stdout","debug on\n");
&debug("jabberd","stdout","version($VERSION)\n");
&debug("jabberd","stdout","config_dir($config_dir)\n");
}
system("$init_tool $init_tool_args");
if (${
print "ERROR: No jobs to launch.\n";
exit(1);
}
foreach my $job (@programs)
{
&LaunchJob($job->[0],$job->[1],$job->[2]);
}
unless (!$daemon || $debug)
{
defined(my $pid = fork()) || die "Could not fork: $!";
POSIX:_exit(0) if $pid;
setsid or die "Could not start a new POSIX Session: $!";
chdir "/" or die "Could not chdir to /: $!";
umask 0;
open STDIN, "/dev/null" or die "Could not set STDIN to /dev/null: $!";
open STDOUT, "/dev/null" or die "Could not set STDOUT to /dev/null: $!";
open STDERR, "/dev/null" or die "Could not set STDERR to /dev/null: $!";
}
while (1)
{
my @ready = $select->can_read(0);
foreach my $fh (@ready)
{
my $line = <$fh>;
if (defined($line))
{
&debug($fhs{$fh}->{job},$fhs{$fh}->{std},$line);
}
else
{
print "ERROR: $fhs{$fh}->{job} died. Shutting down server.\n";
&Signal("TERM");
}
}
select(undef,undef,undef,.01);
}
sub LaunchJob
{
my $job = shift;
my $config = shift;
my $cmd = shift;
if (!defined($cmd) || $cmd eq "")
{
$cmd = $jobs{$job}->{cmd};
if ($cmd eq "") {
print "cmd is empty, cannot launch\n";
return;
}
}
if (defined($config))
{
$cmd .= " -c ".$config;
}
elsif (defined($jobs{$job}->{config}))
{
$cmd .= " -c ".$jobs{$job}->{config};
}
if ($debug && $jobs{$job}->{prefix} ne "MUC") {
$cmd .= " -D";
}
if (defined($jobs{$job}->{args}) && ($jobs{$job}->{args} ne "")) {
$cmd .= " ".$jobs{$job}->{args};
}
&debug("jabberd","stdout","LaunchJob: $job -> $cmd\n");
&CloseJob($job) if exists($jobs{$job}->{launched});
$jobs{$job}->{stdout} = new FileHandle();
$jobs{$job}->{stderr} = new FileHandle();
$jobs{$job}->{stdout}->autoflush(1);
$jobs{$job}->{stderr}->autoflush(1);
my $stdin = new FileHandle();
$jobs{$job}->{pid} = open3($stdin,
$jobs{$job}->{stdout},
$jobs{$job}->{stderr},
$cmd);
print $stdin "\n";
$stdin->close();
$select->add($jobs{$job}->{stdout});
$select->add($jobs{$job}->{stderr});
$jobs{$job}->{launched} = 1;
$fhs{$jobs{$job}->{stdout}}->{job} = $job;
$fhs{$jobs{$job}->{stdout}}->{std} = "stdout";
$fhs{$jobs{$job}->{stderr}}->{job} = $job;
$fhs{$jobs{$job}->{stderr}}->{std} = "stderr";
}
sub CloseJob
{
my $job = shift;
$select->remove($jobs{$job}->{stdout},
$jobs{$job}->{stderr});
$jobs{$job}->{stdout}->close();
$jobs{$job}->{stderr}->close();
delete($jobs{$job}->{launched});
}
sub Signal
{
my $sig = shift;
&debug("jabberd","stdout","Got a signal... pass it on.\n");
foreach my $job (keys(%jobs))
{
next unless exists($jobs{$job}->{launched});
&debug("jabberd","stdout","sending $sig to $jobs{$job}->{pid} : $job\n");
kill $sig => $jobs{$job}->{pid};
}
if (($sig eq "INT") || ($sig eq "TERM"))
{
&debug("jabberd","stdout","It was a $sig. Shut it all down!\n");
exit(0);
}
}
sub debug
{
return unless $debug;
my $job = shift;
my $std = shift;
my $prefix = $jobs{$job}->{prefix};
$prefix = $job if ! defined($prefix);
printf("%-4s: ",$prefix);
print join("",@_);
}
sub usage
{
print "$exe - jabberd wrapper script ($VERSION)\n";
print "Usage: $exe <options>\n";
print "Options are:\n";
print " -c <file> config file to use [default: $config]\n";
print " -D Show debug output\n";
print " -b Push into background\n";
print " -h Show this help\n";
exit(0);
}