install-sh revision 50806d53
150806d53Smrg#!/bin/sh 250806d53Smrg# install - install a program, script, or datafile 350806d53Smrg 450806d53Smrgscriptversion=2005-05-14.22 550806d53Smrg 650806d53Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 750806d53Smrg# later released in X11R6 (xc/config/util/install.sh) with the 850806d53Smrg# following copyright and license. 950806d53Smrg# 1050806d53Smrg# Copyright (C) 1994 X Consortium 1150806d53Smrg# 1250806d53Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1350806d53Smrg# of this software and associated documentation files (the "Software"), to 1450806d53Smrg# deal in the Software without restriction, including without limitation the 1550806d53Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1650806d53Smrg# sell copies of the Software, and to permit persons to whom the Software is 1750806d53Smrg# furnished to do so, subject to the following conditions: 1850806d53Smrg# 1950806d53Smrg# The above copyright notice and this permission notice shall be included in 2050806d53Smrg# all copies or substantial portions of the Software. 2150806d53Smrg# 2250806d53Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2350806d53Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2450806d53Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2550806d53Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2650806d53Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2750806d53Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2850806d53Smrg# 2950806d53Smrg# Except as contained in this notice, the name of the X Consortium shall not 3050806d53Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 3150806d53Smrg# ings in this Software without prior written authorization from the X Consor- 3250806d53Smrg# tium. 3350806d53Smrg# 3450806d53Smrg# 3550806d53Smrg# FSF changes to this file are in the public domain. 3650806d53Smrg# 3750806d53Smrg# Calling this script install-sh is preferred over install.sh, to prevent 3850806d53Smrg# `make' implicit rules from creating a file called install from it 3950806d53Smrg# when there is no Makefile. 4050806d53Smrg# 4150806d53Smrg# This script is compatible with the BSD install script, but was written 4250806d53Smrg# from scratch. It can only install one file at a time, a restriction 4350806d53Smrg# shared with many OS's install programs. 4450806d53Smrg 4550806d53Smrg# set DOITPROG to echo to test this script 4650806d53Smrg 4750806d53Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4850806d53Smrgdoit="${DOITPROG-}" 4950806d53Smrg 5050806d53Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 5150806d53Smrg 5250806d53Smrgmvprog="${MVPROG-mv}" 5350806d53Smrgcpprog="${CPPROG-cp}" 5450806d53Smrgchmodprog="${CHMODPROG-chmod}" 5550806d53Smrgchownprog="${CHOWNPROG-chown}" 5650806d53Smrgchgrpprog="${CHGRPPROG-chgrp}" 5750806d53Smrgstripprog="${STRIPPROG-strip}" 5850806d53Smrgrmprog="${RMPROG-rm}" 5950806d53Smrgmkdirprog="${MKDIRPROG-mkdir}" 6050806d53Smrg 6150806d53Smrgchmodcmd="$chmodprog 0755" 6250806d53Smrgchowncmd= 6350806d53Smrgchgrpcmd= 6450806d53Smrgstripcmd= 6550806d53Smrgrmcmd="$rmprog -f" 6650806d53Smrgmvcmd="$mvprog" 6750806d53Smrgsrc= 6850806d53Smrgdst= 6950806d53Smrgdir_arg= 7050806d53Smrgdstarg= 7150806d53Smrgno_target_directory= 7250806d53Smrg 7350806d53Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7450806d53Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7550806d53Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7650806d53Smrg or: $0 [OPTION]... -d DIRECTORIES... 7750806d53Smrg 7850806d53SmrgIn the 1st form, copy SRCFILE to DSTFILE. 7950806d53SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8050806d53SmrgIn the 4th, create DIRECTORIES. 8150806d53Smrg 8250806d53SmrgOptions: 8350806d53Smrg-c (ignored) 8450806d53Smrg-d create directories instead of installing files. 8550806d53Smrg-g GROUP $chgrpprog installed files to GROUP. 8650806d53Smrg-m MODE $chmodprog installed files to MODE. 8750806d53Smrg-o USER $chownprog installed files to USER. 8850806d53Smrg-s $stripprog installed files. 8950806d53Smrg-t DIRECTORY install into DIRECTORY. 9050806d53Smrg-T report an error if DSTFILE is a directory. 9150806d53Smrg--help display this help and exit. 9250806d53Smrg--version display version info and exit. 9350806d53Smrg 9450806d53SmrgEnvironment variables override the default commands: 9550806d53Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9650806d53Smrg" 9750806d53Smrg 9850806d53Smrgwhile test -n "$1"; do 9950806d53Smrg case $1 in 10050806d53Smrg -c) shift 10150806d53Smrg continue;; 10250806d53Smrg 10350806d53Smrg -d) dir_arg=true 10450806d53Smrg shift 10550806d53Smrg continue;; 10650806d53Smrg 10750806d53Smrg -g) chgrpcmd="$chgrpprog $2" 10850806d53Smrg shift 10950806d53Smrg shift 11050806d53Smrg continue;; 11150806d53Smrg 11250806d53Smrg --help) echo "$usage"; exit $?;; 11350806d53Smrg 11450806d53Smrg -m) chmodcmd="$chmodprog $2" 11550806d53Smrg shift 11650806d53Smrg shift 11750806d53Smrg continue;; 11850806d53Smrg 11950806d53Smrg -o) chowncmd="$chownprog $2" 12050806d53Smrg shift 12150806d53Smrg shift 12250806d53Smrg continue;; 12350806d53Smrg 12450806d53Smrg -s) stripcmd=$stripprog 12550806d53Smrg shift 12650806d53Smrg continue;; 12750806d53Smrg 12850806d53Smrg -t) dstarg=$2 12950806d53Smrg shift 13050806d53Smrg shift 13150806d53Smrg continue;; 13250806d53Smrg 13350806d53Smrg -T) no_target_directory=true 13450806d53Smrg shift 13550806d53Smrg continue;; 13650806d53Smrg 13750806d53Smrg --version) echo "$0 $scriptversion"; exit $?;; 13850806d53Smrg 13950806d53Smrg *) # When -d is used, all remaining arguments are directories to create. 14050806d53Smrg # When -t is used, the destination is already specified. 14150806d53Smrg test -n "$dir_arg$dstarg" && break 14250806d53Smrg # Otherwise, the last argument is the destination. Remove it from $@. 14350806d53Smrg for arg 14450806d53Smrg do 14550806d53Smrg if test -n "$dstarg"; then 14650806d53Smrg # $@ is not empty: it contains at least $arg. 14750806d53Smrg set fnord "$@" "$dstarg" 14850806d53Smrg shift # fnord 14950806d53Smrg fi 15050806d53Smrg shift # arg 15150806d53Smrg dstarg=$arg 15250806d53Smrg done 15350806d53Smrg break;; 15450806d53Smrg esac 15550806d53Smrgdone 15650806d53Smrg 15750806d53Smrgif test -z "$1"; then 15850806d53Smrg if test -z "$dir_arg"; then 15950806d53Smrg echo "$0: no input file specified." >&2 16050806d53Smrg exit 1 16150806d53Smrg fi 16250806d53Smrg # It's OK to call `install-sh -d' without argument. 16350806d53Smrg # This can happen when creating conditional directories. 16450806d53Smrg exit 0 16550806d53Smrgfi 16650806d53Smrg 16750806d53Smrgfor src 16850806d53Smrgdo 16950806d53Smrg # Protect names starting with `-'. 17050806d53Smrg case $src in 17150806d53Smrg -*) src=./$src ;; 17250806d53Smrg esac 17350806d53Smrg 17450806d53Smrg if test -n "$dir_arg"; then 17550806d53Smrg dst=$src 17650806d53Smrg src= 17750806d53Smrg 17850806d53Smrg if test -d "$dst"; then 17950806d53Smrg mkdircmd=: 18050806d53Smrg chmodcmd= 18150806d53Smrg else 18250806d53Smrg mkdircmd=$mkdirprog 18350806d53Smrg fi 18450806d53Smrg else 18550806d53Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18650806d53Smrg # might cause directories to be created, which would be especially bad 18750806d53Smrg # if $src (and thus $dsttmp) contains '*'. 18850806d53Smrg if test ! -f "$src" && test ! -d "$src"; then 18950806d53Smrg echo "$0: $src does not exist." >&2 19050806d53Smrg exit 1 19150806d53Smrg fi 19250806d53Smrg 19350806d53Smrg if test -z "$dstarg"; then 19450806d53Smrg echo "$0: no destination specified." >&2 19550806d53Smrg exit 1 19650806d53Smrg fi 19750806d53Smrg 19850806d53Smrg dst=$dstarg 19950806d53Smrg # Protect names starting with `-'. 20050806d53Smrg case $dst in 20150806d53Smrg -*) dst=./$dst ;; 20250806d53Smrg esac 20350806d53Smrg 20450806d53Smrg # If destination is a directory, append the input filename; won't work 20550806d53Smrg # if double slashes aren't ignored. 20650806d53Smrg if test -d "$dst"; then 20750806d53Smrg if test -n "$no_target_directory"; then 20850806d53Smrg echo "$0: $dstarg: Is a directory" >&2 20950806d53Smrg exit 1 21050806d53Smrg fi 21150806d53Smrg dst=$dst/`basename "$src"` 21250806d53Smrg fi 21350806d53Smrg fi 21450806d53Smrg 21550806d53Smrg # This sed command emulates the dirname command. 21650806d53Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21750806d53Smrg 21850806d53Smrg # Make sure that the destination directory exists. 21950806d53Smrg 22050806d53Smrg # Skip lots of stat calls in the usual case. 22150806d53Smrg if test ! -d "$dstdir"; then 22250806d53Smrg defaultIFS=' 22350806d53Smrg ' 22450806d53Smrg IFS="${IFS-$defaultIFS}" 22550806d53Smrg 22650806d53Smrg oIFS=$IFS 22750806d53Smrg # Some sh's can't handle IFS=/ for some reason. 22850806d53Smrg IFS='%' 22950806d53Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23050806d53Smrg shift 23150806d53Smrg IFS=$oIFS 23250806d53Smrg 23350806d53Smrg pathcomp= 23450806d53Smrg 23550806d53Smrg while test $# -ne 0 ; do 23650806d53Smrg pathcomp=$pathcomp$1 23750806d53Smrg shift 23850806d53Smrg if test ! -d "$pathcomp"; then 23950806d53Smrg $mkdirprog "$pathcomp" 24050806d53Smrg # mkdir can fail with a `File exist' error in case several 24150806d53Smrg # install-sh are creating the directory concurrently. This 24250806d53Smrg # is OK. 24350806d53Smrg test -d "$pathcomp" || exit 24450806d53Smrg fi 24550806d53Smrg pathcomp=$pathcomp/ 24650806d53Smrg done 24750806d53Smrg fi 24850806d53Smrg 24950806d53Smrg if test -n "$dir_arg"; then 25050806d53Smrg $doit $mkdircmd "$dst" \ 25150806d53Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 25250806d53Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 25350806d53Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 25450806d53Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25550806d53Smrg 25650806d53Smrg else 25750806d53Smrg dstfile=`basename "$dst"` 25850806d53Smrg 25950806d53Smrg # Make a couple of temp file names in the proper directory. 26050806d53Smrg dsttmp=$dstdir/_inst.$$_ 26150806d53Smrg rmtmp=$dstdir/_rm.$$_ 26250806d53Smrg 26350806d53Smrg # Trap to clean up those temp files at exit. 26450806d53Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 26550806d53Smrg trap '(exit $?); exit' 1 2 13 15 26650806d53Smrg 26750806d53Smrg # Copy the file name to the temp name. 26850806d53Smrg $doit $cpprog "$src" "$dsttmp" && 26950806d53Smrg 27050806d53Smrg # and set any options; do chmod last to preserve setuid bits. 27150806d53Smrg # 27250806d53Smrg # If any of these fail, we abort the whole thing. If we want to 27350806d53Smrg # ignore errors from any of these, just make sure not to ignore 27450806d53Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27550806d53Smrg # 27650806d53Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27750806d53Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 27850806d53Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 27950806d53Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28050806d53Smrg 28150806d53Smrg # Now rename the file to the real destination. 28250806d53Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 28350806d53Smrg || { 28450806d53Smrg # The rename failed, perhaps because mv can't rename something else 28550806d53Smrg # to itself, or perhaps because mv is so ancient that it does not 28650806d53Smrg # support -f. 28750806d53Smrg 28850806d53Smrg # Now remove or move aside any old file at destination location. 28950806d53Smrg # We try this two ways since rm can't unlink itself on some 29050806d53Smrg # systems and the destination file might be busy for other 29150806d53Smrg # reasons. In this case, the final cleanup might fail but the new 29250806d53Smrg # file should still install successfully. 29350806d53Smrg { 29450806d53Smrg if test -f "$dstdir/$dstfile"; then 29550806d53Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29650806d53Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29750806d53Smrg || { 29850806d53Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29950806d53Smrg (exit 1); exit 1 30050806d53Smrg } 30150806d53Smrg else 30250806d53Smrg : 30350806d53Smrg fi 30450806d53Smrg } && 30550806d53Smrg 30650806d53Smrg # Now rename the file to the real destination. 30750806d53Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30850806d53Smrg } 30950806d53Smrg } 31050806d53Smrg fi || { (exit 1); exit 1; } 31150806d53Smrgdone 31250806d53Smrg 31350806d53Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 31450806d53Smrg{ 31550806d53Smrg (exit 0); exit 0 31650806d53Smrg} 31750806d53Smrg 31850806d53Smrg# Local variables: 31950806d53Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32050806d53Smrg# time-stamp-start: "scriptversion=" 32150806d53Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32250806d53Smrg# time-stamp-end: "$" 32350806d53Smrg# End: 324