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