install-sh revision 226fade8
145bc899bSmrg#!/bin/sh
245bc899bSmrg# install - install a program, script, or datafile
345bc899bSmrg
4226fade8Smrgscriptversion=2005-05-14.22
545bc899bSmrg
645bc899bSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
745bc899bSmrg# later released in X11R6 (xc/config/util/install.sh) with the
845bc899bSmrg# following copyright and license.
945bc899bSmrg#
1045bc899bSmrg# Copyright (C) 1994 X Consortium
1145bc899bSmrg#
1245bc899bSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1345bc899bSmrg# of this software and associated documentation files (the "Software"), to
1445bc899bSmrg# deal in the Software without restriction, including without limitation the
1545bc899bSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1645bc899bSmrg# sell copies of the Software, and to permit persons to whom the Software is
1745bc899bSmrg# furnished to do so, subject to the following conditions:
1845bc899bSmrg#
1945bc899bSmrg# The above copyright notice and this permission notice shall be included in
2045bc899bSmrg# all copies or substantial portions of the Software.
2145bc899bSmrg#
2245bc899bSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2345bc899bSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2445bc899bSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2545bc899bSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2645bc899bSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2745bc899bSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2845bc899bSmrg#
2945bc899bSmrg# Except as contained in this notice, the name of the X Consortium shall not
3045bc899bSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3145bc899bSmrg# ings in this Software without prior written authorization from the X Consor-
3245bc899bSmrg# tium.
3345bc899bSmrg#
3445bc899bSmrg#
3545bc899bSmrg# FSF changes to this file are in the public domain.
3645bc899bSmrg#
3745bc899bSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3845bc899bSmrg# `make' implicit rules from creating a file called install from it
3945bc899bSmrg# when there is no Makefile.
4045bc899bSmrg#
4145bc899bSmrg# This script is compatible with the BSD install script, but was written
42226fade8Smrg# from scratch.  It can only install one file at a time, a restriction
43226fade8Smrg# shared with many OS's install programs.
4445bc899bSmrg
4545bc899bSmrg# set DOITPROG to echo to test this script
4645bc899bSmrg
4745bc899bSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
48226fade8Smrgdoit="${DOITPROG-}"
4945bc899bSmrg
50226fade8Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
511ac89addSmrg
52226fade8Smrgmvprog="${MVPROG-mv}"
53226fade8Smrgcpprog="${CPPROG-cp}"
54226fade8Smrgchmodprog="${CHMODPROG-chmod}"
55226fade8Smrgchownprog="${CHOWNPROG-chown}"
56226fade8Smrgchgrpprog="${CHGRPPROG-chgrp}"
57226fade8Smrgstripprog="${STRIPPROG-strip}"
58226fade8Smrgrmprog="${RMPROG-rm}"
59226fade8Smrgmkdirprog="${MKDIRPROG-mkdir}"
6045bc899bSmrg
61226fade8Smrgchmodcmd="$chmodprog 0755"
621ac89addSmrgchowncmd=
63226fade8Smrgchgrpcmd=
641ac89addSmrgstripcmd=
65226fade8Smrgrmcmd="$rmprog -f"
66226fade8Smrgmvcmd="$mvprog"
6745bc899bSmrgsrc=
6845bc899bSmrgdst=
6945bc899bSmrgdir_arg=
70226fade8Smrgdstarg=
7145bc899bSmrgno_target_directory=
7245bc899bSmrg
73226fade8Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7445bc899bSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7545bc899bSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7645bc899bSmrg   or: $0 [OPTION]... -d DIRECTORIES...
7745bc899bSmrg
7845bc899bSmrgIn the 1st form, copy SRCFILE to DSTFILE.
7945bc899bSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8045bc899bSmrgIn the 4th, create DIRECTORIES.
8145bc899bSmrg
8245bc899bSmrgOptions:
83226fade8Smrg-c         (ignored)
84226fade8Smrg-d         create directories instead of installing files.
85226fade8Smrg-g GROUP   $chgrpprog installed files to GROUP.
86226fade8Smrg-m MODE    $chmodprog installed files to MODE.
87226fade8Smrg-o USER    $chownprog installed files to USER.
88226fade8Smrg-s         $stripprog installed files.
89226fade8Smrg-t DIRECTORY  install into DIRECTORY.
90226fade8Smrg-T         report an error if DSTFILE is a directory.
91226fade8Smrg--help     display this help and exit.
92226fade8Smrg--version  display version info and exit.
9345bc899bSmrg
9445bc899bSmrgEnvironment variables override the default commands:
95226fade8Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9645bc899bSmrg"
9745bc899bSmrg
98226fade8Smrgwhile test -n "$1"; do
9945bc899bSmrg  case $1 in
100226fade8Smrg    -c) shift
101226fade8Smrg        continue;;
10245bc899bSmrg
103226fade8Smrg    -d) dir_arg=true
104226fade8Smrg        shift
105226fade8Smrg        continue;;
10645bc899bSmrg
10745bc899bSmrg    -g) chgrpcmd="$chgrpprog $2"
108226fade8Smrg        shift
109226fade8Smrg        shift
110226fade8Smrg        continue;;
11145bc899bSmrg
11245bc899bSmrg    --help) echo "$usage"; exit $?;;
11345bc899bSmrg
114226fade8Smrg    -m) chmodcmd="$chmodprog $2"
115226fade8Smrg        shift
116226fade8Smrg        shift
117226fade8Smrg        continue;;
11845bc899bSmrg
11945bc899bSmrg    -o) chowncmd="$chownprog $2"
120226fade8Smrg        shift
121226fade8Smrg        shift
122226fade8Smrg        continue;;
12345bc899bSmrg
124226fade8Smrg    -s) stripcmd=$stripprog
125226fade8Smrg        shift
126226fade8Smrg        continue;;
12745bc899bSmrg
128226fade8Smrg    -t) dstarg=$2
129226fade8Smrg	shift
130226fade8Smrg	shift
131226fade8Smrg	continue;;
13245bc899bSmrg
133226fade8Smrg    -T) no_target_directory=true
134226fade8Smrg	shift
135226fade8Smrg	continue;;
13645bc899bSmrg
13745bc899bSmrg    --version) echo "$0 $scriptversion"; exit $?;;
13845bc899bSmrg
139226fade8Smrg    *)  # When -d is used, all remaining arguments are directories to create.
140226fade8Smrg	# When -t is used, the destination is already specified.
141226fade8Smrg	test -n "$dir_arg$dstarg" && break
142226fade8Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
143226fade8Smrg	for arg
144226fade8Smrg	do
145226fade8Smrg          if test -n "$dstarg"; then
146226fade8Smrg	    # $@ is not empty: it contains at least $arg.
147226fade8Smrg	    set fnord "$@" "$dstarg"
148226fade8Smrg	    shift # fnord
149226fade8Smrg	  fi
150226fade8Smrg	  shift # arg
151226fade8Smrg	  dstarg=$arg
152226fade8Smrg	done
15345bc899bSmrg	break;;
15445bc899bSmrg  esac
15545bc899bSmrgdone
15645bc899bSmrg
157226fade8Smrgif test -z "$1"; then
15845bc899bSmrg  if test -z "$dir_arg"; then
15945bc899bSmrg    echo "$0: no input file specified." >&2
16045bc899bSmrg    exit 1
16145bc899bSmrg  fi
16245bc899bSmrg  # It's OK to call `install-sh -d' without argument.
16345bc899bSmrg  # This can happen when creating conditional directories.
16445bc899bSmrg  exit 0
16545bc899bSmrgfi
16645bc899bSmrg
16745bc899bSmrgfor src
16845bc899bSmrgdo
16945bc899bSmrg  # Protect names starting with `-'.
17045bc899bSmrg  case $src in
171226fade8Smrg    -*) src=./$src ;;
17245bc899bSmrg  esac
17345bc899bSmrg
17445bc899bSmrg  if test -n "$dir_arg"; then
17545bc899bSmrg    dst=$src
176226fade8Smrg    src=
1771ac89addSmrg
178226fade8Smrg    if test -d "$dst"; then
179226fade8Smrg      mkdircmd=:
180226fade8Smrg      chmodcmd=
181226fade8Smrg    else
182226fade8Smrg      mkdircmd=$mkdirprog
183226fade8Smrg    fi
184226fade8Smrg  else
18545bc899bSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18645bc899bSmrg    # might cause directories to be created, which would be especially bad
18745bc899bSmrg    # if $src (and thus $dsttmp) contains '*'.
18845bc899bSmrg    if test ! -f "$src" && test ! -d "$src"; then
18945bc899bSmrg      echo "$0: $src does not exist." >&2
19045bc899bSmrg      exit 1
19145bc899bSmrg    fi
19245bc899bSmrg
193226fade8Smrg    if test -z "$dstarg"; then
19445bc899bSmrg      echo "$0: no destination specified." >&2
19545bc899bSmrg      exit 1
19645bc899bSmrg    fi
19745bc899bSmrg
198226fade8Smrg    dst=$dstarg
19945bc899bSmrg    # Protect names starting with `-'.
20045bc899bSmrg    case $dst in
201226fade8Smrg      -*) dst=./$dst ;;
20245bc899bSmrg    esac
20345bc899bSmrg
20445bc899bSmrg    # If destination is a directory, append the input filename; won't work
20545bc899bSmrg    # if double slashes aren't ignored.
20645bc899bSmrg    if test -d "$dst"; then
20745bc899bSmrg      if test -n "$no_target_directory"; then
208226fade8Smrg	echo "$0: $dstarg: Is a directory" >&2
20945bc899bSmrg	exit 1
21045bc899bSmrg      fi
211226fade8Smrg      dst=$dst/`basename "$src"`
21245bc899bSmrg    fi
21345bc899bSmrg  fi
21445bc899bSmrg
215226fade8Smrg  # This sed command emulates the dirname command.
216226fade8Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21745bc899bSmrg
218226fade8Smrg  # Make sure that the destination directory exists.
21945bc899bSmrg
220226fade8Smrg  # Skip lots of stat calls in the usual case.
221226fade8Smrg  if test ! -d "$dstdir"; then
222226fade8Smrg    defaultIFS='
223226fade8Smrg	 '
224226fade8Smrg    IFS="${IFS-$defaultIFS}"
22545bc899bSmrg
226226fade8Smrg    oIFS=$IFS
227226fade8Smrg    # Some sh's can't handle IFS=/ for some reason.
228226fade8Smrg    IFS='%'
229226fade8Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230226fade8Smrg    shift
231226fade8Smrg    IFS=$oIFS
23245bc899bSmrg
233226fade8Smrg    pathcomp=
23445bc899bSmrg
235226fade8Smrg    while test $# -ne 0 ; do
236226fade8Smrg      pathcomp=$pathcomp$1
23745bc899bSmrg      shift
238226fade8Smrg      if test ! -d "$pathcomp"; then
239226fade8Smrg        $mkdirprog "$pathcomp"
240226fade8Smrg	# mkdir can fail with a `File exist' error in case several
241226fade8Smrg	# install-sh are creating the directory concurrently.  This
242226fade8Smrg	# is OK.
243226fade8Smrg	test -d "$pathcomp" || exit
24445bc899bSmrg      fi
245226fade8Smrg      pathcomp=$pathcomp/
246226fade8Smrg    done
24745bc899bSmrg  fi
24845bc899bSmrg
24945bc899bSmrg  if test -n "$dir_arg"; then
250226fade8Smrg    $doit $mkdircmd "$dst" \
251226fade8Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252226fade8Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253226fade8Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254226fade8Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255226fade8Smrg
25645bc899bSmrg  else
257226fade8Smrg    dstfile=`basename "$dst"`
25845bc899bSmrg
25945bc899bSmrg    # Make a couple of temp file names in the proper directory.
26045bc899bSmrg    dsttmp=$dstdir/_inst.$$_
26145bc899bSmrg    rmtmp=$dstdir/_rm.$$_
26245bc899bSmrg
26345bc899bSmrg    # Trap to clean up those temp files at exit.
26445bc899bSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265226fade8Smrg    trap '(exit $?); exit' 1 2 13 15
26645bc899bSmrg
26745bc899bSmrg    # Copy the file name to the temp name.
268226fade8Smrg    $doit $cpprog "$src" "$dsttmp" &&
26945bc899bSmrg
27045bc899bSmrg    # and set any options; do chmod last to preserve setuid bits.
27145bc899bSmrg    #
27245bc899bSmrg    # If any of these fail, we abort the whole thing.  If we want to
27345bc899bSmrg    # ignore errors from any of these, just make sure not to ignore
27445bc899bSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27545bc899bSmrg    #
276226fade8Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277226fade8Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278226fade8Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279226fade8Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280226fade8Smrg
281226fade8Smrg    # Now rename the file to the real destination.
282226fade8Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283226fade8Smrg      || {
284226fade8Smrg	   # The rename failed, perhaps because mv can't rename something else
285226fade8Smrg	   # to itself, or perhaps because mv is so ancient that it does not
286226fade8Smrg	   # support -f.
287226fade8Smrg
288226fade8Smrg	   # Now remove or move aside any old file at destination location.
289226fade8Smrg	   # We try this two ways since rm can't unlink itself on some
290226fade8Smrg	   # systems and the destination file might be busy for other
291226fade8Smrg	   # reasons.  In this case, the final cleanup might fail but the new
292226fade8Smrg	   # file should still install successfully.
293226fade8Smrg	   {
294226fade8Smrg	     if test -f "$dstdir/$dstfile"; then
295226fade8Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296226fade8Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297226fade8Smrg	       || {
298226fade8Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299226fade8Smrg		 (exit 1); exit 1
300226fade8Smrg	       }
301226fade8Smrg	     else
302226fade8Smrg	       :
303226fade8Smrg	     fi
304226fade8Smrg	   } &&
305226fade8Smrg
306226fade8Smrg	   # Now rename the file to the real destination.
307226fade8Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308226fade8Smrg	 }
309226fade8Smrg    }
310226fade8Smrg  fi || { (exit 1); exit 1; }
31145bc899bSmrgdone
31245bc899bSmrg
313226fade8Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
314226fade8Smrg{
315226fade8Smrg  (exit 0); exit 0
316226fade8Smrg}
317226fade8Smrg
31845bc899bSmrg# Local variables:
31945bc899bSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32045bc899bSmrg# time-stamp-start: "scriptversion="
32145bc899bSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32245bc899bSmrg# time-stamp-end: "$"
32345bc899bSmrg# End:
324