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