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