install-sh revision 17a48c7c
117a48c7cSmrg#!/bin/sh
217a48c7cSmrg# install - install a program, script, or datafile
317a48c7cSmrg
417a48c7cSmrgscriptversion=2005-05-14.22
517a48c7cSmrg
617a48c7cSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
717a48c7cSmrg# later released in X11R6 (xc/config/util/install.sh) with the
817a48c7cSmrg# following copyright and license.
917a48c7cSmrg#
1017a48c7cSmrg# Copyright (C) 1994 X Consortium
1117a48c7cSmrg#
1217a48c7cSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1317a48c7cSmrg# of this software and associated documentation files (the "Software"), to
1417a48c7cSmrg# deal in the Software without restriction, including without limitation the
1517a48c7cSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1617a48c7cSmrg# sell copies of the Software, and to permit persons to whom the Software is
1717a48c7cSmrg# furnished to do so, subject to the following conditions:
1817a48c7cSmrg#
1917a48c7cSmrg# The above copyright notice and this permission notice shall be included in
2017a48c7cSmrg# all copies or substantial portions of the Software.
2117a48c7cSmrg#
2217a48c7cSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2317a48c7cSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2417a48c7cSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2517a48c7cSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2617a48c7cSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2717a48c7cSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2817a48c7cSmrg#
2917a48c7cSmrg# Except as contained in this notice, the name of the X Consortium shall not
3017a48c7cSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3117a48c7cSmrg# ings in this Software without prior written authorization from the X Consor-
3217a48c7cSmrg# tium.
3317a48c7cSmrg#
3417a48c7cSmrg#
3517a48c7cSmrg# FSF changes to this file are in the public domain.
3617a48c7cSmrg#
3717a48c7cSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3817a48c7cSmrg# `make' implicit rules from creating a file called install from it
3917a48c7cSmrg# when there is no Makefile.
4017a48c7cSmrg#
4117a48c7cSmrg# This script is compatible with the BSD install script, but was written
4217a48c7cSmrg# from scratch.  It can only install one file at a time, a restriction
4317a48c7cSmrg# shared with many OS's install programs.
4417a48c7cSmrg
4517a48c7cSmrg# set DOITPROG to echo to test this script
4617a48c7cSmrg
4717a48c7cSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4817a48c7cSmrgdoit="${DOITPROG-}"
4917a48c7cSmrg
5017a48c7cSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
5117a48c7cSmrg
5217a48c7cSmrgmvprog="${MVPROG-mv}"
5317a48c7cSmrgcpprog="${CPPROG-cp}"
5417a48c7cSmrgchmodprog="${CHMODPROG-chmod}"
5517a48c7cSmrgchownprog="${CHOWNPROG-chown}"
5617a48c7cSmrgchgrpprog="${CHGRPPROG-chgrp}"
5717a48c7cSmrgstripprog="${STRIPPROG-strip}"
5817a48c7cSmrgrmprog="${RMPROG-rm}"
5917a48c7cSmrgmkdirprog="${MKDIRPROG-mkdir}"
6017a48c7cSmrg
6117a48c7cSmrgchmodcmd="$chmodprog 0755"
6217a48c7cSmrgchowncmd=
6317a48c7cSmrgchgrpcmd=
6417a48c7cSmrgstripcmd=
6517a48c7cSmrgrmcmd="$rmprog -f"
6617a48c7cSmrgmvcmd="$mvprog"
6717a48c7cSmrgsrc=
6817a48c7cSmrgdst=
6917a48c7cSmrgdir_arg=
7017a48c7cSmrgdstarg=
7117a48c7cSmrgno_target_directory=
7217a48c7cSmrg
7317a48c7cSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7417a48c7cSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7517a48c7cSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7617a48c7cSmrg   or: $0 [OPTION]... -d DIRECTORIES...
7717a48c7cSmrg
7817a48c7cSmrgIn the 1st form, copy SRCFILE to DSTFILE.
7917a48c7cSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8017a48c7cSmrgIn the 4th, create DIRECTORIES.
8117a48c7cSmrg
8217a48c7cSmrgOptions:
8317a48c7cSmrg-c         (ignored)
8417a48c7cSmrg-d         create directories instead of installing files.
8517a48c7cSmrg-g GROUP   $chgrpprog installed files to GROUP.
8617a48c7cSmrg-m MODE    $chmodprog installed files to MODE.
8717a48c7cSmrg-o USER    $chownprog installed files to USER.
8817a48c7cSmrg-s         $stripprog installed files.
8917a48c7cSmrg-t DIRECTORY  install into DIRECTORY.
9017a48c7cSmrg-T         report an error if DSTFILE is a directory.
9117a48c7cSmrg--help     display this help and exit.
9217a48c7cSmrg--version  display version info and exit.
9317a48c7cSmrg
9417a48c7cSmrgEnvironment variables override the default commands:
9517a48c7cSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9617a48c7cSmrg"
9717a48c7cSmrg
9817a48c7cSmrgwhile test -n "$1"; do
9917a48c7cSmrg  case $1 in
10017a48c7cSmrg    -c) shift
10117a48c7cSmrg        continue;;
10217a48c7cSmrg
10317a48c7cSmrg    -d) dir_arg=true
10417a48c7cSmrg        shift
10517a48c7cSmrg        continue;;
10617a48c7cSmrg
10717a48c7cSmrg    -g) chgrpcmd="$chgrpprog $2"
10817a48c7cSmrg        shift
10917a48c7cSmrg        shift
11017a48c7cSmrg        continue;;
11117a48c7cSmrg
11217a48c7cSmrg    --help) echo "$usage"; exit $?;;
11317a48c7cSmrg
11417a48c7cSmrg    -m) chmodcmd="$chmodprog $2"
11517a48c7cSmrg        shift
11617a48c7cSmrg        shift
11717a48c7cSmrg        continue;;
11817a48c7cSmrg
11917a48c7cSmrg    -o) chowncmd="$chownprog $2"
12017a48c7cSmrg        shift
12117a48c7cSmrg        shift
12217a48c7cSmrg        continue;;
12317a48c7cSmrg
12417a48c7cSmrg    -s) stripcmd=$stripprog
12517a48c7cSmrg        shift
12617a48c7cSmrg        continue;;
12717a48c7cSmrg
12817a48c7cSmrg    -t) dstarg=$2
12917a48c7cSmrg	shift
13017a48c7cSmrg	shift
13117a48c7cSmrg	continue;;
13217a48c7cSmrg
13317a48c7cSmrg    -T) no_target_directory=true
13417a48c7cSmrg	shift
13517a48c7cSmrg	continue;;
13617a48c7cSmrg
13717a48c7cSmrg    --version) echo "$0 $scriptversion"; exit $?;;
13817a48c7cSmrg
13917a48c7cSmrg    *)  # When -d is used, all remaining arguments are directories to create.
14017a48c7cSmrg	# When -t is used, the destination is already specified.
14117a48c7cSmrg	test -n "$dir_arg$dstarg" && break
14217a48c7cSmrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14317a48c7cSmrg	for arg
14417a48c7cSmrg	do
14517a48c7cSmrg          if test -n "$dstarg"; then
14617a48c7cSmrg	    # $@ is not empty: it contains at least $arg.
14717a48c7cSmrg	    set fnord "$@" "$dstarg"
14817a48c7cSmrg	    shift # fnord
14917a48c7cSmrg	  fi
15017a48c7cSmrg	  shift # arg
15117a48c7cSmrg	  dstarg=$arg
15217a48c7cSmrg	done
15317a48c7cSmrg	break;;
15417a48c7cSmrg  esac
15517a48c7cSmrgdone
15617a48c7cSmrg
15717a48c7cSmrgif test -z "$1"; then
15817a48c7cSmrg  if test -z "$dir_arg"; then
15917a48c7cSmrg    echo "$0: no input file specified." >&2
16017a48c7cSmrg    exit 1
16117a48c7cSmrg  fi
16217a48c7cSmrg  # It's OK to call `install-sh -d' without argument.
16317a48c7cSmrg  # This can happen when creating conditional directories.
16417a48c7cSmrg  exit 0
16517a48c7cSmrgfi
16617a48c7cSmrg
16717a48c7cSmrgfor src
16817a48c7cSmrgdo
16917a48c7cSmrg  # Protect names starting with `-'.
17017a48c7cSmrg  case $src in
17117a48c7cSmrg    -*) src=./$src ;;
17217a48c7cSmrg  esac
17317a48c7cSmrg
17417a48c7cSmrg  if test -n "$dir_arg"; then
17517a48c7cSmrg    dst=$src
17617a48c7cSmrg    src=
17717a48c7cSmrg
17817a48c7cSmrg    if test -d "$dst"; then
17917a48c7cSmrg      mkdircmd=:
18017a48c7cSmrg      chmodcmd=
18117a48c7cSmrg    else
18217a48c7cSmrg      mkdircmd=$mkdirprog
18317a48c7cSmrg    fi
18417a48c7cSmrg  else
18517a48c7cSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18617a48c7cSmrg    # might cause directories to be created, which would be especially bad
18717a48c7cSmrg    # if $src (and thus $dsttmp) contains '*'.
18817a48c7cSmrg    if test ! -f "$src" && test ! -d "$src"; then
18917a48c7cSmrg      echo "$0: $src does not exist." >&2
19017a48c7cSmrg      exit 1
19117a48c7cSmrg    fi
19217a48c7cSmrg
19317a48c7cSmrg    if test -z "$dstarg"; then
19417a48c7cSmrg      echo "$0: no destination specified." >&2
19517a48c7cSmrg      exit 1
19617a48c7cSmrg    fi
19717a48c7cSmrg
19817a48c7cSmrg    dst=$dstarg
19917a48c7cSmrg    # Protect names starting with `-'.
20017a48c7cSmrg    case $dst in
20117a48c7cSmrg      -*) dst=./$dst ;;
20217a48c7cSmrg    esac
20317a48c7cSmrg
20417a48c7cSmrg    # If destination is a directory, append the input filename; won't work
20517a48c7cSmrg    # if double slashes aren't ignored.
20617a48c7cSmrg    if test -d "$dst"; then
20717a48c7cSmrg      if test -n "$no_target_directory"; then
20817a48c7cSmrg	echo "$0: $dstarg: Is a directory" >&2
20917a48c7cSmrg	exit 1
21017a48c7cSmrg      fi
21117a48c7cSmrg      dst=$dst/`basename "$src"`
21217a48c7cSmrg    fi
21317a48c7cSmrg  fi
21417a48c7cSmrg
21517a48c7cSmrg  # This sed command emulates the dirname command.
21617a48c7cSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21717a48c7cSmrg
21817a48c7cSmrg  # Make sure that the destination directory exists.
21917a48c7cSmrg
22017a48c7cSmrg  # Skip lots of stat calls in the usual case.
22117a48c7cSmrg  if test ! -d "$dstdir"; then
22217a48c7cSmrg    defaultIFS='
22317a48c7cSmrg	 '
22417a48c7cSmrg    IFS="${IFS-$defaultIFS}"
22517a48c7cSmrg
22617a48c7cSmrg    oIFS=$IFS
22717a48c7cSmrg    # Some sh's can't handle IFS=/ for some reason.
22817a48c7cSmrg    IFS='%'
22917a48c7cSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23017a48c7cSmrg    shift
23117a48c7cSmrg    IFS=$oIFS
23217a48c7cSmrg
23317a48c7cSmrg    pathcomp=
23417a48c7cSmrg
23517a48c7cSmrg    while test $# -ne 0 ; do
23617a48c7cSmrg      pathcomp=$pathcomp$1
23717a48c7cSmrg      shift
23817a48c7cSmrg      if test ! -d "$pathcomp"; then
23917a48c7cSmrg        $mkdirprog "$pathcomp"
24017a48c7cSmrg	# mkdir can fail with a `File exist' error in case several
24117a48c7cSmrg	# install-sh are creating the directory concurrently.  This
24217a48c7cSmrg	# is OK.
24317a48c7cSmrg	test -d "$pathcomp" || exit
24417a48c7cSmrg      fi
24517a48c7cSmrg      pathcomp=$pathcomp/
24617a48c7cSmrg    done
24717a48c7cSmrg  fi
24817a48c7cSmrg
24917a48c7cSmrg  if test -n "$dir_arg"; then
25017a48c7cSmrg    $doit $mkdircmd "$dst" \
25117a48c7cSmrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25217a48c7cSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25317a48c7cSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25417a48c7cSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25517a48c7cSmrg
25617a48c7cSmrg  else
25717a48c7cSmrg    dstfile=`basename "$dst"`
25817a48c7cSmrg
25917a48c7cSmrg    # Make a couple of temp file names in the proper directory.
26017a48c7cSmrg    dsttmp=$dstdir/_inst.$$_
26117a48c7cSmrg    rmtmp=$dstdir/_rm.$$_
26217a48c7cSmrg
26317a48c7cSmrg    # Trap to clean up those temp files at exit.
26417a48c7cSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26517a48c7cSmrg    trap '(exit $?); exit' 1 2 13 15
26617a48c7cSmrg
26717a48c7cSmrg    # Copy the file name to the temp name.
26817a48c7cSmrg    $doit $cpprog "$src" "$dsttmp" &&
26917a48c7cSmrg
27017a48c7cSmrg    # and set any options; do chmod last to preserve setuid bits.
27117a48c7cSmrg    #
27217a48c7cSmrg    # If any of these fail, we abort the whole thing.  If we want to
27317a48c7cSmrg    # ignore errors from any of these, just make sure not to ignore
27417a48c7cSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27517a48c7cSmrg    #
27617a48c7cSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27717a48c7cSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27817a48c7cSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27917a48c7cSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28017a48c7cSmrg
28117a48c7cSmrg    # Now rename the file to the real destination.
28217a48c7cSmrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28317a48c7cSmrg      || {
28417a48c7cSmrg	   # The rename failed, perhaps because mv can't rename something else
28517a48c7cSmrg	   # to itself, or perhaps because mv is so ancient that it does not
28617a48c7cSmrg	   # support -f.
28717a48c7cSmrg
28817a48c7cSmrg	   # Now remove or move aside any old file at destination location.
28917a48c7cSmrg	   # We try this two ways since rm can't unlink itself on some
29017a48c7cSmrg	   # systems and the destination file might be busy for other
29117a48c7cSmrg	   # reasons.  In this case, the final cleanup might fail but the new
29217a48c7cSmrg	   # file should still install successfully.
29317a48c7cSmrg	   {
29417a48c7cSmrg	     if test -f "$dstdir/$dstfile"; then
29517a48c7cSmrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29617a48c7cSmrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29717a48c7cSmrg	       || {
29817a48c7cSmrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29917a48c7cSmrg		 (exit 1); exit 1
30017a48c7cSmrg	       }
30117a48c7cSmrg	     else
30217a48c7cSmrg	       :
30317a48c7cSmrg	     fi
30417a48c7cSmrg	   } &&
30517a48c7cSmrg
30617a48c7cSmrg	   # Now rename the file to the real destination.
30717a48c7cSmrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30817a48c7cSmrg	 }
30917a48c7cSmrg    }
31017a48c7cSmrg  fi || { (exit 1); exit 1; }
31117a48c7cSmrgdone
31217a48c7cSmrg
31317a48c7cSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
31417a48c7cSmrg{
31517a48c7cSmrg  (exit 0); exit 0
31617a48c7cSmrg}
31717a48c7cSmrg
31817a48c7cSmrg# Local variables:
31917a48c7cSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32017a48c7cSmrg# time-stamp-start: "scriptversion="
32117a48c7cSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32217a48c7cSmrg# time-stamp-end: "$"
32317a48c7cSmrg# End:
324