install-sh revision 1d54945d
11d54945dSmrg#!/bin/sh 21d54945dSmrg# install - install a program, script, or datafile 31d54945dSmrg 41d54945dSmrgscriptversion=2005-05-14.22 51d54945dSmrg 61d54945dSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 71d54945dSmrg# later released in X11R6 (xc/config/util/install.sh) with the 81d54945dSmrg# following copyright and license. 91d54945dSmrg# 101d54945dSmrg# Copyright (C) 1994 X Consortium 111d54945dSmrg# 121d54945dSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 131d54945dSmrg# of this software and associated documentation files (the "Software"), to 141d54945dSmrg# deal in the Software without restriction, including without limitation the 151d54945dSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 161d54945dSmrg# sell copies of the Software, and to permit persons to whom the Software is 171d54945dSmrg# furnished to do so, subject to the following conditions: 181d54945dSmrg# 191d54945dSmrg# The above copyright notice and this permission notice shall be included in 201d54945dSmrg# all copies or substantial portions of the Software. 211d54945dSmrg# 221d54945dSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 231d54945dSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 241d54945dSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 251d54945dSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 261d54945dSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 271d54945dSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 281d54945dSmrg# 291d54945dSmrg# Except as contained in this notice, the name of the X Consortium shall not 301d54945dSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 311d54945dSmrg# ings in this Software without prior written authorization from the X Consor- 321d54945dSmrg# tium. 331d54945dSmrg# 341d54945dSmrg# 351d54945dSmrg# FSF changes to this file are in the public domain. 361d54945dSmrg# 371d54945dSmrg# Calling this script install-sh is preferred over install.sh, to prevent 381d54945dSmrg# `make' implicit rules from creating a file called install from it 391d54945dSmrg# when there is no Makefile. 401d54945dSmrg# 411d54945dSmrg# This script is compatible with the BSD install script, but was written 421d54945dSmrg# from scratch. It can only install one file at a time, a restriction 431d54945dSmrg# shared with many OS's install programs. 441d54945dSmrg 451d54945dSmrg# set DOITPROG to echo to test this script 461d54945dSmrg 471d54945dSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 481d54945dSmrgdoit="${DOITPROG-}" 491d54945dSmrg 501d54945dSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 511d54945dSmrg 521d54945dSmrgmvprog="${MVPROG-mv}" 531d54945dSmrgcpprog="${CPPROG-cp}" 541d54945dSmrgchmodprog="${CHMODPROG-chmod}" 551d54945dSmrgchownprog="${CHOWNPROG-chown}" 561d54945dSmrgchgrpprog="${CHGRPPROG-chgrp}" 571d54945dSmrgstripprog="${STRIPPROG-strip}" 581d54945dSmrgrmprog="${RMPROG-rm}" 591d54945dSmrgmkdirprog="${MKDIRPROG-mkdir}" 601d54945dSmrg 611d54945dSmrgchmodcmd="$chmodprog 0755" 621d54945dSmrgchowncmd= 631d54945dSmrgchgrpcmd= 641d54945dSmrgstripcmd= 651d54945dSmrgrmcmd="$rmprog -f" 661d54945dSmrgmvcmd="$mvprog" 671d54945dSmrgsrc= 681d54945dSmrgdst= 691d54945dSmrgdir_arg= 701d54945dSmrgdstarg= 711d54945dSmrgno_target_directory= 721d54945dSmrg 731d54945dSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 741d54945dSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 751d54945dSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 761d54945dSmrg or: $0 [OPTION]... -d DIRECTORIES... 771d54945dSmrg 781d54945dSmrgIn the 1st form, copy SRCFILE to DSTFILE. 791d54945dSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 801d54945dSmrgIn the 4th, create DIRECTORIES. 811d54945dSmrg 821d54945dSmrgOptions: 831d54945dSmrg-c (ignored) 841d54945dSmrg-d create directories instead of installing files. 851d54945dSmrg-g GROUP $chgrpprog installed files to GROUP. 861d54945dSmrg-m MODE $chmodprog installed files to MODE. 871d54945dSmrg-o USER $chownprog installed files to USER. 881d54945dSmrg-s $stripprog installed files. 891d54945dSmrg-t DIRECTORY install into DIRECTORY. 901d54945dSmrg-T report an error if DSTFILE is a directory. 911d54945dSmrg--help display this help and exit. 921d54945dSmrg--version display version info and exit. 931d54945dSmrg 941d54945dSmrgEnvironment variables override the default commands: 951d54945dSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 961d54945dSmrg" 971d54945dSmrg 981d54945dSmrgwhile test -n "$1"; do 991d54945dSmrg case $1 in 1001d54945dSmrg -c) shift 1011d54945dSmrg continue;; 1021d54945dSmrg 1031d54945dSmrg -d) dir_arg=true 1041d54945dSmrg shift 1051d54945dSmrg continue;; 1061d54945dSmrg 1071d54945dSmrg -g) chgrpcmd="$chgrpprog $2" 1081d54945dSmrg shift 1091d54945dSmrg shift 1101d54945dSmrg continue;; 1111d54945dSmrg 1121d54945dSmrg --help) echo "$usage"; exit $?;; 1131d54945dSmrg 1141d54945dSmrg -m) chmodcmd="$chmodprog $2" 1151d54945dSmrg shift 1161d54945dSmrg shift 1171d54945dSmrg continue;; 1181d54945dSmrg 1191d54945dSmrg -o) chowncmd="$chownprog $2" 1201d54945dSmrg shift 1211d54945dSmrg shift 1221d54945dSmrg continue;; 1231d54945dSmrg 1241d54945dSmrg -s) stripcmd=$stripprog 1251d54945dSmrg shift 1261d54945dSmrg continue;; 1271d54945dSmrg 1281d54945dSmrg -t) dstarg=$2 1291d54945dSmrg shift 1301d54945dSmrg shift 1311d54945dSmrg continue;; 1321d54945dSmrg 1331d54945dSmrg -T) no_target_directory=true 1341d54945dSmrg shift 1351d54945dSmrg continue;; 1361d54945dSmrg 1371d54945dSmrg --version) echo "$0 $scriptversion"; exit $?;; 1381d54945dSmrg 1391d54945dSmrg *) # When -d is used, all remaining arguments are directories to create. 1401d54945dSmrg # When -t is used, the destination is already specified. 1411d54945dSmrg test -n "$dir_arg$dstarg" && break 1421d54945dSmrg # Otherwise, the last argument is the destination. Remove it from $@. 1431d54945dSmrg for arg 1441d54945dSmrg do 1451d54945dSmrg if test -n "$dstarg"; then 1461d54945dSmrg # $@ is not empty: it contains at least $arg. 1471d54945dSmrg set fnord "$@" "$dstarg" 1481d54945dSmrg shift # fnord 1491d54945dSmrg fi 1501d54945dSmrg shift # arg 1511d54945dSmrg dstarg=$arg 1521d54945dSmrg done 1531d54945dSmrg break;; 1541d54945dSmrg esac 1551d54945dSmrgdone 1561d54945dSmrg 1571d54945dSmrgif test -z "$1"; then 1581d54945dSmrg if test -z "$dir_arg"; then 1591d54945dSmrg echo "$0: no input file specified." >&2 1601d54945dSmrg exit 1 1611d54945dSmrg fi 1621d54945dSmrg # It's OK to call `install-sh -d' without argument. 1631d54945dSmrg # This can happen when creating conditional directories. 1641d54945dSmrg exit 0 1651d54945dSmrgfi 1661d54945dSmrg 1671d54945dSmrgfor src 1681d54945dSmrgdo 1691d54945dSmrg # Protect names starting with `-'. 1701d54945dSmrg case $src in 1711d54945dSmrg -*) src=./$src ;; 1721d54945dSmrg esac 1731d54945dSmrg 1741d54945dSmrg if test -n "$dir_arg"; then 1751d54945dSmrg dst=$src 1761d54945dSmrg src= 1771d54945dSmrg 1781d54945dSmrg if test -d "$dst"; then 1791d54945dSmrg mkdircmd=: 1801d54945dSmrg chmodcmd= 1811d54945dSmrg else 1821d54945dSmrg mkdircmd=$mkdirprog 1831d54945dSmrg fi 1841d54945dSmrg else 1851d54945dSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 1861d54945dSmrg # might cause directories to be created, which would be especially bad 1871d54945dSmrg # if $src (and thus $dsttmp) contains '*'. 1881d54945dSmrg if test ! -f "$src" && test ! -d "$src"; then 1891d54945dSmrg echo "$0: $src does not exist." >&2 1901d54945dSmrg exit 1 1911d54945dSmrg fi 1921d54945dSmrg 1931d54945dSmrg if test -z "$dstarg"; then 1941d54945dSmrg echo "$0: no destination specified." >&2 1951d54945dSmrg exit 1 1961d54945dSmrg fi 1971d54945dSmrg 1981d54945dSmrg dst=$dstarg 1991d54945dSmrg # Protect names starting with `-'. 2001d54945dSmrg case $dst in 2011d54945dSmrg -*) dst=./$dst ;; 2021d54945dSmrg esac 2031d54945dSmrg 2041d54945dSmrg # If destination is a directory, append the input filename; won't work 2051d54945dSmrg # if double slashes aren't ignored. 2061d54945dSmrg if test -d "$dst"; then 2071d54945dSmrg if test -n "$no_target_directory"; then 2081d54945dSmrg echo "$0: $dstarg: Is a directory" >&2 2091d54945dSmrg exit 1 2101d54945dSmrg fi 2111d54945dSmrg dst=$dst/`basename "$src"` 2121d54945dSmrg fi 2131d54945dSmrg fi 2141d54945dSmrg 2151d54945dSmrg # This sed command emulates the dirname command. 2161d54945dSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 2171d54945dSmrg 2181d54945dSmrg # Make sure that the destination directory exists. 2191d54945dSmrg 2201d54945dSmrg # Skip lots of stat calls in the usual case. 2211d54945dSmrg if test ! -d "$dstdir"; then 2221d54945dSmrg defaultIFS=' 2231d54945dSmrg ' 2241d54945dSmrg IFS="${IFS-$defaultIFS}" 2251d54945dSmrg 2261d54945dSmrg oIFS=$IFS 2271d54945dSmrg # Some sh's can't handle IFS=/ for some reason. 2281d54945dSmrg IFS='%' 2291d54945dSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 2301d54945dSmrg shift 2311d54945dSmrg IFS=$oIFS 2321d54945dSmrg 2331d54945dSmrg pathcomp= 2341d54945dSmrg 2351d54945dSmrg while test $# -ne 0 ; do 2361d54945dSmrg pathcomp=$pathcomp$1 2371d54945dSmrg shift 2381d54945dSmrg if test ! -d "$pathcomp"; then 2391d54945dSmrg $mkdirprog "$pathcomp" 2401d54945dSmrg # mkdir can fail with a `File exist' error in case several 2411d54945dSmrg # install-sh are creating the directory concurrently. This 2421d54945dSmrg # is OK. 2431d54945dSmrg test -d "$pathcomp" || exit 2441d54945dSmrg fi 2451d54945dSmrg pathcomp=$pathcomp/ 2461d54945dSmrg done 2471d54945dSmrg fi 2481d54945dSmrg 2491d54945dSmrg if test -n "$dir_arg"; then 2501d54945dSmrg $doit $mkdircmd "$dst" \ 2511d54945dSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 2521d54945dSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 2531d54945dSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 2541d54945dSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 2551d54945dSmrg 2561d54945dSmrg else 2571d54945dSmrg dstfile=`basename "$dst"` 2581d54945dSmrg 2591d54945dSmrg # Make a couple of temp file names in the proper directory. 2601d54945dSmrg dsttmp=$dstdir/_inst.$$_ 2611d54945dSmrg rmtmp=$dstdir/_rm.$$_ 2621d54945dSmrg 2631d54945dSmrg # Trap to clean up those temp files at exit. 2641d54945dSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 2651d54945dSmrg trap '(exit $?); exit' 1 2 13 15 2661d54945dSmrg 2671d54945dSmrg # Copy the file name to the temp name. 2681d54945dSmrg $doit $cpprog "$src" "$dsttmp" && 2691d54945dSmrg 2701d54945dSmrg # and set any options; do chmod last to preserve setuid bits. 2711d54945dSmrg # 2721d54945dSmrg # If any of these fail, we abort the whole thing. If we want to 2731d54945dSmrg # ignore errors from any of these, just make sure not to ignore 2741d54945dSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 2751d54945dSmrg # 2761d54945dSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 2771d54945dSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 2781d54945dSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 2791d54945dSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 2801d54945dSmrg 2811d54945dSmrg # Now rename the file to the real destination. 2821d54945dSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 2831d54945dSmrg || { 2841d54945dSmrg # The rename failed, perhaps because mv can't rename something else 2851d54945dSmrg # to itself, or perhaps because mv is so ancient that it does not 2861d54945dSmrg # support -f. 2871d54945dSmrg 2881d54945dSmrg # Now remove or move aside any old file at destination location. 2891d54945dSmrg # We try this two ways since rm can't unlink itself on some 2901d54945dSmrg # systems and the destination file might be busy for other 2911d54945dSmrg # reasons. In this case, the final cleanup might fail but the new 2921d54945dSmrg # file should still install successfully. 2931d54945dSmrg { 2941d54945dSmrg if test -f "$dstdir/$dstfile"; then 2951d54945dSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 2961d54945dSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 2971d54945dSmrg || { 2981d54945dSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2991d54945dSmrg (exit 1); exit 1 3001d54945dSmrg } 3011d54945dSmrg else 3021d54945dSmrg : 3031d54945dSmrg fi 3041d54945dSmrg } && 3051d54945dSmrg 3061d54945dSmrg # Now rename the file to the real destination. 3071d54945dSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 3081d54945dSmrg } 3091d54945dSmrg } 3101d54945dSmrg fi || { (exit 1); exit 1; } 3111d54945dSmrgdone 3121d54945dSmrg 3131d54945dSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 3141d54945dSmrg{ 3151d54945dSmrg (exit 0); exit 0 3161d54945dSmrg} 3171d54945dSmrg 3181d54945dSmrg# Local variables: 3191d54945dSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 3201d54945dSmrg# time-stamp-start: "scriptversion=" 3211d54945dSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 3221d54945dSmrg# time-stamp-end: "$" 3231d54945dSmrg# End: 324