install-sh revision 145479
159243Sobrien#!/bin/sh 259243Sobrien# install - install a program, script, or datafile 3145479Smp 4145479Smpscriptversion=2004-12-17.09 5145479Smp 6145479Smp# This originates from X11R5 (mit/util/scripts/install.sh), which was 7145479Smp# later released in X11R6 (xc/config/util/install.sh) with the 8145479Smp# following copyright and license. 959243Sobrien# 10145479Smp# Copyright (C) 1994 X Consortium 1159243Sobrien# 12145479Smp# Permission is hereby granted, free of charge, to any person obtaining a copy 13145479Smp# of this software and associated documentation files (the "Software"), to 14145479Smp# deal in the Software without restriction, including without limitation the 15145479Smp# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16145479Smp# sell copies of the Software, and to permit persons to whom the Software is 17145479Smp# furnished to do so, subject to the following conditions: 1859243Sobrien# 19145479Smp# The above copyright notice and this permission notice shall be included in 20145479Smp# all copies or substantial portions of the Software. 21145479Smp# 22145479Smp# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23145479Smp# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24145479Smp# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25145479Smp# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26145479Smp# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27145479Smp# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28145479Smp# 29145479Smp# Except as contained in this notice, the name of the X Consortium shall not 30145479Smp# be used in advertising or otherwise to promote the sale, use or other deal- 31145479Smp# ings in this Software without prior written authorization from the X Consor- 32145479Smp# tium. 33145479Smp# 34145479Smp# 35145479Smp# FSF changes to this file are in the public domain. 36145479Smp# 3759243Sobrien# Calling this script install-sh is preferred over install.sh, to prevent 3859243Sobrien# `make' implicit rules from creating a file called install from it 3959243Sobrien# when there is no Makefile. 4059243Sobrien# 4159243Sobrien# This script is compatible with the BSD install script, but was written 4259243Sobrien# from scratch. It can only install one file at a time, a restriction 4359243Sobrien# shared with many OS's install programs. 4459243Sobrien 4559243Sobrien# set DOITPROG to echo to test this script 4659243Sobrien 4759243Sobrien# Don't use :- since 4.3BSD and earlier shells don't like it. 4859243Sobriendoit="${DOITPROG-}" 4959243Sobrien 5059243Sobrien# put in absolute paths if you don't have them in your path; or use env. vars. 5159243Sobrien 5259243Sobrienmvprog="${MVPROG-mv}" 5359243Sobriencpprog="${CPPROG-cp}" 5459243Sobrienchmodprog="${CHMODPROG-chmod}" 5559243Sobrienchownprog="${CHOWNPROG-chown}" 5659243Sobrienchgrpprog="${CHGRPPROG-chgrp}" 5759243Sobrienstripprog="${STRIPPROG-strip}" 5859243Sobrienrmprog="${RMPROG-rm}" 5959243Sobrienmkdirprog="${MKDIRPROG-mkdir}" 6059243Sobrien 6159243Sobrienchmodcmd="$chmodprog 0755" 62145479Smpchowncmd= 63145479Smpchgrpcmd= 64145479Smpstripcmd= 6559243Sobrienrmcmd="$rmprog -f" 6659243Sobrienmvcmd="$mvprog" 67145479Smpsrc= 68145479Smpdst= 69145479Smpdir_arg= 70145479Smpdstarg= 71145479Smpno_target_directory= 7259243Sobrien 73145479Smpusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74145479Smp or: $0 [OPTION]... SRCFILES... DIRECTORY 75145479Smp or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76145479Smp or: $0 [OPTION]... -d DIRECTORIES... 7759243Sobrien 78145479SmpIn the 1st form, copy SRCFILE to DSTFILE. 79145479SmpIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80145479SmpIn the 4th, create DIRECTORIES. 8159243Sobrien 82145479SmpOptions: 83145479Smp-c (ignored) 84145479Smp-d create directories instead of installing files. 85145479Smp-g GROUP $chgrpprog installed files to GROUP. 86145479Smp-m MODE $chmodprog installed files to MODE. 87145479Smp-o USER $chownprog installed files to USER. 88145479Smp-s $stripprog installed files. 89145479Smp-t DIRECTORY install into DIRECTORY. 90145479Smp-T report an error if DSTFILE is a directory. 91145479Smp--help display this help and exit. 92145479Smp--version display version info and exit. 9359243Sobrien 94145479SmpEnvironment variables override the default commands: 95145479Smp CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96145479Smp" 9759243Sobrien 98145479Smpwhile test -n "$1"; do 99145479Smp case $1 in 100145479Smp -c) shift 101145479Smp continue;; 10259243Sobrien 103145479Smp -d) dir_arg=true 104145479Smp shift 105145479Smp continue;; 10659243Sobrien 107145479Smp -g) chgrpcmd="$chgrpprog $2" 108145479Smp shift 109145479Smp shift 110145479Smp continue;; 11159243Sobrien 112145479Smp --help) echo "$usage"; exit 0;; 11359243Sobrien 114145479Smp -m) chmodcmd="$chmodprog $2" 115145479Smp shift 116145479Smp shift 117145479Smp continue;; 11859243Sobrien 119145479Smp -o) chowncmd="$chownprog $2" 120145479Smp shift 121145479Smp shift 122145479Smp continue;; 12359243Sobrien 124145479Smp -s) stripcmd=$stripprog 125145479Smp shift 126145479Smp continue;; 12759243Sobrien 128145479Smp -t) dstarg=$2 129145479Smp shift 130145479Smp shift 131145479Smp continue;; 13259243Sobrien 133145479Smp -T) no_target_directory=true 134145479Smp shift 135145479Smp continue;; 13659243Sobrien 137145479Smp --version) echo "$0 $scriptversion"; exit 0;; 13859243Sobrien 139145479Smp *) # When -d is used, all remaining arguments are directories to create. 140145479Smp # When -t is used, the destination is already specified. 141145479Smp test -n "$dir_arg$dstarg" && break 142145479Smp # Otherwise, the last argument is the destination. Remove it from $@. 143145479Smp for arg 144145479Smp do 145145479Smp if test -n "$dstarg"; then 146145479Smp # $@ is not empty: it contains at least $arg. 147145479Smp set fnord "$@" "$dstarg" 148145479Smp shift # fnord 149145479Smp fi 150145479Smp shift # arg 151145479Smp dstarg=$arg 152145479Smp done 153145479Smp break;; 154145479Smp esac 155145479Smpdone 156145479Smp 157145479Smpif test -z "$1"; then 158145479Smp if test -z "$dir_arg"; then 159145479Smp echo "$0: no input file specified." >&2 160145479Smp exit 1 161145479Smp fi 162145479Smp # It's OK to call `install-sh -d' without argument. 163145479Smp # This can happen when creating conditional directories. 164145479Smp exit 0 16559243Sobrienfi 16659243Sobrien 167145479Smpfor src 168145479Smpdo 169145479Smp # Protect names starting with `-'. 170145479Smp case $src in 171145479Smp -*) src=./$src ;; 172145479Smp esac 17359243Sobrien 174145479Smp if test -n "$dir_arg"; then 175145479Smp dst=$src 176145479Smp src= 17759243Sobrien 178145479Smp if test -d "$dst"; then 179145479Smp mkdircmd=: 180145479Smp chmodcmd= 181145479Smp else 182145479Smp mkdircmd=$mkdirprog 183145479Smp fi 184145479Smp else 185145479Smp # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186145479Smp # might cause directories to be created, which would be especially bad 187145479Smp # if $src (and thus $dsttmp) contains '*'. 188145479Smp if test ! -f "$src" && test ! -d "$src"; then 189145479Smp echo "$0: $src does not exist." >&2 190145479Smp exit 1 191145479Smp fi 19259243Sobrien 193145479Smp if test -z "$dstarg"; then 194145479Smp echo "$0: no destination specified." >&2 195145479Smp exit 1 196145479Smp fi 19759243Sobrien 198145479Smp dst=$dstarg 199145479Smp # Protect names starting with `-'. 200145479Smp case $dst in 201145479Smp -*) dst=./$dst ;; 202145479Smp esac 20359243Sobrien 204145479Smp # If destination is a directory, append the input filename; won't work 205145479Smp # if double slashes aren't ignored. 206145479Smp if test -d "$dst"; then 207145479Smp if test -n "$no_target_directory"; then 208145479Smp echo "$0: $dstarg: Is a directory" >&2 209145479Smp exit 1 210145479Smp fi 211145479Smp dst=$dst/`basename "$src"` 212145479Smp fi 213145479Smp fi 21459243Sobrien 215145479Smp # This sed command emulates the dirname command. 216145479Smp dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21759243Sobrien 218145479Smp # Make sure that the destination directory exists. 21959243Sobrien 220145479Smp # Skip lots of stat calls in the usual case. 221145479Smp if test ! -d "$dstdir"; then 222145479Smp defaultIFS=' 223145479Smp ' 224145479Smp IFS="${IFS-$defaultIFS}" 22559243Sobrien 226145479Smp oIFS=$IFS 227145479Smp # Some sh's can't handle IFS=/ for some reason. 228145479Smp IFS='%' 229145479Smp set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230145479Smp shift 231145479Smp IFS=$oIFS 23259243Sobrien 233145479Smp pathcomp= 23459243Sobrien 235145479Smp while test $# -ne 0 ; do 236145479Smp pathcomp=$pathcomp$1 237145479Smp shift 238145479Smp if test ! -d "$pathcomp"; then 239145479Smp $mkdirprog "$pathcomp" 240145479Smp # mkdir can fail with a `File exist' error in case several 241145479Smp # install-sh are creating the directory concurrently. This 242145479Smp # is OK. 243145479Smp test -d "$pathcomp" || exit 244145479Smp fi 245145479Smp pathcomp=$pathcomp/ 246145479Smp done 247145479Smp fi 24859243Sobrien 249145479Smp if test -n "$dir_arg"; then 250145479Smp $doit $mkdircmd "$dst" \ 251145479Smp && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252145479Smp && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253145479Smp && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254145479Smp && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25559243Sobrien 256145479Smp else 257145479Smp dstfile=`basename "$dst"` 25859243Sobrien 259145479Smp # Make a couple of temp file names in the proper directory. 260145479Smp dsttmp=$dstdir/_inst.$$_ 261145479Smp rmtmp=$dstdir/_rm.$$_ 26259243Sobrien 263145479Smp # Trap to clean up those temp files at exit. 264145479Smp trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265145479Smp trap '(exit $?); exit' 1 2 13 15 26659243Sobrien 267145479Smp # Copy the file name to the temp name. 268145479Smp $doit $cpprog "$src" "$dsttmp" && 26959243Sobrien 270145479Smp # and set any options; do chmod last to preserve setuid bits. 271145479Smp # 272145479Smp # If any of these fail, we abort the whole thing. If we want to 273145479Smp # ignore errors from any of these, just make sure not to ignore 274145479Smp # errors from the above "$doit $cpprog $src $dsttmp" command. 275145479Smp # 276145479Smp { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277145479Smp && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278145479Smp && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279145479Smp && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 28059243Sobrien 281145479Smp # Now rename the file to the real destination. 282145479Smp { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283145479Smp || { 284145479Smp # The rename failed, perhaps because mv can't rename something else 285145479Smp # to itself, or perhaps because mv is so ancient that it does not 286145479Smp # support -f. 28759243Sobrien 288145479Smp # Now remove or move aside any old file at destination location. 289145479Smp # We try this two ways since rm can't unlink itself on some 290145479Smp # systems and the destination file might be busy for other 291145479Smp # reasons. In this case, the final cleanup might fail but the new 292145479Smp # file should still install successfully. 293145479Smp { 294145479Smp if test -f "$dstdir/$dstfile"; then 295145479Smp $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296145479Smp || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297145479Smp || { 298145479Smp echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299145479Smp (exit 1); exit 1 300145479Smp } 301145479Smp else 302145479Smp : 303145479Smp fi 304145479Smp } && 30559243Sobrien 306145479Smp # Now rename the file to the real destination. 307145479Smp $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308145479Smp } 309145479Smp } 310145479Smp fi || { (exit 1); exit 1; } 311145479Smpdone 31259243Sobrien 313145479Smp# The final little trick to "correctly" pass the exit status to the exit trap. 314145479Smp{ 315145479Smp (exit 0); exit 0 316145479Smp} 31759243Sobrien 318145479Smp# Local variables: 319145479Smp# eval: (add-hook 'write-file-hooks 'time-stamp) 320145479Smp# time-stamp-start: "scriptversion=" 321145479Smp# time-stamp-format: "%:y-%02m-%02d.%02H" 322145479Smp# time-stamp-end: "$" 323145479Smp# End: 324