install-sh revision 240a9a23
1240a9a23Smbalmer#!/bin/sh 2240a9a23Smbalmer# install - install a program, script, or datafile 3240a9a23Smbalmer 4240a9a23Smbalmerscriptversion=2005-05-14.22 5240a9a23Smbalmer 6240a9a23Smbalmer# This originates from X11R5 (mit/util/scripts/install.sh), which was 7240a9a23Smbalmer# later released in X11R6 (xc/config/util/install.sh) with the 8240a9a23Smbalmer# following copyright and license. 9240a9a23Smbalmer# 10240a9a23Smbalmer# Copyright (C) 1994 X Consortium 11240a9a23Smbalmer# 12240a9a23Smbalmer# Permission is hereby granted, free of charge, to any person obtaining a copy 13240a9a23Smbalmer# of this software and associated documentation files (the "Software"), to 14240a9a23Smbalmer# deal in the Software without restriction, including without limitation the 15240a9a23Smbalmer# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16240a9a23Smbalmer# sell copies of the Software, and to permit persons to whom the Software is 17240a9a23Smbalmer# furnished to do so, subject to the following conditions: 18240a9a23Smbalmer# 19240a9a23Smbalmer# The above copyright notice and this permission notice shall be included in 20240a9a23Smbalmer# all copies or substantial portions of the Software. 21240a9a23Smbalmer# 22240a9a23Smbalmer# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23240a9a23Smbalmer# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24240a9a23Smbalmer# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25240a9a23Smbalmer# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26240a9a23Smbalmer# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27240a9a23Smbalmer# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28240a9a23Smbalmer# 29240a9a23Smbalmer# Except as contained in this notice, the name of the X Consortium shall not 30240a9a23Smbalmer# be used in advertising or otherwise to promote the sale, use or other deal- 31240a9a23Smbalmer# ings in this Software without prior written authorization from the X Consor- 32240a9a23Smbalmer# tium. 33240a9a23Smbalmer# 34240a9a23Smbalmer# 35240a9a23Smbalmer# FSF changes to this file are in the public domain. 36240a9a23Smbalmer# 37240a9a23Smbalmer# Calling this script install-sh is preferred over install.sh, to prevent 38240a9a23Smbalmer# `make' implicit rules from creating a file called install from it 39240a9a23Smbalmer# when there is no Makefile. 40240a9a23Smbalmer# 41240a9a23Smbalmer# This script is compatible with the BSD install script, but was written 42240a9a23Smbalmer# from scratch. It can only install one file at a time, a restriction 43240a9a23Smbalmer# shared with many OS's install programs. 44240a9a23Smbalmer 45240a9a23Smbalmer# set DOITPROG to echo to test this script 46240a9a23Smbalmer 47240a9a23Smbalmer# Don't use :- since 4.3BSD and earlier shells don't like it. 48240a9a23Smbalmerdoit="${DOITPROG-}" 49240a9a23Smbalmer 50240a9a23Smbalmer# put in absolute paths if you don't have them in your path; or use env. vars. 51240a9a23Smbalmer 52240a9a23Smbalmermvprog="${MVPROG-mv}" 53240a9a23Smbalmercpprog="${CPPROG-cp}" 54240a9a23Smbalmerchmodprog="${CHMODPROG-chmod}" 55240a9a23Smbalmerchownprog="${CHOWNPROG-chown}" 56240a9a23Smbalmerchgrpprog="${CHGRPPROG-chgrp}" 57240a9a23Smbalmerstripprog="${STRIPPROG-strip}" 58240a9a23Smbalmerrmprog="${RMPROG-rm}" 59240a9a23Smbalmermkdirprog="${MKDIRPROG-mkdir}" 60240a9a23Smbalmer 61240a9a23Smbalmerchmodcmd="$chmodprog 0755" 62240a9a23Smbalmerchowncmd= 63240a9a23Smbalmerchgrpcmd= 64240a9a23Smbalmerstripcmd= 65240a9a23Smbalmerrmcmd="$rmprog -f" 66240a9a23Smbalmermvcmd="$mvprog" 67240a9a23Smbalmersrc= 68240a9a23Smbalmerdst= 69240a9a23Smbalmerdir_arg= 70240a9a23Smbalmerdstarg= 71240a9a23Smbalmerno_target_directory= 72240a9a23Smbalmer 73240a9a23Smbalmerusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74240a9a23Smbalmer or: $0 [OPTION]... SRCFILES... DIRECTORY 75240a9a23Smbalmer or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76240a9a23Smbalmer or: $0 [OPTION]... -d DIRECTORIES... 77240a9a23Smbalmer 78240a9a23SmbalmerIn the 1st form, copy SRCFILE to DSTFILE. 79240a9a23SmbalmerIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80240a9a23SmbalmerIn the 4th, create DIRECTORIES. 81240a9a23Smbalmer 82240a9a23SmbalmerOptions: 83240a9a23Smbalmer-c (ignored) 84240a9a23Smbalmer-d create directories instead of installing files. 85240a9a23Smbalmer-g GROUP $chgrpprog installed files to GROUP. 86240a9a23Smbalmer-m MODE $chmodprog installed files to MODE. 87240a9a23Smbalmer-o USER $chownprog installed files to USER. 88240a9a23Smbalmer-s $stripprog installed files. 89240a9a23Smbalmer-t DIRECTORY install into DIRECTORY. 90240a9a23Smbalmer-T report an error if DSTFILE is a directory. 91240a9a23Smbalmer--help display this help and exit. 92240a9a23Smbalmer--version display version info and exit. 93240a9a23Smbalmer 94240a9a23SmbalmerEnvironment variables override the default commands: 95240a9a23Smbalmer CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96240a9a23Smbalmer" 97240a9a23Smbalmer 98240a9a23Smbalmerwhile test -n "$1"; do 99240a9a23Smbalmer case $1 in 100240a9a23Smbalmer -c) shift 101240a9a23Smbalmer continue;; 102240a9a23Smbalmer 103240a9a23Smbalmer -d) dir_arg=true 104240a9a23Smbalmer shift 105240a9a23Smbalmer continue;; 106240a9a23Smbalmer 107240a9a23Smbalmer -g) chgrpcmd="$chgrpprog $2" 108240a9a23Smbalmer shift 109240a9a23Smbalmer shift 110240a9a23Smbalmer continue;; 111240a9a23Smbalmer 112240a9a23Smbalmer --help) echo "$usage"; exit $?;; 113240a9a23Smbalmer 114240a9a23Smbalmer -m) chmodcmd="$chmodprog $2" 115240a9a23Smbalmer shift 116240a9a23Smbalmer shift 117240a9a23Smbalmer continue;; 118240a9a23Smbalmer 119240a9a23Smbalmer -o) chowncmd="$chownprog $2" 120240a9a23Smbalmer shift 121240a9a23Smbalmer shift 122240a9a23Smbalmer continue;; 123240a9a23Smbalmer 124240a9a23Smbalmer -s) stripcmd=$stripprog 125240a9a23Smbalmer shift 126240a9a23Smbalmer continue;; 127240a9a23Smbalmer 128240a9a23Smbalmer -t) dstarg=$2 129240a9a23Smbalmer shift 130240a9a23Smbalmer shift 131240a9a23Smbalmer continue;; 132240a9a23Smbalmer 133240a9a23Smbalmer -T) no_target_directory=true 134240a9a23Smbalmer shift 135240a9a23Smbalmer continue;; 136240a9a23Smbalmer 137240a9a23Smbalmer --version) echo "$0 $scriptversion"; exit $?;; 138240a9a23Smbalmer 139240a9a23Smbalmer *) # When -d is used, all remaining arguments are directories to create. 140240a9a23Smbalmer # When -t is used, the destination is already specified. 141240a9a23Smbalmer test -n "$dir_arg$dstarg" && break 142240a9a23Smbalmer # Otherwise, the last argument is the destination. Remove it from $@. 143240a9a23Smbalmer for arg 144240a9a23Smbalmer do 145240a9a23Smbalmer if test -n "$dstarg"; then 146240a9a23Smbalmer # $@ is not empty: it contains at least $arg. 147240a9a23Smbalmer set fnord "$@" "$dstarg" 148240a9a23Smbalmer shift # fnord 149240a9a23Smbalmer fi 150240a9a23Smbalmer shift # arg 151240a9a23Smbalmer dstarg=$arg 152240a9a23Smbalmer done 153240a9a23Smbalmer break;; 154240a9a23Smbalmer esac 155240a9a23Smbalmerdone 156240a9a23Smbalmer 157240a9a23Smbalmerif test -z "$1"; then 158240a9a23Smbalmer if test -z "$dir_arg"; then 159240a9a23Smbalmer echo "$0: no input file specified." >&2 160240a9a23Smbalmer exit 1 161240a9a23Smbalmer fi 162240a9a23Smbalmer # It's OK to call `install-sh -d' without argument. 163240a9a23Smbalmer # This can happen when creating conditional directories. 164240a9a23Smbalmer exit 0 165240a9a23Smbalmerfi 166240a9a23Smbalmer 167240a9a23Smbalmerfor src 168240a9a23Smbalmerdo 169240a9a23Smbalmer # Protect names starting with `-'. 170240a9a23Smbalmer case $src in 171240a9a23Smbalmer -*) src=./$src ;; 172240a9a23Smbalmer esac 173240a9a23Smbalmer 174240a9a23Smbalmer if test -n "$dir_arg"; then 175240a9a23Smbalmer dst=$src 176240a9a23Smbalmer src= 177240a9a23Smbalmer 178240a9a23Smbalmer if test -d "$dst"; then 179240a9a23Smbalmer mkdircmd=: 180240a9a23Smbalmer chmodcmd= 181240a9a23Smbalmer else 182240a9a23Smbalmer mkdircmd=$mkdirprog 183240a9a23Smbalmer fi 184240a9a23Smbalmer else 185240a9a23Smbalmer # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186240a9a23Smbalmer # might cause directories to be created, which would be especially bad 187240a9a23Smbalmer # if $src (and thus $dsttmp) contains '*'. 188240a9a23Smbalmer if test ! -f "$src" && test ! -d "$src"; then 189240a9a23Smbalmer echo "$0: $src does not exist." >&2 190240a9a23Smbalmer exit 1 191240a9a23Smbalmer fi 192240a9a23Smbalmer 193240a9a23Smbalmer if test -z "$dstarg"; then 194240a9a23Smbalmer echo "$0: no destination specified." >&2 195240a9a23Smbalmer exit 1 196240a9a23Smbalmer fi 197240a9a23Smbalmer 198240a9a23Smbalmer dst=$dstarg 199240a9a23Smbalmer # Protect names starting with `-'. 200240a9a23Smbalmer case $dst in 201240a9a23Smbalmer -*) dst=./$dst ;; 202240a9a23Smbalmer esac 203240a9a23Smbalmer 204240a9a23Smbalmer # If destination is a directory, append the input filename; won't work 205240a9a23Smbalmer # if double slashes aren't ignored. 206240a9a23Smbalmer if test -d "$dst"; then 207240a9a23Smbalmer if test -n "$no_target_directory"; then 208240a9a23Smbalmer echo "$0: $dstarg: Is a directory" >&2 209240a9a23Smbalmer exit 1 210240a9a23Smbalmer fi 211240a9a23Smbalmer dst=$dst/`basename "$src"` 212240a9a23Smbalmer fi 213240a9a23Smbalmer fi 214240a9a23Smbalmer 215240a9a23Smbalmer # This sed command emulates the dirname command. 216240a9a23Smbalmer dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217240a9a23Smbalmer 218240a9a23Smbalmer # Make sure that the destination directory exists. 219240a9a23Smbalmer 220240a9a23Smbalmer # Skip lots of stat calls in the usual case. 221240a9a23Smbalmer if test ! -d "$dstdir"; then 222240a9a23Smbalmer defaultIFS=' 223240a9a23Smbalmer ' 224240a9a23Smbalmer IFS="${IFS-$defaultIFS}" 225240a9a23Smbalmer 226240a9a23Smbalmer oIFS=$IFS 227240a9a23Smbalmer # Some sh's can't handle IFS=/ for some reason. 228240a9a23Smbalmer IFS='%' 229240a9a23Smbalmer set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230240a9a23Smbalmer shift 231240a9a23Smbalmer IFS=$oIFS 232240a9a23Smbalmer 233240a9a23Smbalmer pathcomp= 234240a9a23Smbalmer 235240a9a23Smbalmer while test $# -ne 0 ; do 236240a9a23Smbalmer pathcomp=$pathcomp$1 237240a9a23Smbalmer shift 238240a9a23Smbalmer if test ! -d "$pathcomp"; then 239240a9a23Smbalmer $mkdirprog "$pathcomp" 240240a9a23Smbalmer # mkdir can fail with a `File exist' error in case several 241240a9a23Smbalmer # install-sh are creating the directory concurrently. This 242240a9a23Smbalmer # is OK. 243240a9a23Smbalmer test -d "$pathcomp" || exit 244240a9a23Smbalmer fi 245240a9a23Smbalmer pathcomp=$pathcomp/ 246240a9a23Smbalmer done 247240a9a23Smbalmer fi 248240a9a23Smbalmer 249240a9a23Smbalmer if test -n "$dir_arg"; then 250240a9a23Smbalmer $doit $mkdircmd "$dst" \ 251240a9a23Smbalmer && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252240a9a23Smbalmer && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253240a9a23Smbalmer && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254240a9a23Smbalmer && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255240a9a23Smbalmer 256240a9a23Smbalmer else 257240a9a23Smbalmer dstfile=`basename "$dst"` 258240a9a23Smbalmer 259240a9a23Smbalmer # Make a couple of temp file names in the proper directory. 260240a9a23Smbalmer dsttmp=$dstdir/_inst.$$_ 261240a9a23Smbalmer rmtmp=$dstdir/_rm.$$_ 262240a9a23Smbalmer 263240a9a23Smbalmer # Trap to clean up those temp files at exit. 264240a9a23Smbalmer trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265240a9a23Smbalmer trap '(exit $?); exit' 1 2 13 15 266240a9a23Smbalmer 267240a9a23Smbalmer # Copy the file name to the temp name. 268240a9a23Smbalmer $doit $cpprog "$src" "$dsttmp" && 269240a9a23Smbalmer 270240a9a23Smbalmer # and set any options; do chmod last to preserve setuid bits. 271240a9a23Smbalmer # 272240a9a23Smbalmer # If any of these fail, we abort the whole thing. If we want to 273240a9a23Smbalmer # ignore errors from any of these, just make sure not to ignore 274240a9a23Smbalmer # errors from the above "$doit $cpprog $src $dsttmp" command. 275240a9a23Smbalmer # 276240a9a23Smbalmer { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277240a9a23Smbalmer && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278240a9a23Smbalmer && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279240a9a23Smbalmer && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280240a9a23Smbalmer 281240a9a23Smbalmer # Now rename the file to the real destination. 282240a9a23Smbalmer { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283240a9a23Smbalmer || { 284240a9a23Smbalmer # The rename failed, perhaps because mv can't rename something else 285240a9a23Smbalmer # to itself, or perhaps because mv is so ancient that it does not 286240a9a23Smbalmer # support -f. 287240a9a23Smbalmer 288240a9a23Smbalmer # Now remove or move aside any old file at destination location. 289240a9a23Smbalmer # We try this two ways since rm can't unlink itself on some 290240a9a23Smbalmer # systems and the destination file might be busy for other 291240a9a23Smbalmer # reasons. In this case, the final cleanup might fail but the new 292240a9a23Smbalmer # file should still install successfully. 293240a9a23Smbalmer { 294240a9a23Smbalmer if test -f "$dstdir/$dstfile"; then 295240a9a23Smbalmer $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296240a9a23Smbalmer || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297240a9a23Smbalmer || { 298240a9a23Smbalmer echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299240a9a23Smbalmer (exit 1); exit 1 300240a9a23Smbalmer } 301240a9a23Smbalmer else 302240a9a23Smbalmer : 303240a9a23Smbalmer fi 304240a9a23Smbalmer } && 305240a9a23Smbalmer 306240a9a23Smbalmer # Now rename the file to the real destination. 307240a9a23Smbalmer $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308240a9a23Smbalmer } 309240a9a23Smbalmer } 310240a9a23Smbalmer fi || { (exit 1); exit 1; } 311240a9a23Smbalmerdone 312240a9a23Smbalmer 313240a9a23Smbalmer# The final little trick to "correctly" pass the exit status to the exit trap. 314240a9a23Smbalmer{ 315240a9a23Smbalmer (exit 0); exit 0 316240a9a23Smbalmer} 317240a9a23Smbalmer 318240a9a23Smbalmer# Local variables: 319240a9a23Smbalmer# eval: (add-hook 'write-file-hooks 'time-stamp) 320240a9a23Smbalmer# time-stamp-start: "scriptversion=" 321240a9a23Smbalmer# time-stamp-format: "%:y-%02m-%02d.%02H" 322240a9a23Smbalmer# time-stamp-end: "$" 323240a9a23Smbalmer# End: 324