install-sh revision 444c061a
1444c061aSmrg#!/bin/sh 2444c061aSmrg# install - install a program, script, or datafile 3444c061aSmrg 4444c061aSmrgscriptversion=2005-05-14.22 5444c061aSmrg 6444c061aSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 7444c061aSmrg# later released in X11R6 (xc/config/util/install.sh) with the 8444c061aSmrg# following copyright and license. 9444c061aSmrg# 10444c061aSmrg# Copyright (C) 1994 X Consortium 11444c061aSmrg# 12444c061aSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 13444c061aSmrg# of this software and associated documentation files (the "Software"), to 14444c061aSmrg# deal in the Software without restriction, including without limitation the 15444c061aSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16444c061aSmrg# sell copies of the Software, and to permit persons to whom the Software is 17444c061aSmrg# furnished to do so, subject to the following conditions: 18444c061aSmrg# 19444c061aSmrg# The above copyright notice and this permission notice shall be included in 20444c061aSmrg# all copies or substantial portions of the Software. 21444c061aSmrg# 22444c061aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23444c061aSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24444c061aSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25444c061aSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26444c061aSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27444c061aSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28444c061aSmrg# 29444c061aSmrg# Except as contained in this notice, the name of the X Consortium shall not 30444c061aSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 31444c061aSmrg# ings in this Software without prior written authorization from the X Consor- 32444c061aSmrg# tium. 33444c061aSmrg# 34444c061aSmrg# 35444c061aSmrg# FSF changes to this file are in the public domain. 36444c061aSmrg# 37444c061aSmrg# Calling this script install-sh is preferred over install.sh, to prevent 38444c061aSmrg# `make' implicit rules from creating a file called install from it 39444c061aSmrg# when there is no Makefile. 40444c061aSmrg# 41444c061aSmrg# This script is compatible with the BSD install script, but was written 42444c061aSmrg# from scratch. It can only install one file at a time, a restriction 43444c061aSmrg# shared with many OS's install programs. 44444c061aSmrg 45444c061aSmrg# set DOITPROG to echo to test this script 46444c061aSmrg 47444c061aSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48444c061aSmrgdoit="${DOITPROG-}" 49444c061aSmrg 50444c061aSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 51444c061aSmrg 52444c061aSmrgmvprog="${MVPROG-mv}" 53444c061aSmrgcpprog="${CPPROG-cp}" 54444c061aSmrgchmodprog="${CHMODPROG-chmod}" 55444c061aSmrgchownprog="${CHOWNPROG-chown}" 56444c061aSmrgchgrpprog="${CHGRPPROG-chgrp}" 57444c061aSmrgstripprog="${STRIPPROG-strip}" 58444c061aSmrgrmprog="${RMPROG-rm}" 59444c061aSmrgmkdirprog="${MKDIRPROG-mkdir}" 60444c061aSmrg 61444c061aSmrgchmodcmd="$chmodprog 0755" 62444c061aSmrgchowncmd= 63444c061aSmrgchgrpcmd= 64444c061aSmrgstripcmd= 65444c061aSmrgrmcmd="$rmprog -f" 66444c061aSmrgmvcmd="$mvprog" 67444c061aSmrgsrc= 68444c061aSmrgdst= 69444c061aSmrgdir_arg= 70444c061aSmrgdstarg= 71444c061aSmrgno_target_directory= 72444c061aSmrg 73444c061aSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74444c061aSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 75444c061aSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76444c061aSmrg or: $0 [OPTION]... -d DIRECTORIES... 77444c061aSmrg 78444c061aSmrgIn the 1st form, copy SRCFILE to DSTFILE. 79444c061aSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80444c061aSmrgIn the 4th, create DIRECTORIES. 81444c061aSmrg 82444c061aSmrgOptions: 83444c061aSmrg-c (ignored) 84444c061aSmrg-d create directories instead of installing files. 85444c061aSmrg-g GROUP $chgrpprog installed files to GROUP. 86444c061aSmrg-m MODE $chmodprog installed files to MODE. 87444c061aSmrg-o USER $chownprog installed files to USER. 88444c061aSmrg-s $stripprog installed files. 89444c061aSmrg-t DIRECTORY install into DIRECTORY. 90444c061aSmrg-T report an error if DSTFILE is a directory. 91444c061aSmrg--help display this help and exit. 92444c061aSmrg--version display version info and exit. 93444c061aSmrg 94444c061aSmrgEnvironment variables override the default commands: 95444c061aSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96444c061aSmrg" 97444c061aSmrg 98444c061aSmrgwhile test -n "$1"; do 99444c061aSmrg case $1 in 100444c061aSmrg -c) shift 101444c061aSmrg continue;; 102444c061aSmrg 103444c061aSmrg -d) dir_arg=true 104444c061aSmrg shift 105444c061aSmrg continue;; 106444c061aSmrg 107444c061aSmrg -g) chgrpcmd="$chgrpprog $2" 108444c061aSmrg shift 109444c061aSmrg shift 110444c061aSmrg continue;; 111444c061aSmrg 112444c061aSmrg --help) echo "$usage"; exit $?;; 113444c061aSmrg 114444c061aSmrg -m) chmodcmd="$chmodprog $2" 115444c061aSmrg shift 116444c061aSmrg shift 117444c061aSmrg continue;; 118444c061aSmrg 119444c061aSmrg -o) chowncmd="$chownprog $2" 120444c061aSmrg shift 121444c061aSmrg shift 122444c061aSmrg continue;; 123444c061aSmrg 124444c061aSmrg -s) stripcmd=$stripprog 125444c061aSmrg shift 126444c061aSmrg continue;; 127444c061aSmrg 128444c061aSmrg -t) dstarg=$2 129444c061aSmrg shift 130444c061aSmrg shift 131444c061aSmrg continue;; 132444c061aSmrg 133444c061aSmrg -T) no_target_directory=true 134444c061aSmrg shift 135444c061aSmrg continue;; 136444c061aSmrg 137444c061aSmrg --version) echo "$0 $scriptversion"; exit $?;; 138444c061aSmrg 139444c061aSmrg *) # When -d is used, all remaining arguments are directories to create. 140444c061aSmrg # When -t is used, the destination is already specified. 141444c061aSmrg test -n "$dir_arg$dstarg" && break 142444c061aSmrg # Otherwise, the last argument is the destination. Remove it from $@. 143444c061aSmrg for arg 144444c061aSmrg do 145444c061aSmrg if test -n "$dstarg"; then 146444c061aSmrg # $@ is not empty: it contains at least $arg. 147444c061aSmrg set fnord "$@" "$dstarg" 148444c061aSmrg shift # fnord 149444c061aSmrg fi 150444c061aSmrg shift # arg 151444c061aSmrg dstarg=$arg 152444c061aSmrg done 153444c061aSmrg break;; 154444c061aSmrg esac 155444c061aSmrgdone 156444c061aSmrg 157444c061aSmrgif test -z "$1"; then 158444c061aSmrg if test -z "$dir_arg"; then 159444c061aSmrg echo "$0: no input file specified." >&2 160444c061aSmrg exit 1 161444c061aSmrg fi 162444c061aSmrg # It's OK to call `install-sh -d' without argument. 163444c061aSmrg # This can happen when creating conditional directories. 164444c061aSmrg exit 0 165444c061aSmrgfi 166444c061aSmrg 167444c061aSmrgfor src 168444c061aSmrgdo 169444c061aSmrg # Protect names starting with `-'. 170444c061aSmrg case $src in 171444c061aSmrg -*) src=./$src ;; 172444c061aSmrg esac 173444c061aSmrg 174444c061aSmrg if test -n "$dir_arg"; then 175444c061aSmrg dst=$src 176444c061aSmrg src= 177444c061aSmrg 178444c061aSmrg if test -d "$dst"; then 179444c061aSmrg mkdircmd=: 180444c061aSmrg chmodcmd= 181444c061aSmrg else 182444c061aSmrg mkdircmd=$mkdirprog 183444c061aSmrg fi 184444c061aSmrg else 185444c061aSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186444c061aSmrg # might cause directories to be created, which would be especially bad 187444c061aSmrg # if $src (and thus $dsttmp) contains '*'. 188444c061aSmrg if test ! -f "$src" && test ! -d "$src"; then 189444c061aSmrg echo "$0: $src does not exist." >&2 190444c061aSmrg exit 1 191444c061aSmrg fi 192444c061aSmrg 193444c061aSmrg if test -z "$dstarg"; then 194444c061aSmrg echo "$0: no destination specified." >&2 195444c061aSmrg exit 1 196444c061aSmrg fi 197444c061aSmrg 198444c061aSmrg dst=$dstarg 199444c061aSmrg # Protect names starting with `-'. 200444c061aSmrg case $dst in 201444c061aSmrg -*) dst=./$dst ;; 202444c061aSmrg esac 203444c061aSmrg 204444c061aSmrg # If destination is a directory, append the input filename; won't work 205444c061aSmrg # if double slashes aren't ignored. 206444c061aSmrg if test -d "$dst"; then 207444c061aSmrg if test -n "$no_target_directory"; then 208444c061aSmrg echo "$0: $dstarg: Is a directory" >&2 209444c061aSmrg exit 1 210444c061aSmrg fi 211444c061aSmrg dst=$dst/`basename "$src"` 212444c061aSmrg fi 213444c061aSmrg fi 214444c061aSmrg 215444c061aSmrg # This sed command emulates the dirname command. 216444c061aSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217444c061aSmrg 218444c061aSmrg # Make sure that the destination directory exists. 219444c061aSmrg 220444c061aSmrg # Skip lots of stat calls in the usual case. 221444c061aSmrg if test ! -d "$dstdir"; then 222444c061aSmrg defaultIFS=' 223444c061aSmrg ' 224444c061aSmrg IFS="${IFS-$defaultIFS}" 225444c061aSmrg 226444c061aSmrg oIFS=$IFS 227444c061aSmrg # Some sh's can't handle IFS=/ for some reason. 228444c061aSmrg IFS='%' 229444c061aSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230444c061aSmrg shift 231444c061aSmrg IFS=$oIFS 232444c061aSmrg 233444c061aSmrg pathcomp= 234444c061aSmrg 235444c061aSmrg while test $# -ne 0 ; do 236444c061aSmrg pathcomp=$pathcomp$1 237444c061aSmrg shift 238444c061aSmrg if test ! -d "$pathcomp"; then 239444c061aSmrg $mkdirprog "$pathcomp" 240444c061aSmrg # mkdir can fail with a `File exist' error in case several 241444c061aSmrg # install-sh are creating the directory concurrently. This 242444c061aSmrg # is OK. 243444c061aSmrg test -d "$pathcomp" || exit 244444c061aSmrg fi 245444c061aSmrg pathcomp=$pathcomp/ 246444c061aSmrg done 247444c061aSmrg fi 248444c061aSmrg 249444c061aSmrg if test -n "$dir_arg"; then 250444c061aSmrg $doit $mkdircmd "$dst" \ 251444c061aSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252444c061aSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253444c061aSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254444c061aSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255444c061aSmrg 256444c061aSmrg else 257444c061aSmrg dstfile=`basename "$dst"` 258444c061aSmrg 259444c061aSmrg # Make a couple of temp file names in the proper directory. 260444c061aSmrg dsttmp=$dstdir/_inst.$$_ 261444c061aSmrg rmtmp=$dstdir/_rm.$$_ 262444c061aSmrg 263444c061aSmrg # Trap to clean up those temp files at exit. 264444c061aSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265444c061aSmrg trap '(exit $?); exit' 1 2 13 15 266444c061aSmrg 267444c061aSmrg # Copy the file name to the temp name. 268444c061aSmrg $doit $cpprog "$src" "$dsttmp" && 269444c061aSmrg 270444c061aSmrg # and set any options; do chmod last to preserve setuid bits. 271444c061aSmrg # 272444c061aSmrg # If any of these fail, we abort the whole thing. If we want to 273444c061aSmrg # ignore errors from any of these, just make sure not to ignore 274444c061aSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 275444c061aSmrg # 276444c061aSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277444c061aSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278444c061aSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279444c061aSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280444c061aSmrg 281444c061aSmrg # Now rename the file to the real destination. 282444c061aSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283444c061aSmrg || { 284444c061aSmrg # The rename failed, perhaps because mv can't rename something else 285444c061aSmrg # to itself, or perhaps because mv is so ancient that it does not 286444c061aSmrg # support -f. 287444c061aSmrg 288444c061aSmrg # Now remove or move aside any old file at destination location. 289444c061aSmrg # We try this two ways since rm can't unlink itself on some 290444c061aSmrg # systems and the destination file might be busy for other 291444c061aSmrg # reasons. In this case, the final cleanup might fail but the new 292444c061aSmrg # file should still install successfully. 293444c061aSmrg { 294444c061aSmrg if test -f "$dstdir/$dstfile"; then 295444c061aSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296444c061aSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297444c061aSmrg || { 298444c061aSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299444c061aSmrg (exit 1); exit 1 300444c061aSmrg } 301444c061aSmrg else 302444c061aSmrg : 303444c061aSmrg fi 304444c061aSmrg } && 305444c061aSmrg 306444c061aSmrg # Now rename the file to the real destination. 307444c061aSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308444c061aSmrg } 309444c061aSmrg } 310444c061aSmrg fi || { (exit 1); exit 1; } 311444c061aSmrgdone 312444c061aSmrg 313444c061aSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 314444c061aSmrg{ 315444c061aSmrg (exit 0); exit 0 316444c061aSmrg} 317444c061aSmrg 318444c061aSmrg# Local variables: 319444c061aSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 320444c061aSmrg# time-stamp-start: "scriptversion=" 321444c061aSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 322444c061aSmrg# time-stamp-end: "$" 323444c061aSmrg# End: 324