install-sh revision 9027f4a0
19027f4a0Smrg#!/bin/sh 29027f4a0Smrg# install - install a program, script, or datafile 39027f4a0Smrg 49027f4a0Smrgscriptversion=2005-05-14.22 59027f4a0Smrg 69027f4a0Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 79027f4a0Smrg# later released in X11R6 (xc/config/util/install.sh) with the 89027f4a0Smrg# following copyright and license. 99027f4a0Smrg# 109027f4a0Smrg# Copyright (C) 1994 X Consortium 119027f4a0Smrg# 129027f4a0Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 139027f4a0Smrg# of this software and associated documentation files (the "Software"), to 149027f4a0Smrg# deal in the Software without restriction, including without limitation the 159027f4a0Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 169027f4a0Smrg# sell copies of the Software, and to permit persons to whom the Software is 179027f4a0Smrg# furnished to do so, subject to the following conditions: 189027f4a0Smrg# 199027f4a0Smrg# The above copyright notice and this permission notice shall be included in 209027f4a0Smrg# all copies or substantial portions of the Software. 219027f4a0Smrg# 229027f4a0Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 239027f4a0Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 249027f4a0Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 259027f4a0Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 269027f4a0Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 279027f4a0Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 289027f4a0Smrg# 299027f4a0Smrg# Except as contained in this notice, the name of the X Consortium shall not 309027f4a0Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 319027f4a0Smrg# ings in this Software without prior written authorization from the X Consor- 329027f4a0Smrg# tium. 339027f4a0Smrg# 349027f4a0Smrg# 359027f4a0Smrg# FSF changes to this file are in the public domain. 369027f4a0Smrg# 379027f4a0Smrg# Calling this script install-sh is preferred over install.sh, to prevent 389027f4a0Smrg# `make' implicit rules from creating a file called install from it 399027f4a0Smrg# when there is no Makefile. 409027f4a0Smrg# 419027f4a0Smrg# This script is compatible with the BSD install script, but was written 429027f4a0Smrg# from scratch. It can only install one file at a time, a restriction 439027f4a0Smrg# shared with many OS's install programs. 449027f4a0Smrg 459027f4a0Smrg# set DOITPROG to echo to test this script 469027f4a0Smrg 479027f4a0Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 489027f4a0Smrgdoit="${DOITPROG-}" 499027f4a0Smrg 509027f4a0Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 519027f4a0Smrg 529027f4a0Smrgmvprog="${MVPROG-mv}" 539027f4a0Smrgcpprog="${CPPROG-cp}" 549027f4a0Smrgchmodprog="${CHMODPROG-chmod}" 559027f4a0Smrgchownprog="${CHOWNPROG-chown}" 569027f4a0Smrgchgrpprog="${CHGRPPROG-chgrp}" 579027f4a0Smrgstripprog="${STRIPPROG-strip}" 589027f4a0Smrgrmprog="${RMPROG-rm}" 599027f4a0Smrgmkdirprog="${MKDIRPROG-mkdir}" 609027f4a0Smrg 619027f4a0Smrgchmodcmd="$chmodprog 0755" 629027f4a0Smrgchowncmd= 639027f4a0Smrgchgrpcmd= 649027f4a0Smrgstripcmd= 659027f4a0Smrgrmcmd="$rmprog -f" 669027f4a0Smrgmvcmd="$mvprog" 679027f4a0Smrgsrc= 689027f4a0Smrgdst= 699027f4a0Smrgdir_arg= 709027f4a0Smrgdstarg= 719027f4a0Smrgno_target_directory= 729027f4a0Smrg 739027f4a0Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 749027f4a0Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 759027f4a0Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 769027f4a0Smrg or: $0 [OPTION]... -d DIRECTORIES... 779027f4a0Smrg 789027f4a0SmrgIn the 1st form, copy SRCFILE to DSTFILE. 799027f4a0SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 809027f4a0SmrgIn the 4th, create DIRECTORIES. 819027f4a0Smrg 829027f4a0SmrgOptions: 839027f4a0Smrg-c (ignored) 849027f4a0Smrg-d create directories instead of installing files. 859027f4a0Smrg-g GROUP $chgrpprog installed files to GROUP. 869027f4a0Smrg-m MODE $chmodprog installed files to MODE. 879027f4a0Smrg-o USER $chownprog installed files to USER. 889027f4a0Smrg-s $stripprog installed files. 899027f4a0Smrg-t DIRECTORY install into DIRECTORY. 909027f4a0Smrg-T report an error if DSTFILE is a directory. 919027f4a0Smrg--help display this help and exit. 929027f4a0Smrg--version display version info and exit. 939027f4a0Smrg 949027f4a0SmrgEnvironment variables override the default commands: 959027f4a0Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 969027f4a0Smrg" 979027f4a0Smrg 989027f4a0Smrgwhile test -n "$1"; do 999027f4a0Smrg case $1 in 1009027f4a0Smrg -c) shift 1019027f4a0Smrg continue;; 1029027f4a0Smrg 1039027f4a0Smrg -d) dir_arg=true 1049027f4a0Smrg shift 1059027f4a0Smrg continue;; 1069027f4a0Smrg 1079027f4a0Smrg -g) chgrpcmd="$chgrpprog $2" 1089027f4a0Smrg shift 1099027f4a0Smrg shift 1109027f4a0Smrg continue;; 1119027f4a0Smrg 1129027f4a0Smrg --help) echo "$usage"; exit $?;; 1139027f4a0Smrg 1149027f4a0Smrg -m) chmodcmd="$chmodprog $2" 1159027f4a0Smrg shift 1169027f4a0Smrg shift 1179027f4a0Smrg continue;; 1189027f4a0Smrg 1199027f4a0Smrg -o) chowncmd="$chownprog $2" 1209027f4a0Smrg shift 1219027f4a0Smrg shift 1229027f4a0Smrg continue;; 1239027f4a0Smrg 1249027f4a0Smrg -s) stripcmd=$stripprog 1259027f4a0Smrg shift 1269027f4a0Smrg continue;; 1279027f4a0Smrg 1289027f4a0Smrg -t) dstarg=$2 1299027f4a0Smrg shift 1309027f4a0Smrg shift 1319027f4a0Smrg continue;; 1329027f4a0Smrg 1339027f4a0Smrg -T) no_target_directory=true 1349027f4a0Smrg shift 1359027f4a0Smrg continue;; 1369027f4a0Smrg 1379027f4a0Smrg --version) echo "$0 $scriptversion"; exit $?;; 1389027f4a0Smrg 1399027f4a0Smrg *) # When -d is used, all remaining arguments are directories to create. 1409027f4a0Smrg # When -t is used, the destination is already specified. 1419027f4a0Smrg test -n "$dir_arg$dstarg" && break 1429027f4a0Smrg # Otherwise, the last argument is the destination. Remove it from $@. 1439027f4a0Smrg for arg 1449027f4a0Smrg do 1459027f4a0Smrg if test -n "$dstarg"; then 1469027f4a0Smrg # $@ is not empty: it contains at least $arg. 1479027f4a0Smrg set fnord "$@" "$dstarg" 1489027f4a0Smrg shift # fnord 1499027f4a0Smrg fi 1509027f4a0Smrg shift # arg 1519027f4a0Smrg dstarg=$arg 1529027f4a0Smrg done 1539027f4a0Smrg break;; 1549027f4a0Smrg esac 1559027f4a0Smrgdone 1569027f4a0Smrg 1579027f4a0Smrgif test -z "$1"; then 1589027f4a0Smrg if test -z "$dir_arg"; then 1599027f4a0Smrg echo "$0: no input file specified." >&2 1609027f4a0Smrg exit 1 1619027f4a0Smrg fi 1629027f4a0Smrg # It's OK to call `install-sh -d' without argument. 1639027f4a0Smrg # This can happen when creating conditional directories. 1649027f4a0Smrg exit 0 1659027f4a0Smrgfi 1669027f4a0Smrg 1679027f4a0Smrgfor src 1689027f4a0Smrgdo 1699027f4a0Smrg # Protect names starting with `-'. 1709027f4a0Smrg case $src in 1719027f4a0Smrg -*) src=./$src ;; 1729027f4a0Smrg esac 1739027f4a0Smrg 1749027f4a0Smrg if test -n "$dir_arg"; then 1759027f4a0Smrg dst=$src 1769027f4a0Smrg src= 1779027f4a0Smrg 1789027f4a0Smrg if test -d "$dst"; then 1799027f4a0Smrg mkdircmd=: 1809027f4a0Smrg chmodcmd= 1819027f4a0Smrg else 1829027f4a0Smrg mkdircmd=$mkdirprog 1839027f4a0Smrg fi 1849027f4a0Smrg else 1859027f4a0Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 1869027f4a0Smrg # might cause directories to be created, which would be especially bad 1879027f4a0Smrg # if $src (and thus $dsttmp) contains '*'. 1889027f4a0Smrg if test ! -f "$src" && test ! -d "$src"; then 1899027f4a0Smrg echo "$0: $src does not exist." >&2 1909027f4a0Smrg exit 1 1919027f4a0Smrg fi 1929027f4a0Smrg 1939027f4a0Smrg if test -z "$dstarg"; then 1949027f4a0Smrg echo "$0: no destination specified." >&2 1959027f4a0Smrg exit 1 1969027f4a0Smrg fi 1979027f4a0Smrg 1989027f4a0Smrg dst=$dstarg 1999027f4a0Smrg # Protect names starting with `-'. 2009027f4a0Smrg case $dst in 2019027f4a0Smrg -*) dst=./$dst ;; 2029027f4a0Smrg esac 2039027f4a0Smrg 2049027f4a0Smrg # If destination is a directory, append the input filename; won't work 2059027f4a0Smrg # if double slashes aren't ignored. 2069027f4a0Smrg if test -d "$dst"; then 2079027f4a0Smrg if test -n "$no_target_directory"; then 2089027f4a0Smrg echo "$0: $dstarg: Is a directory" >&2 2099027f4a0Smrg exit 1 2109027f4a0Smrg fi 2119027f4a0Smrg dst=$dst/`basename "$src"` 2129027f4a0Smrg fi 2139027f4a0Smrg fi 2149027f4a0Smrg 2159027f4a0Smrg # This sed command emulates the dirname command. 2169027f4a0Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 2179027f4a0Smrg 2189027f4a0Smrg # Make sure that the destination directory exists. 2199027f4a0Smrg 2209027f4a0Smrg # Skip lots of stat calls in the usual case. 2219027f4a0Smrg if test ! -d "$dstdir"; then 2229027f4a0Smrg defaultIFS=' 2239027f4a0Smrg ' 2249027f4a0Smrg IFS="${IFS-$defaultIFS}" 2259027f4a0Smrg 2269027f4a0Smrg oIFS=$IFS 2279027f4a0Smrg # Some sh's can't handle IFS=/ for some reason. 2289027f4a0Smrg IFS='%' 2299027f4a0Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 2309027f4a0Smrg shift 2319027f4a0Smrg IFS=$oIFS 2329027f4a0Smrg 2339027f4a0Smrg pathcomp= 2349027f4a0Smrg 2359027f4a0Smrg while test $# -ne 0 ; do 2369027f4a0Smrg pathcomp=$pathcomp$1 2379027f4a0Smrg shift 2389027f4a0Smrg if test ! -d "$pathcomp"; then 2399027f4a0Smrg $mkdirprog "$pathcomp" 2409027f4a0Smrg # mkdir can fail with a `File exist' error in case several 2419027f4a0Smrg # install-sh are creating the directory concurrently. This 2429027f4a0Smrg # is OK. 2439027f4a0Smrg test -d "$pathcomp" || exit 2449027f4a0Smrg fi 2459027f4a0Smrg pathcomp=$pathcomp/ 2469027f4a0Smrg done 2479027f4a0Smrg fi 2489027f4a0Smrg 2499027f4a0Smrg if test -n "$dir_arg"; then 2509027f4a0Smrg $doit $mkdircmd "$dst" \ 2519027f4a0Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 2529027f4a0Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 2539027f4a0Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 2549027f4a0Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 2559027f4a0Smrg 2569027f4a0Smrg else 2579027f4a0Smrg dstfile=`basename "$dst"` 2589027f4a0Smrg 2599027f4a0Smrg # Make a couple of temp file names in the proper directory. 2609027f4a0Smrg dsttmp=$dstdir/_inst.$$_ 2619027f4a0Smrg rmtmp=$dstdir/_rm.$$_ 2629027f4a0Smrg 2639027f4a0Smrg # Trap to clean up those temp files at exit. 2649027f4a0Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 2659027f4a0Smrg trap '(exit $?); exit' 1 2 13 15 2669027f4a0Smrg 2679027f4a0Smrg # Copy the file name to the temp name. 2689027f4a0Smrg $doit $cpprog "$src" "$dsttmp" && 2699027f4a0Smrg 2709027f4a0Smrg # and set any options; do chmod last to preserve setuid bits. 2719027f4a0Smrg # 2729027f4a0Smrg # If any of these fail, we abort the whole thing. If we want to 2739027f4a0Smrg # ignore errors from any of these, just make sure not to ignore 2749027f4a0Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 2759027f4a0Smrg # 2769027f4a0Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 2779027f4a0Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 2789027f4a0Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 2799027f4a0Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 2809027f4a0Smrg 2819027f4a0Smrg # Now rename the file to the real destination. 2829027f4a0Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 2839027f4a0Smrg || { 2849027f4a0Smrg # The rename failed, perhaps because mv can't rename something else 2859027f4a0Smrg # to itself, or perhaps because mv is so ancient that it does not 2869027f4a0Smrg # support -f. 2879027f4a0Smrg 2889027f4a0Smrg # Now remove or move aside any old file at destination location. 2899027f4a0Smrg # We try this two ways since rm can't unlink itself on some 2909027f4a0Smrg # systems and the destination file might be busy for other 2919027f4a0Smrg # reasons. In this case, the final cleanup might fail but the new 2929027f4a0Smrg # file should still install successfully. 2939027f4a0Smrg { 2949027f4a0Smrg if test -f "$dstdir/$dstfile"; then 2959027f4a0Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 2969027f4a0Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 2979027f4a0Smrg || { 2989027f4a0Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2999027f4a0Smrg (exit 1); exit 1 3009027f4a0Smrg } 3019027f4a0Smrg else 3029027f4a0Smrg : 3039027f4a0Smrg fi 3049027f4a0Smrg } && 3059027f4a0Smrg 3069027f4a0Smrg # Now rename the file to the real destination. 3079027f4a0Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 3089027f4a0Smrg } 3099027f4a0Smrg } 3109027f4a0Smrg fi || { (exit 1); exit 1; } 3119027f4a0Smrgdone 3129027f4a0Smrg 3139027f4a0Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 3149027f4a0Smrg{ 3159027f4a0Smrg (exit 0); exit 0 3169027f4a0Smrg} 3179027f4a0Smrg 3189027f4a0Smrg# Local variables: 3199027f4a0Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 3209027f4a0Smrg# time-stamp-start: "scriptversion=" 3219027f4a0Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 3229027f4a0Smrg# time-stamp-end: "$" 3239027f4a0Smrg# End: 324