install-sh revision 0bd0e222
10bd0e222Smrg#!/bin/sh 20bd0e222Smrg# 30bd0e222Smrg# install - install a program, script, or datafile 40bd0e222Smrg# 50bd0e222Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 60bd0e222Smrg# later released in X11R6 (xc/config/util/install.sh) with the 70bd0e222Smrg# following copyright and license. 80bd0e222Smrg# 90bd0e222Smrg# Copyright (C) 1994 X Consortium 100bd0e222Smrg# 110bd0e222Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 120bd0e222Smrg# of this software and associated documentation files (the "Software"), to 130bd0e222Smrg# deal in the Software without restriction, including without limitation the 140bd0e222Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 150bd0e222Smrg# sell copies of the Software, and to permit persons to whom the Software is 160bd0e222Smrg# furnished to do so, subject to the following conditions: 170bd0e222Smrg# 180bd0e222Smrg# The above copyright notice and this permission notice shall be included in 190bd0e222Smrg# all copies or substantial portions of the Software. 200bd0e222Smrg# 210bd0e222Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 220bd0e222Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 230bd0e222Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 240bd0e222Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 250bd0e222Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 260bd0e222Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 270bd0e222Smrg# 280bd0e222Smrg# Except as contained in this notice, the name of the X Consortium shall not 290bd0e222Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 300bd0e222Smrg# ings in this Software without prior written authorization from the X Consor- 310bd0e222Smrg# tium. 320bd0e222Smrg# 330bd0e222Smrg# 340bd0e222Smrg# FSF changes to this file are in the public domain. 350bd0e222Smrg# 360bd0e222Smrg# Calling this script install-sh is preferred over install.sh, to prevent 370bd0e222Smrg# `make' implicit rules from creating a file called install from it 380bd0e222Smrg# when there is no Makefile. 390bd0e222Smrg# 400bd0e222Smrg# This script is compatible with the BSD install script, but was written 410bd0e222Smrg# from scratch. It can only install one file at a time, a restriction 420bd0e222Smrg# shared with many OS's install programs. 430bd0e222Smrg 440bd0e222Smrg 450bd0e222Smrg# set DOITPROG to echo to test this script 460bd0e222Smrg 470bd0e222Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 480bd0e222Smrgdoit="${DOITPROG-}" 490bd0e222Smrg 500bd0e222Smrg 510bd0e222Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 520bd0e222Smrg 530bd0e222Smrgmvprog="${MVPROG-mv}" 540bd0e222Smrgcpprog="${CPPROG-cp}" 550bd0e222Smrgchmodprog="${CHMODPROG-chmod}" 560bd0e222Smrgchownprog="${CHOWNPROG-chown}" 570bd0e222Smrgchgrpprog="${CHGRPPROG-chgrp}" 580bd0e222Smrgstripprog="${STRIPPROG-strip}" 590bd0e222Smrgrmprog="${RMPROG-rm}" 600bd0e222Smrgmkdirprog="${MKDIRPROG-mkdir}" 610bd0e222Smrg 620bd0e222Smrgtransformbasename="" 630bd0e222Smrgtransform_arg="" 640bd0e222Smrginstcmd="$mvprog" 650bd0e222Smrgchmodcmd="$chmodprog 0755" 660bd0e222Smrgchowncmd="" 670bd0e222Smrgchgrpcmd="" 680bd0e222Smrgstripcmd="" 690bd0e222Smrgrmcmd="$rmprog -f" 700bd0e222Smrgmvcmd="$mvprog" 710bd0e222Smrgsrc="" 720bd0e222Smrgdst="" 730bd0e222Smrgdir_arg="" 740bd0e222Smrg 750bd0e222Smrgwhile [ x"$1" != x ]; do 760bd0e222Smrg case $1 in 770bd0e222Smrg -c) instcmd=$cpprog 780bd0e222Smrg shift 790bd0e222Smrg continue;; 800bd0e222Smrg 810bd0e222Smrg -d) dir_arg=true 820bd0e222Smrg shift 830bd0e222Smrg continue;; 840bd0e222Smrg 850bd0e222Smrg -m) chmodcmd="$chmodprog $2" 860bd0e222Smrg shift 870bd0e222Smrg shift 880bd0e222Smrg continue;; 890bd0e222Smrg 900bd0e222Smrg -o) chowncmd="$chownprog $2" 910bd0e222Smrg shift 920bd0e222Smrg shift 930bd0e222Smrg continue;; 940bd0e222Smrg 950bd0e222Smrg -g) chgrpcmd="$chgrpprog $2" 960bd0e222Smrg shift 970bd0e222Smrg shift 980bd0e222Smrg continue;; 990bd0e222Smrg 1000bd0e222Smrg -s) stripcmd=$stripprog 1010bd0e222Smrg shift 1020bd0e222Smrg continue;; 1030bd0e222Smrg 1040bd0e222Smrg -t=*) transformarg=`echo $1 | sed 's/-t=//'` 1050bd0e222Smrg shift 1060bd0e222Smrg continue;; 1070bd0e222Smrg 1080bd0e222Smrg -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 1090bd0e222Smrg shift 1100bd0e222Smrg continue;; 1110bd0e222Smrg 1120bd0e222Smrg *) if [ x"$src" = x ] 1130bd0e222Smrg then 1140bd0e222Smrg src=$1 1150bd0e222Smrg else 1160bd0e222Smrg # this colon is to work around a 386BSD /bin/sh bug 1170bd0e222Smrg : 1180bd0e222Smrg dst=$1 1190bd0e222Smrg fi 1200bd0e222Smrg shift 1210bd0e222Smrg continue;; 1220bd0e222Smrg esac 1230bd0e222Smrgdone 1240bd0e222Smrg 1250bd0e222Smrgif [ x"$src" = x ] 1260bd0e222Smrgthen 1270bd0e222Smrg echo "$0: no input file specified" >&2 1280bd0e222Smrg exit 1 1290bd0e222Smrgelse 1300bd0e222Smrg : 1310bd0e222Smrgfi 1320bd0e222Smrg 1330bd0e222Smrgif [ x"$dir_arg" != x ]; then 1340bd0e222Smrg dst=$src 1350bd0e222Smrg src="" 1360bd0e222Smrg 1370bd0e222Smrg if [ -d "$dst" ]; then 1380bd0e222Smrg instcmd=: 1390bd0e222Smrg chmodcmd="" 1400bd0e222Smrg else 1410bd0e222Smrg instcmd=$mkdirprog 1420bd0e222Smrg fi 1430bd0e222Smrgelse 1440bd0e222Smrg 1450bd0e222Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 1460bd0e222Smrg# might cause directories to be created, which would be especially bad 1470bd0e222Smrg# if $src (and thus $dsttmp) contains '*'. 1480bd0e222Smrg 1490bd0e222Smrg if [ -f "$src" ] || [ -d "$src" ] 1500bd0e222Smrg then 1510bd0e222Smrg : 1520bd0e222Smrg else 1530bd0e222Smrg echo "$0: $src does not exist" >&2 1540bd0e222Smrg exit 1 1550bd0e222Smrg fi 1560bd0e222Smrg 1570bd0e222Smrg if [ x"$dst" = x ] 1580bd0e222Smrg then 1590bd0e222Smrg echo "$0: no destination specified" >&2 1600bd0e222Smrg exit 1 1610bd0e222Smrg else 1620bd0e222Smrg : 1630bd0e222Smrg fi 1640bd0e222Smrg 1650bd0e222Smrg# If destination is a directory, append the input filename; if your system 1660bd0e222Smrg# does not like double slashes in filenames, you may need to add some logic 1670bd0e222Smrg 1680bd0e222Smrg if [ -d "$dst" ] 1690bd0e222Smrg then 1700bd0e222Smrg dst=$dst/`basename "$src"` 1710bd0e222Smrg else 1720bd0e222Smrg : 1730bd0e222Smrg fi 1740bd0e222Smrgfi 1750bd0e222Smrg 1760bd0e222Smrg## this sed command emulates the dirname command 1770bd0e222Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 1780bd0e222Smrg 1790bd0e222Smrg# Make sure that the destination directory exists. 1800bd0e222Smrg# this part is taken from Noah Friedman's mkinstalldirs script 1810bd0e222Smrg 1820bd0e222Smrg# Skip lots of stat calls in the usual case. 1830bd0e222Smrgif [ ! -d "$dstdir" ]; then 1840bd0e222SmrgdefaultIFS=' 1850bd0e222Smrg ' 1860bd0e222SmrgIFS="${IFS-$defaultIFS}" 1870bd0e222Smrg 1880bd0e222SmrgoIFS=$IFS 1890bd0e222Smrg# Some sh's can't handle IFS=/ for some reason. 1900bd0e222SmrgIFS='%' 1910bd0e222Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 1920bd0e222SmrgIFS=$oIFS 1930bd0e222Smrg 1940bd0e222Smrgpathcomp='' 1950bd0e222Smrg 1960bd0e222Smrgwhile [ $# -ne 0 ] ; do 1970bd0e222Smrg pathcomp=$pathcomp$1 1980bd0e222Smrg shift 1990bd0e222Smrg 2000bd0e222Smrg if [ ! -d "$pathcomp" ] ; 2010bd0e222Smrg then 2020bd0e222Smrg $mkdirprog "$pathcomp" 2030bd0e222Smrg else 2040bd0e222Smrg : 2050bd0e222Smrg fi 2060bd0e222Smrg 2070bd0e222Smrg pathcomp=$pathcomp/ 2080bd0e222Smrgdone 2090bd0e222Smrgfi 2100bd0e222Smrg 2110bd0e222Smrgif [ x"$dir_arg" != x ] 2120bd0e222Smrgthen 2130bd0e222Smrg $doit $instcmd "$dst" && 2140bd0e222Smrg 2150bd0e222Smrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 2160bd0e222Smrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 2170bd0e222Smrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 2180bd0e222Smrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 2190bd0e222Smrgelse 2200bd0e222Smrg 2210bd0e222Smrg# If we're going to rename the final executable, determine the name now. 2220bd0e222Smrg 2230bd0e222Smrg if [ x"$transformarg" = x ] 2240bd0e222Smrg then 2250bd0e222Smrg dstfile=`basename "$dst"` 2260bd0e222Smrg else 2270bd0e222Smrg dstfile=`basename "$dst" $transformbasename | 2280bd0e222Smrg sed $transformarg`$transformbasename 2290bd0e222Smrg fi 2300bd0e222Smrg 2310bd0e222Smrg# don't allow the sed command to completely eliminate the filename 2320bd0e222Smrg 2330bd0e222Smrg if [ x"$dstfile" = x ] 2340bd0e222Smrg then 2350bd0e222Smrg dstfile=`basename "$dst"` 2360bd0e222Smrg else 2370bd0e222Smrg : 2380bd0e222Smrg fi 2390bd0e222Smrg 2400bd0e222Smrg# Make a couple of temp file names in the proper directory. 2410bd0e222Smrg 2420bd0e222Smrg dsttmp=$dstdir/_inst.$$_ 2430bd0e222Smrg rmtmp=$dstdir/_rm.$$_ 2440bd0e222Smrg 2450bd0e222Smrg# Trap to clean up temp files at exit. 2460bd0e222Smrg 2470bd0e222Smrg trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 2480bd0e222Smrg trap '(exit $?); exit' 1 2 13 15 2490bd0e222Smrg 2500bd0e222Smrg# Move or copy the file name to the temp name 2510bd0e222Smrg 2520bd0e222Smrg $doit $instcmd "$src" "$dsttmp" && 2530bd0e222Smrg 2540bd0e222Smrg# and set any options; do chmod last to preserve setuid bits 2550bd0e222Smrg 2560bd0e222Smrg# If any of these fail, we abort the whole thing. If we want to 2570bd0e222Smrg# ignore errors from any of these, just make sure not to ignore 2580bd0e222Smrg# errors from the above "$doit $instcmd $src $dsttmp" command. 2590bd0e222Smrg 2600bd0e222Smrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 2610bd0e222Smrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 2620bd0e222Smrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 2630bd0e222Smrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 2640bd0e222Smrg 2650bd0e222Smrg# Now remove or move aside any old file at destination location. We try this 2660bd0e222Smrg# two ways since rm can't unlink itself on some systems and the destination 2670bd0e222Smrg# file might be busy for other reasons. In this case, the final cleanup 2680bd0e222Smrg# might fail but the new file should still install successfully. 2690bd0e222Smrg 2700bd0e222Smrg{ 2710bd0e222Smrg if [ -f "$dstdir/$dstfile" ] 2720bd0e222Smrg then 2730bd0e222Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 2740bd0e222Smrg $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 2750bd0e222Smrg { 2760bd0e222Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2770bd0e222Smrg (exit 1); exit 2780bd0e222Smrg } 2790bd0e222Smrg else 2800bd0e222Smrg : 2810bd0e222Smrg fi 2820bd0e222Smrg} && 2830bd0e222Smrg 2840bd0e222Smrg# Now rename the file to the real destination. 2850bd0e222Smrg 2860bd0e222Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 2870bd0e222Smrg 2880bd0e222Smrgfi && 2890bd0e222Smrg 2900bd0e222Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 2910bd0e222Smrg 2920bd0e222Smrg{ 2930bd0e222Smrg (exit 0); exit 2940bd0e222Smrg} 295