install-sh revision 1d54945d
11d54945dSmrg#!/bin/sh
21d54945dSmrg# install - install a program, script, or datafile
31d54945dSmrg
41d54945dSmrgscriptversion=2005-05-14.22
51d54945dSmrg
61d54945dSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
71d54945dSmrg# later released in X11R6 (xc/config/util/install.sh) with the
81d54945dSmrg# following copyright and license.
91d54945dSmrg#
101d54945dSmrg# Copyright (C) 1994 X Consortium
111d54945dSmrg#
121d54945dSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
131d54945dSmrg# of this software and associated documentation files (the "Software"), to
141d54945dSmrg# deal in the Software without restriction, including without limitation the
151d54945dSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
161d54945dSmrg# sell copies of the Software, and to permit persons to whom the Software is
171d54945dSmrg# furnished to do so, subject to the following conditions:
181d54945dSmrg#
191d54945dSmrg# The above copyright notice and this permission notice shall be included in
201d54945dSmrg# all copies or substantial portions of the Software.
211d54945dSmrg#
221d54945dSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
231d54945dSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
241d54945dSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
251d54945dSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
261d54945dSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
271d54945dSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
281d54945dSmrg#
291d54945dSmrg# Except as contained in this notice, the name of the X Consortium shall not
301d54945dSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
311d54945dSmrg# ings in this Software without prior written authorization from the X Consor-
321d54945dSmrg# tium.
331d54945dSmrg#
341d54945dSmrg#
351d54945dSmrg# FSF changes to this file are in the public domain.
361d54945dSmrg#
371d54945dSmrg# Calling this script install-sh is preferred over install.sh, to prevent
381d54945dSmrg# `make' implicit rules from creating a file called install from it
391d54945dSmrg# when there is no Makefile.
401d54945dSmrg#
411d54945dSmrg# This script is compatible with the BSD install script, but was written
421d54945dSmrg# from scratch.  It can only install one file at a time, a restriction
431d54945dSmrg# shared with many OS's install programs.
441d54945dSmrg
451d54945dSmrg# set DOITPROG to echo to test this script
461d54945dSmrg
471d54945dSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
481d54945dSmrgdoit="${DOITPROG-}"
491d54945dSmrg
501d54945dSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
511d54945dSmrg
521d54945dSmrgmvprog="${MVPROG-mv}"
531d54945dSmrgcpprog="${CPPROG-cp}"
541d54945dSmrgchmodprog="${CHMODPROG-chmod}"
551d54945dSmrgchownprog="${CHOWNPROG-chown}"
561d54945dSmrgchgrpprog="${CHGRPPROG-chgrp}"
571d54945dSmrgstripprog="${STRIPPROG-strip}"
581d54945dSmrgrmprog="${RMPROG-rm}"
591d54945dSmrgmkdirprog="${MKDIRPROG-mkdir}"
601d54945dSmrg
611d54945dSmrgchmodcmd="$chmodprog 0755"
621d54945dSmrgchowncmd=
631d54945dSmrgchgrpcmd=
641d54945dSmrgstripcmd=
651d54945dSmrgrmcmd="$rmprog -f"
661d54945dSmrgmvcmd="$mvprog"
671d54945dSmrgsrc=
681d54945dSmrgdst=
691d54945dSmrgdir_arg=
701d54945dSmrgdstarg=
711d54945dSmrgno_target_directory=
721d54945dSmrg
731d54945dSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
741d54945dSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
751d54945dSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
761d54945dSmrg   or: $0 [OPTION]... -d DIRECTORIES...
771d54945dSmrg
781d54945dSmrgIn the 1st form, copy SRCFILE to DSTFILE.
791d54945dSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
801d54945dSmrgIn the 4th, create DIRECTORIES.
811d54945dSmrg
821d54945dSmrgOptions:
831d54945dSmrg-c         (ignored)
841d54945dSmrg-d         create directories instead of installing files.
851d54945dSmrg-g GROUP   $chgrpprog installed files to GROUP.
861d54945dSmrg-m MODE    $chmodprog installed files to MODE.
871d54945dSmrg-o USER    $chownprog installed files to USER.
881d54945dSmrg-s         $stripprog installed files.
891d54945dSmrg-t DIRECTORY  install into DIRECTORY.
901d54945dSmrg-T         report an error if DSTFILE is a directory.
911d54945dSmrg--help     display this help and exit.
921d54945dSmrg--version  display version info and exit.
931d54945dSmrg
941d54945dSmrgEnvironment variables override the default commands:
951d54945dSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
961d54945dSmrg"
971d54945dSmrg
981d54945dSmrgwhile test -n "$1"; do
991d54945dSmrg  case $1 in
1001d54945dSmrg    -c) shift
1011d54945dSmrg        continue;;
1021d54945dSmrg
1031d54945dSmrg    -d) dir_arg=true
1041d54945dSmrg        shift
1051d54945dSmrg        continue;;
1061d54945dSmrg
1071d54945dSmrg    -g) chgrpcmd="$chgrpprog $2"
1081d54945dSmrg        shift
1091d54945dSmrg        shift
1101d54945dSmrg        continue;;
1111d54945dSmrg
1121d54945dSmrg    --help) echo "$usage"; exit $?;;
1131d54945dSmrg
1141d54945dSmrg    -m) chmodcmd="$chmodprog $2"
1151d54945dSmrg        shift
1161d54945dSmrg        shift
1171d54945dSmrg        continue;;
1181d54945dSmrg
1191d54945dSmrg    -o) chowncmd="$chownprog $2"
1201d54945dSmrg        shift
1211d54945dSmrg        shift
1221d54945dSmrg        continue;;
1231d54945dSmrg
1241d54945dSmrg    -s) stripcmd=$stripprog
1251d54945dSmrg        shift
1261d54945dSmrg        continue;;
1271d54945dSmrg
1281d54945dSmrg    -t) dstarg=$2
1291d54945dSmrg	shift
1301d54945dSmrg	shift
1311d54945dSmrg	continue;;
1321d54945dSmrg
1331d54945dSmrg    -T) no_target_directory=true
1341d54945dSmrg	shift
1351d54945dSmrg	continue;;
1361d54945dSmrg
1371d54945dSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1381d54945dSmrg
1391d54945dSmrg    *)  # When -d is used, all remaining arguments are directories to create.
1401d54945dSmrg	# When -t is used, the destination is already specified.
1411d54945dSmrg	test -n "$dir_arg$dstarg" && break
1421d54945dSmrg        # Otherwise, the last argument is the destination.  Remove it from $@.
1431d54945dSmrg	for arg
1441d54945dSmrg	do
1451d54945dSmrg          if test -n "$dstarg"; then
1461d54945dSmrg	    # $@ is not empty: it contains at least $arg.
1471d54945dSmrg	    set fnord "$@" "$dstarg"
1481d54945dSmrg	    shift # fnord
1491d54945dSmrg	  fi
1501d54945dSmrg	  shift # arg
1511d54945dSmrg	  dstarg=$arg
1521d54945dSmrg	done
1531d54945dSmrg	break;;
1541d54945dSmrg  esac
1551d54945dSmrgdone
1561d54945dSmrg
1571d54945dSmrgif test -z "$1"; then
1581d54945dSmrg  if test -z "$dir_arg"; then
1591d54945dSmrg    echo "$0: no input file specified." >&2
1601d54945dSmrg    exit 1
1611d54945dSmrg  fi
1621d54945dSmrg  # It's OK to call `install-sh -d' without argument.
1631d54945dSmrg  # This can happen when creating conditional directories.
1641d54945dSmrg  exit 0
1651d54945dSmrgfi
1661d54945dSmrg
1671d54945dSmrgfor src
1681d54945dSmrgdo
1691d54945dSmrg  # Protect names starting with `-'.
1701d54945dSmrg  case $src in
1711d54945dSmrg    -*) src=./$src ;;
1721d54945dSmrg  esac
1731d54945dSmrg
1741d54945dSmrg  if test -n "$dir_arg"; then
1751d54945dSmrg    dst=$src
1761d54945dSmrg    src=
1771d54945dSmrg
1781d54945dSmrg    if test -d "$dst"; then
1791d54945dSmrg      mkdircmd=:
1801d54945dSmrg      chmodcmd=
1811d54945dSmrg    else
1821d54945dSmrg      mkdircmd=$mkdirprog
1831d54945dSmrg    fi
1841d54945dSmrg  else
1851d54945dSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
1861d54945dSmrg    # might cause directories to be created, which would be especially bad
1871d54945dSmrg    # if $src (and thus $dsttmp) contains '*'.
1881d54945dSmrg    if test ! -f "$src" && test ! -d "$src"; then
1891d54945dSmrg      echo "$0: $src does not exist." >&2
1901d54945dSmrg      exit 1
1911d54945dSmrg    fi
1921d54945dSmrg
1931d54945dSmrg    if test -z "$dstarg"; then
1941d54945dSmrg      echo "$0: no destination specified." >&2
1951d54945dSmrg      exit 1
1961d54945dSmrg    fi
1971d54945dSmrg
1981d54945dSmrg    dst=$dstarg
1991d54945dSmrg    # Protect names starting with `-'.
2001d54945dSmrg    case $dst in
2011d54945dSmrg      -*) dst=./$dst ;;
2021d54945dSmrg    esac
2031d54945dSmrg
2041d54945dSmrg    # If destination is a directory, append the input filename; won't work
2051d54945dSmrg    # if double slashes aren't ignored.
2061d54945dSmrg    if test -d "$dst"; then
2071d54945dSmrg      if test -n "$no_target_directory"; then
2081d54945dSmrg	echo "$0: $dstarg: Is a directory" >&2
2091d54945dSmrg	exit 1
2101d54945dSmrg      fi
2111d54945dSmrg      dst=$dst/`basename "$src"`
2121d54945dSmrg    fi
2131d54945dSmrg  fi
2141d54945dSmrg
2151d54945dSmrg  # This sed command emulates the dirname command.
2161d54945dSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
2171d54945dSmrg
2181d54945dSmrg  # Make sure that the destination directory exists.
2191d54945dSmrg
2201d54945dSmrg  # Skip lots of stat calls in the usual case.
2211d54945dSmrg  if test ! -d "$dstdir"; then
2221d54945dSmrg    defaultIFS='
2231d54945dSmrg	 '
2241d54945dSmrg    IFS="${IFS-$defaultIFS}"
2251d54945dSmrg
2261d54945dSmrg    oIFS=$IFS
2271d54945dSmrg    # Some sh's can't handle IFS=/ for some reason.
2281d54945dSmrg    IFS='%'
2291d54945dSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
2301d54945dSmrg    shift
2311d54945dSmrg    IFS=$oIFS
2321d54945dSmrg
2331d54945dSmrg    pathcomp=
2341d54945dSmrg
2351d54945dSmrg    while test $# -ne 0 ; do
2361d54945dSmrg      pathcomp=$pathcomp$1
2371d54945dSmrg      shift
2381d54945dSmrg      if test ! -d "$pathcomp"; then
2391d54945dSmrg        $mkdirprog "$pathcomp"
2401d54945dSmrg	# mkdir can fail with a `File exist' error in case several
2411d54945dSmrg	# install-sh are creating the directory concurrently.  This
2421d54945dSmrg	# is OK.
2431d54945dSmrg	test -d "$pathcomp" || exit
2441d54945dSmrg      fi
2451d54945dSmrg      pathcomp=$pathcomp/
2461d54945dSmrg    done
2471d54945dSmrg  fi
2481d54945dSmrg
2491d54945dSmrg  if test -n "$dir_arg"; then
2501d54945dSmrg    $doit $mkdircmd "$dst" \
2511d54945dSmrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
2521d54945dSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
2531d54945dSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
2541d54945dSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
2551d54945dSmrg
2561d54945dSmrg  else
2571d54945dSmrg    dstfile=`basename "$dst"`
2581d54945dSmrg
2591d54945dSmrg    # Make a couple of temp file names in the proper directory.
2601d54945dSmrg    dsttmp=$dstdir/_inst.$$_
2611d54945dSmrg    rmtmp=$dstdir/_rm.$$_
2621d54945dSmrg
2631d54945dSmrg    # Trap to clean up those temp files at exit.
2641d54945dSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
2651d54945dSmrg    trap '(exit $?); exit' 1 2 13 15
2661d54945dSmrg
2671d54945dSmrg    # Copy the file name to the temp name.
2681d54945dSmrg    $doit $cpprog "$src" "$dsttmp" &&
2691d54945dSmrg
2701d54945dSmrg    # and set any options; do chmod last to preserve setuid bits.
2711d54945dSmrg    #
2721d54945dSmrg    # If any of these fail, we abort the whole thing.  If we want to
2731d54945dSmrg    # ignore errors from any of these, just make sure not to ignore
2741d54945dSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
2751d54945dSmrg    #
2761d54945dSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
2771d54945dSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
2781d54945dSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
2791d54945dSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
2801d54945dSmrg
2811d54945dSmrg    # Now rename the file to the real destination.
2821d54945dSmrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
2831d54945dSmrg      || {
2841d54945dSmrg	   # The rename failed, perhaps because mv can't rename something else
2851d54945dSmrg	   # to itself, or perhaps because mv is so ancient that it does not
2861d54945dSmrg	   # support -f.
2871d54945dSmrg
2881d54945dSmrg	   # Now remove or move aside any old file at destination location.
2891d54945dSmrg	   # We try this two ways since rm can't unlink itself on some
2901d54945dSmrg	   # systems and the destination file might be busy for other
2911d54945dSmrg	   # reasons.  In this case, the final cleanup might fail but the new
2921d54945dSmrg	   # file should still install successfully.
2931d54945dSmrg	   {
2941d54945dSmrg	     if test -f "$dstdir/$dstfile"; then
2951d54945dSmrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
2961d54945dSmrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
2971d54945dSmrg	       || {
2981d54945dSmrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2991d54945dSmrg		 (exit 1); exit 1
3001d54945dSmrg	       }
3011d54945dSmrg	     else
3021d54945dSmrg	       :
3031d54945dSmrg	     fi
3041d54945dSmrg	   } &&
3051d54945dSmrg
3061d54945dSmrg	   # Now rename the file to the real destination.
3071d54945dSmrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
3081d54945dSmrg	 }
3091d54945dSmrg    }
3101d54945dSmrg  fi || { (exit 1); exit 1; }
3111d54945dSmrgdone
3121d54945dSmrg
3131d54945dSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
3141d54945dSmrg{
3151d54945dSmrg  (exit 0); exit 0
3161d54945dSmrg}
3171d54945dSmrg
3181d54945dSmrg# Local variables:
3191d54945dSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
3201d54945dSmrg# time-stamp-start: "scriptversion="
3211d54945dSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
3221d54945dSmrg# time-stamp-end: "$"
3231d54945dSmrg# End:
324