install-sh revision 44d7874b
144d7874bSmrg#!/bin/sh 244d7874bSmrg# install - install a program, script, or datafile 344d7874bSmrg 444d7874bSmrgscriptversion=2005-05-14.22 544d7874bSmrg 644d7874bSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 744d7874bSmrg# later released in X11R6 (xc/config/util/install.sh) with the 844d7874bSmrg# following copyright and license. 944d7874bSmrg# 1044d7874bSmrg# Copyright (C) 1994 X Consortium 1144d7874bSmrg# 1244d7874bSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1344d7874bSmrg# of this software and associated documentation files (the "Software"), to 1444d7874bSmrg# deal in the Software without restriction, including without limitation the 1544d7874bSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1644d7874bSmrg# sell copies of the Software, and to permit persons to whom the Software is 1744d7874bSmrg# furnished to do so, subject to the following conditions: 1844d7874bSmrg# 1944d7874bSmrg# The above copyright notice and this permission notice shall be included in 2044d7874bSmrg# all copies or substantial portions of the Software. 2144d7874bSmrg# 2244d7874bSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2344d7874bSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2444d7874bSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2544d7874bSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2644d7874bSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2744d7874bSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2844d7874bSmrg# 2944d7874bSmrg# Except as contained in this notice, the name of the X Consortium shall not 3044d7874bSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 3144d7874bSmrg# ings in this Software without prior written authorization from the X Consor- 3244d7874bSmrg# tium. 3344d7874bSmrg# 3444d7874bSmrg# 3544d7874bSmrg# FSF changes to this file are in the public domain. 3644d7874bSmrg# 3744d7874bSmrg# Calling this script install-sh is preferred over install.sh, to prevent 3844d7874bSmrg# `make' implicit rules from creating a file called install from it 3944d7874bSmrg# when there is no Makefile. 4044d7874bSmrg# 4144d7874bSmrg# This script is compatible with the BSD install script, but was written 4244d7874bSmrg# from scratch. It can only install one file at a time, a restriction 4344d7874bSmrg# shared with many OS's install programs. 4444d7874bSmrg 4544d7874bSmrg# set DOITPROG to echo to test this script 4644d7874bSmrg 4744d7874bSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4844d7874bSmrgdoit="${DOITPROG-}" 4944d7874bSmrg 5044d7874bSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 5144d7874bSmrg 5244d7874bSmrgmvprog="${MVPROG-mv}" 5344d7874bSmrgcpprog="${CPPROG-cp}" 5444d7874bSmrgchmodprog="${CHMODPROG-chmod}" 5544d7874bSmrgchownprog="${CHOWNPROG-chown}" 5644d7874bSmrgchgrpprog="${CHGRPPROG-chgrp}" 5744d7874bSmrgstripprog="${STRIPPROG-strip}" 5844d7874bSmrgrmprog="${RMPROG-rm}" 5944d7874bSmrgmkdirprog="${MKDIRPROG-mkdir}" 6044d7874bSmrg 6144d7874bSmrgchmodcmd="$chmodprog 0755" 6244d7874bSmrgchowncmd= 6344d7874bSmrgchgrpcmd= 6444d7874bSmrgstripcmd= 6544d7874bSmrgrmcmd="$rmprog -f" 6644d7874bSmrgmvcmd="$mvprog" 6744d7874bSmrgsrc= 6844d7874bSmrgdst= 6944d7874bSmrgdir_arg= 7044d7874bSmrgdstarg= 7144d7874bSmrgno_target_directory= 7244d7874bSmrg 7344d7874bSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7444d7874bSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7544d7874bSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7644d7874bSmrg or: $0 [OPTION]... -d DIRECTORIES... 7744d7874bSmrg 7844d7874bSmrgIn the 1st form, copy SRCFILE to DSTFILE. 7944d7874bSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8044d7874bSmrgIn the 4th, create DIRECTORIES. 8144d7874bSmrg 8244d7874bSmrgOptions: 8344d7874bSmrg-c (ignored) 8444d7874bSmrg-d create directories instead of installing files. 8544d7874bSmrg-g GROUP $chgrpprog installed files to GROUP. 8644d7874bSmrg-m MODE $chmodprog installed files to MODE. 8744d7874bSmrg-o USER $chownprog installed files to USER. 8844d7874bSmrg-s $stripprog installed files. 8944d7874bSmrg-t DIRECTORY install into DIRECTORY. 9044d7874bSmrg-T report an error if DSTFILE is a directory. 9144d7874bSmrg--help display this help and exit. 9244d7874bSmrg--version display version info and exit. 9344d7874bSmrg 9444d7874bSmrgEnvironment variables override the default commands: 9544d7874bSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9644d7874bSmrg" 9744d7874bSmrg 9844d7874bSmrgwhile test -n "$1"; do 9944d7874bSmrg case $1 in 10044d7874bSmrg -c) shift 10144d7874bSmrg continue;; 10244d7874bSmrg 10344d7874bSmrg -d) dir_arg=true 10444d7874bSmrg shift 10544d7874bSmrg continue;; 10644d7874bSmrg 10744d7874bSmrg -g) chgrpcmd="$chgrpprog $2" 10844d7874bSmrg shift 10944d7874bSmrg shift 11044d7874bSmrg continue;; 11144d7874bSmrg 11244d7874bSmrg --help) echo "$usage"; exit $?;; 11344d7874bSmrg 11444d7874bSmrg -m) chmodcmd="$chmodprog $2" 11544d7874bSmrg shift 11644d7874bSmrg shift 11744d7874bSmrg continue;; 11844d7874bSmrg 11944d7874bSmrg -o) chowncmd="$chownprog $2" 12044d7874bSmrg shift 12144d7874bSmrg shift 12244d7874bSmrg continue;; 12344d7874bSmrg 12444d7874bSmrg -s) stripcmd=$stripprog 12544d7874bSmrg shift 12644d7874bSmrg continue;; 12744d7874bSmrg 12844d7874bSmrg -t) dstarg=$2 12944d7874bSmrg shift 13044d7874bSmrg shift 13144d7874bSmrg continue;; 13244d7874bSmrg 13344d7874bSmrg -T) no_target_directory=true 13444d7874bSmrg shift 13544d7874bSmrg continue;; 13644d7874bSmrg 13744d7874bSmrg --version) echo "$0 $scriptversion"; exit $?;; 13844d7874bSmrg 13944d7874bSmrg *) # When -d is used, all remaining arguments are directories to create. 14044d7874bSmrg # When -t is used, the destination is already specified. 14144d7874bSmrg test -n "$dir_arg$dstarg" && break 14244d7874bSmrg # Otherwise, the last argument is the destination. Remove it from $@. 14344d7874bSmrg for arg 14444d7874bSmrg do 14544d7874bSmrg if test -n "$dstarg"; then 14644d7874bSmrg # $@ is not empty: it contains at least $arg. 14744d7874bSmrg set fnord "$@" "$dstarg" 14844d7874bSmrg shift # fnord 14944d7874bSmrg fi 15044d7874bSmrg shift # arg 15144d7874bSmrg dstarg=$arg 15244d7874bSmrg done 15344d7874bSmrg break;; 15444d7874bSmrg esac 15544d7874bSmrgdone 15644d7874bSmrg 15744d7874bSmrgif test -z "$1"; then 15844d7874bSmrg if test -z "$dir_arg"; then 15944d7874bSmrg echo "$0: no input file specified." >&2 16044d7874bSmrg exit 1 16144d7874bSmrg fi 16244d7874bSmrg # It's OK to call `install-sh -d' without argument. 16344d7874bSmrg # This can happen when creating conditional directories. 16444d7874bSmrg exit 0 16544d7874bSmrgfi 16644d7874bSmrg 16744d7874bSmrgfor src 16844d7874bSmrgdo 16944d7874bSmrg # Protect names starting with `-'. 17044d7874bSmrg case $src in 17144d7874bSmrg -*) src=./$src ;; 17244d7874bSmrg esac 17344d7874bSmrg 17444d7874bSmrg if test -n "$dir_arg"; then 17544d7874bSmrg dst=$src 17644d7874bSmrg src= 17744d7874bSmrg 17844d7874bSmrg if test -d "$dst"; then 17944d7874bSmrg mkdircmd=: 18044d7874bSmrg chmodcmd= 18144d7874bSmrg else 18244d7874bSmrg mkdircmd=$mkdirprog 18344d7874bSmrg fi 18444d7874bSmrg else 18544d7874bSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18644d7874bSmrg # might cause directories to be created, which would be especially bad 18744d7874bSmrg # if $src (and thus $dsttmp) contains '*'. 18844d7874bSmrg if test ! -f "$src" && test ! -d "$src"; then 18944d7874bSmrg echo "$0: $src does not exist." >&2 19044d7874bSmrg exit 1 19144d7874bSmrg fi 19244d7874bSmrg 19344d7874bSmrg if test -z "$dstarg"; then 19444d7874bSmrg echo "$0: no destination specified." >&2 19544d7874bSmrg exit 1 19644d7874bSmrg fi 19744d7874bSmrg 19844d7874bSmrg dst=$dstarg 19944d7874bSmrg # Protect names starting with `-'. 20044d7874bSmrg case $dst in 20144d7874bSmrg -*) dst=./$dst ;; 20244d7874bSmrg esac 20344d7874bSmrg 20444d7874bSmrg # If destination is a directory, append the input filename; won't work 20544d7874bSmrg # if double slashes aren't ignored. 20644d7874bSmrg if test -d "$dst"; then 20744d7874bSmrg if test -n "$no_target_directory"; then 20844d7874bSmrg echo "$0: $dstarg: Is a directory" >&2 20944d7874bSmrg exit 1 21044d7874bSmrg fi 21144d7874bSmrg dst=$dst/`basename "$src"` 21244d7874bSmrg fi 21344d7874bSmrg fi 21444d7874bSmrg 21544d7874bSmrg # This sed command emulates the dirname command. 21644d7874bSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21744d7874bSmrg 21844d7874bSmrg # Make sure that the destination directory exists. 21944d7874bSmrg 22044d7874bSmrg # Skip lots of stat calls in the usual case. 22144d7874bSmrg if test ! -d "$dstdir"; then 22244d7874bSmrg defaultIFS=' 22344d7874bSmrg ' 22444d7874bSmrg IFS="${IFS-$defaultIFS}" 22544d7874bSmrg 22644d7874bSmrg oIFS=$IFS 22744d7874bSmrg # Some sh's can't handle IFS=/ for some reason. 22844d7874bSmrg IFS='%' 22944d7874bSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23044d7874bSmrg shift 23144d7874bSmrg IFS=$oIFS 23244d7874bSmrg 23344d7874bSmrg pathcomp= 23444d7874bSmrg 23544d7874bSmrg while test $# -ne 0 ; do 23644d7874bSmrg pathcomp=$pathcomp$1 23744d7874bSmrg shift 23844d7874bSmrg if test ! -d "$pathcomp"; then 23944d7874bSmrg $mkdirprog "$pathcomp" 24044d7874bSmrg # mkdir can fail with a `File exist' error in case several 24144d7874bSmrg # install-sh are creating the directory concurrently. This 24244d7874bSmrg # is OK. 24344d7874bSmrg test -d "$pathcomp" || exit 24444d7874bSmrg fi 24544d7874bSmrg pathcomp=$pathcomp/ 24644d7874bSmrg done 24744d7874bSmrg fi 24844d7874bSmrg 24944d7874bSmrg if test -n "$dir_arg"; then 25044d7874bSmrg $doit $mkdircmd "$dst" \ 25144d7874bSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 25244d7874bSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 25344d7874bSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 25444d7874bSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25544d7874bSmrg 25644d7874bSmrg else 25744d7874bSmrg dstfile=`basename "$dst"` 25844d7874bSmrg 25944d7874bSmrg # Make a couple of temp file names in the proper directory. 26044d7874bSmrg dsttmp=$dstdir/_inst.$$_ 26144d7874bSmrg rmtmp=$dstdir/_rm.$$_ 26244d7874bSmrg 26344d7874bSmrg # Trap to clean up those temp files at exit. 26444d7874bSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 26544d7874bSmrg trap '(exit $?); exit' 1 2 13 15 26644d7874bSmrg 26744d7874bSmrg # Copy the file name to the temp name. 26844d7874bSmrg $doit $cpprog "$src" "$dsttmp" && 26944d7874bSmrg 27044d7874bSmrg # and set any options; do chmod last to preserve setuid bits. 27144d7874bSmrg # 27244d7874bSmrg # If any of these fail, we abort the whole thing. If we want to 27344d7874bSmrg # ignore errors from any of these, just make sure not to ignore 27444d7874bSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27544d7874bSmrg # 27644d7874bSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27744d7874bSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 27844d7874bSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 27944d7874bSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28044d7874bSmrg 28144d7874bSmrg # Now rename the file to the real destination. 28244d7874bSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 28344d7874bSmrg || { 28444d7874bSmrg # The rename failed, perhaps because mv can't rename something else 28544d7874bSmrg # to itself, or perhaps because mv is so ancient that it does not 28644d7874bSmrg # support -f. 28744d7874bSmrg 28844d7874bSmrg # Now remove or move aside any old file at destination location. 28944d7874bSmrg # We try this two ways since rm can't unlink itself on some 29044d7874bSmrg # systems and the destination file might be busy for other 29144d7874bSmrg # reasons. In this case, the final cleanup might fail but the new 29244d7874bSmrg # file should still install successfully. 29344d7874bSmrg { 29444d7874bSmrg if test -f "$dstdir/$dstfile"; then 29544d7874bSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29644d7874bSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29744d7874bSmrg || { 29844d7874bSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29944d7874bSmrg (exit 1); exit 1 30044d7874bSmrg } 30144d7874bSmrg else 30244d7874bSmrg : 30344d7874bSmrg fi 30444d7874bSmrg } && 30544d7874bSmrg 30644d7874bSmrg # Now rename the file to the real destination. 30744d7874bSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30844d7874bSmrg } 30944d7874bSmrg } 31044d7874bSmrg fi || { (exit 1); exit 1; } 31144d7874bSmrgdone 31244d7874bSmrg 31344d7874bSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 31444d7874bSmrg{ 31544d7874bSmrg (exit 0); exit 0 31644d7874bSmrg} 31744d7874bSmrg 31844d7874bSmrg# Local variables: 31944d7874bSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32044d7874bSmrg# time-stamp-start: "scriptversion=" 32144d7874bSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32244d7874bSmrg# time-stamp-end: "$" 32344d7874bSmrg# End: 324