install-sh revision 876ff6fe
1876ff6feSmrg#!/bin/sh 2876ff6feSmrg# install - install a program, script, or datafile 3876ff6feSmrg 4876ff6feSmrgscriptversion=2005-05-14.22 5876ff6feSmrg 6876ff6feSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 7876ff6feSmrg# later released in X11R6 (xc/config/util/install.sh) with the 8876ff6feSmrg# following copyright and license. 9876ff6feSmrg# 10876ff6feSmrg# Copyright (C) 1994 X Consortium 11876ff6feSmrg# 12876ff6feSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 13876ff6feSmrg# of this software and associated documentation files (the "Software"), to 14876ff6feSmrg# deal in the Software without restriction, including without limitation the 15876ff6feSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16876ff6feSmrg# sell copies of the Software, and to permit persons to whom the Software is 17876ff6feSmrg# furnished to do so, subject to the following conditions: 18876ff6feSmrg# 19876ff6feSmrg# The above copyright notice and this permission notice shall be included in 20876ff6feSmrg# all copies or substantial portions of the Software. 21876ff6feSmrg# 22876ff6feSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23876ff6feSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24876ff6feSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25876ff6feSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26876ff6feSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27876ff6feSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28876ff6feSmrg# 29876ff6feSmrg# Except as contained in this notice, the name of the X Consortium shall not 30876ff6feSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 31876ff6feSmrg# ings in this Software without prior written authorization from the X Consor- 32876ff6feSmrg# tium. 33876ff6feSmrg# 34876ff6feSmrg# 35876ff6feSmrg# FSF changes to this file are in the public domain. 36876ff6feSmrg# 37876ff6feSmrg# Calling this script install-sh is preferred over install.sh, to prevent 38876ff6feSmrg# `make' implicit rules from creating a file called install from it 39876ff6feSmrg# when there is no Makefile. 40876ff6feSmrg# 41876ff6feSmrg# This script is compatible with the BSD install script, but was written 42876ff6feSmrg# from scratch. It can only install one file at a time, a restriction 43876ff6feSmrg# shared with many OS's install programs. 44876ff6feSmrg 45876ff6feSmrg# set DOITPROG to echo to test this script 46876ff6feSmrg 47876ff6feSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48876ff6feSmrgdoit="${DOITPROG-}" 49876ff6feSmrg 50876ff6feSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 51876ff6feSmrg 52876ff6feSmrgmvprog="${MVPROG-mv}" 53876ff6feSmrgcpprog="${CPPROG-cp}" 54876ff6feSmrgchmodprog="${CHMODPROG-chmod}" 55876ff6feSmrgchownprog="${CHOWNPROG-chown}" 56876ff6feSmrgchgrpprog="${CHGRPPROG-chgrp}" 57876ff6feSmrgstripprog="${STRIPPROG-strip}" 58876ff6feSmrgrmprog="${RMPROG-rm}" 59876ff6feSmrgmkdirprog="${MKDIRPROG-mkdir}" 60876ff6feSmrg 61876ff6feSmrgchmodcmd="$chmodprog 0755" 62876ff6feSmrgchowncmd= 63876ff6feSmrgchgrpcmd= 64876ff6feSmrgstripcmd= 65876ff6feSmrgrmcmd="$rmprog -f" 66876ff6feSmrgmvcmd="$mvprog" 67876ff6feSmrgsrc= 68876ff6feSmrgdst= 69876ff6feSmrgdir_arg= 70876ff6feSmrgdstarg= 71876ff6feSmrgno_target_directory= 72876ff6feSmrg 73876ff6feSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74876ff6feSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 75876ff6feSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76876ff6feSmrg or: $0 [OPTION]... -d DIRECTORIES... 77876ff6feSmrg 78876ff6feSmrgIn the 1st form, copy SRCFILE to DSTFILE. 79876ff6feSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80876ff6feSmrgIn the 4th, create DIRECTORIES. 81876ff6feSmrg 82876ff6feSmrgOptions: 83876ff6feSmrg-c (ignored) 84876ff6feSmrg-d create directories instead of installing files. 85876ff6feSmrg-g GROUP $chgrpprog installed files to GROUP. 86876ff6feSmrg-m MODE $chmodprog installed files to MODE. 87876ff6feSmrg-o USER $chownprog installed files to USER. 88876ff6feSmrg-s $stripprog installed files. 89876ff6feSmrg-t DIRECTORY install into DIRECTORY. 90876ff6feSmrg-T report an error if DSTFILE is a directory. 91876ff6feSmrg--help display this help and exit. 92876ff6feSmrg--version display version info and exit. 93876ff6feSmrg 94876ff6feSmrgEnvironment variables override the default commands: 95876ff6feSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96876ff6feSmrg" 97876ff6feSmrg 98876ff6feSmrgwhile test -n "$1"; do 99876ff6feSmrg case $1 in 100876ff6feSmrg -c) shift 101876ff6feSmrg continue;; 102876ff6feSmrg 103876ff6feSmrg -d) dir_arg=true 104876ff6feSmrg shift 105876ff6feSmrg continue;; 106876ff6feSmrg 107876ff6feSmrg -g) chgrpcmd="$chgrpprog $2" 108876ff6feSmrg shift 109876ff6feSmrg shift 110876ff6feSmrg continue;; 111876ff6feSmrg 112876ff6feSmrg --help) echo "$usage"; exit $?;; 113876ff6feSmrg 114876ff6feSmrg -m) chmodcmd="$chmodprog $2" 115876ff6feSmrg shift 116876ff6feSmrg shift 117876ff6feSmrg continue;; 118876ff6feSmrg 119876ff6feSmrg -o) chowncmd="$chownprog $2" 120876ff6feSmrg shift 121876ff6feSmrg shift 122876ff6feSmrg continue;; 123876ff6feSmrg 124876ff6feSmrg -s) stripcmd=$stripprog 125876ff6feSmrg shift 126876ff6feSmrg continue;; 127876ff6feSmrg 128876ff6feSmrg -t) dstarg=$2 129876ff6feSmrg shift 130876ff6feSmrg shift 131876ff6feSmrg continue;; 132876ff6feSmrg 133876ff6feSmrg -T) no_target_directory=true 134876ff6feSmrg shift 135876ff6feSmrg continue;; 136876ff6feSmrg 137876ff6feSmrg --version) echo "$0 $scriptversion"; exit $?;; 138876ff6feSmrg 139876ff6feSmrg *) # When -d is used, all remaining arguments are directories to create. 140876ff6feSmrg # When -t is used, the destination is already specified. 141876ff6feSmrg test -n "$dir_arg$dstarg" && break 142876ff6feSmrg # Otherwise, the last argument is the destination. Remove it from $@. 143876ff6feSmrg for arg 144876ff6feSmrg do 145876ff6feSmrg if test -n "$dstarg"; then 146876ff6feSmrg # $@ is not empty: it contains at least $arg. 147876ff6feSmrg set fnord "$@" "$dstarg" 148876ff6feSmrg shift # fnord 149876ff6feSmrg fi 150876ff6feSmrg shift # arg 151876ff6feSmrg dstarg=$arg 152876ff6feSmrg done 153876ff6feSmrg break;; 154876ff6feSmrg esac 155876ff6feSmrgdone 156876ff6feSmrg 157876ff6feSmrgif test -z "$1"; then 158876ff6feSmrg if test -z "$dir_arg"; then 159876ff6feSmrg echo "$0: no input file specified." >&2 160876ff6feSmrg exit 1 161876ff6feSmrg fi 162876ff6feSmrg # It's OK to call `install-sh -d' without argument. 163876ff6feSmrg # This can happen when creating conditional directories. 164876ff6feSmrg exit 0 165876ff6feSmrgfi 166876ff6feSmrg 167876ff6feSmrgfor src 168876ff6feSmrgdo 169876ff6feSmrg # Protect names starting with `-'. 170876ff6feSmrg case $src in 171876ff6feSmrg -*) src=./$src ;; 172876ff6feSmrg esac 173876ff6feSmrg 174876ff6feSmrg if test -n "$dir_arg"; then 175876ff6feSmrg dst=$src 176876ff6feSmrg src= 177876ff6feSmrg 178876ff6feSmrg if test -d "$dst"; then 179876ff6feSmrg mkdircmd=: 180876ff6feSmrg chmodcmd= 181876ff6feSmrg else 182876ff6feSmrg mkdircmd=$mkdirprog 183876ff6feSmrg fi 184876ff6feSmrg else 185876ff6feSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186876ff6feSmrg # might cause directories to be created, which would be especially bad 187876ff6feSmrg # if $src (and thus $dsttmp) contains '*'. 188876ff6feSmrg if test ! -f "$src" && test ! -d "$src"; then 189876ff6feSmrg echo "$0: $src does not exist." >&2 190876ff6feSmrg exit 1 191876ff6feSmrg fi 192876ff6feSmrg 193876ff6feSmrg if test -z "$dstarg"; then 194876ff6feSmrg echo "$0: no destination specified." >&2 195876ff6feSmrg exit 1 196876ff6feSmrg fi 197876ff6feSmrg 198876ff6feSmrg dst=$dstarg 199876ff6feSmrg # Protect names starting with `-'. 200876ff6feSmrg case $dst in 201876ff6feSmrg -*) dst=./$dst ;; 202876ff6feSmrg esac 203876ff6feSmrg 204876ff6feSmrg # If destination is a directory, append the input filename; won't work 205876ff6feSmrg # if double slashes aren't ignored. 206876ff6feSmrg if test -d "$dst"; then 207876ff6feSmrg if test -n "$no_target_directory"; then 208876ff6feSmrg echo "$0: $dstarg: Is a directory" >&2 209876ff6feSmrg exit 1 210876ff6feSmrg fi 211876ff6feSmrg dst=$dst/`basename "$src"` 212876ff6feSmrg fi 213876ff6feSmrg fi 214876ff6feSmrg 215876ff6feSmrg # This sed command emulates the dirname command. 216876ff6feSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217876ff6feSmrg 218876ff6feSmrg # Make sure that the destination directory exists. 219876ff6feSmrg 220876ff6feSmrg # Skip lots of stat calls in the usual case. 221876ff6feSmrg if test ! -d "$dstdir"; then 222876ff6feSmrg defaultIFS=' 223876ff6feSmrg ' 224876ff6feSmrg IFS="${IFS-$defaultIFS}" 225876ff6feSmrg 226876ff6feSmrg oIFS=$IFS 227876ff6feSmrg # Some sh's can't handle IFS=/ for some reason. 228876ff6feSmrg IFS='%' 229876ff6feSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230876ff6feSmrg shift 231876ff6feSmrg IFS=$oIFS 232876ff6feSmrg 233876ff6feSmrg pathcomp= 234876ff6feSmrg 235876ff6feSmrg while test $# -ne 0 ; do 236876ff6feSmrg pathcomp=$pathcomp$1 237876ff6feSmrg shift 238876ff6feSmrg if test ! -d "$pathcomp"; then 239876ff6feSmrg $mkdirprog "$pathcomp" 240876ff6feSmrg # mkdir can fail with a `File exist' error in case several 241876ff6feSmrg # install-sh are creating the directory concurrently. This 242876ff6feSmrg # is OK. 243876ff6feSmrg test -d "$pathcomp" || exit 244876ff6feSmrg fi 245876ff6feSmrg pathcomp=$pathcomp/ 246876ff6feSmrg done 247876ff6feSmrg fi 248876ff6feSmrg 249876ff6feSmrg if test -n "$dir_arg"; then 250876ff6feSmrg $doit $mkdircmd "$dst" \ 251876ff6feSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252876ff6feSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253876ff6feSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254876ff6feSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255876ff6feSmrg 256876ff6feSmrg else 257876ff6feSmrg dstfile=`basename "$dst"` 258876ff6feSmrg 259876ff6feSmrg # Make a couple of temp file names in the proper directory. 260876ff6feSmrg dsttmp=$dstdir/_inst.$$_ 261876ff6feSmrg rmtmp=$dstdir/_rm.$$_ 262876ff6feSmrg 263876ff6feSmrg # Trap to clean up those temp files at exit. 264876ff6feSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265876ff6feSmrg trap '(exit $?); exit' 1 2 13 15 266876ff6feSmrg 267876ff6feSmrg # Copy the file name to the temp name. 268876ff6feSmrg $doit $cpprog "$src" "$dsttmp" && 269876ff6feSmrg 270876ff6feSmrg # and set any options; do chmod last to preserve setuid bits. 271876ff6feSmrg # 272876ff6feSmrg # If any of these fail, we abort the whole thing. If we want to 273876ff6feSmrg # ignore errors from any of these, just make sure not to ignore 274876ff6feSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 275876ff6feSmrg # 276876ff6feSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277876ff6feSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278876ff6feSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279876ff6feSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280876ff6feSmrg 281876ff6feSmrg # Now rename the file to the real destination. 282876ff6feSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283876ff6feSmrg || { 284876ff6feSmrg # The rename failed, perhaps because mv can't rename something else 285876ff6feSmrg # to itself, or perhaps because mv is so ancient that it does not 286876ff6feSmrg # support -f. 287876ff6feSmrg 288876ff6feSmrg # Now remove or move aside any old file at destination location. 289876ff6feSmrg # We try this two ways since rm can't unlink itself on some 290876ff6feSmrg # systems and the destination file might be busy for other 291876ff6feSmrg # reasons. In this case, the final cleanup might fail but the new 292876ff6feSmrg # file should still install successfully. 293876ff6feSmrg { 294876ff6feSmrg if test -f "$dstdir/$dstfile"; then 295876ff6feSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296876ff6feSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297876ff6feSmrg || { 298876ff6feSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299876ff6feSmrg (exit 1); exit 1 300876ff6feSmrg } 301876ff6feSmrg else 302876ff6feSmrg : 303876ff6feSmrg fi 304876ff6feSmrg } && 305876ff6feSmrg 306876ff6feSmrg # Now rename the file to the real destination. 307876ff6feSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308876ff6feSmrg } 309876ff6feSmrg } 310876ff6feSmrg fi || { (exit 1); exit 1; } 311876ff6feSmrgdone 312876ff6feSmrg 313876ff6feSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 314876ff6feSmrg{ 315876ff6feSmrg (exit 0); exit 0 316876ff6feSmrg} 317876ff6feSmrg 318876ff6feSmrg# Local variables: 319876ff6feSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 320876ff6feSmrg# time-stamp-start: "scriptversion=" 321876ff6feSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 322876ff6feSmrg# time-stamp-end: "$" 323876ff6feSmrg# End: 324