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