1130803Smarcel#!/bin/sh 2130803Smarcel# install - install a program, script, or datafile 3130803Smarcel 4130803Smarcelscriptversion=2004-02-15.20 5130803Smarcel 6130803Smarcel# This originates from X11R5 (mit/util/scripts/install.sh), which was 7130803Smarcel# later released in X11R6 (xc/config/util/install.sh) with the 8130803Smarcel# following copyright and license. 9130803Smarcel# 10130803Smarcel# Copyright (C) 1994 X Consortium 11130803Smarcel# 12130803Smarcel# Permission is hereby granted, free of charge, to any person obtaining a copy 13130803Smarcel# of this software and associated documentation files (the "Software"), to 14130803Smarcel# deal in the Software without restriction, including without limitation the 15130803Smarcel# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16130803Smarcel# sell copies of the Software, and to permit persons to whom the Software is 17130803Smarcel# furnished to do so, subject to the following conditions: 18130803Smarcel# 19130803Smarcel# The above copyright notice and this permission notice shall be included in 20130803Smarcel# all copies or substantial portions of the Software. 21130803Smarcel# 22130803Smarcel# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23130803Smarcel# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24130803Smarcel# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25130803Smarcel# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26130803Smarcel# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27130803Smarcel# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28130803Smarcel# 29130803Smarcel# Except as contained in this notice, the name of the X Consortium shall not 30130803Smarcel# be used in advertising or otherwise to promote the sale, use or other deal- 31130803Smarcel# ings in this Software without prior written authorization from the X Consor- 32130803Smarcel# tium. 33130803Smarcel# 34130803Smarcel# 35130803Smarcel# FSF changes to this file are in the public domain. 36130803Smarcel# 37130803Smarcel# Calling this script install-sh is preferred over install.sh, to prevent 38130803Smarcel# `make' implicit rules from creating a file called install from it 39130803Smarcel# when there is no Makefile. 40130803Smarcel# 41130803Smarcel# This script is compatible with the BSD install script, but was written 42130803Smarcel# from scratch. It can only install one file at a time, a restriction 43130803Smarcel# shared with many OS's install programs. 44130803Smarcel 45130803Smarcel# set DOITPROG to echo to test this script 46130803Smarcel 47130803Smarcel# Don't use :- since 4.3BSD and earlier shells don't like it. 48130803Smarceldoit="${DOITPROG-}" 49130803Smarcel 50130803Smarcel# put in absolute paths if you don't have them in your path; or use env. vars. 51130803Smarcel 52130803Smarcelmvprog="${MVPROG-mv}" 53130803Smarcelcpprog="${CPPROG-cp}" 54130803Smarcelchmodprog="${CHMODPROG-chmod}" 55130803Smarcelchownprog="${CHOWNPROG-chown}" 56130803Smarcelchgrpprog="${CHGRPPROG-chgrp}" 57130803Smarcelstripprog="${STRIPPROG-strip}" 58130803Smarcelrmprog="${RMPROG-rm}" 59130803Smarcelmkdirprog="${MKDIRPROG-mkdir}" 60130803Smarcel 61130803Smarceltransformbasename= 62130803Smarceltransform_arg= 63130803Smarcelinstcmd="$mvprog" 64130803Smarcelchmodcmd="$chmodprog 0755" 65130803Smarcelchowncmd= 66130803Smarcelchgrpcmd= 67130803Smarcelstripcmd= 68130803Smarcelrmcmd="$rmprog -f" 69130803Smarcelmvcmd="$mvprog" 70130803Smarcelsrc= 71130803Smarceldst= 72130803Smarceldir_arg= 73130803Smarcel 74130803Smarcelusage="Usage: $0 [OPTION]... SRCFILE DSTFILE 75130803Smarcel or: $0 [OPTION]... SRCFILES... DIRECTORY 76130803Smarcel or: $0 -d DIRECTORIES... 77130803Smarcel 78130803SmarcelIn the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. 79130803SmarcelIn the second, create the directory path DIR. 80130803Smarcel 81130803SmarcelOptions: 82130803Smarcel-b=TRANSFORMBASENAME 83130803Smarcel-c copy source (using $cpprog) instead of moving (using $mvprog). 84130803Smarcel-d create directories instead of installing files. 85130803Smarcel-g GROUP $chgrp installed files to GROUP. 86130803Smarcel-m MODE $chmod installed files to MODE. 87130803Smarcel-o USER $chown installed files to USER. 88130803Smarcel-s strip installed files (using $stripprog). 89130803Smarcel-t=TRANSFORM 90130803Smarcel--help display this help and exit. 91130803Smarcel--version display version info and exit. 92130803Smarcel 93130803SmarcelEnvironment variables override the default commands: 94130803Smarcel CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 95130803Smarcel" 96130803Smarcel 97130803Smarcelwhile test -n "$1"; do 98130803Smarcel case $1 in 99130803Smarcel -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 100130803Smarcel shift 101130803Smarcel continue;; 102130803Smarcel 103130803Smarcel -c) instcmd=$cpprog 104130803Smarcel shift 105130803Smarcel continue;; 106130803Smarcel 107130803Smarcel -d) dir_arg=true 108130803Smarcel shift 109130803Smarcel continue;; 110130803Smarcel 111130803Smarcel -g) chgrpcmd="$chgrpprog $2" 112130803Smarcel shift 113130803Smarcel shift 114130803Smarcel continue;; 115130803Smarcel 116130803Smarcel --help) echo "$usage"; exit 0;; 117130803Smarcel 118130803Smarcel -m) chmodcmd="$chmodprog $2" 119130803Smarcel shift 120130803Smarcel shift 121130803Smarcel continue;; 122130803Smarcel 123130803Smarcel -o) chowncmd="$chownprog $2" 124130803Smarcel shift 125130803Smarcel shift 126130803Smarcel continue;; 127130803Smarcel 128130803Smarcel -s) stripcmd=$stripprog 129130803Smarcel shift 130130803Smarcel continue;; 131130803Smarcel 132130803Smarcel -t=*) transformarg=`echo $1 | sed 's/-t=//'` 133130803Smarcel shift 134130803Smarcel continue;; 135130803Smarcel 136130803Smarcel --version) echo "$0 $scriptversion"; exit 0;; 137130803Smarcel 138130803Smarcel *) # When -d is used, all remaining arguments are directories to create. 139130803Smarcel test -n "$dir_arg" && break 140130803Smarcel # Otherwise, the last argument is the destination. Remove it from $@. 141130803Smarcel for arg 142130803Smarcel do 143130803Smarcel if test -n "$dstarg"; then 144130803Smarcel # $@ is not empty: it contains at least $arg. 145130803Smarcel set fnord "$@" "$dstarg" 146130803Smarcel shift # fnord 147130803Smarcel fi 148130803Smarcel shift # arg 149130803Smarcel dstarg=$arg 150130803Smarcel done 151130803Smarcel break;; 152130803Smarcel esac 153130803Smarceldone 154130803Smarcel 155130803Smarcelif test -z "$1"; then 156130803Smarcel if test -z "$dir_arg"; then 157130803Smarcel echo "$0: no input file specified." >&2 158130803Smarcel exit 1 159130803Smarcel fi 160130803Smarcel # It's OK to call `install-sh -d' without argument. 161130803Smarcel # This can happen when creating conditional directories. 162130803Smarcel exit 0 163130803Smarcelfi 164130803Smarcel 165130803Smarcelfor src 166130803Smarceldo 167130803Smarcel # Protect names starting with `-'. 168130803Smarcel case $src in 169130803Smarcel -*) src=./$src ;; 170130803Smarcel esac 171130803Smarcel 172130803Smarcel if test -n "$dir_arg"; then 173130803Smarcel dst=$src 174130803Smarcel src= 175130803Smarcel 176130803Smarcel if test -d "$dst"; then 177130803Smarcel instcmd=: 178130803Smarcel chmodcmd= 179130803Smarcel else 180130803Smarcel instcmd=$mkdirprog 181130803Smarcel fi 182130803Smarcel else 183130803Smarcel # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 184130803Smarcel # might cause directories to be created, which would be especially bad 185130803Smarcel # if $src (and thus $dsttmp) contains '*'. 186130803Smarcel if test ! -f "$src" && test ! -d "$src"; then 187130803Smarcel echo "$0: $src does not exist." >&2 188130803Smarcel exit 1 189130803Smarcel fi 190130803Smarcel 191130803Smarcel if test -z "$dstarg"; then 192130803Smarcel echo "$0: no destination specified." >&2 193130803Smarcel exit 1 194130803Smarcel fi 195130803Smarcel 196130803Smarcel dst=$dstarg 197130803Smarcel # Protect names starting with `-'. 198130803Smarcel case $dst in 199130803Smarcel -*) dst=./$dst ;; 200130803Smarcel esac 201130803Smarcel 202130803Smarcel # If destination is a directory, append the input filename; won't work 203130803Smarcel # if double slashes aren't ignored. 204130803Smarcel if test -d "$dst"; then 205130803Smarcel dst=$dst/`basename "$src"` 206130803Smarcel fi 207130803Smarcel fi 208130803Smarcel 209130803Smarcel # This sed command emulates the dirname command. 210130803Smarcel dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 211130803Smarcel 212130803Smarcel # Make sure that the destination directory exists. 213130803Smarcel 214130803Smarcel # Skip lots of stat calls in the usual case. 215130803Smarcel if test ! -d "$dstdir"; then 216130803Smarcel defaultIFS=' 217130803Smarcel ' 218130803Smarcel IFS="${IFS-$defaultIFS}" 219130803Smarcel 220130803Smarcel oIFS=$IFS 221130803Smarcel # Some sh's can't handle IFS=/ for some reason. 222130803Smarcel IFS='%' 223130803Smarcel set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 224130803Smarcel IFS=$oIFS 225130803Smarcel 226130803Smarcel pathcomp= 227130803Smarcel 228130803Smarcel while test $# -ne 0 ; do 229130803Smarcel pathcomp=$pathcomp$1 230130803Smarcel shift 231130803Smarcel if test ! -d "$pathcomp"; then 232130803Smarcel $mkdirprog "$pathcomp" || lasterr=$? 233130803Smarcel # mkdir can fail with a `File exist' error in case several 234130803Smarcel # install-sh are creating the directory concurrently. This 235130803Smarcel # is OK. 236130803Smarcel test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; } 237130803Smarcel fi 238130803Smarcel pathcomp=$pathcomp/ 239130803Smarcel done 240130803Smarcel fi 241130803Smarcel 242130803Smarcel if test -n "$dir_arg"; then 243130803Smarcel $doit $instcmd "$dst" \ 244130803Smarcel && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 245130803Smarcel && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 246130803Smarcel && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 247130803Smarcel && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 248130803Smarcel 249130803Smarcel else 250130803Smarcel # If we're going to rename the final executable, determine the name now. 251130803Smarcel if test -z "$transformarg"; then 252130803Smarcel dstfile=`basename "$dst"` 253130803Smarcel else 254130803Smarcel dstfile=`basename "$dst" $transformbasename \ 255130803Smarcel | sed $transformarg`$transformbasename 256130803Smarcel fi 257130803Smarcel 258130803Smarcel # don't allow the sed command to completely eliminate the filename. 259130803Smarcel test -z "$dstfile" && dstfile=`basename "$dst"` 260130803Smarcel 261130803Smarcel # Make a couple of temp file names in the proper directory. 262130803Smarcel dsttmp=$dstdir/_inst.$$_ 263130803Smarcel rmtmp=$dstdir/_rm.$$_ 264130803Smarcel 265130803Smarcel # Trap to clean up those temp files at exit. 266130803Smarcel trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 267130803Smarcel trap '(exit $?); exit' 1 2 13 15 268130803Smarcel 269130803Smarcel # Move or copy the file name to the temp name 270130803Smarcel $doit $instcmd "$src" "$dsttmp" && 271130803Smarcel 272130803Smarcel # and set any options; do chmod last to preserve setuid bits. 273130803Smarcel # 274130803Smarcel # If any of these fail, we abort the whole thing. If we want to 275130803Smarcel # ignore errors from any of these, just make sure not to ignore 276130803Smarcel # errors from the above "$doit $instcmd $src $dsttmp" command. 277130803Smarcel # 278130803Smarcel { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 279130803Smarcel && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 280130803Smarcel && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 281130803Smarcel && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 282130803Smarcel 283130803Smarcel # Now remove or move aside any old file at destination location. We 284130803Smarcel # try this two ways since rm can't unlink itself on some systems and 285130803Smarcel # the destination file might be busy for other reasons. In this case, 286130803Smarcel # the final cleanup might fail but the new file should still install 287130803Smarcel # successfully. 288130803Smarcel { 289130803Smarcel if test -f "$dstdir/$dstfile"; then 290130803Smarcel $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 291130803Smarcel || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 292130803Smarcel || { 293130803Smarcel echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 294130803Smarcel (exit 1); exit 295130803Smarcel } 296130803Smarcel else 297130803Smarcel : 298130803Smarcel fi 299130803Smarcel } && 300130803Smarcel 301130803Smarcel # Now rename the file to the real destination. 302130803Smarcel $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 303130803Smarcel fi || { (exit 1); exit; } 304130803Smarceldone 305130803Smarcel 306130803Smarcel# The final little trick to "correctly" pass the exit status to the exit trap. 307130803Smarcel{ 308130803Smarcel (exit 0); exit 309130803Smarcel} 310130803Smarcel 311130803Smarcel# Local variables: 312130803Smarcel# eval: (add-hook 'write-file-hooks 'time-stamp) 313130803Smarcel# time-stamp-start: "scriptversion=" 314130803Smarcel# time-stamp-format: "%:y-%02m-%02d.%02H" 315130803Smarcel# time-stamp-end: "$" 316130803Smarcel# End: 317