install-sh revision 14c0a534
114c0a534Smrg#!/bin/sh 214c0a534Smrg# install - install a program, script, or datafile 314c0a534Smrg 414c0a534Smrgscriptversion=2005-05-14.22 514c0a534Smrg 614c0a534Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 714c0a534Smrg# later released in X11R6 (xc/config/util/install.sh) with the 814c0a534Smrg# following copyright and license. 914c0a534Smrg# 1014c0a534Smrg# Copyright (C) 1994 X Consortium 1114c0a534Smrg# 1214c0a534Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1314c0a534Smrg# of this software and associated documentation files (the "Software"), to 1414c0a534Smrg# deal in the Software without restriction, including without limitation the 1514c0a534Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1614c0a534Smrg# sell copies of the Software, and to permit persons to whom the Software is 1714c0a534Smrg# furnished to do so, subject to the following conditions: 1814c0a534Smrg# 1914c0a534Smrg# The above copyright notice and this permission notice shall be included in 2014c0a534Smrg# all copies or substantial portions of the Software. 2114c0a534Smrg# 2214c0a534Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2314c0a534Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2414c0a534Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2514c0a534Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2614c0a534Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2714c0a534Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2814c0a534Smrg# 2914c0a534Smrg# Except as contained in this notice, the name of the X Consortium shall not 3014c0a534Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 3114c0a534Smrg# ings in this Software without prior written authorization from the X Consor- 3214c0a534Smrg# tium. 3314c0a534Smrg# 3414c0a534Smrg# 3514c0a534Smrg# FSF changes to this file are in the public domain. 3614c0a534Smrg# 3714c0a534Smrg# Calling this script install-sh is preferred over install.sh, to prevent 3814c0a534Smrg# `make' implicit rules from creating a file called install from it 3914c0a534Smrg# when there is no Makefile. 4014c0a534Smrg# 4114c0a534Smrg# This script is compatible with the BSD install script, but was written 4214c0a534Smrg# from scratch. It can only install one file at a time, a restriction 4314c0a534Smrg# shared with many OS's install programs. 4414c0a534Smrg 4514c0a534Smrg# set DOITPROG to echo to test this script 4614c0a534Smrg 4714c0a534Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4814c0a534Smrgdoit="${DOITPROG-}" 4914c0a534Smrg 5014c0a534Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 5114c0a534Smrg 5214c0a534Smrgmvprog="${MVPROG-mv}" 5314c0a534Smrgcpprog="${CPPROG-cp}" 5414c0a534Smrgchmodprog="${CHMODPROG-chmod}" 5514c0a534Smrgchownprog="${CHOWNPROG-chown}" 5614c0a534Smrgchgrpprog="${CHGRPPROG-chgrp}" 5714c0a534Smrgstripprog="${STRIPPROG-strip}" 5814c0a534Smrgrmprog="${RMPROG-rm}" 5914c0a534Smrgmkdirprog="${MKDIRPROG-mkdir}" 6014c0a534Smrg 6114c0a534Smrgchmodcmd="$chmodprog 0755" 6214c0a534Smrgchowncmd= 6314c0a534Smrgchgrpcmd= 6414c0a534Smrgstripcmd= 6514c0a534Smrgrmcmd="$rmprog -f" 6614c0a534Smrgmvcmd="$mvprog" 6714c0a534Smrgsrc= 6814c0a534Smrgdst= 6914c0a534Smrgdir_arg= 7014c0a534Smrgdstarg= 7114c0a534Smrgno_target_directory= 7214c0a534Smrg 7314c0a534Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7414c0a534Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7514c0a534Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7614c0a534Smrg or: $0 [OPTION]... -d DIRECTORIES... 7714c0a534Smrg 7814c0a534SmrgIn the 1st form, copy SRCFILE to DSTFILE. 7914c0a534SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8014c0a534SmrgIn the 4th, create DIRECTORIES. 8114c0a534Smrg 8214c0a534SmrgOptions: 8314c0a534Smrg-c (ignored) 8414c0a534Smrg-d create directories instead of installing files. 8514c0a534Smrg-g GROUP $chgrpprog installed files to GROUP. 8614c0a534Smrg-m MODE $chmodprog installed files to MODE. 8714c0a534Smrg-o USER $chownprog installed files to USER. 8814c0a534Smrg-s $stripprog installed files. 8914c0a534Smrg-t DIRECTORY install into DIRECTORY. 9014c0a534Smrg-T report an error if DSTFILE is a directory. 9114c0a534Smrg--help display this help and exit. 9214c0a534Smrg--version display version info and exit. 9314c0a534Smrg 9414c0a534SmrgEnvironment variables override the default commands: 9514c0a534Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9614c0a534Smrg" 9714c0a534Smrg 9814c0a534Smrgwhile test -n "$1"; do 9914c0a534Smrg case $1 in 10014c0a534Smrg -c) shift 10114c0a534Smrg continue;; 10214c0a534Smrg 10314c0a534Smrg -d) dir_arg=true 10414c0a534Smrg shift 10514c0a534Smrg continue;; 10614c0a534Smrg 10714c0a534Smrg -g) chgrpcmd="$chgrpprog $2" 10814c0a534Smrg shift 10914c0a534Smrg shift 11014c0a534Smrg continue;; 11114c0a534Smrg 11214c0a534Smrg --help) echo "$usage"; exit $?;; 11314c0a534Smrg 11414c0a534Smrg -m) chmodcmd="$chmodprog $2" 11514c0a534Smrg shift 11614c0a534Smrg shift 11714c0a534Smrg continue;; 11814c0a534Smrg 11914c0a534Smrg -o) chowncmd="$chownprog $2" 12014c0a534Smrg shift 12114c0a534Smrg shift 12214c0a534Smrg continue;; 12314c0a534Smrg 12414c0a534Smrg -s) stripcmd=$stripprog 12514c0a534Smrg shift 12614c0a534Smrg continue;; 12714c0a534Smrg 12814c0a534Smrg -t) dstarg=$2 12914c0a534Smrg shift 13014c0a534Smrg shift 13114c0a534Smrg continue;; 13214c0a534Smrg 13314c0a534Smrg -T) no_target_directory=true 13414c0a534Smrg shift 13514c0a534Smrg continue;; 13614c0a534Smrg 13714c0a534Smrg --version) echo "$0 $scriptversion"; exit $?;; 13814c0a534Smrg 13914c0a534Smrg *) # When -d is used, all remaining arguments are directories to create. 14014c0a534Smrg # When -t is used, the destination is already specified. 14114c0a534Smrg test -n "$dir_arg$dstarg" && break 14214c0a534Smrg # Otherwise, the last argument is the destination. Remove it from $@. 14314c0a534Smrg for arg 14414c0a534Smrg do 14514c0a534Smrg if test -n "$dstarg"; then 14614c0a534Smrg # $@ is not empty: it contains at least $arg. 14714c0a534Smrg set fnord "$@" "$dstarg" 14814c0a534Smrg shift # fnord 14914c0a534Smrg fi 15014c0a534Smrg shift # arg 15114c0a534Smrg dstarg=$arg 15214c0a534Smrg done 15314c0a534Smrg break;; 15414c0a534Smrg esac 15514c0a534Smrgdone 15614c0a534Smrg 15714c0a534Smrgif test -z "$1"; then 15814c0a534Smrg if test -z "$dir_arg"; then 15914c0a534Smrg echo "$0: no input file specified." >&2 16014c0a534Smrg exit 1 16114c0a534Smrg fi 16214c0a534Smrg # It's OK to call `install-sh -d' without argument. 16314c0a534Smrg # This can happen when creating conditional directories. 16414c0a534Smrg exit 0 16514c0a534Smrgfi 16614c0a534Smrg 16714c0a534Smrgfor src 16814c0a534Smrgdo 16914c0a534Smrg # Protect names starting with `-'. 17014c0a534Smrg case $src in 17114c0a534Smrg -*) src=./$src ;; 17214c0a534Smrg esac 17314c0a534Smrg 17414c0a534Smrg if test -n "$dir_arg"; then 17514c0a534Smrg dst=$src 17614c0a534Smrg src= 17714c0a534Smrg 17814c0a534Smrg if test -d "$dst"; then 17914c0a534Smrg mkdircmd=: 18014c0a534Smrg chmodcmd= 18114c0a534Smrg else 18214c0a534Smrg mkdircmd=$mkdirprog 18314c0a534Smrg fi 18414c0a534Smrg else 18514c0a534Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18614c0a534Smrg # might cause directories to be created, which would be especially bad 18714c0a534Smrg # if $src (and thus $dsttmp) contains '*'. 18814c0a534Smrg if test ! -f "$src" && test ! -d "$src"; then 18914c0a534Smrg echo "$0: $src does not exist." >&2 19014c0a534Smrg exit 1 19114c0a534Smrg fi 19214c0a534Smrg 19314c0a534Smrg if test -z "$dstarg"; then 19414c0a534Smrg echo "$0: no destination specified." >&2 19514c0a534Smrg exit 1 19614c0a534Smrg fi 19714c0a534Smrg 19814c0a534Smrg dst=$dstarg 19914c0a534Smrg # Protect names starting with `-'. 20014c0a534Smrg case $dst in 20114c0a534Smrg -*) dst=./$dst ;; 20214c0a534Smrg esac 20314c0a534Smrg 20414c0a534Smrg # If destination is a directory, append the input filename; won't work 20514c0a534Smrg # if double slashes aren't ignored. 20614c0a534Smrg if test -d "$dst"; then 20714c0a534Smrg if test -n "$no_target_directory"; then 20814c0a534Smrg echo "$0: $dstarg: Is a directory" >&2 20914c0a534Smrg exit 1 21014c0a534Smrg fi 21114c0a534Smrg dst=$dst/`basename "$src"` 21214c0a534Smrg fi 21314c0a534Smrg fi 21414c0a534Smrg 21514c0a534Smrg # This sed command emulates the dirname command. 21614c0a534Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21714c0a534Smrg 21814c0a534Smrg # Make sure that the destination directory exists. 21914c0a534Smrg 22014c0a534Smrg # Skip lots of stat calls in the usual case. 22114c0a534Smrg if test ! -d "$dstdir"; then 22214c0a534Smrg defaultIFS=' 22314c0a534Smrg ' 22414c0a534Smrg IFS="${IFS-$defaultIFS}" 22514c0a534Smrg 22614c0a534Smrg oIFS=$IFS 22714c0a534Smrg # Some sh's can't handle IFS=/ for some reason. 22814c0a534Smrg IFS='%' 22914c0a534Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23014c0a534Smrg shift 23114c0a534Smrg IFS=$oIFS 23214c0a534Smrg 23314c0a534Smrg pathcomp= 23414c0a534Smrg 23514c0a534Smrg while test $# -ne 0 ; do 23614c0a534Smrg pathcomp=$pathcomp$1 23714c0a534Smrg shift 23814c0a534Smrg if test ! -d "$pathcomp"; then 23914c0a534Smrg $mkdirprog "$pathcomp" 24014c0a534Smrg # mkdir can fail with a `File exist' error in case several 24114c0a534Smrg # install-sh are creating the directory concurrently. This 24214c0a534Smrg # is OK. 24314c0a534Smrg test -d "$pathcomp" || exit 24414c0a534Smrg fi 24514c0a534Smrg pathcomp=$pathcomp/ 24614c0a534Smrg done 24714c0a534Smrg fi 24814c0a534Smrg 24914c0a534Smrg if test -n "$dir_arg"; then 25014c0a534Smrg $doit $mkdircmd "$dst" \ 25114c0a534Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 25214c0a534Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 25314c0a534Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 25414c0a534Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25514c0a534Smrg 25614c0a534Smrg else 25714c0a534Smrg dstfile=`basename "$dst"` 25814c0a534Smrg 25914c0a534Smrg # Make a couple of temp file names in the proper directory. 26014c0a534Smrg dsttmp=$dstdir/_inst.$$_ 26114c0a534Smrg rmtmp=$dstdir/_rm.$$_ 26214c0a534Smrg 26314c0a534Smrg # Trap to clean up those temp files at exit. 26414c0a534Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 26514c0a534Smrg trap '(exit $?); exit' 1 2 13 15 26614c0a534Smrg 26714c0a534Smrg # Copy the file name to the temp name. 26814c0a534Smrg $doit $cpprog "$src" "$dsttmp" && 26914c0a534Smrg 27014c0a534Smrg # and set any options; do chmod last to preserve setuid bits. 27114c0a534Smrg # 27214c0a534Smrg # If any of these fail, we abort the whole thing. If we want to 27314c0a534Smrg # ignore errors from any of these, just make sure not to ignore 27414c0a534Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27514c0a534Smrg # 27614c0a534Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27714c0a534Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 27814c0a534Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 27914c0a534Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28014c0a534Smrg 28114c0a534Smrg # Now rename the file to the real destination. 28214c0a534Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 28314c0a534Smrg || { 28414c0a534Smrg # The rename failed, perhaps because mv can't rename something else 28514c0a534Smrg # to itself, or perhaps because mv is so ancient that it does not 28614c0a534Smrg # support -f. 28714c0a534Smrg 28814c0a534Smrg # Now remove or move aside any old file at destination location. 28914c0a534Smrg # We try this two ways since rm can't unlink itself on some 29014c0a534Smrg # systems and the destination file might be busy for other 29114c0a534Smrg # reasons. In this case, the final cleanup might fail but the new 29214c0a534Smrg # file should still install successfully. 29314c0a534Smrg { 29414c0a534Smrg if test -f "$dstdir/$dstfile"; then 29514c0a534Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29614c0a534Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29714c0a534Smrg || { 29814c0a534Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29914c0a534Smrg (exit 1); exit 1 30014c0a534Smrg } 30114c0a534Smrg else 30214c0a534Smrg : 30314c0a534Smrg fi 30414c0a534Smrg } && 30514c0a534Smrg 30614c0a534Smrg # Now rename the file to the real destination. 30714c0a534Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30814c0a534Smrg } 30914c0a534Smrg } 31014c0a534Smrg fi || { (exit 1); exit 1; } 31114c0a534Smrgdone 31214c0a534Smrg 31314c0a534Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 31414c0a534Smrg{ 31514c0a534Smrg (exit 0); exit 0 31614c0a534Smrg} 31714c0a534Smrg 31814c0a534Smrg# Local variables: 31914c0a534Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32014c0a534Smrg# time-stamp-start: "scriptversion=" 32114c0a534Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32214c0a534Smrg# time-stamp-end: "$" 32314c0a534Smrg# End: 324