install-sh revision 0e20ee16
10e20ee16Smrg#!/bin/sh
20e20ee16Smrg#
30e20ee16Smrg# install - install a program, script, or datafile
40e20ee16Smrg#
50e20ee16Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
60e20ee16Smrg# later released in X11R6 (xc/config/util/install.sh) with the
70e20ee16Smrg# following copyright and license.
80e20ee16Smrg#
90e20ee16Smrg# Copyright (C) 1994 X Consortium
100e20ee16Smrg#
110e20ee16Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
120e20ee16Smrg# of this software and associated documentation files (the "Software"), to
130e20ee16Smrg# deal in the Software without restriction, including without limitation the
140e20ee16Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
150e20ee16Smrg# sell copies of the Software, and to permit persons to whom the Software is
160e20ee16Smrg# furnished to do so, subject to the following conditions:
170e20ee16Smrg#
180e20ee16Smrg# The above copyright notice and this permission notice shall be included in
190e20ee16Smrg# all copies or substantial portions of the Software.
200e20ee16Smrg#
210e20ee16Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
220e20ee16Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
230e20ee16Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
240e20ee16Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
250e20ee16Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
260e20ee16Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
270e20ee16Smrg#
280e20ee16Smrg# Except as contained in this notice, the name of the X Consortium shall not
290e20ee16Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
300e20ee16Smrg# ings in this Software without prior written authorization from the X Consor-
310e20ee16Smrg# tium.
320e20ee16Smrg#
330e20ee16Smrg#
340e20ee16Smrg# FSF changes to this file are in the public domain.
350e20ee16Smrg#
360e20ee16Smrg# Calling this script install-sh is preferred over install.sh, to prevent
370e20ee16Smrg# `make' implicit rules from creating a file called install from it
380e20ee16Smrg# when there is no Makefile.
390e20ee16Smrg#
400e20ee16Smrg# This script is compatible with the BSD install script, but was written
410e20ee16Smrg# from scratch.  It can only install one file at a time, a restriction
420e20ee16Smrg# shared with many OS's install programs.
430e20ee16Smrg
440e20ee16Smrg
450e20ee16Smrg# set DOITPROG to echo to test this script
460e20ee16Smrg
470e20ee16Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
480e20ee16Smrgdoit="${DOITPROG-}"
490e20ee16Smrg
500e20ee16Smrg
510e20ee16Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
520e20ee16Smrg
530e20ee16Smrgmvprog="${MVPROG-mv}"
540e20ee16Smrgcpprog="${CPPROG-cp}"
550e20ee16Smrgchmodprog="${CHMODPROG-chmod}"
560e20ee16Smrgchownprog="${CHOWNPROG-chown}"
570e20ee16Smrgchgrpprog="${CHGRPPROG-chgrp}"
580e20ee16Smrgstripprog="${STRIPPROG-strip}"
590e20ee16Smrgrmprog="${RMPROG-rm}"
600e20ee16Smrgmkdirprog="${MKDIRPROG-mkdir}"
610e20ee16Smrg
620e20ee16Smrgtransformbasename=""
630e20ee16Smrgtransform_arg=""
640e20ee16Smrginstcmd="$mvprog"
650e20ee16Smrgchmodcmd="$chmodprog 0755"
660e20ee16Smrgchowncmd=""
670e20ee16Smrgchgrpcmd=""
680e20ee16Smrgstripcmd=""
690e20ee16Smrgrmcmd="$rmprog -f"
700e20ee16Smrgmvcmd="$mvprog"
710e20ee16Smrgsrc=""
720e20ee16Smrgdst=""
730e20ee16Smrgdir_arg=""
740e20ee16Smrg
750e20ee16Smrgwhile [ x"$1" != x ]; do
760e20ee16Smrg    case $1 in
770e20ee16Smrg	-c) instcmd=$cpprog
780e20ee16Smrg	    shift
790e20ee16Smrg	    continue;;
800e20ee16Smrg
810e20ee16Smrg	-d) dir_arg=true
820e20ee16Smrg	    shift
830e20ee16Smrg	    continue;;
840e20ee16Smrg
850e20ee16Smrg	-m) chmodcmd="$chmodprog $2"
860e20ee16Smrg	    shift
870e20ee16Smrg	    shift
880e20ee16Smrg	    continue;;
890e20ee16Smrg
900e20ee16Smrg	-o) chowncmd="$chownprog $2"
910e20ee16Smrg	    shift
920e20ee16Smrg	    shift
930e20ee16Smrg	    continue;;
940e20ee16Smrg
950e20ee16Smrg	-g) chgrpcmd="$chgrpprog $2"
960e20ee16Smrg	    shift
970e20ee16Smrg	    shift
980e20ee16Smrg	    continue;;
990e20ee16Smrg
1000e20ee16Smrg	-s) stripcmd=$stripprog
1010e20ee16Smrg	    shift
1020e20ee16Smrg	    continue;;
1030e20ee16Smrg
1040e20ee16Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
1050e20ee16Smrg	    shift
1060e20ee16Smrg	    continue;;
1070e20ee16Smrg
1080e20ee16Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
1090e20ee16Smrg	    shift
1100e20ee16Smrg	    continue;;
1110e20ee16Smrg
1120e20ee16Smrg	*)  if [ x"$src" = x ]
1130e20ee16Smrg	    then
1140e20ee16Smrg		src=$1
1150e20ee16Smrg	    else
1160e20ee16Smrg		# this colon is to work around a 386BSD /bin/sh bug
1170e20ee16Smrg		:
1180e20ee16Smrg		dst=$1
1190e20ee16Smrg	    fi
1200e20ee16Smrg	    shift
1210e20ee16Smrg	    continue;;
1220e20ee16Smrg    esac
1230e20ee16Smrgdone
1240e20ee16Smrg
1250e20ee16Smrgif [ x"$src" = x ]
1260e20ee16Smrgthen
1270e20ee16Smrg	echo "$0: no input file specified" >&2
1280e20ee16Smrg	exit 1
1290e20ee16Smrgelse
1300e20ee16Smrg	:
1310e20ee16Smrgfi
1320e20ee16Smrg
1330e20ee16Smrgif [ x"$dir_arg" != x ]; then
1340e20ee16Smrg	dst=$src
1350e20ee16Smrg	src=""
1360e20ee16Smrg
1370e20ee16Smrg	if [ -d "$dst" ]; then
1380e20ee16Smrg		instcmd=:
1390e20ee16Smrg		chmodcmd=""
1400e20ee16Smrg	else
1410e20ee16Smrg		instcmd=$mkdirprog
1420e20ee16Smrg	fi
1430e20ee16Smrgelse
1440e20ee16Smrg
1450e20ee16Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
1460e20ee16Smrg# might cause directories to be created, which would be especially bad
1470e20ee16Smrg# if $src (and thus $dsttmp) contains '*'.
1480e20ee16Smrg
1490e20ee16Smrg	if [ -f "$src" ] || [ -d "$src" ]
1500e20ee16Smrg	then
1510e20ee16Smrg		:
1520e20ee16Smrg	else
1530e20ee16Smrg		echo "$0: $src does not exist" >&2
1540e20ee16Smrg		exit 1
1550e20ee16Smrg	fi
1560e20ee16Smrg
1570e20ee16Smrg	if [ x"$dst" = x ]
1580e20ee16Smrg	then
1590e20ee16Smrg		echo "$0: no destination specified" >&2
1600e20ee16Smrg		exit 1
1610e20ee16Smrg	else
1620e20ee16Smrg		:
1630e20ee16Smrg	fi
1640e20ee16Smrg
1650e20ee16Smrg# If destination is a directory, append the input filename; if your system
1660e20ee16Smrg# does not like double slashes in filenames, you may need to add some logic
1670e20ee16Smrg
1680e20ee16Smrg	if [ -d "$dst" ]
1690e20ee16Smrg	then
1700e20ee16Smrg		dst=$dst/`basename "$src"`
1710e20ee16Smrg	else
1720e20ee16Smrg		:
1730e20ee16Smrg	fi
1740e20ee16Smrgfi
1750e20ee16Smrg
1760e20ee16Smrg## this sed command emulates the dirname command
1770e20ee16Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
1780e20ee16Smrg
1790e20ee16Smrg# Make sure that the destination directory exists.
1800e20ee16Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
1810e20ee16Smrg
1820e20ee16Smrg# Skip lots of stat calls in the usual case.
1830e20ee16Smrgif [ ! -d "$dstdir" ]; then
1840e20ee16SmrgdefaultIFS='
1850e20ee16Smrg	'
1860e20ee16SmrgIFS="${IFS-$defaultIFS}"
1870e20ee16Smrg
1880e20ee16SmrgoIFS=$IFS
1890e20ee16Smrg# Some sh's can't handle IFS=/ for some reason.
1900e20ee16SmrgIFS='%'
1910e20ee16Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
1920e20ee16SmrgIFS=$oIFS
1930e20ee16Smrg
1940e20ee16Smrgpathcomp=''
1950e20ee16Smrg
1960e20ee16Smrgwhile [ $# -ne 0 ] ; do
1970e20ee16Smrg	pathcomp=$pathcomp$1
1980e20ee16Smrg	shift
1990e20ee16Smrg
2000e20ee16Smrg	if [ ! -d "$pathcomp" ] ;
2010e20ee16Smrg        then
2020e20ee16Smrg		$mkdirprog "$pathcomp"
2030e20ee16Smrg	else
2040e20ee16Smrg		:
2050e20ee16Smrg	fi
2060e20ee16Smrg
2070e20ee16Smrg	pathcomp=$pathcomp/
2080e20ee16Smrgdone
2090e20ee16Smrgfi
2100e20ee16Smrg
2110e20ee16Smrgif [ x"$dir_arg" != x ]
2120e20ee16Smrgthen
2130e20ee16Smrg	$doit $instcmd "$dst" &&
2140e20ee16Smrg
2150e20ee16Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
2160e20ee16Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
2170e20ee16Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
2180e20ee16Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
2190e20ee16Smrgelse
2200e20ee16Smrg
2210e20ee16Smrg# If we're going to rename the final executable, determine the name now.
2220e20ee16Smrg
2230e20ee16Smrg	if [ x"$transformarg" = x ]
2240e20ee16Smrg	then
2250e20ee16Smrg		dstfile=`basename "$dst"`
2260e20ee16Smrg	else
2270e20ee16Smrg		dstfile=`basename "$dst" $transformbasename |
2280e20ee16Smrg			sed $transformarg`$transformbasename
2290e20ee16Smrg	fi
2300e20ee16Smrg
2310e20ee16Smrg# don't allow the sed command to completely eliminate the filename
2320e20ee16Smrg
2330e20ee16Smrg	if [ x"$dstfile" = x ]
2340e20ee16Smrg	then
2350e20ee16Smrg		dstfile=`basename "$dst"`
2360e20ee16Smrg	else
2370e20ee16Smrg		:
2380e20ee16Smrg	fi
2390e20ee16Smrg
2400e20ee16Smrg# Make a couple of temp file names in the proper directory.
2410e20ee16Smrg
2420e20ee16Smrg	dsttmp=$dstdir/_inst.$$_
2430e20ee16Smrg	rmtmp=$dstdir/_rm.$$_
2440e20ee16Smrg
2450e20ee16Smrg# Trap to clean up temp files at exit.
2460e20ee16Smrg
2470e20ee16Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
2480e20ee16Smrg	trap '(exit $?); exit' 1 2 13 15
2490e20ee16Smrg
2500e20ee16Smrg# Move or copy the file name to the temp name
2510e20ee16Smrg
2520e20ee16Smrg	$doit $instcmd "$src" "$dsttmp" &&
2530e20ee16Smrg
2540e20ee16Smrg# and set any options; do chmod last to preserve setuid bits
2550e20ee16Smrg
2560e20ee16Smrg# If any of these fail, we abort the whole thing.  If we want to
2570e20ee16Smrg# ignore errors from any of these, just make sure not to ignore
2580e20ee16Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
2590e20ee16Smrg
2600e20ee16Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
2610e20ee16Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
2620e20ee16Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
2630e20ee16Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
2640e20ee16Smrg
2650e20ee16Smrg# Now remove or move aside any old file at destination location.  We try this
2660e20ee16Smrg# two ways since rm can't unlink itself on some systems and the destination
2670e20ee16Smrg# file might be busy for other reasons.  In this case, the final cleanup
2680e20ee16Smrg# might fail but the new file should still install successfully.
2690e20ee16Smrg
2700e20ee16Smrg{
2710e20ee16Smrg	if [ -f "$dstdir/$dstfile" ]
2720e20ee16Smrg	then
2730e20ee16Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
2740e20ee16Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
2750e20ee16Smrg		{
2760e20ee16Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2770e20ee16Smrg		  (exit 1); exit
2780e20ee16Smrg		}
2790e20ee16Smrg	else
2800e20ee16Smrg		:
2810e20ee16Smrg	fi
2820e20ee16Smrg} &&
2830e20ee16Smrg
2840e20ee16Smrg# Now rename the file to the real destination.
2850e20ee16Smrg
2860e20ee16Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
2870e20ee16Smrg
2880e20ee16Smrgfi &&
2890e20ee16Smrg
2900e20ee16Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
2910e20ee16Smrg
2920e20ee16Smrg{
2930e20ee16Smrg	(exit 0); exit
2940e20ee16Smrg}
295