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