#!/usr/bin/perl

use Getopt::Long;
use POSIX ('setsid');

sub usage() {
	print "Parameters are --user <username> --group <groupname>\n";
	print "  --directory <directoryname> --logfile <logfilename>\n";
	print "  [--[no]daemon]\n";
	exit 1;
}

my $user;
my $group;
my $extragroup;
my $directory = '/';
my $daemon = 0;
my $logfile;
my @program_with_arguments;

my $ok = 
  GetOptions ('user=s'      => \$user , 
	      'group=s'     => \$group,
	      'extragroup=s' => \$extragroup,
	      'directory=s' => \$directory,
	      'logfile=s'   => \$logfile,
	      'daemon!'	    => \$daemon);

if (!$ok) { usage(); }

@program_with_arguments = @ARGV;

if (!defined($user)) { usage(); }
if (!defined($group)) { usage(); }


$uid = getpwnam($user);
$gid = getgrnam($group);

if (!defined($uid)) { die "Cannot find userid for $user"; }
if (!defined($gid)) { die "Cannot find groupid for $group"; }

if (defined($extragroup)) {
  $extragid = getgrnam($extragroup);
} else {
  $extragid = $gid;
}
if (!defined($extragid)) { die "Cannot find groupid for $extragroup"; }

print "Going to  uid $uid and gid $gid ($extragid)...\n";
$) = "$gid $extragid";
$> = $uid;
$< = $uid;
$( = "$gid";

print "Effective uid $> and gid $)...\n";
print "Real      uid $< and gid $(...\n";

if ($> != $uid) { die "Couldn't set the effective user id to $uid..."; }
if ($) != $gid) { die "Couldn't set the effective group id to $gid..."; }
if ($< != $uid) { die "Couldn't set the real user id to $uid..."; }
if ($( != $uid) { die "Couldn't set the real group id to $gid..."; }

chdir $directory;

if ($logfile eq '') { $logfile = "/dev/null"; }

if ($daemon) {
	open STDIN,"/dev/null"   or die "Can't read /dev/null: $!";
	open STDOUT,">>$logfile"  or die "Can't write $logfile: $!";
	defined(my $pid = fork)  or die "Can't fork: $!";
	exit if $pid;
	setsid()		 or die "Can't start a new session : $!";
	open STDERR,'>&STDOUT'	 or die "Can't dup stdout: $!";
	$0 = "ipfc-launcher-$ARGV[0]";
}

$|=1;

while (1) {
	system { $ARGV[0] } @ARGV;
	sleep 1;
}
