install-sh revision d075918c
19bd41f2cSmrg#!/bin/sh
29bd41f2cSmrg# install - install a program, script, or datafile
39bd41f2cSmrg
4d075918cSmrgscriptversion=2005-05-14.22
59bd41f2cSmrg
69bd41f2cSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
79bd41f2cSmrg# later released in X11R6 (xc/config/util/install.sh) with the
89bd41f2cSmrg# following copyright and license.
99bd41f2cSmrg#
109bd41f2cSmrg# Copyright (C) 1994 X Consortium
119bd41f2cSmrg#
129bd41f2cSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
139bd41f2cSmrg# of this software and associated documentation files (the "Software"), to
149bd41f2cSmrg# deal in the Software without restriction, including without limitation the
159bd41f2cSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
169bd41f2cSmrg# sell copies of the Software, and to permit persons to whom the Software is
179bd41f2cSmrg# furnished to do so, subject to the following conditions:
189bd41f2cSmrg#
199bd41f2cSmrg# The above copyright notice and this permission notice shall be included in
209bd41f2cSmrg# all copies or substantial portions of the Software.
219bd41f2cSmrg#
229bd41f2cSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
239bd41f2cSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
249bd41f2cSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
259bd41f2cSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
269bd41f2cSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
279bd41f2cSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
289bd41f2cSmrg#
299bd41f2cSmrg# Except as contained in this notice, the name of the X Consortium shall not
309bd41f2cSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
319bd41f2cSmrg# ings in this Software without prior written authorization from the X Consor-
329bd41f2cSmrg# tium.
339bd41f2cSmrg#
349bd41f2cSmrg#
359bd41f2cSmrg# FSF changes to this file are in the public domain.
369bd41f2cSmrg#
379bd41f2cSmrg# Calling this script install-sh is preferred over install.sh, to prevent
389bd41f2cSmrg# `make' implicit rules from creating a file called install from it
399bd41f2cSmrg# when there is no Makefile.
409bd41f2cSmrg#
419bd41f2cSmrg# This script is compatible with the BSD install script, but was written
42d075918cSmrg# from scratch.  It can only install one file at a time, a restriction
43d075918cSmrg# shared with many OS's install programs.
449bd41f2cSmrg
459bd41f2cSmrg# set DOITPROG to echo to test this script
469bd41f2cSmrg
479bd41f2cSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
489bd41f2cSmrgdoit="${DOITPROG-}"
499bd41f2cSmrg
50d075918cSmrg# put in absolute paths if you don't have them in your path; or use env. vars.
519bd41f2cSmrg
529bd41f2cSmrgmvprog="${MVPROG-mv}"
539bd41f2cSmrgcpprog="${CPPROG-cp}"
549bd41f2cSmrgchmodprog="${CHMODPROG-chmod}"
559bd41f2cSmrgchownprog="${CHOWNPROG-chown}"
569bd41f2cSmrgchgrpprog="${CHGRPPROG-chgrp}"
579bd41f2cSmrgstripprog="${STRIPPROG-strip}"
589bd41f2cSmrgrmprog="${RMPROG-rm}"
599bd41f2cSmrgmkdirprog="${MKDIRPROG-mkdir}"
609bd41f2cSmrg
61d075918cSmrgchmodcmd="$chmodprog 0755"
629bd41f2cSmrgchowncmd=
639bd41f2cSmrgchgrpcmd=
649bd41f2cSmrgstripcmd=
659bd41f2cSmrgrmcmd="$rmprog -f"
669bd41f2cSmrgmvcmd="$mvprog"
679bd41f2cSmrgsrc=
689bd41f2cSmrgdst=
699bd41f2cSmrgdir_arg=
709bd41f2cSmrgdstarg=
719bd41f2cSmrgno_target_directory=
729bd41f2cSmrg
739bd41f2cSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
749bd41f2cSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
759bd41f2cSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
769bd41f2cSmrg   or: $0 [OPTION]... -d DIRECTORIES...
779bd41f2cSmrg
789bd41f2cSmrgIn the 1st form, copy SRCFILE to DSTFILE.
799bd41f2cSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
809bd41f2cSmrgIn the 4th, create DIRECTORIES.
819bd41f2cSmrg
829bd41f2cSmrgOptions:
839bd41f2cSmrg-c         (ignored)
849bd41f2cSmrg-d         create directories instead of installing files.
859bd41f2cSmrg-g GROUP   $chgrpprog installed files to GROUP.
869bd41f2cSmrg-m MODE    $chmodprog installed files to MODE.
879bd41f2cSmrg-o USER    $chownprog installed files to USER.
889bd41f2cSmrg-s         $stripprog installed files.
899bd41f2cSmrg-t DIRECTORY  install into DIRECTORY.
909bd41f2cSmrg-T         report an error if DSTFILE is a directory.
919bd41f2cSmrg--help     display this help and exit.
929bd41f2cSmrg--version  display version info and exit.
939bd41f2cSmrg
949bd41f2cSmrgEnvironment variables override the default commands:
959bd41f2cSmrg  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
969bd41f2cSmrg"
979bd41f2cSmrg
98d075918cSmrgwhile test -n "$1"; do
999bd41f2cSmrg  case $1 in
1009bd41f2cSmrg    -c) shift
1019bd41f2cSmrg        continue;;
1029bd41f2cSmrg
1039bd41f2cSmrg    -d) dir_arg=true
1049bd41f2cSmrg        shift
1059bd41f2cSmrg        continue;;
1069bd41f2cSmrg
1079bd41f2cSmrg    -g) chgrpcmd="$chgrpprog $2"
1089bd41f2cSmrg        shift
1099bd41f2cSmrg        shift
1109bd41f2cSmrg        continue;;
1119bd41f2cSmrg
1129bd41f2cSmrg    --help) echo "$usage"; exit $?;;
1139bd41f2cSmrg
114d075918cSmrg    -m) chmodcmd="$chmodprog $2"
1159bd41f2cSmrg        shift
1169bd41f2cSmrg        shift
1179bd41f2cSmrg        continue;;
1189bd41f2cSmrg
1199bd41f2cSmrg    -o) chowncmd="$chownprog $2"
1209bd41f2cSmrg        shift
1219bd41f2cSmrg        shift
1229bd41f2cSmrg        continue;;
1239bd41f2cSmrg
1249bd41f2cSmrg    -s) stripcmd=$stripprog
1259bd41f2cSmrg        shift
1269bd41f2cSmrg        continue;;
1279bd41f2cSmrg
1289bd41f2cSmrg    -t) dstarg=$2
1299bd41f2cSmrg	shift
1309bd41f2cSmrg	shift
1319bd41f2cSmrg	continue;;
1329bd41f2cSmrg
1339bd41f2cSmrg    -T) no_target_directory=true
1349bd41f2cSmrg	shift
1359bd41f2cSmrg	continue;;
1369bd41f2cSmrg
1379bd41f2cSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1389bd41f2cSmrg
139d075918cSmrg    *)  # When -d is used, all remaining arguments are directories to create.
140d075918cSmrg	# When -t is used, the destination is already specified.
141d075918cSmrg	test -n "$dir_arg$dstarg" && break
142d075918cSmrg        # Otherwise, the last argument is the destination.  Remove it from $@.
143d075918cSmrg	for arg
144d075918cSmrg	do
145d075918cSmrg          if test -n "$dstarg"; then
146d075918cSmrg	    # $@ is not empty: it contains at least $arg.
147d075918cSmrg	    set fnord "$@" "$dstarg"
148d075918cSmrg	    shift # fnord
149d075918cSmrg	  fi
150d075918cSmrg	  shift # arg
151d075918cSmrg	  dstarg=$arg
152d075918cSmrg	done
1539bd41f2cSmrg	break;;
1549bd41f2cSmrg  esac
1559bd41f2cSmrgdone
1569bd41f2cSmrg
157d075918cSmrgif test -z "$1"; then
1589bd41f2cSmrg  if test -z "$dir_arg"; then
1599bd41f2cSmrg    echo "$0: no input file specified." >&2
1609bd41f2cSmrg    exit 1
1619bd41f2cSmrg  fi
1629bd41f2cSmrg  # It's OK to call `install-sh -d' without argument.
1639bd41f2cSmrg  # This can happen when creating conditional directories.
1649bd41f2cSmrg  exit 0
1659bd41f2cSmrgfi
1669bd41f2cSmrg
1679bd41f2cSmrgfor src
1689bd41f2cSmrgdo
1699bd41f2cSmrg  # Protect names starting with `-'.
1709bd41f2cSmrg  case $src in
1719bd41f2cSmrg    -*) src=./$src ;;
1729bd41f2cSmrg  esac
1739bd41f2cSmrg
1749bd41f2cSmrg  if test -n "$dir_arg"; then
1759bd41f2cSmrg    dst=$src
176d075918cSmrg    src=
1779bd41f2cSmrg
178d075918cSmrg    if test -d "$dst"; then
179d075918cSmrg      mkdircmd=:
180d075918cSmrg      chmodcmd=
181d075918cSmrg    else
182d075918cSmrg      mkdircmd=$mkdirprog
183d075918cSmrg    fi
184d075918cSmrg  else
1859bd41f2cSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
1869bd41f2cSmrg    # might cause directories to be created, which would be especially bad
1879bd41f2cSmrg    # if $src (and thus $dsttmp) contains '*'.
1889bd41f2cSmrg    if test ! -f "$src" && test ! -d "$src"; then
1899bd41f2cSmrg      echo "$0: $src does not exist." >&2
1909bd41f2cSmrg      exit 1
1919bd41f2cSmrg    fi
1929bd41f2cSmrg
1939bd41f2cSmrg    if test -z "$dstarg"; then
1949bd41f2cSmrg      echo "$0: no destination specified." >&2
1959bd41f2cSmrg      exit 1
1969bd41f2cSmrg    fi
1979bd41f2cSmrg
1989bd41f2cSmrg    dst=$dstarg
1999bd41f2cSmrg    # Protect names starting with `-'.
2009bd41f2cSmrg    case $dst in
2019bd41f2cSmrg      -*) dst=./$dst ;;
2029bd41f2cSmrg    esac
2039bd41f2cSmrg
2049bd41f2cSmrg    # If destination is a directory, append the input filename; won't work
2059bd41f2cSmrg    # if double slashes aren't ignored.
2069bd41f2cSmrg    if test -d "$dst"; then
2079bd41f2cSmrg      if test -n "$no_target_directory"; then
2089bd41f2cSmrg	echo "$0: $dstarg: Is a directory" >&2
2099bd41f2cSmrg	exit 1
2109bd41f2cSmrg      fi
211d075918cSmrg      dst=$dst/`basename "$src"`
2129bd41f2cSmrg    fi
2139bd41f2cSmrg  fi
2149bd41f2cSmrg
215d075918cSmrg  # This sed command emulates the dirname command.
216d075918cSmrg  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
2179bd41f2cSmrg
218d075918cSmrg  # Make sure that the destination directory exists.
219d075918cSmrg
220d075918cSmrg  # Skip lots of stat calls in the usual case.
221d075918cSmrg  if test ! -d "$dstdir"; then
222d075918cSmrg    defaultIFS='
223d075918cSmrg	 '
224d075918cSmrg    IFS="${IFS-$defaultIFS}"
2259bd41f2cSmrg
226d075918cSmrg    oIFS=$IFS
227d075918cSmrg    # Some sh's can't handle IFS=/ for some reason.
228d075918cSmrg    IFS='%'
229d075918cSmrg    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230d075918cSmrg    shift
231d075918cSmrg    IFS=$oIFS
232d075918cSmrg
233d075918cSmrg    pathcomp=
234d075918cSmrg
235d075918cSmrg    while test $# -ne 0 ; do
236d075918cSmrg      pathcomp=$pathcomp$1
2379bd41f2cSmrg      shift
238d075918cSmrg      if test ! -d "$pathcomp"; then
239d075918cSmrg        $mkdirprog "$pathcomp"
240d075918cSmrg	# mkdir can fail with a `File exist' error in case several
241d075918cSmrg	# install-sh are creating the directory concurrently.  This
242d075918cSmrg	# is OK.
243d075918cSmrg	test -d "$pathcomp" || exit
2449bd41f2cSmrg      fi
245d075918cSmrg      pathcomp=$pathcomp/
246d075918cSmrg    done
2479bd41f2cSmrg  fi
2489bd41f2cSmrg
2499bd41f2cSmrg  if test -n "$dir_arg"; then
250d075918cSmrg    $doit $mkdircmd "$dst" \
251d075918cSmrg      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252d075918cSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253d075918cSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254d075918cSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255d075918cSmrg
2569bd41f2cSmrg  else
257d075918cSmrg    dstfile=`basename "$dst"`
2589bd41f2cSmrg
2599bd41f2cSmrg    # Make a couple of temp file names in the proper directory.
2609bd41f2cSmrg    dsttmp=$dstdir/_inst.$$_
2619bd41f2cSmrg    rmtmp=$dstdir/_rm.$$_
2629bd41f2cSmrg
2639bd41f2cSmrg    # Trap to clean up those temp files at exit.
2649bd41f2cSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265d075918cSmrg    trap '(exit $?); exit' 1 2 13 15
2669bd41f2cSmrg
2679bd41f2cSmrg    # Copy the file name to the temp name.
268d075918cSmrg    $doit $cpprog "$src" "$dsttmp" &&
2699bd41f2cSmrg
2709bd41f2cSmrg    # and set any options; do chmod last to preserve setuid bits.
2719bd41f2cSmrg    #
2729bd41f2cSmrg    # If any of these fail, we abort the whole thing.  If we want to
2739bd41f2cSmrg    # ignore errors from any of these, just make sure not to ignore
2749bd41f2cSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
2759bd41f2cSmrg    #
2769bd41f2cSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
2779bd41f2cSmrg      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
2789bd41f2cSmrg      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279d075918cSmrg      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
2809bd41f2cSmrg
2819bd41f2cSmrg    # Now rename the file to the real destination.
282d075918cSmrg    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
2839bd41f2cSmrg      || {
2849bd41f2cSmrg	   # The rename failed, perhaps because mv can't rename something else
2859bd41f2cSmrg	   # to itself, or perhaps because mv is so ancient that it does not
2869bd41f2cSmrg	   # support -f.
2879bd41f2cSmrg
2889bd41f2cSmrg	   # Now remove or move aside any old file at destination location.
2899bd41f2cSmrg	   # We try this two ways since rm can't unlink itself on some
2909bd41f2cSmrg	   # systems and the destination file might be busy for other
2919bd41f2cSmrg	   # reasons.  In this case, the final cleanup might fail but the new
2929bd41f2cSmrg	   # file should still install successfully.
2939bd41f2cSmrg	   {
294d075918cSmrg	     if test -f "$dstdir/$dstfile"; then
295d075918cSmrg	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296d075918cSmrg	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
2979bd41f2cSmrg	       || {
298d075918cSmrg		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
2999bd41f2cSmrg		 (exit 1); exit 1
3009bd41f2cSmrg	       }
3019bd41f2cSmrg	     else
3029bd41f2cSmrg	       :
3039bd41f2cSmrg	     fi
3049bd41f2cSmrg	   } &&
3059bd41f2cSmrg
3069bd41f2cSmrg	   # Now rename the file to the real destination.
307d075918cSmrg	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
3089bd41f2cSmrg	 }
309d075918cSmrg    }
310d075918cSmrg  fi || { (exit 1); exit 1; }
3119bd41f2cSmrgdone
3129bd41f2cSmrg
313d075918cSmrg# The final little trick to "correctly" pass the exit status to the exit trap.
314d075918cSmrg{
315d075918cSmrg  (exit 0); exit 0
316d075918cSmrg}
317d075918cSmrg
3189bd41f2cSmrg# Local variables:
3199bd41f2cSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
3209bd41f2cSmrg# time-stamp-start: "scriptversion="
3219bd41f2cSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
3229bd41f2cSmrg# time-stamp-end: "$"
3239bd41f2cSmrg# End:
324