install-sh revision 335e815a
1335e815aSmrg#!/bin/sh
2335e815aSmrg#
3335e815aSmrg# install - install a program, script, or datafile
4335e815aSmrg#
5335e815aSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
6335e815aSmrg# later released in X11R6 (xc/config/util/install.sh) with the
7335e815aSmrg# following copyright and license.
8335e815aSmrg#
9335e815aSmrg# Copyright (C) 1994 X Consortium
10335e815aSmrg#
11335e815aSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
12335e815aSmrg# of this software and associated documentation files (the "Software"), to
13335e815aSmrg# deal in the Software without restriction, including without limitation the
14335e815aSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15335e815aSmrg# sell copies of the Software, and to permit persons to whom the Software is
16335e815aSmrg# furnished to do so, subject to the following conditions:
17335e815aSmrg#
18335e815aSmrg# The above copyright notice and this permission notice shall be included in
19335e815aSmrg# all copies or substantial portions of the Software.
20335e815aSmrg#
21335e815aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22335e815aSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23335e815aSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24335e815aSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25335e815aSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
26335e815aSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27335e815aSmrg#
28335e815aSmrg# Except as contained in this notice, the name of the X Consortium shall not
29335e815aSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
30335e815aSmrg# ings in this Software without prior written authorization from the X Consor-
31335e815aSmrg# tium.
32335e815aSmrg#
33335e815aSmrg#
34335e815aSmrg# FSF changes to this file are in the public domain.
35335e815aSmrg#
36335e815aSmrg# Calling this script install-sh is preferred over install.sh, to prevent
37335e815aSmrg# `make' implicit rules from creating a file called install from it
38335e815aSmrg# when there is no Makefile.
39335e815aSmrg#
40335e815aSmrg# This script is compatible with the BSD install script, but was written
41335e815aSmrg# from scratch.  It can only install one file at a time, a restriction
42335e815aSmrg# shared with many OS's install programs.
43335e815aSmrg
44335e815aSmrg
45335e815aSmrg# set DOITPROG to echo to test this script
46335e815aSmrg
47335e815aSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48335e815aSmrgdoit="${DOITPROG-}"
49335e815aSmrg
50335e815aSmrg
51335e815aSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
52335e815aSmrg
53335e815aSmrgmvprog="${MVPROG-mv}"
54335e815aSmrgcpprog="${CPPROG-cp}"
55335e815aSmrgchmodprog="${CHMODPROG-chmod}"
56335e815aSmrgchownprog="${CHOWNPROG-chown}"
57335e815aSmrgchgrpprog="${CHGRPPROG-chgrp}"
58335e815aSmrgstripprog="${STRIPPROG-strip}"
59335e815aSmrgrmprog="${RMPROG-rm}"
60335e815aSmrgmkdirprog="${MKDIRPROG-mkdir}"
61335e815aSmrg
62335e815aSmrgtransformbasename=""
63335e815aSmrgtransform_arg=""
64335e815aSmrginstcmd="$mvprog"
65335e815aSmrgchmodcmd="$chmodprog 0755"
66335e815aSmrgchowncmd=""
67335e815aSmrgchgrpcmd=""
68335e815aSmrgstripcmd=""
69335e815aSmrgrmcmd="$rmprog -f"
70335e815aSmrgmvcmd="$mvprog"
71335e815aSmrgsrc=""
72335e815aSmrgdst=""
73335e815aSmrgdir_arg=""
74335e815aSmrg
75335e815aSmrgwhile [ x"$1" != x ]; do
76335e815aSmrg    case $1 in
77335e815aSmrg	-c) instcmd=$cpprog
78335e815aSmrg	    shift
79335e815aSmrg	    continue;;
80335e815aSmrg
81335e815aSmrg	-d) dir_arg=true
82335e815aSmrg	    shift
83335e815aSmrg	    continue;;
84335e815aSmrg
85335e815aSmrg	-m) chmodcmd="$chmodprog $2"
86335e815aSmrg	    shift
87335e815aSmrg	    shift
88335e815aSmrg	    continue;;
89335e815aSmrg
90335e815aSmrg	-o) chowncmd="$chownprog $2"
91335e815aSmrg	    shift
92335e815aSmrg	    shift
93335e815aSmrg	    continue;;
94335e815aSmrg
95335e815aSmrg	-g) chgrpcmd="$chgrpprog $2"
96335e815aSmrg	    shift
97335e815aSmrg	    shift
98335e815aSmrg	    continue;;
99335e815aSmrg
100335e815aSmrg	-s) stripcmd=$stripprog
101335e815aSmrg	    shift
102335e815aSmrg	    continue;;
103335e815aSmrg
104335e815aSmrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
105335e815aSmrg	    shift
106335e815aSmrg	    continue;;
107335e815aSmrg
108335e815aSmrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
109335e815aSmrg	    shift
110335e815aSmrg	    continue;;
111335e815aSmrg
112335e815aSmrg	*)  if [ x"$src" = x ]
113335e815aSmrg	    then
114335e815aSmrg		src=$1
115335e815aSmrg	    else
116335e815aSmrg		# this colon is to work around a 386BSD /bin/sh bug
117335e815aSmrg		:
118335e815aSmrg		dst=$1
119335e815aSmrg	    fi
120335e815aSmrg	    shift
121335e815aSmrg	    continue;;
122335e815aSmrg    esac
123335e815aSmrgdone
124335e815aSmrg
125335e815aSmrgif [ x"$src" = x ]
126335e815aSmrgthen
127335e815aSmrg	echo "$0: no input file specified" >&2
128335e815aSmrg	exit 1
129335e815aSmrgelse
130335e815aSmrg	:
131335e815aSmrgfi
132335e815aSmrg
133335e815aSmrgif [ x"$dir_arg" != x ]; then
134335e815aSmrg	dst=$src
135335e815aSmrg	src=""
136335e815aSmrg
137335e815aSmrg	if [ -d "$dst" ]; then
138335e815aSmrg		instcmd=:
139335e815aSmrg		chmodcmd=""
140335e815aSmrg	else
141335e815aSmrg		instcmd=$mkdirprog
142335e815aSmrg	fi
143335e815aSmrgelse
144335e815aSmrg
145335e815aSmrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
146335e815aSmrg# might cause directories to be created, which would be especially bad
147335e815aSmrg# if $src (and thus $dsttmp) contains '*'.
148335e815aSmrg
149335e815aSmrg	if [ -f "$src" ] || [ -d "$src" ]
150335e815aSmrg	then
151335e815aSmrg		:
152335e815aSmrg	else
153335e815aSmrg		echo "$0: $src does not exist" >&2
154335e815aSmrg		exit 1
155335e815aSmrg	fi
156335e815aSmrg
157335e815aSmrg	if [ x"$dst" = x ]
158335e815aSmrg	then
159335e815aSmrg		echo "$0: no destination specified" >&2
160335e815aSmrg		exit 1
161335e815aSmrg	else
162335e815aSmrg		:
163335e815aSmrg	fi
164335e815aSmrg
165335e815aSmrg# If destination is a directory, append the input filename; if your system
166335e815aSmrg# does not like double slashes in filenames, you may need to add some logic
167335e815aSmrg
168335e815aSmrg	if [ -d "$dst" ]
169335e815aSmrg	then
170335e815aSmrg		dst=$dst/`basename "$src"`
171335e815aSmrg	else
172335e815aSmrg		:
173335e815aSmrg	fi
174335e815aSmrgfi
175335e815aSmrg
176335e815aSmrg## this sed command emulates the dirname command
177335e815aSmrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
178335e815aSmrg
179335e815aSmrg# Make sure that the destination directory exists.
180335e815aSmrg#  this part is taken from Noah Friedman's mkinstalldirs script
181335e815aSmrg
182335e815aSmrg# Skip lots of stat calls in the usual case.
183335e815aSmrgif [ ! -d "$dstdir" ]; then
184335e815aSmrgdefaultIFS='
185335e815aSmrg	'
186335e815aSmrgIFS="${IFS-$defaultIFS}"
187335e815aSmrg
188335e815aSmrgoIFS=$IFS
189335e815aSmrg# Some sh's can't handle IFS=/ for some reason.
190335e815aSmrgIFS='%'
191335e815aSmrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
192335e815aSmrgIFS=$oIFS
193335e815aSmrg
194335e815aSmrgpathcomp=''
195335e815aSmrg
196335e815aSmrgwhile [ $# -ne 0 ] ; do
197335e815aSmrg	pathcomp=$pathcomp$1
198335e815aSmrg	shift
199335e815aSmrg
200335e815aSmrg	if [ ! -d "$pathcomp" ] ;
201335e815aSmrg        then
202335e815aSmrg		$mkdirprog "$pathcomp"
203335e815aSmrg	else
204335e815aSmrg		:
205335e815aSmrg	fi
206335e815aSmrg
207335e815aSmrg	pathcomp=$pathcomp/
208335e815aSmrgdone
209335e815aSmrgfi
210335e815aSmrg
211335e815aSmrgif [ x"$dir_arg" != x ]
212335e815aSmrgthen
213335e815aSmrg	$doit $instcmd "$dst" &&
214335e815aSmrg
215335e815aSmrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
216335e815aSmrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
217335e815aSmrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
218335e815aSmrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
219335e815aSmrgelse
220335e815aSmrg
221335e815aSmrg# If we're going to rename the final executable, determine the name now.
222335e815aSmrg
223335e815aSmrg	if [ x"$transformarg" = x ]
224335e815aSmrg	then
225335e815aSmrg		dstfile=`basename "$dst"`
226335e815aSmrg	else
227335e815aSmrg		dstfile=`basename "$dst" $transformbasename |
228335e815aSmrg			sed $transformarg`$transformbasename
229335e815aSmrg	fi
230335e815aSmrg
231335e815aSmrg# don't allow the sed command to completely eliminate the filename
232335e815aSmrg
233335e815aSmrg	if [ x"$dstfile" = x ]
234335e815aSmrg	then
235335e815aSmrg		dstfile=`basename "$dst"`
236335e815aSmrg	else
237335e815aSmrg		:
238335e815aSmrg	fi
239335e815aSmrg
240335e815aSmrg# Make a couple of temp file names in the proper directory.
241335e815aSmrg
242335e815aSmrg	dsttmp=$dstdir/_inst.$$_
243335e815aSmrg	rmtmp=$dstdir/_rm.$$_
244335e815aSmrg
245335e815aSmrg# Trap to clean up temp files at exit.
246335e815aSmrg
247335e815aSmrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
248335e815aSmrg	trap '(exit $?); exit' 1 2 13 15
249335e815aSmrg
250335e815aSmrg# Move or copy the file name to the temp name
251335e815aSmrg
252335e815aSmrg	$doit $instcmd "$src" "$dsttmp" &&
253335e815aSmrg
254335e815aSmrg# and set any options; do chmod last to preserve setuid bits
255335e815aSmrg
256335e815aSmrg# If any of these fail, we abort the whole thing.  If we want to
257335e815aSmrg# ignore errors from any of these, just make sure not to ignore
258335e815aSmrg# errors from the above "$doit $instcmd $src $dsttmp" command.
259335e815aSmrg
260335e815aSmrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
261335e815aSmrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
262335e815aSmrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
263335e815aSmrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
264335e815aSmrg
265335e815aSmrg# Now remove or move aside any old file at destination location.  We try this
266335e815aSmrg# two ways since rm can't unlink itself on some systems and the destination
267335e815aSmrg# file might be busy for other reasons.  In this case, the final cleanup
268335e815aSmrg# might fail but the new file should still install successfully.
269335e815aSmrg
270335e815aSmrg{
271335e815aSmrg	if [ -f "$dstdir/$dstfile" ]
272335e815aSmrg	then
273335e815aSmrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
274335e815aSmrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
275335e815aSmrg		{
276335e815aSmrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
277335e815aSmrg		  (exit 1); exit
278335e815aSmrg		}
279335e815aSmrg	else
280335e815aSmrg		:
281335e815aSmrg	fi
282335e815aSmrg} &&
283335e815aSmrg
284335e815aSmrg# Now rename the file to the real destination.
285335e815aSmrg
286335e815aSmrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
287335e815aSmrg
288335e815aSmrgfi &&
289335e815aSmrg
290335e815aSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
291335e815aSmrg
292335e815aSmrg{
293335e815aSmrg	(exit 0); exit
294335e815aSmrg}
295