install-sh revision ed029a5f
1ed029a5fSmrg#!/bin/sh 2ed029a5fSmrg# 3ed029a5fSmrg# install - install a program, script, or datafile 4ed029a5fSmrg# 5ed029a5fSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 6ed029a5fSmrg# later released in X11R6 (xc/config/util/install.sh) with the 7ed029a5fSmrg# following copyright and license. 8ed029a5fSmrg# 9ed029a5fSmrg# Copyright (C) 1994 X Consortium 10ed029a5fSmrg# 11ed029a5fSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 12ed029a5fSmrg# of this software and associated documentation files (the "Software"), to 13ed029a5fSmrg# deal in the Software without restriction, including without limitation the 14ed029a5fSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15ed029a5fSmrg# sell copies of the Software, and to permit persons to whom the Software is 16ed029a5fSmrg# furnished to do so, subject to the following conditions: 17ed029a5fSmrg# 18ed029a5fSmrg# The above copyright notice and this permission notice shall be included in 19ed029a5fSmrg# all copies or substantial portions of the Software. 20ed029a5fSmrg# 21ed029a5fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22ed029a5fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23ed029a5fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24ed029a5fSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25ed029a5fSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 26ed029a5fSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27ed029a5fSmrg# 28ed029a5fSmrg# Except as contained in this notice, the name of the X Consortium shall not 29ed029a5fSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 30ed029a5fSmrg# ings in this Software without prior written authorization from the X Consor- 31ed029a5fSmrg# tium. 32ed029a5fSmrg# 33ed029a5fSmrg# 34ed029a5fSmrg# FSF changes to this file are in the public domain. 35ed029a5fSmrg# 36ed029a5fSmrg# Calling this script install-sh is preferred over install.sh, to prevent 37ed029a5fSmrg# `make' implicit rules from creating a file called install from it 38ed029a5fSmrg# when there is no Makefile. 39ed029a5fSmrg# 40ed029a5fSmrg# This script is compatible with the BSD install script, but was written 41ed029a5fSmrg# from scratch. It can only install one file at a time, a restriction 42ed029a5fSmrg# shared with many OS's install programs. 43ed029a5fSmrg 44ed029a5fSmrg 45ed029a5fSmrg# set DOITPROG to echo to test this script 46ed029a5fSmrg 47ed029a5fSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48ed029a5fSmrgdoit="${DOITPROG-}" 49ed029a5fSmrg 50ed029a5fSmrg 51ed029a5fSmrg# put in absolute paths if you don't have them in your path; or use env. vars. 52ed029a5fSmrg 53ed029a5fSmrgmvprog="${MVPROG-mv}" 54ed029a5fSmrgcpprog="${CPPROG-cp}" 55ed029a5fSmrgchmodprog="${CHMODPROG-chmod}" 56ed029a5fSmrgchownprog="${CHOWNPROG-chown}" 57ed029a5fSmrgchgrpprog="${CHGRPPROG-chgrp}" 58ed029a5fSmrgstripprog="${STRIPPROG-strip}" 59ed029a5fSmrgrmprog="${RMPROG-rm}" 60ed029a5fSmrgmkdirprog="${MKDIRPROG-mkdir}" 61ed029a5fSmrg 62ed029a5fSmrgtransformbasename="" 63ed029a5fSmrgtransform_arg="" 64ed029a5fSmrginstcmd="$mvprog" 65ed029a5fSmrgchmodcmd="$chmodprog 0755" 66ed029a5fSmrgchowncmd="" 67ed029a5fSmrgchgrpcmd="" 68ed029a5fSmrgstripcmd="" 69ed029a5fSmrgrmcmd="$rmprog -f" 70ed029a5fSmrgmvcmd="$mvprog" 71ed029a5fSmrgsrc="" 72ed029a5fSmrgdst="" 73ed029a5fSmrgdir_arg="" 74ed029a5fSmrg 75ed029a5fSmrgwhile [ x"$1" != x ]; do 76ed029a5fSmrg case $1 in 77ed029a5fSmrg -c) instcmd=$cpprog 78ed029a5fSmrg shift 79ed029a5fSmrg continue;; 80ed029a5fSmrg 81ed029a5fSmrg -d) dir_arg=true 82ed029a5fSmrg shift 83ed029a5fSmrg continue;; 84ed029a5fSmrg 85ed029a5fSmrg -m) chmodcmd="$chmodprog $2" 86ed029a5fSmrg shift 87ed029a5fSmrg shift 88ed029a5fSmrg continue;; 89ed029a5fSmrg 90ed029a5fSmrg -o) chowncmd="$chownprog $2" 91ed029a5fSmrg shift 92ed029a5fSmrg shift 93ed029a5fSmrg continue;; 94ed029a5fSmrg 95ed029a5fSmrg -g) chgrpcmd="$chgrpprog $2" 96ed029a5fSmrg shift 97ed029a5fSmrg shift 98ed029a5fSmrg continue;; 99ed029a5fSmrg 100ed029a5fSmrg -s) stripcmd=$stripprog 101ed029a5fSmrg shift 102ed029a5fSmrg continue;; 103ed029a5fSmrg 104ed029a5fSmrg -t=*) transformarg=`echo $1 | sed 's/-t=//'` 105ed029a5fSmrg shift 106ed029a5fSmrg continue;; 107ed029a5fSmrg 108ed029a5fSmrg -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 109ed029a5fSmrg shift 110ed029a5fSmrg continue;; 111ed029a5fSmrg 112ed029a5fSmrg *) if [ x"$src" = x ] 113ed029a5fSmrg then 114ed029a5fSmrg src=$1 115ed029a5fSmrg else 116ed029a5fSmrg # this colon is to work around a 386BSD /bin/sh bug 117ed029a5fSmrg : 118ed029a5fSmrg dst=$1 119ed029a5fSmrg fi 120ed029a5fSmrg shift 121ed029a5fSmrg continue;; 122ed029a5fSmrg esac 123ed029a5fSmrgdone 124ed029a5fSmrg 125ed029a5fSmrgif [ x"$src" = x ] 126ed029a5fSmrgthen 127ed029a5fSmrg echo "$0: no input file specified" >&2 128ed029a5fSmrg exit 1 129ed029a5fSmrgelse 130ed029a5fSmrg : 131ed029a5fSmrgfi 132ed029a5fSmrg 133ed029a5fSmrgif [ x"$dir_arg" != x ]; then 134ed029a5fSmrg dst=$src 135ed029a5fSmrg src="" 136ed029a5fSmrg 137ed029a5fSmrg if [ -d "$dst" ]; then 138ed029a5fSmrg instcmd=: 139ed029a5fSmrg chmodcmd="" 140ed029a5fSmrg else 141ed029a5fSmrg instcmd=$mkdirprog 142ed029a5fSmrg fi 143ed029a5fSmrgelse 144ed029a5fSmrg 145ed029a5fSmrg# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 146ed029a5fSmrg# might cause directories to be created, which would be especially bad 147ed029a5fSmrg# if $src (and thus $dsttmp) contains '*'. 148ed029a5fSmrg 149ed029a5fSmrg if [ -f "$src" ] || [ -d "$src" ] 150ed029a5fSmrg then 151ed029a5fSmrg : 152ed029a5fSmrg else 153ed029a5fSmrg echo "$0: $src does not exist" >&2 154ed029a5fSmrg exit 1 155ed029a5fSmrg fi 156ed029a5fSmrg 157ed029a5fSmrg if [ x"$dst" = x ] 158ed029a5fSmrg then 159ed029a5fSmrg echo "$0: no destination specified" >&2 160ed029a5fSmrg exit 1 161ed029a5fSmrg else 162ed029a5fSmrg : 163ed029a5fSmrg fi 164ed029a5fSmrg 165ed029a5fSmrg# If destination is a directory, append the input filename; if your system 166ed029a5fSmrg# does not like double slashes in filenames, you may need to add some logic 167ed029a5fSmrg 168ed029a5fSmrg if [ -d "$dst" ] 169ed029a5fSmrg then 170ed029a5fSmrg dst=$dst/`basename "$src"` 171ed029a5fSmrg else 172ed029a5fSmrg : 173ed029a5fSmrg fi 174ed029a5fSmrgfi 175ed029a5fSmrg 176ed029a5fSmrg## this sed command emulates the dirname command 177ed029a5fSmrgdstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 178ed029a5fSmrg 179ed029a5fSmrg# Make sure that the destination directory exists. 180ed029a5fSmrg# this part is taken from Noah Friedman's mkinstalldirs script 181ed029a5fSmrg 182ed029a5fSmrg# Skip lots of stat calls in the usual case. 183ed029a5fSmrgif [ ! -d "$dstdir" ]; then 184ed029a5fSmrgdefaultIFS=' 185ed029a5fSmrg ' 186ed029a5fSmrgIFS="${IFS-$defaultIFS}" 187ed029a5fSmrg 188ed029a5fSmrgoIFS=$IFS 189ed029a5fSmrg# Some sh's can't handle IFS=/ for some reason. 190ed029a5fSmrgIFS='%' 191ed029a5fSmrgset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 192ed029a5fSmrgIFS=$oIFS 193ed029a5fSmrg 194ed029a5fSmrgpathcomp='' 195ed029a5fSmrg 196ed029a5fSmrgwhile [ $# -ne 0 ] ; do 197ed029a5fSmrg pathcomp=$pathcomp$1 198ed029a5fSmrg shift 199ed029a5fSmrg 200ed029a5fSmrg if [ ! -d "$pathcomp" ] ; 201ed029a5fSmrg then 202ed029a5fSmrg $mkdirprog "$pathcomp" 203ed029a5fSmrg else 204ed029a5fSmrg : 205ed029a5fSmrg fi 206ed029a5fSmrg 207ed029a5fSmrg pathcomp=$pathcomp/ 208ed029a5fSmrgdone 209ed029a5fSmrgfi 210ed029a5fSmrg 211ed029a5fSmrgif [ x"$dir_arg" != x ] 212ed029a5fSmrgthen 213ed029a5fSmrg $doit $instcmd "$dst" && 214ed029a5fSmrg 215ed029a5fSmrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 216ed029a5fSmrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 217ed029a5fSmrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 218ed029a5fSmrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 219ed029a5fSmrgelse 220ed029a5fSmrg 221ed029a5fSmrg# If we're going to rename the final executable, determine the name now. 222ed029a5fSmrg 223ed029a5fSmrg if [ x"$transformarg" = x ] 224ed029a5fSmrg then 225ed029a5fSmrg dstfile=`basename "$dst"` 226ed029a5fSmrg else 227ed029a5fSmrg dstfile=`basename "$dst" $transformbasename | 228ed029a5fSmrg sed $transformarg`$transformbasename 229ed029a5fSmrg fi 230ed029a5fSmrg 231ed029a5fSmrg# don't allow the sed command to completely eliminate the filename 232ed029a5fSmrg 233ed029a5fSmrg if [ x"$dstfile" = x ] 234ed029a5fSmrg then 235ed029a5fSmrg dstfile=`basename "$dst"` 236ed029a5fSmrg else 237ed029a5fSmrg : 238ed029a5fSmrg fi 239ed029a5fSmrg 240ed029a5fSmrg# Make a couple of temp file names in the proper directory. 241ed029a5fSmrg 242ed029a5fSmrg dsttmp=$dstdir/_inst.$$_ 243ed029a5fSmrg rmtmp=$dstdir/_rm.$$_ 244ed029a5fSmrg 245ed029a5fSmrg# Trap to clean up temp files at exit. 246ed029a5fSmrg 247ed029a5fSmrg trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 248ed029a5fSmrg trap '(exit $?); exit' 1 2 13 15 249ed029a5fSmrg 250ed029a5fSmrg# Move or copy the file name to the temp name 251ed029a5fSmrg 252ed029a5fSmrg $doit $instcmd "$src" "$dsttmp" && 253ed029a5fSmrg 254ed029a5fSmrg# and set any options; do chmod last to preserve setuid bits 255ed029a5fSmrg 256ed029a5fSmrg# If any of these fail, we abort the whole thing. If we want to 257ed029a5fSmrg# ignore errors from any of these, just make sure not to ignore 258ed029a5fSmrg# errors from the above "$doit $instcmd $src $dsttmp" command. 259ed029a5fSmrg 260ed029a5fSmrg if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 261ed029a5fSmrg if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 262ed029a5fSmrg if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 263ed029a5fSmrg if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 264ed029a5fSmrg 265ed029a5fSmrg# Now remove or move aside any old file at destination location. We try this 266ed029a5fSmrg# two ways since rm can't unlink itself on some systems and the destination 267ed029a5fSmrg# file might be busy for other reasons. In this case, the final cleanup 268ed029a5fSmrg# might fail but the new file should still install successfully. 269ed029a5fSmrg 270ed029a5fSmrg{ 271ed029a5fSmrg if [ -f "$dstdir/$dstfile" ] 272ed029a5fSmrg then 273ed029a5fSmrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 274ed029a5fSmrg $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 275ed029a5fSmrg { 276ed029a5fSmrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 277ed029a5fSmrg (exit 1); exit 278ed029a5fSmrg } 279ed029a5fSmrg else 280ed029a5fSmrg : 281ed029a5fSmrg fi 282ed029a5fSmrg} && 283ed029a5fSmrg 284ed029a5fSmrg# Now rename the file to the real destination. 285ed029a5fSmrg 286ed029a5fSmrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 287ed029a5fSmrg 288ed029a5fSmrgfi && 289ed029a5fSmrg 290ed029a5fSmrg# The final little trick to "correctly" pass the exit status to the exit trap. 291ed029a5fSmrg 292ed029a5fSmrg{ 293ed029a5fSmrg (exit 0); exit 294ed029a5fSmrg} 295