#!/usr/bin/perl
# $Id: inetd2rlinetd.in,v 1.3 2002/01/29 20:13:28 robert Exp $

%services=();
$dir="/etc/rlinetd.d";
$ifile="-";

if ($ARGV[0] eq "-f" ) {
	shift(@ARGV);
	$ifile = shift(@ARGV);
        die "Option \`-f' requires an argument\n" unless ($ifile);
}

$dir = $ARGV[0] if defined $ARGV[0];
die "Directory $dir does not exists\n" unless -d $dir;

open IFILE, $ifile or die "Cannot open $ifile: $!\n";
while (<IFILE>) {
	&add_single_line($_);
}
close IFILE;

&output_services();

exit 0;

sub warn {
	$_ = shift;

	print STDERR $_;
	return 1;
}

sub add_single_line {
	$_ = shift;
	
	chomp;
	return if(/^\s*#/);
	return unless(/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)/);

	my $out		= "";
	my $server	= "";
	my $gid		= "";
	my $rpcvers	= "";
	my $instances	= "";
	my $name	= $1;
	my $proto	= $2;
	my $wait	= $3;
	my $uid		= $4;
	my $exec	= $5;

	&warn("skipping internal service: $name\n") && return 
		if ($exec eq "internal");

	if($proto =~ /^rpc\/(.+)$/) {
		$proto = $1;
		if($name =~ /^(.+)\/(.+)$/) {
			$name = $1;
			$rpcvers = $2;
		}
	}

	&warn("unknown protocol: $proto\n; skipping service $name") && return 
		unless ($proto eq "udp" || $proto eq "tcp");

	if($uid =~ /^(.+)\.(.+)$/) {
		$uid = $1;
		$gid = $2;
	}

	if($exec =~ /^(\S+)\s+(.+)$/) {
		if($1 ne $2) {
			$exec = $2;
			$server = $1;
		}
	}

	if($wait =~ /^wait$/) {
		$instances = 1;
	} elsif($wait =~ /^nowait\.(\d+)$/) {
		$instances = $1;
	}

	$out .= $services{$name} if defined $services{$name};

	$out .= "service \"${name}_${proto}\" {\n";
	$out .= "\tprotocol $proto;\n";
	$out .= "\tport \"$name\";\n";
    	$out .= "\tuser \"$uid\";\n";
    	$out .= "\texec \"$exec\";\n";
	$out .= "\tgroup \"$gid\";\n" if($gid);
	$out .= "\tserver \"$server\";\n" if($server);
	$out .= "\tinstances $instances;\n" if($instances);
	$out .= "\trpc {\n\t\tversion $rpcvers;\n\t}\n" if($rpcvers);
	$out .= "}\n";

	$services{$name} = $out;

}

sub output_services {

	my $tempfile = "$dir/.inetd2rlinetd.$$";
	my $realfile; 

	for my $service (keys %services) {
		open OFILE, ">$tempfile" or die "Cannot open temporary file for writing: $!\n";
		print OFILE "# This file was automatically generated by inetd2rlinetd\n\n";
		print OFILE $services{$service};
		close OFILE;
		
		$realfile = "$dir/$service";
		my $mode= (-e $realfile) ? &ask_user($realfile, $tempfile) : "rename";
		

		if ($mode eq "append") {
			open OFILE, ">>$realfile" or die "Cannot open file $realfile: $!\n";
			print OFILE "\n" . $services{$service};
			close OFILE;
		}
		elsif ($mode eq "rename") {
			rename($tempfile, $realfile) or die "Cannot rename tempfile: $!\n";
		}

		unlink $tempfile;
	}
	

}


sub ask_user {
	my $real_f = shift;
	my $tmp_f  = shift;

	my $mode="";

	while ($mode eq "") {
	
		print STDERR "\n\nFile $real_f already exists\n\n";
		print STDERR "* Show [d]ifference between new version\n";
		print STDERR "* [O]verwrite the file\n";
		print STDERR "* [S]kip the file\n";
		print STDERR "* [A]ppend to the end of the file\n\n";
		print STDERR "Please choose: [D/O/S/A]: ";
		
		do {
			$_=<STDIN>;
			chomp;
			$_= uc $_;
			
			$mode = "rename" 	if ($_ eq "O");
			$mode = "skip"		if ($_ eq "S");
			$mode = "append"	if ($_ eq "A");
			$mode = "diff"		if ($_ eq "D");		
		} until ($mode ne "");

		if ($mode eq "diff") {
			system "diff", "-Nus", "$real_f", "$tmp_f";
			$mode="";
		}
	}
	return $mode;
}


