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