install-sh revision 4fb28925
14fb28925Smrg#!/bin/sh
24fb28925Smrg#
34fb28925Smrg# install - install a program, script, or datafile
44fb28925Smrg#
54fb28925Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
64fb28925Smrg# later released in X11R6 (xc/config/util/install.sh) with the
74fb28925Smrg# following copyright and license.
84fb28925Smrg#
94fb28925Smrg# Copyright (C) 1994 X Consortium
104fb28925Smrg#
114fb28925Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
124fb28925Smrg# of this software and associated documentation files (the "Software"), to
134fb28925Smrg# deal in the Software without restriction, including without limitation the
144fb28925Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
154fb28925Smrg# sell copies of the Software, and to permit persons to whom the Software is
164fb28925Smrg# furnished to do so, subject to the following conditions:
174fb28925Smrg#
184fb28925Smrg# The above copyright notice and this permission notice shall be included in
194fb28925Smrg# all copies or substantial portions of the Software.
204fb28925Smrg#
214fb28925Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
224fb28925Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
234fb28925Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
244fb28925Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
254fb28925Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
264fb28925Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
274fb28925Smrg#
284fb28925Smrg# Except as contained in this notice, the name of the X Consortium shall not
294fb28925Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
304fb28925Smrg# ings in this Software without prior written authorization from the X Consor-
314fb28925Smrg# tium.
324fb28925Smrg#
334fb28925Smrg#
344fb28925Smrg# FSF changes to this file are in the public domain.
354fb28925Smrg#
364fb28925Smrg# Calling this script install-sh is preferred over install.sh, to prevent
374fb28925Smrg# `make' implicit rules from creating a file called install from it
384fb28925Smrg# when there is no Makefile.
394fb28925Smrg#
404fb28925Smrg# This script is compatible with the BSD install script, but was written
414fb28925Smrg# from scratch.  It can only install one file at a time, a restriction
424fb28925Smrg# shared with many OS's install programs.
434fb28925Smrg
444fb28925Smrg
454fb28925Smrg# set DOITPROG to echo to test this script
464fb28925Smrg
474fb28925Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
484fb28925Smrgdoit="${DOITPROG-}"
494fb28925Smrg
504fb28925Smrg
514fb28925Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
524fb28925Smrg
534fb28925Smrgmvprog="${MVPROG-mv}"
544fb28925Smrgcpprog="${CPPROG-cp}"
554fb28925Smrgchmodprog="${CHMODPROG-chmod}"
564fb28925Smrgchownprog="${CHOWNPROG-chown}"
574fb28925Smrgchgrpprog="${CHGRPPROG-chgrp}"
584fb28925Smrgstripprog="${STRIPPROG-strip}"
594fb28925Smrgrmprog="${RMPROG-rm}"
604fb28925Smrgmkdirprog="${MKDIRPROG-mkdir}"
614fb28925Smrg
624fb28925Smrgtransformbasename=""
634fb28925Smrgtransform_arg=""
644fb28925Smrginstcmd="$mvprog"
654fb28925Smrgchmodcmd="$chmodprog 0755"
664fb28925Smrgchowncmd=""
674fb28925Smrgchgrpcmd=""
684fb28925Smrgstripcmd=""
694fb28925Smrgrmcmd="$rmprog -f"
704fb28925Smrgmvcmd="$mvprog"
714fb28925Smrgsrc=""
724fb28925Smrgdst=""
734fb28925Smrgdir_arg=""
744fb28925Smrg
754fb28925Smrgwhile [ x"$1" != x ]; do
764fb28925Smrg    case $1 in
774fb28925Smrg	-c) instcmd=$cpprog
784fb28925Smrg	    shift
794fb28925Smrg	    continue;;
804fb28925Smrg
814fb28925Smrg	-d) dir_arg=true
824fb28925Smrg	    shift
834fb28925Smrg	    continue;;
844fb28925Smrg
854fb28925Smrg	-m) chmodcmd="$chmodprog $2"
864fb28925Smrg	    shift
874fb28925Smrg	    shift
884fb28925Smrg	    continue;;
894fb28925Smrg
904fb28925Smrg	-o) chowncmd="$chownprog $2"
914fb28925Smrg	    shift
924fb28925Smrg	    shift
934fb28925Smrg	    continue;;
944fb28925Smrg
954fb28925Smrg	-g) chgrpcmd="$chgrpprog $2"
964fb28925Smrg	    shift
974fb28925Smrg	    shift
984fb28925Smrg	    continue;;
994fb28925Smrg
1004fb28925Smrg	-s) stripcmd=$stripprog
1014fb28925Smrg	    shift
1024fb28925Smrg	    continue;;
1034fb28925Smrg
1044fb28925Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
1054fb28925Smrg	    shift
1064fb28925Smrg	    continue;;
1074fb28925Smrg
1084fb28925Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
1094fb28925Smrg	    shift
1104fb28925Smrg	    continue;;
1114fb28925Smrg
1124fb28925Smrg	*)  if [ x"$src" = x ]
1134fb28925Smrg	    then
1144fb28925Smrg		src=$1
1154fb28925Smrg	    else
1164fb28925Smrg		# this colon is to work around a 386BSD /bin/sh bug
1174fb28925Smrg		:
1184fb28925Smrg		dst=$1
1194fb28925Smrg	    fi
1204fb28925Smrg	    shift
1214fb28925Smrg	    continue;;
1224fb28925Smrg    esac
1234fb28925Smrgdone
1244fb28925Smrg
1254fb28925Smrgif [ x"$src" = x ]
1264fb28925Smrgthen
1274fb28925Smrg	echo "$0: no input file specified" >&2
1284fb28925Smrg	exit 1
1294fb28925Smrgelse
1304fb28925Smrg	:
1314fb28925Smrgfi
1324fb28925Smrg
1334fb28925Smrgif [ x"$dir_arg" != x ]; then
1344fb28925Smrg	dst=$src
1354fb28925Smrg	src=""
1364fb28925Smrg
1374fb28925Smrg	if [ -d "$dst" ]; then
1384fb28925Smrg		instcmd=:
1394fb28925Smrg		chmodcmd=""
1404fb28925Smrg	else
1414fb28925Smrg		instcmd=$mkdirprog
1424fb28925Smrg	fi
1434fb28925Smrgelse
1444fb28925Smrg
1454fb28925Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
1464fb28925Smrg# might cause directories to be created, which would be especially bad
1474fb28925Smrg# if $src (and thus $dsttmp) contains '*'.
1484fb28925Smrg
1494fb28925Smrg	if [ -f "$src" ] || [ -d "$src" ]
1504fb28925Smrg	then
1514fb28925Smrg		:
1524fb28925Smrg	else
1534fb28925Smrg		echo "$0: $src does not exist" >&2
1544fb28925Smrg		exit 1
1554fb28925Smrg	fi
1564fb28925Smrg
1574fb28925Smrg	if [ x"$dst" = x ]
1584fb28925Smrg	then
1594fb28925Smrg		echo "$0: no destination specified" >&2
1604fb28925Smrg		exit 1
1614fb28925Smrg	else
1624fb28925Smrg		:
1634fb28925Smrg	fi
1644fb28925Smrg
1654fb28925Smrg# If destination is a directory, append the input filename; if your system
1664fb28925Smrg# does not like double slashes in filenames, you may need to add some logic
1674fb28925Smrg
1684fb28925Smrg	if [ -d "$dst" ]
1694fb28925Smrg	then
1704fb28925Smrg		dst=$dst/`basename "$src"`
1714fb28925Smrg	else
1724fb28925Smrg		:
1734fb28925Smrg	fi
1744fb28925Smrgfi
1754fb28925Smrg
1764fb28925Smrg## this sed command emulates the dirname command
1774fb28925Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
1784fb28925Smrg
1794fb28925Smrg# Make sure that the destination directory exists.
1804fb28925Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
1814fb28925Smrg
1824fb28925Smrg# Skip lots of stat calls in the usual case.
1834fb28925Smrgif [ ! -d "$dstdir" ]; then
1844fb28925SmrgdefaultIFS='
1854fb28925Smrg	'
1864fb28925SmrgIFS="${IFS-$defaultIFS}"
1874fb28925Smrg
1884fb28925SmrgoIFS=$IFS
1894fb28925Smrg# Some sh's can't handle IFS=/ for some reason.
1904fb28925SmrgIFS='%'
1914fb28925Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
1924fb28925SmrgIFS=$oIFS
1934fb28925Smrg
1944fb28925Smrgpathcomp=''
1954fb28925Smrg
1964fb28925Smrgwhile [ $# -ne 0 ] ; do
1974fb28925Smrg	pathcomp=$pathcomp$1
1984fb28925Smrg	shift
1994fb28925Smrg
2004fb28925Smrg	if [ ! -d "$pathcomp" ] ;
2014fb28925Smrg        then
2024fb28925Smrg		$mkdirprog "$pathcomp"
2034fb28925Smrg	else
2044fb28925Smrg		:
2054fb28925Smrg	fi
2064fb28925Smrg
2074fb28925Smrg	pathcomp=$pathcomp/
2084fb28925Smrgdone
2094fb28925Smrgfi
2104fb28925Smrg
2114fb28925Smrgif [ x"$dir_arg" != x ]
2124fb28925Smrgthen
2134fb28925Smrg	$doit $instcmd "$dst" &&
2144fb28925Smrg
2154fb28925Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
2164fb28925Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
2174fb28925Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
2184fb28925Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
2194fb28925Smrgelse
2204fb28925Smrg
2214fb28925Smrg# If we're going to rename the final executable, determine the name now.
2224fb28925Smrg
2234fb28925Smrg	if [ x"$transformarg" = x ]
2244fb28925Smrg	then
2254fb28925Smrg		dstfile=`basename "$dst"`
2264fb28925Smrg	else
2274fb28925Smrg		dstfile=`basename "$dst" $transformbasename |
2284fb28925Smrg			sed $transformarg`$transformbasename
2294fb28925Smrg	fi
2304fb28925Smrg
2314fb28925Smrg# don't allow the sed command to completely eliminate the filename
2324fb28925Smrg
2334fb28925Smrg	if [ x"$dstfile" = x ]
2344fb28925Smrg	then
2354fb28925Smrg		dstfile=`basename "$dst"`
2364fb28925Smrg	else
2374fb28925Smrg		:
2384fb28925Smrg	fi
2394fb28925Smrg
2404fb28925Smrg# Make a couple of temp file names in the proper directory.
2414fb28925Smrg
2424fb28925Smrg	dsttmp=$dstdir/_inst.$$_
2434fb28925Smrg	rmtmp=$dstdir/_rm.$$_
2444fb28925Smrg
2454fb28925Smrg# Trap to clean up temp files at exit.
2464fb28925Smrg
2474fb28925Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
2484fb28925Smrg	trap '(exit $?); exit' 1 2 13 15
2494fb28925Smrg
2504fb28925Smrg# Move or copy the file name to the temp name
2514fb28925Smrg
2524fb28925Smrg	$doit $instcmd "$src" "$dsttmp" &&
2534fb28925Smrg
2544fb28925Smrg# and set any options; do chmod last to preserve setuid bits
2554fb28925Smrg
2564fb28925Smrg# If any of these fail, we abort the whole thing.  If we want to
2574fb28925Smrg# ignore errors from any of these, just make sure not to ignore
2584fb28925Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
2594fb28925Smrg
2604fb28925Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
2614fb28925Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
2624fb28925Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
2634fb28925Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
2644fb28925Smrg
2654fb28925Smrg# Now remove or move aside any old file at destination location.  We try this
2664fb28925Smrg# two ways since rm can't unlink itself on some systems and the destination
2674fb28925Smrg# file might be busy for other reasons.  In this case, the final cleanup
2684fb28925Smrg# might fail but the new file should still install successfully.
2694fb28925Smrg
2704fb28925Smrg{
2714fb28925Smrg	if [ -f "$dstdir/$dstfile" ]
2724fb28925Smrg	then
2734fb28925Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
2744fb28925Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
2754fb28925Smrg		{
2764fb28925Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2774fb28925Smrg		  (exit 1); exit
2784fb28925Smrg		}
2794fb28925Smrg	else
2804fb28925Smrg		:
2814fb28925Smrg	fi
2824fb28925Smrg} &&
2834fb28925Smrg
2844fb28925Smrg# Now rename the file to the real destination.
2854fb28925Smrg
2864fb28925Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
2874fb28925Smrg
2884fb28925Smrgfi &&
2894fb28925Smrg
2904fb28925Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
2914fb28925Smrg
2924fb28925Smrg{
2934fb28925Smrg	(exit 0); exit
2944fb28925Smrg}
295