171d7fec4Smrg#!/bin/sh
271d7fec4Smrg# install - install a program, script, or datafile
371d7fec4Smrg
471d7fec4Smrgscriptversion=2005-05-14.22
571d7fec4Smrg
671d7fec4Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
771d7fec4Smrg# later released in X11R6 (xc/config/util/install.sh) with the
871d7fec4Smrg# following copyright and license.
971d7fec4Smrg#
1071d7fec4Smrg# Copyright (C) 1994 X Consortium
1171d7fec4Smrg#
1271d7fec4Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1371d7fec4Smrg# of this software and associated documentation files (the "Software"), to
1471d7fec4Smrg# deal in the Software without restriction, including without limitation the
1571d7fec4Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1671d7fec4Smrg# sell copies of the Software, and to permit persons to whom the Software is
1771d7fec4Smrg# furnished to do so, subject to the following conditions:
1871d7fec4Smrg#
1971d7fec4Smrg# The above copyright notice and this permission notice shall be included in
2071d7fec4Smrg# all copies or substantial portions of the Software.
2171d7fec4Smrg#
2271d7fec4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2371d7fec4Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2471d7fec4Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2571d7fec4Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2671d7fec4Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2771d7fec4Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2871d7fec4Smrg#
2971d7fec4Smrg# Except as contained in this notice, the name of the X Consortium shall not
3071d7fec4Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3171d7fec4Smrg# ings in this Software without prior written authorization from the X Consor-
3271d7fec4Smrg# tium.
3371d7fec4Smrg#
3471d7fec4Smrg#
3571d7fec4Smrg# FSF changes to this file are in the public domain.
3671d7fec4Smrg#
3771d7fec4Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3871d7fec4Smrg# `make' implicit rules from creating a file called install from it
3971d7fec4Smrg# when there is no Makefile.
4071d7fec4Smrg#
4171d7fec4Smrg# This script is compatible with the BSD install script, but was written
4271d7fec4Smrg# from scratch.  It can only install one file at a time, a restriction
4371d7fec4Smrg# shared with many OS's install programs.
4471d7fec4Smrg
4571d7fec4Smrg# set DOITPROG to echo to test this script
4671d7fec4Smrg
4771d7fec4Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4871d7fec4Smrgdoit="${DOITPROG-}"
4971d7fec4Smrg
5071d7fec4Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
5171d7fec4Smrg
5271d7fec4Smrgmvprog="${MVPROG-mv}"
5371d7fec4Smrgcpprog="${CPPROG-cp}"
5471d7fec4Smrgchmodprog="${CHMODPROG-chmod}"
5571d7fec4Smrgchownprog="${CHOWNPROG-chown}"
5671d7fec4Smrgchgrpprog="${CHGRPPROG-chgrp}"
5771d7fec4Smrgstripprog="${STRIPPROG-strip}"
5871d7fec4Smrgrmprog="${RMPROG-rm}"
5971d7fec4Smrgmkdirprog="${MKDIRPROG-mkdir}"
6071d7fec4Smrg
6171d7fec4Smrgchmodcmd="$chmodprog 0755"
6271d7fec4Smrgchowncmd=
6371d7fec4Smrgchgrpcmd=
6471d7fec4Smrgstripcmd=
6571d7fec4Smrgrmcmd="$rmprog -f"
6671d7fec4Smrgmvcmd="$mvprog"
6771d7fec4Smrgsrc=
6871d7fec4Smrgdst=
6971d7fec4Smrgdir_arg=
7071d7fec4Smrgdstarg=
7171d7fec4Smrgno_target_directory=
7271d7fec4Smrg
7371d7fec4Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7471d7fec4Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7571d7fec4Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7671d7fec4Smrg   or: $0 [OPTION]... -d DIRECTORIES...
7771d7fec4Smrg
7871d7fec4SmrgIn the 1st form, copy SRCFILE to DSTFILE.
7971d7fec4SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8071d7fec4SmrgIn the 4th, create DIRECTORIES.
8171d7fec4Smrg
8271d7fec4SmrgOptions:
8371d7fec4Smrg-c         (ignored)
8471d7fec4Smrg-d         create directories instead of installing files.
8571d7fec4Smrg-g GROUP   $chgrpprog installed files to GROUP.
8671d7fec4Smrg-m MODE    $chmodprog installed files to MODE.
8771d7fec4Smrg-o USER    $chownprog installed files to USER.
8871d7fec4Smrg-s         $stripprog installed files.
8971d7fec4Smrg-t DIRECTORY  install into DIRECTORY.
9071d7fec4Smrg-T         report an error if DSTFILE is a directory.
9171d7fec4Smrg--help     display this help and exit.
9271d7fec4Smrg--version  display version info and exit.
9371d7fec4Smrg
9471d7fec4SmrgEnvironment variables override the default commands:
9571d7fec4Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9671d7fec4Smrg"
9771d7fec4Smrg
9871d7fec4Smrgwhile test -n "$1"; do
9971d7fec4Smrg  case $1 in
10071d7fec4Smrg    -c) shift
10171d7fec4Smrg        continue;;
10271d7fec4Smrg
10371d7fec4Smrg    -d) dir_arg=true
10471d7fec4Smrg        shift
10571d7fec4Smrg        continue;;
10671d7fec4Smrg
10771d7fec4Smrg    -g) chgrpcmd="$chgrpprog $2"
10871d7fec4Smrg        shift
10971d7fec4Smrg        shift
11071d7fec4Smrg        continue;;
11171d7fec4Smrg
11271d7fec4Smrg    --help) echo "$usage"; exit $?;;
11371d7fec4Smrg
11471d7fec4Smrg    -m) chmodcmd="$chmodprog $2"
11571d7fec4Smrg        shift
11671d7fec4Smrg        shift
11771d7fec4Smrg        continue;;
11871d7fec4Smrg
11971d7fec4Smrg    -o) chowncmd="$chownprog $2"
12071d7fec4Smrg        shift
12171d7fec4Smrg        shift
12271d7fec4Smrg        continue;;
12371d7fec4Smrg
12471d7fec4Smrg    -s) stripcmd=$stripprog
12571d7fec4Smrg        shift
12671d7fec4Smrg        continue;;
12771d7fec4Smrg
12871d7fec4Smrg    -t) dstarg=$2
12971d7fec4Smrg	shift
13071d7fec4Smrg	shift
13171d7fec4Smrg	continue;;
13271d7fec4Smrg
13371d7fec4Smrg    -T) no_target_directory=true
13471d7fec4Smrg	shift
13571d7fec4Smrg	continue;;
13671d7fec4Smrg
13771d7fec4Smrg    --version) echo "$0 $scriptversion"; exit $?;;
13871d7fec4Smrg
13971d7fec4Smrg    *)  # When -d is used, all remaining arguments are directories to create.
14071d7fec4Smrg	# When -t is used, the destination is already specified.
14171d7fec4Smrg	test -n "$dir_arg$dstarg" && break
14271d7fec4Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14371d7fec4Smrg	for arg
14471d7fec4Smrg	do
14571d7fec4Smrg          if test -n "$dstarg"; then
14671d7fec4Smrg	    # $@ is not empty: it contains at least $arg.
14771d7fec4Smrg	    set fnord "$@" "$dstarg"
14871d7fec4Smrg	    shift # fnord
14971d7fec4Smrg	  fi
15071d7fec4Smrg	  shift # arg
15171d7fec4Smrg	  dstarg=$arg
15271d7fec4Smrg	done
15371d7fec4Smrg	break;;
15471d7fec4Smrg  esac
15571d7fec4Smrgdone
15671d7fec4Smrg
15771d7fec4Smrgif test -z "$1"; then
15871d7fec4Smrg  if test -z "$dir_arg"; then
15971d7fec4Smrg    echo "$0: no input file specified." >&2
16071d7fec4Smrg    exit 1
16171d7fec4Smrg  fi
16271d7fec4Smrg  # It's OK to call `install-sh -d' without argument.
16371d7fec4Smrg  # This can happen when creating conditional directories.
16471d7fec4Smrg  exit 0
16571d7fec4Smrgfi
16671d7fec4Smrg
16771d7fec4Smrgfor src
16871d7fec4Smrgdo
16971d7fec4Smrg  # Protect names starting with `-'.
17071d7fec4Smrg  case $src in
17171d7fec4Smrg    -*) src=./$src ;;
17271d7fec4Smrg  esac
17371d7fec4Smrg
17471d7fec4Smrg  if test -n "$dir_arg"; then
17571d7fec4Smrg    dst=$src
17671d7fec4Smrg    src=
17771d7fec4Smrg
17871d7fec4Smrg    if test -d "$dst"; then
17971d7fec4Smrg      mkdircmd=:
18071d7fec4Smrg      chmodcmd=
18171d7fec4Smrg    else
18271d7fec4Smrg      mkdircmd=$mkdirprog
18371d7fec4Smrg    fi
18471d7fec4Smrg  else
18571d7fec4Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18671d7fec4Smrg    # might cause directories to be created, which would be especially bad
18771d7fec4Smrg    # if $src (and thus $dsttmp) contains '*'.
18871d7fec4Smrg    if test ! -f "$src" && test ! -d "$src"; then
18971d7fec4Smrg      echo "$0: $src does not exist." >&2
19071d7fec4Smrg      exit 1
19171d7fec4Smrg    fi
19271d7fec4Smrg
19371d7fec4Smrg    if test -z "$dstarg"; then
19471d7fec4Smrg      echo "$0: no destination specified." >&2
19571d7fec4Smrg      exit 1
19671d7fec4Smrg    fi
19771d7fec4Smrg
19871d7fec4Smrg    dst=$dstarg
19971d7fec4Smrg    # Protect names starting with `-'.
20071d7fec4Smrg    case $dst in
20171d7fec4Smrg      -*) dst=./$dst ;;
20271d7fec4Smrg    esac
20371d7fec4Smrg
20471d7fec4Smrg    # If destination is a directory, append the input filename; won't work
20571d7fec4Smrg    # if double slashes aren't ignored.
20671d7fec4Smrg    if test -d "$dst"; then
20771d7fec4Smrg      if test -n "$no_target_directory"; then
20871d7fec4Smrg	echo "$0: $dstarg: Is a directory" >&2
20971d7fec4Smrg	exit 1
21071d7fec4Smrg      fi
21171d7fec4Smrg      dst=$dst/`basename "$src"`
21271d7fec4Smrg    fi
21371d7fec4Smrg  fi
21471d7fec4Smrg
21571d7fec4Smrg  # This sed command emulates the dirname command.
21671d7fec4Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21771d7fec4Smrg
21871d7fec4Smrg  # Make sure that the destination directory exists.
21971d7fec4Smrg
22071d7fec4Smrg  # Skip lots of stat calls in the usual case.
22171d7fec4Smrg  if test ! -d "$dstdir"; then
22271d7fec4Smrg    defaultIFS='
22371d7fec4Smrg	 '
22471d7fec4Smrg    IFS="${IFS-$defaultIFS}"
22571d7fec4Smrg
22671d7fec4Smrg    oIFS=$IFS
22771d7fec4Smrg    # Some sh's can't handle IFS=/ for some reason.
22871d7fec4Smrg    IFS='%'
22971d7fec4Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23071d7fec4Smrg    shift
23171d7fec4Smrg    IFS=$oIFS
23271d7fec4Smrg
23371d7fec4Smrg    pathcomp=
23471d7fec4Smrg
23571d7fec4Smrg    while test $# -ne 0 ; do
23671d7fec4Smrg      pathcomp=$pathcomp$1
23771d7fec4Smrg      shift
23871d7fec4Smrg      if test ! -d "$pathcomp"; then
23971d7fec4Smrg        $mkdirprog "$pathcomp"
24071d7fec4Smrg	# mkdir can fail with a `File exist' error in case several
24171d7fec4Smrg	# install-sh are creating the directory concurrently.  This
24271d7fec4Smrg	# is OK.
24371d7fec4Smrg	test -d "$pathcomp" || exit
24471d7fec4Smrg      fi
24571d7fec4Smrg      pathcomp=$pathcomp/
24671d7fec4Smrg    done
24771d7fec4Smrg  fi
24871d7fec4Smrg
24971d7fec4Smrg  if test -n "$dir_arg"; then
25071d7fec4Smrg    $doit $mkdircmd "$dst" \
25171d7fec4Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25271d7fec4Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25371d7fec4Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25471d7fec4Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25571d7fec4Smrg
25671d7fec4Smrg  else
25771d7fec4Smrg    dstfile=`basename "$dst"`
25871d7fec4Smrg
25971d7fec4Smrg    # Make a couple of temp file names in the proper directory.
26071d7fec4Smrg    dsttmp=$dstdir/_inst.$$_
26171d7fec4Smrg    rmtmp=$dstdir/_rm.$$_
26271d7fec4Smrg
26371d7fec4Smrg    # Trap to clean up those temp files at exit.
26471d7fec4Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26571d7fec4Smrg    trap '(exit $?); exit' 1 2 13 15
26671d7fec4Smrg
26771d7fec4Smrg    # Copy the file name to the temp name.
26871d7fec4Smrg    $doit $cpprog "$src" "$dsttmp" &&
26971d7fec4Smrg
27071d7fec4Smrg    # and set any options; do chmod last to preserve setuid bits.
27171d7fec4Smrg    #
27271d7fec4Smrg    # If any of these fail, we abort the whole thing.  If we want to
27371d7fec4Smrg    # ignore errors from any of these, just make sure not to ignore
27471d7fec4Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27571d7fec4Smrg    #
27671d7fec4Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27771d7fec4Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27871d7fec4Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27971d7fec4Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28071d7fec4Smrg
28171d7fec4Smrg    # Now rename the file to the real destination.
28271d7fec4Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28371d7fec4Smrg      || {
28471d7fec4Smrg	   # The rename failed, perhaps because mv can't rename something else
28571d7fec4Smrg	   # to itself, or perhaps because mv is so ancient that it does not
28671d7fec4Smrg	   # support -f.
28771d7fec4Smrg
28871d7fec4Smrg	   # Now remove or move aside any old file at destination location.
28971d7fec4Smrg	   # We try this two ways since rm can't unlink itself on some
29071d7fec4Smrg	   # systems and the destination file might be busy for other
29171d7fec4Smrg	   # reasons.  In this case, the final cleanup might fail but the new
29271d7fec4Smrg	   # file should still install successfully.
29371d7fec4Smrg	   {
29471d7fec4Smrg	     if test -f "$dstdir/$dstfile"; then
29571d7fec4Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29671d7fec4Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29771d7fec4Smrg	       || {
29871d7fec4Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29971d7fec4Smrg		 (exit 1); exit 1
30071d7fec4Smrg	       }
30171d7fec4Smrg	     else
30271d7fec4Smrg	       :
30371d7fec4Smrg	     fi
30471d7fec4Smrg	   } &&
30571d7fec4Smrg
30671d7fec4Smrg	   # Now rename the file to the real destination.
30771d7fec4Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30871d7fec4Smrg	 }
30971d7fec4Smrg    }
31071d7fec4Smrg  fi || { (exit 1); exit 1; }
31171d7fec4Smrgdone
31271d7fec4Smrg
31371d7fec4Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
31471d7fec4Smrg{
31571d7fec4Smrg  (exit 0); exit 0
31671d7fec4Smrg}
31771d7fec4Smrg
31871d7fec4Smrg# Local variables:
31971d7fec4Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32071d7fec4Smrg# time-stamp-start: "scriptversion="
32171d7fec4Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32271d7fec4Smrg# time-stamp-end: "$"
32371d7fec4Smrg# End:
324