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