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