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