install-sh revision 3eed67fa
13eed67faSmbalmer#!/bin/sh
23eed67faSmbalmer# install - install a program, script, or datafile
33eed67faSmbalmer
43eed67faSmbalmerscriptversion=2005-05-14.22
53eed67faSmbalmer
63eed67faSmbalmer# This originates from X11R5 (mit/util/scripts/install.sh), which was
73eed67faSmbalmer# later released in X11R6 (xc/config/util/install.sh) with the
83eed67faSmbalmer# following copyright and license.
93eed67faSmbalmer#
103eed67faSmbalmer# Copyright (C) 1994 X Consortium
113eed67faSmbalmer#
123eed67faSmbalmer# Permission is hereby granted, free of charge, to any person obtaining a copy
133eed67faSmbalmer# of this software and associated documentation files (the "Software"), to
143eed67faSmbalmer# deal in the Software without restriction, including without limitation the
153eed67faSmbalmer# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
163eed67faSmbalmer# sell copies of the Software, and to permit persons to whom the Software is
173eed67faSmbalmer# furnished to do so, subject to the following conditions:
183eed67faSmbalmer#
193eed67faSmbalmer# The above copyright notice and this permission notice shall be included in
203eed67faSmbalmer# all copies or substantial portions of the Software.
213eed67faSmbalmer#
223eed67faSmbalmer# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
233eed67faSmbalmer# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
243eed67faSmbalmer# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
253eed67faSmbalmer# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
263eed67faSmbalmer# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
273eed67faSmbalmer# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
283eed67faSmbalmer#
293eed67faSmbalmer# Except as contained in this notice, the name of the X Consortium shall not
303eed67faSmbalmer# be used in advertising or otherwise to promote the sale, use or other deal-
313eed67faSmbalmer# ings in this Software without prior written authorization from the X Consor-
323eed67faSmbalmer# tium.
333eed67faSmbalmer#
343eed67faSmbalmer#
353eed67faSmbalmer# FSF changes to this file are in the public domain.
363eed67faSmbalmer#
373eed67faSmbalmer# Calling this script install-sh is preferred over install.sh, to prevent
383eed67faSmbalmer# `make' implicit rules from creating a file called install from it
393eed67faSmbalmer# when there is no Makefile.
403eed67faSmbalmer#
413eed67faSmbalmer# This script is compatible with the BSD install script, but was written
423eed67faSmbalmer# from scratch.  It can only install one file at a time, a restriction
433eed67faSmbalmer# shared with many OS's install programs.
443eed67faSmbalmer
453eed67faSmbalmer# set DOITPROG to echo to test this script
463eed67faSmbalmer
473eed67faSmbalmer# Don't use :- since 4.3BSD and earlier shells don't like it.
483eed67faSmbalmerdoit="${DOITPROG-}"
493eed67faSmbalmer
503eed67faSmbalmer# put in absolute paths if you don't have them in your path; or use env. vars.
513eed67faSmbalmer
523eed67faSmbalmermvprog="${MVPROG-mv}"
533eed67faSmbalmercpprog="${CPPROG-cp}"
543eed67faSmbalmerchmodprog="${CHMODPROG-chmod}"
553eed67faSmbalmerchownprog="${CHOWNPROG-chown}"
563eed67faSmbalmerchgrpprog="${CHGRPPROG-chgrp}"
573eed67faSmbalmerstripprog="${STRIPPROG-strip}"
583eed67faSmbalmerrmprog="${RMPROG-rm}"
593eed67faSmbalmermkdirprog="${MKDIRPROG-mkdir}"
603eed67faSmbalmer
613eed67faSmbalmerchmodcmd="$chmodprog 0755"
623eed67faSmbalmerchowncmd=
633eed67faSmbalmerchgrpcmd=
643eed67faSmbalmerstripcmd=
653eed67faSmbalmerrmcmd="$rmprog -f"
663eed67faSmbalmermvcmd="$mvprog"
673eed67faSmbalmersrc=
683eed67faSmbalmerdst=
693eed67faSmbalmerdir_arg=
703eed67faSmbalmerdstarg=
713eed67faSmbalmerno_target_directory=
723eed67faSmbalmer
733eed67faSmbalmerusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
743eed67faSmbalmer   or: $0 [OPTION]... SRCFILES... DIRECTORY
753eed67faSmbalmer   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
763eed67faSmbalmer   or: $0 [OPTION]... -d DIRECTORIES...
773eed67faSmbalmer
783eed67faSmbalmerIn the 1st form, copy SRCFILE to DSTFILE.
793eed67faSmbalmerIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
803eed67faSmbalmerIn the 4th, create DIRECTORIES.
813eed67faSmbalmer
823eed67faSmbalmerOptions:
833eed67faSmbalmer-c         (ignored)
843eed67faSmbalmer-d         create directories instead of installing files.
853eed67faSmbalmer-g GROUP   $chgrpprog installed files to GROUP.
863eed67faSmbalmer-m MODE    $chmodprog installed files to MODE.
873eed67faSmbalmer-o USER    $chownprog installed files to USER.
883eed67faSmbalmer-s         $stripprog installed files.
893eed67faSmbalmer-t DIRECTORY  install into DIRECTORY.
903eed67faSmbalmer-T         report an error if DSTFILE is a directory.
913eed67faSmbalmer--help     display this help and exit.
923eed67faSmbalmer--version  display version info and exit.
933eed67faSmbalmer
943eed67faSmbalmerEnvironment variables override the default commands:
953eed67faSmbalmer  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
963eed67faSmbalmer"
973eed67faSmbalmer
983eed67faSmbalmerwhile test -n "$1"; do
993eed67faSmbalmer  case $1 in
1003eed67faSmbalmer    -c) shift
1013eed67faSmbalmer        continue;;
1023eed67faSmbalmer
1033eed67faSmbalmer    -d) dir_arg=true
1043eed67faSmbalmer        shift
1053eed67faSmbalmer        continue;;
1063eed67faSmbalmer
1073eed67faSmbalmer    -g) chgrpcmd="$chgrpprog $2"
1083eed67faSmbalmer        shift
1093eed67faSmbalmer        shift
1103eed67faSmbalmer        continue;;
1113eed67faSmbalmer
1123eed67faSmbalmer    --help) echo "$usage"; exit $?;;
1133eed67faSmbalmer
1143eed67faSmbalmer    -m) chmodcmd="$chmodprog $2"
1153eed67faSmbalmer        shift
1163eed67faSmbalmer        shift
1173eed67faSmbalmer        continue;;
1183eed67faSmbalmer
1193eed67faSmbalmer    -o) chowncmd="$chownprog $2"
1203eed67faSmbalmer        shift
1213eed67faSmbalmer        shift
1223eed67faSmbalmer        continue;;
1233eed67faSmbalmer
1243eed67faSmbalmer    -s) stripcmd=$stripprog
1253eed67faSmbalmer        shift
1263eed67faSmbalmer        continue;;
1273eed67faSmbalmer
1283eed67faSmbalmer    -t) dstarg=$2
1293eed67faSmbalmer	shift
1303eed67faSmbalmer	shift
1313eed67faSmbalmer	continue;;
1323eed67faSmbalmer
1333eed67faSmbalmer    -T) no_target_directory=true
1343eed67faSmbalmer	shift
1353eed67faSmbalmer	continue;;
1363eed67faSmbalmer
1373eed67faSmbalmer    --version) echo "$0 $scriptversion"; exit $?;;
1383eed67faSmbalmer
1393eed67faSmbalmer    *)  # When -d is used, all remaining arguments are directories to create.
1403eed67faSmbalmer	# When -t is used, the destination is already specified.
1413eed67faSmbalmer	test -n "$dir_arg$dstarg" && break
1423eed67faSmbalmer        # Otherwise, the last argument is the destination.  Remove it from $@.
1433eed67faSmbalmer	for arg
1443eed67faSmbalmer	do
1453eed67faSmbalmer          if test -n "$dstarg"; then
1463eed67faSmbalmer	    # $@ is not empty: it contains at least $arg.
1473eed67faSmbalmer	    set fnord "$@" "$dstarg"
1483eed67faSmbalmer	    shift # fnord
1493eed67faSmbalmer	  fi
1503eed67faSmbalmer	  shift # arg
1513eed67faSmbalmer	  dstarg=$arg
1523eed67faSmbalmer	done
1533eed67faSmbalmer	break;;
1543eed67faSmbalmer  esac
1553eed67faSmbalmerdone
1563eed67faSmbalmer
1573eed67faSmbalmerif test -z "$1"; then
1583eed67faSmbalmer  if test -z "$dir_arg"; then
1593eed67faSmbalmer    echo "$0: no input file specified." >&2
1603eed67faSmbalmer    exit 1
1613eed67faSmbalmer  fi
1623eed67faSmbalmer  # It's OK to call `install-sh -d' without argument.
1633eed67faSmbalmer  # This can happen when creating conditional directories.
1643eed67faSmbalmer  exit 0
1653eed67faSmbalmerfi
1663eed67faSmbalmer
1673eed67faSmbalmerfor src
1683eed67faSmbalmerdo
1693eed67faSmbalmer  # Protect names starting with `-'.
1703eed67faSmbalmer  case $src in
1713eed67faSmbalmer    -*) src=./$src ;;
1723eed67faSmbalmer  esac
1733eed67faSmbalmer
1743eed67faSmbalmer  if test -n "$dir_arg"; then
1753eed67faSmbalmer    dst=$src
1763eed67faSmbalmer    src=
1773eed67faSmbalmer
1783eed67faSmbalmer    if test -d "$dst"; then
1793eed67faSmbalmer      mkdircmd=:
1803eed67faSmbalmer      chmodcmd=
1813eed67faSmbalmer    else
1823eed67faSmbalmer      mkdircmd=$mkdirprog
1833eed67faSmbalmer    fi
1843eed67faSmbalmer  else
1853eed67faSmbalmer    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
1863eed67faSmbalmer    # might cause directories to be created, which would be especially bad
1873eed67faSmbalmer    # if $src (and thus $dsttmp) contains '*'.
1883eed67faSmbalmer    if test ! -f "$src" && test ! -d "$src"; then
1893eed67faSmbalmer      echo "$0: $src does not exist." >&2
1903eed67faSmbalmer      exit 1
1913eed67faSmbalmer    fi
1923eed67faSmbalmer
1933eed67faSmbalmer    if test -z "$dstarg"; then
1943eed67faSmbalmer      echo "$0: no destination specified." >&2
1953eed67faSmbalmer      exit 1
1963eed67faSmbalmer    fi
1973eed67faSmbalmer
1983eed67faSmbalmer    dst=$dstarg
1993eed67faSmbalmer    # Protect names starting with `-'.
2003eed67faSmbalmer    case $dst in
2013eed67faSmbalmer      -*) dst=./$dst ;;
2023eed67faSmbalmer    esac
2033eed67faSmbalmer
2043eed67faSmbalmer    # If destination is a directory, append the input filename; won't work
2053eed67faSmbalmer    # if double slashes aren't ignored.
2063eed67faSmbalmer    if test -d "$dst"; then
2073eed67faSmbalmer      if test -n "$no_target_directory"; then
2083eed67faSmbalmer	echo "$0: $dstarg: Is a directory" >&2
2093eed67faSmbalmer	exit 1
2103eed67faSmbalmer      fi
2113eed67faSmbalmer      dst=$dst/`basename "$src"`
2123eed67faSmbalmer    fi
2133eed67faSmbalmer  fi
2143eed67faSmbalmer
2153eed67faSmbalmer  # This sed command emulates the dirname command.
2163eed67faSmbalmer  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
2173eed67faSmbalmer
2183eed67faSmbalmer  # Make sure that the destination directory exists.
2193eed67faSmbalmer
2203eed67faSmbalmer  # Skip lots of stat calls in the usual case.
2213eed67faSmbalmer  if test ! -d "$dstdir"; then
2223eed67faSmbalmer    defaultIFS='
2233eed67faSmbalmer	 '
2243eed67faSmbalmer    IFS="${IFS-$defaultIFS}"
2253eed67faSmbalmer
2263eed67faSmbalmer    oIFS=$IFS
2273eed67faSmbalmer    # Some sh's can't handle IFS=/ for some reason.
2283eed67faSmbalmer    IFS='%'
2293eed67faSmbalmer    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
2303eed67faSmbalmer    shift
2313eed67faSmbalmer    IFS=$oIFS
2323eed67faSmbalmer
2333eed67faSmbalmer    pathcomp=
2343eed67faSmbalmer
2353eed67faSmbalmer    while test $# -ne 0 ; do
2363eed67faSmbalmer      pathcomp=$pathcomp$1
2373eed67faSmbalmer      shift
2383eed67faSmbalmer      if test ! -d "$pathcomp"; then
2393eed67faSmbalmer        $mkdirprog "$pathcomp"
2403eed67faSmbalmer	# mkdir can fail with a `File exist' error in case several
2413eed67faSmbalmer	# install-sh are creating the directory concurrently.  This
2423eed67faSmbalmer	# is OK.
2433eed67faSmbalmer	test -d "$pathcomp" || exit
2443eed67faSmbalmer      fi
2453eed67faSmbalmer      pathcomp=$pathcomp/
2463eed67faSmbalmer    done
2473eed67faSmbalmer  fi
2483eed67faSmbalmer
2493eed67faSmbalmer  if test -n "$dir_arg"; then
2503eed67faSmbalmer    $doit $mkdircmd "$dst" \
2513eed67faSmbalmer      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
2523eed67faSmbalmer      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
2533eed67faSmbalmer      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
2543eed67faSmbalmer      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
2553eed67faSmbalmer
2563eed67faSmbalmer  else
2573eed67faSmbalmer    dstfile=`basename "$dst"`
2583eed67faSmbalmer
2593eed67faSmbalmer    # Make a couple of temp file names in the proper directory.
2603eed67faSmbalmer    dsttmp=$dstdir/_inst.$$_
2613eed67faSmbalmer    rmtmp=$dstdir/_rm.$$_
2623eed67faSmbalmer
2633eed67faSmbalmer    # Trap to clean up those temp files at exit.
2643eed67faSmbalmer    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
2653eed67faSmbalmer    trap '(exit $?); exit' 1 2 13 15
2663eed67faSmbalmer
2673eed67faSmbalmer    # Copy the file name to the temp name.
2683eed67faSmbalmer    $doit $cpprog "$src" "$dsttmp" &&
2693eed67faSmbalmer
2703eed67faSmbalmer    # and set any options; do chmod last to preserve setuid bits.
2713eed67faSmbalmer    #
2723eed67faSmbalmer    # If any of these fail, we abort the whole thing.  If we want to
2733eed67faSmbalmer    # ignore errors from any of these, just make sure not to ignore
2743eed67faSmbalmer    # errors from the above "$doit $cpprog $src $dsttmp" command.
2753eed67faSmbalmer    #
2763eed67faSmbalmer    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
2773eed67faSmbalmer      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
2783eed67faSmbalmer      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
2793eed67faSmbalmer      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
2803eed67faSmbalmer
2813eed67faSmbalmer    # Now rename the file to the real destination.
2823eed67faSmbalmer    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
2833eed67faSmbalmer      || {
2843eed67faSmbalmer	   # The rename failed, perhaps because mv can't rename something else
2853eed67faSmbalmer	   # to itself, or perhaps because mv is so ancient that it does not
2863eed67faSmbalmer	   # support -f.
2873eed67faSmbalmer
2883eed67faSmbalmer	   # Now remove or move aside any old file at destination location.
2893eed67faSmbalmer	   # We try this two ways since rm can't unlink itself on some
2903eed67faSmbalmer	   # systems and the destination file might be busy for other
2913eed67faSmbalmer	   # reasons.  In this case, the final cleanup might fail but the new
2923eed67faSmbalmer	   # file should still install successfully.
2933eed67faSmbalmer	   {
2943eed67faSmbalmer	     if test -f "$dstdir/$dstfile"; then
2953eed67faSmbalmer	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
2963eed67faSmbalmer	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
2973eed67faSmbalmer	       || {
2983eed67faSmbalmer		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2993eed67faSmbalmer		 (exit 1); exit 1
3003eed67faSmbalmer	       }
3013eed67faSmbalmer	     else
3023eed67faSmbalmer	       :
3033eed67faSmbalmer	     fi
3043eed67faSmbalmer	   } &&
3053eed67faSmbalmer
3063eed67faSmbalmer	   # Now rename the file to the real destination.
3073eed67faSmbalmer	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
3083eed67faSmbalmer	 }
3093eed67faSmbalmer    }
3103eed67faSmbalmer  fi || { (exit 1); exit 1; }
3113eed67faSmbalmerdone
3123eed67faSmbalmer
3133eed67faSmbalmer# The final little trick to "correctly" pass the exit status to the exit trap.
3143eed67faSmbalmer{
3153eed67faSmbalmer  (exit 0); exit 0
3163eed67faSmbalmer}
3173eed67faSmbalmer
3183eed67faSmbalmer# Local variables:
3193eed67faSmbalmer# eval: (add-hook 'write-file-hooks 'time-stamp)
3203eed67faSmbalmer# time-stamp-start: "scriptversion="
3213eed67faSmbalmer# time-stamp-format: "%:y-%02m-%02d.%02H"
3223eed67faSmbalmer# time-stamp-end: "$"
3233eed67faSmbalmer# End:
324