install-sh revision 56f6b22b
156f6b22bSmrg#!/bin/sh
256f6b22bSmrg#
356f6b22bSmrg# install - install a program, script, or datafile
456f6b22bSmrg#
556f6b22bSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
656f6b22bSmrg# later released in X11R6 (xc/config/util/install.sh) with the
756f6b22bSmrg# following copyright and license.
856f6b22bSmrg#
956f6b22bSmrg# Copyright (C) 1994 X Consortium
1056f6b22bSmrg#
1156f6b22bSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1256f6b22bSmrg# of this software and associated documentation files (the "Software"), to
1356f6b22bSmrg# deal in the Software without restriction, including without limitation the
1456f6b22bSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1556f6b22bSmrg# sell copies of the Software, and to permit persons to whom the Software is
1656f6b22bSmrg# furnished to do so, subject to the following conditions:
1756f6b22bSmrg#
1856f6b22bSmrg# The above copyright notice and this permission notice shall be included in
1956f6b22bSmrg# all copies or substantial portions of the Software.
2056f6b22bSmrg#
2156f6b22bSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2256f6b22bSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2356f6b22bSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2456f6b22bSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2556f6b22bSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2656f6b22bSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2756f6b22bSmrg#
2856f6b22bSmrg# Except as contained in this notice, the name of the X Consortium shall not
2956f6b22bSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3056f6b22bSmrg# ings in this Software without prior written authorization from the X Consor-
3156f6b22bSmrg# tium.
3256f6b22bSmrg#
3356f6b22bSmrg#
3456f6b22bSmrg# FSF changes to this file are in the public domain.
3556f6b22bSmrg#
3656f6b22bSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3756f6b22bSmrg# `make' implicit rules from creating a file called install from it
3856f6b22bSmrg# when there is no Makefile.
3956f6b22bSmrg#
4056f6b22bSmrg# This script is compatible with the BSD install script, but was written
4156f6b22bSmrg# from scratch.  It can only install one file at a time, a restriction
4256f6b22bSmrg# shared with many OS's install programs.
4356f6b22bSmrg
4456f6b22bSmrg
4556f6b22bSmrg# set DOITPROG to echo to test this script
4656f6b22bSmrg
4756f6b22bSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4856f6b22bSmrgdoit="${DOITPROG-}"
4956f6b22bSmrg
5056f6b22bSmrg
5156f6b22bSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
5256f6b22bSmrg
5356f6b22bSmrgmvprog="${MVPROG-mv}"
5456f6b22bSmrgcpprog="${CPPROG-cp}"
5556f6b22bSmrgchmodprog="${CHMODPROG-chmod}"
5656f6b22bSmrgchownprog="${CHOWNPROG-chown}"
5756f6b22bSmrgchgrpprog="${CHGRPPROG-chgrp}"
5856f6b22bSmrgstripprog="${STRIPPROG-strip}"
5956f6b22bSmrgrmprog="${RMPROG-rm}"
6056f6b22bSmrgmkdirprog="${MKDIRPROG-mkdir}"
6156f6b22bSmrg
6256f6b22bSmrgtransformbasename=""
6356f6b22bSmrgtransform_arg=""
6456f6b22bSmrginstcmd="$mvprog"
6556f6b22bSmrgchmodcmd="$chmodprog 0755"
6656f6b22bSmrgchowncmd=""
6756f6b22bSmrgchgrpcmd=""
6856f6b22bSmrgstripcmd=""
6956f6b22bSmrgrmcmd="$rmprog -f"
7056f6b22bSmrgmvcmd="$mvprog"
7156f6b22bSmrgsrc=""
7256f6b22bSmrgdst=""
7356f6b22bSmrgdir_arg=""
7456f6b22bSmrg
7556f6b22bSmrgwhile [ x"$1" != x ]; do
7656f6b22bSmrg    case $1 in
7756f6b22bSmrg	-c) instcmd=$cpprog
7856f6b22bSmrg	    shift
7956f6b22bSmrg	    continue;;
8056f6b22bSmrg
8156f6b22bSmrg	-d) dir_arg=true
8256f6b22bSmrg	    shift
8356f6b22bSmrg	    continue;;
8456f6b22bSmrg
8556f6b22bSmrg	-m) chmodcmd="$chmodprog $2"
8656f6b22bSmrg	    shift
8756f6b22bSmrg	    shift
8856f6b22bSmrg	    continue;;
8956f6b22bSmrg
9056f6b22bSmrg	-o) chowncmd="$chownprog $2"
9156f6b22bSmrg	    shift
9256f6b22bSmrg	    shift
9356f6b22bSmrg	    continue;;
9456f6b22bSmrg
9556f6b22bSmrg	-g) chgrpcmd="$chgrpprog $2"
9656f6b22bSmrg	    shift
9756f6b22bSmrg	    shift
9856f6b22bSmrg	    continue;;
9956f6b22bSmrg
10056f6b22bSmrg	-s) stripcmd=$stripprog
10156f6b22bSmrg	    shift
10256f6b22bSmrg	    continue;;
10356f6b22bSmrg
10456f6b22bSmrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
10556f6b22bSmrg	    shift
10656f6b22bSmrg	    continue;;
10756f6b22bSmrg
10856f6b22bSmrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
10956f6b22bSmrg	    shift
11056f6b22bSmrg	    continue;;
11156f6b22bSmrg
11256f6b22bSmrg	*)  if [ x"$src" = x ]
11356f6b22bSmrg	    then
11456f6b22bSmrg		src=$1
11556f6b22bSmrg	    else
11656f6b22bSmrg		# this colon is to work around a 386BSD /bin/sh bug
11756f6b22bSmrg		:
11856f6b22bSmrg		dst=$1
11956f6b22bSmrg	    fi
12056f6b22bSmrg	    shift
12156f6b22bSmrg	    continue;;
12256f6b22bSmrg    esac
12356f6b22bSmrgdone
12456f6b22bSmrg
12556f6b22bSmrgif [ x"$src" = x ]
12656f6b22bSmrgthen
12756f6b22bSmrg	echo "$0: no input file specified" >&2
12856f6b22bSmrg	exit 1
12956f6b22bSmrgelse
13056f6b22bSmrg	:
13156f6b22bSmrgfi
13256f6b22bSmrg
13356f6b22bSmrgif [ x"$dir_arg" != x ]; then
13456f6b22bSmrg	dst=$src
13556f6b22bSmrg	src=""
13656f6b22bSmrg
13756f6b22bSmrg	if [ -d "$dst" ]; then
13856f6b22bSmrg		instcmd=:
13956f6b22bSmrg		chmodcmd=""
14056f6b22bSmrg	else
14156f6b22bSmrg		instcmd=$mkdirprog
14256f6b22bSmrg	fi
14356f6b22bSmrgelse
14456f6b22bSmrg
14556f6b22bSmrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
14656f6b22bSmrg# might cause directories to be created, which would be especially bad
14756f6b22bSmrg# if $src (and thus $dsttmp) contains '*'.
14856f6b22bSmrg
14956f6b22bSmrg	if [ -f "$src" ] || [ -d "$src" ]
15056f6b22bSmrg	then
15156f6b22bSmrg		:
15256f6b22bSmrg	else
15356f6b22bSmrg		echo "$0: $src does not exist" >&2
15456f6b22bSmrg		exit 1
15556f6b22bSmrg	fi
15656f6b22bSmrg
15756f6b22bSmrg	if [ x"$dst" = x ]
15856f6b22bSmrg	then
15956f6b22bSmrg		echo "$0: no destination specified" >&2
16056f6b22bSmrg		exit 1
16156f6b22bSmrg	else
16256f6b22bSmrg		:
16356f6b22bSmrg	fi
16456f6b22bSmrg
16556f6b22bSmrg# If destination is a directory, append the input filename; if your system
16656f6b22bSmrg# does not like double slashes in filenames, you may need to add some logic
16756f6b22bSmrg
16856f6b22bSmrg	if [ -d "$dst" ]
16956f6b22bSmrg	then
17056f6b22bSmrg		dst=$dst/`basename "$src"`
17156f6b22bSmrg	else
17256f6b22bSmrg		:
17356f6b22bSmrg	fi
17456f6b22bSmrgfi
17556f6b22bSmrg
17656f6b22bSmrg## this sed command emulates the dirname command
17756f6b22bSmrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
17856f6b22bSmrg
17956f6b22bSmrg# Make sure that the destination directory exists.
18056f6b22bSmrg#  this part is taken from Noah Friedman's mkinstalldirs script
18156f6b22bSmrg
18256f6b22bSmrg# Skip lots of stat calls in the usual case.
18356f6b22bSmrgif [ ! -d "$dstdir" ]; then
18456f6b22bSmrgdefaultIFS='
18556f6b22bSmrg	'
18656f6b22bSmrgIFS="${IFS-$defaultIFS}"
18756f6b22bSmrg
18856f6b22bSmrgoIFS=$IFS
18956f6b22bSmrg# Some sh's can't handle IFS=/ for some reason.
19056f6b22bSmrgIFS='%'
19156f6b22bSmrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
19256f6b22bSmrgIFS=$oIFS
19356f6b22bSmrg
19456f6b22bSmrgpathcomp=''
19556f6b22bSmrg
19656f6b22bSmrgwhile [ $# -ne 0 ] ; do
19756f6b22bSmrg	pathcomp=$pathcomp$1
19856f6b22bSmrg	shift
19956f6b22bSmrg
20056f6b22bSmrg	if [ ! -d "$pathcomp" ] ;
20156f6b22bSmrg        then
20256f6b22bSmrg		$mkdirprog "$pathcomp"
20356f6b22bSmrg	else
20456f6b22bSmrg		:
20556f6b22bSmrg	fi
20656f6b22bSmrg
20756f6b22bSmrg	pathcomp=$pathcomp/
20856f6b22bSmrgdone
20956f6b22bSmrgfi
21056f6b22bSmrg
21156f6b22bSmrgif [ x"$dir_arg" != x ]
21256f6b22bSmrgthen
21356f6b22bSmrg	$doit $instcmd "$dst" &&
21456f6b22bSmrg
21556f6b22bSmrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
21656f6b22bSmrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
21756f6b22bSmrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
21856f6b22bSmrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
21956f6b22bSmrgelse
22056f6b22bSmrg
22156f6b22bSmrg# If we're going to rename the final executable, determine the name now.
22256f6b22bSmrg
22356f6b22bSmrg	if [ x"$transformarg" = x ]
22456f6b22bSmrg	then
22556f6b22bSmrg		dstfile=`basename "$dst"`
22656f6b22bSmrg	else
22756f6b22bSmrg		dstfile=`basename "$dst" $transformbasename |
22856f6b22bSmrg			sed $transformarg`$transformbasename
22956f6b22bSmrg	fi
23056f6b22bSmrg
23156f6b22bSmrg# don't allow the sed command to completely eliminate the filename
23256f6b22bSmrg
23356f6b22bSmrg	if [ x"$dstfile" = x ]
23456f6b22bSmrg	then
23556f6b22bSmrg		dstfile=`basename "$dst"`
23656f6b22bSmrg	else
23756f6b22bSmrg		:
23856f6b22bSmrg	fi
23956f6b22bSmrg
24056f6b22bSmrg# Make a couple of temp file names in the proper directory.
24156f6b22bSmrg
24256f6b22bSmrg	dsttmp=$dstdir/_inst.$$_
24356f6b22bSmrg	rmtmp=$dstdir/_rm.$$_
24456f6b22bSmrg
24556f6b22bSmrg# Trap to clean up temp files at exit.
24656f6b22bSmrg
24756f6b22bSmrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
24856f6b22bSmrg	trap '(exit $?); exit' 1 2 13 15
24956f6b22bSmrg
25056f6b22bSmrg# Move or copy the file name to the temp name
25156f6b22bSmrg
25256f6b22bSmrg	$doit $instcmd "$src" "$dsttmp" &&
25356f6b22bSmrg
25456f6b22bSmrg# and set any options; do chmod last to preserve setuid bits
25556f6b22bSmrg
25656f6b22bSmrg# If any of these fail, we abort the whole thing.  If we want to
25756f6b22bSmrg# ignore errors from any of these, just make sure not to ignore
25856f6b22bSmrg# errors from the above "$doit $instcmd $src $dsttmp" command.
25956f6b22bSmrg
26056f6b22bSmrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
26156f6b22bSmrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
26256f6b22bSmrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
26356f6b22bSmrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
26456f6b22bSmrg
26556f6b22bSmrg# Now remove or move aside any old file at destination location.  We try this
26656f6b22bSmrg# two ways since rm can't unlink itself on some systems and the destination
26756f6b22bSmrg# file might be busy for other reasons.  In this case, the final cleanup
26856f6b22bSmrg# might fail but the new file should still install successfully.
26956f6b22bSmrg
27056f6b22bSmrg{
27156f6b22bSmrg	if [ -f "$dstdir/$dstfile" ]
27256f6b22bSmrg	then
27356f6b22bSmrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
27456f6b22bSmrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
27556f6b22bSmrg		{
27656f6b22bSmrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
27756f6b22bSmrg		  (exit 1); exit
27856f6b22bSmrg		}
27956f6b22bSmrg	else
28056f6b22bSmrg		:
28156f6b22bSmrg	fi
28256f6b22bSmrg} &&
28356f6b22bSmrg
28456f6b22bSmrg# Now rename the file to the real destination.
28556f6b22bSmrg
28656f6b22bSmrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
28756f6b22bSmrg
28856f6b22bSmrgfi &&
28956f6b22bSmrg
29056f6b22bSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
29156f6b22bSmrg
29256f6b22bSmrg{
29356f6b22bSmrg	(exit 0); exit
29456f6b22bSmrg}
295