install-sh revision 67f05d30
167f05d30Smrg#!/bin/sh
267f05d30Smrg#
367f05d30Smrg# install - install a program, script, or datafile
467f05d30Smrg#
567f05d30Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
667f05d30Smrg# later released in X11R6 (xc/config/util/install.sh) with the
767f05d30Smrg# following copyright and license.
867f05d30Smrg#
967f05d30Smrg# Copyright (C) 1994 X Consortium
1067f05d30Smrg#
1167f05d30Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1267f05d30Smrg# of this software and associated documentation files (the "Software"), to
1367f05d30Smrg# deal in the Software without restriction, including without limitation the
1467f05d30Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1567f05d30Smrg# sell copies of the Software, and to permit persons to whom the Software is
1667f05d30Smrg# furnished to do so, subject to the following conditions:
1767f05d30Smrg#
1867f05d30Smrg# The above copyright notice and this permission notice shall be included in
1967f05d30Smrg# all copies or substantial portions of the Software.
2067f05d30Smrg#
2167f05d30Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2267f05d30Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2367f05d30Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2467f05d30Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2567f05d30Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2667f05d30Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2767f05d30Smrg#
2867f05d30Smrg# Except as contained in this notice, the name of the X Consortium shall not
2967f05d30Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3067f05d30Smrg# ings in this Software without prior written authorization from the X Consor-
3167f05d30Smrg# tium.
3267f05d30Smrg#
3367f05d30Smrg#
3467f05d30Smrg# FSF changes to this file are in the public domain.
3567f05d30Smrg#
3667f05d30Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3767f05d30Smrg# `make' implicit rules from creating a file called install from it
3867f05d30Smrg# when there is no Makefile.
3967f05d30Smrg#
4067f05d30Smrg# This script is compatible with the BSD install script, but was written
4167f05d30Smrg# from scratch.  It can only install one file at a time, a restriction
4267f05d30Smrg# shared with many OS's install programs.
4367f05d30Smrg
4467f05d30Smrg
4567f05d30Smrg# set DOITPROG to echo to test this script
4667f05d30Smrg
4767f05d30Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4867f05d30Smrgdoit="${DOITPROG-}"
4967f05d30Smrg
5067f05d30Smrg
5167f05d30Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
5267f05d30Smrg
5367f05d30Smrgmvprog="${MVPROG-mv}"
5467f05d30Smrgcpprog="${CPPROG-cp}"
5567f05d30Smrgchmodprog="${CHMODPROG-chmod}"
5667f05d30Smrgchownprog="${CHOWNPROG-chown}"
5767f05d30Smrgchgrpprog="${CHGRPPROG-chgrp}"
5867f05d30Smrgstripprog="${STRIPPROG-strip}"
5967f05d30Smrgrmprog="${RMPROG-rm}"
6067f05d30Smrgmkdirprog="${MKDIRPROG-mkdir}"
6167f05d30Smrg
6267f05d30Smrgtransformbasename=""
6367f05d30Smrgtransform_arg=""
6467f05d30Smrginstcmd="$mvprog"
6567f05d30Smrgchmodcmd="$chmodprog 0755"
6667f05d30Smrgchowncmd=""
6767f05d30Smrgchgrpcmd=""
6867f05d30Smrgstripcmd=""
6967f05d30Smrgrmcmd="$rmprog -f"
7067f05d30Smrgmvcmd="$mvprog"
7167f05d30Smrgsrc=""
7267f05d30Smrgdst=""
7367f05d30Smrgdir_arg=""
7467f05d30Smrg
7567f05d30Smrgwhile [ x"$1" != x ]; do
7667f05d30Smrg    case $1 in
7767f05d30Smrg	-c) instcmd=$cpprog
7867f05d30Smrg	    shift
7967f05d30Smrg	    continue;;
8067f05d30Smrg
8167f05d30Smrg	-d) dir_arg=true
8267f05d30Smrg	    shift
8367f05d30Smrg	    continue;;
8467f05d30Smrg
8567f05d30Smrg	-m) chmodcmd="$chmodprog $2"
8667f05d30Smrg	    shift
8767f05d30Smrg	    shift
8867f05d30Smrg	    continue;;
8967f05d30Smrg
9067f05d30Smrg	-o) chowncmd="$chownprog $2"
9167f05d30Smrg	    shift
9267f05d30Smrg	    shift
9367f05d30Smrg	    continue;;
9467f05d30Smrg
9567f05d30Smrg	-g) chgrpcmd="$chgrpprog $2"
9667f05d30Smrg	    shift
9767f05d30Smrg	    shift
9867f05d30Smrg	    continue;;
9967f05d30Smrg
10067f05d30Smrg	-s) stripcmd=$stripprog
10167f05d30Smrg	    shift
10267f05d30Smrg	    continue;;
10367f05d30Smrg
10467f05d30Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
10567f05d30Smrg	    shift
10667f05d30Smrg	    continue;;
10767f05d30Smrg
10867f05d30Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
10967f05d30Smrg	    shift
11067f05d30Smrg	    continue;;
11167f05d30Smrg
11267f05d30Smrg	*)  if [ x"$src" = x ]
11367f05d30Smrg	    then
11467f05d30Smrg		src=$1
11567f05d30Smrg	    else
11667f05d30Smrg		# this colon is to work around a 386BSD /bin/sh bug
11767f05d30Smrg		:
11867f05d30Smrg		dst=$1
11967f05d30Smrg	    fi
12067f05d30Smrg	    shift
12167f05d30Smrg	    continue;;
12267f05d30Smrg    esac
12367f05d30Smrgdone
12467f05d30Smrg
12567f05d30Smrgif [ x"$src" = x ]
12667f05d30Smrgthen
12767f05d30Smrg	echo "$0: no input file specified" >&2
12867f05d30Smrg	exit 1
12967f05d30Smrgelse
13067f05d30Smrg	:
13167f05d30Smrgfi
13267f05d30Smrg
13367f05d30Smrgif [ x"$dir_arg" != x ]; then
13467f05d30Smrg	dst=$src
13567f05d30Smrg	src=""
13667f05d30Smrg
13767f05d30Smrg	if [ -d "$dst" ]; then
13867f05d30Smrg		instcmd=:
13967f05d30Smrg		chmodcmd=""
14067f05d30Smrg	else
14167f05d30Smrg		instcmd=$mkdirprog
14267f05d30Smrg	fi
14367f05d30Smrgelse
14467f05d30Smrg
14567f05d30Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
14667f05d30Smrg# might cause directories to be created, which would be especially bad
14767f05d30Smrg# if $src (and thus $dsttmp) contains '*'.
14867f05d30Smrg
14967f05d30Smrg	if [ -f "$src" ] || [ -d "$src" ]
15067f05d30Smrg	then
15167f05d30Smrg		:
15267f05d30Smrg	else
15367f05d30Smrg		echo "$0: $src does not exist" >&2
15467f05d30Smrg		exit 1
15567f05d30Smrg	fi
15667f05d30Smrg
15767f05d30Smrg	if [ x"$dst" = x ]
15867f05d30Smrg	then
15967f05d30Smrg		echo "$0: no destination specified" >&2
16067f05d30Smrg		exit 1
16167f05d30Smrg	else
16267f05d30Smrg		:
16367f05d30Smrg	fi
16467f05d30Smrg
16567f05d30Smrg# If destination is a directory, append the input filename; if your system
16667f05d30Smrg# does not like double slashes in filenames, you may need to add some logic
16767f05d30Smrg
16867f05d30Smrg	if [ -d "$dst" ]
16967f05d30Smrg	then
17067f05d30Smrg		dst=$dst/`basename "$src"`
17167f05d30Smrg	else
17267f05d30Smrg		:
17367f05d30Smrg	fi
17467f05d30Smrgfi
17567f05d30Smrg
17667f05d30Smrg## this sed command emulates the dirname command
17767f05d30Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
17867f05d30Smrg
17967f05d30Smrg# Make sure that the destination directory exists.
18067f05d30Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
18167f05d30Smrg
18267f05d30Smrg# Skip lots of stat calls in the usual case.
18367f05d30Smrgif [ ! -d "$dstdir" ]; then
18467f05d30SmrgdefaultIFS='
18567f05d30Smrg	'
18667f05d30SmrgIFS="${IFS-$defaultIFS}"
18767f05d30Smrg
18867f05d30SmrgoIFS=$IFS
18967f05d30Smrg# Some sh's can't handle IFS=/ for some reason.
19067f05d30SmrgIFS='%'
19167f05d30Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
19267f05d30SmrgIFS=$oIFS
19367f05d30Smrg
19467f05d30Smrgpathcomp=''
19567f05d30Smrg
19667f05d30Smrgwhile [ $# -ne 0 ] ; do
19767f05d30Smrg	pathcomp=$pathcomp$1
19867f05d30Smrg	shift
19967f05d30Smrg
20067f05d30Smrg	if [ ! -d "$pathcomp" ] ;
20167f05d30Smrg        then
20267f05d30Smrg		$mkdirprog "$pathcomp"
20367f05d30Smrg	else
20467f05d30Smrg		:
20567f05d30Smrg	fi
20667f05d30Smrg
20767f05d30Smrg	pathcomp=$pathcomp/
20867f05d30Smrgdone
20967f05d30Smrgfi
21067f05d30Smrg
21167f05d30Smrgif [ x"$dir_arg" != x ]
21267f05d30Smrgthen
21367f05d30Smrg	$doit $instcmd "$dst" &&
21467f05d30Smrg
21567f05d30Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
21667f05d30Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
21767f05d30Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
21867f05d30Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
21967f05d30Smrgelse
22067f05d30Smrg
22167f05d30Smrg# If we're going to rename the final executable, determine the name now.
22267f05d30Smrg
22367f05d30Smrg	if [ x"$transformarg" = x ]
22467f05d30Smrg	then
22567f05d30Smrg		dstfile=`basename "$dst"`
22667f05d30Smrg	else
22767f05d30Smrg		dstfile=`basename "$dst" $transformbasename |
22867f05d30Smrg			sed $transformarg`$transformbasename
22967f05d30Smrg	fi
23067f05d30Smrg
23167f05d30Smrg# don't allow the sed command to completely eliminate the filename
23267f05d30Smrg
23367f05d30Smrg	if [ x"$dstfile" = x ]
23467f05d30Smrg	then
23567f05d30Smrg		dstfile=`basename "$dst"`
23667f05d30Smrg	else
23767f05d30Smrg		:
23867f05d30Smrg	fi
23967f05d30Smrg
24067f05d30Smrg# Make a couple of temp file names in the proper directory.
24167f05d30Smrg
24267f05d30Smrg	dsttmp=$dstdir/_inst.$$_
24367f05d30Smrg	rmtmp=$dstdir/_rm.$$_
24467f05d30Smrg
24567f05d30Smrg# Trap to clean up temp files at exit.
24667f05d30Smrg
24767f05d30Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
24867f05d30Smrg	trap '(exit $?); exit' 1 2 13 15
24967f05d30Smrg
25067f05d30Smrg# Move or copy the file name to the temp name
25167f05d30Smrg
25267f05d30Smrg	$doit $instcmd "$src" "$dsttmp" &&
25367f05d30Smrg
25467f05d30Smrg# and set any options; do chmod last to preserve setuid bits
25567f05d30Smrg
25667f05d30Smrg# If any of these fail, we abort the whole thing.  If we want to
25767f05d30Smrg# ignore errors from any of these, just make sure not to ignore
25867f05d30Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
25967f05d30Smrg
26067f05d30Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
26167f05d30Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
26267f05d30Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
26367f05d30Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
26467f05d30Smrg
26567f05d30Smrg# Now remove or move aside any old file at destination location.  We try this
26667f05d30Smrg# two ways since rm can't unlink itself on some systems and the destination
26767f05d30Smrg# file might be busy for other reasons.  In this case, the final cleanup
26867f05d30Smrg# might fail but the new file should still install successfully.
26967f05d30Smrg
27067f05d30Smrg{
27167f05d30Smrg	if [ -f "$dstdir/$dstfile" ]
27267f05d30Smrg	then
27367f05d30Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
27467f05d30Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
27567f05d30Smrg		{
27667f05d30Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
27767f05d30Smrg		  (exit 1); exit
27867f05d30Smrg		}
27967f05d30Smrg	else
28067f05d30Smrg		:
28167f05d30Smrg	fi
28267f05d30Smrg} &&
28367f05d30Smrg
28467f05d30Smrg# Now rename the file to the real destination.
28567f05d30Smrg
28667f05d30Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
28767f05d30Smrg
28867f05d30Smrgfi &&
28967f05d30Smrg
29067f05d30Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
29167f05d30Smrg
29267f05d30Smrg{
29367f05d30Smrg	(exit 0); exit
29467f05d30Smrg}
295