install-sh revision 11d341ca
111d341caSmrg#!/bin/sh
211d341caSmrg# install - install a program, script, or datafile
311d341caSmrg
411d341caSmrgscriptversion=2005-05-14.22
511d341caSmrg
611d341caSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
711d341caSmrg# later released in X11R6 (xc/config/util/install.sh) with the
811d341caSmrg# following copyright and license.
911d341caSmrg#
1011d341caSmrg# Copyright (C) 1994 X Consortium
1111d341caSmrg#
1211d341caSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1311d341caSmrg# of this software and associated documentation files (the "Software"), to
1411d341caSmrg# deal in the Software without restriction, including without limitation the
1511d341caSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1611d341caSmrg# sell copies of the Software, and to permit persons to whom the Software is
1711d341caSmrg# furnished to do so, subject to the following conditions:
1811d341caSmrg#
1911d341caSmrg# The above copyright notice and this permission notice shall be included in
2011d341caSmrg# all copies or substantial portions of the Software.
2111d341caSmrg#
2211d341caSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2311d341caSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2411d341caSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2511d341caSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2611d341caSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2711d341caSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2811d341caSmrg#
2911d341caSmrg# Except as contained in this notice, the name of the X Consortium shall not
3011d341caSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3111d341caSmrg# ings in this Software without prior written authorization from the X Consor-
3211d341caSmrg# tium.
3311d341caSmrg#
3411d341caSmrg#
3511d341caSmrg# FSF changes to this file are in the public domain.
3611d341caSmrg#
3711d341caSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3811d341caSmrg# `make' implicit rules from creating a file called install from it
3911d341caSmrg# when there is no Makefile.
4011d341caSmrg#
4111d341caSmrg# This script is compatible with the BSD install script, but was written
4211d341caSmrg# from scratch.  It can only install one file at a time, a restriction
4311d341caSmrg# shared with many OS's install programs.
4411d341caSmrg
4511d341caSmrg# set DOITPROG to echo to test this script
4611d341caSmrg
4711d341caSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4811d341caSmrgdoit="${DOITPROG-}"
4911d341caSmrg
5011d341caSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
5111d341caSmrg
5211d341caSmrgmvprog="${MVPROG-mv}"
5311d341caSmrgcpprog="${CPPROG-cp}"
5411d341caSmrgchmodprog="${CHMODPROG-chmod}"
5511d341caSmrgchownprog="${CHOWNPROG-chown}"
5611d341caSmrgchgrpprog="${CHGRPPROG-chgrp}"
5711d341caSmrgstripprog="${STRIPPROG-strip}"
5811d341caSmrgrmprog="${RMPROG-rm}"
5911d341caSmrgmkdirprog="${MKDIRPROG-mkdir}"
6011d341caSmrg
6111d341caSmrgchmodcmd="$chmodprog 0755"
6211d341caSmrgchowncmd=
6311d341caSmrgchgrpcmd=
6411d341caSmrgstripcmd=
6511d341caSmrgrmcmd="$rmprog -f"
6611d341caSmrgmvcmd="$mvprog"
6711d341caSmrgsrc=
6811d341caSmrgdst=
6911d341caSmrgdir_arg=
7011d341caSmrgdstarg=
7111d341caSmrgno_target_directory=
7211d341caSmrg
7311d341caSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7411d341caSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7511d341caSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7611d341caSmrg   or: $0 [OPTION]... -d DIRECTORIES...
7711d341caSmrg
7811d341caSmrgIn the 1st form, copy SRCFILE to DSTFILE.
7911d341caSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8011d341caSmrgIn the 4th, create DIRECTORIES.
8111d341caSmrg
8211d341caSmrgOptions:
8311d341caSmrg-c         (ignored)
8411d341caSmrg-d         create directories instead of installing files.
8511d341caSmrg-g GROUP   $chgrpprog installed files to GROUP.
8611d341caSmrg-m MODE    $chmodprog installed files to MODE.
8711d341caSmrg-o USER    $chownprog installed files to USER.
8811d341caSmrg-s         $stripprog installed files.
8911d341caSmrg-t DIRECTORY  install into DIRECTORY.
9011d341caSmrg-T         report an error if DSTFILE is a directory.
9111d341caSmrg--help     display this help and exit.
9211d341caSmrg--version  display version info and exit.
9311d341caSmrg
9411d341caSmrgEnvironment variables override the default commands:
9511d341caSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9611d341caSmrg"
9711d341caSmrg
9811d341caSmrgwhile test -n "$1"; do
9911d341caSmrg  case $1 in
10011d341caSmrg    -c) shift
10111d341caSmrg        continue;;
10211d341caSmrg
10311d341caSmrg    -d) dir_arg=true
10411d341caSmrg        shift
10511d341caSmrg        continue;;
10611d341caSmrg
10711d341caSmrg    -g) chgrpcmd="$chgrpprog $2"
10811d341caSmrg        shift
10911d341caSmrg        shift
11011d341caSmrg        continue;;
11111d341caSmrg
11211d341caSmrg    --help) echo "$usage"; exit $?;;
11311d341caSmrg
11411d341caSmrg    -m) chmodcmd="$chmodprog $2"
11511d341caSmrg        shift
11611d341caSmrg        shift
11711d341caSmrg        continue;;
11811d341caSmrg
11911d341caSmrg    -o) chowncmd="$chownprog $2"
12011d341caSmrg        shift
12111d341caSmrg        shift
12211d341caSmrg        continue;;
12311d341caSmrg
12411d341caSmrg    -s) stripcmd=$stripprog
12511d341caSmrg        shift
12611d341caSmrg        continue;;
12711d341caSmrg
12811d341caSmrg    -t) dstarg=$2
12911d341caSmrg	shift
13011d341caSmrg	shift
13111d341caSmrg	continue;;
13211d341caSmrg
13311d341caSmrg    -T) no_target_directory=true
13411d341caSmrg	shift
13511d341caSmrg	continue;;
13611d341caSmrg
13711d341caSmrg    --version) echo "$0 $scriptversion"; exit $?;;
13811d341caSmrg
13911d341caSmrg    *)  # When -d is used, all remaining arguments are directories to create.
14011d341caSmrg	# When -t is used, the destination is already specified.
14111d341caSmrg	test -n "$dir_arg$dstarg" && break
14211d341caSmrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14311d341caSmrg	for arg
14411d341caSmrg	do
14511d341caSmrg          if test -n "$dstarg"; then
14611d341caSmrg	    # $@ is not empty: it contains at least $arg.
14711d341caSmrg	    set fnord "$@" "$dstarg"
14811d341caSmrg	    shift # fnord
14911d341caSmrg	  fi
15011d341caSmrg	  shift # arg
15111d341caSmrg	  dstarg=$arg
15211d341caSmrg	done
15311d341caSmrg	break;;
15411d341caSmrg  esac
15511d341caSmrgdone
15611d341caSmrg
15711d341caSmrgif test -z "$1"; then
15811d341caSmrg  if test -z "$dir_arg"; then
15911d341caSmrg    echo "$0: no input file specified." >&2
16011d341caSmrg    exit 1
16111d341caSmrg  fi
16211d341caSmrg  # It's OK to call `install-sh -d' without argument.
16311d341caSmrg  # This can happen when creating conditional directories.
16411d341caSmrg  exit 0
16511d341caSmrgfi
16611d341caSmrg
16711d341caSmrgfor src
16811d341caSmrgdo
16911d341caSmrg  # Protect names starting with `-'.
17011d341caSmrg  case $src in
17111d341caSmrg    -*) src=./$src ;;
17211d341caSmrg  esac
17311d341caSmrg
17411d341caSmrg  if test -n "$dir_arg"; then
17511d341caSmrg    dst=$src
17611d341caSmrg    src=
17711d341caSmrg
17811d341caSmrg    if test -d "$dst"; then
17911d341caSmrg      mkdircmd=:
18011d341caSmrg      chmodcmd=
18111d341caSmrg    else
18211d341caSmrg      mkdircmd=$mkdirprog
18311d341caSmrg    fi
18411d341caSmrg  else
18511d341caSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18611d341caSmrg    # might cause directories to be created, which would be especially bad
18711d341caSmrg    # if $src (and thus $dsttmp) contains '*'.
18811d341caSmrg    if test ! -f "$src" && test ! -d "$src"; then
18911d341caSmrg      echo "$0: $src does not exist." >&2
19011d341caSmrg      exit 1
19111d341caSmrg    fi
19211d341caSmrg
19311d341caSmrg    if test -z "$dstarg"; then
19411d341caSmrg      echo "$0: no destination specified." >&2
19511d341caSmrg      exit 1
19611d341caSmrg    fi
19711d341caSmrg
19811d341caSmrg    dst=$dstarg
19911d341caSmrg    # Protect names starting with `-'.
20011d341caSmrg    case $dst in
20111d341caSmrg      -*) dst=./$dst ;;
20211d341caSmrg    esac
20311d341caSmrg
20411d341caSmrg    # If destination is a directory, append the input filename; won't work
20511d341caSmrg    # if double slashes aren't ignored.
20611d341caSmrg    if test -d "$dst"; then
20711d341caSmrg      if test -n "$no_target_directory"; then
20811d341caSmrg	echo "$0: $dstarg: Is a directory" >&2
20911d341caSmrg	exit 1
21011d341caSmrg      fi
21111d341caSmrg      dst=$dst/`basename "$src"`
21211d341caSmrg    fi
21311d341caSmrg  fi
21411d341caSmrg
21511d341caSmrg  # This sed command emulates the dirname command.
21611d341caSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21711d341caSmrg
21811d341caSmrg  # Make sure that the destination directory exists.
21911d341caSmrg
22011d341caSmrg  # Skip lots of stat calls in the usual case.
22111d341caSmrg  if test ! -d "$dstdir"; then
22211d341caSmrg    defaultIFS='
22311d341caSmrg	 '
22411d341caSmrg    IFS="${IFS-$defaultIFS}"
22511d341caSmrg
22611d341caSmrg    oIFS=$IFS
22711d341caSmrg    # Some sh's can't handle IFS=/ for some reason.
22811d341caSmrg    IFS='%'
22911d341caSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23011d341caSmrg    shift
23111d341caSmrg    IFS=$oIFS
23211d341caSmrg
23311d341caSmrg    pathcomp=
23411d341caSmrg
23511d341caSmrg    while test $# -ne 0 ; do
23611d341caSmrg      pathcomp=$pathcomp$1
23711d341caSmrg      shift
23811d341caSmrg      if test ! -d "$pathcomp"; then
23911d341caSmrg        $mkdirprog "$pathcomp"
24011d341caSmrg	# mkdir can fail with a `File exist' error in case several
24111d341caSmrg	# install-sh are creating the directory concurrently.  This
24211d341caSmrg	# is OK.
24311d341caSmrg	test -d "$pathcomp" || exit
24411d341caSmrg      fi
24511d341caSmrg      pathcomp=$pathcomp/
24611d341caSmrg    done
24711d341caSmrg  fi
24811d341caSmrg
24911d341caSmrg  if test -n "$dir_arg"; then
25011d341caSmrg    $doit $mkdircmd "$dst" \
25111d341caSmrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25211d341caSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25311d341caSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25411d341caSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25511d341caSmrg
25611d341caSmrg  else
25711d341caSmrg    dstfile=`basename "$dst"`
25811d341caSmrg
25911d341caSmrg    # Make a couple of temp file names in the proper directory.
26011d341caSmrg    dsttmp=$dstdir/_inst.$$_
26111d341caSmrg    rmtmp=$dstdir/_rm.$$_
26211d341caSmrg
26311d341caSmrg    # Trap to clean up those temp files at exit.
26411d341caSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26511d341caSmrg    trap '(exit $?); exit' 1 2 13 15
26611d341caSmrg
26711d341caSmrg    # Copy the file name to the temp name.
26811d341caSmrg    $doit $cpprog "$src" "$dsttmp" &&
26911d341caSmrg
27011d341caSmrg    # and set any options; do chmod last to preserve setuid bits.
27111d341caSmrg    #
27211d341caSmrg    # If any of these fail, we abort the whole thing.  If we want to
27311d341caSmrg    # ignore errors from any of these, just make sure not to ignore
27411d341caSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27511d341caSmrg    #
27611d341caSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27711d341caSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27811d341caSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27911d341caSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28011d341caSmrg
28111d341caSmrg    # Now rename the file to the real destination.
28211d341caSmrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28311d341caSmrg      || {
28411d341caSmrg	   # The rename failed, perhaps because mv can't rename something else
28511d341caSmrg	   # to itself, or perhaps because mv is so ancient that it does not
28611d341caSmrg	   # support -f.
28711d341caSmrg
28811d341caSmrg	   # Now remove or move aside any old file at destination location.
28911d341caSmrg	   # We try this two ways since rm can't unlink itself on some
29011d341caSmrg	   # systems and the destination file might be busy for other
29111d341caSmrg	   # reasons.  In this case, the final cleanup might fail but the new
29211d341caSmrg	   # file should still install successfully.
29311d341caSmrg	   {
29411d341caSmrg	     if test -f "$dstdir/$dstfile"; then
29511d341caSmrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29611d341caSmrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29711d341caSmrg	       || {
29811d341caSmrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29911d341caSmrg		 (exit 1); exit 1
30011d341caSmrg	       }
30111d341caSmrg	     else
30211d341caSmrg	       :
30311d341caSmrg	     fi
30411d341caSmrg	   } &&
30511d341caSmrg
30611d341caSmrg	   # Now rename the file to the real destination.
30711d341caSmrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30811d341caSmrg	 }
30911d341caSmrg    }
31011d341caSmrg  fi || { (exit 1); exit 1; }
31111d341caSmrgdone
31211d341caSmrg
31311d341caSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
31411d341caSmrg{
31511d341caSmrg  (exit 0); exit 0
31611d341caSmrg}
31711d341caSmrg
31811d341caSmrg# Local variables:
31911d341caSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32011d341caSmrg# time-stamp-start: "scriptversion="
32111d341caSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32211d341caSmrg# time-stamp-end: "$"
32311d341caSmrg# End:
324