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