1251883Speter#!/bin/sh 2251883Speter# install - install a program, script, or datafile 3251883Speter 4346442Scyscriptversion=2014-09-12.12; # UTC 5251883Speter 6251883Speter# This originates from X11R5 (mit/util/scripts/install.sh), which was 7251883Speter# later released in X11R6 (xc/config/util/install.sh) with the 8251883Speter# following copyright and license. 9251883Speter# 10251883Speter# Copyright (C) 1994 X Consortium 11251883Speter# 12251883Speter# Permission is hereby granted, free of charge, to any person obtaining a copy 13251883Speter# of this software and associated documentation files (the "Software"), to 14251883Speter# deal in the Software without restriction, including without limitation the 15251883Speter# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16251883Speter# sell copies of the Software, and to permit persons to whom the Software is 17251883Speter# furnished to do so, subject to the following conditions: 18251883Speter# 19251883Speter# The above copyright notice and this permission notice shall be included in 20251883Speter# all copies or substantial portions of the Software. 21251883Speter# 22251883Speter# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23251883Speter# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24251883Speter# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25251883Speter# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26251883Speter# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27251883Speter# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28251883Speter# 29251883Speter# Except as contained in this notice, the name of the X Consortium shall not 30251883Speter# be used in advertising or otherwise to promote the sale, use or other deal- 31251883Speter# ings in this Software without prior written authorization from the X Consor- 32251883Speter# tium. 33251883Speter# 34251883Speter# 35251883Speter# FSF changes to this file are in the public domain. 36251883Speter# 37251883Speter# Calling this script install-sh is preferred over install.sh, to prevent 38298161Sbapt# 'make' implicit rules from creating a file called install from it 39251883Speter# when there is no Makefile. 40251883Speter# 41251883Speter# This script is compatible with the BSD install script, but was written 42269851Speter# from scratch. 43251883Speter 44298161Sbapttab=' ' 45269851Speternl=' 46269851Speter' 47298161SbaptIFS=" $tab$nl" 48269851Speter 49298161Sbapt# Set DOITPROG to "echo" to test this script. 50251883Speter 51269851Speterdoit=${DOITPROG-} 52298161Sbaptdoit_exec=${doit:-exec} 53251883Speter 54269851Speter# Put in absolute file names if you don't have them in your path; 55269851Speter# or use environment vars. 56251883Speter 57269851Speterchgrpprog=${CHGRPPROG-chgrp} 58269851Speterchmodprog=${CHMODPROG-chmod} 59269851Speterchownprog=${CHOWNPROG-chown} 60269851Spetercmpprog=${CMPPROG-cmp} 61269851Spetercpprog=${CPPROG-cp} 62269851Spetermkdirprog=${MKDIRPROG-mkdir} 63269851Spetermvprog=${MVPROG-mv} 64269851Speterrmprog=${RMPROG-rm} 65269851Speterstripprog=${STRIPPROG-strip} 66251883Speter 67269851Speterposix_mkdir= 68269851Speter 69269851Speter# Desired mode of installed file. 70269851Spetermode=0755 71269851Speter 72269851Speterchgrpcmd= 73269851Speterchmodcmd=$chmodprog 74251883Speterchowncmd= 75269851Spetermvcmd=$mvprog 76269851Speterrmcmd="$rmprog -f" 77251883Speterstripcmd= 78269851Speter 79251883Spetersrc= 80251883Speterdst= 81251883Speterdir_arg= 82269851Speterdst_arg= 83269851Speter 84269851Spetercopy_on_change=false 85298161Sbaptis_target_a_directory=possibly 86251883Speter 87269851Speterusage="\ 88269851SpeterUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89251883Speter or: $0 [OPTION]... SRCFILES... DIRECTORY 90251883Speter or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91251883Speter or: $0 [OPTION]... -d DIRECTORIES... 92251883Speter 93251883SpeterIn the 1st form, copy SRCFILE to DSTFILE. 94251883SpeterIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95251883SpeterIn the 4th, create DIRECTORIES. 96251883Speter 97251883SpeterOptions: 98269851Speter --help display this help and exit. 99269851Speter --version display version info and exit. 100251883Speter 101269851Speter -c (ignored) 102269851Speter -C install only if different (preserve the last data modification time) 103269851Speter -d create directories instead of installing files. 104269851Speter -g GROUP $chgrpprog installed files to GROUP. 105269851Speter -m MODE $chmodprog installed files to MODE. 106269851Speter -o USER $chownprog installed files to USER. 107269851Speter -s $stripprog installed files. 108269851Speter -t DIRECTORY install into DIRECTORY. 109269851Speter -T report an error if DSTFILE is a directory. 110269851Speter 111251883SpeterEnvironment variables override the default commands: 112269851Speter CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 113269851Speter RMPROG STRIPPROG 114251883Speter" 115251883Speter 116269851Speterwhile test $# -ne 0; do 117251883Speter case $1 in 118269851Speter -c) ;; 119251883Speter 120269851Speter -C) copy_on_change=true;; 121251883Speter 122269851Speter -d) dir_arg=true;; 123269851Speter 124251883Speter -g) chgrpcmd="$chgrpprog $2" 125298161Sbapt shift;; 126251883Speter 127251883Speter --help) echo "$usage"; exit $?;; 128251883Speter 129269851Speter -m) mode=$2 130298161Sbapt case $mode in 131298161Sbapt *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) 132298161Sbapt echo "$0: invalid mode: $mode" >&2 133298161Sbapt exit 1;; 134298161Sbapt esac 135298161Sbapt shift;; 136251883Speter 137251883Speter -o) chowncmd="$chownprog $2" 138298161Sbapt shift;; 139251883Speter 140269851Speter -s) stripcmd=$stripprog;; 141251883Speter 142298161Sbapt -t) 143298161Sbapt is_target_a_directory=always 144298161Sbapt dst_arg=$2 145298161Sbapt # Protect names problematic for 'test' and other utilities. 146298161Sbapt case $dst_arg in 147298161Sbapt -* | [=\(\)!]) dst_arg=./$dst_arg;; 148298161Sbapt esac 149298161Sbapt shift;; 150251883Speter 151298161Sbapt -T) is_target_a_directory=never;; 152251883Speter 153251883Speter --version) echo "$0 $scriptversion"; exit $?;; 154251883Speter 155298161Sbapt --) shift 156298161Sbapt break;; 157269851Speter 158298161Sbapt -*) echo "$0: invalid option: $1" >&2 159298161Sbapt exit 1;; 160269851Speter 161269851Speter *) break;; 162251883Speter esac 163269851Speter shift 164251883Speterdone 165251883Speter 166298161Sbapt# We allow the use of options -d and -T together, by making -d 167298161Sbapt# take the precedence; this is for compatibility with GNU install. 168298161Sbapt 169298161Sbaptif test -n "$dir_arg"; then 170298161Sbapt if test -n "$dst_arg"; then 171298161Sbapt echo "$0: target directory not allowed when installing a directory." >&2 172298161Sbapt exit 1 173298161Sbapt fi 174298161Sbaptfi 175298161Sbapt 176269851Speterif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177269851Speter # When -d is used, all remaining arguments are directories to create. 178269851Speter # When -t is used, the destination is already specified. 179269851Speter # Otherwise, the last argument is the destination. Remove it from $@. 180269851Speter for arg 181269851Speter do 182269851Speter if test -n "$dst_arg"; then 183269851Speter # $@ is not empty: it contains at least $arg. 184269851Speter set fnord "$@" "$dst_arg" 185269851Speter shift # fnord 186269851Speter fi 187269851Speter shift # arg 188269851Speter dst_arg=$arg 189298161Sbapt # Protect names problematic for 'test' and other utilities. 190269851Speter case $dst_arg in 191269851Speter -* | [=\(\)!]) dst_arg=./$dst_arg;; 192269851Speter esac 193269851Speter done 194269851Speterfi 195269851Speter 196269851Speterif test $# -eq 0; then 197251883Speter if test -z "$dir_arg"; then 198251883Speter echo "$0: no input file specified." >&2 199251883Speter exit 1 200251883Speter fi 201298161Sbapt # It's OK to call 'install-sh -d' without argument. 202251883Speter # This can happen when creating conditional directories. 203251883Speter exit 0 204251883Speterfi 205251883Speter 206269851Speterif test -z "$dir_arg"; then 207298161Sbapt if test $# -gt 1 || test "$is_target_a_directory" = always; then 208298161Sbapt if test ! -d "$dst_arg"; then 209298161Sbapt echo "$0: $dst_arg: Is not a directory." >&2 210298161Sbapt exit 1 211298161Sbapt fi 212298161Sbapt fi 213298161Sbaptfi 214298161Sbapt 215298161Sbaptif test -z "$dir_arg"; then 216269851Speter do_exit='(exit $ret); exit $ret' 217269851Speter trap "ret=129; $do_exit" 1 218269851Speter trap "ret=130; $do_exit" 2 219269851Speter trap "ret=141; $do_exit" 13 220269851Speter trap "ret=143; $do_exit" 15 221269851Speter 222269851Speter # Set umask so as not to create temps with too-generous modes. 223269851Speter # However, 'strip' requires both read and write access to temps. 224269851Speter case $mode in 225269851Speter # Optimize common cases. 226269851Speter *644) cp_umask=133;; 227269851Speter *755) cp_umask=22;; 228269851Speter 229269851Speter *[0-7]) 230269851Speter if test -z "$stripcmd"; then 231298161Sbapt u_plus_rw= 232269851Speter else 233298161Sbapt u_plus_rw='% 200' 234269851Speter fi 235269851Speter cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 236269851Speter *) 237269851Speter if test -z "$stripcmd"; then 238298161Sbapt u_plus_rw= 239269851Speter else 240298161Sbapt u_plus_rw=,u+rw 241269851Speter fi 242269851Speter cp_umask=$mode$u_plus_rw;; 243269851Speter esac 244269851Speterfi 245269851Speter 246251883Speterfor src 247251883Speterdo 248298161Sbapt # Protect names problematic for 'test' and other utilities. 249251883Speter case $src in 250269851Speter -* | [=\(\)!]) src=./$src;; 251251883Speter esac 252251883Speter 253251883Speter if test -n "$dir_arg"; then 254251883Speter dst=$src 255269851Speter dstdir=$dst 256269851Speter test -d "$dstdir" 257269851Speter dstdir_status=$? 258269851Speter else 259251883Speter 260251883Speter # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 261251883Speter # might cause directories to be created, which would be especially bad 262251883Speter # if $src (and thus $dsttmp) contains '*'. 263251883Speter if test ! -f "$src" && test ! -d "$src"; then 264251883Speter echo "$0: $src does not exist." >&2 265251883Speter exit 1 266251883Speter fi 267251883Speter 268269851Speter if test -z "$dst_arg"; then 269251883Speter echo "$0: no destination specified." >&2 270251883Speter exit 1 271251883Speter fi 272269851Speter dst=$dst_arg 273251883Speter 274251883Speter # If destination is a directory, append the input filename; won't work 275251883Speter # if double slashes aren't ignored. 276251883Speter if test -d "$dst"; then 277298161Sbapt if test "$is_target_a_directory" = never; then 278298161Sbapt echo "$0: $dst_arg: Is a directory" >&2 279298161Sbapt exit 1 280251883Speter fi 281269851Speter dstdir=$dst 282269851Speter dst=$dstdir/`basename "$src"` 283269851Speter dstdir_status=0 284269851Speter else 285298161Sbapt dstdir=`dirname "$dst"` 286269851Speter test -d "$dstdir" 287269851Speter dstdir_status=$? 288251883Speter fi 289251883Speter fi 290251883Speter 291269851Speter obsolete_mkdir_used=false 292251883Speter 293269851Speter if test $dstdir_status != 0; then 294269851Speter case $posix_mkdir in 295269851Speter '') 296298161Sbapt # Create intermediate dirs using mode 755 as modified by the umask. 297298161Sbapt # This is like FreeBSD 'install' as of 1997-10-28. 298298161Sbapt umask=`umask` 299298161Sbapt case $stripcmd.$umask in 300298161Sbapt # Optimize common cases. 301298161Sbapt *[2367][2367]) mkdir_umask=$umask;; 302298161Sbapt .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 303251883Speter 304298161Sbapt *[0-7]) 305298161Sbapt mkdir_umask=`expr $umask + 22 \ 306298161Sbapt - $umask % 100 % 40 + $umask % 20 \ 307298161Sbapt - $umask % 10 % 4 + $umask % 2 308298161Sbapt `;; 309298161Sbapt *) mkdir_umask=$umask,go-w;; 310298161Sbapt esac 311251883Speter 312298161Sbapt # With -d, create the new directory with the user-specified mode. 313298161Sbapt # Otherwise, rely on $mkdir_umask. 314298161Sbapt if test -n "$dir_arg"; then 315298161Sbapt mkdir_mode=-m$mode 316298161Sbapt else 317298161Sbapt mkdir_mode= 318298161Sbapt fi 319251883Speter 320298161Sbapt posix_mkdir=false 321298161Sbapt case $umask in 322298161Sbapt *[123567][0-7][0-7]) 323298161Sbapt # POSIX mkdir -p sets u+wx bits regardless of umask, which 324298161Sbapt # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 325298161Sbapt ;; 326298161Sbapt *) 327346442Scy # $RANDOM is not portable (e.g. dash); use it when possible to 328346442Scy # lower collision chance 329298161Sbapt tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 330346442Scy trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 331251883Speter 332346442Scy # As "mkdir -p" follows symlinks and we work in /tmp possibly; so 333346442Scy # create the $tmpdir first (and fail if unsuccessful) to make sure 334346442Scy # that nobody tries to guess the $tmpdir name. 335298161Sbapt if (umask $mkdir_umask && 336346442Scy $mkdirprog $mkdir_mode "$tmpdir" && 337346442Scy exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 338298161Sbapt then 339298161Sbapt if test -z "$dir_arg" || { 340298161Sbapt # Check for POSIX incompatibilities with -m. 341298161Sbapt # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 342298161Sbapt # other-writable bit of parent directory when it shouldn't. 343298161Sbapt # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 344346442Scy test_tmpdir="$tmpdir/a" 345346442Scy ls_ld_tmpdir=`ls -ld "$test_tmpdir"` 346298161Sbapt case $ls_ld_tmpdir in 347298161Sbapt d????-?r-*) different_mode=700;; 348298161Sbapt d????-?--*) different_mode=755;; 349298161Sbapt *) false;; 350298161Sbapt esac && 351346442Scy $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { 352346442Scy ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` 353298161Sbapt test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 354298161Sbapt } 355298161Sbapt } 356298161Sbapt then posix_mkdir=: 357298161Sbapt fi 358346442Scy rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 359298161Sbapt else 360298161Sbapt # Remove any dirs left behind by ancient mkdir implementations. 361346442Scy rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null 362298161Sbapt fi 363298161Sbapt trap '' 0;; 364298161Sbapt esac;; 365269851Speter esac 366269851Speter 367269851Speter if 368269851Speter $posix_mkdir && ( 369298161Sbapt umask $mkdir_umask && 370298161Sbapt $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 371269851Speter ) 372269851Speter then : 373269851Speter else 374269851Speter 375269851Speter # The umask is ridiculous, or mkdir does not conform to POSIX, 376269851Speter # or it failed possibly due to a race condition. Create the 377269851Speter # directory the slow way, step by step, checking for races as we go. 378269851Speter 379269851Speter case $dstdir in 380298161Sbapt /*) prefix='/';; 381298161Sbapt [-=\(\)!]*) prefix='./';; 382298161Sbapt *) prefix='';; 383269851Speter esac 384269851Speter 385269851Speter oIFS=$IFS 386269851Speter IFS=/ 387298161Sbapt set -f 388269851Speter set fnord $dstdir 389251883Speter shift 390298161Sbapt set +f 391269851Speter IFS=$oIFS 392269851Speter 393269851Speter prefixes= 394269851Speter 395269851Speter for d 396269851Speter do 397298161Sbapt test X"$d" = X && continue 398269851Speter 399298161Sbapt prefix=$prefix$d 400298161Sbapt if test -d "$prefix"; then 401298161Sbapt prefixes= 402298161Sbapt else 403298161Sbapt if $posix_mkdir; then 404298161Sbapt (umask=$mkdir_umask && 405298161Sbapt $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 406298161Sbapt # Don't fail if two instances are running concurrently. 407298161Sbapt test -d "$prefix" || exit 1 408298161Sbapt else 409298161Sbapt case $prefix in 410298161Sbapt *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 411298161Sbapt *) qprefix=$prefix;; 412298161Sbapt esac 413298161Sbapt prefixes="$prefixes '$qprefix'" 414298161Sbapt fi 415298161Sbapt fi 416298161Sbapt prefix=$prefix/ 417269851Speter done 418269851Speter 419269851Speter if test -n "$prefixes"; then 420298161Sbapt # Don't fail if two instances are running concurrently. 421298161Sbapt (umask $mkdir_umask && 422298161Sbapt eval "\$doit_exec \$mkdirprog $prefixes") || 423298161Sbapt test -d "$dstdir" || exit 1 424298161Sbapt obsolete_mkdir_used=true 425251883Speter fi 426269851Speter fi 427251883Speter fi 428251883Speter 429251883Speter if test -n "$dir_arg"; then 430269851Speter { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 431269851Speter { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 432269851Speter { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 433269851Speter test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 434251883Speter else 435251883Speter 436251883Speter # Make a couple of temp file names in the proper directory. 437251883Speter dsttmp=$dstdir/_inst.$$_ 438251883Speter rmtmp=$dstdir/_rm.$$_ 439251883Speter 440251883Speter # Trap to clean up those temp files at exit. 441251883Speter trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 442251883Speter 443251883Speter # Copy the file name to the temp name. 444269851Speter (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 445251883Speter 446251883Speter # and set any options; do chmod last to preserve setuid bits. 447251883Speter # 448251883Speter # If any of these fail, we abort the whole thing. If we want to 449251883Speter # ignore errors from any of these, just make sure not to ignore 450251883Speter # errors from the above "$doit $cpprog $src $dsttmp" command. 451251883Speter # 452269851Speter { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 453269851Speter { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 454269851Speter { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 455269851Speter { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 456251883Speter 457269851Speter # If -C, don't bother to copy if it wouldn't change the file. 458269851Speter if $copy_on_change && 459298161Sbapt old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 460298161Sbapt new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 461298161Sbapt set -f && 462269851Speter set X $old && old=:$2:$4:$5:$6 && 463269851Speter set X $new && new=:$2:$4:$5:$6 && 464298161Sbapt set +f && 465269851Speter test "$old" = "$new" && 466269851Speter $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 467269851Speter then 468269851Speter rm -f "$dsttmp" 469269851Speter else 470269851Speter # Rename the file to the real destination. 471269851Speter $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 472269851Speter 473269851Speter # The rename failed, perhaps because mv can't rename something else 474269851Speter # to itself, or perhaps because mv is so ancient that it does not 475269851Speter # support -f. 476269851Speter { 477298161Sbapt # Now remove or move aside any old file at destination location. 478298161Sbapt # We try this two ways since rm can't unlink itself on some 479298161Sbapt # systems and the destination file might be busy for other 480298161Sbapt # reasons. In this case, the final cleanup might fail but the new 481298161Sbapt # file should still install successfully. 482298161Sbapt { 483298161Sbapt test ! -f "$dst" || 484298161Sbapt $doit $rmcmd -f "$dst" 2>/dev/null || 485298161Sbapt { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 486298161Sbapt { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 487298161Sbapt } || 488298161Sbapt { echo "$0: cannot unlink or rename $dst" >&2 489298161Sbapt (exit 1); exit 1 490298161Sbapt } 491298161Sbapt } && 492269851Speter 493298161Sbapt # Now rename the file to the real destination. 494298161Sbapt $doit $mvcmd "$dsttmp" "$dst" 495269851Speter } 496269851Speter fi || exit 1 497269851Speter 498269851Speter trap '' 0 499269851Speter fi 500251883Speterdone 501251883Speter 502251883Speter# Local variables: 503251883Speter# eval: (add-hook 'write-file-hooks 'time-stamp) 504251883Speter# time-stamp-start: "scriptversion=" 505251883Speter# time-stamp-format: "%:y-%02m-%02d.%02H" 506269851Speter# time-stamp-time-zone: "UTC" 507269851Speter# time-stamp-end: "; # UTC" 508251883Speter# End: 509