install-sh revision 301ea0f4
1301ea0f4Smrg#!/bin/sh
2301ea0f4Smrg# install - install a program, script, or datafile
3301ea0f4Smrg
4301ea0f4Smrgscriptversion=2005-05-14.22
5301ea0f4Smrg
6301ea0f4Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7301ea0f4Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8301ea0f4Smrg# following copyright and license.
9301ea0f4Smrg#
10301ea0f4Smrg# Copyright (C) 1994 X Consortium
11301ea0f4Smrg#
12301ea0f4Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13301ea0f4Smrg# of this software and associated documentation files (the "Software"), to
14301ea0f4Smrg# deal in the Software without restriction, including without limitation the
15301ea0f4Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16301ea0f4Smrg# sell copies of the Software, and to permit persons to whom the Software is
17301ea0f4Smrg# furnished to do so, subject to the following conditions:
18301ea0f4Smrg#
19301ea0f4Smrg# The above copyright notice and this permission notice shall be included in
20301ea0f4Smrg# all copies or substantial portions of the Software.
21301ea0f4Smrg#
22301ea0f4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23301ea0f4Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24301ea0f4Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25301ea0f4Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26301ea0f4Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27301ea0f4Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28301ea0f4Smrg#
29301ea0f4Smrg# Except as contained in this notice, the name of the X Consortium shall not
30301ea0f4Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31301ea0f4Smrg# ings in this Software without prior written authorization from the X Consor-
32301ea0f4Smrg# tium.
33301ea0f4Smrg#
34301ea0f4Smrg#
35301ea0f4Smrg# FSF changes to this file are in the public domain.
36301ea0f4Smrg#
37301ea0f4Smrg# Calling this script install-sh is preferred over install.sh, to prevent
38301ea0f4Smrg# `make' implicit rules from creating a file called install from it
39301ea0f4Smrg# when there is no Makefile.
40301ea0f4Smrg#
41301ea0f4Smrg# This script is compatible with the BSD install script, but was written
42301ea0f4Smrg# from scratch.  It can only install one file at a time, a restriction
43301ea0f4Smrg# shared with many OS's install programs.
44301ea0f4Smrg
45301ea0f4Smrg# set DOITPROG to echo to test this script
46301ea0f4Smrg
47301ea0f4Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48301ea0f4Smrgdoit="${DOITPROG-}"
49301ea0f4Smrg
50301ea0f4Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
51301ea0f4Smrg
52301ea0f4Smrgmvprog="${MVPROG-mv}"
53301ea0f4Smrgcpprog="${CPPROG-cp}"
54301ea0f4Smrgchmodprog="${CHMODPROG-chmod}"
55301ea0f4Smrgchownprog="${CHOWNPROG-chown}"
56301ea0f4Smrgchgrpprog="${CHGRPPROG-chgrp}"
57301ea0f4Smrgstripprog="${STRIPPROG-strip}"
58301ea0f4Smrgrmprog="${RMPROG-rm}"
59301ea0f4Smrgmkdirprog="${MKDIRPROG-mkdir}"
60301ea0f4Smrg
61301ea0f4Smrgchmodcmd="$chmodprog 0755"
62301ea0f4Smrgchowncmd=
63301ea0f4Smrgchgrpcmd=
64301ea0f4Smrgstripcmd=
65301ea0f4Smrgrmcmd="$rmprog -f"
66301ea0f4Smrgmvcmd="$mvprog"
67301ea0f4Smrgsrc=
68301ea0f4Smrgdst=
69301ea0f4Smrgdir_arg=
70301ea0f4Smrgdstarg=
71301ea0f4Smrgno_target_directory=
72301ea0f4Smrg
73301ea0f4Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74301ea0f4Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
75301ea0f4Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76301ea0f4Smrg   or: $0 [OPTION]... -d DIRECTORIES...
77301ea0f4Smrg
78301ea0f4SmrgIn the 1st form, copy SRCFILE to DSTFILE.
79301ea0f4SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80301ea0f4SmrgIn the 4th, create DIRECTORIES.
81301ea0f4Smrg
82301ea0f4SmrgOptions:
83301ea0f4Smrg-c         (ignored)
84301ea0f4Smrg-d         create directories instead of installing files.
85301ea0f4Smrg-g GROUP   $chgrpprog installed files to GROUP.
86301ea0f4Smrg-m MODE    $chmodprog installed files to MODE.
87301ea0f4Smrg-o USER    $chownprog installed files to USER.
88301ea0f4Smrg-s         $stripprog installed files.
89301ea0f4Smrg-t DIRECTORY  install into DIRECTORY.
90301ea0f4Smrg-T         report an error if DSTFILE is a directory.
91301ea0f4Smrg--help     display this help and exit.
92301ea0f4Smrg--version  display version info and exit.
93301ea0f4Smrg
94301ea0f4SmrgEnvironment variables override the default commands:
95301ea0f4Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96301ea0f4Smrg"
97301ea0f4Smrg
98301ea0f4Smrgwhile test -n "$1"; do
99301ea0f4Smrg  case $1 in
100301ea0f4Smrg    -c) shift
101301ea0f4Smrg        continue;;
102301ea0f4Smrg
103301ea0f4Smrg    -d) dir_arg=true
104301ea0f4Smrg        shift
105301ea0f4Smrg        continue;;
106301ea0f4Smrg
107301ea0f4Smrg    -g) chgrpcmd="$chgrpprog $2"
108301ea0f4Smrg        shift
109301ea0f4Smrg        shift
110301ea0f4Smrg        continue;;
111301ea0f4Smrg
112301ea0f4Smrg    --help) echo "$usage"; exit $?;;
113301ea0f4Smrg
114301ea0f4Smrg    -m) chmodcmd="$chmodprog $2"
115301ea0f4Smrg        shift
116301ea0f4Smrg        shift
117301ea0f4Smrg        continue;;
118301ea0f4Smrg
119301ea0f4Smrg    -o) chowncmd="$chownprog $2"
120301ea0f4Smrg        shift
121301ea0f4Smrg        shift
122301ea0f4Smrg        continue;;
123301ea0f4Smrg
124301ea0f4Smrg    -s) stripcmd=$stripprog
125301ea0f4Smrg        shift
126301ea0f4Smrg        continue;;
127301ea0f4Smrg
128301ea0f4Smrg    -t) dstarg=$2
129301ea0f4Smrg	shift
130301ea0f4Smrg	shift
131301ea0f4Smrg	continue;;
132301ea0f4Smrg
133301ea0f4Smrg    -T) no_target_directory=true
134301ea0f4Smrg	shift
135301ea0f4Smrg	continue;;
136301ea0f4Smrg
137301ea0f4Smrg    --version) echo "$0 $scriptversion"; exit $?;;
138301ea0f4Smrg
139301ea0f4Smrg    *)  # When -d is used, all remaining arguments are directories to create.
140301ea0f4Smrg	# When -t is used, the destination is already specified.
141301ea0f4Smrg	test -n "$dir_arg$dstarg" && break
142301ea0f4Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
143301ea0f4Smrg	for arg
144301ea0f4Smrg	do
145301ea0f4Smrg          if test -n "$dstarg"; then
146301ea0f4Smrg	    # $@ is not empty: it contains at least $arg.
147301ea0f4Smrg	    set fnord "$@" "$dstarg"
148301ea0f4Smrg	    shift # fnord
149301ea0f4Smrg	  fi
150301ea0f4Smrg	  shift # arg
151301ea0f4Smrg	  dstarg=$arg
152301ea0f4Smrg	done
153301ea0f4Smrg	break;;
154301ea0f4Smrg  esac
155301ea0f4Smrgdone
156301ea0f4Smrg
157301ea0f4Smrgif test -z "$1"; then
158301ea0f4Smrg  if test -z "$dir_arg"; then
159301ea0f4Smrg    echo "$0: no input file specified." >&2
160301ea0f4Smrg    exit 1
161301ea0f4Smrg  fi
162301ea0f4Smrg  # It's OK to call `install-sh -d' without argument.
163301ea0f4Smrg  # This can happen when creating conditional directories.
164301ea0f4Smrg  exit 0
165301ea0f4Smrgfi
166301ea0f4Smrg
167301ea0f4Smrgfor src
168301ea0f4Smrgdo
169301ea0f4Smrg  # Protect names starting with `-'.
170301ea0f4Smrg  case $src in
171301ea0f4Smrg    -*) src=./$src ;;
172301ea0f4Smrg  esac
173301ea0f4Smrg
174301ea0f4Smrg  if test -n "$dir_arg"; then
175301ea0f4Smrg    dst=$src
176301ea0f4Smrg    src=
177301ea0f4Smrg
178301ea0f4Smrg    if test -d "$dst"; then
179301ea0f4Smrg      mkdircmd=:
180301ea0f4Smrg      chmodcmd=
181301ea0f4Smrg    else
182301ea0f4Smrg      mkdircmd=$mkdirprog
183301ea0f4Smrg    fi
184301ea0f4Smrg  else
185301ea0f4Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186301ea0f4Smrg    # might cause directories to be created, which would be especially bad
187301ea0f4Smrg    # if $src (and thus $dsttmp) contains '*'.
188301ea0f4Smrg    if test ! -f "$src" && test ! -d "$src"; then
189301ea0f4Smrg      echo "$0: $src does not exist." >&2
190301ea0f4Smrg      exit 1
191301ea0f4Smrg    fi
192301ea0f4Smrg
193301ea0f4Smrg    if test -z "$dstarg"; then
194301ea0f4Smrg      echo "$0: no destination specified." >&2
195301ea0f4Smrg      exit 1
196301ea0f4Smrg    fi
197301ea0f4Smrg
198301ea0f4Smrg    dst=$dstarg
199301ea0f4Smrg    # Protect names starting with `-'.
200301ea0f4Smrg    case $dst in
201301ea0f4Smrg      -*) dst=./$dst ;;
202301ea0f4Smrg    esac
203301ea0f4Smrg
204301ea0f4Smrg    # If destination is a directory, append the input filename; won't work
205301ea0f4Smrg    # if double slashes aren't ignored.
206301ea0f4Smrg    if test -d "$dst"; then
207301ea0f4Smrg      if test -n "$no_target_directory"; then
208301ea0f4Smrg	echo "$0: $dstarg: Is a directory" >&2
209301ea0f4Smrg	exit 1
210301ea0f4Smrg      fi
211301ea0f4Smrg      dst=$dst/`basename "$src"`
212301ea0f4Smrg    fi
213301ea0f4Smrg  fi
214301ea0f4Smrg
215301ea0f4Smrg  # This sed command emulates the dirname command.
216301ea0f4Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217301ea0f4Smrg
218301ea0f4Smrg  # Make sure that the destination directory exists.
219301ea0f4Smrg
220301ea0f4Smrg  # Skip lots of stat calls in the usual case.
221301ea0f4Smrg  if test ! -d "$dstdir"; then
222301ea0f4Smrg    defaultIFS='
223301ea0f4Smrg	 '
224301ea0f4Smrg    IFS="${IFS-$defaultIFS}"
225301ea0f4Smrg
226301ea0f4Smrg    oIFS=$IFS
227301ea0f4Smrg    # Some sh's can't handle IFS=/ for some reason.
228301ea0f4Smrg    IFS='%'
229301ea0f4Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230301ea0f4Smrg    shift
231301ea0f4Smrg    IFS=$oIFS
232301ea0f4Smrg
233301ea0f4Smrg    pathcomp=
234301ea0f4Smrg
235301ea0f4Smrg    while test $# -ne 0 ; do
236301ea0f4Smrg      pathcomp=$pathcomp$1
237301ea0f4Smrg      shift
238301ea0f4Smrg      if test ! -d "$pathcomp"; then
239301ea0f4Smrg        $mkdirprog "$pathcomp"
240301ea0f4Smrg	# mkdir can fail with a `File exist' error in case several
241301ea0f4Smrg	# install-sh are creating the directory concurrently.  This
242301ea0f4Smrg	# is OK.
243301ea0f4Smrg	test -d "$pathcomp" || exit
244301ea0f4Smrg      fi
245301ea0f4Smrg      pathcomp=$pathcomp/
246301ea0f4Smrg    done
247301ea0f4Smrg  fi
248301ea0f4Smrg
249301ea0f4Smrg  if test -n "$dir_arg"; then
250301ea0f4Smrg    $doit $mkdircmd "$dst" \
251301ea0f4Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252301ea0f4Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253301ea0f4Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254301ea0f4Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255301ea0f4Smrg
256301ea0f4Smrg  else
257301ea0f4Smrg    dstfile=`basename "$dst"`
258301ea0f4Smrg
259301ea0f4Smrg    # Make a couple of temp file names in the proper directory.
260301ea0f4Smrg    dsttmp=$dstdir/_inst.$$_
261301ea0f4Smrg    rmtmp=$dstdir/_rm.$$_
262301ea0f4Smrg
263301ea0f4Smrg    # Trap to clean up those temp files at exit.
264301ea0f4Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265301ea0f4Smrg    trap '(exit $?); exit' 1 2 13 15
266301ea0f4Smrg
267301ea0f4Smrg    # Copy the file name to the temp name.
268301ea0f4Smrg    $doit $cpprog "$src" "$dsttmp" &&
269301ea0f4Smrg
270301ea0f4Smrg    # and set any options; do chmod last to preserve setuid bits.
271301ea0f4Smrg    #
272301ea0f4Smrg    # If any of these fail, we abort the whole thing.  If we want to
273301ea0f4Smrg    # ignore errors from any of these, just make sure not to ignore
274301ea0f4Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
275301ea0f4Smrg    #
276301ea0f4Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277301ea0f4Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278301ea0f4Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279301ea0f4Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280301ea0f4Smrg
281301ea0f4Smrg    # Now rename the file to the real destination.
282301ea0f4Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283301ea0f4Smrg      || {
284301ea0f4Smrg	   # The rename failed, perhaps because mv can't rename something else
285301ea0f4Smrg	   # to itself, or perhaps because mv is so ancient that it does not
286301ea0f4Smrg	   # support -f.
287301ea0f4Smrg
288301ea0f4Smrg	   # Now remove or move aside any old file at destination location.
289301ea0f4Smrg	   # We try this two ways since rm can't unlink itself on some
290301ea0f4Smrg	   # systems and the destination file might be busy for other
291301ea0f4Smrg	   # reasons.  In this case, the final cleanup might fail but the new
292301ea0f4Smrg	   # file should still install successfully.
293301ea0f4Smrg	   {
294301ea0f4Smrg	     if test -f "$dstdir/$dstfile"; then
295301ea0f4Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296301ea0f4Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297301ea0f4Smrg	       || {
298301ea0f4Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299301ea0f4Smrg		 (exit 1); exit 1
300301ea0f4Smrg	       }
301301ea0f4Smrg	     else
302301ea0f4Smrg	       :
303301ea0f4Smrg	     fi
304301ea0f4Smrg	   } &&
305301ea0f4Smrg
306301ea0f4Smrg	   # Now rename the file to the real destination.
307301ea0f4Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308301ea0f4Smrg	 }
309301ea0f4Smrg    }
310301ea0f4Smrg  fi || { (exit 1); exit 1; }
311301ea0f4Smrgdone
312301ea0f4Smrg
313301ea0f4Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
314301ea0f4Smrg{
315301ea0f4Smrg  (exit 0); exit 0
316301ea0f4Smrg}
317301ea0f4Smrg
318301ea0f4Smrg# Local variables:
319301ea0f4Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
320301ea0f4Smrg# time-stamp-start: "scriptversion="
321301ea0f4Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
322301ea0f4Smrg# time-stamp-end: "$"
323301ea0f4Smrg# End:
324