[alt.sources] [comp.sys.sgi] BSD 'install', in perl

kai@uicsrd.csrd.uiuc.edu (03/20/90)

Original-posting-by: kai@uicsrd.csrd.uiuc.edu
Original-subject: Re: Make problems
Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)

[This is an experimental alt.sources re-posting from the newsgroup(s)
comp.sys.sgi. Comments on this service to emv@math.lsa.umich.edu 
(Edward Vielmetti).]



In article <9003051914.AA28827@blumiris.chem.umr.edu>,
bobf@BLUMIRIS.CHEM.UMR.EDU ("Robert B. Funchess") writes:
> I finally figured out what was causing the Make problems ...
> Unless of course I need the BSD-flavor install.
>	< Bob | bobf | Funchess >

I wrote a Perl script to have the BSD flavor install on our System V machines.
We have a mixture of machines, and I didn't want to have two different
Makefiles or targets to install every program.  Enjoy!

Patrick Wolfe	(pwolfe@kai.com, kailand!pwolfe)
System Programmer/Operations Manager, Kuck and Associates, Champaign IL


----  cut here  ----  cut here  ----  cut here  ----  cut here  ----
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Readme install.1 install.pl Makefile ll
# Wrapped by pwolfe@kailand on Sun Mar 18 19:37:50 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Readme' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Readme'\"
else
echo shar: Extracting \"'Readme'\" \(2047 characters\)
sed "s/^X//" >'Readme' <<'END_OF_FILE'
XThis "install" program is a perl script.  You need Larry Wall's perl v3 to run
Xit.  You can get the latest version of perl via anonymous FTP from
Xjpl-devvax.jpl.nasa.gov (128.149.8.43).  I highly recommend it.
X
XI wrote "install" because even though our System V hosts have an "install"
Xcommand, it has completely different options.  I wanted just one version of
XMakefiles for all of our machines and since I was familiar with the bsd version
Xof "install", I wrote a script to emulate it.  It also works equally as well on
Xour System V and BSD 4.[23] machines, and supports every option BSD does.
X
XI've also added a couple of options and features.
X
XThe two additional command line options are "-r" to remove the target before
Xinstalling the new one, and "-l" to do an "ll" after the installation is
Xcomplete.  These are two changes to Makefiles I found myself making
Xconstantly.
X
XThe "-l" option of install requires that you have a "ll" command on every
Xsystem.  On BSD systems that didn't come with an "ll" command, I installed the
Xenclosed two line "ll" Bourne shell script in "/bin".  On our System V hosts, I
Xinstalled the same script, but edited out the -g option (so the output looks
Xthe same).
X
XI also added the ability to install files on multiple hosts with one command.
XYou do this by specifying the target as "hostlist:target", where the "hostlist"
Xis a list of hosts, separated with a plus sign.  "rsh" and "rcp" commands are
Xused to perform the remote operations, but since rsh doesn't return the remote
Xcommand's status, you can't really be sure each remote command is working
Xokay.
X
XIn my Makefiles, I define the variable "HOST" to be a list of hosts or their
Xnicknames that I want the files installed.  This works well because I can
Xoverride the default hostlist by specifying an overriding "HOST=someotherhost"
Xon the "make" command line when I want to.  See the "Makefile" in this
Xdirectory for an example.
X
X        Patrick Wolfe   (pat@kai.com, kailand!pat)
X        System Programmer/Operations Manager, Kuck & Associates, Inc.
X
END_OF_FILE
if test 2047 -ne `wc -c <'Readme'`; then
    echo shar: \"'Readme'\" unpacked with wrong size!
fi
# end of 'Readme'
fi
if test -f 'install.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'install.1'\"
else
echo shar: Extracting \"'install.1'\" \(2849 characters\)
sed "s/^X//" >'install.1' <<'END_OF_FILE'
X...
X.TH INSTALL 1 "1.1" "KAI" "KAI local software"
X
X.SH NAME
Xinstall \- install a program or file 
X
X.SH SYNOPSIS
X.B install
X[\-c] [\-g group] [\-l[ls-options]]
X[\-m mode] [\-o owner] [\-r] [\-s]
Xsource-file [host[+host...]:]target [target ...]
X
X.SH DESCRIPTION
X.I Install
Xperforms operations that are commonly done when installing a program
Xor other file in some system directory.
X
XYou must specify one source file, and at least one target file or
Xdirectory name.  If the target specified is a directory, a file
Xby the same name as the source file will be installed inside in that
Xdirectory.
X
XYou may optionally specify as targets, multiple files, remote files (in the
Xformat host:file), multiple remote files (in the format host+host:file), or a
Xmixture of any of these.  This finally makes installing a file on multiple
Xsystems very easy.
X
XThe options you specify control what is done to the source and target files.
XWith no options, the source file is simply moved to the target file.
X
X.I Install
Xwill stop if any errors occur,
Xbut when executing commands using the remote shell command (rsh),
Xno status code is returned from the remote command, so install
Xcannot tell if the remote command was successful, and will always
Xcontinue as if it was.
X
X.SH OPTIONS
X\-c indicates that the source file is to be copied, not moved, to the
Xtarget file.  In other words, the source file should not be deleted after
Xthe installation is completed.
X
X\-g specifies the group name or number that should be assigned to the target file(s).
XYou must be the superuser, or the owner of the file and a member of the
Xgroup to change the group assigned to a file.
X
X\-l indicates that an "ls" should be performed on the target file
Xafter the installation is done.  This is useful for verifying that the
Xinstallation worked correctly.  You may optionally specify the options to
Xpass to the "ls" command.  The default options used are "\-Fgl".
X
X\-m specifies the mode that should be assigned to the target file(s).
XYou must be the superuser, or the owner of the file
Xto change the mode assigned to a file.
X
X\-o specifies the login name or number that should own the target file(s).
XOn BSD systems, only the superuser can change the owner of a file.  On
XSystem V systems, only the superuser or the owner of a file can change
Xit's owner.
X
X\-r indicates that any old target file should be removed before the new
Xfile is installed.  This is useful for preventing problems caused by
Xownership, group, or permissions of an old version of the target file.
X
X\-s indicates that the target file should be stripped of symbols.  Only
Xuse this option on executable images.
X
X\-v indicates that the install program should be verbose, and display every
Xcommand before it is executed.
X
X.SH ORIGIN
XInstall is a Perl script, written by Patrick Wolfe,
XSystem Manager at Kuck & Associates, Inc.
END_OF_FILE
if test 2849 -ne `wc -c <'install.1'`; then
    echo shar: \"'install.1'\" unpacked with wrong size!
fi
# end of 'install.1'
fi
if test -f 'install.pl' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'install.pl'\"
else
echo shar: Extracting \"'install.pl'\" \(5122 characters\)
sed "s/^X//" >'install.pl' <<'END_OF_FILE'
X#!/usr/local/bin/perl
X#	enhanced version of BSD "install" command
X
X$ENV{'PATH'} = '/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/bsd:/usr/local/etc:/usr/etc:/etc';
X$ENV{'SHELL'} = '/bin/sh';
X$ENV{'IFS'} = '';
X$TRUE  = 1;
X$FALSE = 0;
X$thispgm = $0;
X$thispgm =~ s/.*\///g;
X$my_hostname = `hostname`;
Xchop ($my_hostname);
X$do_remove = $do_copy = $do_strip = $do_chown = $do_chgrp = $do_chmod = $do_ls = $be_verbose = $FALSE;
X
X#	parse command line
Xwhile ($#ARGV >= 0) {
X	if ($ARGV[0] !~ /^-/) {
X		last;
X		}
X	elsif ($ARGV[0] eq "-c") {
X		$do_copy = $TRUE;
X		}
X	elsif ($ARGV[0] eq "-g") {
X		if ($#ARGV == 0) {
X			$errors++;
X			printf stderr "%s:  group id missing\n", $thispgm;
X			}
X		else	{
X			shift;
X			$new_group = $ARGV[0];
X			$do_chgrp = $TRUE;
X			}
X		}
X	elsif ($ARGV[0] eq "-l") {
X		$do_ls = $TRUE;
X		}
X	elsif ($ARGV[0] eq "-m") {
X		if ($#ARGV == 0) {
X			$errors++;
X			printf stderr "%s:  file mode missing\n", $thispgm;
X			}
X		else	{
X			shift;
X			$new_mode = $ARGV[0];
X			$do_chmod = $TRUE;
X			}
X		}
X	elsif ($ARGV[0] eq "-o") {
X		if ($#ARGV == 0) {
X			$errors++;
X			printf stderr "%s:  owner id missing\n", $thispgm;
X			}
X		else	{
X			shift;
X			$new_owner = $ARGV[0];
X			$do_chown = $TRUE;
X			}
X		}
X	elsif ($ARGV[0] eq "-r") {
X		$do_remove = $TRUE;
X		}
X	elsif ($ARGV[0] eq "-s") {
X		$do_strip = $TRUE;
X		}
X	elsif ($ARGV[0] eq "-v") {
X		$be_verbose = $TRUE;
X		}
X	else	{
X		$errors++;
X		printf stderr "%s:  unrecognized command line option \"%s\"\n", $thispgm, $ARGV[0];
X		}
X	shift;
X	}
X
X#	parse source file
Xif ($#ARGV >= 0) {
X	$source = $ARGV[0];
X	if (! -e $source) {
X		$errors++;
X		printf stderr "%s:  source file %s doesn't exist\n", $thispgm, $source;
X		}
X	elsif (! -f $source) {
X		$errors++;
X		printf stderr "%s:  source file %s is not a regular file\n", $thispgm, $source;
X		}
X	shift;
X	}
Xelse	{
X	$errors++;
X	printf stderr "%s:  missing source file name\n", $thispgm;
X	}
X
X@target = ();
Xwhile ($#ARGV >= 0) {
X	$target = $ARGV[0];
X	@t = split (/:/, $ARGV[0]);
X	if ($#t == 0) {
X		$target = $t[0];
X		if (-d $target) {
X			$target =~ s/\/$//g;
X			$target .= "/" . $source;
X			}
X		push (@target, $target);
X		}
X	else	{
X		@h = split (/\+/, $t[0]);
X		for ($ctr = 0; $ctr <= $#h; $ctr++) {
X			if ($h[$ctr] eq $my_hostname) {
X				$target = $t[1];
X				}
X			else	{
X				$target = $h[$ctr] . ":" . $t[1];
X				}
X			if (-d $target) {
X				$target =~ s/\/$//g;
X				$target .= "/" . $source;
X				}
X			push (@target, $target);
X			}
X		}
X	shift;
X	}
Xif ($#target == -1) {
X	$errors++;
X	printf stderr "%s:  missing target file/directory name(s)\n", $thispgm;
X	}
X
Xif ($errors > 0) {
X	printf stderr "\nusage:  %s [-c] [-g group] [-l[ls-opts]] [-m mode] [-o owner] [-r] [-s]\n", $thispgm;
X	printf stderr "                [-v] source [host[+host]:]target [target ...]\n\n";
X	printf stderr "\t-c  = specifies source is to be copied to target, not moved (don't delete source)\n";
X	printf stderr "\t-g  = change target to specified group\n";
X	printf stderr "\t-l  = do an \"ll\" on the target after installation,\n";
X	printf stderr "\t-m  = change target to specified mode\n";
X	printf stderr "\t-o  = change target to specified owner\n";
X	printf stderr "\t-r  = remove old target, if any\n";
X	printf stderr "\t-s  = strip symbols from target (executables only!)\n";
X	printf stderr "\t-v  = be verbose and print all commands before you do them\n";
X	exit (1);
X	}
X
X#	process each target
Xfor ($ctr = 0; $ctr <= $#target; $ctr++ ) {
X	@t = split (/:/, $target[$ctr]);
X	if ($#t == 1) {
X		do remote_install ($t[0], $t[1]);
X		}
X	else	{
X		do local_install ($t[0]);
X		}
X	}
X
Xif (! $do_copy) {
X	do local_command ("rm", "-f", $source);
X	}
X
Xexit (0);
X
Xsub local_install {
X	$target = $_[0];
X
X	if ($do_remove) {
X		do local_command ("rm", "-f", $target);
X		}
X
X	do local_command ("cp", $source, $target);
X
X	if ($do_strip) {
X		do local_command ("strip", $target);
X		}
X
X	if ($do_chown) {
X		do local_command ("chown", $new_owner, $target);
X		}
X
X	if ($do_chgrp) {
X		do local_command ("chgrp", $new_group, $target);
X		}
X
X	if ($do_chmod) {
X		do local_command ("chmod", $new_mode, $target);
X		}
X
X	if ($do_ls) {
X		do local_command ("ll", $target);
X		}
X	}
X
Xsub remote_install {
X	$host = $_[0];
X	$target = $_[1];
X
X	if ($do_remove) {
X		do remote_command ($host, "rm", "-f", $target);
X		}
X
X	do local_command ("rcp", $source, $host . ":" . $target);
X
X	if ($do_strip) {
X		do remote_command ($host, "strip", $target);
X		}
X
X	if ($do_chown) {
X		do remote_command ($host, "chown", $new_owner, $target);
X		}
X
X	if ($do_chgrp) {
X		do remote_command ($host, "chgrp", $new_group, $target);
X		}
X
X	if ($do_chmod) {
X		do remote_command ($host, "chmod", $new_mode, $target);
X		}
X
X	if ($do_ls) {
X		do remote_command ($host, "ll", $target);
X		}
X	}
X
Xsub local_command {
X	$cmd = join (" ", @_);
X	if ($be_verbose) {
X		printf stderr "\t%s\n", $cmd;
X		}
X	$tstat = (system $cmd) >> 8;
X	if ($tstat != 0) {
X		printf stderr "%s:  command \"%s\" failed (returned status %d)\n", $thispgm, $cmd, $tstat;
X		exit (1);
X		}
X	}
X
Xsub remote_command {
X	$rmthost = shift (@_);
X	$rmtcmd = join (" ", @_);
X	if ($be_verbose) {
X		printf stderr "\trsh %s -n %s\n", $rmthost, $rmtcmd;
X		}
X	system "rsh", $rmthost, "-n", $rmtcmd;
X	}
END_OF_FILE
if test 5122 -ne `wc -c <'install.pl'`; then
    echo shar: \"'install.pl'\" unpacked with wrong size!
fi
chmod +x 'install.pl'
# end of 'install.pl'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(538 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XBIN = /usr/local/bin
XMS  = l
XHOST = k+h+i+z+g+b
XFILES = Readme install.1 install.pl Makefile ll
X
Xall:
X	@echo "make install  to install install in $(BIN)"
X	@echo "make manpage  to install the manpage in section $(MS), assuming you have BSD style man page directories"
X
Xinstall: install.pl
X	./install.pl -r -c -m 755 -l install.pl $(HOST):$(BIN)/install
X
X#	for machines with BSD style manpages
Xmanpage: install.1
X	./install.pl -r -c -m 644 -l install.1 $(HOST):/usr/man/man$(MS)/install.$(MS)
X
Xshar: $(FILES)
X	shar $(FILES) > install.shar
X
END_OF_FILE
if test 538 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'll' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ll'\"
else
echo shar: Extracting \"'ll'\" \(18 characters\)
sed "s/^X//" >'ll' <<'END_OF_FILE'
X
X/bin/ls -aFgl $@
END_OF_FILE
if test 18 -ne `wc -c <'ll'`; then
    echo shar: \"'ll'\" unpacked with wrong size!
fi
chmod +x 'll'
# end of 'll'
fi
echo shar: End of shell archive.
exit 0