install-sh revision 45bc899b
101e04c3fSmrg#!/bin/sh
201e04c3fSmrg# install - install a program, script, or datafile
301e04c3fSmrg
401e04c3fSmrgscriptversion=2005-05-14.22
501e04c3fSmrg
601e04c3fSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
701e04c3fSmrg# later released in X11R6 (xc/config/util/install.sh) with the
801e04c3fSmrg# following copyright and license.
901e04c3fSmrg#
1001e04c3fSmrg# Copyright (C) 1994 X Consortium
1101e04c3fSmrg#
1201e04c3fSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1301e04c3fSmrg# of this software and associated documentation files (the "Software"), to
1401e04c3fSmrg# deal in the Software without restriction, including without limitation the
1501e04c3fSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1601e04c3fSmrg# sell copies of the Software, and to permit persons to whom the Software is
1701e04c3fSmrg# furnished to do so, subject to the following conditions:
1801e04c3fSmrg#
1901e04c3fSmrg# The above copyright notice and this permission notice shall be included in
2001e04c3fSmrg# all copies or substantial portions of the Software.
2101e04c3fSmrg#
2201e04c3fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2301e04c3fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2401e04c3fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2501e04c3fSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2601e04c3fSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2701e04c3fSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2801e04c3fSmrg#
297ec681f3Smrg# Except as contained in this notice, the name of the X Consortium shall not
307ec681f3Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3101e04c3fSmrg# ings in this Software without prior written authorization from the X Consor-
3201e04c3fSmrg# tium.
337ec681f3Smrg#
347ec681f3Smrg#
357ec681f3Smrg# FSF changes to this file are in the public domain.
367ec681f3Smrg#
377ec681f3Smrg# Calling this script install-sh is preferred over install.sh, to prevent
387ec681f3Smrg# `make' implicit rules from creating a file called install from it
397ec681f3Smrg# when there is no Makefile.
407ec681f3Smrg#
417ec681f3Smrg# This script is compatible with the BSD install script, but was written
427ec681f3Smrg# from scratch.  It can only install one file at a time, a restriction
4301e04c3fSmrg# shared with many OS's install programs.
4401e04c3fSmrg
457ec681f3Smrg# set DOITPROG to echo to test this script
467ec681f3Smrg
477ec681f3Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
487ec681f3Smrgdoit="${DOITPROG-}"
497ec681f3Smrg
507ec681f3Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
517ec681f3Smrg
527ec681f3Smrgmvprog="${MVPROG-mv}"
537ec681f3Smrgcpprog="${CPPROG-cp}"
547ec681f3Smrgchmodprog="${CHMODPROG-chmod}"
557ec681f3Smrgchownprog="${CHOWNPROG-chown}"
567ec681f3Smrgchgrpprog="${CHGRPPROG-chgrp}"
577ec681f3Smrgstripprog="${STRIPPROG-strip}"
587ec681f3Smrgrmprog="${RMPROG-rm}"
597ec681f3Smrgmkdirprog="${MKDIRPROG-mkdir}"
607ec681f3Smrg
617ec681f3Smrgchmodcmd="$chmodprog 0755"
627ec681f3Smrgchowncmd=
637ec681f3Smrgchgrpcmd=
647ec681f3Smrgstripcmd=
657ec681f3Smrgrmcmd="$rmprog -f"
667ec681f3Smrgmvcmd="$mvprog"
6701e04c3fSmrgsrc=
6801e04c3fSmrgdst=
6901e04c3fSmrgdir_arg=
7001e04c3fSmrgdstarg=
7101e04c3fSmrgno_target_directory=
7201e04c3fSmrg
7301e04c3fSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7401e04c3fSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7501e04c3fSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7601e04c3fSmrg   or: $0 [OPTION]... -d DIRECTORIES...
7701e04c3fSmrg
7801e04c3fSmrgIn the 1st form, copy SRCFILE to DSTFILE.
7901e04c3fSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
807ec681f3SmrgIn the 4th, create DIRECTORIES.
817ec681f3Smrg
827ec681f3SmrgOptions:
837ec681f3Smrg-c         (ignored)
847ec681f3Smrg-d         create directories instead of installing files.
857ec681f3Smrg-g GROUP   $chgrpprog installed files to GROUP.
867ec681f3Smrg-m MODE    $chmodprog installed files to MODE.
877ec681f3Smrg-o USER    $chownprog installed files to USER.
887ec681f3Smrg-s         $stripprog installed files.
897ec681f3Smrg-t DIRECTORY  install into DIRECTORY.
907ec681f3Smrg-T         report an error if DSTFILE is a directory.
917ec681f3Smrg--help     display this help and exit.
927ec681f3Smrg--version  display version info and exit.
937e102996Smaya
947ec681f3SmrgEnvironment variables override the default commands:
957ec681f3Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
967ec681f3Smrg"
977e102996Smaya
987ec681f3Smrgwhile test -n "$1"; do
997ec681f3Smrg  case $1 in
1007e102996Smaya    -c) shift
10101e04c3fSmrg        continue;;
10201e04c3fSmrg
10301e04c3fSmrg    -d) dir_arg=true
1047ec681f3Smrg        shift
1057ec681f3Smrg        continue;;
1067ec681f3Smrg
10701e04c3fSmrg    -g) chgrpcmd="$chgrpprog $2"
10801e04c3fSmrg        shift
10901e04c3fSmrg        shift
11001e04c3fSmrg        continue;;
11101e04c3fSmrg
11201e04c3fSmrg    --help) echo "$usage"; exit $?;;
1137ec681f3Smrg
1147ec681f3Smrg    -m) chmodcmd="$chmodprog $2"
1157ec681f3Smrg        shift
1167ec681f3Smrg        shift
1177ec681f3Smrg        continue;;
1187ec681f3Smrg
1197ec681f3Smrg    -o) chowncmd="$chownprog $2"
1207ec681f3Smrg        shift
1217ec681f3Smrg        shift
1227ec681f3Smrg        continue;;
12301e04c3fSmrg
1247ec681f3Smrg    -s) stripcmd=$stripprog
1257ec681f3Smrg        shift
1267ec681f3Smrg        continue;;
1277ec681f3Smrg
1287ec681f3Smrg    -t) dstarg=$2
1297ec681f3Smrg	shift
1307ec681f3Smrg	shift
1317ec681f3Smrg	continue;;
1327ec681f3Smrg
1337e102996Smaya    -T) no_target_directory=true
1347ec681f3Smrg	shift
1357e102996Smaya	continue;;
1367ec681f3Smrg
1377e102996Smaya    --version) echo "$0 $scriptversion"; exit $?;;
1387ec681f3Smrg
13901e04c3fSmrg    *)  # When -d is used, all remaining arguments are directories to create.
1407ec681f3Smrg	# When -t is used, the destination is already specified.
1417e102996Smaya	test -n "$dir_arg$dstarg" && break
1427ec681f3Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14301e04c3fSmrg	for arg
1447ec681f3Smrg	do
1457e102996Smaya          if test -n "$dstarg"; then
1467ec681f3Smrg	    # $@ is not empty: it contains at least $arg.
14701e04c3fSmrg	    set fnord "$@" "$dstarg"
1487ec681f3Smrg	    shift # fnord
1497e102996Smaya	  fi
1507ec681f3Smrg	  shift # arg
15101e04c3fSmrg	  dstarg=$arg
1527ec681f3Smrg	done
1537ec681f3Smrg	break;;
1547ec681f3Smrg  esac
15501e04c3fSmrgdone
15601e04c3fSmrg
15701e04c3fSmrgif test -z "$1"; then
15801e04c3fSmrg  if test -z "$dir_arg"; then
15901e04c3fSmrg    echo "$0: no input file specified." >&2
16001e04c3fSmrg    exit 1
16101e04c3fSmrg  fi
16201e04c3fSmrg  # It's OK to call `install-sh -d' without argument.
16301e04c3fSmrg  # This can happen when creating conditional directories.
16401e04c3fSmrg  exit 0
16501e04c3fSmrgfi
16601e04c3fSmrg
16701e04c3fSmrgfor src
16801e04c3fSmrgdo
16901e04c3fSmrg  # Protect names starting with `-'.
17001e04c3fSmrg  case $src in
17101e04c3fSmrg    -*) src=./$src ;;
17201e04c3fSmrg  esac
17301e04c3fSmrg
17401e04c3fSmrg  if test -n "$dir_arg"; then
17501e04c3fSmrg    dst=$src
17601e04c3fSmrg    src=
17701e04c3fSmrg
1787ec681f3Smrg    if test -d "$dst"; then
17901e04c3fSmrg      mkdircmd=:
1807ec681f3Smrg      chmodcmd=
1817ec681f3Smrg    else
1827ec681f3Smrg      mkdircmd=$mkdirprog
1837ec681f3Smrg    fi
18401e04c3fSmrg  else
1857ec681f3Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
1867ec681f3Smrg    # might cause directories to be created, which would be especially bad
1877ec681f3Smrg    # if $src (and thus $dsttmp) contains '*'.
1887ec681f3Smrg    if test ! -f "$src" && test ! -d "$src"; then
18901e04c3fSmrg      echo "$0: $src does not exist." >&2
19001e04c3fSmrg      exit 1
19101e04c3fSmrg    fi
19201e04c3fSmrg
19301e04c3fSmrg    if test -z "$dstarg"; then
1947ec681f3Smrg      echo "$0: no destination specified." >&2
1957ec681f3Smrg      exit 1
19601e04c3fSmrg    fi
19701e04c3fSmrg
19801e04c3fSmrg    dst=$dstarg
19901e04c3fSmrg    # Protect names starting with `-'.
20001e04c3fSmrg    case $dst in
2017ec681f3Smrg      -*) dst=./$dst ;;
2027ec681f3Smrg    esac
2037ec681f3Smrg
2047ec681f3Smrg    # If destination is a directory, append the input filename; won't work
2057ec681f3Smrg    # if double slashes aren't ignored.
2067ec681f3Smrg    if test -d "$dst"; then
2077ec681f3Smrg      if test -n "$no_target_directory"; then
2087ec681f3Smrg	echo "$0: $dstarg: Is a directory" >&2
2097ec681f3Smrg	exit 1
2107ec681f3Smrg      fi
2117ec681f3Smrg      dst=$dst/`basename "$src"`
2127ec681f3Smrg    fi
2137ec681f3Smrg  fi
21401e04c3fSmrg
21501e04c3fSmrg  # This sed command emulates the dirname command.
21601e04c3fSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21701e04c3fSmrg
21801e04c3fSmrg  # Make sure that the destination directory exists.
21901e04c3fSmrg
22001e04c3fSmrg  # Skip lots of stat calls in the usual case.
2217ec681f3Smrg  if test ! -d "$dstdir"; then
22201e04c3fSmrg    defaultIFS='
22301e04c3fSmrg	 '
22401e04c3fSmrg    IFS="${IFS-$defaultIFS}"
22501e04c3fSmrg
2267ec681f3Smrg    oIFS=$IFS
22701e04c3fSmrg    # Some sh's can't handle IFS=/ for some reason.
22801e04c3fSmrg    IFS='%'
22901e04c3fSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23001e04c3fSmrg    shift
23101e04c3fSmrg    IFS=$oIFS
23201e04c3fSmrg
23301e04c3fSmrg    pathcomp=
2347ec681f3Smrg
23501e04c3fSmrg    while test $# -ne 0 ; do
23601e04c3fSmrg      pathcomp=$pathcomp$1
23701e04c3fSmrg      shift
23801e04c3fSmrg      if test ! -d "$pathcomp"; then
23901e04c3fSmrg        $mkdirprog "$pathcomp"
24001e04c3fSmrg	# mkdir can fail with a `File exist' error in case several
2417ec681f3Smrg	# install-sh are creating the directory concurrently.  This
24201e04c3fSmrg	# is OK.
2437ec681f3Smrg	test -d "$pathcomp" || exit
2447ec681f3Smrg      fi
2457ec681f3Smrg      pathcomp=$pathcomp/
2467e102996Smaya    done
24701e04c3fSmrg  fi
2487ec681f3Smrg
2497ec681f3Smrg  if test -n "$dir_arg"; then
2507ec681f3Smrg    $doit $mkdircmd "$dst" \
2517ec681f3Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
2527ec681f3Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
2537ec681f3Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
2547ec681f3Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25501e04c3fSmrg
25601e04c3fSmrg  else
2577ec681f3Smrg    dstfile=`basename "$dst"`
25801e04c3fSmrg
2597ec681f3Smrg    # Make a couple of temp file names in the proper directory.
2607ec681f3Smrg    dsttmp=$dstdir/_inst.$$_
26101e04c3fSmrg    rmtmp=$dstdir/_rm.$$_
2627ec681f3Smrg
2637ec681f3Smrg    # Trap to clean up those temp files at exit.
2647ec681f3Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
2657ec681f3Smrg    trap '(exit $?); exit' 1 2 13 15
2667ec681f3Smrg
26701e04c3fSmrg    # Copy the file name to the temp name.
26801e04c3fSmrg    $doit $cpprog "$src" "$dsttmp" &&
2697ec681f3Smrg
27001e04c3fSmrg    # and set any options; do chmod last to preserve setuid bits.
2717ec681f3Smrg    #
2727ec681f3Smrg    # If any of these fail, we abort the whole thing.  If we want to
2737ec681f3Smrg    # ignore errors from any of these, just make sure not to ignore
2747e102996Smaya    # errors from the above "$doit $cpprog $src $dsttmp" command.
27501e04c3fSmrg    #
2767ec681f3Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
2777ec681f3Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
2787ec681f3Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
2797ec681f3Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
2807ec681f3Smrg
2817ec681f3Smrg    # Now rename the file to the real destination.
2827ec681f3Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
2837ec681f3Smrg      || {
2847ec681f3Smrg	   # The rename failed, perhaps because mv can't rename something else
2857ec681f3Smrg	   # to itself, or perhaps because mv is so ancient that it does not
2867ec681f3Smrg	   # support -f.
28701e04c3fSmrg
28801e04c3fSmrg	   # Now remove or move aside any old file at destination location.
28901e04c3fSmrg	   # We try this two ways since rm can't unlink itself on some
29001e04c3fSmrg	   # systems and the destination file might be busy for other
2917ec681f3Smrg	   # reasons.  In this case, the final cleanup might fail but the new
2927ec681f3Smrg	   # file should still install successfully.
2937ec681f3Smrg	   {
2947ec681f3Smrg	     if test -f "$dstdir/$dstfile"; then
2957ec681f3Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
2967ec681f3Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
2977ec681f3Smrg	       || {
2987ec681f3Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2997ec681f3Smrg		 (exit 1); exit 1
3007ec681f3Smrg	       }
3017ec681f3Smrg	     else
3027ec681f3Smrg	       :
30301e04c3fSmrg	     fi
30401e04c3fSmrg	   } &&
30501e04c3fSmrg
30601e04c3fSmrg	   # Now rename the file to the real destination.
3077ec681f3Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30801e04c3fSmrg	 }
30901e04c3fSmrg    }
31001e04c3fSmrg  fi || { (exit 1); exit 1; }
31101e04c3fSmrgdone
31201e04c3fSmrg
31301e04c3fSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
3147ec681f3Smrg{
3157ec681f3Smrg  (exit 0); exit 0
3167ec681f3Smrg}
3177ec681f3Smrg
3187ec681f3Smrg# Local variables:
3197ec681f3Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
3207ec681f3Smrg# time-stamp-start: "scriptversion="
32101e04c3fSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32201e04c3fSmrg# time-stamp-end: "$"
3237ec681f3Smrg# End:
3247ec681f3Smrg