xref: /aoo4110/main/install-sh (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski#!/bin/sh
2*b1cdbd2cSJim Jagielski#
3*b1cdbd2cSJim Jagielski# install - install a program, script, or datafile
4*b1cdbd2cSJim Jagielski# This comes from X11R5 (mit/util/scripts/install.sh).
5*b1cdbd2cSJim Jagielski#
6*b1cdbd2cSJim Jagielski# Copyright 1991 by the Massachusetts Institute of Technology
7*b1cdbd2cSJim Jagielski#
8*b1cdbd2cSJim Jagielski# Permission to use, copy, modify, distribute, and sell this software and its
9*b1cdbd2cSJim Jagielski# documentation for any purpose is hereby granted without fee, provided that
10*b1cdbd2cSJim Jagielski# the above copyright notice appear in all copies and that both that
11*b1cdbd2cSJim Jagielski# copyright notice and this permission notice appear in supporting
12*b1cdbd2cSJim Jagielski# documentation, and that the name of M.I.T. not be used in advertising or
13*b1cdbd2cSJim Jagielski# publicity pertaining to distribution of the software without specific,
14*b1cdbd2cSJim Jagielski# written prior permission.  M.I.T. makes no representations about the
15*b1cdbd2cSJim Jagielski# suitability of this software for any purpose.  It is provided "as is"
16*b1cdbd2cSJim Jagielski# without express or implied warranty.
17*b1cdbd2cSJim Jagielski#
18*b1cdbd2cSJim Jagielski# Calling this script install-sh is preferred over install.sh, to prevent
19*b1cdbd2cSJim Jagielski# `make' implicit rules from creating a file called install from it
20*b1cdbd2cSJim Jagielski# when there is no Makefile.
21*b1cdbd2cSJim Jagielski#
22*b1cdbd2cSJim Jagielski# This script is compatible with the BSD install script, but was written
23*b1cdbd2cSJim Jagielski# from scratch.  It can only install one file at a time, a restriction
24*b1cdbd2cSJim Jagielski# shared with many OS's install programs.
25*b1cdbd2cSJim Jagielski
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski# set DOITPROG to echo to test this script
28*b1cdbd2cSJim Jagielski
29*b1cdbd2cSJim Jagielski# Don't use :- since 4.3BSD and earlier shells don't like it.
30*b1cdbd2cSJim Jagielskidoit="${DOITPROG-}"
31*b1cdbd2cSJim Jagielski
32*b1cdbd2cSJim Jagielski
33*b1cdbd2cSJim Jagielski# put in absolute paths if you don't have them in your path; or use env. vars.
34*b1cdbd2cSJim Jagielski
35*b1cdbd2cSJim Jagielskimvprog="${MVPROG-mv}"
36*b1cdbd2cSJim Jagielskicpprog="${CPPROG-cp}"
37*b1cdbd2cSJim Jagielskichmodprog="${CHMODPROG-chmod}"
38*b1cdbd2cSJim Jagielskichownprog="${CHOWNPROG-chown}"
39*b1cdbd2cSJim Jagielskichgrpprog="${CHGRPPROG-chgrp}"
40*b1cdbd2cSJim Jagielskistripprog="${STRIPPROG-strip}"
41*b1cdbd2cSJim Jagielskirmprog="${RMPROG-rm}"
42*b1cdbd2cSJim Jagielskimkdirprog="${MKDIRPROG-mkdir}"
43*b1cdbd2cSJim Jagielski
44*b1cdbd2cSJim Jagielskitransformbasename=""
45*b1cdbd2cSJim Jagielskitransform_arg=""
46*b1cdbd2cSJim Jagielskiinstcmd="$mvprog"
47*b1cdbd2cSJim Jagielskichmodcmd="$chmodprog 0755"
48*b1cdbd2cSJim Jagielskichowncmd=""
49*b1cdbd2cSJim Jagielskichgrpcmd=""
50*b1cdbd2cSJim Jagielskistripcmd=""
51*b1cdbd2cSJim Jagielskirmcmd="$rmprog -f"
52*b1cdbd2cSJim Jagielskimvcmd="$mvprog"
53*b1cdbd2cSJim Jagielskisrc=""
54*b1cdbd2cSJim Jagielskidst=""
55*b1cdbd2cSJim Jagielskidir_arg=""
56*b1cdbd2cSJim Jagielski
57*b1cdbd2cSJim Jagielskiwhile [ x"$1" != x ]; do
58*b1cdbd2cSJim Jagielski    case $1 in
59*b1cdbd2cSJim Jagielski	-c) instcmd=$cpprog
60*b1cdbd2cSJim Jagielski	    shift
61*b1cdbd2cSJim Jagielski	    continue;;
62*b1cdbd2cSJim Jagielski
63*b1cdbd2cSJim Jagielski	-d) dir_arg=true
64*b1cdbd2cSJim Jagielski	    shift
65*b1cdbd2cSJim Jagielski	    continue;;
66*b1cdbd2cSJim Jagielski
67*b1cdbd2cSJim Jagielski	-m) chmodcmd="$chmodprog $2"
68*b1cdbd2cSJim Jagielski	    shift
69*b1cdbd2cSJim Jagielski	    shift
70*b1cdbd2cSJim Jagielski	    continue;;
71*b1cdbd2cSJim Jagielski
72*b1cdbd2cSJim Jagielski	-o) chowncmd="$chownprog $2"
73*b1cdbd2cSJim Jagielski	    shift
74*b1cdbd2cSJim Jagielski	    shift
75*b1cdbd2cSJim Jagielski	    continue;;
76*b1cdbd2cSJim Jagielski
77*b1cdbd2cSJim Jagielski	-g) chgrpcmd="$chgrpprog $2"
78*b1cdbd2cSJim Jagielski	    shift
79*b1cdbd2cSJim Jagielski	    shift
80*b1cdbd2cSJim Jagielski	    continue;;
81*b1cdbd2cSJim Jagielski
82*b1cdbd2cSJim Jagielski	-s) stripcmd=$stripprog
83*b1cdbd2cSJim Jagielski	    shift
84*b1cdbd2cSJim Jagielski	    continue;;
85*b1cdbd2cSJim Jagielski
86*b1cdbd2cSJim Jagielski	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
87*b1cdbd2cSJim Jagielski	    shift
88*b1cdbd2cSJim Jagielski	    continue;;
89*b1cdbd2cSJim Jagielski
90*b1cdbd2cSJim Jagielski	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
91*b1cdbd2cSJim Jagielski	    shift
92*b1cdbd2cSJim Jagielski	    continue;;
93*b1cdbd2cSJim Jagielski
94*b1cdbd2cSJim Jagielski	*)  if [ x"$src" = x ]
95*b1cdbd2cSJim Jagielski	    then
96*b1cdbd2cSJim Jagielski		src=$1
97*b1cdbd2cSJim Jagielski	    else
98*b1cdbd2cSJim Jagielski		# this colon is to work around a 386BSD /bin/sh bug
99*b1cdbd2cSJim Jagielski		:
100*b1cdbd2cSJim Jagielski		dst=$1
101*b1cdbd2cSJim Jagielski	    fi
102*b1cdbd2cSJim Jagielski	    shift
103*b1cdbd2cSJim Jagielski	    continue;;
104*b1cdbd2cSJim Jagielski    esac
105*b1cdbd2cSJim Jagielskidone
106*b1cdbd2cSJim Jagielski
107*b1cdbd2cSJim Jagielskiif [ x"$src" = x ]
108*b1cdbd2cSJim Jagielskithen
109*b1cdbd2cSJim Jagielski	echo "$0: no input file specified" >&2
110*b1cdbd2cSJim Jagielski	exit 1
111*b1cdbd2cSJim Jagielskielse
112*b1cdbd2cSJim Jagielski	:
113*b1cdbd2cSJim Jagielskifi
114*b1cdbd2cSJim Jagielski
115*b1cdbd2cSJim Jagielskiif [ x"$dir_arg" != x ]; then
116*b1cdbd2cSJim Jagielski	dst=$src
117*b1cdbd2cSJim Jagielski	src=""
118*b1cdbd2cSJim Jagielski
119*b1cdbd2cSJim Jagielski	if [ -d "$dst" ]; then
120*b1cdbd2cSJim Jagielski		instcmd=:
121*b1cdbd2cSJim Jagielski		chmodcmd=""
122*b1cdbd2cSJim Jagielski	else
123*b1cdbd2cSJim Jagielski		instcmd=$mkdirprog
124*b1cdbd2cSJim Jagielski	fi
125*b1cdbd2cSJim Jagielskielse
126*b1cdbd2cSJim Jagielski
127*b1cdbd2cSJim Jagielski# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
128*b1cdbd2cSJim Jagielski# might cause directories to be created, which would be especially bad
129*b1cdbd2cSJim Jagielski# if $src (and thus $dsttmp) contains '*'.
130*b1cdbd2cSJim Jagielski
131*b1cdbd2cSJim Jagielski	if [ -f "$src" ] || [ -d "$src" ]
132*b1cdbd2cSJim Jagielski	then
133*b1cdbd2cSJim Jagielski		:
134*b1cdbd2cSJim Jagielski	else
135*b1cdbd2cSJim Jagielski		echo "$0: $src does not exist" >&2
136*b1cdbd2cSJim Jagielski		exit 1
137*b1cdbd2cSJim Jagielski	fi
138*b1cdbd2cSJim Jagielski
139*b1cdbd2cSJim Jagielski	if [ x"$dst" = x ]
140*b1cdbd2cSJim Jagielski	then
141*b1cdbd2cSJim Jagielski		echo "$0: no destination specified" >&2
142*b1cdbd2cSJim Jagielski		exit 1
143*b1cdbd2cSJim Jagielski	else
144*b1cdbd2cSJim Jagielski		:
145*b1cdbd2cSJim Jagielski	fi
146*b1cdbd2cSJim Jagielski
147*b1cdbd2cSJim Jagielski# If destination is a directory, append the input filename; if your system
148*b1cdbd2cSJim Jagielski# does not like double slashes in filenames, you may need to add some logic
149*b1cdbd2cSJim Jagielski
150*b1cdbd2cSJim Jagielski	if [ -d "$dst" ]
151*b1cdbd2cSJim Jagielski	then
152*b1cdbd2cSJim Jagielski		dst=$dst/`basename "$src"`
153*b1cdbd2cSJim Jagielski	else
154*b1cdbd2cSJim Jagielski		:
155*b1cdbd2cSJim Jagielski	fi
156*b1cdbd2cSJim Jagielskifi
157*b1cdbd2cSJim Jagielski
158*b1cdbd2cSJim Jagielski## this sed command emulates the dirname command
159*b1cdbd2cSJim Jagielskidstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
160*b1cdbd2cSJim Jagielski
161*b1cdbd2cSJim Jagielski# Make sure that the destination directory exists.
162*b1cdbd2cSJim Jagielski#  this part is taken from Noah Friedman's mkinstalldirs script
163*b1cdbd2cSJim Jagielski
164*b1cdbd2cSJim Jagielski# Skip lots of stat calls in the usual case.
165*b1cdbd2cSJim Jagielskiif [ ! -d "$dstdir" ]; then
166*b1cdbd2cSJim JagielskidefaultIFS='
167*b1cdbd2cSJim Jagielski	'
168*b1cdbd2cSJim JagielskiIFS="${IFS-$defaultIFS}"
169*b1cdbd2cSJim Jagielski
170*b1cdbd2cSJim JagielskioIFS=$IFS
171*b1cdbd2cSJim Jagielski# Some sh's can't handle IFS=/ for some reason.
172*b1cdbd2cSJim JagielskiIFS='%'
173*b1cdbd2cSJim Jagielskiset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
174*b1cdbd2cSJim JagielskiIFS=$oIFS
175*b1cdbd2cSJim Jagielski
176*b1cdbd2cSJim Jagielskipathcomp=''
177*b1cdbd2cSJim Jagielski
178*b1cdbd2cSJim Jagielskiwhile [ $# -ne 0 ] ; do
179*b1cdbd2cSJim Jagielski	pathcomp=$pathcomp$1
180*b1cdbd2cSJim Jagielski	shift
181*b1cdbd2cSJim Jagielski
182*b1cdbd2cSJim Jagielski	if [ ! -d "$pathcomp" ] ;
183*b1cdbd2cSJim Jagielski        then
184*b1cdbd2cSJim Jagielski		$mkdirprog "$pathcomp"
185*b1cdbd2cSJim Jagielski	else
186*b1cdbd2cSJim Jagielski		:
187*b1cdbd2cSJim Jagielski	fi
188*b1cdbd2cSJim Jagielski
189*b1cdbd2cSJim Jagielski	pathcomp=$pathcomp/
190*b1cdbd2cSJim Jagielskidone
191*b1cdbd2cSJim Jagielskifi
192*b1cdbd2cSJim Jagielski
193*b1cdbd2cSJim Jagielskiif [ x"$dir_arg" != x ]
194*b1cdbd2cSJim Jagielskithen
195*b1cdbd2cSJim Jagielski	$doit $instcmd "$dst" &&
196*b1cdbd2cSJim Jagielski
197*b1cdbd2cSJim Jagielski	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
198*b1cdbd2cSJim Jagielski	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
199*b1cdbd2cSJim Jagielski	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
200*b1cdbd2cSJim Jagielski	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
201*b1cdbd2cSJim Jagielskielse
202*b1cdbd2cSJim Jagielski
203*b1cdbd2cSJim Jagielski# If we're going to rename the final executable, determine the name now.
204*b1cdbd2cSJim Jagielski
205*b1cdbd2cSJim Jagielski	if [ x"$transformarg" = x ]
206*b1cdbd2cSJim Jagielski	then
207*b1cdbd2cSJim Jagielski		dstfile=`basename "$dst"`
208*b1cdbd2cSJim Jagielski	else
209*b1cdbd2cSJim Jagielski		dstfile=`basename "$dst" $transformbasename |
210*b1cdbd2cSJim Jagielski			sed $transformarg`$transformbasename
211*b1cdbd2cSJim Jagielski	fi
212*b1cdbd2cSJim Jagielski
213*b1cdbd2cSJim Jagielski# don't allow the sed command to completely eliminate the filename
214*b1cdbd2cSJim Jagielski
215*b1cdbd2cSJim Jagielski	if [ x"$dstfile" = x ]
216*b1cdbd2cSJim Jagielski	then
217*b1cdbd2cSJim Jagielski		dstfile=`basename "$dst"`
218*b1cdbd2cSJim Jagielski	else
219*b1cdbd2cSJim Jagielski		:
220*b1cdbd2cSJim Jagielski	fi
221*b1cdbd2cSJim Jagielski
222*b1cdbd2cSJim Jagielski# Make a couple of temp file names in the proper directory.
223*b1cdbd2cSJim Jagielski
224*b1cdbd2cSJim Jagielski	dsttmp=$dstdir/#inst.$$#
225*b1cdbd2cSJim Jagielski	rmtmp=$dstdir/#rm.$$#
226*b1cdbd2cSJim Jagielski
227*b1cdbd2cSJim Jagielski# Trap to clean up temp files at exit.
228*b1cdbd2cSJim Jagielski
229*b1cdbd2cSJim Jagielski	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
230*b1cdbd2cSJim Jagielski	trap '(exit $?); exit' 1 2 13 15
231*b1cdbd2cSJim Jagielski
232*b1cdbd2cSJim Jagielski# Move or copy the file name to the temp name
233*b1cdbd2cSJim Jagielski
234*b1cdbd2cSJim Jagielski	$doit $instcmd "$src" "$dsttmp" &&
235*b1cdbd2cSJim Jagielski
236*b1cdbd2cSJim Jagielski# and set any options; do chmod last to preserve setuid bits
237*b1cdbd2cSJim Jagielski
238*b1cdbd2cSJim Jagielski# If any of these fail, we abort the whole thing.  If we want to
239*b1cdbd2cSJim Jagielski# ignore errors from any of these, just make sure not to ignore
240*b1cdbd2cSJim Jagielski# errors from the above "$doit $instcmd $src $dsttmp" command.
241*b1cdbd2cSJim Jagielski
242*b1cdbd2cSJim Jagielski	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
243*b1cdbd2cSJim Jagielski	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
244*b1cdbd2cSJim Jagielski	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
245*b1cdbd2cSJim Jagielski	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
246*b1cdbd2cSJim Jagielski
247*b1cdbd2cSJim Jagielski# Now remove or move aside any old file at destination location.  We try this
248*b1cdbd2cSJim Jagielski# two ways since rm can't unlink itself on some systems and the destination
249*b1cdbd2cSJim Jagielski# file might be busy for other reasons.  In this case, the final cleanup
250*b1cdbd2cSJim Jagielski# might fail but the new file should still install successfully.
251*b1cdbd2cSJim Jagielski
252*b1cdbd2cSJim Jagielski{
253*b1cdbd2cSJim Jagielski	if [ -f "$dstdir/$dstfile" ]
254*b1cdbd2cSJim Jagielski	then
255*b1cdbd2cSJim Jagielski		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
256*b1cdbd2cSJim Jagielski		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
257*b1cdbd2cSJim Jagielski		{
258*b1cdbd2cSJim Jagielski		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
259*b1cdbd2cSJim Jagielski		  (exit 1); exit
260*b1cdbd2cSJim Jagielski		}
261*b1cdbd2cSJim Jagielski	else
262*b1cdbd2cSJim Jagielski		:
263*b1cdbd2cSJim Jagielski	fi
264*b1cdbd2cSJim Jagielski} &&
265*b1cdbd2cSJim Jagielski
266*b1cdbd2cSJim Jagielski# Now rename the file to the real destination.
267*b1cdbd2cSJim Jagielski
268*b1cdbd2cSJim Jagielski	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
269*b1cdbd2cSJim Jagielski
270*b1cdbd2cSJim Jagielskifi &&
271*b1cdbd2cSJim Jagielski
272*b1cdbd2cSJim Jagielski# The final little trick to "correctly" pass the exit status to the exit trap.
273*b1cdbd2cSJim Jagielski
274*b1cdbd2cSJim Jagielski{
275*b1cdbd2cSJim Jagielski	(exit 0); exit
276*b1cdbd2cSJim Jagielski}
277