install-sh revision 876ff6fe
1876ff6feSmrg#!/bin/sh
2876ff6feSmrg# install - install a program, script, or datafile
3876ff6feSmrg
4876ff6feSmrgscriptversion=2005-05-14.22
5876ff6feSmrg
6876ff6feSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7876ff6feSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8876ff6feSmrg# following copyright and license.
9876ff6feSmrg#
10876ff6feSmrg# Copyright (C) 1994 X Consortium
11876ff6feSmrg#
12876ff6feSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13876ff6feSmrg# of this software and associated documentation files (the "Software"), to
14876ff6feSmrg# deal in the Software without restriction, including without limitation the
15876ff6feSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16876ff6feSmrg# sell copies of the Software, and to permit persons to whom the Software is
17876ff6feSmrg# furnished to do so, subject to the following conditions:
18876ff6feSmrg#
19876ff6feSmrg# The above copyright notice and this permission notice shall be included in
20876ff6feSmrg# all copies or substantial portions of the Software.
21876ff6feSmrg#
22876ff6feSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23876ff6feSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24876ff6feSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25876ff6feSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26876ff6feSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27876ff6feSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28876ff6feSmrg#
29876ff6feSmrg# Except as contained in this notice, the name of the X Consortium shall not
30876ff6feSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31876ff6feSmrg# ings in this Software without prior written authorization from the X Consor-
32876ff6feSmrg# tium.
33876ff6feSmrg#
34876ff6feSmrg#
35876ff6feSmrg# FSF changes to this file are in the public domain.
36876ff6feSmrg#
37876ff6feSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38876ff6feSmrg# `make' implicit rules from creating a file called install from it
39876ff6feSmrg# when there is no Makefile.
40876ff6feSmrg#
41876ff6feSmrg# This script is compatible with the BSD install script, but was written
42876ff6feSmrg# from scratch.  It can only install one file at a time, a restriction
43876ff6feSmrg# shared with many OS's install programs.
44876ff6feSmrg
45876ff6feSmrg# set DOITPROG to echo to test this script
46876ff6feSmrg
47876ff6feSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48876ff6feSmrgdoit="${DOITPROG-}"
49876ff6feSmrg
50876ff6feSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
51876ff6feSmrg
52876ff6feSmrgmvprog="${MVPROG-mv}"
53876ff6feSmrgcpprog="${CPPROG-cp}"
54876ff6feSmrgchmodprog="${CHMODPROG-chmod}"
55876ff6feSmrgchownprog="${CHOWNPROG-chown}"
56876ff6feSmrgchgrpprog="${CHGRPPROG-chgrp}"
57876ff6feSmrgstripprog="${STRIPPROG-strip}"
58876ff6feSmrgrmprog="${RMPROG-rm}"
59876ff6feSmrgmkdirprog="${MKDIRPROG-mkdir}"
60876ff6feSmrg
61876ff6feSmrgchmodcmd="$chmodprog 0755"
62876ff6feSmrgchowncmd=
63876ff6feSmrgchgrpcmd=
64876ff6feSmrgstripcmd=
65876ff6feSmrgrmcmd="$rmprog -f"
66876ff6feSmrgmvcmd="$mvprog"
67876ff6feSmrgsrc=
68876ff6feSmrgdst=
69876ff6feSmrgdir_arg=
70876ff6feSmrgdstarg=
71876ff6feSmrgno_target_directory=
72876ff6feSmrg
73876ff6feSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74876ff6feSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
75876ff6feSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76876ff6feSmrg   or: $0 [OPTION]... -d DIRECTORIES...
77876ff6feSmrg
78876ff6feSmrgIn the 1st form, copy SRCFILE to DSTFILE.
79876ff6feSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80876ff6feSmrgIn the 4th, create DIRECTORIES.
81876ff6feSmrg
82876ff6feSmrgOptions:
83876ff6feSmrg-c         (ignored)
84876ff6feSmrg-d         create directories instead of installing files.
85876ff6feSmrg-g GROUP   $chgrpprog installed files to GROUP.
86876ff6feSmrg-m MODE    $chmodprog installed files to MODE.
87876ff6feSmrg-o USER    $chownprog installed files to USER.
88876ff6feSmrg-s         $stripprog installed files.
89876ff6feSmrg-t DIRECTORY  install into DIRECTORY.
90876ff6feSmrg-T         report an error if DSTFILE is a directory.
91876ff6feSmrg--help     display this help and exit.
92876ff6feSmrg--version  display version info and exit.
93876ff6feSmrg
94876ff6feSmrgEnvironment variables override the default commands:
95876ff6feSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96876ff6feSmrg"
97876ff6feSmrg
98876ff6feSmrgwhile test -n "$1"; do
99876ff6feSmrg  case $1 in
100876ff6feSmrg    -c) shift
101876ff6feSmrg        continue;;
102876ff6feSmrg
103876ff6feSmrg    -d) dir_arg=true
104876ff6feSmrg        shift
105876ff6feSmrg        continue;;
106876ff6feSmrg
107876ff6feSmrg    -g) chgrpcmd="$chgrpprog $2"
108876ff6feSmrg        shift
109876ff6feSmrg        shift
110876ff6feSmrg        continue;;
111876ff6feSmrg
112876ff6feSmrg    --help) echo "$usage"; exit $?;;
113876ff6feSmrg
114876ff6feSmrg    -m) chmodcmd="$chmodprog $2"
115876ff6feSmrg        shift
116876ff6feSmrg        shift
117876ff6feSmrg        continue;;
118876ff6feSmrg
119876ff6feSmrg    -o) chowncmd="$chownprog $2"
120876ff6feSmrg        shift
121876ff6feSmrg        shift
122876ff6feSmrg        continue;;
123876ff6feSmrg
124876ff6feSmrg    -s) stripcmd=$stripprog
125876ff6feSmrg        shift
126876ff6feSmrg        continue;;
127876ff6feSmrg
128876ff6feSmrg    -t) dstarg=$2
129876ff6feSmrg	shift
130876ff6feSmrg	shift
131876ff6feSmrg	continue;;
132876ff6feSmrg
133876ff6feSmrg    -T) no_target_directory=true
134876ff6feSmrg	shift
135876ff6feSmrg	continue;;
136876ff6feSmrg
137876ff6feSmrg    --version) echo "$0 $scriptversion"; exit $?;;
138876ff6feSmrg
139876ff6feSmrg    *)  # When -d is used, all remaining arguments are directories to create.
140876ff6feSmrg	# When -t is used, the destination is already specified.
141876ff6feSmrg	test -n "$dir_arg$dstarg" && break
142876ff6feSmrg        # Otherwise, the last argument is the destination.  Remove it from $@.
143876ff6feSmrg	for arg
144876ff6feSmrg	do
145876ff6feSmrg          if test -n "$dstarg"; then
146876ff6feSmrg	    # $@ is not empty: it contains at least $arg.
147876ff6feSmrg	    set fnord "$@" "$dstarg"
148876ff6feSmrg	    shift # fnord
149876ff6feSmrg	  fi
150876ff6feSmrg	  shift # arg
151876ff6feSmrg	  dstarg=$arg
152876ff6feSmrg	done
153876ff6feSmrg	break;;
154876ff6feSmrg  esac
155876ff6feSmrgdone
156876ff6feSmrg
157876ff6feSmrgif test -z "$1"; then
158876ff6feSmrg  if test -z "$dir_arg"; then
159876ff6feSmrg    echo "$0: no input file specified." >&2
160876ff6feSmrg    exit 1
161876ff6feSmrg  fi
162876ff6feSmrg  # It's OK to call `install-sh -d' without argument.
163876ff6feSmrg  # This can happen when creating conditional directories.
164876ff6feSmrg  exit 0
165876ff6feSmrgfi
166876ff6feSmrg
167876ff6feSmrgfor src
168876ff6feSmrgdo
169876ff6feSmrg  # Protect names starting with `-'.
170876ff6feSmrg  case $src in
171876ff6feSmrg    -*) src=./$src ;;
172876ff6feSmrg  esac
173876ff6feSmrg
174876ff6feSmrg  if test -n "$dir_arg"; then
175876ff6feSmrg    dst=$src
176876ff6feSmrg    src=
177876ff6feSmrg
178876ff6feSmrg    if test -d "$dst"; then
179876ff6feSmrg      mkdircmd=:
180876ff6feSmrg      chmodcmd=
181876ff6feSmrg    else
182876ff6feSmrg      mkdircmd=$mkdirprog
183876ff6feSmrg    fi
184876ff6feSmrg  else
185876ff6feSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186876ff6feSmrg    # might cause directories to be created, which would be especially bad
187876ff6feSmrg    # if $src (and thus $dsttmp) contains '*'.
188876ff6feSmrg    if test ! -f "$src" && test ! -d "$src"; then
189876ff6feSmrg      echo "$0: $src does not exist." >&2
190876ff6feSmrg      exit 1
191876ff6feSmrg    fi
192876ff6feSmrg
193876ff6feSmrg    if test -z "$dstarg"; then
194876ff6feSmrg      echo "$0: no destination specified." >&2
195876ff6feSmrg      exit 1
196876ff6feSmrg    fi
197876ff6feSmrg
198876ff6feSmrg    dst=$dstarg
199876ff6feSmrg    # Protect names starting with `-'.
200876ff6feSmrg    case $dst in
201876ff6feSmrg      -*) dst=./$dst ;;
202876ff6feSmrg    esac
203876ff6feSmrg
204876ff6feSmrg    # If destination is a directory, append the input filename; won't work
205876ff6feSmrg    # if double slashes aren't ignored.
206876ff6feSmrg    if test -d "$dst"; then
207876ff6feSmrg      if test -n "$no_target_directory"; then
208876ff6feSmrg	echo "$0: $dstarg: Is a directory" >&2
209876ff6feSmrg	exit 1
210876ff6feSmrg      fi
211876ff6feSmrg      dst=$dst/`basename "$src"`
212876ff6feSmrg    fi
213876ff6feSmrg  fi
214876ff6feSmrg
215876ff6feSmrg  # This sed command emulates the dirname command.
216876ff6feSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217876ff6feSmrg
218876ff6feSmrg  # Make sure that the destination directory exists.
219876ff6feSmrg
220876ff6feSmrg  # Skip lots of stat calls in the usual case.
221876ff6feSmrg  if test ! -d "$dstdir"; then
222876ff6feSmrg    defaultIFS='
223876ff6feSmrg	 '
224876ff6feSmrg    IFS="${IFS-$defaultIFS}"
225876ff6feSmrg
226876ff6feSmrg    oIFS=$IFS
227876ff6feSmrg    # Some sh's can't handle IFS=/ for some reason.
228876ff6feSmrg    IFS='%'
229876ff6feSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230876ff6feSmrg    shift
231876ff6feSmrg    IFS=$oIFS
232876ff6feSmrg
233876ff6feSmrg    pathcomp=
234876ff6feSmrg
235876ff6feSmrg    while test $# -ne 0 ; do
236876ff6feSmrg      pathcomp=$pathcomp$1
237876ff6feSmrg      shift
238876ff6feSmrg      if test ! -d "$pathcomp"; then
239876ff6feSmrg        $mkdirprog "$pathcomp"
240876ff6feSmrg	# mkdir can fail with a `File exist' error in case several
241876ff6feSmrg	# install-sh are creating the directory concurrently.  This
242876ff6feSmrg	# is OK.
243876ff6feSmrg	test -d "$pathcomp" || exit
244876ff6feSmrg      fi
245876ff6feSmrg      pathcomp=$pathcomp/
246876ff6feSmrg    done
247876ff6feSmrg  fi
248876ff6feSmrg
249876ff6feSmrg  if test -n "$dir_arg"; then
250876ff6feSmrg    $doit $mkdircmd "$dst" \
251876ff6feSmrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252876ff6feSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253876ff6feSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254876ff6feSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255876ff6feSmrg
256876ff6feSmrg  else
257876ff6feSmrg    dstfile=`basename "$dst"`
258876ff6feSmrg
259876ff6feSmrg    # Make a couple of temp file names in the proper directory.
260876ff6feSmrg    dsttmp=$dstdir/_inst.$$_
261876ff6feSmrg    rmtmp=$dstdir/_rm.$$_
262876ff6feSmrg
263876ff6feSmrg    # Trap to clean up those temp files at exit.
264876ff6feSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265876ff6feSmrg    trap '(exit $?); exit' 1 2 13 15
266876ff6feSmrg
267876ff6feSmrg    # Copy the file name to the temp name.
268876ff6feSmrg    $doit $cpprog "$src" "$dsttmp" &&
269876ff6feSmrg
270876ff6feSmrg    # and set any options; do chmod last to preserve setuid bits.
271876ff6feSmrg    #
272876ff6feSmrg    # If any of these fail, we abort the whole thing.  If we want to
273876ff6feSmrg    # ignore errors from any of these, just make sure not to ignore
274876ff6feSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
275876ff6feSmrg    #
276876ff6feSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277876ff6feSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278876ff6feSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279876ff6feSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280876ff6feSmrg
281876ff6feSmrg    # Now rename the file to the real destination.
282876ff6feSmrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283876ff6feSmrg      || {
284876ff6feSmrg	   # The rename failed, perhaps because mv can't rename something else
285876ff6feSmrg	   # to itself, or perhaps because mv is so ancient that it does not
286876ff6feSmrg	   # support -f.
287876ff6feSmrg
288876ff6feSmrg	   # Now remove or move aside any old file at destination location.
289876ff6feSmrg	   # We try this two ways since rm can't unlink itself on some
290876ff6feSmrg	   # systems and the destination file might be busy for other
291876ff6feSmrg	   # reasons.  In this case, the final cleanup might fail but the new
292876ff6feSmrg	   # file should still install successfully.
293876ff6feSmrg	   {
294876ff6feSmrg	     if test -f "$dstdir/$dstfile"; then
295876ff6feSmrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296876ff6feSmrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297876ff6feSmrg	       || {
298876ff6feSmrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299876ff6feSmrg		 (exit 1); exit 1
300876ff6feSmrg	       }
301876ff6feSmrg	     else
302876ff6feSmrg	       :
303876ff6feSmrg	     fi
304876ff6feSmrg	   } &&
305876ff6feSmrg
306876ff6feSmrg	   # Now rename the file to the real destination.
307876ff6feSmrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308876ff6feSmrg	 }
309876ff6feSmrg    }
310876ff6feSmrg  fi || { (exit 1); exit 1; }
311876ff6feSmrgdone
312876ff6feSmrg
313876ff6feSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
314876ff6feSmrg{
315876ff6feSmrg  (exit 0); exit 0
316876ff6feSmrg}
317876ff6feSmrg
318876ff6feSmrg# Local variables:
319876ff6feSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
320876ff6feSmrg# time-stamp-start: "scriptversion="
321876ff6feSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
322876ff6feSmrg# time-stamp-end: "$"
323876ff6feSmrg# End:
324