install-sh revision 50806d53
150806d53Smrg#!/bin/sh
250806d53Smrg# install - install a program, script, or datafile
350806d53Smrg
450806d53Smrgscriptversion=2005-05-14.22
550806d53Smrg
650806d53Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
750806d53Smrg# later released in X11R6 (xc/config/util/install.sh) with the
850806d53Smrg# following copyright and license.
950806d53Smrg#
1050806d53Smrg# Copyright (C) 1994 X Consortium
1150806d53Smrg#
1250806d53Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1350806d53Smrg# of this software and associated documentation files (the "Software"), to
1450806d53Smrg# deal in the Software without restriction, including without limitation the
1550806d53Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1650806d53Smrg# sell copies of the Software, and to permit persons to whom the Software is
1750806d53Smrg# furnished to do so, subject to the following conditions:
1850806d53Smrg#
1950806d53Smrg# The above copyright notice and this permission notice shall be included in
2050806d53Smrg# all copies or substantial portions of the Software.
2150806d53Smrg#
2250806d53Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2350806d53Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2450806d53Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2550806d53Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2650806d53Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2750806d53Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2850806d53Smrg#
2950806d53Smrg# Except as contained in this notice, the name of the X Consortium shall not
3050806d53Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3150806d53Smrg# ings in this Software without prior written authorization from the X Consor-
3250806d53Smrg# tium.
3350806d53Smrg#
3450806d53Smrg#
3550806d53Smrg# FSF changes to this file are in the public domain.
3650806d53Smrg#
3750806d53Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3850806d53Smrg# `make' implicit rules from creating a file called install from it
3950806d53Smrg# when there is no Makefile.
4050806d53Smrg#
4150806d53Smrg# This script is compatible with the BSD install script, but was written
4250806d53Smrg# from scratch.  It can only install one file at a time, a restriction
4350806d53Smrg# shared with many OS's install programs.
4450806d53Smrg
4550806d53Smrg# set DOITPROG to echo to test this script
4650806d53Smrg
4750806d53Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4850806d53Smrgdoit="${DOITPROG-}"
4950806d53Smrg
5050806d53Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
5150806d53Smrg
5250806d53Smrgmvprog="${MVPROG-mv}"
5350806d53Smrgcpprog="${CPPROG-cp}"
5450806d53Smrgchmodprog="${CHMODPROG-chmod}"
5550806d53Smrgchownprog="${CHOWNPROG-chown}"
5650806d53Smrgchgrpprog="${CHGRPPROG-chgrp}"
5750806d53Smrgstripprog="${STRIPPROG-strip}"
5850806d53Smrgrmprog="${RMPROG-rm}"
5950806d53Smrgmkdirprog="${MKDIRPROG-mkdir}"
6050806d53Smrg
6150806d53Smrgchmodcmd="$chmodprog 0755"
6250806d53Smrgchowncmd=
6350806d53Smrgchgrpcmd=
6450806d53Smrgstripcmd=
6550806d53Smrgrmcmd="$rmprog -f"
6650806d53Smrgmvcmd="$mvprog"
6750806d53Smrgsrc=
6850806d53Smrgdst=
6950806d53Smrgdir_arg=
7050806d53Smrgdstarg=
7150806d53Smrgno_target_directory=
7250806d53Smrg
7350806d53Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7450806d53Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7550806d53Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7650806d53Smrg   or: $0 [OPTION]... -d DIRECTORIES...
7750806d53Smrg
7850806d53SmrgIn the 1st form, copy SRCFILE to DSTFILE.
7950806d53SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8050806d53SmrgIn the 4th, create DIRECTORIES.
8150806d53Smrg
8250806d53SmrgOptions:
8350806d53Smrg-c         (ignored)
8450806d53Smrg-d         create directories instead of installing files.
8550806d53Smrg-g GROUP   $chgrpprog installed files to GROUP.
8650806d53Smrg-m MODE    $chmodprog installed files to MODE.
8750806d53Smrg-o USER    $chownprog installed files to USER.
8850806d53Smrg-s         $stripprog installed files.
8950806d53Smrg-t DIRECTORY  install into DIRECTORY.
9050806d53Smrg-T         report an error if DSTFILE is a directory.
9150806d53Smrg--help     display this help and exit.
9250806d53Smrg--version  display version info and exit.
9350806d53Smrg
9450806d53SmrgEnvironment variables override the default commands:
9550806d53Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9650806d53Smrg"
9750806d53Smrg
9850806d53Smrgwhile test -n "$1"; do
9950806d53Smrg  case $1 in
10050806d53Smrg    -c) shift
10150806d53Smrg        continue;;
10250806d53Smrg
10350806d53Smrg    -d) dir_arg=true
10450806d53Smrg        shift
10550806d53Smrg        continue;;
10650806d53Smrg
10750806d53Smrg    -g) chgrpcmd="$chgrpprog $2"
10850806d53Smrg        shift
10950806d53Smrg        shift
11050806d53Smrg        continue;;
11150806d53Smrg
11250806d53Smrg    --help) echo "$usage"; exit $?;;
11350806d53Smrg
11450806d53Smrg    -m) chmodcmd="$chmodprog $2"
11550806d53Smrg        shift
11650806d53Smrg        shift
11750806d53Smrg        continue;;
11850806d53Smrg
11950806d53Smrg    -o) chowncmd="$chownprog $2"
12050806d53Smrg        shift
12150806d53Smrg        shift
12250806d53Smrg        continue;;
12350806d53Smrg
12450806d53Smrg    -s) stripcmd=$stripprog
12550806d53Smrg        shift
12650806d53Smrg        continue;;
12750806d53Smrg
12850806d53Smrg    -t) dstarg=$2
12950806d53Smrg	shift
13050806d53Smrg	shift
13150806d53Smrg	continue;;
13250806d53Smrg
13350806d53Smrg    -T) no_target_directory=true
13450806d53Smrg	shift
13550806d53Smrg	continue;;
13650806d53Smrg
13750806d53Smrg    --version) echo "$0 $scriptversion"; exit $?;;
13850806d53Smrg
13950806d53Smrg    *)  # When -d is used, all remaining arguments are directories to create.
14050806d53Smrg	# When -t is used, the destination is already specified.
14150806d53Smrg	test -n "$dir_arg$dstarg" && break
14250806d53Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14350806d53Smrg	for arg
14450806d53Smrg	do
14550806d53Smrg          if test -n "$dstarg"; then
14650806d53Smrg	    # $@ is not empty: it contains at least $arg.
14750806d53Smrg	    set fnord "$@" "$dstarg"
14850806d53Smrg	    shift # fnord
14950806d53Smrg	  fi
15050806d53Smrg	  shift # arg
15150806d53Smrg	  dstarg=$arg
15250806d53Smrg	done
15350806d53Smrg	break;;
15450806d53Smrg  esac
15550806d53Smrgdone
15650806d53Smrg
15750806d53Smrgif test -z "$1"; then
15850806d53Smrg  if test -z "$dir_arg"; then
15950806d53Smrg    echo "$0: no input file specified." >&2
16050806d53Smrg    exit 1
16150806d53Smrg  fi
16250806d53Smrg  # It's OK to call `install-sh -d' without argument.
16350806d53Smrg  # This can happen when creating conditional directories.
16450806d53Smrg  exit 0
16550806d53Smrgfi
16650806d53Smrg
16750806d53Smrgfor src
16850806d53Smrgdo
16950806d53Smrg  # Protect names starting with `-'.
17050806d53Smrg  case $src in
17150806d53Smrg    -*) src=./$src ;;
17250806d53Smrg  esac
17350806d53Smrg
17450806d53Smrg  if test -n "$dir_arg"; then
17550806d53Smrg    dst=$src
17650806d53Smrg    src=
17750806d53Smrg
17850806d53Smrg    if test -d "$dst"; then
17950806d53Smrg      mkdircmd=:
18050806d53Smrg      chmodcmd=
18150806d53Smrg    else
18250806d53Smrg      mkdircmd=$mkdirprog
18350806d53Smrg    fi
18450806d53Smrg  else
18550806d53Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18650806d53Smrg    # might cause directories to be created, which would be especially bad
18750806d53Smrg    # if $src (and thus $dsttmp) contains '*'.
18850806d53Smrg    if test ! -f "$src" && test ! -d "$src"; then
18950806d53Smrg      echo "$0: $src does not exist." >&2
19050806d53Smrg      exit 1
19150806d53Smrg    fi
19250806d53Smrg
19350806d53Smrg    if test -z "$dstarg"; then
19450806d53Smrg      echo "$0: no destination specified." >&2
19550806d53Smrg      exit 1
19650806d53Smrg    fi
19750806d53Smrg
19850806d53Smrg    dst=$dstarg
19950806d53Smrg    # Protect names starting with `-'.
20050806d53Smrg    case $dst in
20150806d53Smrg      -*) dst=./$dst ;;
20250806d53Smrg    esac
20350806d53Smrg
20450806d53Smrg    # If destination is a directory, append the input filename; won't work
20550806d53Smrg    # if double slashes aren't ignored.
20650806d53Smrg    if test -d "$dst"; then
20750806d53Smrg      if test -n "$no_target_directory"; then
20850806d53Smrg	echo "$0: $dstarg: Is a directory" >&2
20950806d53Smrg	exit 1
21050806d53Smrg      fi
21150806d53Smrg      dst=$dst/`basename "$src"`
21250806d53Smrg    fi
21350806d53Smrg  fi
21450806d53Smrg
21550806d53Smrg  # This sed command emulates the dirname command.
21650806d53Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21750806d53Smrg
21850806d53Smrg  # Make sure that the destination directory exists.
21950806d53Smrg
22050806d53Smrg  # Skip lots of stat calls in the usual case.
22150806d53Smrg  if test ! -d "$dstdir"; then
22250806d53Smrg    defaultIFS='
22350806d53Smrg	 '
22450806d53Smrg    IFS="${IFS-$defaultIFS}"
22550806d53Smrg
22650806d53Smrg    oIFS=$IFS
22750806d53Smrg    # Some sh's can't handle IFS=/ for some reason.
22850806d53Smrg    IFS='%'
22950806d53Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23050806d53Smrg    shift
23150806d53Smrg    IFS=$oIFS
23250806d53Smrg
23350806d53Smrg    pathcomp=
23450806d53Smrg
23550806d53Smrg    while test $# -ne 0 ; do
23650806d53Smrg      pathcomp=$pathcomp$1
23750806d53Smrg      shift
23850806d53Smrg      if test ! -d "$pathcomp"; then
23950806d53Smrg        $mkdirprog "$pathcomp"
24050806d53Smrg	# mkdir can fail with a `File exist' error in case several
24150806d53Smrg	# install-sh are creating the directory concurrently.  This
24250806d53Smrg	# is OK.
24350806d53Smrg	test -d "$pathcomp" || exit
24450806d53Smrg      fi
24550806d53Smrg      pathcomp=$pathcomp/
24650806d53Smrg    done
24750806d53Smrg  fi
24850806d53Smrg
24950806d53Smrg  if test -n "$dir_arg"; then
25050806d53Smrg    $doit $mkdircmd "$dst" \
25150806d53Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25250806d53Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25350806d53Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25450806d53Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25550806d53Smrg
25650806d53Smrg  else
25750806d53Smrg    dstfile=`basename "$dst"`
25850806d53Smrg
25950806d53Smrg    # Make a couple of temp file names in the proper directory.
26050806d53Smrg    dsttmp=$dstdir/_inst.$$_
26150806d53Smrg    rmtmp=$dstdir/_rm.$$_
26250806d53Smrg
26350806d53Smrg    # Trap to clean up those temp files at exit.
26450806d53Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26550806d53Smrg    trap '(exit $?); exit' 1 2 13 15
26650806d53Smrg
26750806d53Smrg    # Copy the file name to the temp name.
26850806d53Smrg    $doit $cpprog "$src" "$dsttmp" &&
26950806d53Smrg
27050806d53Smrg    # and set any options; do chmod last to preserve setuid bits.
27150806d53Smrg    #
27250806d53Smrg    # If any of these fail, we abort the whole thing.  If we want to
27350806d53Smrg    # ignore errors from any of these, just make sure not to ignore
27450806d53Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27550806d53Smrg    #
27650806d53Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27750806d53Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27850806d53Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27950806d53Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28050806d53Smrg
28150806d53Smrg    # Now rename the file to the real destination.
28250806d53Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28350806d53Smrg      || {
28450806d53Smrg	   # The rename failed, perhaps because mv can't rename something else
28550806d53Smrg	   # to itself, or perhaps because mv is so ancient that it does not
28650806d53Smrg	   # support -f.
28750806d53Smrg
28850806d53Smrg	   # Now remove or move aside any old file at destination location.
28950806d53Smrg	   # We try this two ways since rm can't unlink itself on some
29050806d53Smrg	   # systems and the destination file might be busy for other
29150806d53Smrg	   # reasons.  In this case, the final cleanup might fail but the new
29250806d53Smrg	   # file should still install successfully.
29350806d53Smrg	   {
29450806d53Smrg	     if test -f "$dstdir/$dstfile"; then
29550806d53Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29650806d53Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29750806d53Smrg	       || {
29850806d53Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29950806d53Smrg		 (exit 1); exit 1
30050806d53Smrg	       }
30150806d53Smrg	     else
30250806d53Smrg	       :
30350806d53Smrg	     fi
30450806d53Smrg	   } &&
30550806d53Smrg
30650806d53Smrg	   # Now rename the file to the real destination.
30750806d53Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30850806d53Smrg	 }
30950806d53Smrg    }
31050806d53Smrg  fi || { (exit 1); exit 1; }
31150806d53Smrgdone
31250806d53Smrg
31350806d53Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
31450806d53Smrg{
31550806d53Smrg  (exit 0); exit 0
31650806d53Smrg}
31750806d53Smrg
31850806d53Smrg# Local variables:
31950806d53Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32050806d53Smrg# time-stamp-start: "scriptversion="
32150806d53Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32250806d53Smrg# time-stamp-end: "$"
32350806d53Smrg# End:
324