install-sh revision 3294c433
13294c433Smrg#!/bin/sh
23294c433Smrg#
33294c433Smrg# install - install a program, script, or datafile
43294c433Smrg#
53294c433Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
63294c433Smrg# later released in X11R6 (xc/config/util/install.sh) with the
73294c433Smrg# following copyright and license.
83294c433Smrg#
93294c433Smrg# Copyright (C) 1994 X Consortium
103294c433Smrg#
113294c433Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
123294c433Smrg# of this software and associated documentation files (the "Software"), to
133294c433Smrg# deal in the Software without restriction, including without limitation the
143294c433Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
153294c433Smrg# sell copies of the Software, and to permit persons to whom the Software is
163294c433Smrg# furnished to do so, subject to the following conditions:
173294c433Smrg#
183294c433Smrg# The above copyright notice and this permission notice shall be included in
193294c433Smrg# all copies or substantial portions of the Software.
203294c433Smrg#
213294c433Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
223294c433Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
233294c433Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
243294c433Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
253294c433Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
263294c433Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
273294c433Smrg#
283294c433Smrg# Except as contained in this notice, the name of the X Consortium shall not
293294c433Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
303294c433Smrg# ings in this Software without prior written authorization from the X Consor-
313294c433Smrg# tium.
323294c433Smrg#
333294c433Smrg#
343294c433Smrg# FSF changes to this file are in the public domain.
353294c433Smrg#
363294c433Smrg# Calling this script install-sh is preferred over install.sh, to prevent
373294c433Smrg# `make' implicit rules from creating a file called install from it
383294c433Smrg# when there is no Makefile.
393294c433Smrg#
403294c433Smrg# This script is compatible with the BSD install script, but was written
413294c433Smrg# from scratch.  It can only install one file at a time, a restriction
423294c433Smrg# shared with many OS's install programs.
433294c433Smrg
443294c433Smrg
453294c433Smrg# set DOITPROG to echo to test this script
463294c433Smrg
473294c433Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
483294c433Smrgdoit="${DOITPROG-}"
493294c433Smrg
503294c433Smrg
513294c433Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
523294c433Smrg
533294c433Smrgmvprog="${MVPROG-mv}"
543294c433Smrgcpprog="${CPPROG-cp}"
553294c433Smrgchmodprog="${CHMODPROG-chmod}"
563294c433Smrgchownprog="${CHOWNPROG-chown}"
573294c433Smrgchgrpprog="${CHGRPPROG-chgrp}"
583294c433Smrgstripprog="${STRIPPROG-strip}"
593294c433Smrgrmprog="${RMPROG-rm}"
603294c433Smrgmkdirprog="${MKDIRPROG-mkdir}"
613294c433Smrg
623294c433Smrgtransformbasename=""
633294c433Smrgtransform_arg=""
643294c433Smrginstcmd="$mvprog"
653294c433Smrgchmodcmd="$chmodprog 0755"
663294c433Smrgchowncmd=""
673294c433Smrgchgrpcmd=""
683294c433Smrgstripcmd=""
693294c433Smrgrmcmd="$rmprog -f"
703294c433Smrgmvcmd="$mvprog"
713294c433Smrgsrc=""
723294c433Smrgdst=""
733294c433Smrgdir_arg=""
743294c433Smrg
753294c433Smrgwhile [ x"$1" != x ]; do
763294c433Smrg    case $1 in
773294c433Smrg	-c) instcmd=$cpprog
783294c433Smrg	    shift
793294c433Smrg	    continue;;
803294c433Smrg
813294c433Smrg	-d) dir_arg=true
823294c433Smrg	    shift
833294c433Smrg	    continue;;
843294c433Smrg
853294c433Smrg	-m) chmodcmd="$chmodprog $2"
863294c433Smrg	    shift
873294c433Smrg	    shift
883294c433Smrg	    continue;;
893294c433Smrg
903294c433Smrg	-o) chowncmd="$chownprog $2"
913294c433Smrg	    shift
923294c433Smrg	    shift
933294c433Smrg	    continue;;
943294c433Smrg
953294c433Smrg	-g) chgrpcmd="$chgrpprog $2"
963294c433Smrg	    shift
973294c433Smrg	    shift
983294c433Smrg	    continue;;
993294c433Smrg
1003294c433Smrg	-s) stripcmd=$stripprog
1013294c433Smrg	    shift
1023294c433Smrg	    continue;;
1033294c433Smrg
1043294c433Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
1053294c433Smrg	    shift
1063294c433Smrg	    continue;;
1073294c433Smrg
1083294c433Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
1093294c433Smrg	    shift
1103294c433Smrg	    continue;;
1113294c433Smrg
1123294c433Smrg	*)  if [ x"$src" = x ]
1133294c433Smrg	    then
1143294c433Smrg		src=$1
1153294c433Smrg	    else
1163294c433Smrg		# this colon is to work around a 386BSD /bin/sh bug
1173294c433Smrg		:
1183294c433Smrg		dst=$1
1193294c433Smrg	    fi
1203294c433Smrg	    shift
1213294c433Smrg	    continue;;
1223294c433Smrg    esac
1233294c433Smrgdone
1243294c433Smrg
1253294c433Smrgif [ x"$src" = x ]
1263294c433Smrgthen
1273294c433Smrg	echo "$0: no input file specified" >&2
1283294c433Smrg	exit 1
1293294c433Smrgelse
1303294c433Smrg	:
1313294c433Smrgfi
1323294c433Smrg
1333294c433Smrgif [ x"$dir_arg" != x ]; then
1343294c433Smrg	dst=$src
1353294c433Smrg	src=""
1363294c433Smrg
1373294c433Smrg	if [ -d "$dst" ]; then
1383294c433Smrg		instcmd=:
1393294c433Smrg		chmodcmd=""
1403294c433Smrg	else
1413294c433Smrg		instcmd=$mkdirprog
1423294c433Smrg	fi
1433294c433Smrgelse
1443294c433Smrg
1453294c433Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
1463294c433Smrg# might cause directories to be created, which would be especially bad
1473294c433Smrg# if $src (and thus $dsttmp) contains '*'.
1483294c433Smrg
1493294c433Smrg	if [ -f "$src" ] || [ -d "$src" ]
1503294c433Smrg	then
1513294c433Smrg		:
1523294c433Smrg	else
1533294c433Smrg		echo "$0: $src does not exist" >&2
1543294c433Smrg		exit 1
1553294c433Smrg	fi
1563294c433Smrg
1573294c433Smrg	if [ x"$dst" = x ]
1583294c433Smrg	then
1593294c433Smrg		echo "$0: no destination specified" >&2
1603294c433Smrg		exit 1
1613294c433Smrg	else
1623294c433Smrg		:
1633294c433Smrg	fi
1643294c433Smrg
1653294c433Smrg# If destination is a directory, append the input filename; if your system
1663294c433Smrg# does not like double slashes in filenames, you may need to add some logic
1673294c433Smrg
1683294c433Smrg	if [ -d "$dst" ]
1693294c433Smrg	then
1703294c433Smrg		dst=$dst/`basename "$src"`
1713294c433Smrg	else
1723294c433Smrg		:
1733294c433Smrg	fi
1743294c433Smrgfi
1753294c433Smrg
1763294c433Smrg## this sed command emulates the dirname command
1773294c433Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
1783294c433Smrg
1793294c433Smrg# Make sure that the destination directory exists.
1803294c433Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
1813294c433Smrg
1823294c433Smrg# Skip lots of stat calls in the usual case.
1833294c433Smrgif [ ! -d "$dstdir" ]; then
1843294c433SmrgdefaultIFS='
1853294c433Smrg	'
1863294c433SmrgIFS="${IFS-$defaultIFS}"
1873294c433Smrg
1883294c433SmrgoIFS=$IFS
1893294c433Smrg# Some sh's can't handle IFS=/ for some reason.
1903294c433SmrgIFS='%'
1913294c433Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
1923294c433SmrgIFS=$oIFS
1933294c433Smrg
1943294c433Smrgpathcomp=''
1953294c433Smrg
1963294c433Smrgwhile [ $# -ne 0 ] ; do
1973294c433Smrg	pathcomp=$pathcomp$1
1983294c433Smrg	shift
1993294c433Smrg
2003294c433Smrg	if [ ! -d "$pathcomp" ] ;
2013294c433Smrg        then
2023294c433Smrg		$mkdirprog "$pathcomp"
2033294c433Smrg	else
2043294c433Smrg		:
2053294c433Smrg	fi
2063294c433Smrg
2073294c433Smrg	pathcomp=$pathcomp/
2083294c433Smrgdone
2093294c433Smrgfi
2103294c433Smrg
2113294c433Smrgif [ x"$dir_arg" != x ]
2123294c433Smrgthen
2133294c433Smrg	$doit $instcmd "$dst" &&
2143294c433Smrg
2153294c433Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
2163294c433Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
2173294c433Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
2183294c433Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
2193294c433Smrgelse
2203294c433Smrg
2213294c433Smrg# If we're going to rename the final executable, determine the name now.
2223294c433Smrg
2233294c433Smrg	if [ x"$transformarg" = x ]
2243294c433Smrg	then
2253294c433Smrg		dstfile=`basename "$dst"`
2263294c433Smrg	else
2273294c433Smrg		dstfile=`basename "$dst" $transformbasename |
2283294c433Smrg			sed $transformarg`$transformbasename
2293294c433Smrg	fi
2303294c433Smrg
2313294c433Smrg# don't allow the sed command to completely eliminate the filename
2323294c433Smrg
2333294c433Smrg	if [ x"$dstfile" = x ]
2343294c433Smrg	then
2353294c433Smrg		dstfile=`basename "$dst"`
2363294c433Smrg	else
2373294c433Smrg		:
2383294c433Smrg	fi
2393294c433Smrg
2403294c433Smrg# Make a couple of temp file names in the proper directory.
2413294c433Smrg
2423294c433Smrg	dsttmp=$dstdir/_inst.$$_
2433294c433Smrg	rmtmp=$dstdir/_rm.$$_
2443294c433Smrg
2453294c433Smrg# Trap to clean up temp files at exit.
2463294c433Smrg
2473294c433Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
2483294c433Smrg	trap '(exit $?); exit' 1 2 13 15
2493294c433Smrg
2503294c433Smrg# Move or copy the file name to the temp name
2513294c433Smrg
2523294c433Smrg	$doit $instcmd "$src" "$dsttmp" &&
2533294c433Smrg
2543294c433Smrg# and set any options; do chmod last to preserve setuid bits
2553294c433Smrg
2563294c433Smrg# If any of these fail, we abort the whole thing.  If we want to
2573294c433Smrg# ignore errors from any of these, just make sure not to ignore
2583294c433Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
2593294c433Smrg
2603294c433Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
2613294c433Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
2623294c433Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
2633294c433Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
2643294c433Smrg
2653294c433Smrg# Now remove or move aside any old file at destination location.  We try this
2663294c433Smrg# two ways since rm can't unlink itself on some systems and the destination
2673294c433Smrg# file might be busy for other reasons.  In this case, the final cleanup
2683294c433Smrg# might fail but the new file should still install successfully.
2693294c433Smrg
2703294c433Smrg{
2713294c433Smrg	if [ -f "$dstdir/$dstfile" ]
2723294c433Smrg	then
2733294c433Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
2743294c433Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
2753294c433Smrg		{
2763294c433Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2773294c433Smrg		  (exit 1); exit
2783294c433Smrg		}
2793294c433Smrg	else
2803294c433Smrg		:
2813294c433Smrg	fi
2823294c433Smrg} &&
2833294c433Smrg
2843294c433Smrg# Now rename the file to the real destination.
2853294c433Smrg
2863294c433Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
2873294c433Smrg
2883294c433Smrgfi &&
2893294c433Smrg
2903294c433Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
2913294c433Smrg
2923294c433Smrg{
2933294c433Smrg	(exit 0); exit
2943294c433Smrg}
295