1fc89c0fbSmrg#!/bin/sh
2fc89c0fbSmrg# install - install a program, script, or datafile
3fc89c0fbSmrg
4c8df0c59Smrgscriptversion=2024-06-19.01; # UTC
5fc89c0fbSmrg
6fc89c0fbSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7fc89c0fbSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8fc89c0fbSmrg# following copyright and license.
9fc89c0fbSmrg#
10fc89c0fbSmrg# Copyright (C) 1994 X Consortium
11fc89c0fbSmrg#
12fc89c0fbSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13fc89c0fbSmrg# of this software and associated documentation files (the "Software"), to
14fc89c0fbSmrg# deal in the Software without restriction, including without limitation the
15fc89c0fbSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16fc89c0fbSmrg# sell copies of the Software, and to permit persons to whom the Software is
17fc89c0fbSmrg# furnished to do so, subject to the following conditions:
18fc89c0fbSmrg#
19fc89c0fbSmrg# The above copyright notice and this permission notice shall be included in
20fc89c0fbSmrg# all copies or substantial portions of the Software.
21fc89c0fbSmrg#
22fc89c0fbSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23fc89c0fbSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24fc89c0fbSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25fc89c0fbSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26fc89c0fbSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27fc89c0fbSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28fc89c0fbSmrg#
29fc89c0fbSmrg# Except as contained in this notice, the name of the X Consortium shall not
30fc89c0fbSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31fc89c0fbSmrg# ings in this Software without prior written authorization from the X Consor-
32fc89c0fbSmrg# tium.
33fc89c0fbSmrg#
34fc89c0fbSmrg#
35fc89c0fbSmrg# FSF changes to this file are in the public domain.
36fc89c0fbSmrg#
37fc89c0fbSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38576bbdfcSmrg# 'make' implicit rules from creating a file called install from it
39fc89c0fbSmrg# when there is no Makefile.
40fc89c0fbSmrg#
41fc89c0fbSmrg# This script is compatible with the BSD install script, but was written
42fc89c0fbSmrg# from scratch.
43fc89c0fbSmrg
4481676fe2Smrgtab='	'
45fc89c0fbSmrgnl='
46fc89c0fbSmrg'
4781676fe2SmrgIFS=" $tab$nl"
48fc89c0fbSmrg
4981676fe2Smrg# Set DOITPROG to "echo" to test this script.
50fc89c0fbSmrg
5191ec45ceSmrgdoit=${DOITPROG-}
5281676fe2Smrgdoit_exec=${doit:-exec}
53fc89c0fbSmrg
54fc89c0fbSmrg# Put in absolute file names if you don't have them in your path;
55fc89c0fbSmrg# or use environment vars.
56fc89c0fbSmrg
5791ec45ceSmrgchgrpprog=${CHGRPPROG-chgrp}
5891ec45ceSmrgchmodprog=${CHMODPROG-chmod}
5991ec45ceSmrgchownprog=${CHOWNPROG-chown}
6091ec45ceSmrgcmpprog=${CMPPROG-cmp}
6191ec45ceSmrgcpprog=${CPPROG-cp}
6291ec45ceSmrgmkdirprog=${MKDIRPROG-mkdir}
6391ec45ceSmrgmvprog=${MVPROG-mv}
6491ec45ceSmrgrmprog=${RMPROG-rm}
6591ec45ceSmrgstripprog=${STRIPPROG-strip}
6691ec45ceSmrg
67fc89c0fbSmrgposix_mkdir=
68fc89c0fbSmrg
69fc89c0fbSmrg# Desired mode of installed file.
70fc89c0fbSmrgmode=0755
71fc89c0fbSmrg
7249bee38cSmrg# Create dirs (including intermediate dirs) using mode 755.
7349bee38cSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
7449bee38cSmrgmkdir_umask=22
7549bee38cSmrg
7649bee38cSmrgbackupsuffix=
7791ec45ceSmrgchgrpcmd=
78fc89c0fbSmrgchmodcmd=$chmodprog
79fc89c0fbSmrgchowncmd=
8091ec45ceSmrgmvcmd=$mvprog
81fc89c0fbSmrgrmcmd="$rmprog -f"
8291ec45ceSmrgstripcmd=
8391ec45ceSmrg
84fc89c0fbSmrgsrc=
85fc89c0fbSmrgdst=
86fc89c0fbSmrgdir_arg=
8791ec45ceSmrgdst_arg=
8891ec45ceSmrg
8991ec45ceSmrgcopy_on_change=false
9081676fe2Smrgis_target_a_directory=possibly
91fc89c0fbSmrg
9291ec45ceSmrgusage="\
9391ec45ceSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94fc89c0fbSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95fc89c0fbSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96fc89c0fbSmrg   or: $0 [OPTION]... -d DIRECTORIES...
97fc89c0fbSmrg
98fc89c0fbSmrgIn the 1st form, copy SRCFILE to DSTFILE.
99fc89c0fbSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100fc89c0fbSmrgIn the 4th, create DIRECTORIES.
101fc89c0fbSmrg
102fc89c0fbSmrgOptions:
10391ec45ceSmrg     --help     display this help and exit.
10491ec45ceSmrg     --version  display version info and exit.
10591ec45ceSmrg
10691ec45ceSmrg  -c            (ignored)
10749bee38cSmrg  -C            install only if different (preserve data modification time)
10891ec45ceSmrg  -d            create directories instead of installing files.
10991ec45ceSmrg  -g GROUP      $chgrpprog installed files to GROUP.
11091ec45ceSmrg  -m MODE       $chmodprog installed files to MODE.
11191ec45ceSmrg  -o USER       $chownprog installed files to USER.
11249bee38cSmrg  -p            pass -p to $cpprog.
11391ec45ceSmrg  -s            $stripprog installed files.
11449bee38cSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
11591ec45ceSmrg  -t DIRECTORY  install into DIRECTORY.
11691ec45ceSmrg  -T            report an error if DSTFILE is a directory.
117fc89c0fbSmrg
118fc89c0fbSmrgEnvironment variables override the default commands:
11991ec45ceSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
12091ec45ceSmrg  RMPROG STRIPPROG
12149bee38cSmrg
12249bee38cSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
12349bee38cSmrgit's up to you to specify -f if you want it.
12449bee38cSmrg
12549bee38cSmrgIf -S is not specified, no backups are attempted.
12649bee38cSmrg
127c8df0c59SmrgReport bugs to <bug-automake@gnu.org>.
128c8df0c59SmrgGNU Automake home page: <https://www.gnu.org/software/automake/>.
129c8df0c59SmrgGeneral help using GNU software: <https://www.gnu.org/gethelp/>."
130fc89c0fbSmrg
131fc89c0fbSmrgwhile test $# -ne 0; do
132fc89c0fbSmrg  case $1 in
13391ec45ceSmrg    -c) ;;
13491ec45ceSmrg
13591ec45ceSmrg    -C) copy_on_change=true;;
136fc89c0fbSmrg
13791ec45ceSmrg    -d) dir_arg=true;;
138fc89c0fbSmrg
139fc89c0fbSmrg    -g) chgrpcmd="$chgrpprog $2"
14081676fe2Smrg        shift;;
141fc89c0fbSmrg
142fc89c0fbSmrg    --help) echo "$usage"; exit $?;;
143fc89c0fbSmrg
144fc89c0fbSmrg    -m) mode=$2
14581676fe2Smrg        case $mode in
14681676fe2Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14781676fe2Smrg            echo "$0: invalid mode: $mode" >&2
14881676fe2Smrg            exit 1;;
14981676fe2Smrg        esac
15081676fe2Smrg        shift;;
151fc89c0fbSmrg
152fc89c0fbSmrg    -o) chowncmd="$chownprog $2"
15381676fe2Smrg        shift;;
154fc89c0fbSmrg
15549bee38cSmrg    -p) cpprog="$cpprog -p";;
15649bee38cSmrg
15791ec45ceSmrg    -s) stripcmd=$stripprog;;
158fc89c0fbSmrg
15949bee38cSmrg    -S) backupsuffix="$2"
16049bee38cSmrg        shift;;
16149bee38cSmrg
16281676fe2Smrg    -t)
16381676fe2Smrg        is_target_a_directory=always
16481676fe2Smrg        dst_arg=$2
16581676fe2Smrg        # Protect names problematic for 'test' and other utilities.
16681676fe2Smrg        case $dst_arg in
16781676fe2Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16881676fe2Smrg        esac
16981676fe2Smrg        shift;;
170fc89c0fbSmrg
17181676fe2Smrg    -T) is_target_a_directory=never;;
172fc89c0fbSmrg
173c8df0c59Smrg    --version) echo "$0 (GNU Automake) $scriptversion"; exit $?;;
174fc89c0fbSmrg
17581676fe2Smrg    --) shift
17681676fe2Smrg        break;;
177fc89c0fbSmrg
17881676fe2Smrg    -*) echo "$0: invalid option: $1" >&2
17981676fe2Smrg        exit 1;;
180fc89c0fbSmrg
181fc89c0fbSmrg    *)  break;;
182fc89c0fbSmrg  esac
18391ec45ceSmrg  shift
184fc89c0fbSmrgdone
185fc89c0fbSmrg
18681676fe2Smrg# We allow the use of options -d and -T together, by making -d
18781676fe2Smrg# take the precedence; this is for compatibility with GNU install.
18881676fe2Smrg
18981676fe2Smrgif test -n "$dir_arg"; then
19081676fe2Smrg  if test -n "$dst_arg"; then
19181676fe2Smrg    echo "$0: target directory not allowed when installing a directory." >&2
19281676fe2Smrg    exit 1
19381676fe2Smrg  fi
19481676fe2Smrgfi
19581676fe2Smrg
19691ec45ceSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197fc89c0fbSmrg  # When -d is used, all remaining arguments are directories to create.
198fc89c0fbSmrg  # When -t is used, the destination is already specified.
199fc89c0fbSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200fc89c0fbSmrg  for arg
201fc89c0fbSmrg  do
20291ec45ceSmrg    if test -n "$dst_arg"; then
203fc89c0fbSmrg      # $@ is not empty: it contains at least $arg.
20491ec45ceSmrg      set fnord "$@" "$dst_arg"
205fc89c0fbSmrg      shift # fnord
206fc89c0fbSmrg    fi
207fc89c0fbSmrg    shift # arg
20891ec45ceSmrg    dst_arg=$arg
209576bbdfcSmrg    # Protect names problematic for 'test' and other utilities.
210576bbdfcSmrg    case $dst_arg in
211576bbdfcSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
212576bbdfcSmrg    esac
213fc89c0fbSmrg  done
214fc89c0fbSmrgfi
215fc89c0fbSmrg
216fc89c0fbSmrgif test $# -eq 0; then
217fc89c0fbSmrg  if test -z "$dir_arg"; then
218fc89c0fbSmrg    echo "$0: no input file specified." >&2
219fc89c0fbSmrg    exit 1
220fc89c0fbSmrg  fi
221576bbdfcSmrg  # It's OK to call 'install-sh -d' without argument.
222fc89c0fbSmrg  # This can happen when creating conditional directories.
223fc89c0fbSmrg  exit 0
224fc89c0fbSmrgfi
225fc89c0fbSmrg
22681676fe2Smrgif test -z "$dir_arg"; then
22781676fe2Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22881676fe2Smrg    if test ! -d "$dst_arg"; then
22981676fe2Smrg      echo "$0: $dst_arg: Is not a directory." >&2
23081676fe2Smrg      exit 1
23181676fe2Smrg    fi
23281676fe2Smrg  fi
23381676fe2Smrgfi
23481676fe2Smrg
235fc89c0fbSmrgif test -z "$dir_arg"; then
236576bbdfcSmrg  do_exit='(exit $ret); exit $ret'
237576bbdfcSmrg  trap "ret=129; $do_exit" 1
238576bbdfcSmrg  trap "ret=130; $do_exit" 2
239576bbdfcSmrg  trap "ret=141; $do_exit" 13
240576bbdfcSmrg  trap "ret=143; $do_exit" 15
241fc89c0fbSmrg
242fc89c0fbSmrg  # Set umask so as not to create temps with too-generous modes.
243fc89c0fbSmrg  # However, 'strip' requires both read and write access to temps.
244fc89c0fbSmrg  case $mode in
245fc89c0fbSmrg    # Optimize common cases.
246fc89c0fbSmrg    *644) cp_umask=133;;
247fc89c0fbSmrg    *755) cp_umask=22;;
248fc89c0fbSmrg
249fc89c0fbSmrg    *[0-7])
250fc89c0fbSmrg      if test -z "$stripcmd"; then
25181676fe2Smrg        u_plus_rw=
252fc89c0fbSmrg      else
25381676fe2Smrg        u_plus_rw='% 200'
254fc89c0fbSmrg      fi
255fc89c0fbSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256fc89c0fbSmrg    *)
257fc89c0fbSmrg      if test -z "$stripcmd"; then
25881676fe2Smrg        u_plus_rw=
259fc89c0fbSmrg      else
26081676fe2Smrg        u_plus_rw=,u+rw
261fc89c0fbSmrg      fi
262fc89c0fbSmrg      cp_umask=$mode$u_plus_rw;;
263fc89c0fbSmrg  esac
264fc89c0fbSmrgfi
265fc89c0fbSmrg
266fc89c0fbSmrgfor src
267fc89c0fbSmrgdo
268576bbdfcSmrg  # Protect names problematic for 'test' and other utilities.
269fc89c0fbSmrg  case $src in
270576bbdfcSmrg    -* | [=\(\)!]) src=./$src;;
271fc89c0fbSmrg  esac
272fc89c0fbSmrg
273fc89c0fbSmrg  if test -n "$dir_arg"; then
274fc89c0fbSmrg    dst=$src
275fc89c0fbSmrg    dstdir=$dst
276fc89c0fbSmrg    test -d "$dstdir"
277fc89c0fbSmrg    dstdir_status=$?
27849bee38cSmrg    # Don't chown directories that already exist.
27949bee38cSmrg    if test $dstdir_status = 0; then
28049bee38cSmrg      chowncmd=""
28149bee38cSmrg    fi
282fc89c0fbSmrg  else
283fc89c0fbSmrg
284fc89c0fbSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285fc89c0fbSmrg    # might cause directories to be created, which would be especially bad
286fc89c0fbSmrg    # if $src (and thus $dsttmp) contains '*'.
287fc89c0fbSmrg    if test ! -f "$src" && test ! -d "$src"; then
288fc89c0fbSmrg      echo "$0: $src does not exist." >&2
289fc89c0fbSmrg      exit 1
290fc89c0fbSmrg    fi
291fc89c0fbSmrg
29291ec45ceSmrg    if test -z "$dst_arg"; then
293fc89c0fbSmrg      echo "$0: no destination specified." >&2
294fc89c0fbSmrg      exit 1
295fc89c0fbSmrg    fi
29691ec45ceSmrg    dst=$dst_arg
297fc89c0fbSmrg
298f9c28e31Smrg    # If destination is a directory, append the input filename.
299fc89c0fbSmrg    if test -d "$dst"; then
30081676fe2Smrg      if test "$is_target_a_directory" = never; then
30181676fe2Smrg        echo "$0: $dst_arg: Is a directory" >&2
30281676fe2Smrg        exit 1
303fc89c0fbSmrg      fi
304fc89c0fbSmrg      dstdir=$dst
305f9c28e31Smrg      dstbase=`basename "$src"`
306f9c28e31Smrg      case $dst in
307f9c28e31Smrg	*/) dst=$dst$dstbase;;
308f9c28e31Smrg	*)  dst=$dst/$dstbase;;
309f9c28e31Smrg      esac
310fc89c0fbSmrg      dstdir_status=0
311fc89c0fbSmrg    else
31281676fe2Smrg      dstdir=`dirname "$dst"`
313fc89c0fbSmrg      test -d "$dstdir"
314fc89c0fbSmrg      dstdir_status=$?
315fc89c0fbSmrg    fi
316fc89c0fbSmrg  fi
317fc89c0fbSmrg
318f9c28e31Smrg  case $dstdir in
319f9c28e31Smrg    */) dstdirslash=$dstdir;;
320f9c28e31Smrg    *)  dstdirslash=$dstdir/;;
321f9c28e31Smrg  esac
322f9c28e31Smrg
323fc89c0fbSmrg  obsolete_mkdir_used=false
324fc89c0fbSmrg
325fc89c0fbSmrg  if test $dstdir_status != 0; then
326fc89c0fbSmrg    case $posix_mkdir in
327fc89c0fbSmrg      '')
32881676fe2Smrg        # With -d, create the new directory with the user-specified mode.
32981676fe2Smrg        # Otherwise, rely on $mkdir_umask.
33081676fe2Smrg        if test -n "$dir_arg"; then
33181676fe2Smrg          mkdir_mode=-m$mode
33281676fe2Smrg        else
33381676fe2Smrg          mkdir_mode=
33481676fe2Smrg        fi
33581676fe2Smrg
33681676fe2Smrg        posix_mkdir=false
33749bee38cSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
33849bee38cSmrg	# here however when possible just to lower collision chance.
33949bee38cSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
34049bee38cSmrg
34149bee38cSmrg	trap '
34249bee38cSmrg	  ret=$?
34349bee38cSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
34449bee38cSmrg	  exit $ret
34549bee38cSmrg	' 0
34649bee38cSmrg
34749bee38cSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
348c8df0c59Smrg	# directly in world-writable /tmp, make sure that the '$tmpdir'
34949bee38cSmrg	# directory is successfully created first before we actually test
35049bee38cSmrg	# 'mkdir -p'.
35149bee38cSmrg	if (umask $mkdir_umask &&
35249bee38cSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
35349bee38cSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
35449bee38cSmrg	then
35549bee38cSmrg	  if test -z "$dir_arg" || {
356c8df0c59Smrg	       # Check for POSIX incompatibility with -m.
35749bee38cSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35849bee38cSmrg	       # other-writable bit of parent directory when it shouldn't.
35949bee38cSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
36049bee38cSmrg	       test_tmpdir="$tmpdir/a"
36149bee38cSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
36249bee38cSmrg	       case $ls_ld_tmpdir in
36349bee38cSmrg		 d????-?r-*) different_mode=700;;
36449bee38cSmrg		 d????-?--*) different_mode=755;;
36549bee38cSmrg		 *) false;;
36649bee38cSmrg	       esac &&
36749bee38cSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36849bee38cSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36949bee38cSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
37049bee38cSmrg	       }
37149bee38cSmrg	     }
37249bee38cSmrg	  then posix_mkdir=:
37349bee38cSmrg	  fi
37449bee38cSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
37549bee38cSmrg	else
37649bee38cSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
37749bee38cSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
37849bee38cSmrg	fi
37949bee38cSmrg	trap '' 0;;
380fc89c0fbSmrg    esac
381fc89c0fbSmrg
382fc89c0fbSmrg    if
383fc89c0fbSmrg      $posix_mkdir && (
38481676fe2Smrg        umask $mkdir_umask &&
38581676fe2Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386fc89c0fbSmrg      )
387fc89c0fbSmrg    then :
388fc89c0fbSmrg    else
389fc89c0fbSmrg
39049bee38cSmrg      # mkdir does not conform to POSIX,
391fc89c0fbSmrg      # or it failed possibly due to a race condition.  Create the
392fc89c0fbSmrg      # directory the slow way, step by step, checking for races as we go.
393fc89c0fbSmrg
394fc89c0fbSmrg      case $dstdir in
39581676fe2Smrg        /*) prefix='/';;
39681676fe2Smrg        [-=\(\)!]*) prefix='./';;
39781676fe2Smrg        *)  prefix='';;
398fc89c0fbSmrg      esac
399fc89c0fbSmrg
400fc89c0fbSmrg      oIFS=$IFS
401fc89c0fbSmrg      IFS=/
40281676fe2Smrg      set -f
403fc89c0fbSmrg      set fnord $dstdir
404fc89c0fbSmrg      shift
40581676fe2Smrg      set +f
406fc89c0fbSmrg      IFS=$oIFS
407fc89c0fbSmrg
408fc89c0fbSmrg      prefixes=
409fc89c0fbSmrg
410fc89c0fbSmrg      for d
411fc89c0fbSmrg      do
41281676fe2Smrg        test X"$d" = X && continue
41381676fe2Smrg
41481676fe2Smrg        prefix=$prefix$d
41581676fe2Smrg        if test -d "$prefix"; then
41681676fe2Smrg          prefixes=
41781676fe2Smrg        else
41881676fe2Smrg          if $posix_mkdir; then
41949bee38cSmrg            (umask $mkdir_umask &&
42081676fe2Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42181676fe2Smrg            # Don't fail if two instances are running concurrently.
42281676fe2Smrg            test -d "$prefix" || exit 1
42381676fe2Smrg          else
42481676fe2Smrg            case $prefix in
42581676fe2Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42681676fe2Smrg              *) qprefix=$prefix;;
42781676fe2Smrg            esac
42881676fe2Smrg            prefixes="$prefixes '$qprefix'"
42981676fe2Smrg          fi
43081676fe2Smrg        fi
43181676fe2Smrg        prefix=$prefix/
432fc89c0fbSmrg      done
433fc89c0fbSmrg
434fc89c0fbSmrg      if test -n "$prefixes"; then
43581676fe2Smrg        # Don't fail if two instances are running concurrently.
43681676fe2Smrg        (umask $mkdir_umask &&
43781676fe2Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43881676fe2Smrg          test -d "$dstdir" || exit 1
43981676fe2Smrg        obsolete_mkdir_used=true
440fc89c0fbSmrg      fi
441fc89c0fbSmrg    fi
442fc89c0fbSmrg  fi
443fc89c0fbSmrg
444fc89c0fbSmrg  if test -n "$dir_arg"; then
445fc89c0fbSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446fc89c0fbSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447fc89c0fbSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448fc89c0fbSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449fc89c0fbSmrg  else
450fc89c0fbSmrg
451fc89c0fbSmrg    # Make a couple of temp file names in the proper directory.
452f9c28e31Smrg    dsttmp=${dstdirslash}_inst.$$_
453f9c28e31Smrg    rmtmp=${dstdirslash}_rm.$$_
454fc89c0fbSmrg
455fc89c0fbSmrg    # Trap to clean up those temp files at exit.
456fc89c0fbSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457fc89c0fbSmrg
458fc89c0fbSmrg    # Copy the file name to the temp name.
459f9c28e31Smrg    (umask $cp_umask &&
460f9c28e31Smrg     { test -z "$stripcmd" || {
461f9c28e31Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
462f9c28e31Smrg	 # which would cause strip to fail.
463f9c28e31Smrg	 if test -z "$doit"; then
464f9c28e31Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
465f9c28e31Smrg	 else
466f9c28e31Smrg	   $doit touch "$dsttmp"
467f9c28e31Smrg	 fi
468f9c28e31Smrg       }
469f9c28e31Smrg     } &&
470f9c28e31Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471fc89c0fbSmrg
472fc89c0fbSmrg    # and set any options; do chmod last to preserve setuid bits.
473fc89c0fbSmrg    #
474fc89c0fbSmrg    # If any of these fail, we abort the whole thing.  If we want to
475fc89c0fbSmrg    # ignore errors from any of these, just make sure not to ignore
476fc89c0fbSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477fc89c0fbSmrg    #
47891ec45ceSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
47991ec45ceSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
48091ec45ceSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
48191ec45ceSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
48291ec45ceSmrg
48391ec45ceSmrg    # If -C, don't bother to copy if it wouldn't change the file.
48491ec45ceSmrg    if $copy_on_change &&
48581676fe2Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48681676fe2Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48781676fe2Smrg       set -f &&
48891ec45ceSmrg       set X $old && old=:$2:$4:$5:$6 &&
48991ec45ceSmrg       set X $new && new=:$2:$4:$5:$6 &&
49081676fe2Smrg       set +f &&
49191ec45ceSmrg       test "$old" = "$new" &&
49291ec45ceSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
49391ec45ceSmrg    then
49491ec45ceSmrg      rm -f "$dsttmp"
49591ec45ceSmrg    else
49649bee38cSmrg      # If $backupsuffix is set, and the file being installed
49749bee38cSmrg      # already exists, attempt a backup.  Don't worry if it fails,
49849bee38cSmrg      # e.g., if mv doesn't support -f.
49949bee38cSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
50049bee38cSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
50149bee38cSmrg      fi
50249bee38cSmrg
50391ec45ceSmrg      # Rename the file to the real destination.
50491ec45ceSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
50591ec45ceSmrg
50691ec45ceSmrg      # The rename failed, perhaps because mv can't rename something else
50791ec45ceSmrg      # to itself, or perhaps because mv is so ancient that it does not
50891ec45ceSmrg      # support -f.
50991ec45ceSmrg      {
51081676fe2Smrg        # Now remove or move aside any old file at destination location.
51181676fe2Smrg        # We try this two ways since rm can't unlink itself on some
51281676fe2Smrg        # systems and the destination file might be busy for other
51381676fe2Smrg        # reasons.  In this case, the final cleanup might fail but the new
51481676fe2Smrg        # file should still install successfully.
51581676fe2Smrg        {
51681676fe2Smrg          test ! -f "$dst" ||
51749bee38cSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
51881676fe2Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
51949bee38cSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52081676fe2Smrg          } ||
52181676fe2Smrg          { echo "$0: cannot unlink or rename $dst" >&2
52281676fe2Smrg            (exit 1); exit 1
52381676fe2Smrg          }
52481676fe2Smrg        } &&
52581676fe2Smrg
52681676fe2Smrg        # Now rename the file to the real destination.
52781676fe2Smrg        $doit $mvcmd "$dsttmp" "$dst"
52891ec45ceSmrg      }
52991ec45ceSmrg    fi || exit 1
530fc89c0fbSmrg
531fc89c0fbSmrg    trap '' 0
532fc89c0fbSmrg  fi
533fc89c0fbSmrgdone
534fc89c0fbSmrg
535fc89c0fbSmrg# Local variables:
536f9c28e31Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
537fc89c0fbSmrg# time-stamp-start: "scriptversion="
538fc89c0fbSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
539f9c28e31Smrg# time-stamp-time-zone: "UTC0"
54091ec45ceSmrg# time-stamp-end: "; # UTC"
541fc89c0fbSmrg# End:
542