xref: /titanic_44/usr/src/tools/scripts/Install.sh (revision 4bc0a2ef2b7ba50a7a717e7ddbf31472ad28e358)
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, Version 1.0 only
7# (the "License").  You may not use this file except in compliance
8# with the License.
9#
10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11# or http://www.opensolaris.org/os/licensing.
12# See the License for the specific language governing permissions
13# and limitations under the License.
14#
15# When distributing Covered Code, include this CDDL HEADER in each
16# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17# If applicable, add the following below this CDDL HEADER, with the
18# fields enclosed by brackets "[]" replaced with your own identifying
19# information: Portions Copyright [yyyy] [name of copyright owner]
20#
21# CDDL HEADER END
22#
23#
24# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27#From: "@(#)Install	1.56	96/10/11 SMI"
28#ident	"%Z%%M%	%I%	%E% SMI"
29#
30# Author:  Jeff Bonwick
31#
32#	Please report any bugs to bonwick@eng.
33#
34# How Install works:
35#
36#	Install performs the following steps:
37#
38#	1. Figure out how to construct /kernel by looking at Makefile.uts,
39#	   Makefile.$ISA (sparc default), Makefile.$KARCH and the Makefiles
40#	   in the module directories (uts/arch/*/Makefile).
41#
42#	2. Create the requested subset of /kernel in Install's temp space
43#	   (/tmp/Install.username by default.)
44#
45#	3. Create a tar file (/tmp/Install.username/Install.tar) based on (3).
46#
47#	4. If -n was specified, exit.  If a target was specified using -T,
48#	   rcp the tarfile to the target and exit.  If a target was specified
49#	   using -t, rsh to the target machine and untar the tarfile in the
50#	   target directory.
51#
52# If any of these steps fail, Install will give you an error message and,
53# in most cases, suggest corrective measures.  Then, you can recover the
54# install with "Install -R". (This is not required; it's just faster than
55# starting from scratch.)
56#
57# One final comment:  Unfortunately, tar and I disagree on what
58# constitutes a fatal error.  (tar -x will exit 0 even if it can't write
59# anything in the current directory.)  Thus, I am reduced to grepping stderr
60# for (what I consider) fatal and nonfatal error messages.  If you run into
61# a situation where this doesn't behave the way you think it should (either
62# an "Install failed" message after a successful install, or an "Install
63# complete" message after it bombs), please let me know.
64
65#
66# The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
67# under certain circumstances, which can really screw things up; unset it.
68#
69unset CDPATH
70
71INSTALL=`basename $0`
72DOT=`pwd`
73
74TRAILER="Install.$LOGNAME"
75INSTALL_STATE=${INSTALL_STATE-$HOME/.Install.state}
76export INSTALL_STATE
77INSTALL_DIR=${INSTALL_DIR-/tmp/$TRAILER}
78if [ "`basename $INSTALL_DIR`" != "$TRAILER" ]; then
79	INSTALL_DIR="$INSTALL_DIR/$TRAILER"
80fi
81export INSTALL_DIR
82INSTALL_LIB=${INSTALL_LIB-$HOME/LibInstall}
83export INSTALL_LIB
84INSTALL_RC=${INSTALL_RC-$HOME/.Installrc}
85export INSTALL_RC
86INSTALL_CP=${INSTALL_CP-"cp -p"}
87export INSTALL_CP
88INSTALL_RCP=${INSTALL_RCP-"rcp -p"}
89export INSTALL_RCP
90
91STATE=0
92
93DEFAULT_OPTIONS="-naqX"
94GLOM=no
95GLOMNAME=kernel
96IMPL="default"
97WANT32="yes"
98WANT64="yes"
99
100trap 'fail "User Interrupt" "You can resume by typing \"$INSTALL -R\""' 1 2 3 15
101
102usage() {
103	echo ""
104	echo $1
105	echo '
106Usage: Install	[ -w workspace ]
107		[ -s srcdir (default: usr/src/uts) ]
108		[ -k karch (e.g. sun4u; required if not deducible from pwd) ]
109		[ -t target (extract tar file on target, e.g. user@machine:/) ]
110		[ -T target (copy tar file to target, e.g. user@machine:/tmp) ]
111		[ -n (no target, just create tar file in /tmp (default)) ]
112		[ -u (install unix only) ]
113		[ -m (install modules only) ]
114		[ -a (install everything, i.e. unix + modules (default)) ]
115		[ -v (verbose output) ]
116		[ -V (REALLY verbose output) ]
117		[ -q (quiet (default)) ]
118		[ -c (clean up (remove temp files) when done (default) ]
119		[ -p (preserve temp files -- useful for debugging) ]
120		[ -L (library create: put tarfile in $INSTALL_LIB/env.karch) ]
121		[ -l lib (library extract: use $INSTALL_LIB/lib as source) ]
122		[ -D libdir (default: $HOME/LibInstall) ]
123		[ -d tempdir (Install work area (default: /tmp)) ]
124		[ -G glomname (put all files under platform/karch/glomname) ]
125		[ -i impl (e.g. sunfire; recommended with -G) ]
126		[ -x (update /etc/name_to_major et al) ]
127		[ -X (do not update /etc/name_to_major et al (default)) ]
128		[ -P (update /etc/path_to_inst -- generally not advisable) ]
129		[ -h (help -- prints this message) ]
130		[ -R (recover a previous Install) ]
131		[ -o objdir (object directory - either obj or debug (the default)) ]
132		[ -K (do not copy kmdb) ]
133		[ -3 32-bit modules only ]
134		[ -6 64-bit modules only ]
135		[ list of modules to install ]
136
137For full details:
138
139	man -M /ws/on297-gate/public/docs Install
140'
141	exit 1
142}
143
144#
145# Save the current state of Install
146#
147
148save_state() {
149	rm -f $INSTALL_STATE
150	(echo "# State of previous Install
151TARGET=$TARGET
152ENV_PATH=$ENV_PATH
153ENV_NAME=$ENV_NAME
154KARCH=$KARCH
155UTS=$UTS
156INSTALL_DIR=$INSTALL_DIR
157INSTALL_LIB=$INSTALL_LIB
158IMODE=$IMODE
159LIBCREATE=$LIBCREATE
160LIBSRC=$LIBSRC
161VERBOSE=$VERBOSE
162CLEANUP=$CLEANUP
163GLOM=$GLOM
164GLOMNAME=$GLOMNAME
165KMDB=$KMDB
166XFLAG=$XFLAG
167files='$files'
168STATE=$STATE" >$INSTALL_STATE) || verbose "Warning: cannot save state"
169}
170
171#
172# Restore the previous state of Install
173#
174
175restore_state() {
176	test -s $INSTALL_STATE || fail "Can't find $INSTALL_STATE"
177	eval "`cat $INSTALL_STATE`"
178}
179
180#
181# Install failed -- print error messages and exit 2
182#
183
184fail() {
185	save_state
186	while [ $# -gt 0 ]
187	do
188		echo $1
189		shift
190	done
191	echo "Install failed"
192	exit 2
193}
194
195#
196# Echo a string in verbose mode only
197#
198
199verbose() {
200	test "$VERBOSE" != "q" && echo $1
201}
202
203#
204# hack for tmpfs bug -- remove files gradually
205#
206
207remove_dir() {
208	test -d $1 || return
209	local_dot=`pwd`
210	cd $1
211	touch foo
212	rm -f `find . -type f -print`
213	cd $local_dot
214	rm -rf $1
215}
216
217#
218# Copy kernel modules to $INSTALL_DIR
219#
220
221copy_kernel() {
222	# The awk script below looks in Makefile.uts to find out what module
223	# subdirectories to make.  It then looks in Makefile.$KARCH (for root
224	# modules) and Makefile.$ISA (for usr modules) to create a list of
225	# all possible modules.  Finally, it looks at each module's Makefile
226	# to determine where it belongs and what links are required.
227	# This script makes three assumptions:
228	#
229	# 1) Module subdirectories are specified in Makefile.uts by lines of the
230	#    form:
231	#
232	#	ROOT_FOO_DIR = $(ROOT_MOD_DIR)/foo
233	#	USR_BAR_DIR = $(USR_MOD_DIR)/bar
234	#
235	# 2) The corresponding lists of modules appear in Makefile.$KARCH and
236	#    Makefile.$ISA on one or more lines of the form:
237	#
238	#	FOO_KMODS = foo bar
239	#	FOO_KMODS += red white blue
240	#
241	# 3) Each module directory has a Makefile with lines of the form:
242	#
243	#	ROOTMODULE = $(ROOT_FOO_DIR)/$(MODULE)
244	#	USRMODULE = $(USR_FOO_DIR)/$(MODULE)
245	#	ROOTLINK* = $(ROOT_BAR_DIR)/something
246	#	USRLINK* = $(USR_BAR_DIR)/something
247	#
248	# If the structure of Makefile.{$KARCH,uts,$ISA} changes in a way that
249	# invalidates these assumptions, you'll need to pick up a new version of
250	# Install.
251
252	case $KARCH in
253		sun4*)		ISA=sparc;	MACH=sparc;	SUBISA_MAKE=;;
254		i86pc)		ISA=intel;	MACH=i386;	SUBISA_MAKE=$ISA/ia32/Makefile.ia32;;
255		*)		fail "${KARCH}: invalid kernel architecture";;
256	esac
257
258	if [ "$GLOM" = "no" ]; then
259		verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH"
260	else
261		verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH, impl = $IMPL"
262	fi
263
264	UTS_MAKE=Makefile.uts
265	ISA_MAKE=$ISA/Makefile.$ISA
266	KARCH_MAKE=$KARCH/Makefile.$KARCH
267	PSM_MAKE=$UTS/../Makefile.psm
268
269	test -d $KARCH || fail "${KARCH}: invalid kernel architecture"
270	test -d $ISA || fail "${ISA}: invalid instruction set architecture"
271	test -s $UTS_MAKE || fail "Can't find $UTS_MAKE"
272	test -s $ISA_MAKE || fail "Can't find $ISA_MAKE"
273	test -s $KARCH_MAKE || fail "Can't find $KARCH_MAKE"
274	test -s $PSM_MAKE || fail "Can't find $PSM_MAKE"
275
276	#
277	# For 5.8 and 5.9 we used to build a few x86 things in an ia32 subdirectory
278	#
279	[[ -n "$SUBISA_MAKE" && -s "$SUBISA_MAKE" ]] || SUBISA_MAKE=;
280
281	if [ $GLOM = "yes" ]; then
282		if [ -f $KARCH/$IMPL/Makefile.$IMPL ]; then
283			IMPL_MAKE="$KARCH/$IMPL/Makefile.$IMPL"
284		fi
285	else
286		IMPL_MAKE=`nawk -v karch="$KARCH" '
287			$1 == "IMPLEMENTATIONS" {
288			for (i = 3; i <= NF; i++)
289				if ($i != ".WAIT")
290					printf("%s ", karch "/" $i "/Makefile." $i)
291			}' $KARCH_MAKE`
292	fi
293
294	DEVFS="./$ISA/devfs/Makefile"
295
296	verbose "Copying files to ${INSTALL_FILES}..."
297	test -d $INSTALL_FILES || mkdir -p $INSTALL_FILES
298
299	nawk \
300		-v isa="$ISA" \
301		-v mach="$MACH" \
302		-v insd="$INSTALL_FILES" \
303		-v files="$files" \
304		-v verbose=$VERBOSE \
305		-v karch=$KARCH \
306		-v copy="$INSTALL_CP" \
307		-v devfs=$DEVFS \
308		-v auxfiles=$XFLAG \
309		-v ptiflag=$PFLAG \
310		-v glom=$GLOM \
311		-v glomname=$GLOMNAME \
312		-v impl=$IMPL \
313		-v objd=$OBJD \
314		-v want32=$WANT32 \
315		-v want64=$WANT64 \
316		'
317	function run(s) {
318		if (verbose != "q")
319			print s
320		if (system(s))
321			exit 1
322	}
323	function cpf(f1,f2) {
324		if (verbose != "q")
325			print copy " " f1 " " f2
326		if (system(copy " " f1 " " f2))
327			print "WARNING: copy of " f1 " failed"
328	}
329	function mkdir(dir) {
330		if (!touched[dir]) {
331			run("test -d " dir " || mkdir -p " dir)
332			touched[dir]=1
333		}
334		return dir
335	}
336	function vprint(s) {
337		if (verbose == "V")
338			print s
339	}
340	function try_run(s) {
341		if (verbose != "q")
342			print s
343		if (system(s))
344			return 1
345		return 0
346	}
347	function exist(s) {
348		if (verbose != "q")
349			print "test -f " s
350		return !system("test -f " s)
351	}
352
353	function copymod(src, targ, om) {
354		if (om) {
355			run("if [ -f " src " ] ; then " \
356			    copy " " src " " targ " ; fi")
357		} else {
358			run(copy " " src " " targ)
359		}
360	}
361
362	function copymod32(idx, modtarg) {
363		modsrc = modsrcd[idx] "/" objd32 "/" modname[idx]
364
365		if (!exist(modsrc))
366			return (0)
367
368		copymod(modsrc, modtarg, optmod[idx])
369		return (1)
370	}
371
372	function copymod64(idx, modtarg) {
373		modsrc = modsrcd[idx] "/" objd64 "/" modname[idx]
374
375		if (!exist(modsrc))
376			return (0)
377
378		copymod(modsrc, modtarg subdir64, optmod[idx])
379		return (1)
380	}
381
382	function linkmod(lmod, idx, modtarg, did32, did64) {
383		if (lmod ~ /^...MODULE.$/)
384			lmod = "/" modname[idx]
385
386		if (did32 == "yes") {
387			m = modtarg "/" modname[i]
388			run("rm -f " dir lmod "; ln " m " " dir lmod)
389		}
390
391		if (did64 == "yes") {
392			m = modtarg subdir64 "/" modname[i]
393			run("rm -f " dir subdir64 lmod "; ln " m " " \
394			    dir subdir64 lmod)
395		}
396	}
397
398	function slinkmod(slinktarg, idx, modtarg, did32, did64) {
399		if (did32 == "yes") {
400			slink = modtarg "/" slinktarg
401			run("rm -f " slink "; ln -s " modname[i] " " slink)
402		}
403
404		if (did64 == "yes") {
405			slink = modtarg subdir64 "/" slinktarg
406			run("rm -f " slink "; ln -s " modname[i] " " slink)
407		}
408	}
409
410	BEGIN {
411		# If you do NOT want the SVVS modules, set svvs to 0.
412		svvs=1
413		# If you do NOT want the excluded modules, set xmods to 0.
414		xmods=1
415
416		machkernel = "/platform/" karch "/" glomname
417
418		nmods=0
419		do32="no"
420		do64="no"
421		objd32=objd "32"
422		objd64=objd "64"
423		build64and32="no"
424	}
425
426	$1 == "SUBDIR64_" mach {
427		vprint($0)
428		subdir64="/" $3
429		subdir64_relative=$3
430	}
431
432	FILENAME == "Makefile.uts" && $1 == "ALL_BUILDS64" {
433		vprint($0)
434		if ($0 ~ /32/)
435			build64and32="yes"
436	}
437
438	FILENAME == karch "/Makefile." karch && $1 == "ALL_BUILDS" {
439		vprint($0)
440		if ($3 ~ /32/)
441			do32=want32
442		if ($4 ~ /32/)
443			build64and32="yes"
444		if ($3 ~ /ALL_BUILDS64/ && build64and32 == "yes")
445			do32=want32
446		if ($3 ~ /64/ && want64)
447			do64=want64
448	}
449
450	$1 ~ /^(ROOT|USR)_.+_DIR(_32)?$/ {
451		vprint($0)
452		if ($3 ~ /_..CLASS..$/)
453			next
454		slash=index($3,"/")
455		sub(/_32$/,"",$1)
456		if (!slash)
457			slash=length($3)+1
458		parent=substr($3,3,slash-4)
459		subdir=substr($3,slash)
460		if (parent == "ROOT")
461			child=subdir
462		else if (moddirs[parent]) {
463			if ($3 ~ /..PLATFORM.$/)
464				child=moddirs[parent] "/" karch
465			else
466				child=moddirs[parent] subdir
467		} else {
468			print "missing mod dir " parent
469			exit 1
470		}
471		moddirs[$1]=child
472		sub(/^.*kernel/,machkernel,child)
473		glomdirs[$1]=child
474		n=split($1,foo,"_")
475		if (n == 4 && foo[2] != "PSM")
476			notdef[$1]=tolower(foo[2])
477	}
478
479	FILENAME != isa "/Makefile." isa && $1 ~ /^(GENLIB|UNIX)_DIR$/ {
480		vprint($0)
481		n=split($3,foo,"/")
482		slash=index($3,"/")
483		dir="." substr($3,slash)
484		sub(/..PLATFORM./,karch,dir)
485		nmods++
486		modsrcd[nmods]=dir
487		modname[nmods]=foo[n]
488		unixmod[nmods]=1
489	}
490
491	FILENAME != "Makefile.uts" && $1 ~ /KMODS|XMODS/ &&
492	    $1 != "GENUNIX_KMODS" {
493		dir = FILENAME;
494		sub(/\/Makefile.*$/, "", dir);
495		if ($1 ~ "^SVVS_")
496			if (svvs == 0)
497				next
498			else
499				dir = dir "/svvs"
500		if ($1 ~ "XMODS" && xmods == 0)
501			next
502		if ($0 !~ /\$/) {
503			vprint($0)
504			for (i = 3; i <= NF; i++) {
505				if ($i ~ /^(ramdisk|wsdrv|vdi)$/)
506					continue;
507				nmods++
508				modname[nmods]=$i
509				modsrcd[nmods]="./" dir "/" $i
510				if ($1 ~ "^MPSAS_")
511					optmod[nmods] = 1
512			}
513		}
514	}
515
516	FILENAME == karch "/Makefile." karch && $1 == "PLATFORMS" &&
517	    $3 !~ /\(/ {
518		for (i = 3; i <= NF; i++)
519			mkdir(insd "/platform/" $i)
520	}
521
522	FILENAME == karch "/Makefile." karch && ($1 == "IMPLEMENTED_PLATFORM" ||
523	    $1 == "LINKED_PLATFORMS") {
524		for (i = 3; i <= NF; i++)
525			mkdir(insd "/platform/" $i)
526	}
527
528	FILENAME != "Makefile.uts" && $1 == "CONFS" {
529		for (i = 3; i <= NF; i++) {
530			kbi_brain_damage[$i] = "yes"
531		}
532	}
533
534	END {
535		split(files, modlist)
536		for (m in modlist) {
537			mm = modlist[m]
538			if (mm == "modules") {
539				for (i = 1; i <= nmods; i++)
540					if (unixmod[i] == 0)
541						modcopy[i]=1
542				continue
543			}
544			nomodfound = 1
545			for (i = 1; i <= nmods; i++) {
546				if (modname[i] == mm) {
547					modcopy[i]=1
548					nomodfound = 0
549				}
550			}
551			if (nomodfound) {
552				print mm ": invalid module"
553				exit 1
554			}
555		}
556
557		for(i = 1; i <= nmods; i++) {
558			if (!modcopy[i])
559				continue
560
561			confsrc = ""
562			drvfiles[1] = ""
563			classfile = ""
564			ptifile = ""
565			did32=do32
566			did64=do64
567			no_builds="false"
568			modmake=modsrcd[i] "/Makefile"
569
570			while (getline <modmake > 0) {
571				if ($1 == "NO_BUILDS") {
572					vprint($0)
573					no_builds="true"
574				}
575
576				if ($1 == "ALL_BUILDS" && $3 ~ /64/) {
577					vprint($0)
578					did32="ok"
579				}
580
581				if ($1 == "ALL_BUILDS" && $3 ~ /32/) {
582					vprint($0)
583					did64="ok"
584				}
585
586				if ($1 ~ /^(MODULE|UNIX)$/) {
587					vprint($0)
588					modname[i] = $3
589				}
590
591				if ($1 ~ /^(ROOT|USR)(LINK|MODULE$)/) {
592					vprint($0)
593					slash=index($3,"/")
594					parent=substr($3,3,slash-4)
595
596					if (notdef[parent] &&
597					    notdef[parent] != impl &&
598					    glom == "yes") {
599						confsrc = ""
600						break
601					}
602
603					dir = (glom == "no") ? \
604					    moddirs[parent] : glomdirs[parent]
605					if (!dir) {
606						print "no parent for " modname[i]
607						exit 1
608					}
609
610					dir=insd dir
611					mkdir(dir)
612
613					if (do64 == "yes")
614						mkdir(dir subdir64)
615
616					if ($1 ~ /^(ROOT|USR)MODULE$/) {
617						modtarg=dir
618						conftarg=dir
619						if (modname[i] in \
620						    kbi_brain_damage) {
621							confsrc = "./" karch \
622							    "/io"
623							conftarg = insd \
624							    machkernel "/drv"
625
626							mkdir(conftarg)
627
628							if (do64 == "yes") {
629								mkdir(conftarg \
630								    subdir64)
631							}
632						}
633
634						if (do32 == "yes" &&
635						    !copymod32(i, modtarg))
636							did32="no"
637
638						if (do64 == "yes" &&
639						    !copymod64(i, modtarg))
640							did64="no"
641
642					} else {
643						linkmod(substr($3, slash),
644						    i, modtarg, did32, did64)
645					}
646				}
647
648				if ($1 == "SOFTLINKS") {
649					vprint($0)
650					for (j = 3; j <= NF; j++) {
651						slinkmod($j, i, modtarg, did32,
652						    did64)
653					}
654				}
655
656				if ($1 == "CONF_SRCDIR") {
657					vprint($0)
658					slash = index($3, "/")
659					confsrc = "." substr($3, slash)
660				}
661			}
662
663			if (do32 == "yes" && did32 == "no" &&
664			    no_builds == "false") {
665				print "missing 32b file " confsrc "/" modname[i]
666				exit 1
667			}
668
669			if (do64 == "yes" && did64 == "no" &&
670			    no_builds == "false") {
671				print "missing 64b file " confsrc "/" modname[i]
672				exit 1
673			}
674
675			if (confsrc != "") {
676				conffile = confsrc "/" modname[i] ".conf"
677				cpf(conffile, conftarg)
678			}
679
680			close(modmake)
681		}
682
683		#
684		# Make symlinks for KBI for different root node names for a
685		# given platform
686		#
687		km = "./" karch "/Makefile"
688		while (getline <km > 0) {
689			if ($1 == "PLAT_LINKS") {
690				for (i = 3; i <= NF; i++) {
691					mkdir(insd "/platform")
692					run("ln -s " karch " " insd \
693					    "/platform/" $i)
694				}
695			}
696		}
697		close(km)
698
699		if (did64 == "yes" && build64and32 == "no" &&
700		    (try_run("test -f " insd "/platform/" karch "/" \
701		    glomname "/" subdir64_relative "/unix") == 0))
702		{
703			run("ln -s " subdir64_relative "/unix " insd \
704			    "/platform/" karch "/" glomname "/unix")
705
706			if (isa == "sparc" && glom == "no" &&
707			    (try_run("test -f " insd \
708			     "/platform/SUNW,Ultra-Enterprise-10000/" glomname \
709			     "/" subdir64_relative "/unix") == 0)) {
710				run("ln -s " subdir64_relative "/unix " insd \
711				    "/platform/SUNW,Ultra-Enterprise-10000/" \
712				    glomname "/unix")
713			}
714		}
715
716		while (getline <devfs > 0) {
717			if ($1 == "SRCDIR")
718				configdir = "." substr($3, index($3, "/")) "/"
719			if ($1 == "CLASSFILE")
720				classfile = $3
721			if ($1 == "PTIFILE")
722				ptifile = $3
723			if ($1 == "DRVFILES")
724				split(substr($0, index($0, $3)), drvfiles)
725		}
726		close(devfs)
727
728		if (classfile != "" && auxfiles == 1) {
729			dir = mkdir(targ["ROOT_DRV"])
730			cpf(configdir classfile, dir)
731		}
732
733		if (ptifile != "" && ptiflag == 1) {
734			dir = mkdir(insd "/etc")
735			cpf(configdir ptifile, dir)
736		}
737
738		if (drvfiles[1] != "" && auxfiles == 1) {
739			dir = mkdir(insd "/etc")
740			for (file in drvfiles)
741				cpf(configdir drvfiles[file], dir)
742		}
743	}' $UTS_MAKE $PSM_MAKE $ISA_MAKE $SUBISA_MAKE $KARCH_MAKE $IMPL_MAKE
744	[[ $? -ne 0 ]] && fail "Files missing in environment"
745
746	#
747	# on x86, add the glommed kernel name to the root archive
748	#
749	if [[ $KARCH = "i86pc" && $GLOM == "yes" ]]; then
750		filelist="$INSTALL_FILES/etc/boot/solaris/filelist.ramdisk"
751		mkdir -p `dirname $filelist`
752		echo "platform/$KARCH/$GLOMNAME" >$filelist
753	fi
754
755	STATE=1 # all kernel modules copied correctly
756	save_state
757}
758
759kmdb_copy() {
760	typeset src="$1"
761	typeset destdir="$2"
762
763	if [[ ! -d $dest ]] ; then
764		[[ $VERBOSE != "q" ]] && echo "mkdir -p $destdir"
765
766		mkdir -p $destdir || fail "failed to create $destdir"
767	fi
768
769	[[ $VERBOSE != "q" ]] && echo "cp $src $destdir"
770
771	cp $src $destdir || fail "failed to copy $src to $destdir"
772}
773
774kmdb_copy_machkmods() {
775	typeset modbase="$1"
776	typeset destdir="$2"
777	typeset dir=
778	typeset kmod=
779
780	[[ ! -d $modbase ]] && return
781
782	for dir in $(find $modbase -name kmod) ; do
783		set -- $(echo $dir |tr '/' ' ')
784
785		[[ $# -lt 2 ]] && fail "invalid mach kmod dir $dir"
786
787		shift $(($# - 2))
788		kmod=$1
789
790		[[ ! -f $dir/$kmod ]] && continue
791
792		kmdb_copy $dir/$kmod $destdir
793	done
794}
795
796kmdb_copy_karchkmods() {
797	typeset modbase="$1"
798	typeset destdir="$2"
799	typeset bitdir="$3"
800	typeset dir=
801	typeset kmod=
802	typeset karch=
803
804	[[ ! -d $modbase ]] && return
805
806	for dir in $(find $modbase -name kmod) ; do
807		set -- $(echo $dir | tr '/' ' ')
808
809		[[ $# -lt 3 ]] && fail "invalid karch kmod dir $dir"
810
811		shift $(($# - 3))
812		kmod=$1
813		bdir=$2
814
815		[[ $bdir != $bitdir ]] && continue
816		[[ ! -f $dir/$1 ]] && continue
817
818		kmdb_copy $dir/$kmod $destdir
819	done
820}
821
822kmdb_copy_kmdbmod() {
823	typeset kmdbpath="$1"
824	typeset destdir="$2"
825
826	[[ ! -f $kmdbpath ]] && return 1
827
828	kmdb_copy $kmdbpath $destdir
829
830	return 0
831}
832
833copy_kmdb() {
834	typeset kmdbtgtdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME/misc
835	typeset bitdirs=
836	typeset isadir=
837	typeset b64srcdir=
838	typeset b64tgtdir=
839	typeset b32srcdir=
840	typeset b32tgtdir=
841	typeset machdir=
842	typeset platdir=
843
844	if [[ $KMDB = "no" || ! -d $SRC/cmd/mdb ]] ; then
845		# The kmdb copy was suppressed or the workspace doesn't contain
846		# the mdb subtree.  Either way, there's nothing to do.
847		STATE=2
848		save_state
849		return
850	fi
851
852	if [[ $(mach) = "i386" ]] ; then
853		isadir="intel"
854		b64srcdir="amd64"
855		b64tgtdir="amd64"
856		b32srcdir="ia32"
857		b32tgtdir="."
858	else
859		isadir="sparc"
860		b64srcdir="v9"
861		b64tgtdir="sparcv9"
862		b32srcdir="v7"
863		b32tgtdir="."
864	fi
865
866	typeset foundkmdb=no
867	typeset kmdbpath=
868	typeset destdir=
869
870	platdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME
871	if [[ $GLOM = "yes" ]] ; then
872		machdir=$platdir
873	else
874		machdir=$INSTALL_FILES/kernel
875	fi
876
877	if [[ $WANT64 = "yes" ]] ; then
878		# kmdbmod for sparc and x86 are built and installed
879		# in different places
880		if [[ $(mach) = "i386" ]] ; then
881			kmdbpath=$SRC/cmd/mdb/$isadir/$b64srcdir/kmdb/kmdbmod
882			destdir=$machdir/misc/$b64tgtdir
883		else
884			kmdbpath=$SRC/cmd/mdb/$KARCH/$b64srcdir/kmdb/kmdbmod
885			destdir=$platdir/misc/$b64tgtdir
886		fi
887
888		if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
889			foundkmdb="yes"
890
891			kmdb_copy_machkmods $SRC/cmd/mdb/$isadir/$b64srcdir \
892			    $machdir/kmdb/$b64tgtdir
893			kmdb_copy_karchkmods $SRC/cmd/mdb/$KARCH \
894			    $platdir/kmdb/$b64tgtdir $b64srcdir
895		fi
896	fi
897
898	if [[ $WANT32 = "yes" ]] ; then
899		kmdbpath=$SRC/cmd/mdb/$isadir/$b32srcdir/kmdb/kmdbmod
900		destdir=$machdir/misc/$b32tgtdir
901
902		if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
903			foundkmdb="yes"
904
905			kmdb_copy_machkmods $SRC/cmd/mdb/$isadir/$b32srcdir \
906			    $machdir/kmdb/$b32tgtdir
907			kmdb_copy_karchkmods $SRC/cmd/mdb/$KARCH \
908			    $platdir/kmdb/$b32tgtdir $b32srcdir
909		fi
910	fi
911
912	# A kmdb-less workspace isn't fatal, but it is potentially problematic,
913	# as the changes made to uts may have altered something upon which kmdb
914	# depends.  We will therefore remind the user that they haven't built it
915	# yet.
916	if [[ $foundkmdb != "yes" ]] ; then
917		echo "WARNING: kmdb isn't built, and won't be included"
918	fi
919
920	STATE=2
921	save_state
922	return
923}
924
925#
926# Make tarfile
927#
928
929make_tarfile() {
930	echo "Creating tarfile $TARFILE"
931	test -d $INSTALL_FILES || fail "Can't find $INSTALL_FILES"
932	cd $INSTALL_FILES
933	rm -f $TARFILE files
934
935	# We don't want to change the permissions or ownership of pre-existing
936	# directories on the target machine, so we're going to take care to
937	# avoid including directories in the tarfile.  On extraction, tar won't
938	# modify pre-existing directories, and will create non-existent ones as
939	# the user doing the extraction.
940	find . ! -type d -print |fgrep -vx './files' >files
941	tar cf $TARFILE -I files || fail "Couldn't create tarfile $TARFILE"
942	STATE=3
943}
944
945#
946# Routines to copy files to the target machine
947#
948
949remote_fail() {
950	fail "" "$1" "" \
951		"Make sure that $TARGET_MACHINE is up." \
952"Check .rhosts in the home directory of user $TARGET_USER on $TARGET_MACHINE." \
953		"Check /etc/hosts.equiv, /etc/passwd, and /etc/shadow." \
954		"Change permissions on $TARGET_MACHINE as necessary." \
955		"Then, use \"$INSTALL -R\" to resume the install." ""
956}
957
958remote_install() {
959	if [ "$IMODE" = "n" ]; then
960		STATE=4
961		return 0
962	fi
963	test -s $TARFILE || fail "$TARFILE missing or empty"
964	verbose "Installing system on $TARGET"
965	test -d $INSTALL_DIR || fail "Can't find $INSTALL_DIR"
966	cd $INSTALL_DIR
967	rm -f errors fatal nonfatal
968	if [ "$IMODE" = "T" ]; then
969		EMESG="Can't rcp to $TARGET"
970		touch errors
971		sh -e${SHV}c "$INSTALL_RCP $TARFILE $TARGET/Install.tar"
972	else
973		EMESG="Can't rsh to $TARGET_MACHINE"
974		rsh -l $TARGET_USER $TARGET_MACHINE \
975		    "(cd $TARGET_DIR; /usr/bin/tar x${V}f -)" \
976		    <$TARFILE 2>errors
977	fi
978	test $? -ne 0 && remote_fail "$EMESG"
979	cd $INSTALL_DIR
980	egrep "set time|warning|blocksize" errors >nonfatal
981	egrep -v "set time|warning|blocksize" errors >fatal
982	if [ -s fatal ]; then
983		echo "Fatal errors from rsh:"
984		cat fatal
985		remote_fail "Can't install on $TARGET_MACHINE"
986	fi
987	if [ -s nonfatal -a "$VERBOSE" != "q" ]; then
988		echo "Non-fatal errors from rsh:"
989		cat nonfatal
990	fi
991	rm -f fatal nonfatal errors
992	test "$IMODE" = "T" && echo "Files can be extracted on \
993$TARGET_MACHINE using 'tar xvf $TARGET_DIR/Install.tar'"
994	STATE=4
995}
996
997okexit() {
998	cd /tmp
999	test "$CLEANUP" = c && remove_dir $INSTALL_DIR
1000	save_state
1001	verbose "Install complete"
1002	exit 0
1003}
1004
1005#
1006# Process options
1007#
1008
1009RCOPTS=""
1010LIBCREATE="no"
1011LIBSRC=""
1012PFLAG=0
1013ENV_PATH=$CODEMGR_WS
1014OBJD="debug"
1015KMDB="yes"
1016
1017test -s $INSTALL_RC && RCOPTS=`cat $INSTALL_RC`
1018set $INSTALL $DEFAULT_OPTIONS $RCOPTS $*
1019shift
1020
1021while getopts acd:D:G:hi:k:Kl:Lmno:pPqRs:t:T:uvVw:xX36 opt
1022do
1023	case $opt in
1024	    w)	ENV_PATH="$OPTARG"; SRC="$ENV_PATH/usr/src";;
1025	    s)	UTS="$OPTARG";;
1026	    k)	KARCH="$OPTARG";;
1027	  t|T)	TARGET="$OPTARG"; IMODE=$opt; CLEANUP="c";;
1028	    n)	TARGET=""; IMODE="n"; CLEANUP="p";;
1029	    u)	files="unix genunix";;
1030	    m)	files="modules";;
1031	    a)	files="unix genunix modules";;
1032	v|V|q)	VERBOSE=$opt;;
1033	  c|p)	CLEANUP=$opt;;
1034	    L)	LIBCREATE="yes"; CLEANUP="c";;
1035	    l)	LIBSRC="$OPTARG";;
1036	    D)	INSTALL_LIB="$OPTARG";;
1037	    d)	INSTALL_DIR="$OPTARG/$TRAILER";;
1038	    G)	GLOM=yes; GLOMNAME="$OPTARG";;
1039	    x)	XFLAG=1;;
1040	    X)	XFLAG=0;;
1041	    P)	PFLAG=1;;
1042	    h)	usage "${INSTALL}: installs unix and modules";;
1043	    R)	x=$OPTIND; restore_state; OPTIND=$x;;
1044	    i)	IMPL="$OPTARG";;
1045	    o)	OBJD="$OPTARG";;
1046	    K)  KMDB="no";;
1047	    3)  WANT64="no";;
1048	    6)  WANT32="no";;
1049	   \?)	usage "Illegal option";;
1050	esac
1051done
1052shift `expr $OPTIND - 1`
1053
1054ENV_NAME=`basename $ENV_PATH`
1055
1056#
1057# The rest of the command line is a list of individual files to copy.
1058# If non-null, this list overrides the -uma options.
1059#
1060
1061if [[ $# -gt 0 ]] ; then
1062	files="$*"
1063	KMDB="no"
1064fi
1065
1066case $VERBOSE in
1067	v)	V="v"; SHV="x";;
1068	V)	V="v"; SHV="x"; set -x;;
1069	q)	V=""; SHV="";;
1070esac
1071
1072#
1073# Create temp directory for Install's files
1074#
1075
1076test -d $INSTALL_DIR || mkdir -p $INSTALL_DIR || fail "Can't mkdir $INSTALL_DIR"
1077
1078TARFILE=$INSTALL_DIR/Install.${KARCH}.tar
1079INSTALL_FILES=$INSTALL_DIR/$KARCH
1080
1081#
1082# Extract the target machine and target directory from a target of the
1083# form [user@]machine:/dir .
1084#
1085
1086if [ "$IMODE" != "n" ]; then
1087	eval `echo $TARGET | nawk -F':' '{
1088		if (NF != 2 || !length($1) || !length($2))
1089			print "usage \"Invalid target\""
1090		m = $1; d = $2
1091		if ($1 ~ /@/) {
1092		    k = split($1, f, "@");
1093		    if (k != 2 || !length(f[1]) || !length (f[2]))
1094			    print "usage \"Invalid target\""
1095		    u = f[1]; m = f[2]
1096		}
1097		print "TARGET_USER=" u ";"
1098		print "TARGET_MACHINE=" m ";"
1099		print "TARGET_DIR=" d ";"
1100	}'`
1101	if [ -z "$TARGET_USER" ]; then
1102		TARGET_USER=$LOGNAME
1103	fi
1104fi
1105
1106#
1107# Allow the use of library source or target for the install
1108#
1109
1110if [ -n "$LIBSRC" ]; then
1111	LIBSRC="`basename $LIBSRC .tar`.tar"
1112	TARFILE=$INSTALL_LIB/$LIBSRC
1113	test -s $TARFILE || fail "Can't find tarfile $TARFILE"
1114	verbose "Installing from library tarfile $TARFILE"
1115	STATE=3
1116elif [ "$LIBCREATE" = "yes" ]; then
1117	test -d $INSTALL_LIB \
1118		|| mkdir -p $INSTALL_LIB \
1119		|| fail "Can't mkdir $INSTALL_LIB"
1120	TARFILE="$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar"
1121fi
1122
1123#
1124# The next three lines allow recovery and activation with -R,
1125# and library installs with -l.
1126#
1127
1128[[ $STATE -eq 1 ]] && copy_kmdb
1129[[ $STATE -eq 2 ]] && make_tarfile
1130[[ $STATE -eq 3 ]] && remote_install
1131[[ $STATE -eq 4 ]] && okexit
1132
1133save_state
1134
1135cd $DOT
1136DOTDOT=`cd ..; pwd`
1137
1138#
1139# Try to be smart: if DOTDOT ends in uts, then infer UTS and KARCH from DOT
1140# Otherwise, if SRC is set, infer UTS = $SRC/uts.
1141#
1142
1143if [ "`basename $DOTDOT`" = "uts" ]; then
1144	UTS=$DOTDOT
1145	KARCH=`basename $DOT`
1146fi
1147
1148if [ -z "$UTS" -a -n "$SRC" ]; then
1149	UTS="${SRC}/uts"
1150	test -n "$KARCH" || fail "no karch specified (e.g. -k sun4u)"
1151fi
1152
1153if [ "$LIBCREATE" = "yes" ]; then
1154	TARFILE=$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar
1155else
1156	TARFILE=$INSTALL_DIR/Install.${KARCH}.tar
1157fi
1158INSTALL_FILES=$INSTALL_DIR/$KARCH
1159save_state
1160
1161cd $DOT
1162test -z "$UTS" && fail 'Cannot find kernel sources -- $SRC not set'
1163test -d "$UTS" || fail "${UTS}: no such directory"
1164
1165#
1166# Convert UTS into an absolute path.
1167#
1168
1169cd $UTS
1170UTS=`pwd`
1171
1172test "`basename $UTS`" = "uts" || \
1173	verbose "Warning: source path $UTS doesn't end in 'uts'"
1174
1175remove_dir $INSTALL_DIR/$KARCH
1176rm -f $TARFILE
1177
1178copy_kernel	# sets STATE=1 if successful
1179copy_kmdb	# sets STATE=2 if successful
1180make_tarfile	# sets STATE=3 if successful
1181remote_install	# sets STATE=4 if successful
1182
1183okexit
1184