Blame install-sh

Packit d36e9b
#!/bin/sh
Packit d36e9b
# install - install a program, script, or datafile
Packit d36e9b
Packit d36e9b
scriptversion=2005-05-14.22
Packit d36e9b
Packit d36e9b
# This originates from X11R5 (mit/util/scripts/install.sh), which was
Packit d36e9b
# later released in X11R6 (xc/config/util/install.sh) with the
Packit d36e9b
# following copyright and license.
Packit d36e9b
#
Packit d36e9b
# Copyright (C) 1994 X Consortium
Packit d36e9b
#
Packit d36e9b
# Permission is hereby granted, free of charge, to any person obtaining a copy
Packit d36e9b
# of this software and associated documentation files (the "Software"), to
Packit d36e9b
# deal in the Software without restriction, including without limitation the
Packit d36e9b
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit d36e9b
# sell copies of the Software, and to permit persons to whom the Software is
Packit d36e9b
# furnished to do so, subject to the following conditions:
Packit d36e9b
#
Packit d36e9b
# The above copyright notice and this permission notice shall be included in
Packit d36e9b
# all copies or substantial portions of the Software.
Packit d36e9b
#
Packit d36e9b
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit d36e9b
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit d36e9b
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit d36e9b
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit d36e9b
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
Packit d36e9b
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit d36e9b
#
Packit d36e9b
# Except as contained in this notice, the name of the X Consortium shall not
Packit d36e9b
# be used in advertising or otherwise to promote the sale, use or other deal-
Packit d36e9b
# ings in this Software without prior written authorization from the X Consor-
Packit d36e9b
# tium.
Packit d36e9b
#
Packit d36e9b
#
Packit d36e9b
# FSF changes to this file are in the public domain.
Packit d36e9b
#
Packit d36e9b
# Calling this script install-sh is preferred over install.sh, to prevent
Packit d36e9b
# `make' implicit rules from creating a file called install from it
Packit d36e9b
# when there is no Makefile.
Packit d36e9b
#
Packit d36e9b
# This script is compatible with the BSD install script, but was written
Packit d36e9b
# from scratch.  It can only install one file at a time, a restriction
Packit d36e9b
# shared with many OS's install programs.
Packit d36e9b
Packit d36e9b
# set DOITPROG to echo to test this script
Packit d36e9b
Packit d36e9b
# Don't use :- since 4.3BSD and earlier shells don't like it.
Packit d36e9b
doit="${DOITPROG-}"
Packit d36e9b
Packit d36e9b
# put in absolute paths if you don't have them in your path; or use env. vars.
Packit d36e9b
Packit d36e9b
mvprog="${MVPROG-mv}"
Packit d36e9b
cpprog="${CPPROG-cp}"
Packit d36e9b
chmodprog="${CHMODPROG-chmod}"
Packit d36e9b
chownprog="${CHOWNPROG-chown}"
Packit d36e9b
chgrpprog="${CHGRPPROG-chgrp}"
Packit d36e9b
stripprog="${STRIPPROG-strip}"
Packit d36e9b
rmprog="${RMPROG-rm}"
Packit d36e9b
mkdirprog="${MKDIRPROG-mkdir}"
Packit d36e9b
Packit d36e9b
chmodcmd="$chmodprog 0755"
Packit d36e9b
chowncmd=
Packit d36e9b
chgrpcmd=
Packit d36e9b
stripcmd=
Packit d36e9b
rmcmd="$rmprog -f"
Packit d36e9b
mvcmd="$mvprog"
Packit d36e9b
src=
Packit d36e9b
dst=
Packit d36e9b
dir_arg=
Packit d36e9b
dstarg=
Packit d36e9b
no_target_directory=
Packit d36e9b
Packit d36e9b
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
Packit d36e9b
   or: $0 [OPTION]... SRCFILES... DIRECTORY
Packit d36e9b
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
Packit d36e9b
   or: $0 [OPTION]... -d DIRECTORIES...
Packit d36e9b
Packit d36e9b
In the 1st form, copy SRCFILE to DSTFILE.
Packit d36e9b
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
Packit d36e9b
In the 4th, create DIRECTORIES.
Packit d36e9b
Packit d36e9b
Options:
Packit d36e9b
-c         (ignored)
Packit d36e9b
-d         create directories instead of installing files.
Packit d36e9b
-g GROUP   $chgrpprog installed files to GROUP.
Packit d36e9b
-m MODE    $chmodprog installed files to MODE.
Packit d36e9b
-o USER    $chownprog installed files to USER.
Packit d36e9b
-s         $stripprog installed files.
Packit d36e9b
-t DIRECTORY  install into DIRECTORY.
Packit d36e9b
-T         report an error if DSTFILE is a directory.
Packit d36e9b
--help     display this help and exit.
Packit d36e9b
--version  display version info and exit.
Packit d36e9b
Packit d36e9b
Environment variables override the default commands:
Packit d36e9b
  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
Packit d36e9b
"
Packit d36e9b
Packit d36e9b
while test -n "$1"; do
Packit d36e9b
  case $1 in
Packit d36e9b
    -c) shift
Packit d36e9b
        continue;;
Packit d36e9b
Packit d36e9b
    -d) dir_arg=true
Packit d36e9b
        shift
Packit d36e9b
        continue;;
Packit d36e9b
Packit d36e9b
    -g) chgrpcmd="$chgrpprog $2"
Packit d36e9b
        shift
Packit d36e9b
        shift
Packit d36e9b
        continue;;
Packit d36e9b
Packit d36e9b
    --help) echo "$usage"; exit $?;;
Packit d36e9b
Packit d36e9b
    -m) chmodcmd="$chmodprog $2"
Packit d36e9b
        shift
Packit d36e9b
        shift
Packit d36e9b
        continue;;
Packit d36e9b
Packit d36e9b
    -o) chowncmd="$chownprog $2"
Packit d36e9b
        shift
Packit d36e9b
        shift
Packit d36e9b
        continue;;
Packit d36e9b
Packit d36e9b
    -s) stripcmd=$stripprog
Packit d36e9b
        shift
Packit d36e9b
        continue;;
Packit d36e9b
Packit d36e9b
    -t) dstarg=$2
Packit d36e9b
	shift
Packit d36e9b
	shift
Packit d36e9b
	continue;;
Packit d36e9b
Packit d36e9b
    -T) no_target_directory=true
Packit d36e9b
	shift
Packit d36e9b
	continue;;
Packit d36e9b
Packit d36e9b
    --version) echo "$0 $scriptversion"; exit $?;;
Packit d36e9b
Packit d36e9b
    *)  # When -d is used, all remaining arguments are directories to create.
Packit d36e9b
	# When -t is used, the destination is already specified.
Packit d36e9b
	test -n "$dir_arg$dstarg" && break
Packit d36e9b
        # Otherwise, the last argument is the destination.  Remove it from $@.
Packit d36e9b
	for arg
Packit d36e9b
	do
Packit d36e9b
          if test -n "$dstarg"; then
Packit d36e9b
	    # $@ is not empty: it contains at least $arg.
Packit d36e9b
	    set fnord "$@" "$dstarg"
Packit d36e9b
	    shift # fnord
Packit d36e9b
	  fi
Packit d36e9b
	  shift # arg
Packit d36e9b
	  dstarg=$arg
Packit d36e9b
	done
Packit d36e9b
	break;;
Packit d36e9b
  esac
Packit d36e9b
done
Packit d36e9b
Packit d36e9b
if test -z "$1"; then
Packit d36e9b
  if test -z "$dir_arg"; then
Packit d36e9b
    echo "$0: no input file specified." >&2
Packit d36e9b
    exit 1
Packit d36e9b
  fi
Packit d36e9b
  # It's OK to call `install-sh -d' without argument.
Packit d36e9b
  # This can happen when creating conditional directories.
Packit d36e9b
  exit 0
Packit d36e9b
fi
Packit d36e9b
Packit d36e9b
for src
Packit d36e9b
do
Packit d36e9b
  # Protect names starting with `-'.
Packit d36e9b
  case $src in
Packit d36e9b
    -*) src=./$src ;;
Packit d36e9b
  esac
Packit d36e9b
Packit d36e9b
  if test -n "$dir_arg"; then
Packit d36e9b
    dst=$src
Packit d36e9b
    src=
Packit d36e9b
Packit d36e9b
    if test -d "$dst"; then
Packit d36e9b
      mkdircmd=:
Packit d36e9b
      chmodcmd=
Packit d36e9b
    else
Packit d36e9b
      mkdircmd=$mkdirprog
Packit d36e9b
    fi
Packit d36e9b
  else
Packit d36e9b
    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
Packit d36e9b
    # might cause directories to be created, which would be especially bad
Packit d36e9b
    # if $src (and thus $dsttmp) contains '*'.
Packit d36e9b
    if test ! -f "$src" && test ! -d "$src"; then
Packit d36e9b
      echo "$0: $src does not exist." >&2
Packit d36e9b
      exit 1
Packit d36e9b
    fi
Packit d36e9b
Packit d36e9b
    if test -z "$dstarg"; then
Packit d36e9b
      echo "$0: no destination specified." >&2
Packit d36e9b
      exit 1
Packit d36e9b
    fi
Packit d36e9b
Packit d36e9b
    dst=$dstarg
Packit d36e9b
    # Protect names starting with `-'.
Packit d36e9b
    case $dst in
Packit d36e9b
      -*) dst=./$dst ;;
Packit d36e9b
    esac
Packit d36e9b
Packit d36e9b
    # If destination is a directory, append the input filename; won't work
Packit d36e9b
    # if double slashes aren't ignored.
Packit d36e9b
    if test -d "$dst"; then
Packit d36e9b
      if test -n "$no_target_directory"; then
Packit d36e9b
	echo "$0: $dstarg: Is a directory" >&2
Packit d36e9b
	exit 1
Packit d36e9b
      fi
Packit d36e9b
      dst=$dst/`basename "$src"`
Packit d36e9b
    fi
Packit d36e9b
  fi
Packit d36e9b
Packit d36e9b
  # This sed command emulates the dirname command.
Packit d36e9b
  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
Packit d36e9b
Packit d36e9b
  # Make sure that the destination directory exists.
Packit d36e9b
Packit d36e9b
  # Skip lots of stat calls in the usual case.
Packit d36e9b
  if test ! -d "$dstdir"; then
Packit d36e9b
    defaultIFS='
Packit d36e9b
	 '
Packit d36e9b
    IFS="${IFS-$defaultIFS}"
Packit d36e9b
Packit d36e9b
    oIFS=$IFS
Packit d36e9b
    # Some sh's can't handle IFS=/ for some reason.
Packit d36e9b
    IFS='%'
Packit d36e9b
    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
Packit d36e9b
    shift
Packit d36e9b
    IFS=$oIFS
Packit d36e9b
Packit d36e9b
    pathcomp=
Packit d36e9b
Packit d36e9b
    while test $# -ne 0 ; do
Packit d36e9b
      pathcomp=$pathcomp$1
Packit d36e9b
      shift
Packit d36e9b
      if test ! -d "$pathcomp"; then
Packit d36e9b
        $mkdirprog "$pathcomp"
Packit d36e9b
	# mkdir can fail with a `File exist' error in case several
Packit d36e9b
	# install-sh are creating the directory concurrently.  This
Packit d36e9b
	# is OK.
Packit d36e9b
	test -d "$pathcomp" || exit
Packit d36e9b
      fi
Packit d36e9b
      pathcomp=$pathcomp/
Packit d36e9b
    done
Packit d36e9b
  fi
Packit d36e9b
Packit d36e9b
  if test -n "$dir_arg"; then
Packit d36e9b
    $doit $mkdircmd "$dst" \
Packit d36e9b
      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
Packit d36e9b
      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
Packit d36e9b
      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
Packit d36e9b
      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
Packit d36e9b
Packit d36e9b
  else
Packit d36e9b
    dstfile=`basename "$dst"`
Packit d36e9b
Packit d36e9b
    # Make a couple of temp file names in the proper directory.
Packit d36e9b
    dsttmp=$dstdir/_inst.$$_
Packit d36e9b
    rmtmp=$dstdir/_rm.$$_
Packit d36e9b
Packit d36e9b
    # Trap to clean up those temp files at exit.
Packit d36e9b
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
Packit d36e9b
    trap '(exit $?); exit' 1 2 13 15
Packit d36e9b
Packit d36e9b
    # Copy the file name to the temp name.
Packit d36e9b
    $doit $cpprog "$src" "$dsttmp" &&
Packit d36e9b
Packit d36e9b
    # and set any options; do chmod last to preserve setuid bits.
Packit d36e9b
    #
Packit d36e9b
    # If any of these fail, we abort the whole thing.  If we want to
Packit d36e9b
    # ignore errors from any of these, just make sure not to ignore
Packit d36e9b
    # errors from the above "$doit $cpprog $src $dsttmp" command.
Packit d36e9b
    #
Packit d36e9b
    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
Packit d36e9b
      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
Packit d36e9b
      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
Packit d36e9b
      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
Packit d36e9b
Packit d36e9b
    # Now rename the file to the real destination.
Packit d36e9b
    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
Packit d36e9b
      || {
Packit d36e9b
	   # The rename failed, perhaps because mv can't rename something else
Packit d36e9b
	   # to itself, or perhaps because mv is so ancient that it does not
Packit d36e9b
	   # support -f.
Packit d36e9b
Packit d36e9b
	   # Now remove or move aside any old file at destination location.
Packit d36e9b
	   # We try this two ways since rm can't unlink itself on some
Packit d36e9b
	   # systems and the destination file might be busy for other
Packit d36e9b
	   # reasons.  In this case, the final cleanup might fail but the new
Packit d36e9b
	   # file should still install successfully.
Packit d36e9b
	   {
Packit d36e9b
	     if test -f "$dstdir/$dstfile"; then
Packit d36e9b
	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
Packit d36e9b
	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
Packit d36e9b
	       || {
Packit d36e9b
		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
Packit d36e9b
		 (exit 1); exit 1
Packit d36e9b
	       }
Packit d36e9b
	     else
Packit d36e9b
	       :
Packit d36e9b
	     fi
Packit d36e9b
	   } &&
Packit d36e9b
Packit d36e9b
	   # Now rename the file to the real destination.
Packit d36e9b
	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
Packit d36e9b
	 }
Packit d36e9b
    }
Packit d36e9b
  fi || { (exit 1); exit 1; }
Packit d36e9b
done
Packit d36e9b
Packit d36e9b
# The final little trick to "correctly" pass the exit status to the exit trap.
Packit d36e9b
{
Packit d36e9b
  (exit 0); exit 0
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
# Local variables:
Packit d36e9b
# eval: (add-hook 'write-file-hooks 'time-stamp)
Packit d36e9b
# time-stamp-start: "scriptversion="
Packit d36e9b
# time-stamp-format: "%:y-%02m-%02d.%02H"
Packit d36e9b
# time-stamp-end: "$"
Packit d36e9b
# End: