install-sh revision 644fc5c1
1644fc5c1Stron#!/bin/sh 2644fc5c1Stron# 3644fc5c1Stron# install - install a program, script, or datafile 4644fc5c1Stron# 5644fc5c1Stron# This originates from X11R5 (mit/util/scripts/install.sh), which was 6644fc5c1Stron# later released in X11R6 (xc/config/util/install.sh) with the 7644fc5c1Stron# following copyright and license. 8644fc5c1Stron# 9644fc5c1Stron# Copyright (C) 1994 X Consortium 10644fc5c1Stron# 11644fc5c1Stron# Permission is hereby granted, free of charge, to any person obtaining a copy 12644fc5c1Stron# of this software and associated documentation files (the "Software"), to 13644fc5c1Stron# deal in the Software without restriction, including without limitation the 14644fc5c1Stron# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15644fc5c1Stron# sell copies of the Software, and to permit persons to whom the Software is 16644fc5c1Stron# furnished to do so, subject to the following conditions: 17644fc5c1Stron# 18644fc5c1Stron# The above copyright notice and this permission notice shall be included in 19644fc5c1Stron# all copies or substantial portions of the Software. 20644fc5c1Stron# 21644fc5c1Stron# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22644fc5c1Stron# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23644fc5c1Stron# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24644fc5c1Stron# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25644fc5c1Stron# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 26644fc5c1Stron# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27644fc5c1Stron# 28644fc5c1Stron# Except as contained in this notice, the name of the X Consortium shall not 29644fc5c1Stron# be used in advertising or otherwise to promote the sale, use or other deal- 30644fc5c1Stron# ings in this Software without prior written authorization from the X Consor- 31644fc5c1Stron# tium. 32644fc5c1Stron# 33644fc5c1Stron# 34644fc5c1Stron# FSF changes to this file are in the public domain. 35644fc5c1Stron# 36644fc5c1Stron# Calling this script install-sh is preferred over install.sh, to prevent 37644fc5c1Stron# `make' implicit rules from creating a file called install from it 38644fc5c1Stron# when there is no Makefile. 39644fc5c1Stron# 40644fc5c1Stron# This script is compatible with the BSD install script, but was written 41644fc5c1Stron# from scratch. It can only install one file at a time, a restriction 42644fc5c1Stron# shared with many OS's install programs. 43644fc5c1Stron 44644fc5c1Stron 45644fc5c1Stron# set DOITPROG to echo to test this script 46644fc5c1Stron 47644fc5c1Stron# Don't use :- since 4.3BSD and earlier shells don't like it. 48644fc5c1Strondoit="${DOITPROG-}" 49644fc5c1Stron 50644fc5c1Stron 51644fc5c1Stron# put in absolute paths if you don't have them in your path; or use env. vars. 52644fc5c1Stron 53644fc5c1Stronmvprog="${MVPROG-mv}" 54644fc5c1Stroncpprog="${CPPROG-cp}" 55644fc5c1Stronchmodprog="${CHMODPROG-chmod}" 56644fc5c1Stronchownprog="${CHOWNPROG-chown}" 57644fc5c1Stronchgrpprog="${CHGRPPROG-chgrp}" 58644fc5c1Stronstripprog="${STRIPPROG-strip}" 59644fc5c1Stronrmprog="${RMPROG-rm}" 60644fc5c1Stronmkdirprog="${MKDIRPROG-mkdir}" 61644fc5c1Stron 62644fc5c1Strontransformbasename="" 63644fc5c1Strontransform_arg="" 64644fc5c1Stroninstcmd="$mvprog" 65644fc5c1Stronchmodcmd="$chmodprog 0755" 66644fc5c1Stronchowncmd="" 67644fc5c1Stronchgrpcmd="" 68644fc5c1Stronstripcmd="" 69644fc5c1Stronrmcmd="$rmprog -f" 70644fc5c1Stronmvcmd="$mvprog" 71644fc5c1Stronsrc="" 72644fc5c1Strondst="" 73644fc5c1Strondir_arg="" 74644fc5c1Stron 75644fc5c1Stronwhile [ x"$1" != x ]; do 76644fc5c1Stron case $1 in 77644fc5c1Stron -c) instcmd=$cpprog 78644fc5c1Stron shift 79644fc5c1Stron continue;; 80644fc5c1Stron 81644fc5c1Stron -d) dir_arg=true 82644fc5c1Stron shift 83644fc5c1Stron continue;; 84644fc5c1Stron 85644fc5c1Stron -m) chmodcmd="$chmodprog $2" 86644fc5c1Stron shift 87644fc5c1Stron shift 88644fc5c1Stron continue;; 89644fc5c1Stron 90644fc5c1Stron -o) chowncmd="$chownprog $2" 91644fc5c1Stron shift 92644fc5c1Stron shift 93644fc5c1Stron continue;; 94644fc5c1Stron 95644fc5c1Stron -g) chgrpcmd="$chgrpprog $2" 96644fc5c1Stron shift 97644fc5c1Stron shift 98644fc5c1Stron continue;; 99644fc5c1Stron 100644fc5c1Stron -s) stripcmd=$stripprog 101644fc5c1Stron shift 102644fc5c1Stron continue;; 103644fc5c1Stron 104644fc5c1Stron -t=*) transformarg=`echo $1 | sed 's/-t=//'` 105644fc5c1Stron shift 106644fc5c1Stron continue;; 107644fc5c1Stron 108644fc5c1Stron -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 109644fc5c1Stron shift 110644fc5c1Stron continue;; 111644fc5c1Stron 112644fc5c1Stron *) if [ x"$src" = x ] 113644fc5c1Stron then 114644fc5c1Stron src=$1 115644fc5c1Stron else 116644fc5c1Stron # this colon is to work around a 386BSD /bin/sh bug 117644fc5c1Stron : 118644fc5c1Stron dst=$1 119644fc5c1Stron fi 120644fc5c1Stron shift 121644fc5c1Stron continue;; 122644fc5c1Stron esac 123644fc5c1Strondone 124644fc5c1Stron 125644fc5c1Stronif [ x"$src" = x ] 126644fc5c1Stronthen 127644fc5c1Stron echo "$0: no input file specified" >&2 128644fc5c1Stron exit 1 129644fc5c1Stronelse 130644fc5c1Stron : 131644fc5c1Stronfi 132644fc5c1Stron 133644fc5c1Stronif [ x"$dir_arg" != x ]; then 134644fc5c1Stron dst=$src 135644fc5c1Stron src="" 136644fc5c1Stron 137644fc5c1Stron if [ -d "$dst" ]; then 138644fc5c1Stron instcmd=: 139644fc5c1Stron chmodcmd="" 140644fc5c1Stron else 141644fc5c1Stron instcmd=$mkdirprog 142644fc5c1Stron fi 143644fc5c1Stronelse 144644fc5c1Stron 145644fc5c1Stron# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 146644fc5c1Stron# might cause directories to be created, which would be especially bad 147644fc5c1Stron# if $src (and thus $dsttmp) contains '*'. 148644fc5c1Stron 149644fc5c1Stron if [ -f "$src" ] || [ -d "$src" ] 150644fc5c1Stron then 151644fc5c1Stron : 152644fc5c1Stron else 153644fc5c1Stron echo "$0: $src does not exist" >&2 154644fc5c1Stron exit 1 155644fc5c1Stron fi 156644fc5c1Stron 157644fc5c1Stron if [ x"$dst" = x ] 158644fc5c1Stron then 159644fc5c1Stron echo "$0: no destination specified" >&2 160644fc5c1Stron exit 1 161644fc5c1Stron else 162644fc5c1Stron : 163644fc5c1Stron fi 164644fc5c1Stron 165644fc5c1Stron# If destination is a directory, append the input filename; if your system 166644fc5c1Stron# does not like double slashes in filenames, you may need to add some logic 167644fc5c1Stron 168644fc5c1Stron if [ -d "$dst" ] 169644fc5c1Stron then 170644fc5c1Stron dst=$dst/`basename "$src"` 171644fc5c1Stron else 172644fc5c1Stron : 173644fc5c1Stron fi 174644fc5c1Stronfi 175644fc5c1Stron 176644fc5c1Stron## this sed command emulates the dirname command 177644fc5c1Strondstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 178644fc5c1Stron 179644fc5c1Stron# Make sure that the destination directory exists. 180644fc5c1Stron# this part is taken from Noah Friedman's mkinstalldirs script 181644fc5c1Stron 182644fc5c1Stron# Skip lots of stat calls in the usual case. 183644fc5c1Stronif [ ! -d "$dstdir" ]; then 184644fc5c1StrondefaultIFS=' 185644fc5c1Stron ' 186644fc5c1StronIFS="${IFS-$defaultIFS}" 187644fc5c1Stron 188644fc5c1StronoIFS=$IFS 189644fc5c1Stron# Some sh's can't handle IFS=/ for some reason. 190644fc5c1StronIFS='%' 191644fc5c1Stronset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 192644fc5c1StronIFS=$oIFS 193644fc5c1Stron 194644fc5c1Stronpathcomp='' 195644fc5c1Stron 196644fc5c1Stronwhile [ $# -ne 0 ] ; do 197644fc5c1Stron pathcomp=$pathcomp$1 198644fc5c1Stron shift 199644fc5c1Stron 200644fc5c1Stron if [ ! -d "$pathcomp" ] ; 201644fc5c1Stron then 202644fc5c1Stron $mkdirprog "$pathcomp" 203644fc5c1Stron else 204644fc5c1Stron : 205644fc5c1Stron fi 206644fc5c1Stron 207644fc5c1Stron pathcomp=$pathcomp/ 208644fc5c1Strondone 209644fc5c1Stronfi 210644fc5c1Stron 211644fc5c1Stronif [ x"$dir_arg" != x ] 212644fc5c1Stronthen 213644fc5c1Stron $doit $instcmd "$dst" && 214644fc5c1Stron 215644fc5c1Stron if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 216644fc5c1Stron if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 217644fc5c1Stron if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 218644fc5c1Stron if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 219644fc5c1Stronelse 220644fc5c1Stron 221644fc5c1Stron# If we're going to rename the final executable, determine the name now. 222644fc5c1Stron 223644fc5c1Stron if [ x"$transformarg" = x ] 224644fc5c1Stron then 225644fc5c1Stron dstfile=`basename "$dst"` 226644fc5c1Stron else 227644fc5c1Stron dstfile=`basename "$dst" $transformbasename | 228644fc5c1Stron sed $transformarg`$transformbasename 229644fc5c1Stron fi 230644fc5c1Stron 231644fc5c1Stron# don't allow the sed command to completely eliminate the filename 232644fc5c1Stron 233644fc5c1Stron if [ x"$dstfile" = x ] 234644fc5c1Stron then 235644fc5c1Stron dstfile=`basename "$dst"` 236644fc5c1Stron else 237644fc5c1Stron : 238644fc5c1Stron fi 239644fc5c1Stron 240644fc5c1Stron# Make a couple of temp file names in the proper directory. 241644fc5c1Stron 242644fc5c1Stron dsttmp=$dstdir/_inst.$$_ 243644fc5c1Stron rmtmp=$dstdir/_rm.$$_ 244644fc5c1Stron 245644fc5c1Stron# Trap to clean up temp files at exit. 246644fc5c1Stron 247644fc5c1Stron trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 248644fc5c1Stron trap '(exit $?); exit' 1 2 13 15 249644fc5c1Stron 250644fc5c1Stron# Move or copy the file name to the temp name 251644fc5c1Stron 252644fc5c1Stron $doit $instcmd "$src" "$dsttmp" && 253644fc5c1Stron 254644fc5c1Stron# and set any options; do chmod last to preserve setuid bits 255644fc5c1Stron 256644fc5c1Stron# If any of these fail, we abort the whole thing. If we want to 257644fc5c1Stron# ignore errors from any of these, just make sure not to ignore 258644fc5c1Stron# errors from the above "$doit $instcmd $src $dsttmp" command. 259644fc5c1Stron 260644fc5c1Stron if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 261644fc5c1Stron if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 262644fc5c1Stron if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 263644fc5c1Stron if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 264644fc5c1Stron 265644fc5c1Stron# Now remove or move aside any old file at destination location. We try this 266644fc5c1Stron# two ways since rm can't unlink itself on some systems and the destination 267644fc5c1Stron# file might be busy for other reasons. In this case, the final cleanup 268644fc5c1Stron# might fail but the new file should still install successfully. 269644fc5c1Stron 270644fc5c1Stron{ 271644fc5c1Stron if [ -f "$dstdir/$dstfile" ] 272644fc5c1Stron then 273644fc5c1Stron $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 274644fc5c1Stron $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 275644fc5c1Stron { 276644fc5c1Stron echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 277644fc5c1Stron (exit 1); exit 278644fc5c1Stron } 279644fc5c1Stron else 280644fc5c1Stron : 281644fc5c1Stron fi 282644fc5c1Stron} && 283644fc5c1Stron 284644fc5c1Stron# Now rename the file to the real destination. 285644fc5c1Stron 286644fc5c1Stron $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 287644fc5c1Stron 288644fc5c1Stronfi && 289644fc5c1Stron 290644fc5c1Stron# The final little trick to "correctly" pass the exit status to the exit trap. 291644fc5c1Stron 292644fc5c1Stron{ 293644fc5c1Stron (exit 0); exit 294644fc5c1Stron} 295