install-sh revision 644fc5c1
1644fc5c1Stron#!/bin/sh
2644fc5c1Stron#
3644fc5c1Stron# install - install a program, script, or datafile
4644fc5c1Stron#
5644fc5c1Stron# This originates from X11R5 (mit/util/scripts/install.sh), which was
6644fc5c1Stron# later released in X11R6 (xc/config/util/install.sh) with the
7644fc5c1Stron# following copyright and license.
8644fc5c1Stron#
9644fc5c1Stron# Copyright (C) 1994 X Consortium
10644fc5c1Stron#
11644fc5c1Stron# Permission is hereby granted, free of charge, to any person obtaining a copy
12644fc5c1Stron# of this software and associated documentation files (the "Software"), to
13644fc5c1Stron# deal in the Software without restriction, including without limitation the
14644fc5c1Stron# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15644fc5c1Stron# sell copies of the Software, and to permit persons to whom the Software is
16644fc5c1Stron# furnished to do so, subject to the following conditions:
17644fc5c1Stron#
18644fc5c1Stron# The above copyright notice and this permission notice shall be included in
19644fc5c1Stron# all copies or substantial portions of the Software.
20644fc5c1Stron#
21644fc5c1Stron# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22644fc5c1Stron# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23644fc5c1Stron# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24644fc5c1Stron# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25644fc5c1Stron# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
26644fc5c1Stron# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27644fc5c1Stron#
28644fc5c1Stron# Except as contained in this notice, the name of the X Consortium shall not
29644fc5c1Stron# be used in advertising or otherwise to promote the sale, use or other deal-
30644fc5c1Stron# ings in this Software without prior written authorization from the X Consor-
31644fc5c1Stron# tium.
32644fc5c1Stron#
33644fc5c1Stron#
34644fc5c1Stron# FSF changes to this file are in the public domain.
35644fc5c1Stron#
36644fc5c1Stron# Calling this script install-sh is preferred over install.sh, to prevent
37644fc5c1Stron# `make' implicit rules from creating a file called install from it
38644fc5c1Stron# when there is no Makefile.
39644fc5c1Stron#
40644fc5c1Stron# This script is compatible with the BSD install script, but was written
41644fc5c1Stron# from scratch.  It can only install one file at a time, a restriction
42644fc5c1Stron# shared with many OS's install programs.
43644fc5c1Stron
44644fc5c1Stron
45644fc5c1Stron# set DOITPROG to echo to test this script
46644fc5c1Stron
47644fc5c1Stron# Don't use :- since 4.3BSD and earlier shells don't like it.
48644fc5c1Strondoit="${DOITPROG-}"
49644fc5c1Stron
50644fc5c1Stron
51644fc5c1Stron# put in absolute paths if you don't have them in your path; or use env. vars.
52644fc5c1Stron
53644fc5c1Stronmvprog="${MVPROG-mv}"
54644fc5c1Stroncpprog="${CPPROG-cp}"
55644fc5c1Stronchmodprog="${CHMODPROG-chmod}"
56644fc5c1Stronchownprog="${CHOWNPROG-chown}"
57644fc5c1Stronchgrpprog="${CHGRPPROG-chgrp}"
58644fc5c1Stronstripprog="${STRIPPROG-strip}"
59644fc5c1Stronrmprog="${RMPROG-rm}"
60644fc5c1Stronmkdirprog="${MKDIRPROG-mkdir}"
61644fc5c1Stron
62644fc5c1Strontransformbasename=""
63644fc5c1Strontransform_arg=""
64644fc5c1Stroninstcmd="$mvprog"
65644fc5c1Stronchmodcmd="$chmodprog 0755"
66644fc5c1Stronchowncmd=""
67644fc5c1Stronchgrpcmd=""
68644fc5c1Stronstripcmd=""
69644fc5c1Stronrmcmd="$rmprog -f"
70644fc5c1Stronmvcmd="$mvprog"
71644fc5c1Stronsrc=""
72644fc5c1Strondst=""
73644fc5c1Strondir_arg=""
74644fc5c1Stron
75644fc5c1Stronwhile [ x"$1" != x ]; do
76644fc5c1Stron    case $1 in
77644fc5c1Stron	-c) instcmd=$cpprog
78644fc5c1Stron	    shift
79644fc5c1Stron	    continue;;
80644fc5c1Stron
81644fc5c1Stron	-d) dir_arg=true
82644fc5c1Stron	    shift
83644fc5c1Stron	    continue;;
84644fc5c1Stron
85644fc5c1Stron	-m) chmodcmd="$chmodprog $2"
86644fc5c1Stron	    shift
87644fc5c1Stron	    shift
88644fc5c1Stron	    continue;;
89644fc5c1Stron
90644fc5c1Stron	-o) chowncmd="$chownprog $2"
91644fc5c1Stron	    shift
92644fc5c1Stron	    shift
93644fc5c1Stron	    continue;;
94644fc5c1Stron
95644fc5c1Stron	-g) chgrpcmd="$chgrpprog $2"
96644fc5c1Stron	    shift
97644fc5c1Stron	    shift
98644fc5c1Stron	    continue;;
99644fc5c1Stron
100644fc5c1Stron	-s) stripcmd=$stripprog
101644fc5c1Stron	    shift
102644fc5c1Stron	    continue;;
103644fc5c1Stron
104644fc5c1Stron	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
105644fc5c1Stron	    shift
106644fc5c1Stron	    continue;;
107644fc5c1Stron
108644fc5c1Stron	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
109644fc5c1Stron	    shift
110644fc5c1Stron	    continue;;
111644fc5c1Stron
112644fc5c1Stron	*)  if [ x"$src" = x ]
113644fc5c1Stron	    then
114644fc5c1Stron		src=$1
115644fc5c1Stron	    else
116644fc5c1Stron		# this colon is to work around a 386BSD /bin/sh bug
117644fc5c1Stron		:
118644fc5c1Stron		dst=$1
119644fc5c1Stron	    fi
120644fc5c1Stron	    shift
121644fc5c1Stron	    continue;;
122644fc5c1Stron    esac
123644fc5c1Strondone
124644fc5c1Stron
125644fc5c1Stronif [ x"$src" = x ]
126644fc5c1Stronthen
127644fc5c1Stron	echo "$0: no input file specified" >&2
128644fc5c1Stron	exit 1
129644fc5c1Stronelse
130644fc5c1Stron	:
131644fc5c1Stronfi
132644fc5c1Stron
133644fc5c1Stronif [ x"$dir_arg" != x ]; then
134644fc5c1Stron	dst=$src
135644fc5c1Stron	src=""
136644fc5c1Stron
137644fc5c1Stron	if [ -d "$dst" ]; then
138644fc5c1Stron		instcmd=:
139644fc5c1Stron		chmodcmd=""
140644fc5c1Stron	else
141644fc5c1Stron		instcmd=$mkdirprog
142644fc5c1Stron	fi
143644fc5c1Stronelse
144644fc5c1Stron
145644fc5c1Stron# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
146644fc5c1Stron# might cause directories to be created, which would be especially bad
147644fc5c1Stron# if $src (and thus $dsttmp) contains '*'.
148644fc5c1Stron
149644fc5c1Stron	if [ -f "$src" ] || [ -d "$src" ]
150644fc5c1Stron	then
151644fc5c1Stron		:
152644fc5c1Stron	else
153644fc5c1Stron		echo "$0: $src does not exist" >&2
154644fc5c1Stron		exit 1
155644fc5c1Stron	fi
156644fc5c1Stron
157644fc5c1Stron	if [ x"$dst" = x ]
158644fc5c1Stron	then
159644fc5c1Stron		echo "$0: no destination specified" >&2
160644fc5c1Stron		exit 1
161644fc5c1Stron	else
162644fc5c1Stron		:
163644fc5c1Stron	fi
164644fc5c1Stron
165644fc5c1Stron# If destination is a directory, append the input filename; if your system
166644fc5c1Stron# does not like double slashes in filenames, you may need to add some logic
167644fc5c1Stron
168644fc5c1Stron	if [ -d "$dst" ]
169644fc5c1Stron	then
170644fc5c1Stron		dst=$dst/`basename "$src"`
171644fc5c1Stron	else
172644fc5c1Stron		:
173644fc5c1Stron	fi
174644fc5c1Stronfi
175644fc5c1Stron
176644fc5c1Stron## this sed command emulates the dirname command
177644fc5c1Strondstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
178644fc5c1Stron
179644fc5c1Stron# Make sure that the destination directory exists.
180644fc5c1Stron#  this part is taken from Noah Friedman's mkinstalldirs script
181644fc5c1Stron
182644fc5c1Stron# Skip lots of stat calls in the usual case.
183644fc5c1Stronif [ ! -d "$dstdir" ]; then
184644fc5c1StrondefaultIFS='
185644fc5c1Stron	'
186644fc5c1StronIFS="${IFS-$defaultIFS}"
187644fc5c1Stron
188644fc5c1StronoIFS=$IFS
189644fc5c1Stron# Some sh's can't handle IFS=/ for some reason.
190644fc5c1StronIFS='%'
191644fc5c1Stronset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
192644fc5c1StronIFS=$oIFS
193644fc5c1Stron
194644fc5c1Stronpathcomp=''
195644fc5c1Stron
196644fc5c1Stronwhile [ $# -ne 0 ] ; do
197644fc5c1Stron	pathcomp=$pathcomp$1
198644fc5c1Stron	shift
199644fc5c1Stron
200644fc5c1Stron	if [ ! -d "$pathcomp" ] ;
201644fc5c1Stron        then
202644fc5c1Stron		$mkdirprog "$pathcomp"
203644fc5c1Stron	else
204644fc5c1Stron		:
205644fc5c1Stron	fi
206644fc5c1Stron
207644fc5c1Stron	pathcomp=$pathcomp/
208644fc5c1Strondone
209644fc5c1Stronfi
210644fc5c1Stron
211644fc5c1Stronif [ x"$dir_arg" != x ]
212644fc5c1Stronthen
213644fc5c1Stron	$doit $instcmd "$dst" &&
214644fc5c1Stron
215644fc5c1Stron	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
216644fc5c1Stron	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
217644fc5c1Stron	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
218644fc5c1Stron	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
219644fc5c1Stronelse
220644fc5c1Stron
221644fc5c1Stron# If we're going to rename the final executable, determine the name now.
222644fc5c1Stron
223644fc5c1Stron	if [ x"$transformarg" = x ]
224644fc5c1Stron	then
225644fc5c1Stron		dstfile=`basename "$dst"`
226644fc5c1Stron	else
227644fc5c1Stron		dstfile=`basename "$dst" $transformbasename |
228644fc5c1Stron			sed $transformarg`$transformbasename
229644fc5c1Stron	fi
230644fc5c1Stron
231644fc5c1Stron# don't allow the sed command to completely eliminate the filename
232644fc5c1Stron
233644fc5c1Stron	if [ x"$dstfile" = x ]
234644fc5c1Stron	then
235644fc5c1Stron		dstfile=`basename "$dst"`
236644fc5c1Stron	else
237644fc5c1Stron		:
238644fc5c1Stron	fi
239644fc5c1Stron
240644fc5c1Stron# Make a couple of temp file names in the proper directory.
241644fc5c1Stron
242644fc5c1Stron	dsttmp=$dstdir/_inst.$$_
243644fc5c1Stron	rmtmp=$dstdir/_rm.$$_
244644fc5c1Stron
245644fc5c1Stron# Trap to clean up temp files at exit.
246644fc5c1Stron
247644fc5c1Stron	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
248644fc5c1Stron	trap '(exit $?); exit' 1 2 13 15
249644fc5c1Stron
250644fc5c1Stron# Move or copy the file name to the temp name
251644fc5c1Stron
252644fc5c1Stron	$doit $instcmd "$src" "$dsttmp" &&
253644fc5c1Stron
254644fc5c1Stron# and set any options; do chmod last to preserve setuid bits
255644fc5c1Stron
256644fc5c1Stron# If any of these fail, we abort the whole thing.  If we want to
257644fc5c1Stron# ignore errors from any of these, just make sure not to ignore
258644fc5c1Stron# errors from the above "$doit $instcmd $src $dsttmp" command.
259644fc5c1Stron
260644fc5c1Stron	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
261644fc5c1Stron	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
262644fc5c1Stron	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
263644fc5c1Stron	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
264644fc5c1Stron
265644fc5c1Stron# Now remove or move aside any old file at destination location.  We try this
266644fc5c1Stron# two ways since rm can't unlink itself on some systems and the destination
267644fc5c1Stron# file might be busy for other reasons.  In this case, the final cleanup
268644fc5c1Stron# might fail but the new file should still install successfully.
269644fc5c1Stron
270644fc5c1Stron{
271644fc5c1Stron	if [ -f "$dstdir/$dstfile" ]
272644fc5c1Stron	then
273644fc5c1Stron		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
274644fc5c1Stron		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
275644fc5c1Stron		{
276644fc5c1Stron		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
277644fc5c1Stron		  (exit 1); exit
278644fc5c1Stron		}
279644fc5c1Stron	else
280644fc5c1Stron		:
281644fc5c1Stron	fi
282644fc5c1Stron} &&
283644fc5c1Stron
284644fc5c1Stron# Now rename the file to the real destination.
285644fc5c1Stron
286644fc5c1Stron	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
287644fc5c1Stron
288644fc5c1Stronfi &&
289644fc5c1Stron
290644fc5c1Stron# The final little trick to "correctly" pass the exit status to the exit trap.
291644fc5c1Stron
292644fc5c1Stron{
293644fc5c1Stron	(exit 0); exit
294644fc5c1Stron}
295