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