install-sh revision 129be1b7
1129be1b7Smrg#!/bin/sh 2129be1b7Smrg# 3129be1b7Smrg# install - install a program, script, or datafile 4129be1b7Smrg# 5129be1b7Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 6129be1b7Smrg# later released in X11R6 (xc/config/util/install.sh) with the 7129be1b7Smrg# following copyright and license. 8129be1b7Smrg# 9129be1b7Smrg# Copyright (C) 1994 X Consortium 10129be1b7Smrg# 11129be1b7Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 12129be1b7Smrg# of this software and associated documentation files (the "Software"), to 13129be1b7Smrg# deal in the Software without restriction, including without limitation the 14129be1b7Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15129be1b7Smrg# sell copies of the Software, and to permit persons to whom the Software is 16129be1b7Smrg# furnished to do so, subject to the following conditions: 17129be1b7Smrg# 18129be1b7Smrg# The above copyright notice and this permission notice shall be included in 19129be1b7Smrg# all copies or substantial portions of the Software. 20129be1b7Smrg# 21129be1b7Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22129be1b7Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23129be1b7Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24129be1b7Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25129be1b7Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 26129be1b7Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27129be1b7Smrg# 28129be1b7Smrg# Except as contained in this notice, the name of the X Consortium shall not 29129be1b7Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 30129be1b7Smrg# ings in this Software without prior written authorization from the X Consor- 31129be1b7Smrg# tium. 32129be1b7Smrg# 33129be1b7Smrg# 34129be1b7Smrg# FSF changes to this file are in the public domain. 35129be1b7Smrg# 36129be1b7Smrg# Calling this script install-sh is preferred over install.sh, to prevent 37129be1b7Smrg# `make' implicit rules from creating a file called install from it 38129be1b7Smrg# when there is no Makefile. 39129be1b7Smrg# 40129be1b7Smrg# This script is compatible with the BSD install script, but was written 41129be1b7Smrg# from scratch. It can only install one file at a time, a restriction 42129be1b7Smrg# shared with many OS's install programs. 43129be1b7Smrg 44129be1b7Smrg 45129be1b7Smrg# set DOITPROG to echo to test this script 46129be1b7Smrg 47129be1b7Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48129be1b7Smrgdoit="${DOITPROG-}" 49129be1b7Smrg 50129be1b7Smrg 51129be1b7Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 52129be1b7Smrg 53129be1b7Smrgmvprog="${MVPROG-mv}" 54129be1b7Smrgcpprog="${CPPROG-cp}" 55129be1b7Smrgchmodprog="${CHMODPROG-chmod}" 56129be1b7Smrgchownprog="${CHOWNPROG-chown}" 57129be1b7Smrgchgrpprog="${CHGRPPROG-chgrp}" 58129be1b7Smrgstripprog="${STRIPPROG-strip}" 59129be1b7Smrgrmprog="${RMPROG-rm}" 60129be1b7Smrgmkdirprog="${MKDIRPROG-mkdir}" 61129be1b7Smrg 62129be1b7Smrgtransformbasename="" 63129be1b7Smrgtransform_arg="" 64129be1b7Smrginstcmd="$mvprog" 65129be1b7Smrgchmodcmd="$chmodprog 0755" 66129be1b7Smrgchowncmd="" 67129be1b7Smrgchgrpcmd="" 68129be1b7Smrgstripcmd="" 69129be1b7Smrgrmcmd="$rmprog -f" 70129be1b7Smrgmvcmd="$mvprog" 71129be1b7Smrgsrc="" 72129be1b7Smrgdst="" 73129be1b7Smrgdir_arg="" 74129be1b7Smrg 75129be1b7Smrgwhile [ x"$1" != x ]; do 76129be1b7Smrg case $1 in 77129be1b7Smrg -c) instcmd=$cpprog 78129be1b7Smrg shift 79129be1b7Smrg continue;; 80129be1b7Smrg 81129be1b7Smrg -d) dir_arg=true 82129be1b7Smrg shift 83129be1b7Smrg continue;; 84129be1b7Smrg 85129be1b7Smrg -m) chmodcmd="$chmodprog $2" 86129be1b7Smrg shift 87129be1b7Smrg shift 88129be1b7Smrg continue;; 89129be1b7Smrg 90129be1b7Smrg -o) chowncmd="$chownprog $2" 91129be1b7Smrg shift 92129be1b7Smrg shift 93129be1b7Smrg continue;; 94129be1b7Smrg 95129be1b7Smrg -g) chgrpcmd="$chgrpprog $2" 96129be1b7Smrg shift 97129be1b7Smrg shift 98129be1b7Smrg continue;; 99129be1b7Smrg 100129be1b7Smrg -s) stripcmd=$stripprog 101129be1b7Smrg shift 102129be1b7Smrg continue;; 103129be1b7Smrg 104129be1b7Smrg -t=*) transformarg=`echo $1 | sed 's/-t=//'` 105129be1b7Smrg shift 106129be1b7Smrg continue;; 107129be1b7Smrg 108129be1b7Smrg -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 109129be1b7Smrg shift 110129be1b7Smrg continue;; 111129be1b7Smrg 112129be1b7Smrg *) if [ x"$src" = x ] 113129be1b7Smrg then 114129be1b7Smrg src=$1 115129be1b7Smrg else 116129be1b7Smrg # this colon is to work around a 386BSD /bin/sh bug 117129be1b7Smrg : 118129be1b7Smrg dst=$1 119129be1b7Smrg fi 120129be1b7Smrg shift 121129be1b7Smrg continue;; 122129be1b7Smrg esac 123129be1b7Smrgdone 124129be1b7Smrg 125129be1b7Smrgif [ x"$src" = x ] 126129be1b7Smrgthen 127129be1b7Smrg echo "$0: no input file specified" >&2 128129be1b7Smrg exit 1 129129be1b7Smrgelse 130129be1b7Smrg : 131129be1b7Smrgfi 132129be1b7Smrg 133129be1b7Smrgif [ x"$dir_arg" != x ]; then 134129be1b7Smrg dst=$src 135129be1b7Smrg src="" 136129be1b7Smrg 137129be1b7Smrg if [ -d "$dst" ]; then 138129be1b7Smrg instcmd=: 139129be1b7Smrg chmodcmd="" 140129be1b7Smrg else 141129be1b7Smrg instcmd=$mkdirprog 142129be1b7Smrg fi 143129be1b7Smrgelse 144129be1b7Smrg 145129be1b7Smrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 146129be1b7Smrg# might cause directories to be created, which would be especially bad 147129be1b7Smrg# if $src (and thus $dsttmp) contains '*'. 148129be1b7Smrg 149129be1b7Smrg if [ -f "$src" ] || [ -d "$src" ] 150129be1b7Smrg then 151129be1b7Smrg : 152129be1b7Smrg else 153129be1b7Smrg echo "$0: $src does not exist" >&2 154129be1b7Smrg exit 1 155129be1b7Smrg fi 156129be1b7Smrg 157129be1b7Smrg if [ x"$dst" = x ] 158129be1b7Smrg then 159129be1b7Smrg echo "$0: no destination specified" >&2 160129be1b7Smrg exit 1 161129be1b7Smrg else 162129be1b7Smrg : 163129be1b7Smrg fi 164129be1b7Smrg 165129be1b7Smrg# If destination is a directory, append the input filename; if your system 166129be1b7Smrg# does not like double slashes in filenames, you may need to add some logic 167129be1b7Smrg 168129be1b7Smrg if [ -d "$dst" ] 169129be1b7Smrg then 170129be1b7Smrg dst=$dst/`basename "$src"` 171129be1b7Smrg else 172129be1b7Smrg : 173129be1b7Smrg fi 174129be1b7Smrgfi 175129be1b7Smrg 176129be1b7Smrg## this sed command emulates the dirname command 177129be1b7Smrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 178129be1b7Smrg 179129be1b7Smrg# Make sure that the destination directory exists. 180129be1b7Smrg# this part is taken from Noah Friedman's mkinstalldirs script 181129be1b7Smrg 182129be1b7Smrg# Skip lots of stat calls in the usual case. 183129be1b7Smrgif [ ! -d "$dstdir" ]; then 184129be1b7SmrgdefaultIFS=' 185129be1b7Smrg ' 186129be1b7SmrgIFS="${IFS-$defaultIFS}" 187129be1b7Smrg 188129be1b7SmrgoIFS=$IFS 189129be1b7Smrg# Some sh's can't handle IFS=/ for some reason. 190129be1b7SmrgIFS='%' 191129be1b7Smrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 192129be1b7SmrgIFS=$oIFS 193129be1b7Smrg 194129be1b7Smrgpathcomp='' 195129be1b7Smrg 196129be1b7Smrgwhile [ $# -ne 0 ] ; do 197129be1b7Smrg pathcomp=$pathcomp$1 198129be1b7Smrg shift 199129be1b7Smrg 200129be1b7Smrg if [ ! -d "$pathcomp" ] ; 201129be1b7Smrg then 202129be1b7Smrg $mkdirprog "$pathcomp" 203129be1b7Smrg else 204129be1b7Smrg : 205129be1b7Smrg fi 206129be1b7Smrg 207129be1b7Smrg pathcomp=$pathcomp/ 208129be1b7Smrgdone 209129be1b7Smrgfi 210129be1b7Smrg 211129be1b7Smrgif [ x"$dir_arg" != x ] 212129be1b7Smrgthen 213129be1b7Smrg $doit $instcmd "$dst" && 214129be1b7Smrg 215129be1b7Smrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 216129be1b7Smrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 217129be1b7Smrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 218129be1b7Smrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 219129be1b7Smrgelse 220129be1b7Smrg 221129be1b7Smrg# If we're going to rename the final executable, determine the name now. 222129be1b7Smrg 223129be1b7Smrg if [ x"$transformarg" = x ] 224129be1b7Smrg then 225129be1b7Smrg dstfile=`basename "$dst"` 226129be1b7Smrg else 227129be1b7Smrg dstfile=`basename "$dst" $transformbasename | 228129be1b7Smrg sed $transformarg`$transformbasename 229129be1b7Smrg fi 230129be1b7Smrg 231129be1b7Smrg# don't allow the sed command to completely eliminate the filename 232129be1b7Smrg 233129be1b7Smrg if [ x"$dstfile" = x ] 234129be1b7Smrg then 235129be1b7Smrg dstfile=`basename "$dst"` 236129be1b7Smrg else 237129be1b7Smrg : 238129be1b7Smrg fi 239129be1b7Smrg 240129be1b7Smrg# Make a couple of temp file names in the proper directory. 241129be1b7Smrg 242129be1b7Smrg dsttmp=$dstdir/_inst.$$_ 243129be1b7Smrg rmtmp=$dstdir/_rm.$$_ 244129be1b7Smrg 245129be1b7Smrg# Trap to clean up temp files at exit. 246129be1b7Smrg 247129be1b7Smrg trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 248129be1b7Smrg trap '(exit $?); exit' 1 2 13 15 249129be1b7Smrg 250129be1b7Smrg# Move or copy the file name to the temp name 251129be1b7Smrg 252129be1b7Smrg $doit $instcmd "$src" "$dsttmp" && 253129be1b7Smrg 254129be1b7Smrg# and set any options; do chmod last to preserve setuid bits 255129be1b7Smrg 256129be1b7Smrg# If any of these fail, we abort the whole thing. If we want to 257129be1b7Smrg# ignore errors from any of these, just make sure not to ignore 258129be1b7Smrg# errors from the above "$doit $instcmd $src $dsttmp" command. 259129be1b7Smrg 260129be1b7Smrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 261129be1b7Smrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 262129be1b7Smrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 263129be1b7Smrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 264129be1b7Smrg 265129be1b7Smrg# Now remove or move aside any old file at destination location. We try this 266129be1b7Smrg# two ways since rm can't unlink itself on some systems and the destination 267129be1b7Smrg# file might be busy for other reasons. In this case, the final cleanup 268129be1b7Smrg# might fail but the new file should still install successfully. 269129be1b7Smrg 270129be1b7Smrg{ 271129be1b7Smrg if [ -f "$dstdir/$dstfile" ] 272129be1b7Smrg then 273129be1b7Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 274129be1b7Smrg $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 275129be1b7Smrg { 276129be1b7Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 277129be1b7Smrg (exit 1); exit 278129be1b7Smrg } 279129be1b7Smrg else 280129be1b7Smrg : 281129be1b7Smrg fi 282129be1b7Smrg} && 283129be1b7Smrg 284129be1b7Smrg# Now rename the file to the real destination. 285129be1b7Smrg 286129be1b7Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 287129be1b7Smrg 288129be1b7Smrgfi && 289129be1b7Smrg 290129be1b7Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 291129be1b7Smrg 292129be1b7Smrg{ 293129be1b7Smrg (exit 0); exit 294129be1b7Smrg} 295