install-sh revision bb9c676a
1bb9c676aSmrg#!/bin/sh 2bb9c676aSmrg# install - install a program, script, or datafile 3bb9c676aSmrg 4bb9c676aSmrgscriptversion=2005-05-14.22 5bb9c676aSmrg 6bb9c676aSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 7bb9c676aSmrg# later released in X11R6 (xc/config/util/install.sh) with the 8bb9c676aSmrg# following copyright and license. 9bb9c676aSmrg# 10bb9c676aSmrg# Copyright (C) 1994 X Consortium 11bb9c676aSmrg# 12bb9c676aSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 13bb9c676aSmrg# of this software and associated documentation files (the "Software"), to 14bb9c676aSmrg# deal in the Software without restriction, including without limitation the 15bb9c676aSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16bb9c676aSmrg# sell copies of the Software, and to permit persons to whom the Software is 17bb9c676aSmrg# furnished to do so, subject to the following conditions: 18bb9c676aSmrg# 19bb9c676aSmrg# The above copyright notice and this permission notice shall be included in 20bb9c676aSmrg# all copies or substantial portions of the Software. 21bb9c676aSmrg# 22bb9c676aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23bb9c676aSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24bb9c676aSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25bb9c676aSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26bb9c676aSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27bb9c676aSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28bb9c676aSmrg# 29bb9c676aSmrg# Except as contained in this notice, the name of the X Consortium shall not 30bb9c676aSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 31bb9c676aSmrg# ings in this Software without prior written authorization from the X Consor- 32bb9c676aSmrg# tium. 33bb9c676aSmrg# 34bb9c676aSmrg# 35bb9c676aSmrg# FSF changes to this file are in the public domain. 36bb9c676aSmrg# 37bb9c676aSmrg# Calling this script install-sh is preferred over install.sh, to prevent 38bb9c676aSmrg# `make' implicit rules from creating a file called install from it 39bb9c676aSmrg# when there is no Makefile. 40bb9c676aSmrg# 41bb9c676aSmrg# This script is compatible with the BSD install script, but was written 42bb9c676aSmrg# from scratch. It can only install one file at a time, a restriction 43bb9c676aSmrg# shared with many OS's install programs. 44bb9c676aSmrg 45bb9c676aSmrg# set DOITPROG to echo to test this script 46bb9c676aSmrg 47bb9c676aSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48bb9c676aSmrgdoit="${DOITPROG-}" 49bb9c676aSmrg 50bb9c676aSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 51bb9c676aSmrg 52bb9c676aSmrgmvprog="${MVPROG-mv}" 53bb9c676aSmrgcpprog="${CPPROG-cp}" 54bb9c676aSmrgchmodprog="${CHMODPROG-chmod}" 55bb9c676aSmrgchownprog="${CHOWNPROG-chown}" 56bb9c676aSmrgchgrpprog="${CHGRPPROG-chgrp}" 57bb9c676aSmrgstripprog="${STRIPPROG-strip}" 58bb9c676aSmrgrmprog="${RMPROG-rm}" 59bb9c676aSmrgmkdirprog="${MKDIRPROG-mkdir}" 60bb9c676aSmrg 61bb9c676aSmrgchmodcmd="$chmodprog 0755" 62bb9c676aSmrgchowncmd= 63bb9c676aSmrgchgrpcmd= 64bb9c676aSmrgstripcmd= 65bb9c676aSmrgrmcmd="$rmprog -f" 66bb9c676aSmrgmvcmd="$mvprog" 67bb9c676aSmrgsrc= 68bb9c676aSmrgdst= 69bb9c676aSmrgdir_arg= 70bb9c676aSmrgdstarg= 71bb9c676aSmrgno_target_directory= 72bb9c676aSmrg 73bb9c676aSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74bb9c676aSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 75bb9c676aSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76bb9c676aSmrg or: $0 [OPTION]... -d DIRECTORIES... 77bb9c676aSmrg 78bb9c676aSmrgIn the 1st form, copy SRCFILE to DSTFILE. 79bb9c676aSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80bb9c676aSmrgIn the 4th, create DIRECTORIES. 81bb9c676aSmrg 82bb9c676aSmrgOptions: 83bb9c676aSmrg-c (ignored) 84bb9c676aSmrg-d create directories instead of installing files. 85bb9c676aSmrg-g GROUP $chgrpprog installed files to GROUP. 86bb9c676aSmrg-m MODE $chmodprog installed files to MODE. 87bb9c676aSmrg-o USER $chownprog installed files to USER. 88bb9c676aSmrg-s $stripprog installed files. 89bb9c676aSmrg-t DIRECTORY install into DIRECTORY. 90bb9c676aSmrg-T report an error if DSTFILE is a directory. 91bb9c676aSmrg--help display this help and exit. 92bb9c676aSmrg--version display version info and exit. 93bb9c676aSmrg 94bb9c676aSmrgEnvironment variables override the default commands: 95bb9c676aSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96bb9c676aSmrg" 97bb9c676aSmrg 98bb9c676aSmrgwhile test -n "$1"; do 99bb9c676aSmrg case $1 in 100bb9c676aSmrg -c) shift 101bb9c676aSmrg continue;; 102bb9c676aSmrg 103bb9c676aSmrg -d) dir_arg=true 104bb9c676aSmrg shift 105bb9c676aSmrg continue;; 106bb9c676aSmrg 107bb9c676aSmrg -g) chgrpcmd="$chgrpprog $2" 108bb9c676aSmrg shift 109bb9c676aSmrg shift 110bb9c676aSmrg continue;; 111bb9c676aSmrg 112bb9c676aSmrg --help) echo "$usage"; exit $?;; 113bb9c676aSmrg 114bb9c676aSmrg -m) chmodcmd="$chmodprog $2" 115bb9c676aSmrg shift 116bb9c676aSmrg shift 117bb9c676aSmrg continue;; 118bb9c676aSmrg 119bb9c676aSmrg -o) chowncmd="$chownprog $2" 120bb9c676aSmrg shift 121bb9c676aSmrg shift 122bb9c676aSmrg continue;; 123bb9c676aSmrg 124bb9c676aSmrg -s) stripcmd=$stripprog 125bb9c676aSmrg shift 126bb9c676aSmrg continue;; 127bb9c676aSmrg 128bb9c676aSmrg -t) dstarg=$2 129bb9c676aSmrg shift 130bb9c676aSmrg shift 131bb9c676aSmrg continue;; 132bb9c676aSmrg 133bb9c676aSmrg -T) no_target_directory=true 134bb9c676aSmrg shift 135bb9c676aSmrg continue;; 136bb9c676aSmrg 137bb9c676aSmrg --version) echo "$0 $scriptversion"; exit $?;; 138bb9c676aSmrg 139bb9c676aSmrg *) # When -d is used, all remaining arguments are directories to create. 140bb9c676aSmrg # When -t is used, the destination is already specified. 141bb9c676aSmrg test -n "$dir_arg$dstarg" && break 142bb9c676aSmrg # Otherwise, the last argument is the destination. Remove it from $@. 143bb9c676aSmrg for arg 144bb9c676aSmrg do 145bb9c676aSmrg if test -n "$dstarg"; then 146bb9c676aSmrg # $@ is not empty: it contains at least $arg. 147bb9c676aSmrg set fnord "$@" "$dstarg" 148bb9c676aSmrg shift # fnord 149bb9c676aSmrg fi 150bb9c676aSmrg shift # arg 151bb9c676aSmrg dstarg=$arg 152bb9c676aSmrg done 153bb9c676aSmrg break;; 154bb9c676aSmrg esac 155bb9c676aSmrgdone 156bb9c676aSmrg 157bb9c676aSmrgif test -z "$1"; then 158bb9c676aSmrg if test -z "$dir_arg"; then 159bb9c676aSmrg echo "$0: no input file specified." >&2 160bb9c676aSmrg exit 1 161bb9c676aSmrg fi 162bb9c676aSmrg # It's OK to call `install-sh -d' without argument. 163bb9c676aSmrg # This can happen when creating conditional directories. 164bb9c676aSmrg exit 0 165bb9c676aSmrgfi 166bb9c676aSmrg 167bb9c676aSmrgfor src 168bb9c676aSmrgdo 169bb9c676aSmrg # Protect names starting with `-'. 170bb9c676aSmrg case $src in 171bb9c676aSmrg -*) src=./$src ;; 172bb9c676aSmrg esac 173bb9c676aSmrg 174bb9c676aSmrg if test -n "$dir_arg"; then 175bb9c676aSmrg dst=$src 176bb9c676aSmrg src= 177bb9c676aSmrg 178bb9c676aSmrg if test -d "$dst"; then 179bb9c676aSmrg mkdircmd=: 180bb9c676aSmrg chmodcmd= 181bb9c676aSmrg else 182bb9c676aSmrg mkdircmd=$mkdirprog 183bb9c676aSmrg fi 184bb9c676aSmrg else 185bb9c676aSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186bb9c676aSmrg # might cause directories to be created, which would be especially bad 187bb9c676aSmrg # if $src (and thus $dsttmp) contains '*'. 188bb9c676aSmrg if test ! -f "$src" && test ! -d "$src"; then 189bb9c676aSmrg echo "$0: $src does not exist." >&2 190bb9c676aSmrg exit 1 191bb9c676aSmrg fi 192bb9c676aSmrg 193bb9c676aSmrg if test -z "$dstarg"; then 194bb9c676aSmrg echo "$0: no destination specified." >&2 195bb9c676aSmrg exit 1 196bb9c676aSmrg fi 197bb9c676aSmrg 198bb9c676aSmrg dst=$dstarg 199bb9c676aSmrg # Protect names starting with `-'. 200bb9c676aSmrg case $dst in 201bb9c676aSmrg -*) dst=./$dst ;; 202bb9c676aSmrg esac 203bb9c676aSmrg 204bb9c676aSmrg # If destination is a directory, append the input filename; won't work 205bb9c676aSmrg # if double slashes aren't ignored. 206bb9c676aSmrg if test -d "$dst"; then 207bb9c676aSmrg if test -n "$no_target_directory"; then 208bb9c676aSmrg echo "$0: $dstarg: Is a directory" >&2 209bb9c676aSmrg exit 1 210bb9c676aSmrg fi 211bb9c676aSmrg dst=$dst/`basename "$src"` 212bb9c676aSmrg fi 213bb9c676aSmrg fi 214bb9c676aSmrg 215bb9c676aSmrg # This sed command emulates the dirname command. 216bb9c676aSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217bb9c676aSmrg 218bb9c676aSmrg # Make sure that the destination directory exists. 219bb9c676aSmrg 220bb9c676aSmrg # Skip lots of stat calls in the usual case. 221bb9c676aSmrg if test ! -d "$dstdir"; then 222bb9c676aSmrg defaultIFS=' 223bb9c676aSmrg ' 224bb9c676aSmrg IFS="${IFS-$defaultIFS}" 225bb9c676aSmrg 226bb9c676aSmrg oIFS=$IFS 227bb9c676aSmrg # Some sh's can't handle IFS=/ for some reason. 228bb9c676aSmrg IFS='%' 229bb9c676aSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230bb9c676aSmrg shift 231bb9c676aSmrg IFS=$oIFS 232bb9c676aSmrg 233bb9c676aSmrg pathcomp= 234bb9c676aSmrg 235bb9c676aSmrg while test $# -ne 0 ; do 236bb9c676aSmrg pathcomp=$pathcomp$1 237bb9c676aSmrg shift 238bb9c676aSmrg if test ! -d "$pathcomp"; then 239bb9c676aSmrg $mkdirprog "$pathcomp" 240bb9c676aSmrg # mkdir can fail with a `File exist' error in case several 241bb9c676aSmrg # install-sh are creating the directory concurrently. This 242bb9c676aSmrg # is OK. 243bb9c676aSmrg test -d "$pathcomp" || exit 244bb9c676aSmrg fi 245bb9c676aSmrg pathcomp=$pathcomp/ 246bb9c676aSmrg done 247bb9c676aSmrg fi 248bb9c676aSmrg 249bb9c676aSmrg if test -n "$dir_arg"; then 250bb9c676aSmrg $doit $mkdircmd "$dst" \ 251bb9c676aSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252bb9c676aSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253bb9c676aSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254bb9c676aSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255bb9c676aSmrg 256bb9c676aSmrg else 257bb9c676aSmrg dstfile=`basename "$dst"` 258bb9c676aSmrg 259bb9c676aSmrg # Make a couple of temp file names in the proper directory. 260bb9c676aSmrg dsttmp=$dstdir/_inst.$$_ 261bb9c676aSmrg rmtmp=$dstdir/_rm.$$_ 262bb9c676aSmrg 263bb9c676aSmrg # Trap to clean up those temp files at exit. 264bb9c676aSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265bb9c676aSmrg trap '(exit $?); exit' 1 2 13 15 266bb9c676aSmrg 267bb9c676aSmrg # Copy the file name to the temp name. 268bb9c676aSmrg $doit $cpprog "$src" "$dsttmp" && 269bb9c676aSmrg 270bb9c676aSmrg # and set any options; do chmod last to preserve setuid bits. 271bb9c676aSmrg # 272bb9c676aSmrg # If any of these fail, we abort the whole thing. If we want to 273bb9c676aSmrg # ignore errors from any of these, just make sure not to ignore 274bb9c676aSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 275bb9c676aSmrg # 276bb9c676aSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277bb9c676aSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278bb9c676aSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279bb9c676aSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280bb9c676aSmrg 281bb9c676aSmrg # Now rename the file to the real destination. 282bb9c676aSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283bb9c676aSmrg || { 284bb9c676aSmrg # The rename failed, perhaps because mv can't rename something else 285bb9c676aSmrg # to itself, or perhaps because mv is so ancient that it does not 286bb9c676aSmrg # support -f. 287bb9c676aSmrg 288bb9c676aSmrg # Now remove or move aside any old file at destination location. 289bb9c676aSmrg # We try this two ways since rm can't unlink itself on some 290bb9c676aSmrg # systems and the destination file might be busy for other 291bb9c676aSmrg # reasons. In this case, the final cleanup might fail but the new 292bb9c676aSmrg # file should still install successfully. 293bb9c676aSmrg { 294bb9c676aSmrg if test -f "$dstdir/$dstfile"; then 295bb9c676aSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296bb9c676aSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297bb9c676aSmrg || { 298bb9c676aSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299bb9c676aSmrg (exit 1); exit 1 300bb9c676aSmrg } 301bb9c676aSmrg else 302bb9c676aSmrg : 303bb9c676aSmrg fi 304bb9c676aSmrg } && 305bb9c676aSmrg 306bb9c676aSmrg # Now rename the file to the real destination. 307bb9c676aSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308bb9c676aSmrg } 309bb9c676aSmrg } 310bb9c676aSmrg fi || { (exit 1); exit 1; } 311bb9c676aSmrgdone 312bb9c676aSmrg 313bb9c676aSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 314bb9c676aSmrg{ 315bb9c676aSmrg (exit 0); exit 0 316bb9c676aSmrg} 317bb9c676aSmrg 318bb9c676aSmrg# Local variables: 319bb9c676aSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 320bb9c676aSmrg# time-stamp-start: "scriptversion=" 321bb9c676aSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 322bb9c676aSmrg# time-stamp-end: "$" 323bb9c676aSmrg# End: 324