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