install-sh revision 72b676d7
172b676d7Smrg#!/bin/sh
272b676d7Smrg# install - install a program, script, or datafile
372b676d7Smrg
472b676d7Smrgscriptversion=2005-05-14.22
572b676d7Smrg
672b676d7Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
772b676d7Smrg# later released in X11R6 (xc/config/util/install.sh) with the
872b676d7Smrg# following copyright and license.
972b676d7Smrg#
1072b676d7Smrg# Copyright (C) 1994 X Consortium
1172b676d7Smrg#
1272b676d7Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1372b676d7Smrg# of this software and associated documentation files (the "Software"), to
1472b676d7Smrg# deal in the Software without restriction, including without limitation the
1572b676d7Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1672b676d7Smrg# sell copies of the Software, and to permit persons to whom the Software is
1772b676d7Smrg# furnished to do so, subject to the following conditions:
1872b676d7Smrg#
1972b676d7Smrg# The above copyright notice and this permission notice shall be included in
2072b676d7Smrg# all copies or substantial portions of the Software.
2172b676d7Smrg#
2272b676d7Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2372b676d7Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2472b676d7Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2572b676d7Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2672b676d7Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2772b676d7Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2872b676d7Smrg#
2972b676d7Smrg# Except as contained in this notice, the name of the X Consortium shall not
3072b676d7Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3172b676d7Smrg# ings in this Software without prior written authorization from the X Consor-
3272b676d7Smrg# tium.
3372b676d7Smrg#
3472b676d7Smrg#
3572b676d7Smrg# FSF changes to this file are in the public domain.
3672b676d7Smrg#
3772b676d7Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3872b676d7Smrg# `make' implicit rules from creating a file called install from it
3972b676d7Smrg# when there is no Makefile.
4072b676d7Smrg#
4172b676d7Smrg# This script is compatible with the BSD install script, but was written
4272b676d7Smrg# from scratch.  It can only install one file at a time, a restriction
4372b676d7Smrg# shared with many OS's install programs.
4472b676d7Smrg
4572b676d7Smrg# set DOITPROG to echo to test this script
4672b676d7Smrg
4772b676d7Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4872b676d7Smrgdoit="${DOITPROG-}"
4972b676d7Smrg
5072b676d7Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
5172b676d7Smrg
5272b676d7Smrgmvprog="${MVPROG-mv}"
5372b676d7Smrgcpprog="${CPPROG-cp}"
5472b676d7Smrgchmodprog="${CHMODPROG-chmod}"
5572b676d7Smrgchownprog="${CHOWNPROG-chown}"
5672b676d7Smrgchgrpprog="${CHGRPPROG-chgrp}"
5772b676d7Smrgstripprog="${STRIPPROG-strip}"
5872b676d7Smrgrmprog="${RMPROG-rm}"
5972b676d7Smrgmkdirprog="${MKDIRPROG-mkdir}"
6072b676d7Smrg
6172b676d7Smrgchmodcmd="$chmodprog 0755"
6272b676d7Smrgchowncmd=
6372b676d7Smrgchgrpcmd=
6472b676d7Smrgstripcmd=
6572b676d7Smrgrmcmd="$rmprog -f"
6672b676d7Smrgmvcmd="$mvprog"
6772b676d7Smrgsrc=
6872b676d7Smrgdst=
6972b676d7Smrgdir_arg=
7072b676d7Smrgdstarg=
7172b676d7Smrgno_target_directory=
7272b676d7Smrg
7372b676d7Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7472b676d7Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7572b676d7Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7672b676d7Smrg   or: $0 [OPTION]... -d DIRECTORIES...
7772b676d7Smrg
7872b676d7SmrgIn the 1st form, copy SRCFILE to DSTFILE.
7972b676d7SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8072b676d7SmrgIn the 4th, create DIRECTORIES.
8172b676d7Smrg
8272b676d7SmrgOptions:
8372b676d7Smrg-c         (ignored)
8472b676d7Smrg-d         create directories instead of installing files.
8572b676d7Smrg-g GROUP   $chgrpprog installed files to GROUP.
8672b676d7Smrg-m MODE    $chmodprog installed files to MODE.
8772b676d7Smrg-o USER    $chownprog installed files to USER.
8872b676d7Smrg-s         $stripprog installed files.
8972b676d7Smrg-t DIRECTORY  install into DIRECTORY.
9072b676d7Smrg-T         report an error if DSTFILE is a directory.
9172b676d7Smrg--help     display this help and exit.
9272b676d7Smrg--version  display version info and exit.
9372b676d7Smrg
9472b676d7SmrgEnvironment variables override the default commands:
9572b676d7Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9672b676d7Smrg"
9772b676d7Smrg
9872b676d7Smrgwhile test -n "$1"; do
9972b676d7Smrg  case $1 in
10072b676d7Smrg    -c) shift
10172b676d7Smrg        continue;;
10272b676d7Smrg
10372b676d7Smrg    -d) dir_arg=true
10472b676d7Smrg        shift
10572b676d7Smrg        continue;;
10672b676d7Smrg
10772b676d7Smrg    -g) chgrpcmd="$chgrpprog $2"
10872b676d7Smrg        shift
10972b676d7Smrg        shift
11072b676d7Smrg        continue;;
11172b676d7Smrg
11272b676d7Smrg    --help) echo "$usage"; exit $?;;
11372b676d7Smrg
11472b676d7Smrg    -m) chmodcmd="$chmodprog $2"
11572b676d7Smrg        shift
11672b676d7Smrg        shift
11772b676d7Smrg        continue;;
11872b676d7Smrg
11972b676d7Smrg    -o) chowncmd="$chownprog $2"
12072b676d7Smrg        shift
12172b676d7Smrg        shift
12272b676d7Smrg        continue;;
12372b676d7Smrg
12472b676d7Smrg    -s) stripcmd=$stripprog
12572b676d7Smrg        shift
12672b676d7Smrg        continue;;
12772b676d7Smrg
12872b676d7Smrg    -t) dstarg=$2
12972b676d7Smrg	shift
13072b676d7Smrg	shift
13172b676d7Smrg	continue;;
13272b676d7Smrg
13372b676d7Smrg    -T) no_target_directory=true
13472b676d7Smrg	shift
13572b676d7Smrg	continue;;
13672b676d7Smrg
13772b676d7Smrg    --version) echo "$0 $scriptversion"; exit $?;;
13872b676d7Smrg
13972b676d7Smrg    *)  # When -d is used, all remaining arguments are directories to create.
14072b676d7Smrg	# When -t is used, the destination is already specified.
14172b676d7Smrg	test -n "$dir_arg$dstarg" && break
14272b676d7Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14372b676d7Smrg	for arg
14472b676d7Smrg	do
14572b676d7Smrg          if test -n "$dstarg"; then
14672b676d7Smrg	    # $@ is not empty: it contains at least $arg.
14772b676d7Smrg	    set fnord "$@" "$dstarg"
14872b676d7Smrg	    shift # fnord
14972b676d7Smrg	  fi
15072b676d7Smrg	  shift # arg
15172b676d7Smrg	  dstarg=$arg
15272b676d7Smrg	done
15372b676d7Smrg	break;;
15472b676d7Smrg  esac
15572b676d7Smrgdone
15672b676d7Smrg
15772b676d7Smrgif test -z "$1"; then
15872b676d7Smrg  if test -z "$dir_arg"; then
15972b676d7Smrg    echo "$0: no input file specified." >&2
16072b676d7Smrg    exit 1
16172b676d7Smrg  fi
16272b676d7Smrg  # It's OK to call `install-sh -d' without argument.
16372b676d7Smrg  # This can happen when creating conditional directories.
16472b676d7Smrg  exit 0
16572b676d7Smrgfi
16672b676d7Smrg
16772b676d7Smrgfor src
16872b676d7Smrgdo
16972b676d7Smrg  # Protect names starting with `-'.
17072b676d7Smrg  case $src in
17172b676d7Smrg    -*) src=./$src ;;
17272b676d7Smrg  esac
17372b676d7Smrg
17472b676d7Smrg  if test -n "$dir_arg"; then
17572b676d7Smrg    dst=$src
17672b676d7Smrg    src=
17772b676d7Smrg
17872b676d7Smrg    if test -d "$dst"; then
17972b676d7Smrg      mkdircmd=:
18072b676d7Smrg      chmodcmd=
18172b676d7Smrg    else
18272b676d7Smrg      mkdircmd=$mkdirprog
18372b676d7Smrg    fi
18472b676d7Smrg  else
18572b676d7Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18672b676d7Smrg    # might cause directories to be created, which would be especially bad
18772b676d7Smrg    # if $src (and thus $dsttmp) contains '*'.
18872b676d7Smrg    if test ! -f "$src" && test ! -d "$src"; then
18972b676d7Smrg      echo "$0: $src does not exist." >&2
19072b676d7Smrg      exit 1
19172b676d7Smrg    fi
19272b676d7Smrg
19372b676d7Smrg    if test -z "$dstarg"; then
19472b676d7Smrg      echo "$0: no destination specified." >&2
19572b676d7Smrg      exit 1
19672b676d7Smrg    fi
19772b676d7Smrg
19872b676d7Smrg    dst=$dstarg
19972b676d7Smrg    # Protect names starting with `-'.
20072b676d7Smrg    case $dst in
20172b676d7Smrg      -*) dst=./$dst ;;
20272b676d7Smrg    esac
20372b676d7Smrg
20472b676d7Smrg    # If destination is a directory, append the input filename; won't work
20572b676d7Smrg    # if double slashes aren't ignored.
20672b676d7Smrg    if test -d "$dst"; then
20772b676d7Smrg      if test -n "$no_target_directory"; then
20872b676d7Smrg	echo "$0: $dstarg: Is a directory" >&2
20972b676d7Smrg	exit 1
21072b676d7Smrg      fi
21172b676d7Smrg      dst=$dst/`basename "$src"`
21272b676d7Smrg    fi
21372b676d7Smrg  fi
21472b676d7Smrg
21572b676d7Smrg  # This sed command emulates the dirname command.
21672b676d7Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21772b676d7Smrg
21872b676d7Smrg  # Make sure that the destination directory exists.
21972b676d7Smrg
22072b676d7Smrg  # Skip lots of stat calls in the usual case.
22172b676d7Smrg  if test ! -d "$dstdir"; then
22272b676d7Smrg    defaultIFS='
22372b676d7Smrg	 '
22472b676d7Smrg    IFS="${IFS-$defaultIFS}"
22572b676d7Smrg
22672b676d7Smrg    oIFS=$IFS
22772b676d7Smrg    # Some sh's can't handle IFS=/ for some reason.
22872b676d7Smrg    IFS='%'
22972b676d7Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23072b676d7Smrg    shift
23172b676d7Smrg    IFS=$oIFS
23272b676d7Smrg
23372b676d7Smrg    pathcomp=
23472b676d7Smrg
23572b676d7Smrg    while test $# -ne 0 ; do
23672b676d7Smrg      pathcomp=$pathcomp$1
23772b676d7Smrg      shift
23872b676d7Smrg      if test ! -d "$pathcomp"; then
23972b676d7Smrg        $mkdirprog "$pathcomp"
24072b676d7Smrg	# mkdir can fail with a `File exist' error in case several
24172b676d7Smrg	# install-sh are creating the directory concurrently.  This
24272b676d7Smrg	# is OK.
24372b676d7Smrg	test -d "$pathcomp" || exit
24472b676d7Smrg      fi
24572b676d7Smrg      pathcomp=$pathcomp/
24672b676d7Smrg    done
24772b676d7Smrg  fi
24872b676d7Smrg
24972b676d7Smrg  if test -n "$dir_arg"; then
25072b676d7Smrg    $doit $mkdircmd "$dst" \
25172b676d7Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25272b676d7Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25372b676d7Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25472b676d7Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25572b676d7Smrg
25672b676d7Smrg  else
25772b676d7Smrg    dstfile=`basename "$dst"`
25872b676d7Smrg
25972b676d7Smrg    # Make a couple of temp file names in the proper directory.
26072b676d7Smrg    dsttmp=$dstdir/_inst.$$_
26172b676d7Smrg    rmtmp=$dstdir/_rm.$$_
26272b676d7Smrg
26372b676d7Smrg    # Trap to clean up those temp files at exit.
26472b676d7Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26572b676d7Smrg    trap '(exit $?); exit' 1 2 13 15
26672b676d7Smrg
26772b676d7Smrg    # Copy the file name to the temp name.
26872b676d7Smrg    $doit $cpprog "$src" "$dsttmp" &&
26972b676d7Smrg
27072b676d7Smrg    # and set any options; do chmod last to preserve setuid bits.
27172b676d7Smrg    #
27272b676d7Smrg    # If any of these fail, we abort the whole thing.  If we want to
27372b676d7Smrg    # ignore errors from any of these, just make sure not to ignore
27472b676d7Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27572b676d7Smrg    #
27672b676d7Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27772b676d7Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27872b676d7Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27972b676d7Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28072b676d7Smrg
28172b676d7Smrg    # Now rename the file to the real destination.
28272b676d7Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28372b676d7Smrg      || {
28472b676d7Smrg	   # The rename failed, perhaps because mv can't rename something else
28572b676d7Smrg	   # to itself, or perhaps because mv is so ancient that it does not
28672b676d7Smrg	   # support -f.
28772b676d7Smrg
28872b676d7Smrg	   # Now remove or move aside any old file at destination location.
28972b676d7Smrg	   # We try this two ways since rm can't unlink itself on some
29072b676d7Smrg	   # systems and the destination file might be busy for other
29172b676d7Smrg	   # reasons.  In this case, the final cleanup might fail but the new
29272b676d7Smrg	   # file should still install successfully.
29372b676d7Smrg	   {
29472b676d7Smrg	     if test -f "$dstdir/$dstfile"; then
29572b676d7Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29672b676d7Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29772b676d7Smrg	       || {
29872b676d7Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29972b676d7Smrg		 (exit 1); exit 1
30072b676d7Smrg	       }
30172b676d7Smrg	     else
30272b676d7Smrg	       :
30372b676d7Smrg	     fi
30472b676d7Smrg	   } &&
30572b676d7Smrg
30672b676d7Smrg	   # Now rename the file to the real destination.
30772b676d7Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30872b676d7Smrg	 }
30972b676d7Smrg    }
31072b676d7Smrg  fi || { (exit 1); exit 1; }
31172b676d7Smrgdone
31272b676d7Smrg
31372b676d7Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
31472b676d7Smrg{
31572b676d7Smrg  (exit 0); exit 0
31672b676d7Smrg}
31772b676d7Smrg
31872b676d7Smrg# Local variables:
31972b676d7Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32072b676d7Smrg# time-stamp-start: "scriptversion="
32172b676d7Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32272b676d7Smrg# time-stamp-end: "$"
32372b676d7Smrg# End:
324