install-sh revision 566738d7
1566738d7Smrg#!/bin/sh
2566738d7Smrg#
3566738d7Smrg# install - install a program, script, or datafile
4566738d7Smrg#
5566738d7Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
6566738d7Smrg# later released in X11R6 (xc/config/util/install.sh) with the
7566738d7Smrg# following copyright and license.
8566738d7Smrg#
9566738d7Smrg# Copyright (C) 1994 X Consortium
10566738d7Smrg#
11566738d7Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
12566738d7Smrg# of this software and associated documentation files (the "Software"), to
13566738d7Smrg# deal in the Software without restriction, including without limitation the
14566738d7Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15566738d7Smrg# sell copies of the Software, and to permit persons to whom the Software is
16566738d7Smrg# furnished to do so, subject to the following conditions:
17566738d7Smrg#
18566738d7Smrg# The above copyright notice and this permission notice shall be included in
19566738d7Smrg# all copies or substantial portions of the Software.
20566738d7Smrg#
21566738d7Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22566738d7Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23566738d7Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24566738d7Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25566738d7Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
26566738d7Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27566738d7Smrg#
28566738d7Smrg# Except as contained in this notice, the name of the X Consortium shall not
29566738d7Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
30566738d7Smrg# ings in this Software without prior written authorization from the X Consor-
31566738d7Smrg# tium.
32566738d7Smrg#
33566738d7Smrg#
34566738d7Smrg# FSF changes to this file are in the public domain.
35566738d7Smrg#
36566738d7Smrg# Calling this script install-sh is preferred over install.sh, to prevent
37566738d7Smrg# `make' implicit rules from creating a file called install from it
38566738d7Smrg# when there is no Makefile.
39566738d7Smrg#
40566738d7Smrg# This script is compatible with the BSD install script, but was written
41566738d7Smrg# from scratch.  It can only install one file at a time, a restriction
42566738d7Smrg# shared with many OS's install programs.
43566738d7Smrg
44566738d7Smrg
45566738d7Smrg# set DOITPROG to echo to test this script
46566738d7Smrg
47566738d7Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48566738d7Smrgdoit="${DOITPROG-}"
49566738d7Smrg
50566738d7Smrg
51566738d7Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
52566738d7Smrg
53566738d7Smrgmvprog="${MVPROG-mv}"
54566738d7Smrgcpprog="${CPPROG-cp}"
55566738d7Smrgchmodprog="${CHMODPROG-chmod}"
56566738d7Smrgchownprog="${CHOWNPROG-chown}"
57566738d7Smrgchgrpprog="${CHGRPPROG-chgrp}"
58566738d7Smrgstripprog="${STRIPPROG-strip}"
59566738d7Smrgrmprog="${RMPROG-rm}"
60566738d7Smrgmkdirprog="${MKDIRPROG-mkdir}"
61566738d7Smrg
62566738d7Smrgtransformbasename=""
63566738d7Smrgtransform_arg=""
64566738d7Smrginstcmd="$mvprog"
65566738d7Smrgchmodcmd="$chmodprog 0755"
66566738d7Smrgchowncmd=""
67566738d7Smrgchgrpcmd=""
68566738d7Smrgstripcmd=""
69566738d7Smrgrmcmd="$rmprog -f"
70566738d7Smrgmvcmd="$mvprog"
71566738d7Smrgsrc=""
72566738d7Smrgdst=""
73566738d7Smrgdir_arg=""
74566738d7Smrg
75566738d7Smrgwhile [ x"$1" != x ]; do
76566738d7Smrg    case $1 in
77566738d7Smrg	-c) instcmd=$cpprog
78566738d7Smrg	    shift
79566738d7Smrg	    continue;;
80566738d7Smrg
81566738d7Smrg	-d) dir_arg=true
82566738d7Smrg	    shift
83566738d7Smrg	    continue;;
84566738d7Smrg
85566738d7Smrg	-m) chmodcmd="$chmodprog $2"
86566738d7Smrg	    shift
87566738d7Smrg	    shift
88566738d7Smrg	    continue;;
89566738d7Smrg
90566738d7Smrg	-o) chowncmd="$chownprog $2"
91566738d7Smrg	    shift
92566738d7Smrg	    shift
93566738d7Smrg	    continue;;
94566738d7Smrg
95566738d7Smrg	-g) chgrpcmd="$chgrpprog $2"
96566738d7Smrg	    shift
97566738d7Smrg	    shift
98566738d7Smrg	    continue;;
99566738d7Smrg
100566738d7Smrg	-s) stripcmd=$stripprog
101566738d7Smrg	    shift
102566738d7Smrg	    continue;;
103566738d7Smrg
104566738d7Smrg	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
105566738d7Smrg	    shift
106566738d7Smrg	    continue;;
107566738d7Smrg
108566738d7Smrg	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
109566738d7Smrg	    shift
110566738d7Smrg	    continue;;
111566738d7Smrg
112566738d7Smrg	*)  if [ x"$src" = x ]
113566738d7Smrg	    then
114566738d7Smrg		src=$1
115566738d7Smrg	    else
116566738d7Smrg		# this colon is to work around a 386BSD /bin/sh bug
117566738d7Smrg		:
118566738d7Smrg		dst=$1
119566738d7Smrg	    fi
120566738d7Smrg	    shift
121566738d7Smrg	    continue;;
122566738d7Smrg    esac
123566738d7Smrgdone
124566738d7Smrg
125566738d7Smrgif [ x"$src" = x ]
126566738d7Smrgthen
127566738d7Smrg	echo "$0: no input file specified" >&2
128566738d7Smrg	exit 1
129566738d7Smrgelse
130566738d7Smrg	:
131566738d7Smrgfi
132566738d7Smrg
133566738d7Smrgif [ x"$dir_arg" != x ]; then
134566738d7Smrg	dst=$src
135566738d7Smrg	src=""
136566738d7Smrg
137566738d7Smrg	if [ -d "$dst" ]; then
138566738d7Smrg		instcmd=:
139566738d7Smrg		chmodcmd=""
140566738d7Smrg	else
141566738d7Smrg		instcmd=$mkdirprog
142566738d7Smrg	fi
143566738d7Smrgelse
144566738d7Smrg
145566738d7Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
146566738d7Smrg# might cause directories to be created, which would be especially bad
147566738d7Smrg# if $src (and thus $dsttmp) contains '*'.
148566738d7Smrg
149566738d7Smrg	if [ -f "$src" ] || [ -d "$src" ]
150566738d7Smrg	then
151566738d7Smrg		:
152566738d7Smrg	else
153566738d7Smrg		echo "$0: $src does not exist" >&2
154566738d7Smrg		exit 1
155566738d7Smrg	fi
156566738d7Smrg
157566738d7Smrg	if [ x"$dst" = x ]
158566738d7Smrg	then
159566738d7Smrg		echo "$0: no destination specified" >&2
160566738d7Smrg		exit 1
161566738d7Smrg	else
162566738d7Smrg		:
163566738d7Smrg	fi
164566738d7Smrg
165566738d7Smrg# If destination is a directory, append the input filename; if your system
166566738d7Smrg# does not like double slashes in filenames, you may need to add some logic
167566738d7Smrg
168566738d7Smrg	if [ -d "$dst" ]
169566738d7Smrg	then
170566738d7Smrg		dst=$dst/`basename "$src"`
171566738d7Smrg	else
172566738d7Smrg		:
173566738d7Smrg	fi
174566738d7Smrgfi
175566738d7Smrg
176566738d7Smrg## this sed command emulates the dirname command
177566738d7Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
178566738d7Smrg
179566738d7Smrg# Make sure that the destination directory exists.
180566738d7Smrg#  this part is taken from Noah Friedman's mkinstalldirs script
181566738d7Smrg
182566738d7Smrg# Skip lots of stat calls in the usual case.
183566738d7Smrgif [ ! -d "$dstdir" ]; then
184566738d7SmrgdefaultIFS='
185566738d7Smrg	'
186566738d7SmrgIFS="${IFS-$defaultIFS}"
187566738d7Smrg
188566738d7SmrgoIFS=$IFS
189566738d7Smrg# Some sh's can't handle IFS=/ for some reason.
190566738d7SmrgIFS='%'
191566738d7Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
192566738d7SmrgIFS=$oIFS
193566738d7Smrg
194566738d7Smrgpathcomp=''
195566738d7Smrg
196566738d7Smrgwhile [ $# -ne 0 ] ; do
197566738d7Smrg	pathcomp=$pathcomp$1
198566738d7Smrg	shift
199566738d7Smrg
200566738d7Smrg	if [ ! -d "$pathcomp" ] ;
201566738d7Smrg        then
202566738d7Smrg		$mkdirprog "$pathcomp"
203566738d7Smrg	else
204566738d7Smrg		:
205566738d7Smrg	fi
206566738d7Smrg
207566738d7Smrg	pathcomp=$pathcomp/
208566738d7Smrgdone
209566738d7Smrgfi
210566738d7Smrg
211566738d7Smrgif [ x"$dir_arg" != x ]
212566738d7Smrgthen
213566738d7Smrg	$doit $instcmd "$dst" &&
214566738d7Smrg
215566738d7Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
216566738d7Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
217566738d7Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
218566738d7Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
219566738d7Smrgelse
220566738d7Smrg
221566738d7Smrg# If we're going to rename the final executable, determine the name now.
222566738d7Smrg
223566738d7Smrg	if [ x"$transformarg" = x ]
224566738d7Smrg	then
225566738d7Smrg		dstfile=`basename "$dst"`
226566738d7Smrg	else
227566738d7Smrg		dstfile=`basename "$dst" $transformbasename |
228566738d7Smrg			sed $transformarg`$transformbasename
229566738d7Smrg	fi
230566738d7Smrg
231566738d7Smrg# don't allow the sed command to completely eliminate the filename
232566738d7Smrg
233566738d7Smrg	if [ x"$dstfile" = x ]
234566738d7Smrg	then
235566738d7Smrg		dstfile=`basename "$dst"`
236566738d7Smrg	else
237566738d7Smrg		:
238566738d7Smrg	fi
239566738d7Smrg
240566738d7Smrg# Make a couple of temp file names in the proper directory.
241566738d7Smrg
242566738d7Smrg	dsttmp=$dstdir/_inst.$$_
243566738d7Smrg	rmtmp=$dstdir/_rm.$$_
244566738d7Smrg
245566738d7Smrg# Trap to clean up temp files at exit.
246566738d7Smrg
247566738d7Smrg	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
248566738d7Smrg	trap '(exit $?); exit' 1 2 13 15
249566738d7Smrg
250566738d7Smrg# Move or copy the file name to the temp name
251566738d7Smrg
252566738d7Smrg	$doit $instcmd "$src" "$dsttmp" &&
253566738d7Smrg
254566738d7Smrg# and set any options; do chmod last to preserve setuid bits
255566738d7Smrg
256566738d7Smrg# If any of these fail, we abort the whole thing.  If we want to
257566738d7Smrg# ignore errors from any of these, just make sure not to ignore
258566738d7Smrg# errors from the above "$doit $instcmd $src $dsttmp" command.
259566738d7Smrg
260566738d7Smrg	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
261566738d7Smrg	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
262566738d7Smrg	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
263566738d7Smrg	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
264566738d7Smrg
265566738d7Smrg# Now remove or move aside any old file at destination location.  We try this
266566738d7Smrg# two ways since rm can't unlink itself on some systems and the destination
267566738d7Smrg# file might be busy for other reasons.  In this case, the final cleanup
268566738d7Smrg# might fail but the new file should still install successfully.
269566738d7Smrg
270566738d7Smrg{
271566738d7Smrg	if [ -f "$dstdir/$dstfile" ]
272566738d7Smrg	then
273566738d7Smrg		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
274566738d7Smrg		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
275566738d7Smrg		{
276566738d7Smrg		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
277566738d7Smrg		  (exit 1); exit
278566738d7Smrg		}
279566738d7Smrg	else
280566738d7Smrg		:
281566738d7Smrg	fi
282566738d7Smrg} &&
283566738d7Smrg
284566738d7Smrg# Now rename the file to the real destination.
285566738d7Smrg
286566738d7Smrg	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
287566738d7Smrg
288566738d7Smrgfi &&
289566738d7Smrg
290566738d7Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
291566738d7Smrg
292566738d7Smrg{
293566738d7Smrg	(exit 0); exit
294566738d7Smrg}
295