install-sh revision d075918c
19bd41f2cSmrg#!/bin/sh 29bd41f2cSmrg# install - install a program, script, or datafile 39bd41f2cSmrg 4d075918cSmrgscriptversion=2005-05-14.22 59bd41f2cSmrg 69bd41f2cSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 79bd41f2cSmrg# later released in X11R6 (xc/config/util/install.sh) with the 89bd41f2cSmrg# following copyright and license. 99bd41f2cSmrg# 109bd41f2cSmrg# Copyright (C) 1994 X Consortium 119bd41f2cSmrg# 129bd41f2cSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 139bd41f2cSmrg# of this software and associated documentation files (the "Software"), to 149bd41f2cSmrg# deal in the Software without restriction, including without limitation the 159bd41f2cSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 169bd41f2cSmrg# sell copies of the Software, and to permit persons to whom the Software is 179bd41f2cSmrg# furnished to do so, subject to the following conditions: 189bd41f2cSmrg# 199bd41f2cSmrg# The above copyright notice and this permission notice shall be included in 209bd41f2cSmrg# all copies or substantial portions of the Software. 219bd41f2cSmrg# 229bd41f2cSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 239bd41f2cSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 249bd41f2cSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 259bd41f2cSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 269bd41f2cSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 279bd41f2cSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 289bd41f2cSmrg# 299bd41f2cSmrg# Except as contained in this notice, the name of the X Consortium shall not 309bd41f2cSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 319bd41f2cSmrg# ings in this Software without prior written authorization from the X Consor- 329bd41f2cSmrg# tium. 339bd41f2cSmrg# 349bd41f2cSmrg# 359bd41f2cSmrg# FSF changes to this file are in the public domain. 369bd41f2cSmrg# 379bd41f2cSmrg# Calling this script install-sh is preferred over install.sh, to prevent 389bd41f2cSmrg# `make' implicit rules from creating a file called install from it 399bd41f2cSmrg# when there is no Makefile. 409bd41f2cSmrg# 419bd41f2cSmrg# This script is compatible with the BSD install script, but was written 42d075918cSmrg# from scratch. It can only install one file at a time, a restriction 43d075918cSmrg# shared with many OS's install programs. 449bd41f2cSmrg 459bd41f2cSmrg# set DOITPROG to echo to test this script 469bd41f2cSmrg 479bd41f2cSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 489bd41f2cSmrgdoit="${DOITPROG-}" 499bd41f2cSmrg 50d075918cSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 519bd41f2cSmrg 529bd41f2cSmrgmvprog="${MVPROG-mv}" 539bd41f2cSmrgcpprog="${CPPROG-cp}" 549bd41f2cSmrgchmodprog="${CHMODPROG-chmod}" 559bd41f2cSmrgchownprog="${CHOWNPROG-chown}" 569bd41f2cSmrgchgrpprog="${CHGRPPROG-chgrp}" 579bd41f2cSmrgstripprog="${STRIPPROG-strip}" 589bd41f2cSmrgrmprog="${RMPROG-rm}" 599bd41f2cSmrgmkdirprog="${MKDIRPROG-mkdir}" 609bd41f2cSmrg 61d075918cSmrgchmodcmd="$chmodprog 0755" 629bd41f2cSmrgchowncmd= 639bd41f2cSmrgchgrpcmd= 649bd41f2cSmrgstripcmd= 659bd41f2cSmrgrmcmd="$rmprog -f" 669bd41f2cSmrgmvcmd="$mvprog" 679bd41f2cSmrgsrc= 689bd41f2cSmrgdst= 699bd41f2cSmrgdir_arg= 709bd41f2cSmrgdstarg= 719bd41f2cSmrgno_target_directory= 729bd41f2cSmrg 739bd41f2cSmrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 749bd41f2cSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 759bd41f2cSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 769bd41f2cSmrg or: $0 [OPTION]... -d DIRECTORIES... 779bd41f2cSmrg 789bd41f2cSmrgIn the 1st form, copy SRCFILE to DSTFILE. 799bd41f2cSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 809bd41f2cSmrgIn the 4th, create DIRECTORIES. 819bd41f2cSmrg 829bd41f2cSmrgOptions: 839bd41f2cSmrg-c (ignored) 849bd41f2cSmrg-d create directories instead of installing files. 859bd41f2cSmrg-g GROUP $chgrpprog installed files to GROUP. 869bd41f2cSmrg-m MODE $chmodprog installed files to MODE. 879bd41f2cSmrg-o USER $chownprog installed files to USER. 889bd41f2cSmrg-s $stripprog installed files. 899bd41f2cSmrg-t DIRECTORY install into DIRECTORY. 909bd41f2cSmrg-T report an error if DSTFILE is a directory. 919bd41f2cSmrg--help display this help and exit. 929bd41f2cSmrg--version display version info and exit. 939bd41f2cSmrg 949bd41f2cSmrgEnvironment variables override the default commands: 959bd41f2cSmrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 969bd41f2cSmrg" 979bd41f2cSmrg 98d075918cSmrgwhile test -n "$1"; do 999bd41f2cSmrg case $1 in 1009bd41f2cSmrg -c) shift 1019bd41f2cSmrg continue;; 1029bd41f2cSmrg 1039bd41f2cSmrg -d) dir_arg=true 1049bd41f2cSmrg shift 1059bd41f2cSmrg continue;; 1069bd41f2cSmrg 1079bd41f2cSmrg -g) chgrpcmd="$chgrpprog $2" 1089bd41f2cSmrg shift 1099bd41f2cSmrg shift 1109bd41f2cSmrg continue;; 1119bd41f2cSmrg 1129bd41f2cSmrg --help) echo "$usage"; exit $?;; 1139bd41f2cSmrg 114d075918cSmrg -m) chmodcmd="$chmodprog $2" 1159bd41f2cSmrg shift 1169bd41f2cSmrg shift 1179bd41f2cSmrg continue;; 1189bd41f2cSmrg 1199bd41f2cSmrg -o) chowncmd="$chownprog $2" 1209bd41f2cSmrg shift 1219bd41f2cSmrg shift 1229bd41f2cSmrg continue;; 1239bd41f2cSmrg 1249bd41f2cSmrg -s) stripcmd=$stripprog 1259bd41f2cSmrg shift 1269bd41f2cSmrg continue;; 1279bd41f2cSmrg 1289bd41f2cSmrg -t) dstarg=$2 1299bd41f2cSmrg shift 1309bd41f2cSmrg shift 1319bd41f2cSmrg continue;; 1329bd41f2cSmrg 1339bd41f2cSmrg -T) no_target_directory=true 1349bd41f2cSmrg shift 1359bd41f2cSmrg continue;; 1369bd41f2cSmrg 1379bd41f2cSmrg --version) echo "$0 $scriptversion"; exit $?;; 1389bd41f2cSmrg 139d075918cSmrg *) # When -d is used, all remaining arguments are directories to create. 140d075918cSmrg # When -t is used, the destination is already specified. 141d075918cSmrg test -n "$dir_arg$dstarg" && break 142d075918cSmrg # Otherwise, the last argument is the destination. Remove it from $@. 143d075918cSmrg for arg 144d075918cSmrg do 145d075918cSmrg if test -n "$dstarg"; then 146d075918cSmrg # $@ is not empty: it contains at least $arg. 147d075918cSmrg set fnord "$@" "$dstarg" 148d075918cSmrg shift # fnord 149d075918cSmrg fi 150d075918cSmrg shift # arg 151d075918cSmrg dstarg=$arg 152d075918cSmrg done 1539bd41f2cSmrg break;; 1549bd41f2cSmrg esac 1559bd41f2cSmrgdone 1569bd41f2cSmrg 157d075918cSmrgif test -z "$1"; then 1589bd41f2cSmrg if test -z "$dir_arg"; then 1599bd41f2cSmrg echo "$0: no input file specified." >&2 1609bd41f2cSmrg exit 1 1619bd41f2cSmrg fi 1629bd41f2cSmrg # It's OK to call `install-sh -d' without argument. 1639bd41f2cSmrg # This can happen when creating conditional directories. 1649bd41f2cSmrg exit 0 1659bd41f2cSmrgfi 1669bd41f2cSmrg 1679bd41f2cSmrgfor src 1689bd41f2cSmrgdo 1699bd41f2cSmrg # Protect names starting with `-'. 1709bd41f2cSmrg case $src in 1719bd41f2cSmrg -*) src=./$src ;; 1729bd41f2cSmrg esac 1739bd41f2cSmrg 1749bd41f2cSmrg if test -n "$dir_arg"; then 1759bd41f2cSmrg dst=$src 176d075918cSmrg src= 1779bd41f2cSmrg 178d075918cSmrg if test -d "$dst"; then 179d075918cSmrg mkdircmd=: 180d075918cSmrg chmodcmd= 181d075918cSmrg else 182d075918cSmrg mkdircmd=$mkdirprog 183d075918cSmrg fi 184d075918cSmrg else 1859bd41f2cSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 1869bd41f2cSmrg # might cause directories to be created, which would be especially bad 1879bd41f2cSmrg # if $src (and thus $dsttmp) contains '*'. 1889bd41f2cSmrg if test ! -f "$src" && test ! -d "$src"; then 1899bd41f2cSmrg echo "$0: $src does not exist." >&2 1909bd41f2cSmrg exit 1 1919bd41f2cSmrg fi 1929bd41f2cSmrg 1939bd41f2cSmrg if test -z "$dstarg"; then 1949bd41f2cSmrg echo "$0: no destination specified." >&2 1959bd41f2cSmrg exit 1 1969bd41f2cSmrg fi 1979bd41f2cSmrg 1989bd41f2cSmrg dst=$dstarg 1999bd41f2cSmrg # Protect names starting with `-'. 2009bd41f2cSmrg case $dst in 2019bd41f2cSmrg -*) dst=./$dst ;; 2029bd41f2cSmrg esac 2039bd41f2cSmrg 2049bd41f2cSmrg # If destination is a directory, append the input filename; won't work 2059bd41f2cSmrg # if double slashes aren't ignored. 2069bd41f2cSmrg if test -d "$dst"; then 2079bd41f2cSmrg if test -n "$no_target_directory"; then 2089bd41f2cSmrg echo "$0: $dstarg: Is a directory" >&2 2099bd41f2cSmrg exit 1 2109bd41f2cSmrg fi 211d075918cSmrg dst=$dst/`basename "$src"` 2129bd41f2cSmrg fi 2139bd41f2cSmrg fi 2149bd41f2cSmrg 215d075918cSmrg # This sed command emulates the dirname command. 216d075918cSmrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 2179bd41f2cSmrg 218d075918cSmrg # Make sure that the destination directory exists. 219d075918cSmrg 220d075918cSmrg # Skip lots of stat calls in the usual case. 221d075918cSmrg if test ! -d "$dstdir"; then 222d075918cSmrg defaultIFS=' 223d075918cSmrg ' 224d075918cSmrg IFS="${IFS-$defaultIFS}" 2259bd41f2cSmrg 226d075918cSmrg oIFS=$IFS 227d075918cSmrg # Some sh's can't handle IFS=/ for some reason. 228d075918cSmrg IFS='%' 229d075918cSmrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230d075918cSmrg shift 231d075918cSmrg IFS=$oIFS 232d075918cSmrg 233d075918cSmrg pathcomp= 234d075918cSmrg 235d075918cSmrg while test $# -ne 0 ; do 236d075918cSmrg pathcomp=$pathcomp$1 2379bd41f2cSmrg shift 238d075918cSmrg if test ! -d "$pathcomp"; then 239d075918cSmrg $mkdirprog "$pathcomp" 240d075918cSmrg # mkdir can fail with a `File exist' error in case several 241d075918cSmrg # install-sh are creating the directory concurrently. This 242d075918cSmrg # is OK. 243d075918cSmrg test -d "$pathcomp" || exit 2449bd41f2cSmrg fi 245d075918cSmrg pathcomp=$pathcomp/ 246d075918cSmrg done 2479bd41f2cSmrg fi 2489bd41f2cSmrg 2499bd41f2cSmrg if test -n "$dir_arg"; then 250d075918cSmrg $doit $mkdircmd "$dst" \ 251d075918cSmrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252d075918cSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253d075918cSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254d075918cSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255d075918cSmrg 2569bd41f2cSmrg else 257d075918cSmrg dstfile=`basename "$dst"` 2589bd41f2cSmrg 2599bd41f2cSmrg # Make a couple of temp file names in the proper directory. 2609bd41f2cSmrg dsttmp=$dstdir/_inst.$$_ 2619bd41f2cSmrg rmtmp=$dstdir/_rm.$$_ 2629bd41f2cSmrg 2639bd41f2cSmrg # Trap to clean up those temp files at exit. 2649bd41f2cSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265d075918cSmrg trap '(exit $?); exit' 1 2 13 15 2669bd41f2cSmrg 2679bd41f2cSmrg # Copy the file name to the temp name. 268d075918cSmrg $doit $cpprog "$src" "$dsttmp" && 2699bd41f2cSmrg 2709bd41f2cSmrg # and set any options; do chmod last to preserve setuid bits. 2719bd41f2cSmrg # 2729bd41f2cSmrg # If any of these fail, we abort the whole thing. If we want to 2739bd41f2cSmrg # ignore errors from any of these, just make sure not to ignore 2749bd41f2cSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 2759bd41f2cSmrg # 2769bd41f2cSmrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 2779bd41f2cSmrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 2789bd41f2cSmrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279d075918cSmrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 2809bd41f2cSmrg 2819bd41f2cSmrg # Now rename the file to the real destination. 282d075918cSmrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 2839bd41f2cSmrg || { 2849bd41f2cSmrg # The rename failed, perhaps because mv can't rename something else 2859bd41f2cSmrg # to itself, or perhaps because mv is so ancient that it does not 2869bd41f2cSmrg # support -f. 2879bd41f2cSmrg 2889bd41f2cSmrg # Now remove or move aside any old file at destination location. 2899bd41f2cSmrg # We try this two ways since rm can't unlink itself on some 2909bd41f2cSmrg # systems and the destination file might be busy for other 2919bd41f2cSmrg # reasons. In this case, the final cleanup might fail but the new 2929bd41f2cSmrg # file should still install successfully. 2939bd41f2cSmrg { 294d075918cSmrg if test -f "$dstdir/$dstfile"; then 295d075918cSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296d075918cSmrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 2979bd41f2cSmrg || { 298d075918cSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2999bd41f2cSmrg (exit 1); exit 1 3009bd41f2cSmrg } 3019bd41f2cSmrg else 3029bd41f2cSmrg : 3039bd41f2cSmrg fi 3049bd41f2cSmrg } && 3059bd41f2cSmrg 3069bd41f2cSmrg # Now rename the file to the real destination. 307d075918cSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 3089bd41f2cSmrg } 309d075918cSmrg } 310d075918cSmrg fi || { (exit 1); exit 1; } 3119bd41f2cSmrgdone 3129bd41f2cSmrg 313d075918cSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 314d075918cSmrg{ 315d075918cSmrg (exit 0); exit 0 316d075918cSmrg} 317d075918cSmrg 3189bd41f2cSmrg# Local variables: 3199bd41f2cSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 3209bd41f2cSmrg# time-stamp-start: "scriptversion=" 3219bd41f2cSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 3229bd41f2cSmrg# time-stamp-end: "$" 3239bd41f2cSmrg# End: 324