install-sh revision cbeba4ae
1cbeba4aeSmrg#!/bin/sh 2cbeba4aeSmrg# 3cbeba4aeSmrg# install - install a program, script, or datafile 4cbeba4aeSmrg# 5cbeba4aeSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 6cbeba4aeSmrg# later released in X11R6 (xc/config/util/install.sh) with the 7cbeba4aeSmrg# following copyright and license. 8cbeba4aeSmrg# 9cbeba4aeSmrg# Copyright (C) 1994 X Consortium 10cbeba4aeSmrg# 11cbeba4aeSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 12cbeba4aeSmrg# of this software and associated documentation files (the "Software"), to 13cbeba4aeSmrg# deal in the Software without restriction, including without limitation the 14cbeba4aeSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15cbeba4aeSmrg# sell copies of the Software, and to permit persons to whom the Software is 16cbeba4aeSmrg# furnished to do so, subject to the following conditions: 17cbeba4aeSmrg# 18cbeba4aeSmrg# The above copyright notice and this permission notice shall be included in 19cbeba4aeSmrg# all copies or substantial portions of the Software. 20cbeba4aeSmrg# 21cbeba4aeSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22cbeba4aeSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23cbeba4aeSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24cbeba4aeSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25cbeba4aeSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 26cbeba4aeSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27cbeba4aeSmrg# 28cbeba4aeSmrg# Except as contained in this notice, the name of the X Consortium shall not 29cbeba4aeSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 30cbeba4aeSmrg# ings in this Software without prior written authorization from the X Consor- 31cbeba4aeSmrg# tium. 32cbeba4aeSmrg# 33cbeba4aeSmrg# 34cbeba4aeSmrg# FSF changes to this file are in the public domain. 35cbeba4aeSmrg# 36cbeba4aeSmrg# Calling this script install-sh is preferred over install.sh, to prevent 37cbeba4aeSmrg# `make' implicit rules from creating a file called install from it 38cbeba4aeSmrg# when there is no Makefile. 39cbeba4aeSmrg# 40cbeba4aeSmrg# This script is compatible with the BSD install script, but was written 41cbeba4aeSmrg# from scratch. It can only install one file at a time, a restriction 42cbeba4aeSmrg# shared with many OS's install programs. 43cbeba4aeSmrg 44cbeba4aeSmrg 45cbeba4aeSmrg# set DOITPROG to echo to test this script 46cbeba4aeSmrg 47cbeba4aeSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48cbeba4aeSmrgdoit="${DOITPROG-}" 49cbeba4aeSmrg 50cbeba4aeSmrg 51cbeba4aeSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 52cbeba4aeSmrg 53cbeba4aeSmrgmvprog="${MVPROG-mv}" 54cbeba4aeSmrgcpprog="${CPPROG-cp}" 55cbeba4aeSmrgchmodprog="${CHMODPROG-chmod}" 56cbeba4aeSmrgchownprog="${CHOWNPROG-chown}" 57cbeba4aeSmrgchgrpprog="${CHGRPPROG-chgrp}" 58cbeba4aeSmrgstripprog="${STRIPPROG-strip}" 59cbeba4aeSmrgrmprog="${RMPROG-rm}" 60cbeba4aeSmrgmkdirprog="${MKDIRPROG-mkdir}" 61cbeba4aeSmrg 62cbeba4aeSmrgtransformbasename="" 63cbeba4aeSmrgtransform_arg="" 64cbeba4aeSmrginstcmd="$mvprog" 65cbeba4aeSmrgchmodcmd="$chmodprog 0755" 66cbeba4aeSmrgchowncmd="" 67cbeba4aeSmrgchgrpcmd="" 68cbeba4aeSmrgstripcmd="" 69cbeba4aeSmrgrmcmd="$rmprog -f" 70cbeba4aeSmrgmvcmd="$mvprog" 71cbeba4aeSmrgsrc="" 72cbeba4aeSmrgdst="" 73cbeba4aeSmrgdir_arg="" 74cbeba4aeSmrg 75cbeba4aeSmrgwhile [ x"$1" != x ]; do 76cbeba4aeSmrg case $1 in 77cbeba4aeSmrg -c) instcmd=$cpprog 78cbeba4aeSmrg shift 79cbeba4aeSmrg continue;; 80cbeba4aeSmrg 81cbeba4aeSmrg -d) dir_arg=true 82cbeba4aeSmrg shift 83cbeba4aeSmrg continue;; 84cbeba4aeSmrg 85cbeba4aeSmrg -m) chmodcmd="$chmodprog $2" 86cbeba4aeSmrg shift 87cbeba4aeSmrg shift 88cbeba4aeSmrg continue;; 89cbeba4aeSmrg 90cbeba4aeSmrg -o) chowncmd="$chownprog $2" 91cbeba4aeSmrg shift 92cbeba4aeSmrg shift 93cbeba4aeSmrg continue;; 94cbeba4aeSmrg 95cbeba4aeSmrg -g) chgrpcmd="$chgrpprog $2" 96cbeba4aeSmrg shift 97cbeba4aeSmrg shift 98cbeba4aeSmrg continue;; 99cbeba4aeSmrg 100cbeba4aeSmrg -s) stripcmd=$stripprog 101cbeba4aeSmrg shift 102cbeba4aeSmrg continue;; 103cbeba4aeSmrg 104cbeba4aeSmrg -t=*) transformarg=`echo $1 | sed 's/-t=//'` 105cbeba4aeSmrg shift 106cbeba4aeSmrg continue;; 107cbeba4aeSmrg 108cbeba4aeSmrg -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 109cbeba4aeSmrg shift 110cbeba4aeSmrg continue;; 111cbeba4aeSmrg 112cbeba4aeSmrg *) if [ x"$src" = x ] 113cbeba4aeSmrg then 114cbeba4aeSmrg src=$1 115cbeba4aeSmrg else 116cbeba4aeSmrg # this colon is to work around a 386BSD /bin/sh bug 117cbeba4aeSmrg : 118cbeba4aeSmrg dst=$1 119cbeba4aeSmrg fi 120cbeba4aeSmrg shift 121cbeba4aeSmrg continue;; 122cbeba4aeSmrg esac 123cbeba4aeSmrgdone 124cbeba4aeSmrg 125cbeba4aeSmrgif [ x"$src" = x ] 126cbeba4aeSmrgthen 127cbeba4aeSmrg echo "$0: no input file specified" >&2 128cbeba4aeSmrg exit 1 129cbeba4aeSmrgelse 130cbeba4aeSmrg : 131cbeba4aeSmrgfi 132cbeba4aeSmrg 133cbeba4aeSmrgif [ x"$dir_arg" != x ]; then 134cbeba4aeSmrg dst=$src 135cbeba4aeSmrg src="" 136cbeba4aeSmrg 137cbeba4aeSmrg if [ -d "$dst" ]; then 138cbeba4aeSmrg instcmd=: 139cbeba4aeSmrg chmodcmd="" 140cbeba4aeSmrg else 141cbeba4aeSmrg instcmd=$mkdirprog 142cbeba4aeSmrg fi 143cbeba4aeSmrgelse 144cbeba4aeSmrg 145cbeba4aeSmrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 146cbeba4aeSmrg# might cause directories to be created, which would be especially bad 147cbeba4aeSmrg# if $src (and thus $dsttmp) contains '*'. 148cbeba4aeSmrg 149cbeba4aeSmrg if [ -f "$src" ] || [ -d "$src" ] 150cbeba4aeSmrg then 151cbeba4aeSmrg : 152cbeba4aeSmrg else 153cbeba4aeSmrg echo "$0: $src does not exist" >&2 154cbeba4aeSmrg exit 1 155cbeba4aeSmrg fi 156cbeba4aeSmrg 157cbeba4aeSmrg if [ x"$dst" = x ] 158cbeba4aeSmrg then 159cbeba4aeSmrg echo "$0: no destination specified" >&2 160cbeba4aeSmrg exit 1 161cbeba4aeSmrg else 162cbeba4aeSmrg : 163cbeba4aeSmrg fi 164cbeba4aeSmrg 165cbeba4aeSmrg# If destination is a directory, append the input filename; if your system 166cbeba4aeSmrg# does not like double slashes in filenames, you may need to add some logic 167cbeba4aeSmrg 168cbeba4aeSmrg if [ -d "$dst" ] 169cbeba4aeSmrg then 170cbeba4aeSmrg dst=$dst/`basename "$src"` 171cbeba4aeSmrg else 172cbeba4aeSmrg : 173cbeba4aeSmrg fi 174cbeba4aeSmrgfi 175cbeba4aeSmrg 176cbeba4aeSmrg## this sed command emulates the dirname command 177cbeba4aeSmrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 178cbeba4aeSmrg 179cbeba4aeSmrg# Make sure that the destination directory exists. 180cbeba4aeSmrg# this part is taken from Noah Friedman's mkinstalldirs script 181cbeba4aeSmrg 182cbeba4aeSmrg# Skip lots of stat calls in the usual case. 183cbeba4aeSmrgif [ ! -d "$dstdir" ]; then 184cbeba4aeSmrgdefaultIFS=' 185cbeba4aeSmrg ' 186cbeba4aeSmrgIFS="${IFS-$defaultIFS}" 187cbeba4aeSmrg 188cbeba4aeSmrgoIFS=$IFS 189cbeba4aeSmrg# Some sh's can't handle IFS=/ for some reason. 190cbeba4aeSmrgIFS='%' 191cbeba4aeSmrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 192cbeba4aeSmrgIFS=$oIFS 193cbeba4aeSmrg 194cbeba4aeSmrgpathcomp='' 195cbeba4aeSmrg 196cbeba4aeSmrgwhile [ $# -ne 0 ] ; do 197cbeba4aeSmrg pathcomp=$pathcomp$1 198cbeba4aeSmrg shift 199cbeba4aeSmrg 200cbeba4aeSmrg if [ ! -d "$pathcomp" ] ; 201cbeba4aeSmrg then 202cbeba4aeSmrg $mkdirprog "$pathcomp" 203cbeba4aeSmrg else 204cbeba4aeSmrg : 205cbeba4aeSmrg fi 206cbeba4aeSmrg 207cbeba4aeSmrg pathcomp=$pathcomp/ 208cbeba4aeSmrgdone 209cbeba4aeSmrgfi 210cbeba4aeSmrg 211cbeba4aeSmrgif [ x"$dir_arg" != x ] 212cbeba4aeSmrgthen 213cbeba4aeSmrg $doit $instcmd "$dst" && 214cbeba4aeSmrg 215cbeba4aeSmrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 216cbeba4aeSmrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 217cbeba4aeSmrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 218cbeba4aeSmrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 219cbeba4aeSmrgelse 220cbeba4aeSmrg 221cbeba4aeSmrg# If we're going to rename the final executable, determine the name now. 222cbeba4aeSmrg 223cbeba4aeSmrg if [ x"$transformarg" = x ] 224cbeba4aeSmrg then 225cbeba4aeSmrg dstfile=`basename "$dst"` 226cbeba4aeSmrg else 227cbeba4aeSmrg dstfile=`basename "$dst" $transformbasename | 228cbeba4aeSmrg sed $transformarg`$transformbasename 229cbeba4aeSmrg fi 230cbeba4aeSmrg 231cbeba4aeSmrg# don't allow the sed command to completely eliminate the filename 232cbeba4aeSmrg 233cbeba4aeSmrg if [ x"$dstfile" = x ] 234cbeba4aeSmrg then 235cbeba4aeSmrg dstfile=`basename "$dst"` 236cbeba4aeSmrg else 237cbeba4aeSmrg : 238cbeba4aeSmrg fi 239cbeba4aeSmrg 240cbeba4aeSmrg# Make a couple of temp file names in the proper directory. 241cbeba4aeSmrg 242cbeba4aeSmrg dsttmp=$dstdir/_inst.$$_ 243cbeba4aeSmrg rmtmp=$dstdir/_rm.$$_ 244cbeba4aeSmrg 245cbeba4aeSmrg# Trap to clean up temp files at exit. 246cbeba4aeSmrg 247cbeba4aeSmrg trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 248cbeba4aeSmrg trap '(exit $?); exit' 1 2 13 15 249cbeba4aeSmrg 250cbeba4aeSmrg# Move or copy the file name to the temp name 251cbeba4aeSmrg 252cbeba4aeSmrg $doit $instcmd "$src" "$dsttmp" && 253cbeba4aeSmrg 254cbeba4aeSmrg# and set any options; do chmod last to preserve setuid bits 255cbeba4aeSmrg 256cbeba4aeSmrg# If any of these fail, we abort the whole thing. If we want to 257cbeba4aeSmrg# ignore errors from any of these, just make sure not to ignore 258cbeba4aeSmrg# errors from the above "$doit $instcmd $src $dsttmp" command. 259cbeba4aeSmrg 260cbeba4aeSmrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 261cbeba4aeSmrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 262cbeba4aeSmrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 263cbeba4aeSmrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 264cbeba4aeSmrg 265cbeba4aeSmrg# Now remove or move aside any old file at destination location. We try this 266cbeba4aeSmrg# two ways since rm can't unlink itself on some systems and the destination 267cbeba4aeSmrg# file might be busy for other reasons. In this case, the final cleanup 268cbeba4aeSmrg# might fail but the new file should still install successfully. 269cbeba4aeSmrg 270cbeba4aeSmrg{ 271cbeba4aeSmrg if [ -f "$dstdir/$dstfile" ] 272cbeba4aeSmrg then 273cbeba4aeSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 274cbeba4aeSmrg $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 275cbeba4aeSmrg { 276cbeba4aeSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 277cbeba4aeSmrg (exit 1); exit 278cbeba4aeSmrg } 279cbeba4aeSmrg else 280cbeba4aeSmrg : 281cbeba4aeSmrg fi 282cbeba4aeSmrg} && 283cbeba4aeSmrg 284cbeba4aeSmrg# Now rename the file to the real destination. 285cbeba4aeSmrg 286cbeba4aeSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 287cbeba4aeSmrg 288cbeba4aeSmrgfi && 289cbeba4aeSmrg 290cbeba4aeSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 291cbeba4aeSmrg 292cbeba4aeSmrg{ 293cbeba4aeSmrg (exit 0); exit 294cbeba4aeSmrg} 295