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