install-sh revision b1cb5b87
1b1cb5b87Smrg#!/bin/sh
2b1cb5b87Smrg#
3b1cb5b87Smrg# install - install a program, script, or datafile
4b1cb5b87Smrg#
5b1cb5b87Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
6b1cb5b87Smrg# later released in X11R6 (xc/config/util/install.sh) with the
7b1cb5b87Smrg# following copyright and license.
8b1cb5b87Smrg#
9b1cb5b87Smrg# Copyright (C) 1994 X Consortium
10b1cb5b87Smrg#
11b1cb5b87Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
12b1cb5b87Smrg# of this software and associated documentation files (the "Software"), to
13b1cb5b87Smrg# deal in the Software without restriction, including without limitation the
14b1cb5b87Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15b1cb5b87Smrg# sell copies of the Software, and to permit persons to whom the Software is
16b1cb5b87Smrg# furnished to do so, subject to the following conditions:
17b1cb5b87Smrg#
18b1cb5b87Smrg# The above copyright notice and this permission notice shall be included in
19b1cb5b87Smrg# all copies or substantial portions of the Software.
20b1cb5b87Smrg#
21b1cb5b87Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22b1cb5b87Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23b1cb5b87Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24b1cb5b87Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25b1cb5b87Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
26b1cb5b87Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27b1cb5b87Smrg#
28b1cb5b87Smrg# Except as contained in this notice, the name of the X Consortium shall not
29b1cb5b87Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
30b1cb5b87Smrg# ings in this Software without prior written authorization from the X Consor-
31b1cb5b87Smrg# tium.
32b1cb5b87Smrg#
33b1cb5b87Smrg#
34b1cb5b87Smrg# FSF changes to this file are in the public domain.
35b1cb5b87Smrg#
36b1cb5b87Smrg# Calling this script install-sh is preferred over install.sh, to prevent
37b1cb5b87Smrg# `make' implicit rules from creating a file called install from it
38b1cb5b87Smrg# when there is no Makefile.
39b1cb5b87Smrg#
40b1cb5b87Smrg# This script is compatible with the BSD install script, but was written
41b1cb5b87Smrg# from scratch.  It can only install one file at a time, a restriction
42b1cb5b87Smrg# shared with many OS's install programs.
43b1cb5b87Smrg
44b1cb5b87Smrg
45b1cb5b87Smrg# set DOITPROG to echo to test this script
46b1cb5b87Smrg
47b1cb5b87Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48b1cb5b87Smrgdoit="${DOITPROG-}"
49b1cb5b87Smrg
50b1cb5b87Smrg
51b1cb5b87Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
52b1cb5b87Smrg
53b1cb5b87Smrgmvprog="${MVPROG-mv}"
54b1cb5b87Smrgcpprog="${CPPROG-cp}"
55b1cb5b87Smrgchmodprog="${CHMODPROG-chmod}"
56b1cb5b87Smrgchownprog="${CHOWNPROG-chown}"
57b1cb5b87Smrgchgrpprog="${CHGRPPROG-chgrp}"
58b1cb5b87Smrgstripprog="${STRIPPROG-strip}"
59b1cb5b87Smrgrmprog="${RMPROG-rm}"
60b1cb5b87Smrgmkdirprog="${MKDIRPROG-mkdir}"
61b1cb5b87Smrg
62b1cb5b87Smrgtransformbasename=""
63b1cb5b87Smrgtransform_arg=""
64b1cb5b87Smrginstcmd="$mvprog"
65b1cb5b87Smrgchmodcmd="$chmodprog 0755"
66b1cb5b87Smrgchowncmd=""
67b1cb5b87Smrgchgrpcmd=""
68b1cb5b87Smrgstripcmd=""
69b1cb5b87Smrgrmcmd="$rmprog -f"
70b1cb5b87Smrgmvcmd="$mvprog"
71b1cb5b87Smrgsrc=""
72b1cb5b87Smrgdst=""
73b1cb5b87Smrgdir_arg=""
74b1cb5b87Smrg
75b1cb5b87Smrgwhile [ x"$1" != x ]; do
76b1cb5b87Smrg    case $1 in
77b1cb5b87Smrg	-c) instcmd=$cpprog
78b1cb5b87Smrg	    shift
79b1cb5b87Smrg	    continue;;
80b1cb5b87Smrg
81b1cb5b87Smrg	-d) dir_arg=true
82b1cb5b87Smrg	    shift
83b1cb5b87Smrg	    continue;;
84b1cb5b87Smrg
85b1cb5b87Smrg	-m) chmodcmd="$chmodprog $2"
86b1cb5b87Smrg	    shift
87b1cb5b87Smrg	    shift
88b1cb5b87Smrg	    continue;;
89b1cb5b87Smrg
90b1cb5b87Smrg	-o) chowncmd="$chownprog $2"
91b1cb5b87Smrg	    shift
92b1cb5b87Smrg	    shift
93b1cb5b87Smrg	    continue;;
94b1cb5b87Smrg
95b1cb5b87Smrg	-g) chgrpcmd="$chgrpprog $2"
96b1cb5b87Smrg	    shift
97b1cb5b87Smrg	    shift
98b1cb5b87Smrg	    continue;;
99b1cb5b87Smrg
100b1cb5b87Smrg	-s) stripcmd=$stripprog
101b1cb5b87Smrg	    shift
102b1cb5b87Smrg	    continue;;
103b1cb5b87Smrg
104b1cb5b87Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
105b1cb5b87Smrg	    shift
106b1cb5b87Smrg	    continue;;
107b1cb5b87Smrg
108b1cb5b87Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
109b1cb5b87Smrg	    shift
110b1cb5b87Smrg	    continue;;
111b1cb5b87Smrg
112b1cb5b87Smrg	*)  if [ x"$src" = x ]
113b1cb5b87Smrg	    then
114b1cb5b87Smrg		src=$1
115b1cb5b87Smrg	    else
116b1cb5b87Smrg		# this colon is to work around a 386BSD /bin/sh bug
117b1cb5b87Smrg		:
118b1cb5b87Smrg		dst=$1
119b1cb5b87Smrg	    fi
120b1cb5b87Smrg	    shift
121b1cb5b87Smrg	    continue;;
122b1cb5b87Smrg    esac
123b1cb5b87Smrgdone
124b1cb5b87Smrg
125b1cb5b87Smrgif [ x"$src" = x ]
126b1cb5b87Smrgthen
127b1cb5b87Smrg	echo "$0: no input file specified" >&2
128b1cb5b87Smrg	exit 1
129b1cb5b87Smrgelse
130b1cb5b87Smrg	:
131b1cb5b87Smrgfi
132b1cb5b87Smrg
133b1cb5b87Smrgif [ x"$dir_arg" != x ]; then
134b1cb5b87Smrg	dst=$src
135b1cb5b87Smrg	src=""
136b1cb5b87Smrg
137b1cb5b87Smrg	if [ -d "$dst" ]; then
138b1cb5b87Smrg		instcmd=:
139b1cb5b87Smrg		chmodcmd=""
140b1cb5b87Smrg	else
141b1cb5b87Smrg		instcmd=$mkdirprog
142b1cb5b87Smrg	fi
143b1cb5b87Smrgelse
144b1cb5b87Smrg
145b1cb5b87Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
146b1cb5b87Smrg# might cause directories to be created, which would be especially bad
147b1cb5b87Smrg# if $src (and thus $dsttmp) contains '*'.
148b1cb5b87Smrg
149b1cb5b87Smrg	if [ -f "$src" ] || [ -d "$src" ]
150b1cb5b87Smrg	then
151b1cb5b87Smrg		:
152b1cb5b87Smrg	else
153b1cb5b87Smrg		echo "$0: $src does not exist" >&2
154b1cb5b87Smrg		exit 1
155b1cb5b87Smrg	fi
156b1cb5b87Smrg
157b1cb5b87Smrg	if [ x"$dst" = x ]
158b1cb5b87Smrg	then
159b1cb5b87Smrg		echo "$0: no destination specified" >&2
160b1cb5b87Smrg		exit 1
161b1cb5b87Smrg	else
162b1cb5b87Smrg		:
163b1cb5b87Smrg	fi
164b1cb5b87Smrg
165b1cb5b87Smrg# If destination is a directory, append the input filename; if your system
166b1cb5b87Smrg# does not like double slashes in filenames, you may need to add some logic
167b1cb5b87Smrg
168b1cb5b87Smrg	if [ -d "$dst" ]
169b1cb5b87Smrg	then
170b1cb5b87Smrg		dst=$dst/`basename "$src"`
171b1cb5b87Smrg	else
172b1cb5b87Smrg		:
173b1cb5b87Smrg	fi
174b1cb5b87Smrgfi
175b1cb5b87Smrg
176b1cb5b87Smrg## this sed command emulates the dirname command
177b1cb5b87Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
178b1cb5b87Smrg
179b1cb5b87Smrg# Make sure that the destination directory exists.
180b1cb5b87Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
181b1cb5b87Smrg
182b1cb5b87Smrg# Skip lots of stat calls in the usual case.
183b1cb5b87Smrgif [ ! -d "$dstdir" ]; then
184b1cb5b87SmrgdefaultIFS='
185b1cb5b87Smrg	'
186b1cb5b87SmrgIFS="${IFS-$defaultIFS}"
187b1cb5b87Smrg
188b1cb5b87SmrgoIFS=$IFS
189b1cb5b87Smrg# Some sh's can't handle IFS=/ for some reason.
190b1cb5b87SmrgIFS='%'
191b1cb5b87Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
192b1cb5b87SmrgIFS=$oIFS
193b1cb5b87Smrg
194b1cb5b87Smrgpathcomp=''
195b1cb5b87Smrg
196b1cb5b87Smrgwhile [ $# -ne 0 ] ; do
197b1cb5b87Smrg	pathcomp=$pathcomp$1
198b1cb5b87Smrg	shift
199b1cb5b87Smrg
200b1cb5b87Smrg	if [ ! -d "$pathcomp" ] ;
201b1cb5b87Smrg        then
202b1cb5b87Smrg		$mkdirprog "$pathcomp"
203b1cb5b87Smrg	else
204b1cb5b87Smrg		:
205b1cb5b87Smrg	fi
206b1cb5b87Smrg
207b1cb5b87Smrg	pathcomp=$pathcomp/
208b1cb5b87Smrgdone
209b1cb5b87Smrgfi
210b1cb5b87Smrg
211b1cb5b87Smrgif [ x"$dir_arg" != x ]
212b1cb5b87Smrgthen
213b1cb5b87Smrg	$doit $instcmd "$dst" &&
214b1cb5b87Smrg
215b1cb5b87Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
216b1cb5b87Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
217b1cb5b87Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
218b1cb5b87Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
219b1cb5b87Smrgelse
220b1cb5b87Smrg
221b1cb5b87Smrg# If we're going to rename the final executable, determine the name now.
222b1cb5b87Smrg
223b1cb5b87Smrg	if [ x"$transformarg" = x ]
224b1cb5b87Smrg	then
225b1cb5b87Smrg		dstfile=`basename "$dst"`
226b1cb5b87Smrg	else
227b1cb5b87Smrg		dstfile=`basename "$dst" $transformbasename |
228b1cb5b87Smrg			sed $transformarg`$transformbasename
229b1cb5b87Smrg	fi
230b1cb5b87Smrg
231b1cb5b87Smrg# don't allow the sed command to completely eliminate the filename
232b1cb5b87Smrg
233b1cb5b87Smrg	if [ x"$dstfile" = x ]
234b1cb5b87Smrg	then
235b1cb5b87Smrg		dstfile=`basename "$dst"`
236b1cb5b87Smrg	else
237b1cb5b87Smrg		:
238b1cb5b87Smrg	fi
239b1cb5b87Smrg
240b1cb5b87Smrg# Make a couple of temp file names in the proper directory.
241b1cb5b87Smrg
242b1cb5b87Smrg	dsttmp=$dstdir/_inst.$$_
243b1cb5b87Smrg	rmtmp=$dstdir/_rm.$$_
244b1cb5b87Smrg
245b1cb5b87Smrg# Trap to clean up temp files at exit.
246b1cb5b87Smrg
247b1cb5b87Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
248b1cb5b87Smrg	trap '(exit $?); exit' 1 2 13 15
249b1cb5b87Smrg
250b1cb5b87Smrg# Move or copy the file name to the temp name
251b1cb5b87Smrg
252b1cb5b87Smrg	$doit $instcmd "$src" "$dsttmp" &&
253b1cb5b87Smrg
254b1cb5b87Smrg# and set any options; do chmod last to preserve setuid bits
255b1cb5b87Smrg
256b1cb5b87Smrg# If any of these fail, we abort the whole thing.  If we want to
257b1cb5b87Smrg# ignore errors from any of these, just make sure not to ignore
258b1cb5b87Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
259b1cb5b87Smrg
260b1cb5b87Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
261b1cb5b87Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
262b1cb5b87Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
263b1cb5b87Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
264b1cb5b87Smrg
265b1cb5b87Smrg# Now remove or move aside any old file at destination location.  We try this
266b1cb5b87Smrg# two ways since rm can't unlink itself on some systems and the destination
267b1cb5b87Smrg# file might be busy for other reasons.  In this case, the final cleanup
268b1cb5b87Smrg# might fail but the new file should still install successfully.
269b1cb5b87Smrg
270b1cb5b87Smrg{
271b1cb5b87Smrg	if [ -f "$dstdir/$dstfile" ]
272b1cb5b87Smrg	then
273b1cb5b87Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
274b1cb5b87Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
275b1cb5b87Smrg		{
276b1cb5b87Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
277b1cb5b87Smrg		  (exit 1); exit
278b1cb5b87Smrg		}
279b1cb5b87Smrg	else
280b1cb5b87Smrg		:
281b1cb5b87Smrg	fi
282b1cb5b87Smrg} &&
283b1cb5b87Smrg
284b1cb5b87Smrg# Now rename the file to the real destination.
285b1cb5b87Smrg
286b1cb5b87Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
287b1cb5b87Smrg
288b1cb5b87Smrgfi &&
289b1cb5b87Smrg
290b1cb5b87Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
291b1cb5b87Smrg
292b1cb5b87Smrg{
293b1cb5b87Smrg	(exit 0); exit
294b1cb5b87Smrg}
295