install-sh revision 92bb16f8
192bb16f8Smrg#!/bin/sh 292bb16f8Smrg# install - install a program, script, or datafile 392bb16f8Smrg 492bb16f8Smrgscriptversion=2005-05-14.22 592bb16f8Smrg 692bb16f8Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 792bb16f8Smrg# later released in X11R6 (xc/config/util/install.sh) with the 892bb16f8Smrg# following copyright and license. 992bb16f8Smrg# 1092bb16f8Smrg# Copyright (C) 1994 X Consortium 1192bb16f8Smrg# 1292bb16f8Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1392bb16f8Smrg# of this software and associated documentation files (the "Software"), to 1492bb16f8Smrg# deal in the Software without restriction, including without limitation the 1592bb16f8Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1692bb16f8Smrg# sell copies of the Software, and to permit persons to whom the Software is 1792bb16f8Smrg# furnished to do so, subject to the following conditions: 1892bb16f8Smrg# 1992bb16f8Smrg# The above copyright notice and this permission notice shall be included in 2092bb16f8Smrg# all copies or substantial portions of the Software. 2192bb16f8Smrg# 2292bb16f8Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2392bb16f8Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2492bb16f8Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2592bb16f8Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2692bb16f8Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2792bb16f8Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2892bb16f8Smrg# 2992bb16f8Smrg# Except as contained in this notice, the name of the X Consortium shall not 3092bb16f8Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 3192bb16f8Smrg# ings in this Software without prior written authorization from the X Consor- 3292bb16f8Smrg# tium. 3392bb16f8Smrg# 3492bb16f8Smrg# 3592bb16f8Smrg# FSF changes to this file are in the public domain. 3692bb16f8Smrg# 3792bb16f8Smrg# Calling this script install-sh is preferred over install.sh, to prevent 3892bb16f8Smrg# `make' implicit rules from creating a file called install from it 3992bb16f8Smrg# when there is no Makefile. 4092bb16f8Smrg# 4192bb16f8Smrg# This script is compatible with the BSD install script, but was written 4292bb16f8Smrg# from scratch. It can only install one file at a time, a restriction 4392bb16f8Smrg# shared with many OS's install programs. 4492bb16f8Smrg 4592bb16f8Smrg# set DOITPROG to echo to test this script 4692bb16f8Smrg 4792bb16f8Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4892bb16f8Smrgdoit="${DOITPROG-}" 4992bb16f8Smrg 5092bb16f8Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 5192bb16f8Smrg 5292bb16f8Smrgmvprog="${MVPROG-mv}" 5392bb16f8Smrgcpprog="${CPPROG-cp}" 5492bb16f8Smrgchmodprog="${CHMODPROG-chmod}" 5592bb16f8Smrgchownprog="${CHOWNPROG-chown}" 5692bb16f8Smrgchgrpprog="${CHGRPPROG-chgrp}" 5792bb16f8Smrgstripprog="${STRIPPROG-strip}" 5892bb16f8Smrgrmprog="${RMPROG-rm}" 5992bb16f8Smrgmkdirprog="${MKDIRPROG-mkdir}" 6092bb16f8Smrg 6192bb16f8Smrgchmodcmd="$chmodprog 0755" 6292bb16f8Smrgchowncmd= 6392bb16f8Smrgchgrpcmd= 6492bb16f8Smrgstripcmd= 6592bb16f8Smrgrmcmd="$rmprog -f" 6692bb16f8Smrgmvcmd="$mvprog" 6792bb16f8Smrgsrc= 6892bb16f8Smrgdst= 6992bb16f8Smrgdir_arg= 7092bb16f8Smrgdstarg= 7192bb16f8Smrgno_target_directory= 7292bb16f8Smrg 7392bb16f8Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7492bb16f8Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7592bb16f8Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7692bb16f8Smrg or: $0 [OPTION]... -d DIRECTORIES... 7792bb16f8Smrg 7892bb16f8SmrgIn the 1st form, copy SRCFILE to DSTFILE. 7992bb16f8SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8092bb16f8SmrgIn the 4th, create DIRECTORIES. 8192bb16f8Smrg 8292bb16f8SmrgOptions: 8392bb16f8Smrg-c (ignored) 8492bb16f8Smrg-d create directories instead of installing files. 8592bb16f8Smrg-g GROUP $chgrpprog installed files to GROUP. 8692bb16f8Smrg-m MODE $chmodprog installed files to MODE. 8792bb16f8Smrg-o USER $chownprog installed files to USER. 8892bb16f8Smrg-s $stripprog installed files. 8992bb16f8Smrg-t DIRECTORY install into DIRECTORY. 9092bb16f8Smrg-T report an error if DSTFILE is a directory. 9192bb16f8Smrg--help display this help and exit. 9292bb16f8Smrg--version display version info and exit. 9392bb16f8Smrg 9492bb16f8SmrgEnvironment variables override the default commands: 9592bb16f8Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9692bb16f8Smrg" 9792bb16f8Smrg 9892bb16f8Smrgwhile test -n "$1"; do 9992bb16f8Smrg case $1 in 10092bb16f8Smrg -c) shift 10192bb16f8Smrg continue;; 10292bb16f8Smrg 10392bb16f8Smrg -d) dir_arg=true 10492bb16f8Smrg shift 10592bb16f8Smrg continue;; 10692bb16f8Smrg 10792bb16f8Smrg -g) chgrpcmd="$chgrpprog $2" 10892bb16f8Smrg shift 10992bb16f8Smrg shift 11092bb16f8Smrg continue;; 11192bb16f8Smrg 11292bb16f8Smrg --help) echo "$usage"; exit $?;; 11392bb16f8Smrg 11492bb16f8Smrg -m) chmodcmd="$chmodprog $2" 11592bb16f8Smrg shift 11692bb16f8Smrg shift 11792bb16f8Smrg continue;; 11892bb16f8Smrg 11992bb16f8Smrg -o) chowncmd="$chownprog $2" 12092bb16f8Smrg shift 12192bb16f8Smrg shift 12292bb16f8Smrg continue;; 12392bb16f8Smrg 12492bb16f8Smrg -s) stripcmd=$stripprog 12592bb16f8Smrg shift 12692bb16f8Smrg continue;; 12792bb16f8Smrg 12892bb16f8Smrg -t) dstarg=$2 12992bb16f8Smrg shift 13092bb16f8Smrg shift 13192bb16f8Smrg continue;; 13292bb16f8Smrg 13392bb16f8Smrg -T) no_target_directory=true 13492bb16f8Smrg shift 13592bb16f8Smrg continue;; 13692bb16f8Smrg 13792bb16f8Smrg --version) echo "$0 $scriptversion"; exit $?;; 13892bb16f8Smrg 13992bb16f8Smrg *) # When -d is used, all remaining arguments are directories to create. 14092bb16f8Smrg # When -t is used, the destination is already specified. 14192bb16f8Smrg test -n "$dir_arg$dstarg" && break 14292bb16f8Smrg # Otherwise, the last argument is the destination. Remove it from $@. 14392bb16f8Smrg for arg 14492bb16f8Smrg do 14592bb16f8Smrg if test -n "$dstarg"; then 14692bb16f8Smrg # $@ is not empty: it contains at least $arg. 14792bb16f8Smrg set fnord "$@" "$dstarg" 14892bb16f8Smrg shift # fnord 14992bb16f8Smrg fi 15092bb16f8Smrg shift # arg 15192bb16f8Smrg dstarg=$arg 15292bb16f8Smrg done 15392bb16f8Smrg break;; 15492bb16f8Smrg esac 15592bb16f8Smrgdone 15692bb16f8Smrg 15792bb16f8Smrgif test -z "$1"; then 15892bb16f8Smrg if test -z "$dir_arg"; then 15992bb16f8Smrg echo "$0: no input file specified." >&2 16092bb16f8Smrg exit 1 16192bb16f8Smrg fi 16292bb16f8Smrg # It's OK to call `install-sh -d' without argument. 16392bb16f8Smrg # This can happen when creating conditional directories. 16492bb16f8Smrg exit 0 16592bb16f8Smrgfi 16692bb16f8Smrg 16792bb16f8Smrgfor src 16892bb16f8Smrgdo 16992bb16f8Smrg # Protect names starting with `-'. 17092bb16f8Smrg case $src in 17192bb16f8Smrg -*) src=./$src ;; 17292bb16f8Smrg esac 17392bb16f8Smrg 17492bb16f8Smrg if test -n "$dir_arg"; then 17592bb16f8Smrg dst=$src 17692bb16f8Smrg src= 17792bb16f8Smrg 17892bb16f8Smrg if test -d "$dst"; then 17992bb16f8Smrg mkdircmd=: 18092bb16f8Smrg chmodcmd= 18192bb16f8Smrg else 18292bb16f8Smrg mkdircmd=$mkdirprog 18392bb16f8Smrg fi 18492bb16f8Smrg else 18592bb16f8Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18692bb16f8Smrg # might cause directories to be created, which would be especially bad 18792bb16f8Smrg # if $src (and thus $dsttmp) contains '*'. 18892bb16f8Smrg if test ! -f "$src" && test ! -d "$src"; then 18992bb16f8Smrg echo "$0: $src does not exist." >&2 19092bb16f8Smrg exit 1 19192bb16f8Smrg fi 19292bb16f8Smrg 19392bb16f8Smrg if test -z "$dstarg"; then 19492bb16f8Smrg echo "$0: no destination specified." >&2 19592bb16f8Smrg exit 1 19692bb16f8Smrg fi 19792bb16f8Smrg 19892bb16f8Smrg dst=$dstarg 19992bb16f8Smrg # Protect names starting with `-'. 20092bb16f8Smrg case $dst in 20192bb16f8Smrg -*) dst=./$dst ;; 20292bb16f8Smrg esac 20392bb16f8Smrg 20492bb16f8Smrg # If destination is a directory, append the input filename; won't work 20592bb16f8Smrg # if double slashes aren't ignored. 20692bb16f8Smrg if test -d "$dst"; then 20792bb16f8Smrg if test -n "$no_target_directory"; then 20892bb16f8Smrg echo "$0: $dstarg: Is a directory" >&2 20992bb16f8Smrg exit 1 21092bb16f8Smrg fi 21192bb16f8Smrg dst=$dst/`basename "$src"` 21292bb16f8Smrg fi 21392bb16f8Smrg fi 21492bb16f8Smrg 21592bb16f8Smrg # This sed command emulates the dirname command. 21692bb16f8Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21792bb16f8Smrg 21892bb16f8Smrg # Make sure that the destination directory exists. 21992bb16f8Smrg 22092bb16f8Smrg # Skip lots of stat calls in the usual case. 22192bb16f8Smrg if test ! -d "$dstdir"; then 22292bb16f8Smrg defaultIFS=' 22392bb16f8Smrg ' 22492bb16f8Smrg IFS="${IFS-$defaultIFS}" 22592bb16f8Smrg 22692bb16f8Smrg oIFS=$IFS 22792bb16f8Smrg # Some sh's can't handle IFS=/ for some reason. 22892bb16f8Smrg IFS='%' 22992bb16f8Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23092bb16f8Smrg shift 23192bb16f8Smrg IFS=$oIFS 23292bb16f8Smrg 23392bb16f8Smrg pathcomp= 23492bb16f8Smrg 23592bb16f8Smrg while test $# -ne 0 ; do 23692bb16f8Smrg pathcomp=$pathcomp$1 23792bb16f8Smrg shift 23892bb16f8Smrg if test ! -d "$pathcomp"; then 23992bb16f8Smrg $mkdirprog "$pathcomp" 24092bb16f8Smrg # mkdir can fail with a `File exist' error in case several 24192bb16f8Smrg # install-sh are creating the directory concurrently. This 24292bb16f8Smrg # is OK. 24392bb16f8Smrg test -d "$pathcomp" || exit 24492bb16f8Smrg fi 24592bb16f8Smrg pathcomp=$pathcomp/ 24692bb16f8Smrg done 24792bb16f8Smrg fi 24892bb16f8Smrg 24992bb16f8Smrg if test -n "$dir_arg"; then 25092bb16f8Smrg $doit $mkdircmd "$dst" \ 25192bb16f8Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 25292bb16f8Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 25392bb16f8Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 25492bb16f8Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25592bb16f8Smrg 25692bb16f8Smrg else 25792bb16f8Smrg dstfile=`basename "$dst"` 25892bb16f8Smrg 25992bb16f8Smrg # Make a couple of temp file names in the proper directory. 26092bb16f8Smrg dsttmp=$dstdir/_inst.$$_ 26192bb16f8Smrg rmtmp=$dstdir/_rm.$$_ 26292bb16f8Smrg 26392bb16f8Smrg # Trap to clean up those temp files at exit. 26492bb16f8Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 26592bb16f8Smrg trap '(exit $?); exit' 1 2 13 15 26692bb16f8Smrg 26792bb16f8Smrg # Copy the file name to the temp name. 26892bb16f8Smrg $doit $cpprog "$src" "$dsttmp" && 26992bb16f8Smrg 27092bb16f8Smrg # and set any options; do chmod last to preserve setuid bits. 27192bb16f8Smrg # 27292bb16f8Smrg # If any of these fail, we abort the whole thing. If we want to 27392bb16f8Smrg # ignore errors from any of these, just make sure not to ignore 27492bb16f8Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27592bb16f8Smrg # 27692bb16f8Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27792bb16f8Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 27892bb16f8Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 27992bb16f8Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28092bb16f8Smrg 28192bb16f8Smrg # Now rename the file to the real destination. 28292bb16f8Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 28392bb16f8Smrg || { 28492bb16f8Smrg # The rename failed, perhaps because mv can't rename something else 28592bb16f8Smrg # to itself, or perhaps because mv is so ancient that it does not 28692bb16f8Smrg # support -f. 28792bb16f8Smrg 28892bb16f8Smrg # Now remove or move aside any old file at destination location. 28992bb16f8Smrg # We try this two ways since rm can't unlink itself on some 29092bb16f8Smrg # systems and the destination file might be busy for other 29192bb16f8Smrg # reasons. In this case, the final cleanup might fail but the new 29292bb16f8Smrg # file should still install successfully. 29392bb16f8Smrg { 29492bb16f8Smrg if test -f "$dstdir/$dstfile"; then 29592bb16f8Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29692bb16f8Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29792bb16f8Smrg || { 29892bb16f8Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29992bb16f8Smrg (exit 1); exit 1 30092bb16f8Smrg } 30192bb16f8Smrg else 30292bb16f8Smrg : 30392bb16f8Smrg fi 30492bb16f8Smrg } && 30592bb16f8Smrg 30692bb16f8Smrg # Now rename the file to the real destination. 30792bb16f8Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30892bb16f8Smrg } 30992bb16f8Smrg } 31092bb16f8Smrg fi || { (exit 1); exit 1; } 31192bb16f8Smrgdone 31292bb16f8Smrg 31392bb16f8Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 31492bb16f8Smrg{ 31592bb16f8Smrg (exit 0); exit 0 31692bb16f8Smrg} 31792bb16f8Smrg 31892bb16f8Smrg# Local variables: 31992bb16f8Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32092bb16f8Smrg# time-stamp-start: "scriptversion=" 32192bb16f8Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32292bb16f8Smrg# time-stamp-end: "$" 32392bb16f8Smrg# End: 324