install-sh revision 41b2f0bd
141b2f0bdSmrg#!/bin/sh 241b2f0bdSmrg# install - install a program, script, or datafile 341b2f0bdSmrg 441b2f0bdSmrgscriptversion=2005-05-14.22 541b2f0bdSmrg 641b2f0bdSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 741b2f0bdSmrg# later released in X11R6 (xc/config/util/install.sh) with the 841b2f0bdSmrg# following copyright and license. 941b2f0bdSmrg# 1041b2f0bdSmrg# Copyright (C) 1994 X Consortium 1141b2f0bdSmrg# 1241b2f0bdSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1341b2f0bdSmrg# of this software and associated documentation files (the "Software"), to 1441b2f0bdSmrg# deal in the Software without restriction, including without limitation the 1541b2f0bdSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1641b2f0bdSmrg# sell copies of the Software, and to permit persons to whom the Software is 1741b2f0bdSmrg# furnished to do so, subject to the following conditions: 1841b2f0bdSmrg# 1941b2f0bdSmrg# The above copyright notice and this permission notice shall be included in 2041b2f0bdSmrg# all copies or substantial portions of the Software. 2141b2f0bdSmrg# 2241b2f0bdSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2341b2f0bdSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2441b2f0bdSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2541b2f0bdSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2641b2f0bdSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2741b2f0bdSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2841b2f0bdSmrg# 2941b2f0bdSmrg# Except as contained in this notice, the name of the X Consortium shall not 3041b2f0bdSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 3141b2f0bdSmrg# ings in this Software without prior written authorization from the X Consor- 3241b2f0bdSmrg# tium. 3341b2f0bdSmrg# 3441b2f0bdSmrg# 3541b2f0bdSmrg# FSF changes to this file are in the public domain. 3641b2f0bdSmrg# 3741b2f0bdSmrg# Calling this script install-sh is preferred over install.sh, to prevent 3841b2f0bdSmrg# `make' implicit rules from creating a file called install from it 3941b2f0bdSmrg# when there is no Makefile. 4041b2f0bdSmrg# 4141b2f0bdSmrg# This script is compatible with the BSD install script, but was written 4241b2f0bdSmrg# from scratch. It can only install one file at a time, a restriction 4341b2f0bdSmrg# shared with many OS's install programs. 4441b2f0bdSmrg 4541b2f0bdSmrg# set DOITPROG to echo to test this script 4641b2f0bdSmrg 4741b2f0bdSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4841b2f0bdSmrgdoit="${DOITPROG-}" 4941b2f0bdSmrg 5041b2f0bdSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 5141b2f0bdSmrg 5241b2f0bdSmrgmvprog="${MVPROG-mv}" 5341b2f0bdSmrgcpprog="${CPPROG-cp}" 5441b2f0bdSmrgchmodprog="${CHMODPROG-chmod}" 5541b2f0bdSmrgchownprog="${CHOWNPROG-chown}" 5641b2f0bdSmrgchgrpprog="${CHGRPPROG-chgrp}" 5741b2f0bdSmrgstripprog="${STRIPPROG-strip}" 5841b2f0bdSmrgrmprog="${RMPROG-rm}" 5941b2f0bdSmrgmkdirprog="${MKDIRPROG-mkdir}" 6041b2f0bdSmrg 6141b2f0bdSmrgchmodcmd="$chmodprog 0755" 6241b2f0bdSmrgchowncmd= 6341b2f0bdSmrgchgrpcmd= 6441b2f0bdSmrgstripcmd= 6541b2f0bdSmrgrmcmd="$rmprog -f" 6641b2f0bdSmrgmvcmd="$mvprog" 6741b2f0bdSmrgsrc= 6841b2f0bdSmrgdst= 6941b2f0bdSmrgdir_arg= 7041b2f0bdSmrgdstarg= 7141b2f0bdSmrgno_target_directory= 7241b2f0bdSmrg 7341b2f0bdSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 7441b2f0bdSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7541b2f0bdSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 7641b2f0bdSmrg or: $0 [OPTION]... -d DIRECTORIES... 7741b2f0bdSmrg 7841b2f0bdSmrgIn the 1st form, copy SRCFILE to DSTFILE. 7941b2f0bdSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 8041b2f0bdSmrgIn the 4th, create DIRECTORIES. 8141b2f0bdSmrg 8241b2f0bdSmrgOptions: 8341b2f0bdSmrg-c (ignored) 8441b2f0bdSmrg-d create directories instead of installing files. 8541b2f0bdSmrg-g GROUP $chgrpprog installed files to GROUP. 8641b2f0bdSmrg-m MODE $chmodprog installed files to MODE. 8741b2f0bdSmrg-o USER $chownprog installed files to USER. 8841b2f0bdSmrg-s $stripprog installed files. 8941b2f0bdSmrg-t DIRECTORY install into DIRECTORY. 9041b2f0bdSmrg-T report an error if DSTFILE is a directory. 9141b2f0bdSmrg--help display this help and exit. 9241b2f0bdSmrg--version display version info and exit. 9341b2f0bdSmrg 9441b2f0bdSmrgEnvironment variables override the default commands: 9541b2f0bdSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9641b2f0bdSmrg" 9741b2f0bdSmrg 9841b2f0bdSmrgwhile test -n "$1"; do 9941b2f0bdSmrg case $1 in 10041b2f0bdSmrg -c) shift 10141b2f0bdSmrg continue;; 10241b2f0bdSmrg 10341b2f0bdSmrg -d) dir_arg=true 10441b2f0bdSmrg shift 10541b2f0bdSmrg continue;; 10641b2f0bdSmrg 10741b2f0bdSmrg -g) chgrpcmd="$chgrpprog $2" 10841b2f0bdSmrg shift 10941b2f0bdSmrg shift 11041b2f0bdSmrg continue;; 11141b2f0bdSmrg 11241b2f0bdSmrg --help) echo "$usage"; exit $?;; 11341b2f0bdSmrg 11441b2f0bdSmrg -m) chmodcmd="$chmodprog $2" 11541b2f0bdSmrg shift 11641b2f0bdSmrg shift 11741b2f0bdSmrg continue;; 11841b2f0bdSmrg 11941b2f0bdSmrg -o) chowncmd="$chownprog $2" 12041b2f0bdSmrg shift 12141b2f0bdSmrg shift 12241b2f0bdSmrg continue;; 12341b2f0bdSmrg 12441b2f0bdSmrg -s) stripcmd=$stripprog 12541b2f0bdSmrg shift 12641b2f0bdSmrg continue;; 12741b2f0bdSmrg 12841b2f0bdSmrg -t) dstarg=$2 12941b2f0bdSmrg shift 13041b2f0bdSmrg shift 13141b2f0bdSmrg continue;; 13241b2f0bdSmrg 13341b2f0bdSmrg -T) no_target_directory=true 13441b2f0bdSmrg shift 13541b2f0bdSmrg continue;; 13641b2f0bdSmrg 13741b2f0bdSmrg --version) echo "$0 $scriptversion"; exit $?;; 13841b2f0bdSmrg 13941b2f0bdSmrg *) # When -d is used, all remaining arguments are directories to create. 14041b2f0bdSmrg # When -t is used, the destination is already specified. 14141b2f0bdSmrg test -n "$dir_arg$dstarg" && break 14241b2f0bdSmrg # Otherwise, the last argument is the destination. Remove it from $@. 14341b2f0bdSmrg for arg 14441b2f0bdSmrg do 14541b2f0bdSmrg if test -n "$dstarg"; then 14641b2f0bdSmrg # $@ is not empty: it contains at least $arg. 14741b2f0bdSmrg set fnord "$@" "$dstarg" 14841b2f0bdSmrg shift # fnord 14941b2f0bdSmrg fi 15041b2f0bdSmrg shift # arg 15141b2f0bdSmrg dstarg=$arg 15241b2f0bdSmrg done 15341b2f0bdSmrg break;; 15441b2f0bdSmrg esac 15541b2f0bdSmrgdone 15641b2f0bdSmrg 15741b2f0bdSmrgif test -z "$1"; then 15841b2f0bdSmrg if test -z "$dir_arg"; then 15941b2f0bdSmrg echo "$0: no input file specified." >&2 16041b2f0bdSmrg exit 1 16141b2f0bdSmrg fi 16241b2f0bdSmrg # It's OK to call `install-sh -d' without argument. 16341b2f0bdSmrg # This can happen when creating conditional directories. 16441b2f0bdSmrg exit 0 16541b2f0bdSmrgfi 16641b2f0bdSmrg 16741b2f0bdSmrgfor src 16841b2f0bdSmrgdo 16941b2f0bdSmrg # Protect names starting with `-'. 17041b2f0bdSmrg case $src in 17141b2f0bdSmrg -*) src=./$src ;; 17241b2f0bdSmrg esac 17341b2f0bdSmrg 17441b2f0bdSmrg if test -n "$dir_arg"; then 17541b2f0bdSmrg dst=$src 17641b2f0bdSmrg src= 17741b2f0bdSmrg 17841b2f0bdSmrg if test -d "$dst"; then 17941b2f0bdSmrg mkdircmd=: 18041b2f0bdSmrg chmodcmd= 18141b2f0bdSmrg else 18241b2f0bdSmrg mkdircmd=$mkdirprog 18341b2f0bdSmrg fi 18441b2f0bdSmrg else 18541b2f0bdSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18641b2f0bdSmrg # might cause directories to be created, which would be especially bad 18741b2f0bdSmrg # if $src (and thus $dsttmp) contains '*'. 18841b2f0bdSmrg if test ! -f "$src" && test ! -d "$src"; then 18941b2f0bdSmrg echo "$0: $src does not exist." >&2 19041b2f0bdSmrg exit 1 19141b2f0bdSmrg fi 19241b2f0bdSmrg 19341b2f0bdSmrg if test -z "$dstarg"; then 19441b2f0bdSmrg echo "$0: no destination specified." >&2 19541b2f0bdSmrg exit 1 19641b2f0bdSmrg fi 19741b2f0bdSmrg 19841b2f0bdSmrg dst=$dstarg 19941b2f0bdSmrg # Protect names starting with `-'. 20041b2f0bdSmrg case $dst in 20141b2f0bdSmrg -*) dst=./$dst ;; 20241b2f0bdSmrg esac 20341b2f0bdSmrg 20441b2f0bdSmrg # If destination is a directory, append the input filename; won't work 20541b2f0bdSmrg # if double slashes aren't ignored. 20641b2f0bdSmrg if test -d "$dst"; then 20741b2f0bdSmrg if test -n "$no_target_directory"; then 20841b2f0bdSmrg echo "$0: $dstarg: Is a directory" >&2 20941b2f0bdSmrg exit 1 21041b2f0bdSmrg fi 21141b2f0bdSmrg dst=$dst/`basename "$src"` 21241b2f0bdSmrg fi 21341b2f0bdSmrg fi 21441b2f0bdSmrg 21541b2f0bdSmrg # This sed command emulates the dirname command. 21641b2f0bdSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21741b2f0bdSmrg 21841b2f0bdSmrg # Make sure that the destination directory exists. 21941b2f0bdSmrg 22041b2f0bdSmrg # Skip lots of stat calls in the usual case. 22141b2f0bdSmrg if test ! -d "$dstdir"; then 22241b2f0bdSmrg defaultIFS=' 22341b2f0bdSmrg ' 22441b2f0bdSmrg IFS="${IFS-$defaultIFS}" 22541b2f0bdSmrg 22641b2f0bdSmrg oIFS=$IFS 22741b2f0bdSmrg # Some sh's can't handle IFS=/ for some reason. 22841b2f0bdSmrg IFS='%' 22941b2f0bdSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23041b2f0bdSmrg shift 23141b2f0bdSmrg IFS=$oIFS 23241b2f0bdSmrg 23341b2f0bdSmrg pathcomp= 23441b2f0bdSmrg 23541b2f0bdSmrg while test $# -ne 0 ; do 23641b2f0bdSmrg pathcomp=$pathcomp$1 23741b2f0bdSmrg shift 23841b2f0bdSmrg if test ! -d "$pathcomp"; then 23941b2f0bdSmrg $mkdirprog "$pathcomp" 24041b2f0bdSmrg # mkdir can fail with a `File exist' error in case several 24141b2f0bdSmrg # install-sh are creating the directory concurrently. This 24241b2f0bdSmrg # is OK. 24341b2f0bdSmrg test -d "$pathcomp" || exit 24441b2f0bdSmrg fi 24541b2f0bdSmrg pathcomp=$pathcomp/ 24641b2f0bdSmrg done 24741b2f0bdSmrg fi 24841b2f0bdSmrg 24941b2f0bdSmrg if test -n "$dir_arg"; then 25041b2f0bdSmrg $doit $mkdircmd "$dst" \ 25141b2f0bdSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 25241b2f0bdSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 25341b2f0bdSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 25441b2f0bdSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25541b2f0bdSmrg 25641b2f0bdSmrg else 25741b2f0bdSmrg dstfile=`basename "$dst"` 25841b2f0bdSmrg 25941b2f0bdSmrg # Make a couple of temp file names in the proper directory. 26041b2f0bdSmrg dsttmp=$dstdir/_inst.$$_ 26141b2f0bdSmrg rmtmp=$dstdir/_rm.$$_ 26241b2f0bdSmrg 26341b2f0bdSmrg # Trap to clean up those temp files at exit. 26441b2f0bdSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 26541b2f0bdSmrg trap '(exit $?); exit' 1 2 13 15 26641b2f0bdSmrg 26741b2f0bdSmrg # Copy the file name to the temp name. 26841b2f0bdSmrg $doit $cpprog "$src" "$dsttmp" && 26941b2f0bdSmrg 27041b2f0bdSmrg # and set any options; do chmod last to preserve setuid bits. 27141b2f0bdSmrg # 27241b2f0bdSmrg # If any of these fail, we abort the whole thing. If we want to 27341b2f0bdSmrg # ignore errors from any of these, just make sure not to ignore 27441b2f0bdSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 27541b2f0bdSmrg # 27641b2f0bdSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27741b2f0bdSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 27841b2f0bdSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 27941b2f0bdSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28041b2f0bdSmrg 28141b2f0bdSmrg # Now rename the file to the real destination. 28241b2f0bdSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 28341b2f0bdSmrg || { 28441b2f0bdSmrg # The rename failed, perhaps because mv can't rename something else 28541b2f0bdSmrg # to itself, or perhaps because mv is so ancient that it does not 28641b2f0bdSmrg # support -f. 28741b2f0bdSmrg 28841b2f0bdSmrg # Now remove or move aside any old file at destination location. 28941b2f0bdSmrg # We try this two ways since rm can't unlink itself on some 29041b2f0bdSmrg # systems and the destination file might be busy for other 29141b2f0bdSmrg # reasons. In this case, the final cleanup might fail but the new 29241b2f0bdSmrg # file should still install successfully. 29341b2f0bdSmrg { 29441b2f0bdSmrg if test -f "$dstdir/$dstfile"; then 29541b2f0bdSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29641b2f0bdSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29741b2f0bdSmrg || { 29841b2f0bdSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29941b2f0bdSmrg (exit 1); exit 1 30041b2f0bdSmrg } 30141b2f0bdSmrg else 30241b2f0bdSmrg : 30341b2f0bdSmrg fi 30441b2f0bdSmrg } && 30541b2f0bdSmrg 30641b2f0bdSmrg # Now rename the file to the real destination. 30741b2f0bdSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30841b2f0bdSmrg } 30941b2f0bdSmrg } 31041b2f0bdSmrg fi || { (exit 1); exit 1; } 31141b2f0bdSmrgdone 31241b2f0bdSmrg 31341b2f0bdSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 31441b2f0bdSmrg{ 31541b2f0bdSmrg (exit 0); exit 0 31641b2f0bdSmrg} 31741b2f0bdSmrg 31841b2f0bdSmrg# Local variables: 31941b2f0bdSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 32041b2f0bdSmrg# time-stamp-start: "scriptversion=" 32141b2f0bdSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 32241b2f0bdSmrg# time-stamp-end: "$" 32341b2f0bdSmrg# End: 324