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