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