install-sh revision 226fade8
145bc899bSmrg#!/bin/sh 245bc899bSmrg# install - install a program, script, or datafile 345bc899bSmrg 4226fade8Smrgscriptversion=2005-05-14.22 545bc899bSmrg 645bc899bSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 745bc899bSmrg# later released in X11R6 (xc/config/util/install.sh) with the 845bc899bSmrg# following copyright and license. 945bc899bSmrg# 1045bc899bSmrg# Copyright (C) 1994 X Consortium 1145bc899bSmrg# 1245bc899bSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1345bc899bSmrg# of this software and associated documentation files (the "Software"), to 1445bc899bSmrg# deal in the Software without restriction, including without limitation the 1545bc899bSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1645bc899bSmrg# sell copies of the Software, and to permit persons to whom the Software is 1745bc899bSmrg# furnished to do so, subject to the following conditions: 1845bc899bSmrg# 1945bc899bSmrg# The above copyright notice and this permission notice shall be included in 2045bc899bSmrg# all copies or substantial portions of the Software. 2145bc899bSmrg# 2245bc899bSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2345bc899bSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2445bc899bSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2545bc899bSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2645bc899bSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2745bc899bSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2845bc899bSmrg# 2945bc899bSmrg# Except as contained in this notice, the name of the X Consortium shall not 3045bc899bSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 3145bc899bSmrg# ings in this Software without prior written authorization from the X Consor- 3245bc899bSmrg# tium. 3345bc899bSmrg# 3445bc899bSmrg# 3545bc899bSmrg# FSF changes to this file are in the public domain. 3645bc899bSmrg# 3745bc899bSmrg# Calling this script install-sh is preferred over install.sh, to prevent 3845bc899bSmrg# `make' implicit rules from creating a file called install from it 3945bc899bSmrg# when there is no Makefile. 4045bc899bSmrg# 4145bc899bSmrg# This script is compatible with the BSD install script, but was written 42226fade8Smrg# from scratch. It can only install one file at a time, a restriction 43226fade8Smrg# shared with many OS's install programs. 4445bc899bSmrg 4545bc899bSmrg# set DOITPROG to echo to test this script 4645bc899bSmrg 4745bc899bSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48226fade8Smrgdoit="${DOITPROG-}" 4945bc899bSmrg 50226fade8Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 511ac89addSmrg 52226fade8Smrgmvprog="${MVPROG-mv}" 53226fade8Smrgcpprog="${CPPROG-cp}" 54226fade8Smrgchmodprog="${CHMODPROG-chmod}" 55226fade8Smrgchownprog="${CHOWNPROG-chown}" 56226fade8Smrgchgrpprog="${CHGRPPROG-chgrp}" 57226fade8Smrgstripprog="${STRIPPROG-strip}" 58226fade8Smrgrmprog="${RMPROG-rm}" 59226fade8Smrgmkdirprog="${MKDIRPROG-mkdir}" 6045bc899bSmrg 61226fade8Smrgchmodcmd="$chmodprog 0755" 621ac89addSmrgchowncmd= 63226fade8Smrgchgrpcmd= 641ac89addSmrgstripcmd= 65226fade8Smrgrmcmd="$rmprog -f" 66226fade8Smrgmvcmd="$mvprog" 6745bc899bSmrgsrc= 6845bc899bSmrgdst= 6945bc899bSmrgdir_arg= 70226fade8Smrgdstarg= 7145bc899bSmrgno_target_directory= 7245bc899bSmrg 73226fade8Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7445bc899bSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7545bc899bSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7645bc899bSmrg or: $0 [OPTION]... -d DIRECTORIES... 7745bc899bSmrg 7845bc899bSmrgIn the 1st form, copy SRCFILE to DSTFILE. 7945bc899bSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8045bc899bSmrgIn the 4th, create DIRECTORIES. 8145bc899bSmrg 8245bc899bSmrgOptions: 83226fade8Smrg-c (ignored) 84226fade8Smrg-d create directories instead of installing files. 85226fade8Smrg-g GROUP $chgrpprog installed files to GROUP. 86226fade8Smrg-m MODE $chmodprog installed files to MODE. 87226fade8Smrg-o USER $chownprog installed files to USER. 88226fade8Smrg-s $stripprog installed files. 89226fade8Smrg-t DIRECTORY install into DIRECTORY. 90226fade8Smrg-T report an error if DSTFILE is a directory. 91226fade8Smrg--help display this help and exit. 92226fade8Smrg--version display version info and exit. 9345bc899bSmrg 9445bc899bSmrgEnvironment variables override the default commands: 95226fade8Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9645bc899bSmrg" 9745bc899bSmrg 98226fade8Smrgwhile test -n "$1"; do 9945bc899bSmrg case $1 in 100226fade8Smrg -c) shift 101226fade8Smrg continue;; 10245bc899bSmrg 103226fade8Smrg -d) dir_arg=true 104226fade8Smrg shift 105226fade8Smrg continue;; 10645bc899bSmrg 10745bc899bSmrg -g) chgrpcmd="$chgrpprog $2" 108226fade8Smrg shift 109226fade8Smrg shift 110226fade8Smrg continue;; 11145bc899bSmrg 11245bc899bSmrg --help) echo "$usage"; exit $?;; 11345bc899bSmrg 114226fade8Smrg -m) chmodcmd="$chmodprog $2" 115226fade8Smrg shift 116226fade8Smrg shift 117226fade8Smrg continue;; 11845bc899bSmrg 11945bc899bSmrg -o) chowncmd="$chownprog $2" 120226fade8Smrg shift 121226fade8Smrg shift 122226fade8Smrg continue;; 12345bc899bSmrg 124226fade8Smrg -s) stripcmd=$stripprog 125226fade8Smrg shift 126226fade8Smrg continue;; 12745bc899bSmrg 128226fade8Smrg -t) dstarg=$2 129226fade8Smrg shift 130226fade8Smrg shift 131226fade8Smrg continue;; 13245bc899bSmrg 133226fade8Smrg -T) no_target_directory=true 134226fade8Smrg shift 135226fade8Smrg continue;; 13645bc899bSmrg 13745bc899bSmrg --version) echo "$0 $scriptversion"; exit $?;; 13845bc899bSmrg 139226fade8Smrg *) # When -d is used, all remaining arguments are directories to create. 140226fade8Smrg # When -t is used, the destination is already specified. 141226fade8Smrg test -n "$dir_arg$dstarg" && break 142226fade8Smrg # Otherwise, the last argument is the destination. Remove it from $@. 143226fade8Smrg for arg 144226fade8Smrg do 145226fade8Smrg if test -n "$dstarg"; then 146226fade8Smrg # $@ is not empty: it contains at least $arg. 147226fade8Smrg set fnord "$@" "$dstarg" 148226fade8Smrg shift # fnord 149226fade8Smrg fi 150226fade8Smrg shift # arg 151226fade8Smrg dstarg=$arg 152226fade8Smrg done 15345bc899bSmrg break;; 15445bc899bSmrg esac 15545bc899bSmrgdone 15645bc899bSmrg 157226fade8Smrgif test -z "$1"; then 15845bc899bSmrg if test -z "$dir_arg"; then 15945bc899bSmrg echo "$0: no input file specified." >&2 16045bc899bSmrg exit 1 16145bc899bSmrg fi 16245bc899bSmrg # It's OK to call `install-sh -d' without argument. 16345bc899bSmrg # This can happen when creating conditional directories. 16445bc899bSmrg exit 0 16545bc899bSmrgfi 16645bc899bSmrg 16745bc899bSmrgfor src 16845bc899bSmrgdo 16945bc899bSmrg # Protect names starting with `-'. 17045bc899bSmrg case $src in 171226fade8Smrg -*) src=./$src ;; 17245bc899bSmrg esac 17345bc899bSmrg 17445bc899bSmrg if test -n "$dir_arg"; then 17545bc899bSmrg dst=$src 176226fade8Smrg src= 1771ac89addSmrg 178226fade8Smrg if test -d "$dst"; then 179226fade8Smrg mkdircmd=: 180226fade8Smrg chmodcmd= 181226fade8Smrg else 182226fade8Smrg mkdircmd=$mkdirprog 183226fade8Smrg fi 184226fade8Smrg else 18545bc899bSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18645bc899bSmrg # might cause directories to be created, which would be especially bad 18745bc899bSmrg # if $src (and thus $dsttmp) contains '*'. 18845bc899bSmrg if test ! -f "$src" && test ! -d "$src"; then 18945bc899bSmrg echo "$0: $src does not exist." >&2 19045bc899bSmrg exit 1 19145bc899bSmrg fi 19245bc899bSmrg 193226fade8Smrg if test -z "$dstarg"; then 19445bc899bSmrg echo "$0: no destination specified." >&2 19545bc899bSmrg exit 1 19645bc899bSmrg fi 19745bc899bSmrg 198226fade8Smrg dst=$dstarg 19945bc899bSmrg # Protect names starting with `-'. 20045bc899bSmrg case $dst in 201226fade8Smrg -*) dst=./$dst ;; 20245bc899bSmrg esac 20345bc899bSmrg 20445bc899bSmrg # If destination is a directory, append the input filename; won't work 20545bc899bSmrg # if double slashes aren't ignored. 20645bc899bSmrg if test -d "$dst"; then 20745bc899bSmrg if test -n "$no_target_directory"; then 208226fade8Smrg echo "$0: $dstarg: Is a directory" >&2 20945bc899bSmrg exit 1 21045bc899bSmrg fi 211226fade8Smrg dst=$dst/`basename "$src"` 21245bc899bSmrg fi 21345bc899bSmrg fi 21445bc899bSmrg 215226fade8Smrg # This sed command emulates the dirname command. 216226fade8Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21745bc899bSmrg 218226fade8Smrg # Make sure that the destination directory exists. 21945bc899bSmrg 220226fade8Smrg # Skip lots of stat calls in the usual case. 221226fade8Smrg if test ! -d "$dstdir"; then 222226fade8Smrg defaultIFS=' 223226fade8Smrg ' 224226fade8Smrg IFS="${IFS-$defaultIFS}" 22545bc899bSmrg 226226fade8Smrg oIFS=$IFS 227226fade8Smrg # Some sh's can't handle IFS=/ for some reason. 228226fade8Smrg IFS='%' 229226fade8Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230226fade8Smrg shift 231226fade8Smrg IFS=$oIFS 23245bc899bSmrg 233226fade8Smrg pathcomp= 23445bc899bSmrg 235226fade8Smrg while test $# -ne 0 ; do 236226fade8Smrg pathcomp=$pathcomp$1 23745bc899bSmrg shift 238226fade8Smrg if test ! -d "$pathcomp"; then 239226fade8Smrg $mkdirprog "$pathcomp" 240226fade8Smrg # mkdir can fail with a `File exist' error in case several 241226fade8Smrg # install-sh are creating the directory concurrently. This 242226fade8Smrg # is OK. 243226fade8Smrg test -d "$pathcomp" || exit 24445bc899bSmrg fi 245226fade8Smrg pathcomp=$pathcomp/ 246226fade8Smrg done 24745bc899bSmrg fi 24845bc899bSmrg 24945bc899bSmrg if test -n "$dir_arg"; then 250226fade8Smrg $doit $mkdircmd "$dst" \ 251226fade8Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252226fade8Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253226fade8Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254226fade8Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255226fade8Smrg 25645bc899bSmrg else 257226fade8Smrg dstfile=`basename "$dst"` 25845bc899bSmrg 25945bc899bSmrg # Make a couple of temp file names in the proper directory. 26045bc899bSmrg dsttmp=$dstdir/_inst.$$_ 26145bc899bSmrg rmtmp=$dstdir/_rm.$$_ 26245bc899bSmrg 26345bc899bSmrg # Trap to clean up those temp files at exit. 26445bc899bSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265226fade8Smrg trap '(exit $?); exit' 1 2 13 15 26645bc899bSmrg 26745bc899bSmrg # Copy the file name to the temp name. 268226fade8Smrg $doit $cpprog "$src" "$dsttmp" && 26945bc899bSmrg 27045bc899bSmrg # and set any options; do chmod last to preserve setuid bits. 27145bc899bSmrg # 27245bc899bSmrg # If any of these fail, we abort the whole thing. If we want to 27345bc899bSmrg # ignore errors from any of these, just make sure not to ignore 27445bc899bSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27545bc899bSmrg # 276226fade8Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277226fade8Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278226fade8Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279226fade8Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280226fade8Smrg 281226fade8Smrg # Now rename the file to the real destination. 282226fade8Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283226fade8Smrg || { 284226fade8Smrg # The rename failed, perhaps because mv can't rename something else 285226fade8Smrg # to itself, or perhaps because mv is so ancient that it does not 286226fade8Smrg # support -f. 287226fade8Smrg 288226fade8Smrg # Now remove or move aside any old file at destination location. 289226fade8Smrg # We try this two ways since rm can't unlink itself on some 290226fade8Smrg # systems and the destination file might be busy for other 291226fade8Smrg # reasons. In this case, the final cleanup might fail but the new 292226fade8Smrg # file should still install successfully. 293226fade8Smrg { 294226fade8Smrg if test -f "$dstdir/$dstfile"; then 295226fade8Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296226fade8Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297226fade8Smrg || { 298226fade8Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299226fade8Smrg (exit 1); exit 1 300226fade8Smrg } 301226fade8Smrg else 302226fade8Smrg : 303226fade8Smrg fi 304226fade8Smrg } && 305226fade8Smrg 306226fade8Smrg # Now rename the file to the real destination. 307226fade8Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308226fade8Smrg } 309226fade8Smrg } 310226fade8Smrg fi || { (exit 1); exit 1; } 31145bc899bSmrgdone 31245bc899bSmrg 313226fade8Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 314226fade8Smrg{ 315226fade8Smrg (exit 0); exit 0 316226fade8Smrg} 317226fade8Smrg 31845bc899bSmrg# Local variables: 31945bc899bSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32045bc899bSmrg# time-stamp-start: "scriptversion=" 32145bc899bSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32245bc899bSmrg# time-stamp-end: "$" 32345bc899bSmrg# End: 324