install-sh revision 15fb4814
115fb4814Smrg#!/bin/sh
215fb4814Smrg# install - install a program, script, or datafile
315fb4814Smrg
415fb4814Smrgscriptversion=2005-05-14.22
515fb4814Smrg
615fb4814Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
715fb4814Smrg# later released in X11R6 (xc/config/util/install.sh) with the
815fb4814Smrg# following copyright and license.
915fb4814Smrg#
1015fb4814Smrg# Copyright (C) 1994 X Consortium
1115fb4814Smrg#
1215fb4814Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1315fb4814Smrg# of this software and associated documentation files (the "Software"), to
1415fb4814Smrg# deal in the Software without restriction, including without limitation the
1515fb4814Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1615fb4814Smrg# sell copies of the Software, and to permit persons to whom the Software is
1715fb4814Smrg# furnished to do so, subject to the following conditions:
1815fb4814Smrg#
1915fb4814Smrg# The above copyright notice and this permission notice shall be included in
2015fb4814Smrg# all copies or substantial portions of the Software.
2115fb4814Smrg#
2215fb4814Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2315fb4814Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2415fb4814Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2515fb4814Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2615fb4814Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2715fb4814Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2815fb4814Smrg#
2915fb4814Smrg# Except as contained in this notice, the name of the X Consortium shall not
3015fb4814Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3115fb4814Smrg# ings in this Software without prior written authorization from the X Consor-
3215fb4814Smrg# tium.
3315fb4814Smrg#
3415fb4814Smrg#
3515fb4814Smrg# FSF changes to this file are in the public domain.
3615fb4814Smrg#
3715fb4814Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3815fb4814Smrg# `make' implicit rules from creating a file called install from it
3915fb4814Smrg# when there is no Makefile.
4015fb4814Smrg#
4115fb4814Smrg# This script is compatible with the BSD install script, but was written
4215fb4814Smrg# from scratch.  It can only install one file at a time, a restriction
4315fb4814Smrg# shared with many OS's install programs.
4415fb4814Smrg
4515fb4814Smrg# set DOITPROG to echo to test this script
4615fb4814Smrg
4715fb4814Smrg# Don't use :- since 4.3BSD and earlier shells don't like it.
4815fb4814Smrgdoit="${DOITPROG-}"
4915fb4814Smrg
5015fb4814Smrg# put in absolute paths if you don't have them in your path; or use env. vars.
5115fb4814Smrg
5215fb4814Smrgmvprog="${MVPROG-mv}"
5315fb4814Smrgcpprog="${CPPROG-cp}"
5415fb4814Smrgchmodprog="${CHMODPROG-chmod}"
5515fb4814Smrgchownprog="${CHOWNPROG-chown}"
5615fb4814Smrgchgrpprog="${CHGRPPROG-chgrp}"
5715fb4814Smrgstripprog="${STRIPPROG-strip}"
5815fb4814Smrgrmprog="${RMPROG-rm}"
5915fb4814Smrgmkdirprog="${MKDIRPROG-mkdir}"
6015fb4814Smrg
6115fb4814Smrgchmodcmd="$chmodprog 0755"
6215fb4814Smrgchowncmd=
6315fb4814Smrgchgrpcmd=
6415fb4814Smrgstripcmd=
6515fb4814Smrgrmcmd="$rmprog -f"
6615fb4814Smrgmvcmd="$mvprog"
6715fb4814Smrgsrc=
6815fb4814Smrgdst=
6915fb4814Smrgdir_arg=
7015fb4814Smrgdstarg=
7115fb4814Smrgno_target_directory=
7215fb4814Smrg
7315fb4814Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
7415fb4814Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
7515fb4814Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
7615fb4814Smrg   or: $0 [OPTION]... -d DIRECTORIES...
7715fb4814Smrg
7815fb4814SmrgIn the 1st form, copy SRCFILE to DSTFILE.
7915fb4814SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8015fb4814SmrgIn the 4th, create DIRECTORIES.
8115fb4814Smrg
8215fb4814SmrgOptions:
8315fb4814Smrg-c         (ignored)
8415fb4814Smrg-d         create directories instead of installing files.
8515fb4814Smrg-g GROUP   $chgrpprog installed files to GROUP.
8615fb4814Smrg-m MODE    $chmodprog installed files to MODE.
8715fb4814Smrg-o USER    $chownprog installed files to USER.
8815fb4814Smrg-s         $stripprog installed files.
8915fb4814Smrg-t DIRECTORY  install into DIRECTORY.
9015fb4814Smrg-T         report an error if DSTFILE is a directory.
9115fb4814Smrg--help     display this help and exit.
9215fb4814Smrg--version  display version info and exit.
9315fb4814Smrg
9415fb4814SmrgEnvironment variables override the default commands:
9515fb4814Smrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
9615fb4814Smrg"
9715fb4814Smrg
9815fb4814Smrgwhile test -n "$1"; do
9915fb4814Smrg  case $1 in
10015fb4814Smrg    -c) shift
10115fb4814Smrg        continue;;
10215fb4814Smrg
10315fb4814Smrg    -d) dir_arg=true
10415fb4814Smrg        shift
10515fb4814Smrg        continue;;
10615fb4814Smrg
10715fb4814Smrg    -g) chgrpcmd="$chgrpprog $2"
10815fb4814Smrg        shift
10915fb4814Smrg        shift
11015fb4814Smrg        continue;;
11115fb4814Smrg
11215fb4814Smrg    --help) echo "$usage"; exit $?;;
11315fb4814Smrg
11415fb4814Smrg    -m) chmodcmd="$chmodprog $2"
11515fb4814Smrg        shift
11615fb4814Smrg        shift
11715fb4814Smrg        continue;;
11815fb4814Smrg
11915fb4814Smrg    -o) chowncmd="$chownprog $2"
12015fb4814Smrg        shift
12115fb4814Smrg        shift
12215fb4814Smrg        continue;;
12315fb4814Smrg
12415fb4814Smrg    -s) stripcmd=$stripprog
12515fb4814Smrg        shift
12615fb4814Smrg        continue;;
12715fb4814Smrg
12815fb4814Smrg    -t) dstarg=$2
12915fb4814Smrg	shift
13015fb4814Smrg	shift
13115fb4814Smrg	continue;;
13215fb4814Smrg
13315fb4814Smrg    -T) no_target_directory=true
13415fb4814Smrg	shift
13515fb4814Smrg	continue;;
13615fb4814Smrg
13715fb4814Smrg    --version) echo "$0 $scriptversion"; exit $?;;
13815fb4814Smrg
13915fb4814Smrg    *)  # When -d is used, all remaining arguments are directories to create.
14015fb4814Smrg	# When -t is used, the destination is already specified.
14115fb4814Smrg	test -n "$dir_arg$dstarg" && break
14215fb4814Smrg        # Otherwise, the last argument is the destination.  Remove it from $@.
14315fb4814Smrg	for arg
14415fb4814Smrg	do
14515fb4814Smrg          if test -n "$dstarg"; then
14615fb4814Smrg	    # $@ is not empty: it contains at least $arg.
14715fb4814Smrg	    set fnord "$@" "$dstarg"
14815fb4814Smrg	    shift # fnord
14915fb4814Smrg	  fi
15015fb4814Smrg	  shift # arg
15115fb4814Smrg	  dstarg=$arg
15215fb4814Smrg	done
15315fb4814Smrg	break;;
15415fb4814Smrg  esac
15515fb4814Smrgdone
15615fb4814Smrg
15715fb4814Smrgif test -z "$1"; then
15815fb4814Smrg  if test -z "$dir_arg"; then
15915fb4814Smrg    echo "$0: no input file specified." >&2
16015fb4814Smrg    exit 1
16115fb4814Smrg  fi
16215fb4814Smrg  # It's OK to call `install-sh -d' without argument.
16315fb4814Smrg  # This can happen when creating conditional directories.
16415fb4814Smrg  exit 0
16515fb4814Smrgfi
16615fb4814Smrg
16715fb4814Smrgfor src
16815fb4814Smrgdo
16915fb4814Smrg  # Protect names starting with `-'.
17015fb4814Smrg  case $src in
17115fb4814Smrg    -*) src=./$src ;;
17215fb4814Smrg  esac
17315fb4814Smrg
17415fb4814Smrg  if test -n "$dir_arg"; then
17515fb4814Smrg    dst=$src
17615fb4814Smrg    src=
17715fb4814Smrg
17815fb4814Smrg    if test -d "$dst"; then
17915fb4814Smrg      mkdircmd=:
18015fb4814Smrg      chmodcmd=
18115fb4814Smrg    else
18215fb4814Smrg      mkdircmd=$mkdirprog
18315fb4814Smrg    fi
18415fb4814Smrg  else
18515fb4814Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18615fb4814Smrg    # might cause directories to be created, which would be especially bad
18715fb4814Smrg    # if $src (and thus $dsttmp) contains '*'.
18815fb4814Smrg    if test ! -f "$src" && test ! -d "$src"; then
18915fb4814Smrg      echo "$0: $src does not exist." >&2
19015fb4814Smrg      exit 1
19115fb4814Smrg    fi
19215fb4814Smrg
19315fb4814Smrg    if test -z "$dstarg"; then
19415fb4814Smrg      echo "$0: no destination specified." >&2
19515fb4814Smrg      exit 1
19615fb4814Smrg    fi
19715fb4814Smrg
19815fb4814Smrg    dst=$dstarg
19915fb4814Smrg    # Protect names starting with `-'.
20015fb4814Smrg    case $dst in
20115fb4814Smrg      -*) dst=./$dst ;;
20215fb4814Smrg    esac
20315fb4814Smrg
20415fb4814Smrg    # If destination is a directory, append the input filename; won't work
20515fb4814Smrg    # if double slashes aren't ignored.
20615fb4814Smrg    if test -d "$dst"; then
20715fb4814Smrg      if test -n "$no_target_directory"; then
20815fb4814Smrg	echo "$0: $dstarg: Is a directory" >&2
20915fb4814Smrg	exit 1
21015fb4814Smrg      fi
21115fb4814Smrg      dst=$dst/`basename "$src"`
21215fb4814Smrg    fi
21315fb4814Smrg  fi
21415fb4814Smrg
21515fb4814Smrg  # This sed command emulates the dirname command.
21615fb4814Smrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21715fb4814Smrg
21815fb4814Smrg  # Make sure that the destination directory exists.
21915fb4814Smrg
22015fb4814Smrg  # Skip lots of stat calls in the usual case.
22115fb4814Smrg  if test ! -d "$dstdir"; then
22215fb4814Smrg    defaultIFS='
22315fb4814Smrg	 '
22415fb4814Smrg    IFS="${IFS-$defaultIFS}"
22515fb4814Smrg
22615fb4814Smrg    oIFS=$IFS
22715fb4814Smrg    # Some sh's can't handle IFS=/ for some reason.
22815fb4814Smrg    IFS='%'
22915fb4814Smrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23015fb4814Smrg    shift
23115fb4814Smrg    IFS=$oIFS
23215fb4814Smrg
23315fb4814Smrg    pathcomp=
23415fb4814Smrg
23515fb4814Smrg    while test $# -ne 0 ; do
23615fb4814Smrg      pathcomp=$pathcomp$1
23715fb4814Smrg      shift
23815fb4814Smrg      if test ! -d "$pathcomp"; then
23915fb4814Smrg        $mkdirprog "$pathcomp"
24015fb4814Smrg	# mkdir can fail with a `File exist' error in case several
24115fb4814Smrg	# install-sh are creating the directory concurrently.  This
24215fb4814Smrg	# is OK.
24315fb4814Smrg	test -d "$pathcomp" || exit
24415fb4814Smrg      fi
24515fb4814Smrg      pathcomp=$pathcomp/
24615fb4814Smrg    done
24715fb4814Smrg  fi
24815fb4814Smrg
24915fb4814Smrg  if test -n "$dir_arg"; then
25015fb4814Smrg    $doit $mkdircmd "$dst" \
25115fb4814Smrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
25215fb4814Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
25315fb4814Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
25415fb4814Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25515fb4814Smrg
25615fb4814Smrg  else
25715fb4814Smrg    dstfile=`basename "$dst"`
25815fb4814Smrg
25915fb4814Smrg    # Make a couple of temp file names in the proper directory.
26015fb4814Smrg    dsttmp=$dstdir/_inst.$$_
26115fb4814Smrg    rmtmp=$dstdir/_rm.$$_
26215fb4814Smrg
26315fb4814Smrg    # Trap to clean up those temp files at exit.
26415fb4814Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
26515fb4814Smrg    trap '(exit $?); exit' 1 2 13 15
26615fb4814Smrg
26715fb4814Smrg    # Copy the file name to the temp name.
26815fb4814Smrg    $doit $cpprog "$src" "$dsttmp" &&
26915fb4814Smrg
27015fb4814Smrg    # and set any options; do chmod last to preserve setuid bits.
27115fb4814Smrg    #
27215fb4814Smrg    # If any of these fail, we abort the whole thing.  If we want to
27315fb4814Smrg    # ignore errors from any of these, just make sure not to ignore
27415fb4814Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
27515fb4814Smrg    #
27615fb4814Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
27715fb4814Smrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
27815fb4814Smrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
27915fb4814Smrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
28015fb4814Smrg
28115fb4814Smrg    # Now rename the file to the real destination.
28215fb4814Smrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
28315fb4814Smrg      || {
28415fb4814Smrg	   # The rename failed, perhaps because mv can't rename something else
28515fb4814Smrg	   # to itself, or perhaps because mv is so ancient that it does not
28615fb4814Smrg	   # support -f.
28715fb4814Smrg
28815fb4814Smrg	   # Now remove or move aside any old file at destination location.
28915fb4814Smrg	   # We try this two ways since rm can't unlink itself on some
29015fb4814Smrg	   # systems and the destination file might be busy for other
29115fb4814Smrg	   # reasons.  In this case, the final cleanup might fail but the new
29215fb4814Smrg	   # file should still install successfully.
29315fb4814Smrg	   {
29415fb4814Smrg	     if test -f "$dstdir/$dstfile"; then
29515fb4814Smrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
29615fb4814Smrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
29715fb4814Smrg	       || {
29815fb4814Smrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
29915fb4814Smrg		 (exit 1); exit 1
30015fb4814Smrg	       }
30115fb4814Smrg	     else
30215fb4814Smrg	       :
30315fb4814Smrg	     fi
30415fb4814Smrg	   } &&
30515fb4814Smrg
30615fb4814Smrg	   # Now rename the file to the real destination.
30715fb4814Smrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
30815fb4814Smrg	 }
30915fb4814Smrg    }
31015fb4814Smrg  fi || { (exit 1); exit 1; }
31115fb4814Smrgdone
31215fb4814Smrg
31315fb4814Smrg# The final little trick to "correctly" pass the exit status to the exit trap.
31415fb4814Smrg{
31515fb4814Smrg  (exit 0); exit 0
31615fb4814Smrg}
31715fb4814Smrg
31815fb4814Smrg# Local variables:
31915fb4814Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
32015fb4814Smrg# time-stamp-start: "scriptversion="
32115fb4814Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
32215fb4814Smrg# time-stamp-end: "$"
32315fb4814Smrg# End:
324