install-sh revision b1297603
1b1297603Smrg#!/bin/sh
2b1297603Smrg# install - install a program, script, or datafile
3b1297603Smrg
4b1297603Smrgscriptversion=2005-05-14.22
5b1297603Smrg
6b1297603Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7b1297603Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8b1297603Smrg# following copyright and license.
9b1297603Smrg#
10b1297603Smrg# Copyright (C) 1994 X Consortium
11b1297603Smrg#
12b1297603Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13b1297603Smrg# of this software and associated documentation files (the "Software"), to
14b1297603Smrg# deal in the Software without restriction, including without limitation the
15b1297603Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16b1297603Smrg# sell copies of the Software, and to permit persons to whom the Software is
17b1297603Smrg# furnished to do so, subject to the following conditions:
18b1297603Smrg#
19b1297603Smrg# The above copyright notice and this permission notice shall be included in
20b1297603Smrg# all copies or substantial portions of the Software.
21b1297603Smrg#
22b1297603Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23b1297603Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24b1297603Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25b1297603Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26b1297603Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27b1297603Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28b1297603Smrg#
29b1297603Smrg# Except as contained in this notice, the name of the X Consortium shall not
30b1297603Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31b1297603Smrg# ings in this Software without prior written authorization from the X Consor-
32b1297603Smrg# tium.
33b1297603Smrg#
34b1297603Smrg#
35b1297603Smrg# FSF changes to this file are in the public domain.
36b1297603Smrg#
37b1297603Smrg# Calling this script install-sh is preferred over install.sh, to prevent
38b1297603Smrg# `make' implicit rules from creating a file called install from it
39b1297603Smrg# when there is no Makefile.
40b1297603Smrg#
41b1297603Smrg# This script is compatible with the BSD install script, but was written
42b1297603Smrg# from scratch.  It can only install one file at a time, a restriction
43b1297603Smrg# shared with many OS's install programs.
44b1297603Smrg
45b1297603Smrg# set DOITPROG to echo to test this script
46b1297603Smrg
47b1297603Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48b1297603Smrgdoit="${DOITPROG-}"
49b1297603Smrg
50b1297603Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
51b1297603Smrg
52b1297603Smrgmvprog="${MVPROG-mv}"
53b1297603Smrgcpprog="${CPPROG-cp}"
54b1297603Smrgchmodprog="${CHMODPROG-chmod}"
55b1297603Smrgchownprog="${CHOWNPROG-chown}"
56b1297603Smrgchgrpprog="${CHGRPPROG-chgrp}"
57b1297603Smrgstripprog="${STRIPPROG-strip}"
58b1297603Smrgrmprog="${RMPROG-rm}"
59b1297603Smrgmkdirprog="${MKDIRPROG-mkdir}"
60b1297603Smrg
61b1297603Smrgchmodcmd="$chmodprog 0755"
62b1297603Smrgchowncmd=
63b1297603Smrgchgrpcmd=
64b1297603Smrgstripcmd=
65b1297603Smrgrmcmd="$rmprog -f"
66b1297603Smrgmvcmd="$mvprog"
67b1297603Smrgsrc=
68b1297603Smrgdst=
69b1297603Smrgdir_arg=
70b1297603Smrgdstarg=
71b1297603Smrgno_target_directory=
72b1297603Smrg
73b1297603Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74b1297603Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
75b1297603Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76b1297603Smrg   or: $0 [OPTION]... -d DIRECTORIES...
77b1297603Smrg
78b1297603SmrgIn the 1st form, copy SRCFILE to DSTFILE.
79b1297603SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80b1297603SmrgIn the 4th, create DIRECTORIES.
81b1297603Smrg
82b1297603SmrgOptions:
83b1297603Smrg-c         (ignored)
84b1297603Smrg-d         create directories instead of installing files.
85b1297603Smrg-g GROUP   $chgrpprog installed files to GROUP.
86b1297603Smrg-m MODE    $chmodprog installed files to MODE.
87b1297603Smrg-o USER    $chownprog installed files to USER.
88b1297603Smrg-s         $stripprog installed files.
89b1297603Smrg-t DIRECTORY  install into DIRECTORY.
90b1297603Smrg-T         report an error if DSTFILE is a directory.
91b1297603Smrg--help     display this help and exit.
92b1297603Smrg--version  display version info and exit.
93b1297603Smrg
94b1297603SmrgEnvironment variables override the default commands:
95b1297603Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96b1297603Smrg"
97b1297603Smrg
98b1297603Smrgwhile test -n "$1"; do
99b1297603Smrg  case $1 in
100b1297603Smrg    -c) shift
101b1297603Smrg        continue;;
102b1297603Smrg
103b1297603Smrg    -d) dir_arg=true
104b1297603Smrg        shift
105b1297603Smrg        continue;;
106b1297603Smrg
107b1297603Smrg    -g) chgrpcmd="$chgrpprog $2"
108b1297603Smrg        shift
109b1297603Smrg        shift
110b1297603Smrg        continue;;
111b1297603Smrg
112b1297603Smrg    --help) echo "$usage"; exit $?;;
113b1297603Smrg
114b1297603Smrg    -m) chmodcmd="$chmodprog $2"
115b1297603Smrg        shift
116b1297603Smrg        shift
117b1297603Smrg        continue;;
118b1297603Smrg
119b1297603Smrg    -o) chowncmd="$chownprog $2"
120b1297603Smrg        shift
121b1297603Smrg        shift
122b1297603Smrg        continue;;
123b1297603Smrg
124b1297603Smrg    -s) stripcmd=$stripprog
125b1297603Smrg        shift
126b1297603Smrg        continue;;
127b1297603Smrg
128b1297603Smrg    -t) dstarg=$2
129b1297603Smrg	shift
130b1297603Smrg	shift
131b1297603Smrg	continue;;
132b1297603Smrg
133b1297603Smrg    -T) no_target_directory=true
134b1297603Smrg	shift
135b1297603Smrg	continue;;
136b1297603Smrg
137b1297603Smrg    --version) echo "$0 $scriptversion"; exit $?;;
138b1297603Smrg
139b1297603Smrg    *)  # When -d is used, all remaining arguments are directories to create.
140b1297603Smrg	# When -t is used, the destination is already specified.
141b1297603Smrg	test -n "$dir_arg$dstarg" && break
142b1297603Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
143b1297603Smrg	for arg
144b1297603Smrg	do
145b1297603Smrg          if test -n "$dstarg"; then
146b1297603Smrg	    # $@ is not empty: it contains at least $arg.
147b1297603Smrg	    set fnord "$@" "$dstarg"
148b1297603Smrg	    shift # fnord
149b1297603Smrg	  fi
150b1297603Smrg	  shift # arg
151b1297603Smrg	  dstarg=$arg
152b1297603Smrg	done
153b1297603Smrg	break;;
154b1297603Smrg  esac
155b1297603Smrgdone
156b1297603Smrg
157b1297603Smrgif test -z "$1"; then
158b1297603Smrg  if test -z "$dir_arg"; then
159b1297603Smrg    echo "$0: no input file specified." >&2
160b1297603Smrg    exit 1
161b1297603Smrg  fi
162b1297603Smrg  # It's OK to call `install-sh -d' without argument.
163b1297603Smrg  # This can happen when creating conditional directories.
164b1297603Smrg  exit 0
165b1297603Smrgfi
166b1297603Smrg
167b1297603Smrgfor src
168b1297603Smrgdo
169b1297603Smrg  # Protect names starting with `-'.
170b1297603Smrg  case $src in
171b1297603Smrg    -*) src=./$src ;;
172b1297603Smrg  esac
173b1297603Smrg
174b1297603Smrg  if test -n "$dir_arg"; then
175b1297603Smrg    dst=$src
176b1297603Smrg    src=
177b1297603Smrg
178b1297603Smrg    if test -d "$dst"; then
179b1297603Smrg      mkdircmd=:
180b1297603Smrg      chmodcmd=
181b1297603Smrg    else
182b1297603Smrg      mkdircmd=$mkdirprog
183b1297603Smrg    fi
184b1297603Smrg  else
185b1297603Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186b1297603Smrg    # might cause directories to be created, which would be especially bad
187b1297603Smrg    # if $src (and thus $dsttmp) contains '*'.
188b1297603Smrg    if test ! -f "$src" && test ! -d "$src"; then
189b1297603Smrg      echo "$0: $src does not exist." >&2
190b1297603Smrg      exit 1
191b1297603Smrg    fi
192b1297603Smrg
193b1297603Smrg    if test -z "$dstarg"; then
194b1297603Smrg      echo "$0: no destination specified." >&2
195b1297603Smrg      exit 1
196b1297603Smrg    fi
197b1297603Smrg
198b1297603Smrg    dst=$dstarg
199b1297603Smrg    # Protect names starting with `-'.
200b1297603Smrg    case $dst in
201b1297603Smrg      -*) dst=./$dst ;;
202b1297603Smrg    esac
203b1297603Smrg
204b1297603Smrg    # If destination is a directory, append the input filename; won't work
205b1297603Smrg    # if double slashes aren't ignored.
206b1297603Smrg    if test -d "$dst"; then
207b1297603Smrg      if test -n "$no_target_directory"; then
208b1297603Smrg	echo "$0: $dstarg: Is a directory" >&2
209b1297603Smrg	exit 1
210b1297603Smrg      fi
211b1297603Smrg      dst=$dst/`basename "$src"`
212b1297603Smrg    fi
213b1297603Smrg  fi
214b1297603Smrg
215b1297603Smrg  # This sed command emulates the dirname command.
216b1297603Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217b1297603Smrg
218b1297603Smrg  # Make sure that the destination directory exists.
219b1297603Smrg
220b1297603Smrg  # Skip lots of stat calls in the usual case.
221b1297603Smrg  if test ! -d "$dstdir"; then
222b1297603Smrg    defaultIFS='
223b1297603Smrg	 '
224b1297603Smrg    IFS="${IFS-$defaultIFS}"
225b1297603Smrg
226b1297603Smrg    oIFS=$IFS
227b1297603Smrg    # Some sh's can't handle IFS=/ for some reason.
228b1297603Smrg    IFS='%'
229b1297603Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230b1297603Smrg    shift
231b1297603Smrg    IFS=$oIFS
232b1297603Smrg
233b1297603Smrg    pathcomp=
234b1297603Smrg
235b1297603Smrg    while test $# -ne 0 ; do
236b1297603Smrg      pathcomp=$pathcomp$1
237b1297603Smrg      shift
238b1297603Smrg      if test ! -d "$pathcomp"; then
239b1297603Smrg        $mkdirprog "$pathcomp"
240b1297603Smrg	# mkdir can fail with a `File exist' error in case several
241b1297603Smrg	# install-sh are creating the directory concurrently.  This
242b1297603Smrg	# is OK.
243b1297603Smrg	test -d "$pathcomp" || exit
244b1297603Smrg      fi
245b1297603Smrg      pathcomp=$pathcomp/
246b1297603Smrg    done
247b1297603Smrg  fi
248b1297603Smrg
249b1297603Smrg  if test -n "$dir_arg"; then
250b1297603Smrg    $doit $mkdircmd "$dst" \
251b1297603Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252b1297603Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253b1297603Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254b1297603Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255b1297603Smrg
256b1297603Smrg  else
257b1297603Smrg    dstfile=`basename "$dst"`
258b1297603Smrg
259b1297603Smrg    # Make a couple of temp file names in the proper directory.
260b1297603Smrg    dsttmp=$dstdir/_inst.$$_
261b1297603Smrg    rmtmp=$dstdir/_rm.$$_
262b1297603Smrg
263b1297603Smrg    # Trap to clean up those temp files at exit.
264b1297603Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265b1297603Smrg    trap '(exit $?); exit' 1 2 13 15
266b1297603Smrg
267b1297603Smrg    # Copy the file name to the temp name.
268b1297603Smrg    $doit $cpprog "$src" "$dsttmp" &&
269b1297603Smrg
270b1297603Smrg    # and set any options; do chmod last to preserve setuid bits.
271b1297603Smrg    #
272b1297603Smrg    # If any of these fail, we abort the whole thing.  If we want to
273b1297603Smrg    # ignore errors from any of these, just make sure not to ignore
274b1297603Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
275b1297603Smrg    #
276b1297603Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277b1297603Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278b1297603Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279b1297603Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280b1297603Smrg
281b1297603Smrg    # Now rename the file to the real destination.
282b1297603Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283b1297603Smrg      || {
284b1297603Smrg	   # The rename failed, perhaps because mv can't rename something else
285b1297603Smrg	   # to itself, or perhaps because mv is so ancient that it does not
286b1297603Smrg	   # support -f.
287b1297603Smrg
288b1297603Smrg	   # Now remove or move aside any old file at destination location.
289b1297603Smrg	   # We try this two ways since rm can't unlink itself on some
290b1297603Smrg	   # systems and the destination file might be busy for other
291b1297603Smrg	   # reasons.  In this case, the final cleanup might fail but the new
292b1297603Smrg	   # file should still install successfully.
293b1297603Smrg	   {
294b1297603Smrg	     if test -f "$dstdir/$dstfile"; then
295b1297603Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296b1297603Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297b1297603Smrg	       || {
298b1297603Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299b1297603Smrg		 (exit 1); exit 1
300b1297603Smrg	       }
301b1297603Smrg	     else
302b1297603Smrg	       :
303b1297603Smrg	     fi
304b1297603Smrg	   } &&
305b1297603Smrg
306b1297603Smrg	   # Now rename the file to the real destination.
307b1297603Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308b1297603Smrg	 }
309b1297603Smrg    }
310b1297603Smrg  fi || { (exit 1); exit 1; }
311b1297603Smrgdone
312b1297603Smrg
313b1297603Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
314b1297603Smrg{
315b1297603Smrg  (exit 0); exit 0
316b1297603Smrg}
317b1297603Smrg
318b1297603Smrg# Local variables:
319b1297603Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
320b1297603Smrg# time-stamp-start: "scriptversion="
321b1297603Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
322b1297603Smrg# time-stamp-end: "$"
323b1297603Smrg# End:
324