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