install-sh revision 0eb10989
10eb10989Smrg#!/bin/sh 20eb10989Smrg# install - install a program, script, or datafile 30eb10989Smrg 40eb10989Smrgscriptversion=2005-05-14.22 50eb10989Smrg 60eb10989Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 70eb10989Smrg# later released in X11R6 (xc/config/util/install.sh) with the 80eb10989Smrg# following copyright and license. 90eb10989Smrg# 100eb10989Smrg# Copyright (C) 1994 X Consortium 110eb10989Smrg# 120eb10989Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 130eb10989Smrg# of this software and associated documentation files (the "Software"), to 140eb10989Smrg# deal in the Software without restriction, including without limitation the 150eb10989Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 160eb10989Smrg# sell copies of the Software, and to permit persons to whom the Software is 170eb10989Smrg# furnished to do so, subject to the following conditions: 180eb10989Smrg# 190eb10989Smrg# The above copyright notice and this permission notice shall be included in 200eb10989Smrg# all copies or substantial portions of the Software. 210eb10989Smrg# 220eb10989Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 230eb10989Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 240eb10989Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 250eb10989Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 260eb10989Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 270eb10989Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 280eb10989Smrg# 290eb10989Smrg# Except as contained in this notice, the name of the X Consortium shall not 300eb10989Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 310eb10989Smrg# ings in this Software without prior written authorization from the X Consor- 320eb10989Smrg# tium. 330eb10989Smrg# 340eb10989Smrg# 350eb10989Smrg# FSF changes to this file are in the public domain. 360eb10989Smrg# 370eb10989Smrg# Calling this script install-sh is preferred over install.sh, to prevent 380eb10989Smrg# `make' implicit rules from creating a file called install from it 390eb10989Smrg# when there is no Makefile. 400eb10989Smrg# 410eb10989Smrg# This script is compatible with the BSD install script, but was written 420eb10989Smrg# from scratch. It can only install one file at a time, a restriction 430eb10989Smrg# shared with many OS's install programs. 440eb10989Smrg 450eb10989Smrg# set DOITPROG to echo to test this script 460eb10989Smrg 470eb10989Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 480eb10989Smrgdoit="${DOITPROG-}" 490eb10989Smrg 500eb10989Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 510eb10989Smrg 520eb10989Smrgmvprog="${MVPROG-mv}" 530eb10989Smrgcpprog="${CPPROG-cp}" 540eb10989Smrgchmodprog="${CHMODPROG-chmod}" 550eb10989Smrgchownprog="${CHOWNPROG-chown}" 560eb10989Smrgchgrpprog="${CHGRPPROG-chgrp}" 570eb10989Smrgstripprog="${STRIPPROG-strip}" 580eb10989Smrgrmprog="${RMPROG-rm}" 590eb10989Smrgmkdirprog="${MKDIRPROG-mkdir}" 600eb10989Smrg 610eb10989Smrgchmodcmd="$chmodprog 0755" 620eb10989Smrgchowncmd= 630eb10989Smrgchgrpcmd= 640eb10989Smrgstripcmd= 650eb10989Smrgrmcmd="$rmprog -f" 660eb10989Smrgmvcmd="$mvprog" 670eb10989Smrgsrc= 680eb10989Smrgdst= 690eb10989Smrgdir_arg= 700eb10989Smrgdstarg= 710eb10989Smrgno_target_directory= 720eb10989Smrg 730eb10989Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 740eb10989Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 750eb10989Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 760eb10989Smrg or: $0 [OPTION]... -d DIRECTORIES... 770eb10989Smrg 780eb10989SmrgIn the 1st form, copy SRCFILE to DSTFILE. 790eb10989SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 800eb10989SmrgIn the 4th, create DIRECTORIES. 810eb10989Smrg 820eb10989SmrgOptions: 830eb10989Smrg-c (ignored) 840eb10989Smrg-d create directories instead of installing files. 850eb10989Smrg-g GROUP $chgrpprog installed files to GROUP. 860eb10989Smrg-m MODE $chmodprog installed files to MODE. 870eb10989Smrg-o USER $chownprog installed files to USER. 880eb10989Smrg-s $stripprog installed files. 890eb10989Smrg-t DIRECTORY install into DIRECTORY. 900eb10989Smrg-T report an error if DSTFILE is a directory. 910eb10989Smrg--help display this help and exit. 920eb10989Smrg--version display version info and exit. 930eb10989Smrg 940eb10989SmrgEnvironment variables override the default commands: 950eb10989Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 960eb10989Smrg" 970eb10989Smrg 980eb10989Smrgwhile test -n "$1"; do 990eb10989Smrg case $1 in 1000eb10989Smrg -c) shift 1010eb10989Smrg continue;; 1020eb10989Smrg 1030eb10989Smrg -d) dir_arg=true 1040eb10989Smrg shift 1050eb10989Smrg continue;; 1060eb10989Smrg 1070eb10989Smrg -g) chgrpcmd="$chgrpprog $2" 1080eb10989Smrg shift 1090eb10989Smrg shift 1100eb10989Smrg continue;; 1110eb10989Smrg 1120eb10989Smrg --help) echo "$usage"; exit $?;; 1130eb10989Smrg 1140eb10989Smrg -m) chmodcmd="$chmodprog $2" 1150eb10989Smrg shift 1160eb10989Smrg shift 1170eb10989Smrg continue;; 1180eb10989Smrg 1190eb10989Smrg -o) chowncmd="$chownprog $2" 1200eb10989Smrg shift 1210eb10989Smrg shift 1220eb10989Smrg continue;; 1230eb10989Smrg 1240eb10989Smrg -s) stripcmd=$stripprog 1250eb10989Smrg shift 1260eb10989Smrg continue;; 1270eb10989Smrg 1280eb10989Smrg -t) dstarg=$2 1290eb10989Smrg shift 1300eb10989Smrg shift 1310eb10989Smrg continue;; 1320eb10989Smrg 1330eb10989Smrg -T) no_target_directory=true 1340eb10989Smrg shift 1350eb10989Smrg continue;; 1360eb10989Smrg 1370eb10989Smrg --version) echo "$0 $scriptversion"; exit $?;; 1380eb10989Smrg 1390eb10989Smrg *) # When -d is used, all remaining arguments are directories to create. 1400eb10989Smrg # When -t is used, the destination is already specified. 1410eb10989Smrg test -n "$dir_arg$dstarg" && break 1420eb10989Smrg # Otherwise, the last argument is the destination. Remove it from $@. 1430eb10989Smrg for arg 1440eb10989Smrg do 1450eb10989Smrg if test -n "$dstarg"; then 1460eb10989Smrg # $@ is not empty: it contains at least $arg. 1470eb10989Smrg set fnord "$@" "$dstarg" 1480eb10989Smrg shift # fnord 1490eb10989Smrg fi 1500eb10989Smrg shift # arg 1510eb10989Smrg dstarg=$arg 1520eb10989Smrg done 1530eb10989Smrg break;; 1540eb10989Smrg esac 1550eb10989Smrgdone 1560eb10989Smrg 1570eb10989Smrgif test -z "$1"; then 1580eb10989Smrg if test -z "$dir_arg"; then 1590eb10989Smrg echo "$0: no input file specified." >&2 1600eb10989Smrg exit 1 1610eb10989Smrg fi 1620eb10989Smrg # It's OK to call `install-sh -d' without argument. 1630eb10989Smrg # This can happen when creating conditional directories. 1640eb10989Smrg exit 0 1650eb10989Smrgfi 1660eb10989Smrg 1670eb10989Smrgfor src 1680eb10989Smrgdo 1690eb10989Smrg # Protect names starting with `-'. 1700eb10989Smrg case $src in 1710eb10989Smrg -*) src=./$src ;; 1720eb10989Smrg esac 1730eb10989Smrg 1740eb10989Smrg if test -n "$dir_arg"; then 1750eb10989Smrg dst=$src 1760eb10989Smrg src= 1770eb10989Smrg 1780eb10989Smrg if test -d "$dst"; then 1790eb10989Smrg mkdircmd=: 1800eb10989Smrg chmodcmd= 1810eb10989Smrg else 1820eb10989Smrg mkdircmd=$mkdirprog 1830eb10989Smrg fi 1840eb10989Smrg else 1850eb10989Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 1860eb10989Smrg # might cause directories to be created, which would be especially bad 1870eb10989Smrg # if $src (and thus $dsttmp) contains '*'. 1880eb10989Smrg if test ! -f "$src" && test ! -d "$src"; then 1890eb10989Smrg echo "$0: $src does not exist." >&2 1900eb10989Smrg exit 1 1910eb10989Smrg fi 1920eb10989Smrg 1930eb10989Smrg if test -z "$dstarg"; then 1940eb10989Smrg echo "$0: no destination specified." >&2 1950eb10989Smrg exit 1 1960eb10989Smrg fi 1970eb10989Smrg 1980eb10989Smrg dst=$dstarg 1990eb10989Smrg # Protect names starting with `-'. 2000eb10989Smrg case $dst in 2010eb10989Smrg -*) dst=./$dst ;; 2020eb10989Smrg esac 2030eb10989Smrg 2040eb10989Smrg # If destination is a directory, append the input filename; won't work 2050eb10989Smrg # if double slashes aren't ignored. 2060eb10989Smrg if test -d "$dst"; then 2070eb10989Smrg if test -n "$no_target_directory"; then 2080eb10989Smrg echo "$0: $dstarg: Is a directory" >&2 2090eb10989Smrg exit 1 2100eb10989Smrg fi 2110eb10989Smrg dst=$dst/`basename "$src"` 2120eb10989Smrg fi 2130eb10989Smrg fi 2140eb10989Smrg 2150eb10989Smrg # This sed command emulates the dirname command. 2160eb10989Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 2170eb10989Smrg 2180eb10989Smrg # Make sure that the destination directory exists. 2190eb10989Smrg 2200eb10989Smrg # Skip lots of stat calls in the usual case. 2210eb10989Smrg if test ! -d "$dstdir"; then 2220eb10989Smrg defaultIFS=' 2230eb10989Smrg ' 2240eb10989Smrg IFS="${IFS-$defaultIFS}" 2250eb10989Smrg 2260eb10989Smrg oIFS=$IFS 2270eb10989Smrg # Some sh's can't handle IFS=/ for some reason. 2280eb10989Smrg IFS='%' 2290eb10989Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 2300eb10989Smrg shift 2310eb10989Smrg IFS=$oIFS 2320eb10989Smrg 2330eb10989Smrg pathcomp= 2340eb10989Smrg 2350eb10989Smrg while test $# -ne 0 ; do 2360eb10989Smrg pathcomp=$pathcomp$1 2370eb10989Smrg shift 2380eb10989Smrg if test ! -d "$pathcomp"; then 2390eb10989Smrg $mkdirprog "$pathcomp" 2400eb10989Smrg # mkdir can fail with a `File exist' error in case several 2410eb10989Smrg # install-sh are creating the directory concurrently. This 2420eb10989Smrg # is OK. 2430eb10989Smrg test -d "$pathcomp" || exit 2440eb10989Smrg fi 2450eb10989Smrg pathcomp=$pathcomp/ 2460eb10989Smrg done 2470eb10989Smrg fi 2480eb10989Smrg 2490eb10989Smrg if test -n "$dir_arg"; then 2500eb10989Smrg $doit $mkdircmd "$dst" \ 2510eb10989Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 2520eb10989Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 2530eb10989Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 2540eb10989Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 2550eb10989Smrg 2560eb10989Smrg else 2570eb10989Smrg dstfile=`basename "$dst"` 2580eb10989Smrg 2590eb10989Smrg # Make a couple of temp file names in the proper directory. 2600eb10989Smrg dsttmp=$dstdir/_inst.$$_ 2610eb10989Smrg rmtmp=$dstdir/_rm.$$_ 2620eb10989Smrg 2630eb10989Smrg # Trap to clean up those temp files at exit. 2640eb10989Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 2650eb10989Smrg trap '(exit $?); exit' 1 2 13 15 2660eb10989Smrg 2670eb10989Smrg # Copy the file name to the temp name. 2680eb10989Smrg $doit $cpprog "$src" "$dsttmp" && 2690eb10989Smrg 2700eb10989Smrg # and set any options; do chmod last to preserve setuid bits. 2710eb10989Smrg # 2720eb10989Smrg # If any of these fail, we abort the whole thing. If we want to 2730eb10989Smrg # ignore errors from any of these, just make sure not to ignore 2740eb10989Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 2750eb10989Smrg # 2760eb10989Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 2770eb10989Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 2780eb10989Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 2790eb10989Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 2800eb10989Smrg 2810eb10989Smrg # Now rename the file to the real destination. 2820eb10989Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 2830eb10989Smrg || { 2840eb10989Smrg # The rename failed, perhaps because mv can't rename something else 2850eb10989Smrg # to itself, or perhaps because mv is so ancient that it does not 2860eb10989Smrg # support -f. 2870eb10989Smrg 2880eb10989Smrg # Now remove or move aside any old file at destination location. 2890eb10989Smrg # We try this two ways since rm can't unlink itself on some 2900eb10989Smrg # systems and the destination file might be busy for other 2910eb10989Smrg # reasons. In this case, the final cleanup might fail but the new 2920eb10989Smrg # file should still install successfully. 2930eb10989Smrg { 2940eb10989Smrg if test -f "$dstdir/$dstfile"; then 2950eb10989Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 2960eb10989Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 2970eb10989Smrg || { 2980eb10989Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2990eb10989Smrg (exit 1); exit 1 3000eb10989Smrg } 3010eb10989Smrg else 3020eb10989Smrg : 3030eb10989Smrg fi 3040eb10989Smrg } && 3050eb10989Smrg 3060eb10989Smrg # Now rename the file to the real destination. 3070eb10989Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 3080eb10989Smrg } 3090eb10989Smrg } 3100eb10989Smrg fi || { (exit 1); exit 1; } 3110eb10989Smrgdone 3120eb10989Smrg 3130eb10989Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 3140eb10989Smrg{ 3150eb10989Smrg (exit 0); exit 0 3160eb10989Smrg} 3170eb10989Smrg 3180eb10989Smrg# Local variables: 3190eb10989Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 3200eb10989Smrg# time-stamp-start: "scriptversion=" 3210eb10989Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 3220eb10989Smrg# time-stamp-end: "$" 3230eb10989Smrg# End: 324