175a6cdb3SDavid E. O'Brien#!/bin/sh 275a6cdb3SDavid E. O'Brien# install - install a program, script, or datafile 3d1d50c78SDavid E. O'Brien 4d1d50c78SDavid E. O'Brienscriptversion=2005-05-14.22 5d1d50c78SDavid E. O'Brien 6d1d50c78SDavid E. O'Brien# This originates from X11R5 (mit/util/scripts/install.sh), which was 7d1d50c78SDavid E. O'Brien# later released in X11R6 (xc/config/util/install.sh) with the 8d1d50c78SDavid E. O'Brien# following copyright and license. 9a2e8fb4cSDavid E. O'Brien# 10d1d50c78SDavid E. O'Brien# Copyright (C) 1994 X Consortium 11a2e8fb4cSDavid E. O'Brien# 12d1d50c78SDavid E. O'Brien# Permission is hereby granted, free of charge, to any person obtaining a copy 13d1d50c78SDavid E. O'Brien# of this software and associated documentation files (the "Software"), to 14d1d50c78SDavid E. O'Brien# deal in the Software without restriction, including without limitation the 15d1d50c78SDavid E. O'Brien# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16d1d50c78SDavid E. O'Brien# sell copies of the Software, and to permit persons to whom the Software is 17d1d50c78SDavid E. O'Brien# furnished to do so, subject to the following conditions: 18d1d50c78SDavid E. O'Brien# 19d1d50c78SDavid E. O'Brien# The above copyright notice and this permission notice shall be included in 20d1d50c78SDavid E. O'Brien# all copies or substantial portions of the Software. 21d1d50c78SDavid E. O'Brien# 22d1d50c78SDavid E. O'Brien# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23d1d50c78SDavid E. O'Brien# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24d1d50c78SDavid E. O'Brien# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25d1d50c78SDavid E. O'Brien# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26d1d50c78SDavid E. O'Brien# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27d1d50c78SDavid E. O'Brien# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28d1d50c78SDavid E. O'Brien# 29d1d50c78SDavid E. O'Brien# Except as contained in this notice, the name of the X Consortium shall not 30d1d50c78SDavid E. O'Brien# be used in advertising or otherwise to promote the sale, use or other deal- 31d1d50c78SDavid E. O'Brien# ings in this Software without prior written authorization from the X Consor- 32d1d50c78SDavid E. O'Brien# tium. 33d1d50c78SDavid E. O'Brien# 34d1d50c78SDavid E. O'Brien# 35d1d50c78SDavid E. O'Brien# FSF changes to this file are in the public domain. 3675a6cdb3SDavid E. O'Brien# 3775a6cdb3SDavid E. O'Brien# Calling this script install-sh is preferred over install.sh, to prevent 3875a6cdb3SDavid E. O'Brien# `make' implicit rules from creating a file called install from it 3975a6cdb3SDavid E. O'Brien# when there is no Makefile. 4075a6cdb3SDavid E. O'Brien# 4175a6cdb3SDavid E. O'Brien# This script is compatible with the BSD install script, but was written 42a2e8fb4cSDavid E. O'Brien# from scratch. It can only install one file at a time, a restriction 43a2e8fb4cSDavid E. O'Brien# shared with many OS's install programs. 4475a6cdb3SDavid E. O'Brien 4575a6cdb3SDavid E. O'Brien# set DOITPROG to echo to test this script 4675a6cdb3SDavid E. O'Brien 4775a6cdb3SDavid E. O'Brien# Don't use :- since 4.3BSD and earlier shells don't like it. 4875a6cdb3SDavid E. O'Briendoit="${DOITPROG-}" 4975a6cdb3SDavid E. O'Brien 5075a6cdb3SDavid E. O'Brien# put in absolute paths if you don't have them in your path; or use env. vars. 5175a6cdb3SDavid E. O'Brien 5275a6cdb3SDavid E. O'Brienmvprog="${MVPROG-mv}" 5375a6cdb3SDavid E. O'Briencpprog="${CPPROG-cp}" 5475a6cdb3SDavid E. O'Brienchmodprog="${CHMODPROG-chmod}" 5575a6cdb3SDavid E. O'Brienchownprog="${CHOWNPROG-chown}" 5675a6cdb3SDavid E. O'Brienchgrpprog="${CHGRPPROG-chgrp}" 5775a6cdb3SDavid E. O'Brienstripprog="${STRIPPROG-strip}" 5875a6cdb3SDavid E. O'Brienrmprog="${RMPROG-rm}" 5975a6cdb3SDavid E. O'Brienmkdirprog="${MKDIRPROG-mkdir}" 6075a6cdb3SDavid E. O'Brien 6175a6cdb3SDavid E. O'Brienchmodcmd="$chmodprog 0755" 62d1d50c78SDavid E. O'Brienchowncmd= 63d1d50c78SDavid E. O'Brienchgrpcmd= 64d1d50c78SDavid E. O'Brienstripcmd= 6575a6cdb3SDavid E. O'Brienrmcmd="$rmprog -f" 6675a6cdb3SDavid E. O'Brienmvcmd="$mvprog" 67d1d50c78SDavid E. O'Briensrc= 68d1d50c78SDavid E. O'Briendst= 69d1d50c78SDavid E. O'Briendir_arg= 70d1d50c78SDavid E. O'Briendstarg= 71d1d50c78SDavid E. O'Brienno_target_directory= 7275a6cdb3SDavid E. O'Brien 73d1d50c78SDavid E. O'Brienusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74d1d50c78SDavid E. O'Brien or: $0 [OPTION]... SRCFILES... DIRECTORY 75d1d50c78SDavid E. O'Brien or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76d1d50c78SDavid E. O'Brien or: $0 [OPTION]... -d DIRECTORIES... 77d1d50c78SDavid E. O'Brien 78d1d50c78SDavid E. O'BrienIn the 1st form, copy SRCFILE to DSTFILE. 79d1d50c78SDavid E. O'BrienIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80d1d50c78SDavid E. O'BrienIn the 4th, create DIRECTORIES. 81d1d50c78SDavid E. O'Brien 82d1d50c78SDavid E. O'BrienOptions: 83d1d50c78SDavid E. O'Brien-c (ignored) 84d1d50c78SDavid E. O'Brien-d create directories instead of installing files. 85d1d50c78SDavid E. O'Brien-g GROUP $chgrpprog installed files to GROUP. 86d1d50c78SDavid E. O'Brien-m MODE $chmodprog installed files to MODE. 87d1d50c78SDavid E. O'Brien-o USER $chownprog installed files to USER. 88d1d50c78SDavid E. O'Brien-s $stripprog installed files. 89d1d50c78SDavid E. O'Brien-t DIRECTORY install into DIRECTORY. 90d1d50c78SDavid E. O'Brien-T report an error if DSTFILE is a directory. 91d1d50c78SDavid E. O'Brien--help display this help and exit. 92d1d50c78SDavid E. O'Brien--version display version info and exit. 93d1d50c78SDavid E. O'Brien 94d1d50c78SDavid E. O'BrienEnvironment variables override the default commands: 95d1d50c78SDavid E. O'Brien CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96d1d50c78SDavid E. O'Brien" 97d1d50c78SDavid E. O'Brien 98d1d50c78SDavid E. O'Brienwhile test -n "$1"; do 9975a6cdb3SDavid E. O'Brien case $1 in 100d1d50c78SDavid E. O'Brien -c) shift 10175a6cdb3SDavid E. O'Brien continue;; 10275a6cdb3SDavid E. O'Brien 10375a6cdb3SDavid E. O'Brien -d) dir_arg=true 10475a6cdb3SDavid E. O'Brien shift 10575a6cdb3SDavid E. O'Brien continue;; 10675a6cdb3SDavid E. O'Brien 107d1d50c78SDavid E. O'Brien -g) chgrpcmd="$chgrpprog $2" 108d1d50c78SDavid E. O'Brien shift 109d1d50c78SDavid E. O'Brien shift 110d1d50c78SDavid E. O'Brien continue;; 111d1d50c78SDavid E. O'Brien 112d1d50c78SDavid E. O'Brien --help) echo "$usage"; exit $?;; 113d1d50c78SDavid E. O'Brien 11475a6cdb3SDavid E. O'Brien -m) chmodcmd="$chmodprog $2" 11575a6cdb3SDavid E. O'Brien shift 11675a6cdb3SDavid E. O'Brien shift 11775a6cdb3SDavid E. O'Brien continue;; 11875a6cdb3SDavid E. O'Brien 11975a6cdb3SDavid E. O'Brien -o) chowncmd="$chownprog $2" 12075a6cdb3SDavid E. O'Brien shift 12175a6cdb3SDavid E. O'Brien shift 12275a6cdb3SDavid E. O'Brien continue;; 12375a6cdb3SDavid E. O'Brien 124d1d50c78SDavid E. O'Brien -s) stripcmd=$stripprog 125d1d50c78SDavid E. O'Brien shift 126d1d50c78SDavid E. O'Brien continue;; 127d1d50c78SDavid E. O'Brien 128d1d50c78SDavid E. O'Brien -t) dstarg=$2 12975a6cdb3SDavid E. O'Brien shift 13075a6cdb3SDavid E. O'Brien shift 13175a6cdb3SDavid E. O'Brien continue;; 13275a6cdb3SDavid E. O'Brien 133d1d50c78SDavid E. O'Brien -T) no_target_directory=true 13475a6cdb3SDavid E. O'Brien shift 13575a6cdb3SDavid E. O'Brien continue;; 13675a6cdb3SDavid E. O'Brien 137d1d50c78SDavid E. O'Brien --version) echo "$0 $scriptversion"; exit $?;; 13875a6cdb3SDavid E. O'Brien 139d1d50c78SDavid E. O'Brien *) # When -d is used, all remaining arguments are directories to create. 140d1d50c78SDavid E. O'Brien # When -t is used, the destination is already specified. 141d1d50c78SDavid E. O'Brien test -n "$dir_arg$dstarg" && break 142d1d50c78SDavid E. O'Brien # Otherwise, the last argument is the destination. Remove it from $@. 143d1d50c78SDavid E. O'Brien for arg 144d1d50c78SDavid E. O'Brien do 145d1d50c78SDavid E. O'Brien if test -n "$dstarg"; then 146d1d50c78SDavid E. O'Brien # $@ is not empty: it contains at least $arg. 147d1d50c78SDavid E. O'Brien set fnord "$@" "$dstarg" 148d1d50c78SDavid E. O'Brien shift # fnord 14975a6cdb3SDavid E. O'Brien fi 150d1d50c78SDavid E. O'Brien shift # arg 151d1d50c78SDavid E. O'Brien dstarg=$arg 152d1d50c78SDavid E. O'Brien done 153d1d50c78SDavid E. O'Brien break;; 15475a6cdb3SDavid E. O'Brien esac 15575a6cdb3SDavid E. O'Briendone 15675a6cdb3SDavid E. O'Brien 157d1d50c78SDavid E. O'Brienif test -z "$1"; then 158d1d50c78SDavid E. O'Brien if test -z "$dir_arg"; then 159d1d50c78SDavid E. O'Brien echo "$0: no input file specified." >&2 16075a6cdb3SDavid E. O'Brien exit 1 161d1d50c78SDavid E. O'Brien fi 162d1d50c78SDavid E. O'Brien # It's OK to call `install-sh -d' without argument. 163d1d50c78SDavid E. O'Brien # This can happen when creating conditional directories. 164d1d50c78SDavid E. O'Brien exit 0 16575a6cdb3SDavid E. O'Brienfi 16675a6cdb3SDavid E. O'Brien 167d1d50c78SDavid E. O'Brienfor src 168d1d50c78SDavid E. O'Briendo 169d1d50c78SDavid E. O'Brien # Protect names starting with `-'. 170d1d50c78SDavid E. O'Brien case $src in 171d1d50c78SDavid E. O'Brien -*) src=./$src ;; 172d1d50c78SDavid E. O'Brien esac 173d1d50c78SDavid E. O'Brien 174d1d50c78SDavid E. O'Brien if test -n "$dir_arg"; then 17575a6cdb3SDavid E. O'Brien dst=$src 176d1d50c78SDavid E. O'Brien src= 17775a6cdb3SDavid E. O'Brien 178d1d50c78SDavid E. O'Brien if test -d "$dst"; then 179d1d50c78SDavid E. O'Brien mkdircmd=: 180d1d50c78SDavid E. O'Brien chmodcmd= 18175a6cdb3SDavid E. O'Brien else 182d1d50c78SDavid E. O'Brien mkdircmd=$mkdirprog 18375a6cdb3SDavid E. O'Brien fi 18475a6cdb3SDavid E. O'Brien else 185d1d50c78SDavid E. O'Brien # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 18675a6cdb3SDavid E. O'Brien # might cause directories to be created, which would be especially bad 18775a6cdb3SDavid E. O'Brien # if $src (and thus $dsttmp) contains '*'. 188d1d50c78SDavid E. O'Brien if test ! -f "$src" && test ! -d "$src"; then 189d1d50c78SDavid E. O'Brien echo "$0: $src does not exist." >&2 19075a6cdb3SDavid E. O'Brien exit 1 19175a6cdb3SDavid E. O'Brien fi 19275a6cdb3SDavid E. O'Brien 193d1d50c78SDavid E. O'Brien if test -z "$dstarg"; then 194d1d50c78SDavid E. O'Brien echo "$0: no destination specified." >&2 19575a6cdb3SDavid E. O'Brien exit 1 19675a6cdb3SDavid E. O'Brien fi 19775a6cdb3SDavid E. O'Brien 198d1d50c78SDavid E. O'Brien dst=$dstarg 199d1d50c78SDavid E. O'Brien # Protect names starting with `-'. 200d1d50c78SDavid E. O'Brien case $dst in 201d1d50c78SDavid E. O'Brien -*) dst=./$dst ;; 202d1d50c78SDavid E. O'Brien esac 20375a6cdb3SDavid E. O'Brien 204d1d50c78SDavid E. O'Brien # If destination is a directory, append the input filename; won't work 205d1d50c78SDavid E. O'Brien # if double slashes aren't ignored. 206d1d50c78SDavid E. O'Brien if test -d "$dst"; then 207d1d50c78SDavid E. O'Brien if test -n "$no_target_directory"; then 208d1d50c78SDavid E. O'Brien echo "$0: $dstarg: Is a directory" >&2 209d1d50c78SDavid E. O'Brien exit 1 210d1d50c78SDavid E. O'Brien fi 211d1d50c78SDavid E. O'Brien dst=$dst/`basename "$src"` 21275a6cdb3SDavid E. O'Brien fi 21375a6cdb3SDavid E. O'Brien fi 21475a6cdb3SDavid E. O'Brien 215d1d50c78SDavid E. O'Brien # This sed command emulates the dirname command. 216d1d50c78SDavid E. O'Brien dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 21775a6cdb3SDavid E. O'Brien 21875a6cdb3SDavid E. O'Brien # Make sure that the destination directory exists. 21975a6cdb3SDavid E. O'Brien 22075a6cdb3SDavid E. O'Brien # Skip lots of stat calls in the usual case. 221d1d50c78SDavid E. O'Brien if test ! -d "$dstdir"; then 22275a6cdb3SDavid E. O'Brien defaultIFS=' 22375a6cdb3SDavid E. O'Brien ' 224d1d50c78SDavid E. O'Brien IFS="${IFS-$defaultIFS}" 22575a6cdb3SDavid E. O'Brien 226d1d50c78SDavid E. O'Brien oIFS=$IFS 22775a6cdb3SDavid E. O'Brien # Some sh's can't handle IFS=/ for some reason. 22875a6cdb3SDavid E. O'Brien IFS='%' 229d1d50c78SDavid E. O'Brien set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 23075a6cdb3SDavid E. O'Brien shift 231d1d50c78SDavid E. O'Brien IFS=$oIFS 23275a6cdb3SDavid E. O'Brien 233d1d50c78SDavid E. O'Brien pathcomp= 234d1d50c78SDavid E. O'Brien 235d1d50c78SDavid E. O'Brien while test $# -ne 0 ; do 236d1d50c78SDavid E. O'Brien pathcomp=$pathcomp$1 237d1d50c78SDavid E. O'Brien shift 238d1d50c78SDavid E. O'Brien if test ! -d "$pathcomp"; then 239d1d50c78SDavid E. O'Brien $mkdirprog "$pathcomp" 240d1d50c78SDavid E. O'Brien # mkdir can fail with a `File exist' error in case several 241d1d50c78SDavid E. O'Brien # install-sh are creating the directory concurrently. This 242d1d50c78SDavid E. O'Brien # is OK. 243d1d50c78SDavid E. O'Brien test -d "$pathcomp" || exit 24475a6cdb3SDavid E. O'Brien fi 245d1d50c78SDavid E. O'Brien pathcomp=$pathcomp/ 24675a6cdb3SDavid E. O'Brien done 24775a6cdb3SDavid E. O'Brien fi 24875a6cdb3SDavid E. O'Brien 249d1d50c78SDavid E. O'Brien if test -n "$dir_arg"; then 250d1d50c78SDavid E. O'Brien $doit $mkdircmd "$dst" \ 251d1d50c78SDavid E. O'Brien && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252d1d50c78SDavid E. O'Brien && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253d1d50c78SDavid E. O'Brien && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254d1d50c78SDavid E. O'Brien && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 25575a6cdb3SDavid E. O'Brien 25675a6cdb3SDavid E. O'Brien else 257d1d50c78SDavid E. O'Brien dstfile=`basename "$dst"` 25875a6cdb3SDavid E. O'Brien 259d1d50c78SDavid E. O'Brien # Make a couple of temp file names in the proper directory. 260d1d50c78SDavid E. O'Brien dsttmp=$dstdir/_inst.$$_ 261d1d50c78SDavid E. O'Brien rmtmp=$dstdir/_rm.$$_ 26275a6cdb3SDavid E. O'Brien 263d1d50c78SDavid E. O'Brien # Trap to clean up those temp files at exit. 264d1d50c78SDavid E. O'Brien trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265d1d50c78SDavid E. O'Brien trap '(exit $?); exit' 1 2 13 15 26675a6cdb3SDavid E. O'Brien 267d1d50c78SDavid E. O'Brien # Copy the file name to the temp name. 268d1d50c78SDavid E. O'Brien $doit $cpprog "$src" "$dsttmp" && 26975a6cdb3SDavid E. O'Brien 270d1d50c78SDavid E. O'Brien # and set any options; do chmod last to preserve setuid bits. 271d1d50c78SDavid E. O'Brien # 272d1d50c78SDavid E. O'Brien # If any of these fail, we abort the whole thing. If we want to 273d1d50c78SDavid E. O'Brien # ignore errors from any of these, just make sure not to ignore 274d1d50c78SDavid E. O'Brien # errors from the above "$doit $cpprog $src $dsttmp" command. 275d1d50c78SDavid E. O'Brien # 276d1d50c78SDavid E. O'Brien { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277d1d50c78SDavid E. O'Brien && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278d1d50c78SDavid E. O'Brien && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279d1d50c78SDavid E. O'Brien && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280d1d50c78SDavid E. O'Brien 281d1d50c78SDavid E. O'Brien # Now rename the file to the real destination. 282d1d50c78SDavid E. O'Brien { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283d1d50c78SDavid E. O'Brien || { 284d1d50c78SDavid E. O'Brien # The rename failed, perhaps because mv can't rename something else 285d1d50c78SDavid E. O'Brien # to itself, or perhaps because mv is so ancient that it does not 286d1d50c78SDavid E. O'Brien # support -f. 287d1d50c78SDavid E. O'Brien 288d1d50c78SDavid E. O'Brien # Now remove or move aside any old file at destination location. 289d1d50c78SDavid E. O'Brien # We try this two ways since rm can't unlink itself on some 290d1d50c78SDavid E. O'Brien # systems and the destination file might be busy for other 291d1d50c78SDavid E. O'Brien # reasons. In this case, the final cleanup might fail but the new 292d1d50c78SDavid E. O'Brien # file should still install successfully. 293d1d50c78SDavid E. O'Brien { 294d1d50c78SDavid E. O'Brien if test -f "$dstdir/$dstfile"; then 295d1d50c78SDavid E. O'Brien $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296d1d50c78SDavid E. O'Brien || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297d1d50c78SDavid E. O'Brien || { 298d1d50c78SDavid E. O'Brien echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299d1d50c78SDavid E. O'Brien (exit 1); exit 1 300d1d50c78SDavid E. O'Brien } 30175a6cdb3SDavid E. O'Brien else 302a2e8fb4cSDavid E. O'Brien : 30375a6cdb3SDavid E. O'Brien fi 304d1d50c78SDavid E. O'Brien } && 30575a6cdb3SDavid E. O'Brien 30675a6cdb3SDavid E. O'Brien # Now rename the file to the real destination. 307d1d50c78SDavid E. O'Brien $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308d1d50c78SDavid E. O'Brien } 309d1d50c78SDavid E. O'Brien } 310d1d50c78SDavid E. O'Brien fi || { (exit 1); exit 1; } 311d1d50c78SDavid E. O'Briendone 31275a6cdb3SDavid E. O'Brien 313d1d50c78SDavid E. O'Brien# The final little trick to "correctly" pass the exit status to the exit trap. 314d1d50c78SDavid E. O'Brien{ 315d1d50c78SDavid E. O'Brien (exit 0); exit 0 316d1d50c78SDavid E. O'Brien} 31775a6cdb3SDavid E. O'Brien 318d1d50c78SDavid E. O'Brien# Local variables: 319d1d50c78SDavid E. O'Brien# eval: (add-hook 'write-file-hooks 'time-stamp) 320d1d50c78SDavid E. O'Brien# time-stamp-start: "scriptversion=" 321d1d50c78SDavid E. O'Brien# time-stamp-format: "%:y-%02m-%02d.%02H" 322d1d50c78SDavid E. O'Brien# time-stamp-end: "$" 323d1d50c78SDavid E. O'Brien# End: 324