#!/usr/local/bin/perl
#	enhanced version of BSD "install" command

$ENV{'PATH'} = '/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/bsd:/usr/local/etc:/usr/etc:/etc';
$ENV{'SHELL'} = '/bin/sh';
$ENV{'IFS'} = '';
$TRUE  = 1;
$FALSE = 0;
$thispgm = $0;
$thispgm =~ s/.*\///g;
$my_hostname = `hostname`;
chop ($my_hostname);
$do_remove = $do_copy = $do_strip = $do_chown = $do_chgrp = $do_chmod = $do_ls = $be_verbose = $FALSE;

#	parse command line
while ($#ARGV >= 0) {
	if ($ARGV[0] !~ /^-/) {
		last;
		}
	elsif ($ARGV[0] eq "-c") {
		$do_copy = $TRUE;
		}
	elsif ($ARGV[0] eq "-g") {
		if ($#ARGV == 0) {
			$errors++;
			printf stderr "%s:  group id missing\n", $thispgm;
			}
		else	{
			shift;
			$new_group = $ARGV[0];
			$do_chgrp = $TRUE;
			}
		}
	elsif ($ARGV[0] eq "-l") {
		$do_ls = $TRUE;
		}
	elsif ($ARGV[0] eq "-m") {
		if ($#ARGV == 0) {
			$errors++;
			printf stderr "%s:  file mode missing\n", $thispgm;
			}
		else	{
			shift;
			$new_mode = $ARGV[0];
			$do_chmod = $TRUE;
			}
		}
	elsif ($ARGV[0] eq "-o") {
		if ($#ARGV == 0) {
			$errors++;
			printf stderr "%s:  owner id missing\n", $thispgm;
			}
		else	{
			shift;
			$new_owner = $ARGV[0];
			$do_chown = $TRUE;
			}
		}
	elsif ($ARGV[0] eq "-r") {
		$do_remove = $TRUE;
		}
	elsif ($ARGV[0] eq "-s") {
		$do_strip = $TRUE;
		}
	elsif ($ARGV[0] eq "-v") {
		$be_verbose = $TRUE;
		}
	else	{
		$errors++;
		printf stderr "%s:  unrecognized command line option \"%s\"\n", $thispgm, $ARGV[0];
		}
	shift;
	}

#	parse source file
if ($#ARGV >= 0) {
	$source = $ARGV[0];
	if (! -e $source) {
		$errors++;
		printf stderr "%s:  source file %s doesn't exist\n", $thispgm, $source;
		}
	elsif (! -f $source) {
		$errors++;
		printf stderr "%s:  source file %s is not a regular file\n", $thispgm, $source;
		}
	shift;
	}
else	{
	$errors++;
	printf stderr "%s:  missing source file name\n", $thispgm;
	}

@target = ();
while ($#ARGV >= 0) {
	$target = $ARGV[0];
	@t = split (/:/, $ARGV[0]);
	if ($#t == 0) {
		$target = $t[0];
		if (-d $target) {
			$target =~ s/\/$//g;
			$target .= "/" . $source;
			}
		push (@target, $target);
		}
	else	{
		@h = split (/\+/, $t[0]);
		for ($ctr = 0; $ctr <= $#h; $ctr++) {
			if ($h[$ctr] eq $my_hostname) {
				$target = $t[1];
				}
			else	{
				$target = $h[$ctr] . ":" . $t[1];
				}
			if (-d $target) {
				$target =~ s/\/$//g;
				$target .= "/" . $source;
				}
			push (@target, $target);
			}
		}
	shift;
	}
if ($#target == -1) {
	$errors++;
	printf stderr "%s:  missing target file/directory name(s)\n", $thispgm;
	}

if ($errors > 0) {
	printf stderr "\nusage:  %s [-c] [-g group] [-l[ls-opts]] [-m mode] [-o owner] [-r] [-s]\n", $thispgm;
	printf stderr "                [-v] source [host[+host]:]target [target ...]\n\n";
	printf stderr "\t-c  = specifies source is to be copied to target, not moved (don't delete source)\n";
	printf stderr "\t-g  = change target to specified group\n";
	printf stderr "\t-l  = do an \"ll\" on the target after installation,\n";
	printf stderr "\t-m  = change target to specified mode\n";
	printf stderr "\t-o  = change target to specified owner\n";
	printf stderr "\t-r  = remove old target, if any\n";
	printf stderr "\t-s  = strip symbols from target (executables only!)\n";
	printf stderr "\t-v  = be verbose and print all commands before you do them\n";
	exit (1);
	}

#	process each target
for ($ctr = 0; $ctr <= $#target; $ctr++ ) {
	@t = split (/:/, $target[$ctr]);
	if ($#t == 1) {
		do remote_install ($t[0], $t[1]);
		}
	else	{
		do local_install ($t[0]);
		}
	}

if (! $do_copy) {
	do local_command ("rm", "-f", $source);
	}

exit (0);

sub local_install {
	$target = $_[0];

	if ($do_remove) {
		do local_command ("rm", "-f", $target);
		}

	do local_command ("cp", $source, $target);

	if ($do_strip) {
		do local_command ("strip", $target);
		}

	if ($do_chown) {
		do local_command ("chown", $new_owner, $target);
		}

	if ($do_chgrp) {
		do local_command ("chgrp", $new_group, $target);
		}

	if ($do_chmod) {
		do local_command ("chmod", $new_mode, $target);
		}

	if ($do_ls) {
		do local_command ("ll", $target);
		}
	}

sub remote_install {
	$host = $_[0];
	$target = $_[1];

	if ($do_remove) {
		do remote_command ($host, "rm", "-f", $target);
		}

	do local_command ("rcp", $source, $host . ":" . $target);

	if ($do_strip) {
		do remote_command ($host, "strip", $target);
		}

	if ($do_chown) {
		do remote_command ($host, "chown", $new_owner, $target);
		}

	if ($do_chgrp) {
		do remote_command ($host, "chgrp", $new_group, $target);
		}

	if ($do_chmod) {
		do remote_command ($host, "chmod", $new_mode, $target);
		}

	if ($do_ls) {
		do remote_command ($host, "ll", $target);
		}
	}

sub local_command {
	$cmd = join (" ", @_);
	if ($be_verbose) {
		printf stderr "\t%s\n", $cmd;
		}
	$tstat = (system $cmd) >> 8;
	if ($tstat != 0) {
		printf stderr "%s:  command \"%s\" failed (returned status %d)\n", $thispgm, $cmd, $tstat;
		exit (1);
		}
	}

sub remote_command {
	$rmthost = shift (@_);
	$rmtcmd = join (" ", @_);
	if ($be_verbose) {
		printf stderr "\trsh %s -n %s\n", $rmthost, $rmtcmd;
		}
	system "rsh", $rmthost, "-n", $rmtcmd;
	}
