1*946379e7Schristos#!/bin/sh 2*946379e7Schristos# install - install a program, script, or datafile 3*946379e7Schristos 4*946379e7Schristosscriptversion=2005-05-14.22 5*946379e7Schristos 6*946379e7Schristos# This originates from X11R5 (mit/util/scripts/install.sh), which was 7*946379e7Schristos# later released in X11R6 (xc/config/util/install.sh) with the 8*946379e7Schristos# following copyright and license. 9*946379e7Schristos# 10*946379e7Schristos# Copyright (C) 1994 X Consortium 11*946379e7Schristos# 12*946379e7Schristos# Permission is hereby granted, free of charge, to any person obtaining a copy 13*946379e7Schristos# of this software and associated documentation files (the "Software"), to 14*946379e7Schristos# deal in the Software without restriction, including without limitation the 15*946379e7Schristos# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16*946379e7Schristos# sell copies of the Software, and to permit persons to whom the Software is 17*946379e7Schristos# furnished to do so, subject to the following conditions: 18*946379e7Schristos# 19*946379e7Schristos# The above copyright notice and this permission notice shall be included in 20*946379e7Schristos# all copies or substantial portions of the Software. 21*946379e7Schristos# 22*946379e7Schristos# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23*946379e7Schristos# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24*946379e7Schristos# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25*946379e7Schristos# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26*946379e7Schristos# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27*946379e7Schristos# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28*946379e7Schristos# 29*946379e7Schristos# Except as contained in this notice, the name of the X Consortium shall not 30*946379e7Schristos# be used in advertising or otherwise to promote the sale, use or other deal- 31*946379e7Schristos# ings in this Software without prior written authorization from the X Consor- 32*946379e7Schristos# tium. 33*946379e7Schristos# 34*946379e7Schristos# 35*946379e7Schristos# FSF changes to this file are in the public domain. 36*946379e7Schristos# 37*946379e7Schristos# Calling this script install-sh is preferred over install.sh, to prevent 38*946379e7Schristos# `make' implicit rules from creating a file called install from it 39*946379e7Schristos# when there is no Makefile. 40*946379e7Schristos# 41*946379e7Schristos# This script is compatible with the BSD install script, but was written 42*946379e7Schristos# from scratch. It can only install one file at a time, a restriction 43*946379e7Schristos# shared with many OS's install programs. 44*946379e7Schristos 45*946379e7Schristos# set DOITPROG to echo to test this script 46*946379e7Schristos 47*946379e7Schristos# Don't use :- since 4.3BSD and earlier shells don't like it. 48*946379e7Schristosdoit="${DOITPROG-}" 49*946379e7Schristos 50*946379e7Schristos# put in absolute paths if you don't have them in your path; or use env. vars. 51*946379e7Schristos 52*946379e7Schristosmvprog="${MVPROG-mv}" 53*946379e7Schristoscpprog="${CPPROG-cp}" 54*946379e7Schristoschmodprog="${CHMODPROG-chmod}" 55*946379e7Schristoschownprog="${CHOWNPROG-chown}" 56*946379e7Schristoschgrpprog="${CHGRPPROG-chgrp}" 57*946379e7Schristosstripprog="${STRIPPROG-strip}" 58*946379e7Schristosrmprog="${RMPROG-rm}" 59*946379e7Schristosmkdirprog="${MKDIRPROG-mkdir}" 60*946379e7Schristos 61*946379e7Schristoschmodcmd="$chmodprog 0755" 62*946379e7Schristoschowncmd= 63*946379e7Schristoschgrpcmd= 64*946379e7Schristosstripcmd= 65*946379e7Schristosrmcmd="$rmprog -f" 66*946379e7Schristosmvcmd="$mvprog" 67*946379e7Schristossrc= 68*946379e7Schristosdst= 69*946379e7Schristosdir_arg= 70*946379e7Schristosdstarg= 71*946379e7Schristosno_target_directory= 72*946379e7Schristos 73*946379e7Schristosusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74*946379e7Schristos or: $0 [OPTION]... SRCFILES... DIRECTORY 75*946379e7Schristos or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76*946379e7Schristos or: $0 [OPTION]... -d DIRECTORIES... 77*946379e7Schristos 78*946379e7SchristosIn the 1st form, copy SRCFILE to DSTFILE. 79*946379e7SchristosIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80*946379e7SchristosIn the 4th, create DIRECTORIES. 81*946379e7Schristos 82*946379e7SchristosOptions: 83*946379e7Schristos-c (ignored) 84*946379e7Schristos-d create directories instead of installing files. 85*946379e7Schristos-g GROUP $chgrpprog installed files to GROUP. 86*946379e7Schristos-m MODE $chmodprog installed files to MODE. 87*946379e7Schristos-o USER $chownprog installed files to USER. 88*946379e7Schristos-s $stripprog installed files. 89*946379e7Schristos-t DIRECTORY install into DIRECTORY. 90*946379e7Schristos-T report an error if DSTFILE is a directory. 91*946379e7Schristos--help display this help and exit. 92*946379e7Schristos--version display version info and exit. 93*946379e7Schristos 94*946379e7SchristosEnvironment variables override the default commands: 95*946379e7Schristos CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96*946379e7Schristos" 97*946379e7Schristos 98*946379e7Schristoswhile test -n "$1"; do 99*946379e7Schristos case $1 in 100*946379e7Schristos -c) shift 101*946379e7Schristos continue;; 102*946379e7Schristos 103*946379e7Schristos -d) dir_arg=true 104*946379e7Schristos shift 105*946379e7Schristos continue;; 106*946379e7Schristos 107*946379e7Schristos -g) chgrpcmd="$chgrpprog $2" 108*946379e7Schristos shift 109*946379e7Schristos shift 110*946379e7Schristos continue;; 111*946379e7Schristos 112*946379e7Schristos --help) echo "$usage"; exit $?;; 113*946379e7Schristos 114*946379e7Schristos -m) chmodcmd="$chmodprog $2" 115*946379e7Schristos shift 116*946379e7Schristos shift 117*946379e7Schristos continue;; 118*946379e7Schristos 119*946379e7Schristos -o) chowncmd="$chownprog $2" 120*946379e7Schristos shift 121*946379e7Schristos shift 122*946379e7Schristos continue;; 123*946379e7Schristos 124*946379e7Schristos -s) stripcmd=$stripprog 125*946379e7Schristos shift 126*946379e7Schristos continue;; 127*946379e7Schristos 128*946379e7Schristos -t) dstarg=$2 129*946379e7Schristos shift 130*946379e7Schristos shift 131*946379e7Schristos continue;; 132*946379e7Schristos 133*946379e7Schristos -T) no_target_directory=true 134*946379e7Schristos shift 135*946379e7Schristos continue;; 136*946379e7Schristos 137*946379e7Schristos --version) echo "$0 $scriptversion"; exit $?;; 138*946379e7Schristos 139*946379e7Schristos *) # When -d is used, all remaining arguments are directories to create. 140*946379e7Schristos # When -t is used, the destination is already specified. 141*946379e7Schristos test -n "$dir_arg$dstarg" && break 142*946379e7Schristos # Otherwise, the last argument is the destination. Remove it from $@. 143*946379e7Schristos for arg 144*946379e7Schristos do 145*946379e7Schristos if test -n "$dstarg"; then 146*946379e7Schristos # $@ is not empty: it contains at least $arg. 147*946379e7Schristos set fnord "$@" "$dstarg" 148*946379e7Schristos shift # fnord 149*946379e7Schristos fi 150*946379e7Schristos shift # arg 151*946379e7Schristos dstarg=$arg 152*946379e7Schristos done 153*946379e7Schristos break;; 154*946379e7Schristos esac 155*946379e7Schristosdone 156*946379e7Schristos 157*946379e7Schristosif test -z "$1"; then 158*946379e7Schristos if test -z "$dir_arg"; then 159*946379e7Schristos echo "$0: no input file specified." >&2 160*946379e7Schristos exit 1 161*946379e7Schristos fi 162*946379e7Schristos # It's OK to call `install-sh -d' without argument. 163*946379e7Schristos # This can happen when creating conditional directories. 164*946379e7Schristos exit 0 165*946379e7Schristosfi 166*946379e7Schristos 167*946379e7Schristosfor src 168*946379e7Schristosdo 169*946379e7Schristos # Protect names starting with `-'. 170*946379e7Schristos case $src in 171*946379e7Schristos -*) src=./$src ;; 172*946379e7Schristos esac 173*946379e7Schristos 174*946379e7Schristos if test -n "$dir_arg"; then 175*946379e7Schristos dst=$src 176*946379e7Schristos src= 177*946379e7Schristos 178*946379e7Schristos if test -d "$dst"; then 179*946379e7Schristos mkdircmd=: 180*946379e7Schristos chmodcmd= 181*946379e7Schristos else 182*946379e7Schristos mkdircmd=$mkdirprog 183*946379e7Schristos fi 184*946379e7Schristos else 185*946379e7Schristos # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186*946379e7Schristos # might cause directories to be created, which would be especially bad 187*946379e7Schristos # if $src (and thus $dsttmp) contains '*'. 188*946379e7Schristos if test ! -f "$src" && test ! -d "$src"; then 189*946379e7Schristos echo "$0: $src does not exist." >&2 190*946379e7Schristos exit 1 191*946379e7Schristos fi 192*946379e7Schristos 193*946379e7Schristos if test -z "$dstarg"; then 194*946379e7Schristos echo "$0: no destination specified." >&2 195*946379e7Schristos exit 1 196*946379e7Schristos fi 197*946379e7Schristos 198*946379e7Schristos dst=$dstarg 199*946379e7Schristos # Protect names starting with `-'. 200*946379e7Schristos case $dst in 201*946379e7Schristos -*) dst=./$dst ;; 202*946379e7Schristos esac 203*946379e7Schristos 204*946379e7Schristos # If destination is a directory, append the input filename; won't work 205*946379e7Schristos # if double slashes aren't ignored. 206*946379e7Schristos if test -d "$dst"; then 207*946379e7Schristos if test -n "$no_target_directory"; then 208*946379e7Schristos echo "$0: $dstarg: Is a directory" >&2 209*946379e7Schristos exit 1 210*946379e7Schristos fi 211*946379e7Schristos dst=$dst/`basename "$src"` 212*946379e7Schristos fi 213*946379e7Schristos fi 214*946379e7Schristos 215*946379e7Schristos # This sed command emulates the dirname command. 216*946379e7Schristos dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217*946379e7Schristos 218*946379e7Schristos # Make sure that the destination directory exists. 219*946379e7Schristos 220*946379e7Schristos # Skip lots of stat calls in the usual case. 221*946379e7Schristos if test ! -d "$dstdir"; then 222*946379e7Schristos defaultIFS=' 223*946379e7Schristos ' 224*946379e7Schristos IFS="${IFS-$defaultIFS}" 225*946379e7Schristos 226*946379e7Schristos oIFS=$IFS 227*946379e7Schristos # Some sh's can't handle IFS=/ for some reason. 228*946379e7Schristos IFS='%' 229*946379e7Schristos set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230*946379e7Schristos shift 231*946379e7Schristos IFS=$oIFS 232*946379e7Schristos 233*946379e7Schristos pathcomp= 234*946379e7Schristos 235*946379e7Schristos while test $# -ne 0 ; do 236*946379e7Schristos pathcomp=$pathcomp$1 237*946379e7Schristos shift 238*946379e7Schristos if test ! -d "$pathcomp"; then 239*946379e7Schristos $mkdirprog "$pathcomp" 240*946379e7Schristos # mkdir can fail with a `File exist' error in case several 241*946379e7Schristos # install-sh are creating the directory concurrently. This 242*946379e7Schristos # is OK. 243*946379e7Schristos test -d "$pathcomp" || exit 244*946379e7Schristos fi 245*946379e7Schristos pathcomp=$pathcomp/ 246*946379e7Schristos done 247*946379e7Schristos fi 248*946379e7Schristos 249*946379e7Schristos if test -n "$dir_arg"; then 250*946379e7Schristos $doit $mkdircmd "$dst" \ 251*946379e7Schristos && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252*946379e7Schristos && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253*946379e7Schristos && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254*946379e7Schristos && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255*946379e7Schristos 256*946379e7Schristos else 257*946379e7Schristos dstfile=`basename "$dst"` 258*946379e7Schristos 259*946379e7Schristos # Make a couple of temp file names in the proper directory. 260*946379e7Schristos dsttmp=$dstdir/_inst.$$_ 261*946379e7Schristos rmtmp=$dstdir/_rm.$$_ 262*946379e7Schristos 263*946379e7Schristos # Trap to clean up those temp files at exit. 264*946379e7Schristos trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265*946379e7Schristos trap '(exit $?); exit' 1 2 13 15 266*946379e7Schristos 267*946379e7Schristos # Copy the file name to the temp name. 268*946379e7Schristos $doit $cpprog "$src" "$dsttmp" && 269*946379e7Schristos 270*946379e7Schristos # and set any options; do chmod last to preserve setuid bits. 271*946379e7Schristos # 272*946379e7Schristos # If any of these fail, we abort the whole thing. If we want to 273*946379e7Schristos # ignore errors from any of these, just make sure not to ignore 274*946379e7Schristos # errors from the above "$doit $cpprog $src $dsttmp" command. 275*946379e7Schristos # 276*946379e7Schristos { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277*946379e7Schristos && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278*946379e7Schristos && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279*946379e7Schristos && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280*946379e7Schristos 281*946379e7Schristos # Now rename the file to the real destination. 282*946379e7Schristos { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283*946379e7Schristos || { 284*946379e7Schristos # The rename failed, perhaps because mv can't rename something else 285*946379e7Schristos # to itself, or perhaps because mv is so ancient that it does not 286*946379e7Schristos # support -f. 287*946379e7Schristos 288*946379e7Schristos # Now remove or move aside any old file at destination location. 289*946379e7Schristos # We try this two ways since rm can't unlink itself on some 290*946379e7Schristos # systems and the destination file might be busy for other 291*946379e7Schristos # reasons. In this case, the final cleanup might fail but the new 292*946379e7Schristos # file should still install successfully. 293*946379e7Schristos { 294*946379e7Schristos if test -f "$dstdir/$dstfile"; then 295*946379e7Schristos $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296*946379e7Schristos || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297*946379e7Schristos || { 298*946379e7Schristos echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299*946379e7Schristos (exit 1); exit 1 300*946379e7Schristos } 301*946379e7Schristos else 302*946379e7Schristos : 303*946379e7Schristos fi 304*946379e7Schristos } && 305*946379e7Schristos 306*946379e7Schristos # Now rename the file to the real destination. 307*946379e7Schristos $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308*946379e7Schristos } 309*946379e7Schristos } 310*946379e7Schristos fi || { (exit 1); exit 1; } 311*946379e7Schristosdone 312*946379e7Schristos 313*946379e7Schristos# The final little trick to "correctly" pass the exit status to the exit trap. 314*946379e7Schristos{ 315*946379e7Schristos (exit 0); exit 0 316*946379e7Schristos} 317*946379e7Schristos 318*946379e7Schristos# Local variables: 319*946379e7Schristos# eval: (add-hook 'write-file-hooks 'time-stamp) 320*946379e7Schristos# time-stamp-start: "scriptversion=" 321*946379e7Schristos# time-stamp-format: "%:y-%02m-%02d.%02H" 322*946379e7Schristos# time-stamp-end: "$" 323*946379e7Schristos# End: 324