install-sh revision 3da7aff1
13da7aff1Smrg#!/bin/sh 23da7aff1Smrg# 33da7aff1Smrg# install - install a program, script, or datafile 43da7aff1Smrg# 53da7aff1Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 63da7aff1Smrg# later released in X11R6 (xc/config/util/install.sh) with the 73da7aff1Smrg# following copyright and license. 83da7aff1Smrg# 93da7aff1Smrg# Copyright (C) 1994 X Consortium 103da7aff1Smrg# 113da7aff1Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 123da7aff1Smrg# of this software and associated documentation files (the "Software"), to 133da7aff1Smrg# deal in the Software without restriction, including without limitation the 143da7aff1Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 153da7aff1Smrg# sell copies of the Software, and to permit persons to whom the Software is 163da7aff1Smrg# furnished to do so, subject to the following conditions: 173da7aff1Smrg# 183da7aff1Smrg# The above copyright notice and this permission notice shall be included in 193da7aff1Smrg# all copies or substantial portions of the Software. 203da7aff1Smrg# 213da7aff1Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 223da7aff1Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 233da7aff1Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 243da7aff1Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 253da7aff1Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 263da7aff1Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 273da7aff1Smrg# 283da7aff1Smrg# Except as contained in this notice, the name of the X Consortium shall not 293da7aff1Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 303da7aff1Smrg# ings in this Software without prior written authorization from the X Consor- 313da7aff1Smrg# tium. 323da7aff1Smrg# 333da7aff1Smrg# 343da7aff1Smrg# FSF changes to this file are in the public domain. 353da7aff1Smrg# 363da7aff1Smrg# Calling this script install-sh is preferred over install.sh, to prevent 373da7aff1Smrg# `make' implicit rules from creating a file called install from it 383da7aff1Smrg# when there is no Makefile. 393da7aff1Smrg# 403da7aff1Smrg# This script is compatible with the BSD install script, but was written 413da7aff1Smrg# from scratch. It can only install one file at a time, a restriction 423da7aff1Smrg# shared with many OS's install programs. 433da7aff1Smrg 443da7aff1Smrg 453da7aff1Smrg# set DOITPROG to echo to test this script 463da7aff1Smrg 473da7aff1Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 483da7aff1Smrgdoit="${DOITPROG-}" 493da7aff1Smrg 503da7aff1Smrg 513da7aff1Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 523da7aff1Smrg 533da7aff1Smrgmvprog="${MVPROG-mv}" 543da7aff1Smrgcpprog="${CPPROG-cp}" 553da7aff1Smrgchmodprog="${CHMODPROG-chmod}" 563da7aff1Smrgchownprog="${CHOWNPROG-chown}" 573da7aff1Smrgchgrpprog="${CHGRPPROG-chgrp}" 583da7aff1Smrgstripprog="${STRIPPROG-strip}" 593da7aff1Smrgrmprog="${RMPROG-rm}" 603da7aff1Smrgmkdirprog="${MKDIRPROG-mkdir}" 613da7aff1Smrg 623da7aff1Smrgtransformbasename="" 633da7aff1Smrgtransform_arg="" 643da7aff1Smrginstcmd="$mvprog" 653da7aff1Smrgchmodcmd="$chmodprog 0755" 663da7aff1Smrgchowncmd="" 673da7aff1Smrgchgrpcmd="" 683da7aff1Smrgstripcmd="" 693da7aff1Smrgrmcmd="$rmprog -f" 703da7aff1Smrgmvcmd="$mvprog" 713da7aff1Smrgsrc="" 723da7aff1Smrgdst="" 733da7aff1Smrgdir_arg="" 743da7aff1Smrg 753da7aff1Smrgwhile [ x"$1" != x ]; do 763da7aff1Smrg case $1 in 773da7aff1Smrg -c) instcmd=$cpprog 783da7aff1Smrg shift 793da7aff1Smrg continue;; 803da7aff1Smrg 813da7aff1Smrg -d) dir_arg=true 823da7aff1Smrg shift 833da7aff1Smrg continue;; 843da7aff1Smrg 853da7aff1Smrg -m) chmodcmd="$chmodprog $2" 863da7aff1Smrg shift 873da7aff1Smrg shift 883da7aff1Smrg continue;; 893da7aff1Smrg 903da7aff1Smrg -o) chowncmd="$chownprog $2" 913da7aff1Smrg shift 923da7aff1Smrg shift 933da7aff1Smrg continue;; 943da7aff1Smrg 953da7aff1Smrg -g) chgrpcmd="$chgrpprog $2" 963da7aff1Smrg shift 973da7aff1Smrg shift 983da7aff1Smrg continue;; 993da7aff1Smrg 1003da7aff1Smrg -s) stripcmd=$stripprog 1013da7aff1Smrg shift 1023da7aff1Smrg continue;; 1033da7aff1Smrg 1043da7aff1Smrg -t=*) transformarg=`echo $1 | sed 's/-t=//'` 1053da7aff1Smrg shift 1063da7aff1Smrg continue;; 1073da7aff1Smrg 1083da7aff1Smrg -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 1093da7aff1Smrg shift 1103da7aff1Smrg continue;; 1113da7aff1Smrg 1123da7aff1Smrg *) if [ x"$src" = x ] 1133da7aff1Smrg then 1143da7aff1Smrg src=$1 1153da7aff1Smrg else 1163da7aff1Smrg # this colon is to work around a 386BSD /bin/sh bug 1173da7aff1Smrg : 1183da7aff1Smrg dst=$1 1193da7aff1Smrg fi 1203da7aff1Smrg shift 1213da7aff1Smrg continue;; 1223da7aff1Smrg esac 1233da7aff1Smrgdone 1243da7aff1Smrg 1253da7aff1Smrgif [ x"$src" = x ] 1263da7aff1Smrgthen 1273da7aff1Smrg echo "$0: no input file specified" >&2 1283da7aff1Smrg exit 1 1293da7aff1Smrgelse 1303da7aff1Smrg : 1313da7aff1Smrgfi 1323da7aff1Smrg 1333da7aff1Smrgif [ x"$dir_arg" != x ]; then 1343da7aff1Smrg dst=$src 1353da7aff1Smrg src="" 1363da7aff1Smrg 1373da7aff1Smrg if [ -d "$dst" ]; then 1383da7aff1Smrg instcmd=: 1393da7aff1Smrg chmodcmd="" 1403da7aff1Smrg else 1413da7aff1Smrg instcmd=$mkdirprog 1423da7aff1Smrg fi 1433da7aff1Smrgelse 1443da7aff1Smrg 1453da7aff1Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 1463da7aff1Smrg# might cause directories to be created, which would be especially bad 1473da7aff1Smrg# if $src (and thus $dsttmp) contains '*'. 1483da7aff1Smrg 1493da7aff1Smrg if [ -f "$src" ] || [ -d "$src" ] 1503da7aff1Smrg then 1513da7aff1Smrg : 1523da7aff1Smrg else 1533da7aff1Smrg echo "$0: $src does not exist" >&2 1543da7aff1Smrg exit 1 1553da7aff1Smrg fi 1563da7aff1Smrg 1573da7aff1Smrg if [ x"$dst" = x ] 1583da7aff1Smrg then 1593da7aff1Smrg echo "$0: no destination specified" >&2 1603da7aff1Smrg exit 1 1613da7aff1Smrg else 1623da7aff1Smrg : 1633da7aff1Smrg fi 1643da7aff1Smrg 1653da7aff1Smrg# If destination is a directory, append the input filename; if your system 1663da7aff1Smrg# does not like double slashes in filenames, you may need to add some logic 1673da7aff1Smrg 1683da7aff1Smrg if [ -d "$dst" ] 1693da7aff1Smrg then 1703da7aff1Smrg dst=$dst/`basename "$src"` 1713da7aff1Smrg else 1723da7aff1Smrg : 1733da7aff1Smrg fi 1743da7aff1Smrgfi 1753da7aff1Smrg 1763da7aff1Smrg## this sed command emulates the dirname command 1773da7aff1Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 1783da7aff1Smrg 1793da7aff1Smrg# Make sure that the destination directory exists. 1803da7aff1Smrg# this part is taken from Noah Friedman's mkinstalldirs script 1813da7aff1Smrg 1823da7aff1Smrg# Skip lots of stat calls in the usual case. 1833da7aff1Smrgif [ ! -d "$dstdir" ]; then 1843da7aff1SmrgdefaultIFS=' 1853da7aff1Smrg ' 1863da7aff1SmrgIFS="${IFS-$defaultIFS}" 1873da7aff1Smrg 1883da7aff1SmrgoIFS=$IFS 1893da7aff1Smrg# Some sh's can't handle IFS=/ for some reason. 1903da7aff1SmrgIFS='%' 1913da7aff1Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 1923da7aff1SmrgIFS=$oIFS 1933da7aff1Smrg 1943da7aff1Smrgpathcomp='' 1953da7aff1Smrg 1963da7aff1Smrgwhile [ $# -ne 0 ] ; do 1973da7aff1Smrg pathcomp=$pathcomp$1 1983da7aff1Smrg shift 1993da7aff1Smrg 2003da7aff1Smrg if [ ! -d "$pathcomp" ] ; 2013da7aff1Smrg then 2023da7aff1Smrg $mkdirprog "$pathcomp" 2033da7aff1Smrg else 2043da7aff1Smrg : 2053da7aff1Smrg fi 2063da7aff1Smrg 2073da7aff1Smrg pathcomp=$pathcomp/ 2083da7aff1Smrgdone 2093da7aff1Smrgfi 2103da7aff1Smrg 2113da7aff1Smrgif [ x"$dir_arg" != x ] 2123da7aff1Smrgthen 2133da7aff1Smrg $doit $instcmd "$dst" && 2143da7aff1Smrg 2153da7aff1Smrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 2163da7aff1Smrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 2173da7aff1Smrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 2183da7aff1Smrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 2193da7aff1Smrgelse 2203da7aff1Smrg 2213da7aff1Smrg# If we're going to rename the final executable, determine the name now. 2223da7aff1Smrg 2233da7aff1Smrg if [ x"$transformarg" = x ] 2243da7aff1Smrg then 2253da7aff1Smrg dstfile=`basename "$dst"` 2263da7aff1Smrg else 2273da7aff1Smrg dstfile=`basename "$dst" $transformbasename | 2283da7aff1Smrg sed $transformarg`$transformbasename 2293da7aff1Smrg fi 2303da7aff1Smrg 2313da7aff1Smrg# don't allow the sed command to completely eliminate the filename 2323da7aff1Smrg 2333da7aff1Smrg if [ x"$dstfile" = x ] 2343da7aff1Smrg then 2353da7aff1Smrg dstfile=`basename "$dst"` 2363da7aff1Smrg else 2373da7aff1Smrg : 2383da7aff1Smrg fi 2393da7aff1Smrg 2403da7aff1Smrg# Make a couple of temp file names in the proper directory. 2413da7aff1Smrg 2423da7aff1Smrg dsttmp=$dstdir/_inst.$$_ 2433da7aff1Smrg rmtmp=$dstdir/_rm.$$_ 2443da7aff1Smrg 2453da7aff1Smrg# Trap to clean up temp files at exit. 2463da7aff1Smrg 2473da7aff1Smrg trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 2483da7aff1Smrg trap '(exit $?); exit' 1 2 13 15 2493da7aff1Smrg 2503da7aff1Smrg# Move or copy the file name to the temp name 2513da7aff1Smrg 2523da7aff1Smrg $doit $instcmd "$src" "$dsttmp" && 2533da7aff1Smrg 2543da7aff1Smrg# and set any options; do chmod last to preserve setuid bits 2553da7aff1Smrg 2563da7aff1Smrg# If any of these fail, we abort the whole thing. If we want to 2573da7aff1Smrg# ignore errors from any of these, just make sure not to ignore 2583da7aff1Smrg# errors from the above "$doit $instcmd $src $dsttmp" command. 2593da7aff1Smrg 2603da7aff1Smrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 2613da7aff1Smrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 2623da7aff1Smrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 2633da7aff1Smrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 2643da7aff1Smrg 2653da7aff1Smrg# Now remove or move aside any old file at destination location. We try this 2663da7aff1Smrg# two ways since rm can't unlink itself on some systems and the destination 2673da7aff1Smrg# file might be busy for other reasons. In this case, the final cleanup 2683da7aff1Smrg# might fail but the new file should still install successfully. 2693da7aff1Smrg 2703da7aff1Smrg{ 2713da7aff1Smrg if [ -f "$dstdir/$dstfile" ] 2723da7aff1Smrg then 2733da7aff1Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 2743da7aff1Smrg $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 2753da7aff1Smrg { 2763da7aff1Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2773da7aff1Smrg (exit 1); exit 2783da7aff1Smrg } 2793da7aff1Smrg else 2803da7aff1Smrg : 2813da7aff1Smrg fi 2823da7aff1Smrg} && 2833da7aff1Smrg 2843da7aff1Smrg# Now rename the file to the real destination. 2853da7aff1Smrg 2863da7aff1Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 2873da7aff1Smrg 2883da7aff1Smrgfi && 2893da7aff1Smrg 2903da7aff1Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 2913da7aff1Smrg 2923da7aff1Smrg{ 2933da7aff1Smrg (exit 0); exit 2943da7aff1Smrg} 295