install-sh revision 20d725fb
120d725fbSmrg#!/bin/sh
220d725fbSmrg# install - install a program, script, or datafile
320d725fbSmrg
420d725fbSmrgscriptversion=2005-05-14.22
520d725fbSmrg
620d725fbSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
720d725fbSmrg# later released in X11R6 (xc/config/util/install.sh) with the
820d725fbSmrg# following copyright and license.
920d725fbSmrg#
1020d725fbSmrg# Copyright (C) 1994 X Consortium
1120d725fbSmrg#
1220d725fbSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1320d725fbSmrg# of this software and associated documentation files (the "Software"), to
1420d725fbSmrg# deal in the Software without restriction, including without limitation the
1520d725fbSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1620d725fbSmrg# sell copies of the Software, and to permit persons to whom the Software is
1720d725fbSmrg# furnished to do so, subject to the following conditions:
1820d725fbSmrg#
1920d725fbSmrg# The above copyright notice and this permission notice shall be included in
2020d725fbSmrg# all copies or substantial portions of the Software.
2120d725fbSmrg#
2220d725fbSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2320d725fbSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2420d725fbSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2520d725fbSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2620d725fbSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2720d725fbSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2820d725fbSmrg#
2920d725fbSmrg# Except as contained in this notice, the name of the X Consortium shall not
3020d725fbSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3120d725fbSmrg# ings in this Software without prior written authorization from the X Consor-
3220d725fbSmrg# tium.
3320d725fbSmrg#
3420d725fbSmrg#
3520d725fbSmrg# FSF changes to this file are in the public domain.
3620d725fbSmrg#
3720d725fbSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3820d725fbSmrg# `make' implicit rules from creating a file called install from it
3920d725fbSmrg# when there is no Makefile.
4020d725fbSmrg#
4120d725fbSmrg# This script is compatible with the BSD install script, but was written
4220d725fbSmrg# from scratch.  It can only install one file at a time, a restriction
4320d725fbSmrg# shared with many OS's install programs.
4420d725fbSmrg
4520d725fbSmrg# set DOITPROG to echo to test this script
4620d725fbSmrg
4720d725fbSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4820d725fbSmrgdoit="${DOITPROG-}"
4920d725fbSmrg
5020d725fbSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
5120d725fbSmrg
5220d725fbSmrgmvprog="${MVPROG-mv}"
5320d725fbSmrgcpprog="${CPPROG-cp}"
5420d725fbSmrgchmodprog="${CHMODPROG-chmod}"
5520d725fbSmrgchownprog="${CHOWNPROG-chown}"
5620d725fbSmrgchgrpprog="${CHGRPPROG-chgrp}"
5720d725fbSmrgstripprog="${STRIPPROG-strip}"
5820d725fbSmrgrmprog="${RMPROG-rm}"
5920d725fbSmrgmkdirprog="${MKDIRPROG-mkdir}"
6020d725fbSmrg
6120d725fbSmrgchmodcmd="$chmodprog 0755"
6220d725fbSmrgchowncmd=
6320d725fbSmrgchgrpcmd=
6420d725fbSmrgstripcmd=
6520d725fbSmrgrmcmd="$rmprog -f"
6620d725fbSmrgmvcmd="$mvprog"
6720d725fbSmrgsrc=
6820d725fbSmrgdst=
6920d725fbSmrgdir_arg=
7020d725fbSmrgdstarg=
7120d725fbSmrgno_target_directory=
7220d725fbSmrg
7320d725fbSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7420d725fbSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7520d725fbSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7620d725fbSmrg   or: $0 [OPTION]... -d DIRECTORIES...
7720d725fbSmrg
7820d725fbSmrgIn the 1st form, copy SRCFILE to DSTFILE.
7920d725fbSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8020d725fbSmrgIn the 4th, create DIRECTORIES.
8120d725fbSmrg
8220d725fbSmrgOptions:
8320d725fbSmrg-c         (ignored)
8420d725fbSmrg-d         create directories instead of installing files.
8520d725fbSmrg-g GROUP   $chgrpprog installed files to GROUP.
8620d725fbSmrg-m MODE    $chmodprog installed files to MODE.
8720d725fbSmrg-o USER    $chownprog installed files to USER.
8820d725fbSmrg-s         $stripprog installed files.
8920d725fbSmrg-t DIRECTORY  install into DIRECTORY.
9020d725fbSmrg-T         report an error if DSTFILE is a directory.
9120d725fbSmrg--help     display this help and exit.
9220d725fbSmrg--version  display version info and exit.
9320d725fbSmrg
9420d725fbSmrgEnvironment variables override the default commands:
9520d725fbSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9620d725fbSmrg"
9720d725fbSmrg
9820d725fbSmrgwhile test -n "$1"; do
9920d725fbSmrg  case $1 in
10020d725fbSmrg    -c) shift
10120d725fbSmrg        continue;;
10220d725fbSmrg
10320d725fbSmrg    -d) dir_arg=true
10420d725fbSmrg        shift
10520d725fbSmrg        continue;;
10620d725fbSmrg
10720d725fbSmrg    -g) chgrpcmd="$chgrpprog $2"
10820d725fbSmrg        shift
10920d725fbSmrg        shift
11020d725fbSmrg        continue;;
11120d725fbSmrg
11220d725fbSmrg    --help) echo "$usage"; exit $?;;
11320d725fbSmrg
11420d725fbSmrg    -m) chmodcmd="$chmodprog $2"
11520d725fbSmrg        shift
11620d725fbSmrg        shift
11720d725fbSmrg        continue;;
11820d725fbSmrg
11920d725fbSmrg    -o) chowncmd="$chownprog $2"
12020d725fbSmrg        shift
12120d725fbSmrg        shift
12220d725fbSmrg        continue;;
12320d725fbSmrg
12420d725fbSmrg    -s) stripcmd=$stripprog
12520d725fbSmrg        shift
12620d725fbSmrg        continue;;
12720d725fbSmrg
12820d725fbSmrg    -t) dstarg=$2
12920d725fbSmrg	shift
13020d725fbSmrg	shift
13120d725fbSmrg	continue;;
13220d725fbSmrg
13320d725fbSmrg    -T) no_target_directory=true
13420d725fbSmrg	shift
13520d725fbSmrg	continue;;
13620d725fbSmrg
13720d725fbSmrg    --version) echo "$0 $scriptversion"; exit $?;;
13820d725fbSmrg
13920d725fbSmrg    *)  # When -d is used, all remaining arguments are directories to create.
14020d725fbSmrg	# When -t is used, the destination is already specified.
14120d725fbSmrg	test -n "$dir_arg$dstarg" && break
14220d725fbSmrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14320d725fbSmrg	for arg
14420d725fbSmrg	do
14520d725fbSmrg          if test -n "$dstarg"; then
14620d725fbSmrg	    # $@ is not empty: it contains at least $arg.
14720d725fbSmrg	    set fnord "$@" "$dstarg"
14820d725fbSmrg	    shift # fnord
14920d725fbSmrg	  fi
15020d725fbSmrg	  shift # arg
15120d725fbSmrg	  dstarg=$arg
15220d725fbSmrg	done
15320d725fbSmrg	break;;
15420d725fbSmrg  esac
15520d725fbSmrgdone
15620d725fbSmrg
15720d725fbSmrgif test -z "$1"; then
15820d725fbSmrg  if test -z "$dir_arg"; then
15920d725fbSmrg    echo "$0: no input file specified." >&2
16020d725fbSmrg    exit 1
16120d725fbSmrg  fi
16220d725fbSmrg  # It's OK to call `install-sh -d' without argument.
16320d725fbSmrg  # This can happen when creating conditional directories.
16420d725fbSmrg  exit 0
16520d725fbSmrgfi
16620d725fbSmrg
16720d725fbSmrgfor src
16820d725fbSmrgdo
16920d725fbSmrg  # Protect names starting with `-'.
17020d725fbSmrg  case $src in
17120d725fbSmrg    -*) src=./$src ;;
17220d725fbSmrg  esac
17320d725fbSmrg
17420d725fbSmrg  if test -n "$dir_arg"; then
17520d725fbSmrg    dst=$src
17620d725fbSmrg    src=
17720d725fbSmrg
17820d725fbSmrg    if test -d "$dst"; then
17920d725fbSmrg      mkdircmd=:
18020d725fbSmrg      chmodcmd=
18120d725fbSmrg    else
18220d725fbSmrg      mkdircmd=$mkdirprog
18320d725fbSmrg    fi
18420d725fbSmrg  else
18520d725fbSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18620d725fbSmrg    # might cause directories to be created, which would be especially bad
18720d725fbSmrg    # if $src (and thus $dsttmp) contains '*'.
18820d725fbSmrg    if test ! -f "$src" && test ! -d "$src"; then
18920d725fbSmrg      echo "$0: $src does not exist." >&2
19020d725fbSmrg      exit 1
19120d725fbSmrg    fi
19220d725fbSmrg
19320d725fbSmrg    if test -z "$dstarg"; then
19420d725fbSmrg      echo "$0: no destination specified." >&2
19520d725fbSmrg      exit 1
19620d725fbSmrg    fi
19720d725fbSmrg
19820d725fbSmrg    dst=$dstarg
19920d725fbSmrg    # Protect names starting with `-'.
20020d725fbSmrg    case $dst in
20120d725fbSmrg      -*) dst=./$dst ;;
20220d725fbSmrg    esac
20320d725fbSmrg
20420d725fbSmrg    # If destination is a directory, append the input filename; won't work
20520d725fbSmrg    # if double slashes aren't ignored.
20620d725fbSmrg    if test -d "$dst"; then
20720d725fbSmrg      if test -n "$no_target_directory"; then
20820d725fbSmrg	echo "$0: $dstarg: Is a directory" >&2
20920d725fbSmrg	exit 1
21020d725fbSmrg      fi
21120d725fbSmrg      dst=$dst/`basename "$src"`
21220d725fbSmrg    fi
21320d725fbSmrg  fi
21420d725fbSmrg
21520d725fbSmrg  # This sed command emulates the dirname command.
21620d725fbSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21720d725fbSmrg
21820d725fbSmrg  # Make sure that the destination directory exists.
21920d725fbSmrg
22020d725fbSmrg  # Skip lots of stat calls in the usual case.
22120d725fbSmrg  if test ! -d "$dstdir"; then
22220d725fbSmrg    defaultIFS='
22320d725fbSmrg	 '
22420d725fbSmrg    IFS="${IFS-$defaultIFS}"
22520d725fbSmrg
22620d725fbSmrg    oIFS=$IFS
22720d725fbSmrg    # Some sh's can't handle IFS=/ for some reason.
22820d725fbSmrg    IFS='%'
22920d725fbSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23020d725fbSmrg    shift
23120d725fbSmrg    IFS=$oIFS
23220d725fbSmrg
23320d725fbSmrg    pathcomp=
23420d725fbSmrg
23520d725fbSmrg    while test $# -ne 0 ; do
23620d725fbSmrg      pathcomp=$pathcomp$1
23720d725fbSmrg      shift
23820d725fbSmrg      if test ! -d "$pathcomp"; then
23920d725fbSmrg        $mkdirprog "$pathcomp"
24020d725fbSmrg	# mkdir can fail with a `File exist' error in case several
24120d725fbSmrg	# install-sh are creating the directory concurrently.  This
24220d725fbSmrg	# is OK.
24320d725fbSmrg	test -d "$pathcomp" || exit
24420d725fbSmrg      fi
24520d725fbSmrg      pathcomp=$pathcomp/
24620d725fbSmrg    done
24720d725fbSmrg  fi
24820d725fbSmrg
24920d725fbSmrg  if test -n "$dir_arg"; then
25020d725fbSmrg    $doit $mkdircmd "$dst" \
25120d725fbSmrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25220d725fbSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25320d725fbSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25420d725fbSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25520d725fbSmrg
25620d725fbSmrg  else
25720d725fbSmrg    dstfile=`basename "$dst"`
25820d725fbSmrg
25920d725fbSmrg    # Make a couple of temp file names in the proper directory.
26020d725fbSmrg    dsttmp=$dstdir/_inst.$$_
26120d725fbSmrg    rmtmp=$dstdir/_rm.$$_
26220d725fbSmrg
26320d725fbSmrg    # Trap to clean up those temp files at exit.
26420d725fbSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26520d725fbSmrg    trap '(exit $?); exit' 1 2 13 15
26620d725fbSmrg
26720d725fbSmrg    # Copy the file name to the temp name.
26820d725fbSmrg    $doit $cpprog "$src" "$dsttmp" &&
26920d725fbSmrg
27020d725fbSmrg    # and set any options; do chmod last to preserve setuid bits.
27120d725fbSmrg    #
27220d725fbSmrg    # If any of these fail, we abort the whole thing.  If we want to
27320d725fbSmrg    # ignore errors from any of these, just make sure not to ignore
27420d725fbSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27520d725fbSmrg    #
27620d725fbSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27720d725fbSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27820d725fbSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27920d725fbSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28020d725fbSmrg
28120d725fbSmrg    # Now rename the file to the real destination.
28220d725fbSmrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28320d725fbSmrg      || {
28420d725fbSmrg	   # The rename failed, perhaps because mv can't rename something else
28520d725fbSmrg	   # to itself, or perhaps because mv is so ancient that it does not
28620d725fbSmrg	   # support -f.
28720d725fbSmrg
28820d725fbSmrg	   # Now remove or move aside any old file at destination location.
28920d725fbSmrg	   # We try this two ways since rm can't unlink itself on some
29020d725fbSmrg	   # systems and the destination file might be busy for other
29120d725fbSmrg	   # reasons.  In this case, the final cleanup might fail but the new
29220d725fbSmrg	   # file should still install successfully.
29320d725fbSmrg	   {
29420d725fbSmrg	     if test -f "$dstdir/$dstfile"; then
29520d725fbSmrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29620d725fbSmrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29720d725fbSmrg	       || {
29820d725fbSmrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29920d725fbSmrg		 (exit 1); exit 1
30020d725fbSmrg	       }
30120d725fbSmrg	     else
30220d725fbSmrg	       :
30320d725fbSmrg	     fi
30420d725fbSmrg	   } &&
30520d725fbSmrg
30620d725fbSmrg	   # Now rename the file to the real destination.
30720d725fbSmrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30820d725fbSmrg	 }
30920d725fbSmrg    }
31020d725fbSmrg  fi || { (exit 1); exit 1; }
31120d725fbSmrgdone
31220d725fbSmrg
31320d725fbSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
31420d725fbSmrg{
31520d725fbSmrg  (exit 0); exit 0
31620d725fbSmrg}
31720d725fbSmrg
31820d725fbSmrg# Local variables:
31920d725fbSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32020d725fbSmrg# time-stamp-start: "scriptversion="
32120d725fbSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32220d725fbSmrg# time-stamp-end: "$"
32320d725fbSmrg# End:
324