install-sh revision 17ca54c3
117ca54c3Smrg#!/bin/sh 217ca54c3Smrg# install - install a program, script, or datafile 317ca54c3Smrg 417ca54c3Smrgscriptversion=2004-02-15.20 517ca54c3Smrg 617ca54c3Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 717ca54c3Smrg# later released in X11R6 (xc/config/util/install.sh) with the 817ca54c3Smrg# following copyright and license. 917ca54c3Smrg# 1017ca54c3Smrg# Copyright (C) 1994 X Consortium 1117ca54c3Smrg# 1217ca54c3Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 1317ca54c3Smrg# of this software and associated documentation files (the "Software"), to 1417ca54c3Smrg# deal in the Software without restriction, including without limitation the 1517ca54c3Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1617ca54c3Smrg# sell copies of the Software, and to permit persons to whom the Software is 1717ca54c3Smrg# furnished to do so, subject to the following conditions: 1817ca54c3Smrg# 1917ca54c3Smrg# The above copyright notice and this permission notice shall be included in 2017ca54c3Smrg# all copies or substantial portions of the Software. 2117ca54c3Smrg# 2217ca54c3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2317ca54c3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2417ca54c3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2517ca54c3Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2617ca54c3Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 2717ca54c3Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2817ca54c3Smrg# 2917ca54c3Smrg# Except as contained in this notice, the name of the X Consortium shall not 3017ca54c3Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 3117ca54c3Smrg# ings in this Software without prior written authorization from the X Consor- 3217ca54c3Smrg# tium. 3317ca54c3Smrg# 3417ca54c3Smrg# 3517ca54c3Smrg# FSF changes to this file are in the public domain. 3617ca54c3Smrg# 3717ca54c3Smrg# Calling this script install-sh is preferred over install.sh, to prevent 3817ca54c3Smrg# `make' implicit rules from creating a file called install from it 3917ca54c3Smrg# when there is no Makefile. 4017ca54c3Smrg# 4117ca54c3Smrg# This script is compatible with the BSD install script, but was written 4217ca54c3Smrg# from scratch. It can only install one file at a time, a restriction 4317ca54c3Smrg# shared with many OS's install programs. 4417ca54c3Smrg 4517ca54c3Smrg# set DOITPROG to echo to test this script 4617ca54c3Smrg 4717ca54c3Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 4817ca54c3Smrgdoit="${DOITPROG-}" 4917ca54c3Smrg 5017ca54c3Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 5117ca54c3Smrg 5217ca54c3Smrgmvprog="${MVPROG-mv}" 5317ca54c3Smrgcpprog="${CPPROG-cp}" 5417ca54c3Smrgchmodprog="${CHMODPROG-chmod}" 5517ca54c3Smrgchownprog="${CHOWNPROG-chown}" 5617ca54c3Smrgchgrpprog="${CHGRPPROG-chgrp}" 5717ca54c3Smrgstripprog="${STRIPPROG-strip}" 5817ca54c3Smrgrmprog="${RMPROG-rm}" 5917ca54c3Smrgmkdirprog="${MKDIRPROG-mkdir}" 6017ca54c3Smrg 6117ca54c3Smrgtransformbasename= 6217ca54c3Smrgtransform_arg= 6317ca54c3Smrginstcmd="$mvprog" 6417ca54c3Smrgchmodcmd="$chmodprog 0755" 6517ca54c3Smrgchowncmd= 6617ca54c3Smrgchgrpcmd= 6717ca54c3Smrgstripcmd= 6817ca54c3Smrgrmcmd="$rmprog -f" 6917ca54c3Smrgmvcmd="$mvprog" 7017ca54c3Smrgsrc= 7117ca54c3Smrgdst= 7217ca54c3Smrgdir_arg= 7317ca54c3Smrg 7417ca54c3Smrgusage="Usage: $0 [OPTION]... SRCFILE DSTFILE 7517ca54c3Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 7617ca54c3Smrg or: $0 -d DIRECTORIES... 7717ca54c3Smrg 7817ca54c3SmrgIn the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. 7917ca54c3SmrgIn the second, create the directory path DIR. 8017ca54c3Smrg 8117ca54c3SmrgOptions: 8217ca54c3Smrg-b=TRANSFORMBASENAME 8317ca54c3Smrg-c copy source (using $cpprog) instead of moving (using $mvprog). 8417ca54c3Smrg-d create directories instead of installing files. 8517ca54c3Smrg-g GROUP $chgrp installed files to GROUP. 8617ca54c3Smrg-m MODE $chmod installed files to MODE. 8717ca54c3Smrg-o USER $chown installed files to USER. 8817ca54c3Smrg-s strip installed files (using $stripprog). 8917ca54c3Smrg-t=TRANSFORM 9017ca54c3Smrg--help display this help and exit. 9117ca54c3Smrg--version display version info and exit. 9217ca54c3Smrg 9317ca54c3SmrgEnvironment variables override the default commands: 9417ca54c3Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 9517ca54c3Smrg" 9617ca54c3Smrg 9717ca54c3Smrgwhile test -n "$1"; do 9817ca54c3Smrg case $1 in 9917ca54c3Smrg -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 10017ca54c3Smrg shift 10117ca54c3Smrg continue;; 10217ca54c3Smrg 10317ca54c3Smrg -c) instcmd=$cpprog 10417ca54c3Smrg shift 10517ca54c3Smrg continue;; 10617ca54c3Smrg 10717ca54c3Smrg -d) dir_arg=true 10817ca54c3Smrg shift 10917ca54c3Smrg continue;; 11017ca54c3Smrg 11117ca54c3Smrg -g) chgrpcmd="$chgrpprog $2" 11217ca54c3Smrg shift 11317ca54c3Smrg shift 11417ca54c3Smrg continue;; 11517ca54c3Smrg 11617ca54c3Smrg --help) echo "$usage"; exit 0;; 11717ca54c3Smrg 11817ca54c3Smrg -m) chmodcmd="$chmodprog $2" 11917ca54c3Smrg shift 12017ca54c3Smrg shift 12117ca54c3Smrg continue;; 12217ca54c3Smrg 12317ca54c3Smrg -o) chowncmd="$chownprog $2" 12417ca54c3Smrg shift 12517ca54c3Smrg shift 12617ca54c3Smrg continue;; 12717ca54c3Smrg 12817ca54c3Smrg -s) stripcmd=$stripprog 12917ca54c3Smrg shift 13017ca54c3Smrg continue;; 13117ca54c3Smrg 13217ca54c3Smrg -t=*) transformarg=`echo $1 | sed 's/-t=//'` 13317ca54c3Smrg shift 13417ca54c3Smrg continue;; 13517ca54c3Smrg 13617ca54c3Smrg --version) echo "$0 $scriptversion"; exit 0;; 13717ca54c3Smrg 13817ca54c3Smrg *) # When -d is used, all remaining arguments are directories to create. 13917ca54c3Smrg test -n "$dir_arg" && break 14017ca54c3Smrg # Otherwise, the last argument is the destination. Remove it from $@. 14117ca54c3Smrg for arg 14217ca54c3Smrg do 14317ca54c3Smrg if test -n "$dstarg"; then 14417ca54c3Smrg # $@ is not empty: it contains at least $arg. 14517ca54c3Smrg set fnord "$@" "$dstarg" 14617ca54c3Smrg shift # fnord 14717ca54c3Smrg fi 14817ca54c3Smrg shift # arg 14917ca54c3Smrg dstarg=$arg 15017ca54c3Smrg done 15117ca54c3Smrg break;; 15217ca54c3Smrg esac 15317ca54c3Smrgdone 15417ca54c3Smrg 15517ca54c3Smrgif test -z "$1"; then 15617ca54c3Smrg if test -z "$dir_arg"; then 15717ca54c3Smrg echo "$0: no input file specified." >&2 15817ca54c3Smrg exit 1 15917ca54c3Smrg fi 16017ca54c3Smrg # It's OK to call `install-sh -d' without argument. 16117ca54c3Smrg # This can happen when creating conditional directories. 16217ca54c3Smrg exit 0 16317ca54c3Smrgfi 16417ca54c3Smrg 16517ca54c3Smrgfor src 16617ca54c3Smrgdo 16717ca54c3Smrg # Protect names starting with `-'. 16817ca54c3Smrg case $src in 16917ca54c3Smrg -*) src=./$src ;; 17017ca54c3Smrg esac 17117ca54c3Smrg 17217ca54c3Smrg if test -n "$dir_arg"; then 17317ca54c3Smrg dst=$src 17417ca54c3Smrg src= 17517ca54c3Smrg 17617ca54c3Smrg if test -d "$dst"; then 17717ca54c3Smrg instcmd=: 17817ca54c3Smrg chmodcmd= 17917ca54c3Smrg else 18017ca54c3Smrg instcmd=$mkdirprog 18117ca54c3Smrg fi 18217ca54c3Smrg else 18317ca54c3Smrg # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 18417ca54c3Smrg # might cause directories to be created, which would be especially bad 18517ca54c3Smrg # if $src (and thus $dsttmp) contains '*'. 18617ca54c3Smrg if test ! -f "$src" && test ! -d "$src"; then 18717ca54c3Smrg echo "$0: $src does not exist." >&2 18817ca54c3Smrg exit 1 18917ca54c3Smrg fi 19017ca54c3Smrg 19117ca54c3Smrg if test -z "$dstarg"; then 19217ca54c3Smrg echo "$0: no destination specified." >&2 19317ca54c3Smrg exit 1 19417ca54c3Smrg fi 19517ca54c3Smrg 19617ca54c3Smrg dst=$dstarg 19717ca54c3Smrg # Protect names starting with `-'. 19817ca54c3Smrg case $dst in 19917ca54c3Smrg -*) dst=./$dst ;; 20017ca54c3Smrg esac 20117ca54c3Smrg 20217ca54c3Smrg # If destination is a directory, append the input filename; won't work 20317ca54c3Smrg # if double slashes aren't ignored. 20417ca54c3Smrg if test -d "$dst"; then 20517ca54c3Smrg dst=$dst/`basename "$src"` 20617ca54c3Smrg fi 20717ca54c3Smrg fi 20817ca54c3Smrg 20917ca54c3Smrg # This sed command emulates the dirname command. 21017ca54c3Smrg dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 21117ca54c3Smrg 21217ca54c3Smrg # Make sure that the destination directory exists. 21317ca54c3Smrg 21417ca54c3Smrg # Skip lots of stat calls in the usual case. 21517ca54c3Smrg if test ! -d "$dstdir"; then 21617ca54c3Smrg defaultIFS=' 21717ca54c3Smrg ' 21817ca54c3Smrg IFS="${IFS-$defaultIFS}" 21917ca54c3Smrg 22017ca54c3Smrg oIFS=$IFS 22117ca54c3Smrg # Some sh's can't handle IFS=/ for some reason. 22217ca54c3Smrg IFS='%' 22317ca54c3Smrg set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 22417ca54c3Smrg IFS=$oIFS 22517ca54c3Smrg 22617ca54c3Smrg pathcomp= 22717ca54c3Smrg 22817ca54c3Smrg while test $# -ne 0 ; do 22917ca54c3Smrg pathcomp=$pathcomp$1 23017ca54c3Smrg shift 23117ca54c3Smrg if test ! -d "$pathcomp"; then 23217ca54c3Smrg $mkdirprog "$pathcomp" || lasterr=$? 23317ca54c3Smrg # mkdir can fail with a `File exist' error in case several 23417ca54c3Smrg # install-sh are creating the directory concurrently. This 23517ca54c3Smrg # is OK. 23617ca54c3Smrg test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; } 23717ca54c3Smrg fi 23817ca54c3Smrg pathcomp=$pathcomp/ 23917ca54c3Smrg done 24017ca54c3Smrg fi 24117ca54c3Smrg 24217ca54c3Smrg if test -n "$dir_arg"; then 24317ca54c3Smrg $doit $instcmd "$dst" \ 24417ca54c3Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 24517ca54c3Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 24617ca54c3Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 24717ca54c3Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 24817ca54c3Smrg 24917ca54c3Smrg else 25017ca54c3Smrg # If we're going to rename the final executable, determine the name now. 25117ca54c3Smrg if test -z "$transformarg"; then 25217ca54c3Smrg dstfile=`basename "$dst"` 25317ca54c3Smrg else 25417ca54c3Smrg dstfile=`basename "$dst" $transformbasename \ 25517ca54c3Smrg | sed $transformarg`$transformbasename 25617ca54c3Smrg fi 25717ca54c3Smrg 25817ca54c3Smrg # don't allow the sed command to completely eliminate the filename. 25917ca54c3Smrg test -z "$dstfile" && dstfile=`basename "$dst"` 26017ca54c3Smrg 26117ca54c3Smrg # Make a couple of temp file names in the proper directory. 26217ca54c3Smrg dsttmp=$dstdir/_inst.$$_ 26317ca54c3Smrg rmtmp=$dstdir/_rm.$$_ 26417ca54c3Smrg 26517ca54c3Smrg # Trap to clean up those temp files at exit. 26617ca54c3Smrg trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 26717ca54c3Smrg trap '(exit $?); exit' 1 2 13 15 26817ca54c3Smrg 26917ca54c3Smrg # Move or copy the file name to the temp name 27017ca54c3Smrg $doit $instcmd "$src" "$dsttmp" && 27117ca54c3Smrg 27217ca54c3Smrg # and set any options; do chmod last to preserve setuid bits. 27317ca54c3Smrg # 27417ca54c3Smrg # If any of these fail, we abort the whole thing. If we want to 27517ca54c3Smrg # ignore errors from any of these, just make sure not to ignore 27617ca54c3Smrg # errors from the above "$doit $instcmd $src $dsttmp" command. 27717ca54c3Smrg # 27817ca54c3Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 27917ca54c3Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 28017ca54c3Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 28117ca54c3Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28217ca54c3Smrg 28317ca54c3Smrg # Now remove or move aside any old file at destination location. We 28417ca54c3Smrg # try this two ways since rm can't unlink itself on some systems and 28517ca54c3Smrg # the destination file might be busy for other reasons. In this case, 28617ca54c3Smrg # the final cleanup might fail but the new file should still install 28717ca54c3Smrg # successfully. 28817ca54c3Smrg { 28917ca54c3Smrg if test -f "$dstdir/$dstfile"; then 29017ca54c3Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 29117ca54c3Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 29217ca54c3Smrg || { 29317ca54c3Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 29417ca54c3Smrg (exit 1); exit 29517ca54c3Smrg } 29617ca54c3Smrg else 29717ca54c3Smrg : 29817ca54c3Smrg fi 29917ca54c3Smrg } && 30017ca54c3Smrg 30117ca54c3Smrg # Now rename the file to the real destination. 30217ca54c3Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 30317ca54c3Smrg fi || { (exit 1); exit; } 30417ca54c3Smrgdone 30517ca54c3Smrg 30617ca54c3Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 30717ca54c3Smrg{ 30817ca54c3Smrg (exit 0); exit 30917ca54c3Smrg} 31017ca54c3Smrg 31117ca54c3Smrg# Local variables: 31217ca54c3Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 31317ca54c3Smrg# time-stamp-start: "scriptversion=" 31417ca54c3Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 31517ca54c3Smrg# time-stamp-end: "$" 31617ca54c3Smrg# End: 317