Home | History | Annotate | Download | only in scripts
      1 #!/bin/ksh
      2 #
      3 # CDDL HEADER START
      4 #
      5 # The contents of this file are subject to the terms of the
      6 # Common Development and Distribution License (the "License").
      7 # You may not use this file except in compliance with the License.
      8 #
      9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10 # or http://www.opensolaris.org/os/licensing.
     11 # See the License for the specific language governing permissions
     12 # and limitations under the License.
     13 #
     14 # When distributing Covered Code, include this CDDL HEADER in each
     15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16 # If applicable, add the following below this CDDL HEADER, with the
     17 # fields enclosed by brackets "[]" replaced with your own identifying
     18 # information: Portions Copyright [yyyy] [name of copyright owner]
     19 #
     20 # CDDL HEADER END
     21 #
     22 #
     23 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24 # Use is subject to license terms.
     25 #
     26 #From: "@(#)Install	1.56	96/10/11 SMI"
     27 #ident	"%Z%%M%	%I%	%E% SMI"
     28 #
     29 # Author:  Jeff Bonwick
     30 #
     31 #	Please report any bugs to bonwick@eng.
     32 #
     33 # How Install works:
     34 #
     35 #	Install performs the following steps:
     36 #
     37 #	1. Get the list of modules, configuration files, and links
     38 #	   that are desired.
     39 #
     40 #	2. Create the requested subset of /kernel in Install's temp space
     41 #	   (/tmp/Install.username by default.)
     42 #
     43 #	3. Create a tar file (/tmp/Install.username/Install.tar) based on (3).
     44 #
     45 #	4. If -n was specified, exit.  If a target was specified using -T,
     46 #	   rcp the tarfile to the target and exit.  If a target was specified
     47 #	   using -t, rsh to the target machine and untar the tarfile in the
     48 #	   target directory.
     49 #
     50 # If any of these steps fail, Install will give you an error message and,
     51 # in most cases, suggest corrective measures.  Then, you can recover the
     52 # install with "Install -R". (This is not required; it's just faster than
     53 # starting from scratch.)
     54 #
     55 # One final comment:  Unfortunately, tar and I disagree on what
     56 # constitutes a fatal error.  (tar -x will exit 0 even if it can't write
     57 # anything in the current directory.)  Thus, I am reduced to grepping stderr
     58 # for (what I consider) fatal and nonfatal error messages.  If you run into
     59 # a situation where this doesn't behave the way you think it should (either
     60 # an "Install failed" message after a successful install, or an "Install
     61 # complete" message after it bombs), please let me know.
     62 
     63 #
     64 # The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
     65 # under certain circumstances, which can really screw things up; unset it.
     66 #
     67 unset CDPATH
     68 
     69 INSTALL=`basename $0`
     70 DOT=`pwd`
     71 
     72 TRAILER="Install.$LOGNAME"
     73 INSTALL_STATE=${INSTALL_STATE-$HOME/.Install.state}
     74 export INSTALL_STATE
     75 INSTALL_DIR=${INSTALL_DIR-/tmp/$TRAILER}
     76 if [ "`basename $INSTALL_DIR`" != "$TRAILER" ]; then
     77 	INSTALL_DIR="$INSTALL_DIR/$TRAILER"
     78 fi
     79 export INSTALL_DIR
     80 INSTALL_LIB=${INSTALL_LIB-$HOME/LibInstall}
     81 export INSTALL_LIB
     82 INSTALL_RC=${INSTALL_RC-$HOME/.Installrc}
     83 export INSTALL_RC
     84 INSTALL_CP=${INSTALL_CP-"cp -p"}
     85 export INSTALL_CP
     86 INSTALL_RCP=${INSTALL_RCP-"rcp -p"}
     87 export INSTALL_RCP
     88 
     89 STATE=0
     90 
     91 DEFAULT_OPTIONS="-naq"
     92 GLOM=no
     93 GLOMNAME=kernel
     94 IMPL="default"
     95 WANT32="yes"
     96 WANT64="yes"
     97 
     98 modlist=/tmp/modlist$$
     99 # dummy directory for make state files.
    100 modstatedir=/tmp/modstate$$
    101 
    102 trap 'fail "User Interrupt" "You can resume by typing \"$INSTALL -R\""' 1 2 3 15
    103 
    104 usage() {
    105 	echo ""
    106 	echo $1
    107 	echo '
    108 Usage: Install	[ -w workspace ]
    109 		[ -s srcdir (default: usr/src/uts) ]
    110 		[ -k karch (e.g. sun4u; required if not deducible from pwd) ]
    111 		[ -t target (extract tar file on target, e.g. user@machine:/) ]
    112 		[ -T target (copy tar file to target, e.g. user@machine:/tmp) ]
    113 		[ -n (no target, just create tar file in /tmp (default)) ]
    114 		[ -u (install unix only) ]
    115 		[ -m (install modules only) ]
    116 		[ -a (install everything, i.e. unix + modules (default)) ]
    117 		[ -v (verbose output) ]
    118 		[ -V (REALLY verbose output) ]
    119 		[ -q (quiet (default)) ]
    120 		[ -c (clean up (remove temp files) when done (default) ]
    121 		[ -p (preserve temp files -- useful for debugging) ]
    122 		[ -L (library create: put tarfile in $INSTALL_LIB/env.karch) ]
    123 		[ -l lib (library extract: use $INSTALL_LIB/lib as source) ]
    124 		[ -D libdir (default: $HOME/LibInstall) ]
    125 		[ -d tempdir (Install work area (default: /tmp)) ]
    126 		[ -G glomname (put all files under platform/karch/glomname) ]
    127 		[ -i impl (e.g. sunfire; recommended with -G) ]
    128 		[ -x (update /etc/name_to_major et al) ]
    129 		[ -X (do not update /etc/name_to_major et al (default)) ]
    130 		[ -P (update /etc/path_to_inst -- generally not advisable) ]
    131 		[ -h (help -- prints this message) ]
    132 		[ -R (recover a previous Install) ]
    133 		[ -o objdir (object directory - either obj or debug (the default)) ]
    134 		[ -K (do not copy kmdb) ]
    135 		[ -3 32-bit modules only ]
    136 		[ -6 64-bit modules only ]
    137 		[ list of modules to install ]
    138 
    139 For full details:
    140 
    141 	man -M /ws/on297-gate/public/docs Install
    142 '
    143 	exit 1
    144 }
    145 
    146 #
    147 # Save the current state of Install
    148 #
    149 
    150 save_state() {
    151 	rm -f $INSTALL_STATE
    152 	(echo "# State of previous Install
    153 TARGET=$TARGET
    154 ENV_PATH=$ENV_PATH
    155 ENV_NAME=$ENV_NAME
    156 KARCH=$KARCH
    157 UTS=$UTS
    158 INSTALL_DIR=$INSTALL_DIR
    159 INSTALL_LIB=$INSTALL_LIB
    160 IMODE=$IMODE
    161 LIBCREATE=$LIBCREATE
    162 LIBSRC=$LIBSRC
    163 VERBOSE=$VERBOSE
    164 CLEANUP=$CLEANUP
    165 GLOM=$GLOM
    166 GLOMNAME=$GLOMNAME
    167 KMDB=$KMDB
    168 files='$files'
    169 STATE=$STATE" >$INSTALL_STATE) || verbose "Warning: cannot save state"
    170 }
    171 
    172 #
    173 # Restore the previous state of Install
    174 #
    175 
    176 restore_state() {
    177 	test -s $INSTALL_STATE || fail "Can't find $INSTALL_STATE"
    178 	eval "`cat $INSTALL_STATE`"
    179 }
    180 
    181 #
    182 # Install failed -- print error messages and exit 2
    183 #
    184 
    185 fail() {
    186 	save_state
    187 	#
    188 	# We might have gotten here via a trap.  So wait for any
    189 	# children (especially "make modlist") to exit before giving
    190 	# the error message or cleaning up.
    191 	#
    192 	wait
    193 	while [ $# -gt 0 ]
    194 	do
    195 		echo $1
    196 		shift
    197 	done
    198 	rm -rf $modstatedir
    199 	rm -f $modlist
    200 	echo "Install failed"
    201 	exit 2
    202 }
    203 
    204 #
    205 # Echo a string in verbose mode only
    206 #
    207 
    208 verbose() {
    209 	test "$VERBOSE" != "q" && echo $1
    210 }
    211 
    212 #
    213 # hack for tmpfs bug -- remove files gradually
    214 #
    215 
    216 remove_dir() {
    217 	test -d $1 || return
    218 	local_dot=`pwd`
    219 	cd $1
    220 	touch foo
    221 	rm -f `find . -type f -print`
    222 	cd $local_dot
    223 	rm -rf $1
    224 }
    225 
    226 #
    227 # Create a directory if it doesn't already exist.
    228 # mkdir will provide an error message, so don't provide an additional
    229 # message.
    230 #
    231 
    232 tstmkdir() {
    233 	[ -d $1 ] || mkdir -p $1 || fail
    234 }
    235 
    236 #
    237 # Patch up target directories for glommed kernel.
    238 # usage: fixglom listfile glomname
    239 #
    240 
    241 fixglom() {
    242 	nawk \
    243 	    -v glomname=$2 \
    244 	    -v karch=$KARCH ' 
    245 	$1 == "MOD" || $1 == "SYMLINK" {
    246 		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3)
    247 		sub(/^kernel/, "platform/" karch "/" glomname, $3)
    248 		sub(/^usr.kernel/, "platform/" karch "/" glomname, $3)
    249 		print
    250 	}
    251 	$1 == "LINK" {
    252 		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $2)
    253 		sub(/^kernel/, "platform/" karch "/" glomname, $2)
    254 		sub(/^usr.kernel/, "platform/" karch "/" glomname, $2)
    255 		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $4)
    256 		sub(/^kernel/, "platform/" karch "/" glomname, $4)
    257 		sub(/^usr.kernel/, "platform/" karch "/" glomname, $4)
    258 		print
    259 	}
    260 	$1 == "CONF" {
    261 		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $2)
    262 		sub(/^kernel/, "platform/" karch "/" glomname, $2)
    263 		sub(/^usr.kernel/, "platform/" karch "/" glomname, $2)
    264 		print
    265 	}
    266 	' $1 > $1.new
    267 	mv $1.new $1
    268 }
    269 
    270 #
    271 # Remove entries from 
    272 # usage: filtimpl listfile implname
    273 #
    274 
    275 filtimpl() {
    276 	nawk \
    277 	    -v impl=$2 '
    278 	$1 == "MOD" || $1 == "SYMLINK" {
    279 		if ($5 == "all" || $5 == impl)
    280 			print
    281 	}
    282 	$1 == "CONF" {
    283 		if ($4 == "all" || $4 == impl)
    284 			print
    285 	}
    286 	$1 == "LINK" {
    287 		if ($6 == "all" || $6 == impl)
    288 			print
    289 	}
    290 	' $1 > $1.new
    291 	mv $1.new $1
    292 }
    293 
    294 #
    295 # Filter the module list to match the user's request.
    296 # Usage: filtmod listfile modules
    297 #
    298 filtmod() {
    299 	nawk -v reqstring="$2" '
    300 	function modmatch(modname) {
    301 		if (reqstring == "All") {
    302 			return (1)
    303 		} else if (reqstring == "Modules") {
    304 			if (modname != "unix" && modname != "genunix")
    305 				return (1)
    306 		} else {
    307 			if (modname in reqmods)
    308 				return (1)
    309 		}
    310 		return (0)
    311 	}
    312 	BEGIN {
    313 		#
    314 		# The split call creates indexes 1, 2, 3, ...  We want
    315 		# the module names as indexes.
    316 		#
    317 		split(reqstring, tmpmods)
    318 		for (i in tmpmods)
    319 			reqmods[tmpmods[i]] = 1
    320 	}
    321 	$1 == "MOD" {
    322 		if (modmatch($2))
    323 			print
    324 	}
    325 	$1 == "CONF" {
    326 		if (modmatch($5))
    327 			print
    328 	}
    329 	$1 == "SYMLINK" {
    330 		if (modmatch($6))
    331 			print
    332 	}
    333 	$1 == "LINK" {
    334 		if (modmatch($3))
    335 			print
    336 	}
    337 	' $1 > $1.new
    338 	mv $1.new $1
    339 }
    340 
    341 #
    342 # Copy a module, or create a link, as needed.
    343 # See $SRC/uts/Makefile.targ ($(MODLIST_DEPS) target) for the format
    344 # of the different input lines.
    345 #
    346 
    347 copymod() {
    348 	case $1 in
    349 	MOD)
    350 		targdir=$INSTALL_FILES/$3
    351 		tstmkdir $targdir
    352 		target=$targdir/$2
    353 		verbose "$INSTALL_CP $6/${OBJD}$4/$2 $target"
    354 		$INSTALL_CP $6/${OBJD}$4/$2 $target || \
    355 		    fail "can't create $target"
    356 		;;
    357 	SYMLINK)
    358 		targdir=$INSTALL_FILES/$3
    359 		tstmkdir $targdir
    360 		target=$targdir/$4
    361 		rm -f $target
    362 		verbose "ln -s $2 $target"
    363 		ln -s $2 $target || fail "can't create $target"
    364 		;;
    365 	LINK)
    366 		targdir=$INSTALL_FILES/$4
    367 		tstmkdir $targdir
    368 		target=$targdir/$5
    369 		rm -f $target
    370 		verbose "ln $INSTALL_FILES/$2/$3 $target"
    371 		ln $INSTALL_FILES/$2/$3 $target || fail "can't create $target"
    372 		;;
    373 	CONF)
    374 		target=$INSTALL_FILES/$2
    375 		tstmkdir `dirname $target`
    376 		conffile=`basename $2`
    377 		verbose "$INSTALL_CP $3/$conffile $target"
    378 		$INSTALL_CP $3/$conffile $target
    379 		;;
    380 	*)
    381 		fail "unrecognized modlist entry: $*"
    382 		;;
    383 	esac
    384 }
    385 
    386 #
    387 # Copy kernel modules to $INSTALL_DIR
    388 #
    389 
    390 copy_kernel() {
    391 
    392 	case $KARCH in
    393 		sun4*)		ISA=sparc;	MACH=sparc	;;
    394 		i86*)		ISA=intel;	MACH=i386	;;
    395 		*)		fail "${KARCH}: invalid kernel architecture";;
    396 	esac
    397 	export MACH
    398 
    399 	if [ "$GLOM" = "no" ]; then
    400 		verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH"
    401 	else
    402 		verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH, impl = $IMPL"
    403 	fi
    404 
    405 	test -d $KARCH || fail "${KARCH}: invalid kernel architecture"
    406 	test -d $ISA || fail "${ISA}: invalid instruction set architecture"
    407 
    408 	tstmkdir $INSTALL_FILES
    409 	rm -rf $modstatedir
    410 	tstmkdir $modstatedir
    411 	export MODSTATE=$modstatedir/state
    412 
    413 	#
    414 	# Figure out which "make" to use.  dmake is faster than serial
    415 	# make, but dmake 7.3 has a bug that causes it to lose log
    416 	# output, which means the modlist might be incomplete.
    417 	#
    418 	make=dmake
    419 	dmvers=`$make -version`
    420 	if [ $? -ne 0 ]; then
    421 		make=/usr/ccs/bin/make
    422 	elif [[ $dmvers = *Distributed?Make?7.3* ]]; then
    423 		unset make
    424 		searchpath="/ws/onnv-tools/SUNWspro/SOS10/bin
    425 			/opt/SUNWspro/SOS10/bin
    426 			/opt/SUNWspro/bin"
    427 		for dmpath in $searchpath; do
    428 			verbose "Trying $dmpath/dmake"
    429 			if [ -x $dmpath/dmake ]; then
    430 				dmvers=`$dmpath/dmake -version`
    431 				if [[ $dmvers != *Distributed?Make?7.3* ]]; then
    432 					make="$dmpath/dmake"
    433 					break;
    434 				fi
    435 			fi
    436 		done
    437 		if [ -z $make ]; then
    438 			make=/usr/ccs/bin/make
    439 			echo "Warning: dmake 7.3 doesn't work with Install;" \
    440 				"using $make"
    441 		fi
    442 	fi
    443 
    444 	#
    445 	# Get a list of all modules, configuration files, and links
    446 	# that we might want to install.
    447 	#
    448 	verbose "Building module list..."
    449 	(cd $KARCH; MAKEFLAGS=e $make -K $MODSTATE modlist.karch) | \
    450 	    egrep "^MOD|^CONF|^LINK|^SYMLINK" > $modlist
    451 	[ $VERBOSE = "V" ] && cat $modlist
    452 	if [ "$GLOM" = "yes" ]; then
    453 		fixglom $modlist $GLOMNAME
    454 		filtimpl $modlist $IMPL
    455 	fi
    456 	if [[ -n "$files" && "$files" != All ]]; then
    457 		filtmod $modlist "$files"
    458 	fi
    459 
    460 	#
    461 	# Copy modules and create links.  For architectures with both
    462 	# 32- and 64-bit modules, we'll likely have duplicate
    463 	# configuration files, so do those after filtering out the
    464 	# duplicates.
    465 	#
    466 	verbose "Copying files to ${INSTALL_FILES}..."
    467 
    468 	#
    469 	# The IFS is reset to the newline character so we can buffer the
    470 	# output of grep without piping it directly to copymod, otherwise
    471 	# if fail() is called, then it will deadlock in fail()'s wait call
    472 	#
    473 	OIFS="$IFS"
    474 	IFS="
    475 	"
    476 	set -- `grep -v "^CONF" $modlist`;
    477 	IFS="$OIFS"
    478 	for onemod in "$@"; do
    479 		copymod $onemod
    480 	done
    481 	
    482 	OIFS="$IFS"
    483 	IFS="
    484 	"
    485 	set -- `grep "^CONF" $modlist | sort | uniq`;
    486 	IFS="$OIFS"
    487 	for onemod in "$@"; do
    488 		copymod $onemod
    489 	done
    490 
    491 	#
    492 	# Add the glommed kernel name to the root archive
    493 	#
    494 	if [[ $GLOM == "yes" ]];
    495 	then
    496 		filelist="$INSTALL_FILES/etc/boot/solaris/filelist.ramdisk"
    497 		mkdir -p `dirname $filelist`
    498 		echo "platform/$KARCH/$GLOMNAME" >$filelist
    499 	fi
    500 
    501 	STATE=1 # all kernel modules copied correctly
    502 	save_state
    503 }
    504 
    505 kmdb_copy() {
    506 	typeset src="$1"
    507 	typeset destdir="$2"
    508 
    509 	if [[ ! -d $dest ]] ; then
    510 		[[ $VERBOSE != "q" ]] && echo "mkdir -p $destdir"
    511 
    512 		mkdir -p $destdir || fail "failed to create $destdir"
    513 	fi
    514 
    515 	[[ $VERBOSE != "q" ]] && echo "cp $src $destdir"
    516 
    517 	cp $src $destdir || fail "failed to copy $src to $destdir"
    518 }
    519 
    520 kmdb_copy_machkmods() {
    521 	typeset modbase="$1"
    522 	typeset destdir="$2"
    523 	typeset dir=
    524 	typeset kmod=
    525 
    526 	[[ ! -d $modbase ]] && return
    527 
    528 	for dir in $(find $modbase -name kmod) ; do
    529 		set -- $(echo $dir |tr '/' ' ')
    530 
    531 		[[ $# -lt 2 ]] && fail "invalid mach kmod dir $dir"
    532 
    533 		shift $(($# - 2))
    534 		kmod=$1
    535 
    536 		[[ ! -f $dir/$kmod ]] && continue
    537 
    538 		kmdb_copy $dir/$kmod $destdir
    539 	done
    540 }
    541 
    542 kmdb_copy_karchkmods() {
    543 	typeset modbase="$1"
    544 	typeset destdir="$2"
    545 	typeset bitdir="$3"
    546 	typeset dir=
    547 	typeset kmod=
    548 	typeset karch=
    549 
    550 	[[ ! -d $modbase ]] && return
    551 
    552 	for dir in $(find $modbase -name kmod) ; do
    553 		set -- $(echo $dir | tr '/' ' ')
    554 
    555 		[[ $# -lt 3 ]] && fail "invalid karch kmod dir $dir"
    556 
    557 		shift $(($# - 3))
    558 		kmod=$1
    559 		bdir=$2
    560 
    561 		[[ $bdir != $bitdir ]] && continue
    562 		[[ ! -f $dir/$1 ]] && continue
    563 
    564 		kmdb_copy $dir/$kmod $destdir
    565 	done
    566 }
    567 
    568 kmdb_copy_kmdbmod() {
    569 	typeset kmdbpath="$1"
    570 	typeset destdir="$2"
    571 
    572 	[[ ! -f $kmdbpath ]] && return 1
    573 
    574 	kmdb_copy $kmdbpath $destdir
    575 
    576 	return 0
    577 }
    578 
    579 copy_kmdb() {
    580 	typeset kmdbtgtdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME/misc
    581 	typeset bitdirs=
    582 	typeset isadir=
    583 	typeset b64srcdir=
    584 	typeset b64tgtdir=
    585 	typeset b32srcdir=
    586 	typeset b32tgtdir=
    587 	typeset machdir=
    588 	typeset platdir=
    589 
    590 	if [[ $KMDB = "no" || ! -d $SRC/cmd/mdb ]] ; then
    591 		# The kmdb copy was suppressed or the workspace doesn't contain
    592 		# the mdb subtree.  Either way, there's nothing to do.
    593 		STATE=2
    594 		save_state
    595 		return
    596 	fi
    597 
    598 	if [[ $(mach) = "i386" ]] ; then
    599 		isadir="intel"
    600 		b64srcdir="amd64"
    601 		b64tgtdir="amd64"
    602 		b32srcdir="ia32"
    603 		b32tgtdir="."
    604 	else
    605 		isadir="sparc"
    606 		b64srcdir="v9"
    607 		b64tgtdir="sparcv9"
    608 		b32srcdir="v7"
    609 		b32tgtdir="."
    610 	fi
    611 
    612 	typeset foundkmdb=no
    613 	typeset kmdbpath=
    614 	typeset destdir=
    615 
    616 	platdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME
    617 	if [[ $GLOM = "yes" ]] ; then
    618 		machdir=$platdir
    619 	else
    620 		machdir=$INSTALL_FILES/kernel
    621 	fi
    622 
    623 	srctrees=$SRC
    624 	if [[ -d $SRC/../closed && "$CLOSED_IS_PRESENT" != no ]]; then
    625 		srctrees="$srctrees $SRC/../closed"
    626 	fi
    627 	if [[ $WANT64 = "yes" ]] ; then
    628 		# kmdbmod for sparc and x86 are built and installed
    629 		# in different places
    630 		if [[ $(mach) = "i386" ]] ; then
    631 			kmdbpath=$SRC/cmd/mdb/$isadir/$b64srcdir/kmdb/kmdbmod
    632 			destdir=$machdir/misc/$b64tgtdir
    633 		else
    634 			kmdbpath=$SRC/cmd/mdb/$KARCH/$b64srcdir/kmdb/kmdbmod
    635 			destdir=$platdir/misc/$b64tgtdir
    636 		fi
    637 
    638 		if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
    639 			foundkmdb="yes"
    640 
    641 			for tree in $srctrees; do
    642 				kmdb_copy_machkmods \
    643 				    $tree/cmd/mdb/$isadir/$b64srcdir \
    644 				    $machdir/kmdb/$b64tgtdir
    645 				kmdb_copy_karchkmods $tree/cmd/mdb/$KARCH \
    646 				    $platdir/kmdb/$b64tgtdir $b64srcdir
    647 			done
    648 		fi
    649 	fi
    650 
    651 	if [[ $WANT32 = "yes" ]] ; then
    652 		kmdbpath=$SRC/cmd/mdb/$isadir/$b32srcdir/kmdb/kmdbmod
    653 		destdir=$machdir/misc/$b32tgtdir
    654 
    655 		if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
    656 			foundkmdb="yes"
    657 
    658 			for tree in $srctrees; do
    659 				kmdb_copy_machkmods \
    660 				    $tree/cmd/mdb/$isadir/$b32srcdir \
    661 				    $machdir/kmdb/$b32tgtdir
    662 				kmdb_copy_karchkmods $tree/cmd/mdb/$KARCH \
    663 				    $platdir/kmdb/$b32tgtdir $b32srcdir
    664 			done
    665 		fi
    666 	fi
    667 
    668 	# A kmdb-less workspace isn't fatal, but it is potentially problematic,
    669 	# as the changes made to uts may have altered something upon which kmdb
    670 	# depends.  We will therefore remind the user that they haven't built it
    671 	# yet.
    672 	if [[ $foundkmdb != "yes" ]] ; then
    673 		echo "WARNING: kmdb isn't built, and won't be included"
    674 	fi
    675 
    676 	STATE=2
    677 	save_state
    678 	return
    679 }
    680 
    681 #
    682 # Make tarfile
    683 #
    684 
    685 make_tarfile() {
    686 	echo "Creating tarfile $TARFILE"
    687 	test -d $INSTALL_FILES || fail "Can't find $INSTALL_FILES"
    688 	cd $INSTALL_FILES
    689 	rm -f $TARFILE files
    690 
    691 	# We don't want to change the permissions or ownership of pre-existing
    692 	# directories on the target machine, so we're going to take care to
    693 	# avoid including directories in the tarfile.  On extraction, tar won't
    694 	# modify pre-existing directories, and will create non-existent ones as
    695 	# the user doing the extraction.
    696 	find . ! -type d -print |fgrep -vx './files' >files
    697 	tar cf $TARFILE -I files || fail "Couldn't create tarfile $TARFILE"
    698 	STATE=3
    699 }
    700 
    701 #
    702 # Routines to copy files to the target machine
    703 #
    704 
    705 remote_fail() {
    706 	fail "" "$1" "" \
    707 		"Make sure that $TARGET_MACHINE is up." \
    708 "Check .rhosts in the home directory of user $TARGET_USER on $TARGET_MACHINE." \
    709 		"Check /etc/hosts.equiv, /etc/passwd, and /etc/shadow." \
    710 		"Change permissions on $TARGET_MACHINE as necessary." \
    711 		"Then, use \"$INSTALL -R\" to resume the install." ""
    712 }
    713 
    714 remote_install() {
    715 	if [ "$IMODE" = "n" ]; then
    716 		STATE=4
    717 		return 0
    718 	fi
    719 	test -s $TARFILE || fail "$TARFILE missing or empty"
    720 	verbose "Installing system on $TARGET"
    721 	test -d $INSTALL_DIR || fail "Can't find $INSTALL_DIR"
    722 	cd $INSTALL_DIR
    723 	rm -f errors fatal nonfatal
    724 	if [ "$IMODE" = "T" ]; then
    725 		EMESG="Can't rcp to $TARGET"
    726 		touch errors
    727 		sh -e${SHV}c "$INSTALL_RCP $TARFILE $TARGET/Install.tar"
    728 	else
    729 		EMESG="Can't rsh to $TARGET_MACHINE"
    730 		rsh -l $TARGET_USER $TARGET_MACHINE \
    731 		    "(cd $TARGET_DIR; /usr/bin/tar x${V}f -)" \
    732 		    <$TARFILE 2>errors
    733 	fi
    734 	test $? -ne 0 && remote_fail "$EMESG"
    735 	cd $INSTALL_DIR
    736 	egrep "set time|warning|blocksize" errors >nonfatal
    737 	egrep -v "set time|warning|blocksize" errors >fatal
    738 	if [ -s fatal ]; then
    739 		echo "Fatal errors from rsh:"
    740 		cat fatal
    741 		remote_fail "Can't install on $TARGET_MACHINE"
    742 	fi
    743 	if [ -s nonfatal -a "$VERBOSE" != "q" ]; then
    744 		echo "Non-fatal errors from rsh:"
    745 		cat nonfatal
    746 	fi
    747 	rm -f fatal nonfatal errors
    748 	test "$IMODE" = "T" && echo "Files can be extracted on \
    749 $TARGET_MACHINE using 'tar xvf $TARGET_DIR/Install.tar'"
    750 	STATE=4
    751 }
    752 
    753 okexit() {
    754 	cd /tmp
    755 	test "$CLEANUP" = c && remove_dir $INSTALL_DIR
    756 	save_state
    757 	rm -rf $modstatedir
    758 	rm -f $modlist
    759 	verbose "Install complete"
    760 	exit 0
    761 }
    762 
    763 #
    764 # Process options
    765 #
    766 
    767 RCOPTS=""
    768 LIBCREATE="no"
    769 LIBSRC=""
    770 PFLAG=0
    771 ENV_PATH=$CODEMGR_WS
    772 OBJD="debug"
    773 KMDB="yes"
    774 
    775 test -s $INSTALL_RC && RCOPTS=`cat $INSTALL_RC`
    776 set $INSTALL $DEFAULT_OPTIONS $RCOPTS $*
    777 shift
    778 
    779 while getopts acd:D:G:hi:k:Kl:Lmno:pPqRs:t:T:uvVw:xX36 opt
    780 do
    781 	case $opt in
    782 	    w)	ENV_PATH="$OPTARG"; SRC="$ENV_PATH/usr/src";;
    783 	    s)	UTS="$OPTARG";;
    784 	    k)	KARCH="$OPTARG";;
    785 	  t|T)	TARGET="$OPTARG"; IMODE=$opt; CLEANUP="c";;
    786 	    n)	TARGET=""; IMODE="n"; CLEANUP="p";;
    787 	    u)	files="unix genunix";;
    788 	    m)	files="Modules";;
    789 	    a)	files="All";;
    790 	v|V|q)	VERBOSE=$opt;;
    791 	  c|p)	CLEANUP=$opt;;
    792 	    L)	LIBCREATE="yes"; CLEANUP="c";;
    793 	    l)	LIBSRC="$OPTARG";;
    794 	    D)	INSTALL_LIB="$OPTARG";;
    795 	    d)	INSTALL_DIR="$OPTARG/$TRAILER";;
    796 	    G)	GLOM=yes; GLOMNAME="$OPTARG";;
    797 	  X|x)	echo "-$opt is obsolete; ignored";;
    798 	    P)	PFLAG=1;;
    799 	    h)	usage "${INSTALL}: installs unix and modules";;
    800 	    R)	x=$OPTIND; restore_state; OPTIND=$x;;
    801 	    i)	IMPL="$OPTARG";;
    802 	    o)	OBJD="$OPTARG";;
    803 	    K)  KMDB="no";;
    804 	    3)  WANT64="no";;
    805 	    6)  WANT32="no";;
    806 	   \?)	usage "Illegal option";;
    807 	esac
    808 done
    809 shift `expr $OPTIND - 1`
    810 
    811 ENV_NAME=`basename $ENV_PATH`
    812 
    813 #
    814 # The rest of the command line is a list of individual files to copy.
    815 # If non-null, this list overrides the -uma options.
    816 #
    817 
    818 if [[ $# -gt 0 ]] ; then
    819 	files="$*"
    820 	KMDB="no"
    821 fi
    822 
    823 case $VERBOSE in
    824 	v)	V="v"; SHV="x";;
    825 	V)	V="v"; SHV="x"; set -x;;
    826 	q)	V=""; SHV="";;
    827 esac
    828 
    829 #
    830 # Create temp directory for Install's files
    831 #
    832 
    833 tstmkdir $INSTALL_DIR
    834 
    835 TARFILE=$INSTALL_DIR/Install.${KARCH}.tar
    836 INSTALL_FILES=$INSTALL_DIR/$KARCH
    837 
    838 #
    839 # Extract the target machine and target directory from a target of the
    840 # form [user@]machine:/dir .
    841 #
    842 
    843 if [ "$IMODE" != "n" ]; then
    844 	eval `echo $TARGET | nawk -F':' '{ 
    845 		if (NF != 2 || !length($1) || !length($2))
    846 			print "usage \"Invalid target\""
    847 		m = $1; d = $2
    848 		if ($1 ~ /@/) {
    849 		    k = split($1, f, "@");
    850 		    if (k != 2 || !length(f[1]) || !length (f[2]))
    851 			    print "usage \"Invalid target\""
    852 		    u = f[1]; m = f[2]
    853 		}
    854 		print "TARGET_USER=" u ";"
    855 		print "TARGET_MACHINE=" m ";"
    856 		print "TARGET_DIR=" d ";"
    857 	}'`
    858 	if [ -z "$TARGET_USER" ]; then
    859 		TARGET_USER=$LOGNAME
    860 	fi
    861 fi
    862 
    863 #
    864 # Allow the use of library source or target for the install
    865 #
    866 
    867 if [ -n "$LIBSRC" ]; then
    868 	LIBSRC="`basename $LIBSRC .tar`.tar"
    869 	TARFILE=$INSTALL_LIB/$LIBSRC
    870 	test -s $TARFILE || fail "Can't find tarfile $TARFILE"
    871 	verbose "Installing from library tarfile $TARFILE"
    872 	STATE=3
    873 elif [ "$LIBCREATE" = "yes" ]; then
    874 	tstmkdir $INSTALL_LIB
    875 	TARFILE="$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar"
    876 fi
    877 
    878 #
    879 # The next few lines allow recovery and activation with -R,
    880 # and library installs with -l.
    881 #
    882 
    883 [[ $STATE -eq 1 ]] && copy_kmdb
    884 [[ $STATE -eq 2 ]] && make_tarfile
    885 [[ $STATE -eq 3 ]] && remote_install
    886 [[ $STATE -eq 4 ]] && okexit
    887 
    888 save_state
    889 
    890 cd $DOT
    891 DOTDOT=`cd ..; pwd`
    892 
    893 #
    894 # Try to be smart: if DOTDOT ends in uts, then infer UTS and KARCH from DOT
    895 # Otherwise, if SRC is set, infer UTS = $SRC/uts.
    896 #
    897 
    898 if [ "`basename $DOTDOT`" = "uts" ]; then
    899 	UTS=$DOTDOT
    900 	KARCH=`basename $DOT`
    901 	if [ ! -n "$SRC" ]; then
    902 		SRC=`dirname $DOTDOT`
    903 		verbose "Setting SRC to $SRC"
    904 	fi
    905 	export SRC
    906 fi
    907 
    908 if [ -z "$UTS" -a -n "$SRC" ]; then
    909 	UTS="${SRC}/uts"
    910 	test -n "$KARCH" || fail "no karch specified (e.g. -k sun4u)"
    911 fi
    912 
    913 if [ "$LIBCREATE" = "yes" ]; then
    914 	TARFILE=$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar
    915 else
    916 	TARFILE=$INSTALL_DIR/Install.${KARCH}.tar
    917 fi
    918 INSTALL_FILES=$INSTALL_DIR/$KARCH
    919 save_state
    920 
    921 cd $DOT
    922 test -z "$UTS" && fail 'Cannot find kernel sources -- $SRC not set'
    923 test -d "$UTS" || fail "${UTS}: no such directory"
    924 
    925 #
    926 # Convert UTS into an absolute path.
    927 #
    928 
    929 cd $UTS
    930 UTS=`pwd`
    931 
    932 test "`basename $UTS`" = "uts" || \
    933 	verbose "Warning: source path $UTS doesn't end in 'uts'"
    934 
    935 remove_dir $INSTALL_DIR/$KARCH
    936 rm -f $TARFILE
    937 
    938 copy_kernel	# sets STATE=1 if successful
    939 copy_kmdb	# sets STATE=2 if successful
    940 make_tarfile	# sets STATE=3 if successful
    941 remote_install	# sets STATE=4 if successful
    942 
    943 okexit
    944