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