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