install-sh revision 2c393a42
12c393a42Smrg#!/bin/sh 22c393a42Smrg# install - install a program, script, or datafile 32c393a42Smrg 42c393a42Smrgscriptversion=2005-05-14.22 52c393a42Smrg 62c393a42Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 72c393a42Smrg# later released in X11R6 (xc/config/util/install.sh) with the 82c393a42Smrg# following copyright and license. 92c393a42Smrg# 102c393a42Smrg# Copyright (C) 1994 X Consortium 112c393a42Smrg# 122c393a42Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 132c393a42Smrg# of this software and associated documentation files (the "Software"), to 142c393a42Smrg# deal in the Software without restriction, including without limitation the 152c393a42Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 162c393a42Smrg# sell copies of the Software, and to permit persons to whom the Software is 172c393a42Smrg# furnished to do so, subject to the following conditions: 182c393a42Smrg# 192c393a42Smrg# The above copyright notice and this permission notice shall be included in 202c393a42Smrg# all copies or substantial portions of the Software. 212c393a42Smrg# 222c393a42Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 232c393a42Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 242c393a42Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 252c393a42Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 262c393a42Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 272c393a42Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 282c393a42Smrg# 292c393a42Smrg# Except as contained in this notice, the name of the X Consortium shall not 302c393a42Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 312c393a42Smrg# ings in this Software without prior written authorization from the X Consor- 322c393a42Smrg# tium. 332c393a42Smrg# 342c393a42Smrg# 352c393a42Smrg# FSF changes to this file are in the public domain. 362c393a42Smrg# 372c393a42Smrg# Calling this script install-sh is preferred over install.sh, to prevent 382c393a42Smrg# `make' implicit rules from creating a file called install from it 392c393a42Smrg# when there is no Makefile. 402c393a42Smrg# 412c393a42Smrg# This script is compatible with the BSD install script, but was written 422c393a42Smrg# from scratch. It can only install one file at a time, a restriction 432c393a42Smrg# shared with many OS's install programs. 442c393a42Smrg 452c393a42Smrg# set DOITPROG to echo to test this script 462c393a42Smrg 472c393a42Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 482c393a42Smrgdoit="${DOITPROG-}" 492c393a42Smrg 502c393a42Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 512c393a42Smrg 522c393a42Smrgmvprog="${MVPROG-mv}" 532c393a42Smrgcpprog="${CPPROG-cp}" 542c393a42Smrgchmodprog="${CHMODPROG-chmod}" 552c393a42Smrgchownprog="${CHOWNPROG-chown}" 562c393a42Smrgchgrpprog="${CHGRPPROG-chgrp}" 572c393a42Smrgstripprog="${STRIPPROG-strip}" 582c393a42Smrgrmprog="${RMPROG-rm}" 592c393a42Smrgmkdirprog="${MKDIRPROG-mkdir}" 602c393a42Smrg 612c393a42Smrgchmodcmd="$chmodprog 0755" 622c393a42Smrgchowncmd= 632c393a42Smrgchgrpcmd= 642c393a42Smrgstripcmd= 652c393a42Smrgrmcmd="$rmprog -f" 662c393a42Smrgmvcmd="$mvprog" 672c393a42Smrgsrc= 682c393a42Smrgdst= 692c393a42Smrgdir_arg= 702c393a42Smrgdstarg= 712c393a42Smrgno_target_directory= 722c393a42Smrg 732c393a42Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 742c393a42Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 752c393a42Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 762c393a42Smrg or: $0 [OPTION]... -d DIRECTORIES... 772c393a42Smrg 782c393a42SmrgIn the 1st form, copy SRCFILE to DSTFILE. 792c393a42SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 802c393a42SmrgIn the 4th, create DIRECTORIES. 812c393a42Smrg 822c393a42SmrgOptions: 832c393a42Smrg-c (ignored) 842c393a42Smrg-d create directories instead of installing files. 852c393a42Smrg-g GROUP $chgrpprog installed files to GROUP. 862c393a42Smrg-m MODE $chmodprog installed files to MODE. 872c393a42Smrg-o USER $chownprog installed files to USER. 882c393a42Smrg-s $stripprog installed files. 892c393a42Smrg-t DIRECTORY install into DIRECTORY. 902c393a42Smrg-T report an error if DSTFILE is a directory. 912c393a42Smrg--help display this help and exit. 922c393a42Smrg--version display version info and exit. 932c393a42Smrg 942c393a42SmrgEnvironment variables override the default commands: 952c393a42Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 962c393a42Smrg" 972c393a42Smrg 982c393a42Smrgwhile test -n "$1"; do 992c393a42Smrg case $1 in 1002c393a42Smrg -c) shift 1012c393a42Smrg continue;; 1022c393a42Smrg 1032c393a42Smrg -d) dir_arg=true 1042c393a42Smrg shift 1052c393a42Smrg continue;; 1062c393a42Smrg 1072c393a42Smrg -g) chgrpcmd="$chgrpprog $2" 1082c393a42Smrg shift 1092c393a42Smrg shift 1102c393a42Smrg continue;; 1112c393a42Smrg 1122c393a42Smrg --help) echo "$usage"; exit $?;; 1132c393a42Smrg 1142c393a42Smrg -m) chmodcmd="$chmodprog $2" 1152c393a42Smrg shift 1162c393a42Smrg shift 1172c393a42Smrg continue;; 1182c393a42Smrg 1192c393a42Smrg -o) chowncmd="$chownprog $2" 1202c393a42Smrg shift 1212c393a42Smrg shift 1222c393a42Smrg continue;; 1232c393a42Smrg 1242c393a42Smrg -s) stripcmd=$stripprog 1252c393a42Smrg shift 1262c393a42Smrg continue;; 1272c393a42Smrg 1282c393a42Smrg -t) dstarg=$2 1292c393a42Smrg shift 1302c393a42Smrg shift 1312c393a42Smrg continue;; 1322c393a42Smrg 1332c393a42Smrg -T) no_target_directory=true 1342c393a42Smrg shift 1352c393a42Smrg continue;; 1362c393a42Smrg 1372c393a42Smrg --version) echo "$0 $scriptversion"; exit $?;; 1382c393a42Smrg 1392c393a42Smrg *) # When -d is used, all remaining arguments are directories to create. 1402c393a42Smrg # When -t is used, the destination is already specified. 1412c393a42Smrg test -n "$dir_arg$dstarg" && break 1422c393a42Smrg # Otherwise, the last argument is the destination. Remove it from $@. 1432c393a42Smrg for arg 1442c393a42Smrg do 1452c393a42Smrg if test -n "$dstarg"; then 1462c393a42Smrg # $@ is not empty: it contains at least $arg. 1472c393a42Smrg set fnord "$@" "$dstarg" 1482c393a42Smrg shift # fnord 1492c393a42Smrg fi 1502c393a42Smrg shift # arg 1512c393a42Smrg dstarg=$arg 1522c393a42Smrg done 1532c393a42Smrg break;; 1542c393a42Smrg esac 1552c393a42Smrgdone 1562c393a42Smrg 1572c393a42Smrgif test -z "$1"; then 1582c393a42Smrg if test -z "$dir_arg"; then 1592c393a42Smrg echo "$0: no input file specified." >&2 1602c393a42Smrg exit 1 1612c393a42Smrg fi 1622c393a42Smrg # It's OK to call `install-sh -d' without argument. 1632c393a42Smrg # This can happen when creating conditional directories. 1642c393a42Smrg exit 0 1652c393a42Smrgfi 1662c393a42Smrg 1672c393a42Smrgfor src 1682c393a42Smrgdo 1692c393a42Smrg # Protect names starting with `-'. 1702c393a42Smrg case $src in 1712c393a42Smrg -*) src=./$src ;; 1722c393a42Smrg esac 1732c393a42Smrg 1742c393a42Smrg if test -n "$dir_arg"; then 1752c393a42Smrg dst=$src 1762c393a42Smrg src= 1772c393a42Smrg 1782c393a42Smrg if test -d "$dst"; then 1792c393a42Smrg mkdircmd=: 1802c393a42Smrg chmodcmd= 1812c393a42Smrg else 1822c393a42Smrg mkdircmd=$mkdirprog 1832c393a42Smrg fi 1842c393a42Smrg else 1852c393a42Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 1862c393a42Smrg # might cause directories to be created, which would be especially bad 1872c393a42Smrg # if $src (and thus $dsttmp) contains '*'. 1882c393a42Smrg if test ! -f "$src" && test ! -d "$src"; then 1892c393a42Smrg echo "$0: $src does not exist." >&2 1902c393a42Smrg exit 1 1912c393a42Smrg fi 1922c393a42Smrg 1932c393a42Smrg if test -z "$dstarg"; then 1942c393a42Smrg echo "$0: no destination specified." >&2 1952c393a42Smrg exit 1 1962c393a42Smrg fi 1972c393a42Smrg 1982c393a42Smrg dst=$dstarg 1992c393a42Smrg # Protect names starting with `-'. 2002c393a42Smrg case $dst in 2012c393a42Smrg -*) dst=./$dst ;; 2022c393a42Smrg esac 2032c393a42Smrg 2042c393a42Smrg # If destination is a directory, append the input filename; won't work 2052c393a42Smrg # if double slashes aren't ignored. 2062c393a42Smrg if test -d "$dst"; then 2072c393a42Smrg if test -n "$no_target_directory"; then 2082c393a42Smrg echo "$0: $dstarg: Is a directory" >&2 2092c393a42Smrg exit 1 2102c393a42Smrg fi 2112c393a42Smrg dst=$dst/`basename "$src"` 2122c393a42Smrg fi 2132c393a42Smrg fi 2142c393a42Smrg 2152c393a42Smrg # This sed command emulates the dirname command. 2162c393a42Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 2172c393a42Smrg 2182c393a42Smrg # Make sure that the destination directory exists. 2192c393a42Smrg 2202c393a42Smrg # Skip lots of stat calls in the usual case. 2212c393a42Smrg if test ! -d "$dstdir"; then 2222c393a42Smrg defaultIFS=' 2232c393a42Smrg ' 2242c393a42Smrg IFS="${IFS-$defaultIFS}" 2252c393a42Smrg 2262c393a42Smrg oIFS=$IFS 2272c393a42Smrg # Some sh's can't handle IFS=/ for some reason. 2282c393a42Smrg IFS='%' 2292c393a42Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 2302c393a42Smrg shift 2312c393a42Smrg IFS=$oIFS 2322c393a42Smrg 2332c393a42Smrg pathcomp= 2342c393a42Smrg 2352c393a42Smrg while test $# -ne 0 ; do 2362c393a42Smrg pathcomp=$pathcomp$1 2372c393a42Smrg shift 2382c393a42Smrg if test ! -d "$pathcomp"; then 2392c393a42Smrg $mkdirprog "$pathcomp" 2402c393a42Smrg # mkdir can fail with a `File exist' error in case several 2412c393a42Smrg # install-sh are creating the directory concurrently. This 2422c393a42Smrg # is OK. 2432c393a42Smrg test -d "$pathcomp" || exit 2442c393a42Smrg fi 2452c393a42Smrg pathcomp=$pathcomp/ 2462c393a42Smrg done 2472c393a42Smrg fi 2482c393a42Smrg 2492c393a42Smrg if test -n "$dir_arg"; then 2502c393a42Smrg $doit $mkdircmd "$dst" \ 2512c393a42Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 2522c393a42Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 2532c393a42Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 2542c393a42Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 2552c393a42Smrg 2562c393a42Smrg else 2572c393a42Smrg dstfile=`basename "$dst"` 2582c393a42Smrg 2592c393a42Smrg # Make a couple of temp file names in the proper directory. 2602c393a42Smrg dsttmp=$dstdir/_inst.$$_ 2612c393a42Smrg rmtmp=$dstdir/_rm.$$_ 2622c393a42Smrg 2632c393a42Smrg # Trap to clean up those temp files at exit. 2642c393a42Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 2652c393a42Smrg trap '(exit $?); exit' 1 2 13 15 2662c393a42Smrg 2672c393a42Smrg # Copy the file name to the temp name. 2682c393a42Smrg $doit $cpprog "$src" "$dsttmp" && 2692c393a42Smrg 2702c393a42Smrg # and set any options; do chmod last to preserve setuid bits. 2712c393a42Smrg # 2722c393a42Smrg # If any of these fail, we abort the whole thing. If we want to 2732c393a42Smrg # ignore errors from any of these, just make sure not to ignore 2742c393a42Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 2752c393a42Smrg # 2762c393a42Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 2772c393a42Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 2782c393a42Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 2792c393a42Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 2802c393a42Smrg 2812c393a42Smrg # Now rename the file to the real destination. 2822c393a42Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 2832c393a42Smrg || { 2842c393a42Smrg # The rename failed, perhaps because mv can't rename something else 2852c393a42Smrg # to itself, or perhaps because mv is so ancient that it does not 2862c393a42Smrg # support -f. 2872c393a42Smrg 2882c393a42Smrg # Now remove or move aside any old file at destination location. 2892c393a42Smrg # We try this two ways since rm can't unlink itself on some 2902c393a42Smrg # systems and the destination file might be busy for other 2912c393a42Smrg # reasons. In this case, the final cleanup might fail but the new 2922c393a42Smrg # file should still install successfully. 2932c393a42Smrg { 2942c393a42Smrg if test -f "$dstdir/$dstfile"; then 2952c393a42Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 2962c393a42Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 2972c393a42Smrg || { 2982c393a42Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 2992c393a42Smrg (exit 1); exit 1 3002c393a42Smrg } 3012c393a42Smrg else 3022c393a42Smrg : 3032c393a42Smrg fi 3042c393a42Smrg } && 3052c393a42Smrg 3062c393a42Smrg # Now rename the file to the real destination. 3072c393a42Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 3082c393a42Smrg } 3092c393a42Smrg } 3102c393a42Smrg fi || { (exit 1); exit 1; } 3112c393a42Smrgdone 3122c393a42Smrg 3132c393a42Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 3142c393a42Smrg{ 3152c393a42Smrg (exit 0); exit 0 3162c393a42Smrg} 3172c393a42Smrg 3182c393a42Smrg# Local variables: 3192c393a42Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 3202c393a42Smrg# time-stamp-start: "scriptversion=" 3212c393a42Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 3222c393a42Smrg# time-stamp-end: "$" 3232c393a42Smrg# End: 324