install-sh revision 11d341ca
111d341caSmrg#!/bin/sh 211d341caSmrg# install - install a program, script, or datafile 311d341caSmrg 411d341caSmrgscriptversion=2005-05-14.22 511d341caSmrg 611d341caSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 711d341caSmrg# later released in X11R6 (xc/config/util/install.sh) with the 811d341caSmrg# following copyright and license. 911d341caSmrg# 1011d341caSmrg# Copyright (C) 1994 X Consortium 1111d341caSmrg# 1211d341caSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1311d341caSmrg# of this software and associated documentation files (the "Software"), to 1411d341caSmrg# deal in the Software without restriction, including without limitation the 1511d341caSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1611d341caSmrg# sell copies of the Software, and to permit persons to whom the Software is 1711d341caSmrg# furnished to do so, subject to the following conditions: 1811d341caSmrg# 1911d341caSmrg# The above copyright notice and this permission notice shall be included in 2011d341caSmrg# all copies or substantial portions of the Software. 2111d341caSmrg# 2211d341caSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2311d341caSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2411d341caSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2511d341caSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2611d341caSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2711d341caSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2811d341caSmrg# 2911d341caSmrg# Except as contained in this notice, the name of the X Consortium shall not 3011d341caSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 3111d341caSmrg# ings in this Software without prior written authorization from the X Consor- 3211d341caSmrg# tium. 3311d341caSmrg# 3411d341caSmrg# 3511d341caSmrg# FSF changes to this file are in the public domain. 3611d341caSmrg# 3711d341caSmrg# Calling this script install-sh is preferred over install.sh, to prevent 3811d341caSmrg# `make' implicit rules from creating a file called install from it 3911d341caSmrg# when there is no Makefile. 4011d341caSmrg# 4111d341caSmrg# This script is compatible with the BSD install script, but was written 4211d341caSmrg# from scratch. It can only install one file at a time, a restriction 4311d341caSmrg# shared with many OS's install programs. 4411d341caSmrg 4511d341caSmrg# set DOITPROG to echo to test this script 4611d341caSmrg 4711d341caSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4811d341caSmrgdoit="${DOITPROG-}" 4911d341caSmrg 5011d341caSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 5111d341caSmrg 5211d341caSmrgmvprog="${MVPROG-mv}" 5311d341caSmrgcpprog="${CPPROG-cp}" 5411d341caSmrgchmodprog="${CHMODPROG-chmod}" 5511d341caSmrgchownprog="${CHOWNPROG-chown}" 5611d341caSmrgchgrpprog="${CHGRPPROG-chgrp}" 5711d341caSmrgstripprog="${STRIPPROG-strip}" 5811d341caSmrgrmprog="${RMPROG-rm}" 5911d341caSmrgmkdirprog="${MKDIRPROG-mkdir}" 6011d341caSmrg 6111d341caSmrgchmodcmd="$chmodprog 0755" 6211d341caSmrgchowncmd= 6311d341caSmrgchgrpcmd= 6411d341caSmrgstripcmd= 6511d341caSmrgrmcmd="$rmprog -f" 6611d341caSmrgmvcmd="$mvprog" 6711d341caSmrgsrc= 6811d341caSmrgdst= 6911d341caSmrgdir_arg= 7011d341caSmrgdstarg= 7111d341caSmrgno_target_directory= 7211d341caSmrg 7311d341caSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7411d341caSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7511d341caSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7611d341caSmrg or: $0 [OPTION]... -d DIRECTORIES... 7711d341caSmrg 7811d341caSmrgIn the 1st form, copy SRCFILE to DSTFILE. 7911d341caSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8011d341caSmrgIn the 4th, create DIRECTORIES. 8111d341caSmrg 8211d341caSmrgOptions: 8311d341caSmrg-c (ignored) 8411d341caSmrg-d create directories instead of installing files. 8511d341caSmrg-g GROUP $chgrpprog installed files to GROUP. 8611d341caSmrg-m MODE $chmodprog installed files to MODE. 8711d341caSmrg-o USER $chownprog installed files to USER. 8811d341caSmrg-s $stripprog installed files. 8911d341caSmrg-t DIRECTORY install into DIRECTORY. 9011d341caSmrg-T report an error if DSTFILE is a directory. 9111d341caSmrg--help display this help and exit. 9211d341caSmrg--version display version info and exit. 9311d341caSmrg 9411d341caSmrgEnvironment variables override the default commands: 9511d341caSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9611d341caSmrg" 9711d341caSmrg 9811d341caSmrgwhile test -n "$1"; do 9911d341caSmrg case $1 in 10011d341caSmrg -c) shift 10111d341caSmrg continue;; 10211d341caSmrg 10311d341caSmrg -d) dir_arg=true 10411d341caSmrg shift 10511d341caSmrg continue;; 10611d341caSmrg 10711d341caSmrg -g) chgrpcmd="$chgrpprog $2" 10811d341caSmrg shift 10911d341caSmrg shift 11011d341caSmrg continue;; 11111d341caSmrg 11211d341caSmrg --help) echo "$usage"; exit $?;; 11311d341caSmrg 11411d341caSmrg -m) chmodcmd="$chmodprog $2" 11511d341caSmrg shift 11611d341caSmrg shift 11711d341caSmrg continue;; 11811d341caSmrg 11911d341caSmrg -o) chowncmd="$chownprog $2" 12011d341caSmrg shift 12111d341caSmrg shift 12211d341caSmrg continue;; 12311d341caSmrg 12411d341caSmrg -s) stripcmd=$stripprog 12511d341caSmrg shift 12611d341caSmrg continue;; 12711d341caSmrg 12811d341caSmrg -t) dstarg=$2 12911d341caSmrg shift 13011d341caSmrg shift 13111d341caSmrg continue;; 13211d341caSmrg 13311d341caSmrg -T) no_target_directory=true 13411d341caSmrg shift 13511d341caSmrg continue;; 13611d341caSmrg 13711d341caSmrg --version) echo "$0 $scriptversion"; exit $?;; 13811d341caSmrg 13911d341caSmrg *) # When -d is used, all remaining arguments are directories to create. 14011d341caSmrg # When -t is used, the destination is already specified. 14111d341caSmrg test -n "$dir_arg$dstarg" && break 14211d341caSmrg # Otherwise, the last argument is the destination. Remove it from $@. 14311d341caSmrg for arg 14411d341caSmrg do 14511d341caSmrg if test -n "$dstarg"; then 14611d341caSmrg # $@ is not empty: it contains at least $arg. 14711d341caSmrg set fnord "$@" "$dstarg" 14811d341caSmrg shift # fnord 14911d341caSmrg fi 15011d341caSmrg shift # arg 15111d341caSmrg dstarg=$arg 15211d341caSmrg done 15311d341caSmrg break;; 15411d341caSmrg esac 15511d341caSmrgdone 15611d341caSmrg 15711d341caSmrgif test -z "$1"; then 15811d341caSmrg if test -z "$dir_arg"; then 15911d341caSmrg echo "$0: no input file specified." >&2 16011d341caSmrg exit 1 16111d341caSmrg fi 16211d341caSmrg # It's OK to call `install-sh -d' without argument. 16311d341caSmrg # This can happen when creating conditional directories. 16411d341caSmrg exit 0 16511d341caSmrgfi 16611d341caSmrg 16711d341caSmrgfor src 16811d341caSmrgdo 16911d341caSmrg # Protect names starting with `-'. 17011d341caSmrg case $src in 17111d341caSmrg -*) src=./$src ;; 17211d341caSmrg esac 17311d341caSmrg 17411d341caSmrg if test -n "$dir_arg"; then 17511d341caSmrg dst=$src 17611d341caSmrg src= 17711d341caSmrg 17811d341caSmrg if test -d "$dst"; then 17911d341caSmrg mkdircmd=: 18011d341caSmrg chmodcmd= 18111d341caSmrg else 18211d341caSmrg mkdircmd=$mkdirprog 18311d341caSmrg fi 18411d341caSmrg else 18511d341caSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18611d341caSmrg # might cause directories to be created, which would be especially bad 18711d341caSmrg # if $src (and thus $dsttmp) contains '*'. 18811d341caSmrg if test ! -f "$src" && test ! -d "$src"; then 18911d341caSmrg echo "$0: $src does not exist." >&2 19011d341caSmrg exit 1 19111d341caSmrg fi 19211d341caSmrg 19311d341caSmrg if test -z "$dstarg"; then 19411d341caSmrg echo "$0: no destination specified." >&2 19511d341caSmrg exit 1 19611d341caSmrg fi 19711d341caSmrg 19811d341caSmrg dst=$dstarg 19911d341caSmrg # Protect names starting with `-'. 20011d341caSmrg case $dst in 20111d341caSmrg -*) dst=./$dst ;; 20211d341caSmrg esac 20311d341caSmrg 20411d341caSmrg # If destination is a directory, append the input filename; won't work 20511d341caSmrg # if double slashes aren't ignored. 20611d341caSmrg if test -d "$dst"; then 20711d341caSmrg if test -n "$no_target_directory"; then 20811d341caSmrg echo "$0: $dstarg: Is a directory" >&2 20911d341caSmrg exit 1 21011d341caSmrg fi 21111d341caSmrg dst=$dst/`basename "$src"` 21211d341caSmrg fi 21311d341caSmrg fi 21411d341caSmrg 21511d341caSmrg # This sed command emulates the dirname command. 21611d341caSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21711d341caSmrg 21811d341caSmrg # Make sure that the destination directory exists. 21911d341caSmrg 22011d341caSmrg # Skip lots of stat calls in the usual case. 22111d341caSmrg if test ! -d "$dstdir"; then 22211d341caSmrg defaultIFS=' 22311d341caSmrg ' 22411d341caSmrg IFS="${IFS-$defaultIFS}" 22511d341caSmrg 22611d341caSmrg oIFS=$IFS 22711d341caSmrg # Some sh's can't handle IFS=/ for some reason. 22811d341caSmrg IFS='%' 22911d341caSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23011d341caSmrg shift 23111d341caSmrg IFS=$oIFS 23211d341caSmrg 23311d341caSmrg pathcomp= 23411d341caSmrg 23511d341caSmrg while test $# -ne 0 ; do 23611d341caSmrg pathcomp=$pathcomp$1 23711d341caSmrg shift 23811d341caSmrg if test ! -d "$pathcomp"; then 23911d341caSmrg $mkdirprog "$pathcomp" 24011d341caSmrg # mkdir can fail with a `File exist' error in case several 24111d341caSmrg # install-sh are creating the directory concurrently. This 24211d341caSmrg # is OK. 24311d341caSmrg test -d "$pathcomp" || exit 24411d341caSmrg fi 24511d341caSmrg pathcomp=$pathcomp/ 24611d341caSmrg done 24711d341caSmrg fi 24811d341caSmrg 24911d341caSmrg if test -n "$dir_arg"; then 25011d341caSmrg $doit $mkdircmd "$dst" \ 25111d341caSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 25211d341caSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 25311d341caSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 25411d341caSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25511d341caSmrg 25611d341caSmrg else 25711d341caSmrg dstfile=`basename "$dst"` 25811d341caSmrg 25911d341caSmrg # Make a couple of temp file names in the proper directory. 26011d341caSmrg dsttmp=$dstdir/_inst.$$_ 26111d341caSmrg rmtmp=$dstdir/_rm.$$_ 26211d341caSmrg 26311d341caSmrg # Trap to clean up those temp files at exit. 26411d341caSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 26511d341caSmrg trap '(exit $?); exit' 1 2 13 15 26611d341caSmrg 26711d341caSmrg # Copy the file name to the temp name. 26811d341caSmrg $doit $cpprog "$src" "$dsttmp" && 26911d341caSmrg 27011d341caSmrg # and set any options; do chmod last to preserve setuid bits. 27111d341caSmrg # 27211d341caSmrg # If any of these fail, we abort the whole thing. If we want to 27311d341caSmrg # ignore errors from any of these, just make sure not to ignore 27411d341caSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27511d341caSmrg # 27611d341caSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27711d341caSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 27811d341caSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 27911d341caSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28011d341caSmrg 28111d341caSmrg # Now rename the file to the real destination. 28211d341caSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 28311d341caSmrg || { 28411d341caSmrg # The rename failed, perhaps because mv can't rename something else 28511d341caSmrg # to itself, or perhaps because mv is so ancient that it does not 28611d341caSmrg # support -f. 28711d341caSmrg 28811d341caSmrg # Now remove or move aside any old file at destination location. 28911d341caSmrg # We try this two ways since rm can't unlink itself on some 29011d341caSmrg # systems and the destination file might be busy for other 29111d341caSmrg # reasons. In this case, the final cleanup might fail but the new 29211d341caSmrg # file should still install successfully. 29311d341caSmrg { 29411d341caSmrg if test -f "$dstdir/$dstfile"; then 29511d341caSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29611d341caSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29711d341caSmrg || { 29811d341caSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29911d341caSmrg (exit 1); exit 1 30011d341caSmrg } 30111d341caSmrg else 30211d341caSmrg : 30311d341caSmrg fi 30411d341caSmrg } && 30511d341caSmrg 30611d341caSmrg # Now rename the file to the real destination. 30711d341caSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30811d341caSmrg } 30911d341caSmrg } 31011d341caSmrg fi || { (exit 1); exit 1; } 31111d341caSmrgdone 31211d341caSmrg 31311d341caSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 31411d341caSmrg{ 31511d341caSmrg (exit 0); exit 0 31611d341caSmrg} 31711d341caSmrg 31811d341caSmrg# Local variables: 31911d341caSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32011d341caSmrg# time-stamp-start: "scriptversion=" 32111d341caSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32211d341caSmrg# time-stamp-end: "$" 32311d341caSmrg# End: 324