1234949Sbapt#! /bin/sh 2234949Sbapt# 3234949Sbapt# install - install a program, script, or datafile 4234949Sbapt# 5234949Sbapt# This originates from X11R5 (mit/util/scripts/install.sh), which was 6234949Sbapt# later released in X11R6 (xc/config/util/install.sh) with the 7234949Sbapt# following copyright and license. 8234949Sbapt# 9234949Sbapt# Copyright (C) 1994 X Consortium 10234949Sbapt# 11234949Sbapt# Permission is hereby granted, free of charge, to any person obtaining a copy 12234949Sbapt# of this software and associated documentation files (the "Software"), to 13234949Sbapt# deal in the Software without restriction, including without limitation the 14234949Sbapt# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15234949Sbapt# sell copies of the Software, and to permit persons to whom the Software is 16234949Sbapt# furnished to do so, subject to the following conditions: 17234949Sbapt# 18234949Sbapt# The above copyright notice and this permission notice shall be included in 19234949Sbapt# all copies or substantial portions of the Software. 20234949Sbapt# 21234949Sbapt# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22234949Sbapt# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23234949Sbapt# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24234949Sbapt# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25234949Sbapt# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 26234949Sbapt# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27234949Sbapt# 28234949Sbapt# Except as contained in this notice, the name of the X Consortium shall not 29234949Sbapt# be used in advertising or otherwise to promote the sale, use or other deal- 30234949Sbapt# ings in this Software without prior written authorization from the X Consor- 31234949Sbapt# tium. 32234949Sbapt# 33234949Sbapt# 34234949Sbapt# FSF changes to this file are in the public domain. 35234949Sbapt# 36234949Sbapt# Calling this script install-sh is preferred over install.sh, to prevent 37234949Sbapt# `make' implicit rules from creating a file called install from it 38234949Sbapt# when there is no Makefile. 39234949Sbapt# 40234949Sbapt# This script is compatible with the BSD install script, but was written 41234949Sbapt# from scratch. It can only install one file at a time, a restriction 42234949Sbapt# shared with many OS's install programs. 43234949Sbapt 44234949Sbapt 45234949Sbapt# set DOITPROG to echo to test this script 46234949Sbapt 47234949Sbapt# Don't use :- since 4.3BSD and earlier shells don't like it. 48234949Sbaptdoit="${DOITPROG-}" 49234949Sbapt 50234949Sbapt 51234949Sbapt# put in absolute paths if you don't have them in your path; or use env. vars. 52234949Sbapt 53234949Sbaptmvprog="${MVPROG-mv}" 54234949Sbaptcpprog="${CPPROG-cp}" 55234949Sbaptchmodprog="${CHMODPROG-chmod}" 56234949Sbaptchownprog="${CHOWNPROG-chown}" 57234949Sbaptchgrpprog="${CHGRPPROG-chgrp}" 58234949Sbaptstripprog="${STRIPPROG-strip}" 59234949Sbaptrmprog="${RMPROG-rm}" 60234949Sbaptmkdirprog="${MKDIRPROG-mkdir}" 61234949Sbapt 62234949Sbapttransformbasename="" 63234949Sbapttransform_arg="" 64234949Sbaptinstcmd="$mvprog" 65234949Sbaptchmodcmd="$chmodprog 0755" 66234949Sbaptchowncmd="" 67234949Sbaptchgrpcmd="" 68234949Sbaptstripcmd="" 69234949Sbaptrmcmd="$rmprog -f" 70234949Sbaptmvcmd="$mvprog" 71234949Sbaptsrc="" 72234949Sbaptdst="" 73234949Sbaptdir_arg="" 74234949Sbapt 75234949Sbaptwhile [ x"$1" != x ]; do 76234949Sbapt case $1 in 77234949Sbapt -c) instcmd=$cpprog 78234949Sbapt shift 79234949Sbapt continue;; 80234949Sbapt 81234949Sbapt -d) dir_arg=true 82234949Sbapt shift 83234949Sbapt continue;; 84234949Sbapt 85234949Sbapt -m) chmodcmd="$chmodprog $2" 86234949Sbapt shift 87234949Sbapt shift 88234949Sbapt continue;; 89234949Sbapt 90234949Sbapt -o) chowncmd="$chownprog $2" 91234949Sbapt shift 92234949Sbapt shift 93234949Sbapt continue;; 94234949Sbapt 95234949Sbapt -g) chgrpcmd="$chgrpprog $2" 96234949Sbapt shift 97234949Sbapt shift 98234949Sbapt continue;; 99234949Sbapt 100234949Sbapt -s) stripcmd=$stripprog 101234949Sbapt shift 102234949Sbapt continue;; 103234949Sbapt 104234949Sbapt -t=*) transformarg=`echo $1 | sed 's/-t=//'` 105234949Sbapt shift 106234949Sbapt continue;; 107234949Sbapt 108234949Sbapt -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 109234949Sbapt shift 110234949Sbapt continue;; 111234949Sbapt 112234949Sbapt *) if [ x"$src" = x ] 113234949Sbapt then 114234949Sbapt src=$1 115234949Sbapt else 116234949Sbapt # this colon is to work around a 386BSD /bin/sh bug 117234949Sbapt : 118234949Sbapt dst=$1 119234949Sbapt fi 120234949Sbapt shift 121234949Sbapt continue;; 122234949Sbapt esac 123234949Sbaptdone 124234949Sbapt 125234949Sbaptif [ x"$src" = x ] 126234949Sbaptthen 127234949Sbapt echo "$0: no input file specified" >&2 128234949Sbapt exit 1 129234949Sbaptelse 130234949Sbapt : 131234949Sbaptfi 132234949Sbapt 133234949Sbaptif [ x"$dir_arg" != x ]; then 134234949Sbapt dst=$src 135234949Sbapt src="" 136234949Sbapt 137234949Sbapt if [ -d "$dst" ]; then 138234949Sbapt instcmd=: 139234949Sbapt chmodcmd="" 140234949Sbapt else 141234949Sbapt instcmd=$mkdirprog 142234949Sbapt fi 143234949Sbaptelse 144234949Sbapt 145234949Sbapt# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 146234949Sbapt# might cause directories to be created, which would be especially bad 147234949Sbapt# if $src (and thus $dsttmp) contains '*'. 148234949Sbapt 149234949Sbapt if [ -f "$src" ] || [ -d "$src" ] 150234949Sbapt then 151234949Sbapt : 152234949Sbapt else 153234949Sbapt echo "$0: $src does not exist" >&2 154234949Sbapt exit 1 155234949Sbapt fi 156234949Sbapt 157234949Sbapt if [ x"$dst" = x ] 158234949Sbapt then 159234949Sbapt echo "$0: no destination specified" >&2 160234949Sbapt exit 1 161234949Sbapt else 162234949Sbapt : 163234949Sbapt fi 164234949Sbapt 165234949Sbapt# If destination is a directory, append the input filename; if your system 166234949Sbapt# does not like double slashes in filenames, you may need to add some logic 167234949Sbapt 168234949Sbapt if [ -d "$dst" ] 169234949Sbapt then 170234949Sbapt dst=$dst/`basename "$src"` 171234949Sbapt else 172234949Sbapt : 173234949Sbapt fi 174234949Sbaptfi 175234949Sbapt 176234949Sbapt## this sed command emulates the dirname command 177234949Sbaptdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 178234949Sbapt 179234949Sbapt# Make sure that the destination directory exists. 180234949Sbapt# this part is taken from Noah Friedman's mkinstalldirs script 181234949Sbapt 182234949Sbapt# Skip lots of stat calls in the usual case. 183234949Sbaptif [ ! -d "$dstdir" ]; then 184234949SbaptdefaultIFS=' 185234949Sbapt ' 186234949SbaptIFS="${IFS-$defaultIFS}" 187234949Sbapt 188234949SbaptoIFS=$IFS 189234949Sbapt# Some sh's can't handle IFS=/ for some reason. 190234949SbaptIFS='%' 191234949Sbaptset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 192234949SbaptIFS=$oIFS 193234949Sbapt 194234949Sbaptpathcomp='' 195234949Sbapt 196234949Sbaptwhile [ $# -ne 0 ] ; do 197234949Sbapt pathcomp=$pathcomp$1 198234949Sbapt shift 199234949Sbapt 200234949Sbapt if [ ! -d "$pathcomp" ] ; 201234949Sbapt then 202234949Sbapt $mkdirprog "$pathcomp" 203234949Sbapt else 204234949Sbapt : 205234949Sbapt fi 206234949Sbapt 207234949Sbapt pathcomp=$pathcomp/ 208234949Sbaptdone 209234949Sbaptfi 210234949Sbapt 211234949Sbaptif [ x"$dir_arg" != x ] 212234949Sbaptthen 213234949Sbapt $doit $instcmd "$dst" && 214234949Sbapt 215234949Sbapt if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 216234949Sbapt if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 217234949Sbapt if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 218234949Sbapt if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 219234949Sbaptelse 220234949Sbapt 221234949Sbapt# If we're going to rename the final executable, determine the name now. 222234949Sbapt 223234949Sbapt if [ x"$transformarg" = x ] 224234949Sbapt then 225234949Sbapt dstfile=`basename "$dst"` 226234949Sbapt else 227234949Sbapt dstfile=`basename "$dst" $transformbasename | 228234949Sbapt sed $transformarg`$transformbasename 229234949Sbapt fi 230234949Sbapt 231234949Sbapt# don't allow the sed command to completely eliminate the filename 232234949Sbapt 233234949Sbapt if [ x"$dstfile" = x ] 234234949Sbapt then 235234949Sbapt dstfile=`basename "$dst"` 236234949Sbapt else 237234949Sbapt : 238234949Sbapt fi 239234949Sbapt 240234949Sbapt# Make a couple of temp file names in the proper directory. 241234949Sbapt 242234949Sbapt dsttmp=$dstdir/#inst.$$# 243234949Sbapt rmtmp=$dstdir/#rm.$$# 244234949Sbapt 245234949Sbapt# Trap to clean up temp files at exit. 246234949Sbapt 247234949Sbapt trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 248234949Sbapt trap '(exit $?); exit' 1 2 13 15 249234949Sbapt 250234949Sbapt# Move or copy the file name to the temp name 251234949Sbapt 252234949Sbapt $doit $instcmd "$src" "$dsttmp" && 253234949Sbapt 254234949Sbapt# and set any options; do chmod last to preserve setuid bits 255234949Sbapt 256234949Sbapt# If any of these fail, we abort the whole thing. If we want to 257234949Sbapt# ignore errors from any of these, just make sure not to ignore 258234949Sbapt# errors from the above "$doit $instcmd $src $dsttmp" command. 259234949Sbapt 260234949Sbapt if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 261234949Sbapt if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 262234949Sbapt if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 263234949Sbapt if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 264234949Sbapt 265234949Sbapt# Now remove or move aside any old file at destination location. We try this 266234949Sbapt# two ways since rm can't unlink itself on some systems and the destination 267234949Sbapt# file might be busy for other reasons. In this case, the final cleanup 268234949Sbapt# might fail but the new file should still install successfully. 269234949Sbapt 270234949Sbapt{ 271234949Sbapt if [ -f "$dstdir/$dstfile" ] 272234949Sbapt then 273234949Sbapt $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 274234949Sbapt $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 275234949Sbapt { 276234949Sbapt echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 277234949Sbapt (exit 1); exit 278234949Sbapt } 279234949Sbapt else 280234949Sbapt : 281234949Sbapt fi 282234949Sbapt} && 283234949Sbapt 284234949Sbapt# Now rename the file to the real destination. 285234949Sbapt 286234949Sbapt $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 287234949Sbapt 288234949Sbaptfi && 289234949Sbapt 290234949Sbapt# The final little trick to "correctly" pass the exit status to the exit trap. 291234949Sbapt 292234949Sbapt{ 293234949Sbapt (exit 0); exit 294234949Sbapt} 295