install-sh revision 8108eb18
18108eb18Smrg#!/bin/sh
28108eb18Smrg#
38108eb18Smrg# install - install a program, script, or datafile
48108eb18Smrg#
58108eb18Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
68108eb18Smrg# later released in X11R6 (xc/config/util/install.sh) with the
78108eb18Smrg# following copyright and license.
88108eb18Smrg#
98108eb18Smrg# Copyright (C) 1994 X Consortium
108108eb18Smrg#
118108eb18Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
128108eb18Smrg# of this software and associated documentation files (the "Software"), to
138108eb18Smrg# deal in the Software without restriction, including without limitation the
148108eb18Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
158108eb18Smrg# sell copies of the Software, and to permit persons to whom the Software is
168108eb18Smrg# furnished to do so, subject to the following conditions:
178108eb18Smrg#
188108eb18Smrg# The above copyright notice and this permission notice shall be included in
198108eb18Smrg# all copies or substantial portions of the Software.
208108eb18Smrg#
218108eb18Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
228108eb18Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
238108eb18Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
248108eb18Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
258108eb18Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
268108eb18Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
278108eb18Smrg#
288108eb18Smrg# Except as contained in this notice, the name of the X Consortium shall not
298108eb18Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
308108eb18Smrg# ings in this Software without prior written authorization from the X Consor-
318108eb18Smrg# tium.
328108eb18Smrg#
338108eb18Smrg#
348108eb18Smrg# FSF changes to this file are in the public domain.
358108eb18Smrg#
368108eb18Smrg# Calling this script install-sh is preferred over install.sh, to prevent
378108eb18Smrg# `make' implicit rules from creating a file called install from it
388108eb18Smrg# when there is no Makefile.
398108eb18Smrg#
408108eb18Smrg# This script is compatible with the BSD install script, but was written
418108eb18Smrg# from scratch.  It can only install one file at a time, a restriction
428108eb18Smrg# shared with many OS's install programs.
438108eb18Smrg
448108eb18Smrg
458108eb18Smrg# set DOITPROG to echo to test this script
468108eb18Smrg
478108eb18Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
488108eb18Smrgdoit="${DOITPROG-}"
498108eb18Smrg
508108eb18Smrg
518108eb18Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
528108eb18Smrg
538108eb18Smrgmvprog="${MVPROG-mv}"
548108eb18Smrgcpprog="${CPPROG-cp}"
558108eb18Smrgchmodprog="${CHMODPROG-chmod}"
568108eb18Smrgchownprog="${CHOWNPROG-chown}"
578108eb18Smrgchgrpprog="${CHGRPPROG-chgrp}"
588108eb18Smrgstripprog="${STRIPPROG-strip}"
598108eb18Smrgrmprog="${RMPROG-rm}"
608108eb18Smrgmkdirprog="${MKDIRPROG-mkdir}"
618108eb18Smrg
628108eb18Smrgtransformbasename=""
638108eb18Smrgtransform_arg=""
648108eb18Smrginstcmd="$mvprog"
658108eb18Smrgchmodcmd="$chmodprog 0755"
668108eb18Smrgchowncmd=""
678108eb18Smrgchgrpcmd=""
688108eb18Smrgstripcmd=""
698108eb18Smrgrmcmd="$rmprog -f"
708108eb18Smrgmvcmd="$mvprog"
718108eb18Smrgsrc=""
728108eb18Smrgdst=""
738108eb18Smrgdir_arg=""
748108eb18Smrg
758108eb18Smrgwhile [ x"$1" != x ]; do
768108eb18Smrg    case $1 in
778108eb18Smrg	-c) instcmd=$cpprog
788108eb18Smrg	    shift
798108eb18Smrg	    continue;;
808108eb18Smrg
818108eb18Smrg	-d) dir_arg=true
828108eb18Smrg	    shift
838108eb18Smrg	    continue;;
848108eb18Smrg
858108eb18Smrg	-m) chmodcmd="$chmodprog $2"
868108eb18Smrg	    shift
878108eb18Smrg	    shift
888108eb18Smrg	    continue;;
898108eb18Smrg
908108eb18Smrg	-o) chowncmd="$chownprog $2"
918108eb18Smrg	    shift
928108eb18Smrg	    shift
938108eb18Smrg	    continue;;
948108eb18Smrg
958108eb18Smrg	-g) chgrpcmd="$chgrpprog $2"
968108eb18Smrg	    shift
978108eb18Smrg	    shift
988108eb18Smrg	    continue;;
998108eb18Smrg
1008108eb18Smrg	-s) stripcmd=$stripprog
1018108eb18Smrg	    shift
1028108eb18Smrg	    continue;;
1038108eb18Smrg
1048108eb18Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
1058108eb18Smrg	    shift
1068108eb18Smrg	    continue;;
1078108eb18Smrg
1088108eb18Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
1098108eb18Smrg	    shift
1108108eb18Smrg	    continue;;
1118108eb18Smrg
1128108eb18Smrg	*)  if [ x"$src" = x ]
1138108eb18Smrg	    then
1148108eb18Smrg		src=$1
1158108eb18Smrg	    else
1168108eb18Smrg		# this colon is to work around a 386BSD /bin/sh bug
1178108eb18Smrg		:
1188108eb18Smrg		dst=$1
1198108eb18Smrg	    fi
1208108eb18Smrg	    shift
1218108eb18Smrg	    continue;;
1228108eb18Smrg    esac
1238108eb18Smrgdone
1248108eb18Smrg
1258108eb18Smrgif [ x"$src" = x ]
1268108eb18Smrgthen
1278108eb18Smrg	echo "$0: no input file specified" >&2
1288108eb18Smrg	exit 1
1298108eb18Smrgelse
1308108eb18Smrg	:
1318108eb18Smrgfi
1328108eb18Smrg
1338108eb18Smrgif [ x"$dir_arg" != x ]; then
1348108eb18Smrg	dst=$src
1358108eb18Smrg	src=""
1368108eb18Smrg
1378108eb18Smrg	if [ -d "$dst" ]; then
1388108eb18Smrg		instcmd=:
1398108eb18Smrg		chmodcmd=""
1408108eb18Smrg	else
1418108eb18Smrg		instcmd=$mkdirprog
1428108eb18Smrg	fi
1438108eb18Smrgelse
1448108eb18Smrg
1458108eb18Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
1468108eb18Smrg# might cause directories to be created, which would be especially bad
1478108eb18Smrg# if $src (and thus $dsttmp) contains '*'.
1488108eb18Smrg
1498108eb18Smrg	if [ -f "$src" ] || [ -d "$src" ]
1508108eb18Smrg	then
1518108eb18Smrg		:
1528108eb18Smrg	else
1538108eb18Smrg		echo "$0: $src does not exist" >&2
1548108eb18Smrg		exit 1
1558108eb18Smrg	fi
1568108eb18Smrg
1578108eb18Smrg	if [ x"$dst" = x ]
1588108eb18Smrg	then
1598108eb18Smrg		echo "$0: no destination specified" >&2
1608108eb18Smrg		exit 1
1618108eb18Smrg	else
1628108eb18Smrg		:
1638108eb18Smrg	fi
1648108eb18Smrg
1658108eb18Smrg# If destination is a directory, append the input filename; if your system
1668108eb18Smrg# does not like double slashes in filenames, you may need to add some logic
1678108eb18Smrg
1688108eb18Smrg	if [ -d "$dst" ]
1698108eb18Smrg	then
1708108eb18Smrg		dst=$dst/`basename "$src"`
1718108eb18Smrg	else
1728108eb18Smrg		:
1738108eb18Smrg	fi
1748108eb18Smrgfi
1758108eb18Smrg
1768108eb18Smrg## this sed command emulates the dirname command
1778108eb18Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
1788108eb18Smrg
1798108eb18Smrg# Make sure that the destination directory exists.
1808108eb18Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
1818108eb18Smrg
1828108eb18Smrg# Skip lots of stat calls in the usual case.
1838108eb18Smrgif [ ! -d "$dstdir" ]; then
1848108eb18SmrgdefaultIFS='
1858108eb18Smrg	'
1868108eb18SmrgIFS="${IFS-$defaultIFS}"
1878108eb18Smrg
1888108eb18SmrgoIFS=$IFS
1898108eb18Smrg# Some sh's can't handle IFS=/ for some reason.
1908108eb18SmrgIFS='%'
1918108eb18Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
1928108eb18SmrgIFS=$oIFS
1938108eb18Smrg
1948108eb18Smrgpathcomp=''
1958108eb18Smrg
1968108eb18Smrgwhile [ $# -ne 0 ] ; do
1978108eb18Smrg	pathcomp=$pathcomp$1
1988108eb18Smrg	shift
1998108eb18Smrg
2008108eb18Smrg	if [ ! -d "$pathcomp" ] ;
2018108eb18Smrg        then
2028108eb18Smrg		$mkdirprog "$pathcomp"
2038108eb18Smrg	else
2048108eb18Smrg		:
2058108eb18Smrg	fi
2068108eb18Smrg
2078108eb18Smrg	pathcomp=$pathcomp/
2088108eb18Smrgdone
2098108eb18Smrgfi
2108108eb18Smrg
2118108eb18Smrgif [ x"$dir_arg" != x ]
2128108eb18Smrgthen
2138108eb18Smrg	$doit $instcmd "$dst" &&
2148108eb18Smrg
2158108eb18Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
2168108eb18Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
2178108eb18Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
2188108eb18Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
2198108eb18Smrgelse
2208108eb18Smrg
2218108eb18Smrg# If we're going to rename the final executable, determine the name now.
2228108eb18Smrg
2238108eb18Smrg	if [ x"$transformarg" = x ]
2248108eb18Smrg	then
2258108eb18Smrg		dstfile=`basename "$dst"`
2268108eb18Smrg	else
2278108eb18Smrg		dstfile=`basename "$dst" $transformbasename |
2288108eb18Smrg			sed $transformarg`$transformbasename
2298108eb18Smrg	fi
2308108eb18Smrg
2318108eb18Smrg# don't allow the sed command to completely eliminate the filename
2328108eb18Smrg
2338108eb18Smrg	if [ x"$dstfile" = x ]
2348108eb18Smrg	then
2358108eb18Smrg		dstfile=`basename "$dst"`
2368108eb18Smrg	else
2378108eb18Smrg		:
2388108eb18Smrg	fi
2398108eb18Smrg
2408108eb18Smrg# Make a couple of temp file names in the proper directory.
2418108eb18Smrg
2428108eb18Smrg	dsttmp=$dstdir/_inst.$$_
2438108eb18Smrg	rmtmp=$dstdir/_rm.$$_
2448108eb18Smrg
2458108eb18Smrg# Trap to clean up temp files at exit.
2468108eb18Smrg
2478108eb18Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
2488108eb18Smrg	trap '(exit $?); exit' 1 2 13 15
2498108eb18Smrg
2508108eb18Smrg# Move or copy the file name to the temp name
2518108eb18Smrg
2528108eb18Smrg	$doit $instcmd "$src" "$dsttmp" &&
2538108eb18Smrg
2548108eb18Smrg# and set any options; do chmod last to preserve setuid bits
2558108eb18Smrg
2568108eb18Smrg# If any of these fail, we abort the whole thing.  If we want to
2578108eb18Smrg# ignore errors from any of these, just make sure not to ignore
2588108eb18Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
2598108eb18Smrg
2608108eb18Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
2618108eb18Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
2628108eb18Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
2638108eb18Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
2648108eb18Smrg
2658108eb18Smrg# Now remove or move aside any old file at destination location.  We try this
2668108eb18Smrg# two ways since rm can't unlink itself on some systems and the destination
2678108eb18Smrg# file might be busy for other reasons.  In this case, the final cleanup
2688108eb18Smrg# might fail but the new file should still install successfully.
2698108eb18Smrg
2708108eb18Smrg{
2718108eb18Smrg	if [ -f "$dstdir/$dstfile" ]
2728108eb18Smrg	then
2738108eb18Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
2748108eb18Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
2758108eb18Smrg		{
2768108eb18Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2778108eb18Smrg		  (exit 1); exit
2788108eb18Smrg		}
2798108eb18Smrg	else
2808108eb18Smrg		:
2818108eb18Smrg	fi
2828108eb18Smrg} &&
2838108eb18Smrg
2848108eb18Smrg# Now rename the file to the real destination.
2858108eb18Smrg
2868108eb18Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
2878108eb18Smrg
2888108eb18Smrgfi &&
2898108eb18Smrg
2908108eb18Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
2918108eb18Smrg
2928108eb18Smrg{
2938108eb18Smrg	(exit 0); exit
2948108eb18Smrg}
295