1*b1cdbd2cSJim Jagielski#!/bin/sh 2*b1cdbd2cSJim Jagielski# 3*b1cdbd2cSJim Jagielski# install - install a program, script, or datafile 4*b1cdbd2cSJim Jagielski# This comes from X11R5 (mit/util/scripts/install.sh). 5*b1cdbd2cSJim Jagielski# 6*b1cdbd2cSJim Jagielski# Copyright 1991 by the Massachusetts Institute of Technology 7*b1cdbd2cSJim Jagielski# 8*b1cdbd2cSJim Jagielski# Permission to use, copy, modify, distribute, and sell this software and its 9*b1cdbd2cSJim Jagielski# documentation for any purpose is hereby granted without fee, provided that 10*b1cdbd2cSJim Jagielski# the above copyright notice appear in all copies and that both that 11*b1cdbd2cSJim Jagielski# copyright notice and this permission notice appear in supporting 12*b1cdbd2cSJim Jagielski# documentation, and that the name of M.I.T. not be used in advertising or 13*b1cdbd2cSJim Jagielski# publicity pertaining to distribution of the software without specific, 14*b1cdbd2cSJim Jagielski# written prior permission. M.I.T. makes no representations about the 15*b1cdbd2cSJim Jagielski# suitability of this software for any purpose. It is provided "as is" 16*b1cdbd2cSJim Jagielski# without express or implied warranty. 17*b1cdbd2cSJim Jagielski# 18*b1cdbd2cSJim Jagielski# Calling this script install-sh is preferred over install.sh, to prevent 19*b1cdbd2cSJim Jagielski# `make' implicit rules from creating a file called install from it 20*b1cdbd2cSJim Jagielski# when there is no Makefile. 21*b1cdbd2cSJim Jagielski# 22*b1cdbd2cSJim Jagielski# This script is compatible with the BSD install script, but was written 23*b1cdbd2cSJim Jagielski# from scratch. It can only install one file at a time, a restriction 24*b1cdbd2cSJim Jagielski# shared with many OS's install programs. 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski# set DOITPROG to echo to test this script 28*b1cdbd2cSJim Jagielski 29*b1cdbd2cSJim Jagielski# Don't use :- since 4.3BSD and earlier shells don't like it. 30*b1cdbd2cSJim Jagielskidoit="${DOITPROG-}" 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielski 33*b1cdbd2cSJim Jagielski# put in absolute paths if you don't have them in your path; or use env. vars. 34*b1cdbd2cSJim Jagielski 35*b1cdbd2cSJim Jagielskimvprog="${MVPROG-mv}" 36*b1cdbd2cSJim Jagielskicpprog="${CPPROG-cp}" 37*b1cdbd2cSJim Jagielskichmodprog="${CHMODPROG-chmod}" 38*b1cdbd2cSJim Jagielskichownprog="${CHOWNPROG-chown}" 39*b1cdbd2cSJim Jagielskichgrpprog="${CHGRPPROG-chgrp}" 40*b1cdbd2cSJim Jagielskistripprog="${STRIPPROG-strip}" 41*b1cdbd2cSJim Jagielskirmprog="${RMPROG-rm}" 42*b1cdbd2cSJim Jagielskimkdirprog="${MKDIRPROG-mkdir}" 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielskitransformbasename="" 45*b1cdbd2cSJim Jagielskitransform_arg="" 46*b1cdbd2cSJim Jagielskiinstcmd="$mvprog" 47*b1cdbd2cSJim Jagielskichmodcmd="$chmodprog 0755" 48*b1cdbd2cSJim Jagielskichowncmd="" 49*b1cdbd2cSJim Jagielskichgrpcmd="" 50*b1cdbd2cSJim Jagielskistripcmd="" 51*b1cdbd2cSJim Jagielskirmcmd="$rmprog -f" 52*b1cdbd2cSJim Jagielskimvcmd="$mvprog" 53*b1cdbd2cSJim Jagielskisrc="" 54*b1cdbd2cSJim Jagielskidst="" 55*b1cdbd2cSJim Jagielskidir_arg="" 56*b1cdbd2cSJim Jagielski 57*b1cdbd2cSJim Jagielskiwhile [ x"$1" != x ]; do 58*b1cdbd2cSJim Jagielski case $1 in 59*b1cdbd2cSJim Jagielski -c) instcmd=$cpprog 60*b1cdbd2cSJim Jagielski shift 61*b1cdbd2cSJim Jagielski continue;; 62*b1cdbd2cSJim Jagielski 63*b1cdbd2cSJim Jagielski -d) dir_arg=true 64*b1cdbd2cSJim Jagielski shift 65*b1cdbd2cSJim Jagielski continue;; 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielski -m) chmodcmd="$chmodprog $2" 68*b1cdbd2cSJim Jagielski shift 69*b1cdbd2cSJim Jagielski shift 70*b1cdbd2cSJim Jagielski continue;; 71*b1cdbd2cSJim Jagielski 72*b1cdbd2cSJim Jagielski -o) chowncmd="$chownprog $2" 73*b1cdbd2cSJim Jagielski shift 74*b1cdbd2cSJim Jagielski shift 75*b1cdbd2cSJim Jagielski continue;; 76*b1cdbd2cSJim Jagielski 77*b1cdbd2cSJim Jagielski -g) chgrpcmd="$chgrpprog $2" 78*b1cdbd2cSJim Jagielski shift 79*b1cdbd2cSJim Jagielski shift 80*b1cdbd2cSJim Jagielski continue;; 81*b1cdbd2cSJim Jagielski 82*b1cdbd2cSJim Jagielski -s) stripcmd=$stripprog 83*b1cdbd2cSJim Jagielski shift 84*b1cdbd2cSJim Jagielski continue;; 85*b1cdbd2cSJim Jagielski 86*b1cdbd2cSJim Jagielski -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87*b1cdbd2cSJim Jagielski shift 88*b1cdbd2cSJim Jagielski continue;; 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91*b1cdbd2cSJim Jagielski shift 92*b1cdbd2cSJim Jagielski continue;; 93*b1cdbd2cSJim Jagielski 94*b1cdbd2cSJim Jagielski *) if [ x"$src" = x ] 95*b1cdbd2cSJim Jagielski then 96*b1cdbd2cSJim Jagielski src=$1 97*b1cdbd2cSJim Jagielski else 98*b1cdbd2cSJim Jagielski # this colon is to work around a 386BSD /bin/sh bug 99*b1cdbd2cSJim Jagielski : 100*b1cdbd2cSJim Jagielski dst=$1 101*b1cdbd2cSJim Jagielski fi 102*b1cdbd2cSJim Jagielski shift 103*b1cdbd2cSJim Jagielski continue;; 104*b1cdbd2cSJim Jagielski esac 105*b1cdbd2cSJim Jagielskidone 106*b1cdbd2cSJim Jagielski 107*b1cdbd2cSJim Jagielskiif [ x"$src" = x ] 108*b1cdbd2cSJim Jagielskithen 109*b1cdbd2cSJim Jagielski echo "$0: no input file specified" >&2 110*b1cdbd2cSJim Jagielski exit 1 111*b1cdbd2cSJim Jagielskielse 112*b1cdbd2cSJim Jagielski : 113*b1cdbd2cSJim Jagielskifi 114*b1cdbd2cSJim Jagielski 115*b1cdbd2cSJim Jagielskiif [ x"$dir_arg" != x ]; then 116*b1cdbd2cSJim Jagielski dst=$src 117*b1cdbd2cSJim Jagielski src="" 118*b1cdbd2cSJim Jagielski 119*b1cdbd2cSJim Jagielski if [ -d "$dst" ]; then 120*b1cdbd2cSJim Jagielski instcmd=: 121*b1cdbd2cSJim Jagielski chmodcmd="" 122*b1cdbd2cSJim Jagielski else 123*b1cdbd2cSJim Jagielski instcmd=$mkdirprog 124*b1cdbd2cSJim Jagielski fi 125*b1cdbd2cSJim Jagielskielse 126*b1cdbd2cSJim Jagielski 127*b1cdbd2cSJim Jagielski# Waiting for this to be detected by the "$instcmd $src $dsttmp" command 128*b1cdbd2cSJim Jagielski# might cause directories to be created, which would be especially bad 129*b1cdbd2cSJim Jagielski# if $src (and thus $dsttmp) contains '*'. 130*b1cdbd2cSJim Jagielski 131*b1cdbd2cSJim Jagielski if [ -f "$src" ] || [ -d "$src" ] 132*b1cdbd2cSJim Jagielski then 133*b1cdbd2cSJim Jagielski : 134*b1cdbd2cSJim Jagielski else 135*b1cdbd2cSJim Jagielski echo "$0: $src does not exist" >&2 136*b1cdbd2cSJim Jagielski exit 1 137*b1cdbd2cSJim Jagielski fi 138*b1cdbd2cSJim Jagielski 139*b1cdbd2cSJim Jagielski if [ x"$dst" = x ] 140*b1cdbd2cSJim Jagielski then 141*b1cdbd2cSJim Jagielski echo "$0: no destination specified" >&2 142*b1cdbd2cSJim Jagielski exit 1 143*b1cdbd2cSJim Jagielski else 144*b1cdbd2cSJim Jagielski : 145*b1cdbd2cSJim Jagielski fi 146*b1cdbd2cSJim Jagielski 147*b1cdbd2cSJim Jagielski# If destination is a directory, append the input filename; if your system 148*b1cdbd2cSJim Jagielski# does not like double slashes in filenames, you may need to add some logic 149*b1cdbd2cSJim Jagielski 150*b1cdbd2cSJim Jagielski if [ -d "$dst" ] 151*b1cdbd2cSJim Jagielski then 152*b1cdbd2cSJim Jagielski dst=$dst/`basename "$src"` 153*b1cdbd2cSJim Jagielski else 154*b1cdbd2cSJim Jagielski : 155*b1cdbd2cSJim Jagielski fi 156*b1cdbd2cSJim Jagielskifi 157*b1cdbd2cSJim Jagielski 158*b1cdbd2cSJim Jagielski## this sed command emulates the dirname command 159*b1cdbd2cSJim Jagielskidstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 160*b1cdbd2cSJim Jagielski 161*b1cdbd2cSJim Jagielski# Make sure that the destination directory exists. 162*b1cdbd2cSJim Jagielski# this part is taken from Noah Friedman's mkinstalldirs script 163*b1cdbd2cSJim Jagielski 164*b1cdbd2cSJim Jagielski# Skip lots of stat calls in the usual case. 165*b1cdbd2cSJim Jagielskiif [ ! -d "$dstdir" ]; then 166*b1cdbd2cSJim JagielskidefaultIFS=' 167*b1cdbd2cSJim Jagielski ' 168*b1cdbd2cSJim JagielskiIFS="${IFS-$defaultIFS}" 169*b1cdbd2cSJim Jagielski 170*b1cdbd2cSJim JagielskioIFS=$IFS 171*b1cdbd2cSJim Jagielski# Some sh's can't handle IFS=/ for some reason. 172*b1cdbd2cSJim JagielskiIFS='%' 173*b1cdbd2cSJim Jagielskiset - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 174*b1cdbd2cSJim JagielskiIFS=$oIFS 175*b1cdbd2cSJim Jagielski 176*b1cdbd2cSJim Jagielskipathcomp='' 177*b1cdbd2cSJim Jagielski 178*b1cdbd2cSJim Jagielskiwhile [ $# -ne 0 ] ; do 179*b1cdbd2cSJim Jagielski pathcomp=$pathcomp$1 180*b1cdbd2cSJim Jagielski shift 181*b1cdbd2cSJim Jagielski 182*b1cdbd2cSJim Jagielski if [ ! -d "$pathcomp" ] ; 183*b1cdbd2cSJim Jagielski then 184*b1cdbd2cSJim Jagielski $mkdirprog "$pathcomp" 185*b1cdbd2cSJim Jagielski else 186*b1cdbd2cSJim Jagielski : 187*b1cdbd2cSJim Jagielski fi 188*b1cdbd2cSJim Jagielski 189*b1cdbd2cSJim Jagielski pathcomp=$pathcomp/ 190*b1cdbd2cSJim Jagielskidone 191*b1cdbd2cSJim Jagielskifi 192*b1cdbd2cSJim Jagielski 193*b1cdbd2cSJim Jagielskiif [ x"$dir_arg" != x ] 194*b1cdbd2cSJim Jagielskithen 195*b1cdbd2cSJim Jagielski $doit $instcmd "$dst" && 196*b1cdbd2cSJim Jagielski 197*b1cdbd2cSJim Jagielski if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 198*b1cdbd2cSJim Jagielski if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 199*b1cdbd2cSJim Jagielski if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 200*b1cdbd2cSJim Jagielski if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 201*b1cdbd2cSJim Jagielskielse 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielski# If we're going to rename the final executable, determine the name now. 204*b1cdbd2cSJim Jagielski 205*b1cdbd2cSJim Jagielski if [ x"$transformarg" = x ] 206*b1cdbd2cSJim Jagielski then 207*b1cdbd2cSJim Jagielski dstfile=`basename "$dst"` 208*b1cdbd2cSJim Jagielski else 209*b1cdbd2cSJim Jagielski dstfile=`basename "$dst" $transformbasename | 210*b1cdbd2cSJim Jagielski sed $transformarg`$transformbasename 211*b1cdbd2cSJim Jagielski fi 212*b1cdbd2cSJim Jagielski 213*b1cdbd2cSJim Jagielski# don't allow the sed command to completely eliminate the filename 214*b1cdbd2cSJim Jagielski 215*b1cdbd2cSJim Jagielski if [ x"$dstfile" = x ] 216*b1cdbd2cSJim Jagielski then 217*b1cdbd2cSJim Jagielski dstfile=`basename "$dst"` 218*b1cdbd2cSJim Jagielski else 219*b1cdbd2cSJim Jagielski : 220*b1cdbd2cSJim Jagielski fi 221*b1cdbd2cSJim Jagielski 222*b1cdbd2cSJim Jagielski# Make a couple of temp file names in the proper directory. 223*b1cdbd2cSJim Jagielski 224*b1cdbd2cSJim Jagielski dsttmp=$dstdir/#inst.$$# 225*b1cdbd2cSJim Jagielski rmtmp=$dstdir/#rm.$$# 226*b1cdbd2cSJim Jagielski 227*b1cdbd2cSJim Jagielski# Trap to clean up temp files at exit. 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 230*b1cdbd2cSJim Jagielski trap '(exit $?); exit' 1 2 13 15 231*b1cdbd2cSJim Jagielski 232*b1cdbd2cSJim Jagielski# Move or copy the file name to the temp name 233*b1cdbd2cSJim Jagielski 234*b1cdbd2cSJim Jagielski $doit $instcmd "$src" "$dsttmp" && 235*b1cdbd2cSJim Jagielski 236*b1cdbd2cSJim Jagielski# and set any options; do chmod last to preserve setuid bits 237*b1cdbd2cSJim Jagielski 238*b1cdbd2cSJim Jagielski# If any of these fail, we abort the whole thing. If we want to 239*b1cdbd2cSJim Jagielski# ignore errors from any of these, just make sure not to ignore 240*b1cdbd2cSJim Jagielski# errors from the above "$doit $instcmd $src $dsttmp" command. 241*b1cdbd2cSJim Jagielski 242*b1cdbd2cSJim Jagielski if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 243*b1cdbd2cSJim Jagielski if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 244*b1cdbd2cSJim Jagielski if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 245*b1cdbd2cSJim Jagielski if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 246*b1cdbd2cSJim Jagielski 247*b1cdbd2cSJim Jagielski# Now remove or move aside any old file at destination location. We try this 248*b1cdbd2cSJim Jagielski# two ways since rm can't unlink itself on some systems and the destination 249*b1cdbd2cSJim Jagielski# file might be busy for other reasons. In this case, the final cleanup 250*b1cdbd2cSJim Jagielski# might fail but the new file should still install successfully. 251*b1cdbd2cSJim Jagielski 252*b1cdbd2cSJim Jagielski{ 253*b1cdbd2cSJim Jagielski if [ -f "$dstdir/$dstfile" ] 254*b1cdbd2cSJim Jagielski then 255*b1cdbd2cSJim Jagielski $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 256*b1cdbd2cSJim Jagielski $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 257*b1cdbd2cSJim Jagielski { 258*b1cdbd2cSJim Jagielski echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 259*b1cdbd2cSJim Jagielski (exit 1); exit 260*b1cdbd2cSJim Jagielski } 261*b1cdbd2cSJim Jagielski else 262*b1cdbd2cSJim Jagielski : 263*b1cdbd2cSJim Jagielski fi 264*b1cdbd2cSJim Jagielski} && 265*b1cdbd2cSJim Jagielski 266*b1cdbd2cSJim Jagielski# Now rename the file to the real destination. 267*b1cdbd2cSJim Jagielski 268*b1cdbd2cSJim Jagielski $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 269*b1cdbd2cSJim Jagielski 270*b1cdbd2cSJim Jagielskifi && 271*b1cdbd2cSJim Jagielski 272*b1cdbd2cSJim Jagielski# The final little trick to "correctly" pass the exit status to the exit trap. 273*b1cdbd2cSJim Jagielski 274*b1cdbd2cSJim Jagielski{ 275*b1cdbd2cSJim Jagielski (exit 0); exit 276*b1cdbd2cSJim Jagielski} 277