install-sh revision 191cded7
1191cded7Smrg#!/bin/sh 2191cded7Smrg# install - install a program, script, or datafile 3191cded7Smrg 4191cded7Smrgscriptversion=2005-05-14.22 5191cded7Smrg 6191cded7Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 7191cded7Smrg# later released in X11R6 (xc/config/util/install.sh) with the 8191cded7Smrg# following copyright and license. 9191cded7Smrg# 10191cded7Smrg# Copyright (C) 1994 X Consortium 11191cded7Smrg# 12191cded7Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 13191cded7Smrg# of this software and associated documentation files (the "Software"), to 14191cded7Smrg# deal in the Software without restriction, including without limitation the 15191cded7Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16191cded7Smrg# sell copies of the Software, and to permit persons to whom the Software is 17191cded7Smrg# furnished to do so, subject to the following conditions: 18191cded7Smrg# 19191cded7Smrg# The above copyright notice and this permission notice shall be included in 20191cded7Smrg# all copies or substantial portions of the Software. 21191cded7Smrg# 22191cded7Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23191cded7Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24191cded7Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25191cded7Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26191cded7Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27191cded7Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28191cded7Smrg# 29191cded7Smrg# Except as contained in this notice, the name of the X Consortium shall not 30191cded7Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 31191cded7Smrg# ings in this Software without prior written authorization from the X Consor- 32191cded7Smrg# tium. 33191cded7Smrg# 34191cded7Smrg# 35191cded7Smrg# FSF changes to this file are in the public domain. 36191cded7Smrg# 37191cded7Smrg# Calling this script install-sh is preferred over install.sh, to prevent 38191cded7Smrg# `make' implicit rules from creating a file called install from it 39191cded7Smrg# when there is no Makefile. 40191cded7Smrg# 41191cded7Smrg# This script is compatible with the BSD install script, but was written 42191cded7Smrg# from scratch. It can only install one file at a time, a restriction 43191cded7Smrg# shared with many OS's install programs. 44191cded7Smrg 45191cded7Smrg# set DOITPROG to echo to test this script 46191cded7Smrg 47191cded7Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48191cded7Smrgdoit="${DOITPROG-}" 49191cded7Smrg 50191cded7Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 51191cded7Smrg 52191cded7Smrgmvprog="${MVPROG-mv}" 53191cded7Smrgcpprog="${CPPROG-cp}" 54191cded7Smrgchmodprog="${CHMODPROG-chmod}" 55191cded7Smrgchownprog="${CHOWNPROG-chown}" 56191cded7Smrgchgrpprog="${CHGRPPROG-chgrp}" 57191cded7Smrgstripprog="${STRIPPROG-strip}" 58191cded7Smrgrmprog="${RMPROG-rm}" 59191cded7Smrgmkdirprog="${MKDIRPROG-mkdir}" 60191cded7Smrg 61191cded7Smrgchmodcmd="$chmodprog 0755" 62191cded7Smrgchowncmd= 63191cded7Smrgchgrpcmd= 64191cded7Smrgstripcmd= 65191cded7Smrgrmcmd="$rmprog -f" 66191cded7Smrgmvcmd="$mvprog" 67191cded7Smrgsrc= 68191cded7Smrgdst= 69191cded7Smrgdir_arg= 70191cded7Smrgdstarg= 71191cded7Smrgno_target_directory= 72191cded7Smrg 73191cded7Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74191cded7Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 75191cded7Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76191cded7Smrg or: $0 [OPTION]... -d DIRECTORIES... 77191cded7Smrg 78191cded7SmrgIn the 1st form, copy SRCFILE to DSTFILE. 79191cded7SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80191cded7SmrgIn the 4th, create DIRECTORIES. 81191cded7Smrg 82191cded7SmrgOptions: 83191cded7Smrg-c (ignored) 84191cded7Smrg-d create directories instead of installing files. 85191cded7Smrg-g GROUP $chgrpprog installed files to GROUP. 86191cded7Smrg-m MODE $chmodprog installed files to MODE. 87191cded7Smrg-o USER $chownprog installed files to USER. 88191cded7Smrg-s $stripprog installed files. 89191cded7Smrg-t DIRECTORY install into DIRECTORY. 90191cded7Smrg-T report an error if DSTFILE is a directory. 91191cded7Smrg--help display this help and exit. 92191cded7Smrg--version display version info and exit. 93191cded7Smrg 94191cded7SmrgEnvironment variables override the default commands: 95191cded7Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96191cded7Smrg" 97191cded7Smrg 98191cded7Smrgwhile test -n "$1"; do 99191cded7Smrg case $1 in 100191cded7Smrg -c) shift 101191cded7Smrg continue;; 102191cded7Smrg 103191cded7Smrg -d) dir_arg=true 104191cded7Smrg shift 105191cded7Smrg continue;; 106191cded7Smrg 107191cded7Smrg -g) chgrpcmd="$chgrpprog $2" 108191cded7Smrg shift 109191cded7Smrg shift 110191cded7Smrg continue;; 111191cded7Smrg 112191cded7Smrg --help) echo "$usage"; exit $?;; 113191cded7Smrg 114191cded7Smrg -m) chmodcmd="$chmodprog $2" 115191cded7Smrg shift 116191cded7Smrg shift 117191cded7Smrg continue;; 118191cded7Smrg 119191cded7Smrg -o) chowncmd="$chownprog $2" 120191cded7Smrg shift 121191cded7Smrg shift 122191cded7Smrg continue;; 123191cded7Smrg 124191cded7Smrg -s) stripcmd=$stripprog 125191cded7Smrg shift 126191cded7Smrg continue;; 127191cded7Smrg 128191cded7Smrg -t) dstarg=$2 129191cded7Smrg shift 130191cded7Smrg shift 131191cded7Smrg continue;; 132191cded7Smrg 133191cded7Smrg -T) no_target_directory=true 134191cded7Smrg shift 135191cded7Smrg continue;; 136191cded7Smrg 137191cded7Smrg --version) echo "$0 $scriptversion"; exit $?;; 138191cded7Smrg 139191cded7Smrg *) # When -d is used, all remaining arguments are directories to create. 140191cded7Smrg # When -t is used, the destination is already specified. 141191cded7Smrg test -n "$dir_arg$dstarg" && break 142191cded7Smrg # Otherwise, the last argument is the destination. Remove it from $@. 143191cded7Smrg for arg 144191cded7Smrg do 145191cded7Smrg if test -n "$dstarg"; then 146191cded7Smrg # $@ is not empty: it contains at least $arg. 147191cded7Smrg set fnord "$@" "$dstarg" 148191cded7Smrg shift # fnord 149191cded7Smrg fi 150191cded7Smrg shift # arg 151191cded7Smrg dstarg=$arg 152191cded7Smrg done 153191cded7Smrg break;; 154191cded7Smrg esac 155191cded7Smrgdone 156191cded7Smrg 157191cded7Smrgif test -z "$1"; then 158191cded7Smrg if test -z "$dir_arg"; then 159191cded7Smrg echo "$0: no input file specified." >&2 160191cded7Smrg exit 1 161191cded7Smrg fi 162191cded7Smrg # It's OK to call `install-sh -d' without argument. 163191cded7Smrg # This can happen when creating conditional directories. 164191cded7Smrg exit 0 165191cded7Smrgfi 166191cded7Smrg 167191cded7Smrgfor src 168191cded7Smrgdo 169191cded7Smrg # Protect names starting with `-'. 170191cded7Smrg case $src in 171191cded7Smrg -*) src=./$src ;; 172191cded7Smrg esac 173191cded7Smrg 174191cded7Smrg if test -n "$dir_arg"; then 175191cded7Smrg dst=$src 176191cded7Smrg src= 177191cded7Smrg 178191cded7Smrg if test -d "$dst"; then 179191cded7Smrg mkdircmd=: 180191cded7Smrg chmodcmd= 181191cded7Smrg else 182191cded7Smrg mkdircmd=$mkdirprog 183191cded7Smrg fi 184191cded7Smrg else 185191cded7Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186191cded7Smrg # might cause directories to be created, which would be especially bad 187191cded7Smrg # if $src (and thus $dsttmp) contains '*'. 188191cded7Smrg if test ! -f "$src" && test ! -d "$src"; then 189191cded7Smrg echo "$0: $src does not exist." >&2 190191cded7Smrg exit 1 191191cded7Smrg fi 192191cded7Smrg 193191cded7Smrg if test -z "$dstarg"; then 194191cded7Smrg echo "$0: no destination specified." >&2 195191cded7Smrg exit 1 196191cded7Smrg fi 197191cded7Smrg 198191cded7Smrg dst=$dstarg 199191cded7Smrg # Protect names starting with `-'. 200191cded7Smrg case $dst in 201191cded7Smrg -*) dst=./$dst ;; 202191cded7Smrg esac 203191cded7Smrg 204191cded7Smrg # If destination is a directory, append the input filename; won't work 205191cded7Smrg # if double slashes aren't ignored. 206191cded7Smrg if test -d "$dst"; then 207191cded7Smrg if test -n "$no_target_directory"; then 208191cded7Smrg echo "$0: $dstarg: Is a directory" >&2 209191cded7Smrg exit 1 210191cded7Smrg fi 211191cded7Smrg dst=$dst/`basename "$src"` 212191cded7Smrg fi 213191cded7Smrg fi 214191cded7Smrg 215191cded7Smrg # This sed command emulates the dirname command. 216191cded7Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217191cded7Smrg 218191cded7Smrg # Make sure that the destination directory exists. 219191cded7Smrg 220191cded7Smrg # Skip lots of stat calls in the usual case. 221191cded7Smrg if test ! -d "$dstdir"; then 222191cded7Smrg defaultIFS=' 223191cded7Smrg ' 224191cded7Smrg IFS="${IFS-$defaultIFS}" 225191cded7Smrg 226191cded7Smrg oIFS=$IFS 227191cded7Smrg # Some sh's can't handle IFS=/ for some reason. 228191cded7Smrg IFS='%' 229191cded7Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230191cded7Smrg shift 231191cded7Smrg IFS=$oIFS 232191cded7Smrg 233191cded7Smrg pathcomp= 234191cded7Smrg 235191cded7Smrg while test $# -ne 0 ; do 236191cded7Smrg pathcomp=$pathcomp$1 237191cded7Smrg shift 238191cded7Smrg if test ! -d "$pathcomp"; then 239191cded7Smrg $mkdirprog "$pathcomp" 240191cded7Smrg # mkdir can fail with a `File exist' error in case several 241191cded7Smrg # install-sh are creating the directory concurrently. This 242191cded7Smrg # is OK. 243191cded7Smrg test -d "$pathcomp" || exit 244191cded7Smrg fi 245191cded7Smrg pathcomp=$pathcomp/ 246191cded7Smrg done 247191cded7Smrg fi 248191cded7Smrg 249191cded7Smrg if test -n "$dir_arg"; then 250191cded7Smrg $doit $mkdircmd "$dst" \ 251191cded7Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252191cded7Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253191cded7Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254191cded7Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255191cded7Smrg 256191cded7Smrg else 257191cded7Smrg dstfile=`basename "$dst"` 258191cded7Smrg 259191cded7Smrg # Make a couple of temp file names in the proper directory. 260191cded7Smrg dsttmp=$dstdir/_inst.$$_ 261191cded7Smrg rmtmp=$dstdir/_rm.$$_ 262191cded7Smrg 263191cded7Smrg # Trap to clean up those temp files at exit. 264191cded7Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265191cded7Smrg trap '(exit $?); exit' 1 2 13 15 266191cded7Smrg 267191cded7Smrg # Copy the file name to the temp name. 268191cded7Smrg $doit $cpprog "$src" "$dsttmp" && 269191cded7Smrg 270191cded7Smrg # and set any options; do chmod last to preserve setuid bits. 271191cded7Smrg # 272191cded7Smrg # If any of these fail, we abort the whole thing. If we want to 273191cded7Smrg # ignore errors from any of these, just make sure not to ignore 274191cded7Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 275191cded7Smrg # 276191cded7Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277191cded7Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278191cded7Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279191cded7Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280191cded7Smrg 281191cded7Smrg # Now rename the file to the real destination. 282191cded7Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283191cded7Smrg || { 284191cded7Smrg # The rename failed, perhaps because mv can't rename something else 285191cded7Smrg # to itself, or perhaps because mv is so ancient that it does not 286191cded7Smrg # support -f. 287191cded7Smrg 288191cded7Smrg # Now remove or move aside any old file at destination location. 289191cded7Smrg # We try this two ways since rm can't unlink itself on some 290191cded7Smrg # systems and the destination file might be busy for other 291191cded7Smrg # reasons. In this case, the final cleanup might fail but the new 292191cded7Smrg # file should still install successfully. 293191cded7Smrg { 294191cded7Smrg if test -f "$dstdir/$dstfile"; then 295191cded7Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296191cded7Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297191cded7Smrg || { 298191cded7Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299191cded7Smrg (exit 1); exit 1 300191cded7Smrg } 301191cded7Smrg else 302191cded7Smrg : 303191cded7Smrg fi 304191cded7Smrg } && 305191cded7Smrg 306191cded7Smrg # Now rename the file to the real destination. 307191cded7Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308191cded7Smrg } 309191cded7Smrg } 310191cded7Smrg fi || { (exit 1); exit 1; } 311191cded7Smrgdone 312191cded7Smrg 313191cded7Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 314191cded7Smrg{ 315191cded7Smrg (exit 0); exit 0 316191cded7Smrg} 317191cded7Smrg 318191cded7Smrg# Local variables: 319191cded7Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 320191cded7Smrg# time-stamp-start: "scriptversion=" 321191cded7Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 322191cded7Smrg# time-stamp-end: "$" 323191cded7Smrg# End: 324