install-sh revision 130561
154359Sroberto#!/bin/sh
254359Sroberto#
354359Sroberto# install - install a program, script, or datafile
454359Sroberto#
554359Sroberto# This originates from X11R5 (mit/util/scripts/install.sh), which was
654359Sroberto# later released in X11R6 (xc/config/util/install.sh) with the
754359Sroberto# following copyright and license.
854359Sroberto#
954359Sroberto# Copyright (C) 1994 X Consortium
10132451Sroberto#
11132451Sroberto# Permission is hereby granted, free of charge, to any person obtaining a copy
12132451Sroberto# of this software and associated documentation files (the "Software"), to
13132451Sroberto# deal in the Software without restriction, including without limitation the
14132451Sroberto# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1554359Sroberto# sell copies of the Software, and to permit persons to whom the Software is
1654359Sroberto# furnished to do so, subject to the following conditions:
17182007Sroberto#
18182007Sroberto# The above copyright notice and this permission notice shall be included in
19182007Sroberto# all copies or substantial portions of the Software.
2054359Sroberto#
2154359Sroberto# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2282498Sroberto# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2354359Sroberto# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2454359Sroberto# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2554359Sroberto# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2682498Sroberto# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27182007Sroberto#
2882498Sroberto# Except as contained in this notice, the name of the X Consortium shall not
2982498Sroberto# be used in advertising or otherwise to promote the sale, use or other deal-
3054359Sroberto# ings in this Software without prior written authorization from the X Consor-
3154359Sroberto# tium.
3254359Sroberto#
3354359Sroberto#
3454359Sroberto# FSF changes to this file are in the public domain.
3554359Sroberto#
3654359Sroberto# Calling this script install-sh is preferred over install.sh, to prevent
3754359Sroberto# `make' implicit rules from creating a file called install from it
3882498Sroberto# when there is no Makefile.
3982498Sroberto#
4082498Sroberto# This script is compatible with the BSD install script, but was written
4182498Sroberto# from scratch.  It can only install one file at a time, a restriction
4282498Sroberto# shared with many OS's install programs.
4382498Sroberto
4482498Sroberto
4582498Sroberto# set DOITPROG to echo to test this script
4682498Sroberto
4782498Sroberto# Don't use :- since 4.3BSD and earlier shells don't like it.
4882498Srobertodoit="${DOITPROG-}"
4982498Sroberto
5082498Sroberto
5182498Sroberto# put in absolute paths if you don't have them in your path; or use env. vars.
5282498Sroberto
5382498Srobertomvprog="${MVPROG-mv}"
5482498Srobertocpprog="${CPPROG-cp}"
5554359Srobertochmodprog="${CHMODPROG-chmod}"
5654359Srobertochownprog="${CHOWNPROG-chown}"
5754359Srobertochgrpprog="${CHGRPPROG-chgrp}"
5854359Srobertostripprog="${STRIPPROG-strip}"
5954359Srobertormprog="${RMPROG-rm}"
6056746Srobertomkdirprog="${MKDIRPROG-mkdir}"
6156746Sroberto
6256746Srobertotransformbasename=""
6356746Srobertotransform_arg=""
6456746Srobertoinstcmd="$mvprog"
6554359Srobertochmodcmd="$chmodprog 0755"
6654359Srobertochowncmd=""
6782498Srobertochgrpcmd=""
6854359Srobertostripcmd=""
6954359Srobertormcmd="$rmprog -f"
7082498Srobertomvcmd="$mvprog"
7182498Srobertosrc=""
7254359Srobertodst=""
7354359Srobertodir_arg=""
7454359Sroberto
7554359Srobertowhile [ x"$1" != x ]; do
7654359Sroberto    case $1 in
7754359Sroberto	-c) instcmd=$cpprog
7854359Sroberto	    shift
7954359Sroberto	    continue;;
8054359Sroberto
8154359Sroberto	-d) dir_arg=true
8254359Sroberto	    shift
8354359Sroberto	    continue;;
8454359Sroberto
8554359Sroberto	-m) chmodcmd="$chmodprog $2"
8654359Sroberto	    shift
8754359Sroberto	    shift
8854359Sroberto	    continue;;
8982498Sroberto
9082498Sroberto	-o) chowncmd="$chownprog $2"
9182498Sroberto	    shift
9282498Sroberto	    shift
9382498Sroberto	    continue;;
9482498Sroberto
9554359Sroberto	-g) chgrpcmd="$chgrpprog $2"
9654359Sroberto	    shift
9754359Sroberto	    shift
9854359Sroberto	    continue;;
9954359Sroberto
10054359Sroberto	-s) stripcmd=$stripprog
10154359Sroberto	    shift
10282498Sroberto	    continue;;
10382498Sroberto
10482498Sroberto	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
10582498Sroberto	    shift
10682498Sroberto	    continue;;
10782498Sroberto
10854359Sroberto	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
10954359Sroberto	    shift
11054359Sroberto	    continue;;
11154359Sroberto
11254359Sroberto	*)  if [ x"$src" = x ]
11354359Sroberto	    then
11454359Sroberto		src=$1
11554359Sroberto	    else
11654359Sroberto		# this colon is to work around a 386BSD /bin/sh bug
11754359Sroberto		:
11854359Sroberto		dst=$1
11954359Sroberto	    fi
12082498Sroberto	    shift
12182498Sroberto	    continue;;
12282498Sroberto    esac
12382498Srobertodone
12482498Sroberto
12554359Srobertoif [ x"$src" = x ]
12654359Srobertothen
12754359Sroberto	echo "$0: no input file specified" >&2
12854359Sroberto	exit 1
12954359Srobertoelse
13054359Sroberto	:
13154359Srobertofi
13254359Sroberto
13354359Srobertoif [ x"$dir_arg" != x ]; then
13454359Sroberto	dst=$src
13554359Sroberto	src=""
13654359Sroberto
13754359Sroberto	if [ -d "$dst" ]; then
13854359Sroberto		instcmd=:
13954359Sroberto		chmodcmd=""
14054359Sroberto	else
14154359Sroberto		instcmd=$mkdirprog
14254359Sroberto	fi
14354359Srobertoelse
14454359Sroberto
14554359Sroberto# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
14654359Sroberto# might cause directories to be created, which would be especially bad
14754359Sroberto# if $src (and thus $dsttmp) contains '*'.
14856746Sroberto
149132451Sroberto	if [ -f "$src" ] || [ -d "$src" ]
150182007Sroberto	then
151182007Sroberto		:
152182007Sroberto	else
153182007Sroberto		echo "$0: $src does not exist" >&2
154182007Sroberto		exit 1
155182007Sroberto	fi
156182007Sroberto
157182007Sroberto	if [ x"$dst" = x ]
158182007Sroberto	then
159182007Sroberto		echo "$0: no destination specified" >&2
160182007Sroberto		exit 1
161182007Sroberto	else
162182007Sroberto		:
163182007Sroberto	fi
164182007Sroberto
165182007Sroberto# If destination is a directory, append the input filename; if your system
166182007Sroberto# does not like double slashes in filenames, you may need to add some logic
167182007Sroberto
168182007Sroberto	if [ -d "$dst" ]
16954359Sroberto	then
170182007Sroberto		dst=$dst/`basename "$src"`
171182007Sroberto	else
172182007Sroberto		:
173182007Sroberto	fi
174182007Srobertofi
175182007Sroberto
176182007Sroberto## this sed command emulates the dirname command
177182007Srobertodstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
178182007Sroberto
179182007Sroberto# Make sure that the destination directory exists.
180182007Sroberto#  this part is taken from Noah Friedman's mkinstalldirs script
181182007Sroberto
182182007Sroberto# Skip lots of stat calls in the usual case.
183182007Srobertoif [ ! -d "$dstdir" ]; then
184182007SrobertodefaultIFS='
185182007Sroberto	'
186182007SrobertoIFS="${IFS-$defaultIFS}"
187182007Sroberto
188182007SrobertooIFS=$IFS
189182007Sroberto# Some sh's can't handle IFS=/ for some reason.
190182007SrobertoIFS='%'
191182007Srobertoset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
192182007SrobertoIFS=$oIFS
193182007Sroberto
194182007Srobertopathcomp=''
195182007Sroberto
196182007Srobertowhile [ $# -ne 0 ] ; do
197182007Sroberto	pathcomp=$pathcomp$1
19854359Sroberto	shift
19954359Sroberto
20054359Sroberto	if [ ! -d "$pathcomp" ] ;
201132451Sroberto        then
202132451Sroberto		$mkdirprog "$pathcomp"
20354359Sroberto	else
20454359Sroberto		:
20554359Sroberto	fi
20654359Sroberto
20754359Sroberto	pathcomp=$pathcomp/
20854359Srobertodone
20954359Srobertofi
21054359Sroberto
21154359Srobertoif [ x"$dir_arg" != x ]
21254359Srobertothen
21354359Sroberto	$doit $instcmd "$dst" &&
21454359Sroberto
21554359Sroberto	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
21654359Sroberto	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
21754359Sroberto	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
21854359Sroberto	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
21954359Srobertoelse
22054359Sroberto
22154359Sroberto# If we're going to rename the final executable, determine the name now.
22282498Sroberto
22354359Sroberto	if [ x"$transformarg" = x ]
22454359Sroberto	then
22554359Sroberto		dstfile=`basename "$dst"`
22654359Sroberto	else
22754359Sroberto		dstfile=`basename "$dst" $transformbasename |
22882498Sroberto			sed $transformarg`$transformbasename
22982498Sroberto	fi
23082498Sroberto
23182498Sroberto# don't allow the sed command to completely eliminate the filename
23282498Sroberto
23382498Sroberto	if [ x"$dstfile" = x ]
23482498Sroberto	then
23582498Sroberto		dstfile=`basename "$dst"`
23682498Sroberto	else
23782498Sroberto		:
23882498Sroberto	fi
23982498Sroberto
24082498Sroberto# Make a couple of temp file names in the proper directory.
24154359Sroberto
24282498Sroberto	dsttmp=$dstdir/#inst.$$#
24354359Sroberto	rmtmp=$dstdir/#rm.$$#
24454359Sroberto
24554359Sroberto# Trap to clean up temp files at exit.
24654359Sroberto
24754359Sroberto	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
24854359Sroberto	trap '(exit $?); exit' 1 2 13 15
24954359Sroberto
25054359Sroberto# Move or copy the file name to the temp name
25154359Sroberto
25254359Sroberto	$doit $instcmd "$src" "$dsttmp" &&
25354359Sroberto
25454359Sroberto# and set any options; do chmod last to preserve setuid bits
25554359Sroberto
25654359Sroberto# If any of these fail, we abort the whole thing.  If we want to
25754359Sroberto# ignore errors from any of these, just make sure not to ignore
25854359Sroberto# errors from the above "$doit $instcmd $src $dsttmp" command.
25982498Sroberto
26082498Sroberto	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
26182498Sroberto	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
26282498Sroberto	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
26354359Sroberto	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
26454359Sroberto
26554359Sroberto# Now remove or move aside any old file at destination location.  We try this
26654359Sroberto# two ways since rm can't unlink itself on some systems and the destination
26782498Sroberto# file might be busy for other reasons.  In this case, the final cleanup
26854359Sroberto# might fail but the new file should still install successfully.
26982498Sroberto
27082498Sroberto{
27182498Sroberto	if [ -f "$dstdir/$dstfile" ]
27282498Sroberto	then
27382498Sroberto		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
27482498Sroberto		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
27582498Sroberto		{
27682498Sroberto		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
27782498Sroberto		  (exit 1); exit
27882498Sroberto		}
27982498Sroberto	else
28082498Sroberto		:
28182498Sroberto	fi
28282498Sroberto} &&
28382498Sroberto
28482498Sroberto# Now rename the file to the real destination.
28582498Sroberto
28682498Sroberto	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
28782498Sroberto
28882498Srobertofi &&
28982498Sroberto
29082498Sroberto# The final little trick to "correctly" pass the exit status to the exit trap.
29182498Sroberto
29282498Sroberto{
29382498Sroberto	(exit 0); exit
29482498Sroberto}
29582498Sroberto