install-sh revision 08f3b10e
108f3b10eSmrg#!/bin/sh
208f3b10eSmrg#
308f3b10eSmrg# install - install a program, script, or datafile
408f3b10eSmrg#
508f3b10eSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
608f3b10eSmrg# later released in X11R6 (xc/config/util/install.sh) with the
708f3b10eSmrg# following copyright and license.
808f3b10eSmrg#
908f3b10eSmrg# Copyright (C) 1994 X Consortium
1008f3b10eSmrg#
1108f3b10eSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1208f3b10eSmrg# of this software and associated documentation files (the "Software"), to
1308f3b10eSmrg# deal in the Software without restriction, including without limitation the
1408f3b10eSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1508f3b10eSmrg# sell copies of the Software, and to permit persons to whom the Software is
1608f3b10eSmrg# furnished to do so, subject to the following conditions:
1708f3b10eSmrg#
1808f3b10eSmrg# The above copyright notice and this permission notice shall be included in
1908f3b10eSmrg# all copies or substantial portions of the Software.
2008f3b10eSmrg#
2108f3b10eSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2208f3b10eSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2308f3b10eSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2408f3b10eSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2508f3b10eSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2608f3b10eSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2708f3b10eSmrg#
2808f3b10eSmrg# Except as contained in this notice, the name of the X Consortium shall not
2908f3b10eSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3008f3b10eSmrg# ings in this Software without prior written authorization from the X Consor-
3108f3b10eSmrg# tium.
3208f3b10eSmrg#
3308f3b10eSmrg#
3408f3b10eSmrg# FSF changes to this file are in the public domain.
3508f3b10eSmrg#
3608f3b10eSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3708f3b10eSmrg# `make' implicit rules from creating a file called install from it
3808f3b10eSmrg# when there is no Makefile.
3908f3b10eSmrg#
4008f3b10eSmrg# This script is compatible with the BSD install script, but was written
4108f3b10eSmrg# from scratch.  It can only install one file at a time, a restriction
4208f3b10eSmrg# shared with many OS's install programs.
4308f3b10eSmrg
4408f3b10eSmrg
4508f3b10eSmrg# set DOITPROG to echo to test this script
4608f3b10eSmrg
4708f3b10eSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4808f3b10eSmrgdoit="${DOITPROG-}"
4908f3b10eSmrg
5008f3b10eSmrg
5108f3b10eSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
5208f3b10eSmrg
5308f3b10eSmrgmvprog="${MVPROG-mv}"
5408f3b10eSmrgcpprog="${CPPROG-cp}"
5508f3b10eSmrgchmodprog="${CHMODPROG-chmod}"
5608f3b10eSmrgchownprog="${CHOWNPROG-chown}"
5708f3b10eSmrgchgrpprog="${CHGRPPROG-chgrp}"
5808f3b10eSmrgstripprog="${STRIPPROG-strip}"
5908f3b10eSmrgrmprog="${RMPROG-rm}"
6008f3b10eSmrgmkdirprog="${MKDIRPROG-mkdir}"
6108f3b10eSmrg
6208f3b10eSmrgtransformbasename=""
6308f3b10eSmrgtransform_arg=""
6408f3b10eSmrginstcmd="$mvprog"
6508f3b10eSmrgchmodcmd="$chmodprog 0755"
6608f3b10eSmrgchowncmd=""
6708f3b10eSmrgchgrpcmd=""
6808f3b10eSmrgstripcmd=""
6908f3b10eSmrgrmcmd="$rmprog -f"
7008f3b10eSmrgmvcmd="$mvprog"
7108f3b10eSmrgsrc=""
7208f3b10eSmrgdst=""
7308f3b10eSmrgdir_arg=""
7408f3b10eSmrg
7508f3b10eSmrgwhile [ x"$1" != x ]; do
7608f3b10eSmrg    case $1 in
7708f3b10eSmrg	-c) instcmd=$cpprog
7808f3b10eSmrg	    shift
7908f3b10eSmrg	    continue;;
8008f3b10eSmrg
8108f3b10eSmrg	-d) dir_arg=true
8208f3b10eSmrg	    shift
8308f3b10eSmrg	    continue;;
8408f3b10eSmrg
8508f3b10eSmrg	-m) chmodcmd="$chmodprog $2"
8608f3b10eSmrg	    shift
8708f3b10eSmrg	    shift
8808f3b10eSmrg	    continue;;
8908f3b10eSmrg
9008f3b10eSmrg	-o) chowncmd="$chownprog $2"
9108f3b10eSmrg	    shift
9208f3b10eSmrg	    shift
9308f3b10eSmrg	    continue;;
9408f3b10eSmrg
9508f3b10eSmrg	-g) chgrpcmd="$chgrpprog $2"
9608f3b10eSmrg	    shift
9708f3b10eSmrg	    shift
9808f3b10eSmrg	    continue;;
9908f3b10eSmrg
10008f3b10eSmrg	-s) stripcmd=$stripprog
10108f3b10eSmrg	    shift
10208f3b10eSmrg	    continue;;
10308f3b10eSmrg
10408f3b10eSmrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
10508f3b10eSmrg	    shift
10608f3b10eSmrg	    continue;;
10708f3b10eSmrg
10808f3b10eSmrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
10908f3b10eSmrg	    shift
11008f3b10eSmrg	    continue;;
11108f3b10eSmrg
11208f3b10eSmrg	*)  if [ x"$src" = x ]
11308f3b10eSmrg	    then
11408f3b10eSmrg		src=$1
11508f3b10eSmrg	    else
11608f3b10eSmrg		# this colon is to work around a 386BSD /bin/sh bug
11708f3b10eSmrg		:
11808f3b10eSmrg		dst=$1
11908f3b10eSmrg	    fi
12008f3b10eSmrg	    shift
12108f3b10eSmrg	    continue;;
12208f3b10eSmrg    esac
12308f3b10eSmrgdone
12408f3b10eSmrg
12508f3b10eSmrgif [ x"$src" = x ]
12608f3b10eSmrgthen
12708f3b10eSmrg	echo "$0: no input file specified" >&2
12808f3b10eSmrg	exit 1
12908f3b10eSmrgelse
13008f3b10eSmrg	:
13108f3b10eSmrgfi
13208f3b10eSmrg
13308f3b10eSmrgif [ x"$dir_arg" != x ]; then
13408f3b10eSmrg	dst=$src
13508f3b10eSmrg	src=""
13608f3b10eSmrg
13708f3b10eSmrg	if [ -d "$dst" ]; then
13808f3b10eSmrg		instcmd=:
13908f3b10eSmrg		chmodcmd=""
14008f3b10eSmrg	else
14108f3b10eSmrg		instcmd=$mkdirprog
14208f3b10eSmrg	fi
14308f3b10eSmrgelse
14408f3b10eSmrg
14508f3b10eSmrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
14608f3b10eSmrg# might cause directories to be created, which would be especially bad
14708f3b10eSmrg# if $src (and thus $dsttmp) contains '*'.
14808f3b10eSmrg
14908f3b10eSmrg	if [ -f "$src" ] || [ -d "$src" ]
15008f3b10eSmrg	then
15108f3b10eSmrg		:
15208f3b10eSmrg	else
15308f3b10eSmrg		echo "$0: $src does not exist" >&2
15408f3b10eSmrg		exit 1
15508f3b10eSmrg	fi
15608f3b10eSmrg
15708f3b10eSmrg	if [ x"$dst" = x ]
15808f3b10eSmrg	then
15908f3b10eSmrg		echo "$0: no destination specified" >&2
16008f3b10eSmrg		exit 1
16108f3b10eSmrg	else
16208f3b10eSmrg		:
16308f3b10eSmrg	fi
16408f3b10eSmrg
16508f3b10eSmrg# If destination is a directory, append the input filename; if your system
16608f3b10eSmrg# does not like double slashes in filenames, you may need to add some logic
16708f3b10eSmrg
16808f3b10eSmrg	if [ -d "$dst" ]
16908f3b10eSmrg	then
17008f3b10eSmrg		dst=$dst/`basename "$src"`
17108f3b10eSmrg	else
17208f3b10eSmrg		:
17308f3b10eSmrg	fi
17408f3b10eSmrgfi
17508f3b10eSmrg
17608f3b10eSmrg## this sed command emulates the dirname command
17708f3b10eSmrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
17808f3b10eSmrg
17908f3b10eSmrg# Make sure that the destination directory exists.
18008f3b10eSmrg#  this part is taken from Noah Friedman's mkinstalldirs script
18108f3b10eSmrg
18208f3b10eSmrg# Skip lots of stat calls in the usual case.
18308f3b10eSmrgif [ ! -d "$dstdir" ]; then
18408f3b10eSmrgdefaultIFS='
18508f3b10eSmrg	'
18608f3b10eSmrgIFS="${IFS-$defaultIFS}"
18708f3b10eSmrg
18808f3b10eSmrgoIFS=$IFS
18908f3b10eSmrg# Some sh's can't handle IFS=/ for some reason.
19008f3b10eSmrgIFS='%'
19108f3b10eSmrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
19208f3b10eSmrgIFS=$oIFS
19308f3b10eSmrg
19408f3b10eSmrgpathcomp=''
19508f3b10eSmrg
19608f3b10eSmrgwhile [ $# -ne 0 ] ; do
19708f3b10eSmrg	pathcomp=$pathcomp$1
19808f3b10eSmrg	shift
19908f3b10eSmrg
20008f3b10eSmrg	if [ ! -d "$pathcomp" ] ;
20108f3b10eSmrg        then
20208f3b10eSmrg		$mkdirprog "$pathcomp"
20308f3b10eSmrg	else
20408f3b10eSmrg		:
20508f3b10eSmrg	fi
20608f3b10eSmrg
20708f3b10eSmrg	pathcomp=$pathcomp/
20808f3b10eSmrgdone
20908f3b10eSmrgfi
21008f3b10eSmrg
21108f3b10eSmrgif [ x"$dir_arg" != x ]
21208f3b10eSmrgthen
21308f3b10eSmrg	$doit $instcmd "$dst" &&
21408f3b10eSmrg
21508f3b10eSmrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
21608f3b10eSmrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
21708f3b10eSmrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
21808f3b10eSmrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
21908f3b10eSmrgelse
22008f3b10eSmrg
22108f3b10eSmrg# If we're going to rename the final executable, determine the name now.
22208f3b10eSmrg
22308f3b10eSmrg	if [ x"$transformarg" = x ]
22408f3b10eSmrg	then
22508f3b10eSmrg		dstfile=`basename "$dst"`
22608f3b10eSmrg	else
22708f3b10eSmrg		dstfile=`basename "$dst" $transformbasename |
22808f3b10eSmrg			sed $transformarg`$transformbasename
22908f3b10eSmrg	fi
23008f3b10eSmrg
23108f3b10eSmrg# don't allow the sed command to completely eliminate the filename
23208f3b10eSmrg
23308f3b10eSmrg	if [ x"$dstfile" = x ]
23408f3b10eSmrg	then
23508f3b10eSmrg		dstfile=`basename "$dst"`
23608f3b10eSmrg	else
23708f3b10eSmrg		:
23808f3b10eSmrg	fi
23908f3b10eSmrg
24008f3b10eSmrg# Make a couple of temp file names in the proper directory.
24108f3b10eSmrg
24208f3b10eSmrg	dsttmp=$dstdir/_inst.$$_
24308f3b10eSmrg	rmtmp=$dstdir/_rm.$$_
24408f3b10eSmrg
24508f3b10eSmrg# Trap to clean up temp files at exit.
24608f3b10eSmrg
24708f3b10eSmrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
24808f3b10eSmrg	trap '(exit $?); exit' 1 2 13 15
24908f3b10eSmrg
25008f3b10eSmrg# Move or copy the file name to the temp name
25108f3b10eSmrg
25208f3b10eSmrg	$doit $instcmd "$src" "$dsttmp" &&
25308f3b10eSmrg
25408f3b10eSmrg# and set any options; do chmod last to preserve setuid bits
25508f3b10eSmrg
25608f3b10eSmrg# If any of these fail, we abort the whole thing.  If we want to
25708f3b10eSmrg# ignore errors from any of these, just make sure not to ignore
25808f3b10eSmrg# errors from the above "$doit $instcmd $src $dsttmp" command.
25908f3b10eSmrg
26008f3b10eSmrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
26108f3b10eSmrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
26208f3b10eSmrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
26308f3b10eSmrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
26408f3b10eSmrg
26508f3b10eSmrg# Now remove or move aside any old file at destination location.  We try this
26608f3b10eSmrg# two ways since rm can't unlink itself on some systems and the destination
26708f3b10eSmrg# file might be busy for other reasons.  In this case, the final cleanup
26808f3b10eSmrg# might fail but the new file should still install successfully.
26908f3b10eSmrg
27008f3b10eSmrg{
27108f3b10eSmrg	if [ -f "$dstdir/$dstfile" ]
27208f3b10eSmrg	then
27308f3b10eSmrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
27408f3b10eSmrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
27508f3b10eSmrg		{
27608f3b10eSmrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
27708f3b10eSmrg		  (exit 1); exit
27808f3b10eSmrg		}
27908f3b10eSmrg	else
28008f3b10eSmrg		:
28108f3b10eSmrg	fi
28208f3b10eSmrg} &&
28308f3b10eSmrg
28408f3b10eSmrg# Now rename the file to the real destination.
28508f3b10eSmrg
28608f3b10eSmrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
28708f3b10eSmrg
28808f3b10eSmrgfi &&
28908f3b10eSmrg
29008f3b10eSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
29108f3b10eSmrg
29208f3b10eSmrg{
29308f3b10eSmrg	(exit 0); exit
29408f3b10eSmrg}
295