install-sh revision 16fd1166
16df26cacSmrg#!/bin/sh
26df26cacSmrg# install - install a program, script, or datafile
36df26cacSmrg
416fd1166Smrgscriptversion=2005-05-14.22
56df26cacSmrg
66df26cacSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
76df26cacSmrg# later released in X11R6 (xc/config/util/install.sh) with the
86df26cacSmrg# following copyright and license.
96df26cacSmrg#
106df26cacSmrg# Copyright (C) 1994 X Consortium
116df26cacSmrg#
126df26cacSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
136df26cacSmrg# of this software and associated documentation files (the "Software"), to
146df26cacSmrg# deal in the Software without restriction, including without limitation the
156df26cacSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
166df26cacSmrg# sell copies of the Software, and to permit persons to whom the Software is
176df26cacSmrg# furnished to do so, subject to the following conditions:
186df26cacSmrg#
196df26cacSmrg# The above copyright notice and this permission notice shall be included in
206df26cacSmrg# all copies or substantial portions of the Software.
216df26cacSmrg#
226df26cacSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
236df26cacSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
246df26cacSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
256df26cacSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
266df26cacSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
276df26cacSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
286df26cacSmrg#
296df26cacSmrg# Except as contained in this notice, the name of the X Consortium shall not
306df26cacSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
316df26cacSmrg# ings in this Software without prior written authorization from the X Consor-
326df26cacSmrg# tium.
336df26cacSmrg#
346df26cacSmrg#
356df26cacSmrg# FSF changes to this file are in the public domain.
366df26cacSmrg#
376df26cacSmrg# Calling this script install-sh is preferred over install.sh, to prevent
386df26cacSmrg# `make' implicit rules from creating a file called install from it
396df26cacSmrg# when there is no Makefile.
406df26cacSmrg#
416df26cacSmrg# This script is compatible with the BSD install script, but was written
4216fd1166Smrg# from scratch.  It can only install one file at a time, a restriction
4316fd1166Smrg# shared with many OS's install programs.
446df26cacSmrg
456df26cacSmrg# set DOITPROG to echo to test this script
466df26cacSmrg
476df26cacSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
486df26cacSmrgdoit="${DOITPROG-}"
496df26cacSmrg
5016fd1166Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
516df26cacSmrg
526df26cacSmrgmvprog="${MVPROG-mv}"
536df26cacSmrgcpprog="${CPPROG-cp}"
546df26cacSmrgchmodprog="${CHMODPROG-chmod}"
556df26cacSmrgchownprog="${CHOWNPROG-chown}"
566df26cacSmrgchgrpprog="${CHGRPPROG-chgrp}"
576df26cacSmrgstripprog="${STRIPPROG-strip}"
586df26cacSmrgrmprog="${RMPROG-rm}"
596df26cacSmrgmkdirprog="${MKDIRPROG-mkdir}"
606df26cacSmrg
6116fd1166Smrgchmodcmd="$chmodprog 0755"
626df26cacSmrgchowncmd=
636df26cacSmrgchgrpcmd=
646df26cacSmrgstripcmd=
656df26cacSmrgrmcmd="$rmprog -f"
666df26cacSmrgmvcmd="$mvprog"
676df26cacSmrgsrc=
686df26cacSmrgdst=
696df26cacSmrgdir_arg=
706df26cacSmrgdstarg=
716df26cacSmrgno_target_directory=
726df26cacSmrg
736df26cacSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
746df26cacSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
756df26cacSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
766df26cacSmrg   or: $0 [OPTION]... -d DIRECTORIES...
776df26cacSmrg
786df26cacSmrgIn the 1st form, copy SRCFILE to DSTFILE.
796df26cacSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
806df26cacSmrgIn the 4th, create DIRECTORIES.
816df26cacSmrg
826df26cacSmrgOptions:
836df26cacSmrg-c         (ignored)
846df26cacSmrg-d         create directories instead of installing files.
856df26cacSmrg-g GROUP   $chgrpprog installed files to GROUP.
866df26cacSmrg-m MODE    $chmodprog installed files to MODE.
876df26cacSmrg-o USER    $chownprog installed files to USER.
886df26cacSmrg-s         $stripprog installed files.
896df26cacSmrg-t DIRECTORY  install into DIRECTORY.
906df26cacSmrg-T         report an error if DSTFILE is a directory.
916df26cacSmrg--help     display this help and exit.
926df26cacSmrg--version  display version info and exit.
936df26cacSmrg
946df26cacSmrgEnvironment variables override the default commands:
956df26cacSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
966df26cacSmrg"
976df26cacSmrg
9816fd1166Smrgwhile test -n "$1"; do
996df26cacSmrg  case $1 in
1006df26cacSmrg    -c) shift
1016df26cacSmrg        continue;;
1026df26cacSmrg
1036df26cacSmrg    -d) dir_arg=true
1046df26cacSmrg        shift
1056df26cacSmrg        continue;;
1066df26cacSmrg
1076df26cacSmrg    -g) chgrpcmd="$chgrpprog $2"
1086df26cacSmrg        shift
1096df26cacSmrg        shift
1106df26cacSmrg        continue;;
1116df26cacSmrg
1126df26cacSmrg    --help) echo "$usage"; exit $?;;
1136df26cacSmrg
11416fd1166Smrg    -m) chmodcmd="$chmodprog $2"
1156df26cacSmrg        shift
1166df26cacSmrg        shift
1176df26cacSmrg        continue;;
1186df26cacSmrg
1196df26cacSmrg    -o) chowncmd="$chownprog $2"
1206df26cacSmrg        shift
1216df26cacSmrg        shift
1226df26cacSmrg        continue;;
1236df26cacSmrg
1246df26cacSmrg    -s) stripcmd=$stripprog
1256df26cacSmrg        shift
1266df26cacSmrg        continue;;
1276df26cacSmrg
1286df26cacSmrg    -t) dstarg=$2
1296df26cacSmrg	shift
1306df26cacSmrg	shift
1316df26cacSmrg	continue;;
1326df26cacSmrg
1336df26cacSmrg    -T) no_target_directory=true
1346df26cacSmrg	shift
1356df26cacSmrg	continue;;
1366df26cacSmrg
1376df26cacSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1386df26cacSmrg
13916fd1166Smrg    *)  # When -d is used, all remaining arguments are directories to create.
14016fd1166Smrg	# When -t is used, the destination is already specified.
14116fd1166Smrg	test -n "$dir_arg$dstarg" && break
14216fd1166Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14316fd1166Smrg	for arg
14416fd1166Smrg	do
14516fd1166Smrg          if test -n "$dstarg"; then
14616fd1166Smrg	    # $@ is not empty: it contains at least $arg.
14716fd1166Smrg	    set fnord "$@" "$dstarg"
14816fd1166Smrg	    shift # fnord
14916fd1166Smrg	  fi
15016fd1166Smrg	  shift # arg
15116fd1166Smrg	  dstarg=$arg
15216fd1166Smrg	done
1536df26cacSmrg	break;;
1546df26cacSmrg  esac
1556df26cacSmrgdone
1566df26cacSmrg
15716fd1166Smrgif test -z "$1"; then
1586df26cacSmrg  if test -z "$dir_arg"; then
1596df26cacSmrg    echo "$0: no input file specified." >&2
1606df26cacSmrg    exit 1
1616df26cacSmrg  fi
1626df26cacSmrg  # It's OK to call `install-sh -d' without argument.
1636df26cacSmrg  # This can happen when creating conditional directories.
1646df26cacSmrg  exit 0
1656df26cacSmrgfi
1666df26cacSmrg
1676df26cacSmrgfor src
1686df26cacSmrgdo
1696df26cacSmrg  # Protect names starting with `-'.
1706df26cacSmrg  case $src in
1716df26cacSmrg    -*) src=./$src ;;
1726df26cacSmrg  esac
1736df26cacSmrg
1746df26cacSmrg  if test -n "$dir_arg"; then
1756df26cacSmrg    dst=$src
17616fd1166Smrg    src=
1776df26cacSmrg
17816fd1166Smrg    if test -d "$dst"; then
17916fd1166Smrg      mkdircmd=:
18016fd1166Smrg      chmodcmd=
18116fd1166Smrg    else
18216fd1166Smrg      mkdircmd=$mkdirprog
18316fd1166Smrg    fi
18416fd1166Smrg  else
1856df26cacSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
1866df26cacSmrg    # might cause directories to be created, which would be especially bad
1876df26cacSmrg    # if $src (and thus $dsttmp) contains '*'.
1886df26cacSmrg    if test ! -f "$src" && test ! -d "$src"; then
1896df26cacSmrg      echo "$0: $src does not exist." >&2
1906df26cacSmrg      exit 1
1916df26cacSmrg    fi
1926df26cacSmrg
1936df26cacSmrg    if test -z "$dstarg"; then
1946df26cacSmrg      echo "$0: no destination specified." >&2
1956df26cacSmrg      exit 1
1966df26cacSmrg    fi
1976df26cacSmrg
1986df26cacSmrg    dst=$dstarg
1996df26cacSmrg    # Protect names starting with `-'.
2006df26cacSmrg    case $dst in
2016df26cacSmrg      -*) dst=./$dst ;;
2026df26cacSmrg    esac
2036df26cacSmrg
2046df26cacSmrg    # If destination is a directory, append the input filename; won't work
2056df26cacSmrg    # if double slashes aren't ignored.
2066df26cacSmrg    if test -d "$dst"; then
2076df26cacSmrg      if test -n "$no_target_directory"; then
2086df26cacSmrg	echo "$0: $dstarg: Is a directory" >&2
2096df26cacSmrg	exit 1
2106df26cacSmrg      fi
21116fd1166Smrg      dst=$dst/`basename "$src"`
2126df26cacSmrg    fi
2136df26cacSmrg  fi
2146df26cacSmrg
21516fd1166Smrg  # This sed command emulates the dirname command.
21616fd1166Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
2176df26cacSmrg
21816fd1166Smrg  # Make sure that the destination directory exists.
21916fd1166Smrg
22016fd1166Smrg  # Skip lots of stat calls in the usual case.
22116fd1166Smrg  if test ! -d "$dstdir"; then
22216fd1166Smrg    defaultIFS='
22316fd1166Smrg	 '
22416fd1166Smrg    IFS="${IFS-$defaultIFS}"
2256df26cacSmrg
22616fd1166Smrg    oIFS=$IFS
22716fd1166Smrg    # Some sh's can't handle IFS=/ for some reason.
22816fd1166Smrg    IFS='%'
22916fd1166Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23016fd1166Smrg    shift
23116fd1166Smrg    IFS=$oIFS
23216fd1166Smrg
23316fd1166Smrg    pathcomp=
23416fd1166Smrg
23516fd1166Smrg    while test $# -ne 0 ; do
23616fd1166Smrg      pathcomp=$pathcomp$1
2376df26cacSmrg      shift
23816fd1166Smrg      if test ! -d "$pathcomp"; then
23916fd1166Smrg        $mkdirprog "$pathcomp"
24016fd1166Smrg	# mkdir can fail with a `File exist' error in case several
24116fd1166Smrg	# install-sh are creating the directory concurrently.  This
24216fd1166Smrg	# is OK.
24316fd1166Smrg	test -d "$pathcomp" || exit
2446df26cacSmrg      fi
24516fd1166Smrg      pathcomp=$pathcomp/
24616fd1166Smrg    done
2476df26cacSmrg  fi
2486df26cacSmrg
2496df26cacSmrg  if test -n "$dir_arg"; then
25016fd1166Smrg    $doit $mkdircmd "$dst" \
25116fd1166Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25216fd1166Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25316fd1166Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25416fd1166Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25516fd1166Smrg
2566df26cacSmrg  else
25716fd1166Smrg    dstfile=`basename "$dst"`
2586df26cacSmrg
2596df26cacSmrg    # Make a couple of temp file names in the proper directory.
2606df26cacSmrg    dsttmp=$dstdir/_inst.$$_
2616df26cacSmrg    rmtmp=$dstdir/_rm.$$_
2626df26cacSmrg
2636df26cacSmrg    # Trap to clean up those temp files at exit.
2646df26cacSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26516fd1166Smrg    trap '(exit $?); exit' 1 2 13 15
2666df26cacSmrg
2676df26cacSmrg    # Copy the file name to the temp name.
26816fd1166Smrg    $doit $cpprog "$src" "$dsttmp" &&
2696df26cacSmrg
2706df26cacSmrg    # and set any options; do chmod last to preserve setuid bits.
2716df26cacSmrg    #
2726df26cacSmrg    # If any of these fail, we abort the whole thing.  If we want to
2736df26cacSmrg    # ignore errors from any of these, just make sure not to ignore
2746df26cacSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
2756df26cacSmrg    #
2766df26cacSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
2776df26cacSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
2786df26cacSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27916fd1166Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
2806df26cacSmrg
2816df26cacSmrg    # Now rename the file to the real destination.
28216fd1166Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
2836df26cacSmrg      || {
2846df26cacSmrg	   # The rename failed, perhaps because mv can't rename something else
2856df26cacSmrg	   # to itself, or perhaps because mv is so ancient that it does not
2866df26cacSmrg	   # support -f.
2876df26cacSmrg
2886df26cacSmrg	   # Now remove or move aside any old file at destination location.
2896df26cacSmrg	   # We try this two ways since rm can't unlink itself on some
2906df26cacSmrg	   # systems and the destination file might be busy for other
2916df26cacSmrg	   # reasons.  In this case, the final cleanup might fail but the new
2926df26cacSmrg	   # file should still install successfully.
2936df26cacSmrg	   {
29416fd1166Smrg	     if test -f "$dstdir/$dstfile"; then
29516fd1166Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29616fd1166Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
2976df26cacSmrg	       || {
29816fd1166Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2996df26cacSmrg		 (exit 1); exit 1
3006df26cacSmrg	       }
3016df26cacSmrg	     else
3026df26cacSmrg	       :
3036df26cacSmrg	     fi
3046df26cacSmrg	   } &&
3056df26cacSmrg
3066df26cacSmrg	   # Now rename the file to the real destination.
30716fd1166Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
3086df26cacSmrg	 }
30916fd1166Smrg    }
31016fd1166Smrg  fi || { (exit 1); exit 1; }
3116df26cacSmrgdone
3126df26cacSmrg
31316fd1166Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
31416fd1166Smrg{
31516fd1166Smrg  (exit 0); exit 0
31616fd1166Smrg}
31716fd1166Smrg
3186df26cacSmrg# Local variables:
3196df26cacSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
3206df26cacSmrg# time-stamp-start: "scriptversion="
3216df26cacSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
3226df26cacSmrg# time-stamp-end: "$"
3236df26cacSmrg# End:
324