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