install-sh revision 97e8a2e8
197e8a2e8Smrg#!/bin/sh
297e8a2e8Smrg#
397e8a2e8Smrg# install - install a program, script, or datafile
497e8a2e8Smrg#
597e8a2e8Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
697e8a2e8Smrg# later released in X11R6 (xc/config/util/install.sh) with the
797e8a2e8Smrg# following copyright and license.
897e8a2e8Smrg#
997e8a2e8Smrg# Copyright (C) 1994 X Consortium
1097e8a2e8Smrg#
1197e8a2e8Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1297e8a2e8Smrg# of this software and associated documentation files (the "Software"), to
1397e8a2e8Smrg# deal in the Software without restriction, including without limitation the
1497e8a2e8Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1597e8a2e8Smrg# sell copies of the Software, and to permit persons to whom the Software is
1697e8a2e8Smrg# furnished to do so, subject to the following conditions:
1797e8a2e8Smrg#
1897e8a2e8Smrg# The above copyright notice and this permission notice shall be included in
1997e8a2e8Smrg# all copies or substantial portions of the Software.
2097e8a2e8Smrg#
2197e8a2e8Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2297e8a2e8Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2397e8a2e8Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2497e8a2e8Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2597e8a2e8Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2697e8a2e8Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2797e8a2e8Smrg#
2897e8a2e8Smrg# Except as contained in this notice, the name of the X Consortium shall not
2997e8a2e8Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3097e8a2e8Smrg# ings in this Software without prior written authorization from the X Consor-
3197e8a2e8Smrg# tium.
3297e8a2e8Smrg#
3397e8a2e8Smrg#
3497e8a2e8Smrg# FSF changes to this file are in the public domain.
3597e8a2e8Smrg#
3697e8a2e8Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3797e8a2e8Smrg# `make' implicit rules from creating a file called install from it
3897e8a2e8Smrg# when there is no Makefile.
3997e8a2e8Smrg#
4097e8a2e8Smrg# This script is compatible with the BSD install script, but was written
4197e8a2e8Smrg# from scratch.  It can only install one file at a time, a restriction
4297e8a2e8Smrg# shared with many OS's install programs.
4397e8a2e8Smrg
4497e8a2e8Smrg
4597e8a2e8Smrg# set DOITPROG to echo to test this script
4697e8a2e8Smrg
4797e8a2e8Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4897e8a2e8Smrgdoit="${DOITPROG-}"
4997e8a2e8Smrg
5097e8a2e8Smrg
5197e8a2e8Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
5297e8a2e8Smrg
5397e8a2e8Smrgmvprog="${MVPROG-mv}"
5497e8a2e8Smrgcpprog="${CPPROG-cp}"
5597e8a2e8Smrgchmodprog="${CHMODPROG-chmod}"
5697e8a2e8Smrgchownprog="${CHOWNPROG-chown}"
5797e8a2e8Smrgchgrpprog="${CHGRPPROG-chgrp}"
5897e8a2e8Smrgstripprog="${STRIPPROG-strip}"
5997e8a2e8Smrgrmprog="${RMPROG-rm}"
6097e8a2e8Smrgmkdirprog="${MKDIRPROG-mkdir}"
6197e8a2e8Smrg
6297e8a2e8Smrgtransformbasename=""
6397e8a2e8Smrgtransform_arg=""
6497e8a2e8Smrginstcmd="$mvprog"
6597e8a2e8Smrgchmodcmd="$chmodprog 0755"
6697e8a2e8Smrgchowncmd=""
6797e8a2e8Smrgchgrpcmd=""
6897e8a2e8Smrgstripcmd=""
6997e8a2e8Smrgrmcmd="$rmprog -f"
7097e8a2e8Smrgmvcmd="$mvprog"
7197e8a2e8Smrgsrc=""
7297e8a2e8Smrgdst=""
7397e8a2e8Smrgdir_arg=""
7497e8a2e8Smrg
7597e8a2e8Smrgwhile [ x"$1" != x ]; do
7697e8a2e8Smrg    case $1 in
7797e8a2e8Smrg	-c) instcmd=$cpprog
7897e8a2e8Smrg	    shift
7997e8a2e8Smrg	    continue;;
8097e8a2e8Smrg
8197e8a2e8Smrg	-d) dir_arg=true
8297e8a2e8Smrg	    shift
8397e8a2e8Smrg	    continue;;
8497e8a2e8Smrg
8597e8a2e8Smrg	-m) chmodcmd="$chmodprog $2"
8697e8a2e8Smrg	    shift
8797e8a2e8Smrg	    shift
8897e8a2e8Smrg	    continue;;
8997e8a2e8Smrg
9097e8a2e8Smrg	-o) chowncmd="$chownprog $2"
9197e8a2e8Smrg	    shift
9297e8a2e8Smrg	    shift
9397e8a2e8Smrg	    continue;;
9497e8a2e8Smrg
9597e8a2e8Smrg	-g) chgrpcmd="$chgrpprog $2"
9697e8a2e8Smrg	    shift
9797e8a2e8Smrg	    shift
9897e8a2e8Smrg	    continue;;
9997e8a2e8Smrg
10097e8a2e8Smrg	-s) stripcmd=$stripprog
10197e8a2e8Smrg	    shift
10297e8a2e8Smrg	    continue;;
10397e8a2e8Smrg
10497e8a2e8Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
10597e8a2e8Smrg	    shift
10697e8a2e8Smrg	    continue;;
10797e8a2e8Smrg
10897e8a2e8Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
10997e8a2e8Smrg	    shift
11097e8a2e8Smrg	    continue;;
11197e8a2e8Smrg
11297e8a2e8Smrg	*)  if [ x"$src" = x ]
11397e8a2e8Smrg	    then
11497e8a2e8Smrg		src=$1
11597e8a2e8Smrg	    else
11697e8a2e8Smrg		# this colon is to work around a 386BSD /bin/sh bug
11797e8a2e8Smrg		:
11897e8a2e8Smrg		dst=$1
11997e8a2e8Smrg	    fi
12097e8a2e8Smrg	    shift
12197e8a2e8Smrg	    continue;;
12297e8a2e8Smrg    esac
12397e8a2e8Smrgdone
12497e8a2e8Smrg
12597e8a2e8Smrgif [ x"$src" = x ]
12697e8a2e8Smrgthen
12797e8a2e8Smrg	echo "$0: no input file specified" >&2
12897e8a2e8Smrg	exit 1
12997e8a2e8Smrgelse
13097e8a2e8Smrg	:
13197e8a2e8Smrgfi
13297e8a2e8Smrg
13397e8a2e8Smrgif [ x"$dir_arg" != x ]; then
13497e8a2e8Smrg	dst=$src
13597e8a2e8Smrg	src=""
13697e8a2e8Smrg
13797e8a2e8Smrg	if [ -d "$dst" ]; then
13897e8a2e8Smrg		instcmd=:
13997e8a2e8Smrg		chmodcmd=""
14097e8a2e8Smrg	else
14197e8a2e8Smrg		instcmd=$mkdirprog
14297e8a2e8Smrg	fi
14397e8a2e8Smrgelse
14497e8a2e8Smrg
14597e8a2e8Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
14697e8a2e8Smrg# might cause directories to be created, which would be especially bad
14797e8a2e8Smrg# if $src (and thus $dsttmp) contains '*'.
14897e8a2e8Smrg
14997e8a2e8Smrg	if [ -f "$src" ] || [ -d "$src" ]
15097e8a2e8Smrg	then
15197e8a2e8Smrg		:
15297e8a2e8Smrg	else
15397e8a2e8Smrg		echo "$0: $src does not exist" >&2
15497e8a2e8Smrg		exit 1
15597e8a2e8Smrg	fi
15697e8a2e8Smrg
15797e8a2e8Smrg	if [ x"$dst" = x ]
15897e8a2e8Smrg	then
15997e8a2e8Smrg		echo "$0: no destination specified" >&2
16097e8a2e8Smrg		exit 1
16197e8a2e8Smrg	else
16297e8a2e8Smrg		:
16397e8a2e8Smrg	fi
16497e8a2e8Smrg
16597e8a2e8Smrg# If destination is a directory, append the input filename; if your system
16697e8a2e8Smrg# does not like double slashes in filenames, you may need to add some logic
16797e8a2e8Smrg
16897e8a2e8Smrg	if [ -d "$dst" ]
16997e8a2e8Smrg	then
17097e8a2e8Smrg		dst=$dst/`basename "$src"`
17197e8a2e8Smrg	else
17297e8a2e8Smrg		:
17397e8a2e8Smrg	fi
17497e8a2e8Smrgfi
17597e8a2e8Smrg
17697e8a2e8Smrg## this sed command emulates the dirname command
17797e8a2e8Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
17897e8a2e8Smrg
17997e8a2e8Smrg# Make sure that the destination directory exists.
18097e8a2e8Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
18197e8a2e8Smrg
18297e8a2e8Smrg# Skip lots of stat calls in the usual case.
18397e8a2e8Smrgif [ ! -d "$dstdir" ]; then
18497e8a2e8SmrgdefaultIFS='
18597e8a2e8Smrg	'
18697e8a2e8SmrgIFS="${IFS-$defaultIFS}"
18797e8a2e8Smrg
18897e8a2e8SmrgoIFS=$IFS
18997e8a2e8Smrg# Some sh's can't handle IFS=/ for some reason.
19097e8a2e8SmrgIFS='%'
19197e8a2e8Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
19297e8a2e8SmrgIFS=$oIFS
19397e8a2e8Smrg
19497e8a2e8Smrgpathcomp=''
19597e8a2e8Smrg
19697e8a2e8Smrgwhile [ $# -ne 0 ] ; do
19797e8a2e8Smrg	pathcomp=$pathcomp$1
19897e8a2e8Smrg	shift
19997e8a2e8Smrg
20097e8a2e8Smrg	if [ ! -d "$pathcomp" ] ;
20197e8a2e8Smrg        then
20297e8a2e8Smrg		$mkdirprog "$pathcomp"
20397e8a2e8Smrg	else
20497e8a2e8Smrg		:
20597e8a2e8Smrg	fi
20697e8a2e8Smrg
20797e8a2e8Smrg	pathcomp=$pathcomp/
20897e8a2e8Smrgdone
20997e8a2e8Smrgfi
21097e8a2e8Smrg
21197e8a2e8Smrgif [ x"$dir_arg" != x ]
21297e8a2e8Smrgthen
21397e8a2e8Smrg	$doit $instcmd "$dst" &&
21497e8a2e8Smrg
21597e8a2e8Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
21697e8a2e8Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
21797e8a2e8Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
21897e8a2e8Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
21997e8a2e8Smrgelse
22097e8a2e8Smrg
22197e8a2e8Smrg# If we're going to rename the final executable, determine the name now.
22297e8a2e8Smrg
22397e8a2e8Smrg	if [ x"$transformarg" = x ]
22497e8a2e8Smrg	then
22597e8a2e8Smrg		dstfile=`basename "$dst"`
22697e8a2e8Smrg	else
22797e8a2e8Smrg		dstfile=`basename "$dst" $transformbasename |
22897e8a2e8Smrg			sed $transformarg`$transformbasename
22997e8a2e8Smrg	fi
23097e8a2e8Smrg
23197e8a2e8Smrg# don't allow the sed command to completely eliminate the filename
23297e8a2e8Smrg
23397e8a2e8Smrg	if [ x"$dstfile" = x ]
23497e8a2e8Smrg	then
23597e8a2e8Smrg		dstfile=`basename "$dst"`
23697e8a2e8Smrg	else
23797e8a2e8Smrg		:
23897e8a2e8Smrg	fi
23997e8a2e8Smrg
24097e8a2e8Smrg# Make a couple of temp file names in the proper directory.
24197e8a2e8Smrg
24297e8a2e8Smrg	dsttmp=$dstdir/_inst.$$_
24397e8a2e8Smrg	rmtmp=$dstdir/_rm.$$_
24497e8a2e8Smrg
24597e8a2e8Smrg# Trap to clean up temp files at exit.
24697e8a2e8Smrg
24797e8a2e8Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
24897e8a2e8Smrg	trap '(exit $?); exit' 1 2 13 15
24997e8a2e8Smrg
25097e8a2e8Smrg# Move or copy the file name to the temp name
25197e8a2e8Smrg
25297e8a2e8Smrg	$doit $instcmd "$src" "$dsttmp" &&
25397e8a2e8Smrg
25497e8a2e8Smrg# and set any options; do chmod last to preserve setuid bits
25597e8a2e8Smrg
25697e8a2e8Smrg# If any of these fail, we abort the whole thing.  If we want to
25797e8a2e8Smrg# ignore errors from any of these, just make sure not to ignore
25897e8a2e8Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
25997e8a2e8Smrg
26097e8a2e8Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
26197e8a2e8Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
26297e8a2e8Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
26397e8a2e8Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
26497e8a2e8Smrg
26597e8a2e8Smrg# Now remove or move aside any old file at destination location.  We try this
26697e8a2e8Smrg# two ways since rm can't unlink itself on some systems and the destination
26797e8a2e8Smrg# file might be busy for other reasons.  In this case, the final cleanup
26897e8a2e8Smrg# might fail but the new file should still install successfully.
26997e8a2e8Smrg
27097e8a2e8Smrg{
27197e8a2e8Smrg	if [ -f "$dstdir/$dstfile" ]
27297e8a2e8Smrg	then
27397e8a2e8Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
27497e8a2e8Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
27597e8a2e8Smrg		{
27697e8a2e8Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
27797e8a2e8Smrg		  (exit 1); exit
27897e8a2e8Smrg		}
27997e8a2e8Smrg	else
28097e8a2e8Smrg		:
28197e8a2e8Smrg	fi
28297e8a2e8Smrg} &&
28397e8a2e8Smrg
28497e8a2e8Smrg# Now rename the file to the real destination.
28597e8a2e8Smrg
28697e8a2e8Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
28797e8a2e8Smrg
28897e8a2e8Smrgfi &&
28997e8a2e8Smrg
29097e8a2e8Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
29197e8a2e8Smrg
29297e8a2e8Smrg{
29397e8a2e8Smrg	(exit 0); exit
29497e8a2e8Smrg}
295