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