xref: /titanic_41/usr/src/tools/scripts/nightly.sh (revision e0724c534a46ca4754330bc022bf1e2a68f5bb93)
1#!/bin/ksh -p
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#
24# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
25# Copyright 2008, 2010, Richard Lowe
26# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
27# Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
28#
29# Based on the nightly script from the integration folks,
30# Mostly modified and owned by mike_s.
31# Changes also by kjc, dmk.
32#
33# BRINGOVER_WS may be specified in the env file.
34# The default is the old behavior of CLONE_WS
35#
36# -i on the command line, means fast options, so when it's on the
37# command line (only), lint and check builds are skipped no matter what
38# the setting of their individual flags are in NIGHTLY_OPTIONS.
39#
40# LINTDIRS can be set in the env file, format is a list of:
41#
42#	/dirname-to-run-lint-on flag
43#
44#	Where flag is:	y - enable lint noise diff output
45#			n - disable lint noise diff output
46#
47#	For example: LINTDIRS="$SRC/uts n $SRC/stand y $SRC/psm y"
48#
49# OPTHOME and TEAMWARE may be set in the environment to override /opt
50# and /opt/teamware defaults.
51#
52
53#
54# The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
55# under certain circumstances, which can really screw things up; unset it.
56#
57unset CDPATH
58
59# Get the absolute path of the nightly script that the user invoked.  This
60# may be a relative path, and we need to do this before changing directory.
61nightly_path=`whence $0`
62
63#
64# Keep track of where we found nightly so we can invoke the matching
65# which_scm script.  If that doesn't work, don't go guessing, just rely
66# on the $PATH settings, which will generally give us either /opt/onbld
67# or the user's workspace.
68#
69WHICH_SCM=$(dirname $nightly_path)/which_scm
70if [[ ! -x $WHICH_SCM ]]; then
71	WHICH_SCM=which_scm
72fi
73
74function fatal_error
75{
76	print -u2 "nightly: $*"
77	exit 1
78}
79
80#
81# Function to do a DEBUG and non-DEBUG build. Needed because we might
82# need to do another for the source build, and since we only deliver DEBUG or
83# non-DEBUG packages.
84#
85# usage: normal_build
86#
87function normal_build {
88
89	typeset orig_p_FLAG="$p_FLAG"
90	typeset crypto_signer="$CODESIGN_USER"
91
92	suffix=""
93
94	# non-DEBUG build begins
95
96	if [ "$F_FLAG" = "n" ]; then
97		set_non_debug_build_flags
98		CODESIGN_USER="$crypto_signer" \
99		    build "non-DEBUG" "$suffix-nd" "-nd" "$MULTI_PROTO"
100		if [ "$build_ok" = "y" -a "$X_FLAG" = "y" -a \
101		    "$p_FLAG" = "y" ]; then
102			copy_ihv_pkgs non-DEBUG -nd
103		fi
104	else
105		echo "\n==== No non-DEBUG $open_only build ====\n" >> "$LOGFILE"
106	fi
107
108	# non-DEBUG build ends
109
110	# DEBUG build begins
111
112	if [ "$D_FLAG" = "y" ]; then
113		set_debug_build_flags
114		CODESIGN_USER="$crypto_signer" \
115		    build "DEBUG" "$suffix" "" "$MULTI_PROTO"
116		if [ "$build_ok" = "y" -a "$X_FLAG" = "y" -a \
117		    "$p_FLAG" = "y" ]; then
118			copy_ihv_pkgs DEBUG ""
119		fi
120	else
121		echo "\n==== No DEBUG $open_only build ====\n" >> "$LOGFILE"
122	fi
123
124	# DEBUG build ends
125
126	p_FLAG="$orig_p_FLAG"
127}
128
129#
130# usage: run_hook HOOKNAME ARGS...
131#
132# If variable "$HOOKNAME" is defined, insert a section header into
133# our logs and then run the command with ARGS
134#
135function run_hook {
136	HOOKNAME=$1
137    	eval HOOKCMD=\$$HOOKNAME
138	shift
139
140	if [ -n "$HOOKCMD" ]; then
141	    	(
142			echo "\n==== Running $HOOKNAME command: $HOOKCMD ====\n"
143		    	( $HOOKCMD "$@" 2>&1 )
144			if [ "$?" -ne 0 ]; then
145			    	# Let exit status propagate up
146			    	touch $TMPDIR/abort
147			fi
148		) | tee -a $mail_msg_file >> $LOGFILE
149
150		if [ -f $TMPDIR/abort ]; then
151			build_ok=n
152			echo "\nAborting at request of $HOOKNAME" |
153				tee -a $mail_msg_file >> $LOGFILE
154			exit 1
155		fi
156	fi
157}
158
159#
160# usage: filelist DESTDIR PATTERN
161#
162function filelist {
163	DEST=$1
164	PATTERN=$2
165	cd ${DEST}
166
167	OBJFILES=${ORIG_SRC}/xmod/obj_files
168	if [ ! -f ${OBJFILES} ]; then
169		return;
170	fi
171	for i in `grep -v '^#' ${OBJFILES} | \
172	    grep ${PATTERN} | cut -d: -f2 | tr -d ' \t'`
173	do
174		# wildcard expansion
175		for j in $i
176		do
177			if [ -f "$j" ]; then
178				echo $j
179			fi
180			if [ -d "$j" ]; then
181				echo $j
182			fi
183		done
184	done | sort | uniq
185}
186
187# function to save off binaries after a full build for later
188# restoration
189function save_binaries {
190	# save off list of binaries
191	echo "\n==== Saving binaries from build at `date` ====\n" | \
192	    tee -a $mail_msg_file >> $LOGFILE
193	rm -f ${BINARCHIVE}
194	cd ${CODEMGR_WS}
195	filelist ${CODEMGR_WS} '^preserve:' >> $LOGFILE
196	filelist ${CODEMGR_WS} '^preserve:' | \
197	    cpio -ocB 2>/dev/null | compress \
198	    > ${BINARCHIVE}
199}
200
201# delete files
202# usage: hybridize_files DESTDIR MAKE_TARGET
203function hybridize_files {
204	DEST=$1
205	MAKETARG=$2
206
207	echo "\n==== Hybridizing files at `date` ====\n" | \
208	    tee -a $mail_msg_file >> $LOGFILE
209	for i in `filelist ${DEST} '^delete:'`
210	do
211		echo "removing ${i}." | tee -a $mail_msg_file >> $LOGFILE
212		rm -rf "${i}"
213	done
214	for i in `filelist ${DEST} '^hybridize:' `
215	do
216		echo "hybridizing ${i}." | tee -a $mail_msg_file >> $LOGFILE
217		rm -f ${i}+
218		sed -e "/^# HYBRID DELETE START/,/^# HYBRID DELETE END/d" \
219		    < ${i} > ${i}+
220		mv ${i}+ ${i}
221	done
222}
223
224# restore binaries into the proper source tree.
225# usage: restore_binaries DESTDIR MAKE_TARGET
226function restore_binaries {
227	DEST=$1
228	MAKETARG=$2
229
230	echo "\n==== Restoring binaries to ${MAKETARG} at `date` ====\n" | \
231	    tee -a $mail_msg_file >> $LOGFILE
232	cd ${DEST}
233	zcat ${BINARCHIVE} | \
234	    cpio -idmucvB 2>/dev/null | tee -a $mail_msg_file >> ${LOGFILE}
235}
236
237# rename files we save binaries of
238# usage: rename_files DESTDIR MAKE_TARGET
239function rename_files {
240	DEST=$1
241	MAKETARG=$2
242	echo "\n==== Renaming source files in ${MAKETARG} at `date` ====\n" | \
243	    tee -a $mail_msg_file >> $LOGFILE
244	for i in `filelist ${DEST} '^rename:'`
245	do
246		echo ${i} | tee -a $mail_msg_file >> ${LOGFILE}
247		rm -f ${i}.export
248		mv ${i} ${i}.export
249	done
250}
251
252#
253# Copy some or all of the source tree.
254#
255# Returns 0 for success, non-zero for failure.
256#
257# usage: copy_source CODEMGR_WS DESTDIR LABEL SRCROOT
258#
259function copy_source {
260	WS=$1
261	DEST=$2
262	label=$3
263	srcroot=$4
264
265	printf "\n==== Creating %s source from %s (%s) ====\n\n" \
266	    "$DEST" "$WS" "$label" | tee -a $mail_msg_file >> $LOGFILE
267
268	printf "cleaning out %s\n" "$DEST." >> $LOGFILE
269	rm -rf "$DEST" >> $LOGFILE 2>&1
270
271	printf "creating %s\n" "$DEST." >> $LOGFILE
272	mkdir -p "$DEST" 2>> $LOGFILE
273
274	if (( $? != 0 )) ; then
275		printf "failed to create %s\n" "$DEST" |
276		    tee -a $mail_msg_file >> $LOGFILE
277		build_ok=n
278		return 1
279	fi
280	cd "$WS"
281
282	printf "populating %s\n" "$DEST." >> $LOGFILE
283
284	case "$SCM_TYPE" in
285	teamware)
286		find $srcroot -name 's\.*' -a -type f -print | \
287		    sed -e 's,SCCS\/s.,,' | \
288		    grep -v '/\.del-*' | \
289		    cpio -pd $DEST >>$LOGFILE 2>&1
290		if (( $? != 0 )) ; then
291		    printf "cpio failed for %s\n" "$DEST" |
292			tee -a $mail_msg_file >> $LOGFILE
293		    build_ok=n
294		    return 1
295		fi
296		;;
297	mercurial)
298		copy_source_mercurial $DEST $srcroot
299		if (( $? != 0 )) ; then
300		    build_ok=n
301		    return 1
302		fi
303		;;
304	*)
305		build_ok=n
306		echo "Tree copy is not supported for workspace type" \
307		    "$SCM_TYPE" | tee -a $mail_msg_file >> $LOGFILE
308		return 1
309		;;
310	esac
311
312	return 0
313}
314
315#
316# Mercurial-specific copy code for copy_source().  Handles the
317# combined open and closed trees.
318#
319# Returns 0 for success, non-zero for failure.
320#
321# usage: copy_source_mercurial destdir srcroot
322#
323function copy_source_mercurial {
324	typeset dest=$1
325	typeset srcroot=$2
326	typeset open_top closed_top
327
328	case $srcroot in
329	usr)
330		open_top=usr
331		if [[ "$CLOSED_IS_PRESENT" = yes ]]; then
332			closed_top=usr/closed
333		fi
334		;;
335	usr/closed*)
336		if [[ "$CLOSED_IS_PRESENT" = no ]]; then
337			printf "can't copy %s: closed tree not present.\n" \
338			    "$srcroot" | tee -a $mail_msg_file >> $LOGFILE
339			return 1
340		fi
341		closed_top="$srcroot"
342		;;
343	*)
344		open_top="$srcroot"
345		;;
346	esac
347
348	if [[ -n "$open_top" ]]; then
349		hg locate -I "$open_top" | cpio -pd "$dest" >>$LOGFILE 2>&1
350		if (( $? != 0 )) ; then
351		    printf "cpio failed for %s\n" "$dest" |
352			tee -a $mail_msg_file >> $LOGFILE
353		    return 1
354		fi
355	fi
356
357	if [[ -n "$closed_top" ]]; then
358		mkdir -p "$dest/usr/closed" || return 1
359		if [[ "$closed_top" = usr/closed ]]; then
360			(cd usr/closed; hg locate |
361			    cpio -pd "$dest/usr/closed") >>$LOGFILE 2>&1
362			if (( $? != 0 )) ; then
363			    printf "cpio failed for %s/usr/closed\n" \
364				"$dest" | tee -a $mail_msg_file >> $LOGFILE
365			    return 1
366			fi
367		else
368			# copy subtree of usr/closed
369			closed_top=${closed_top#usr/closed/}
370			(cd usr/closed; hg locate -I "$closed_top" |
371			    cpio -pd "$dest/usr/closed") >>$LOGFILE 2>&1
372			if (( $? != 0 )) ; then
373			    printf "cpio failed for %s/usr/closed/%s\n" \
374				"$dest" "$closed_top" |
375				tee -a $mail_msg_file >> $LOGFILE
376			    return 1
377			fi
378		fi
379	fi
380
381	return 0
382}
383
384#
385# function to create (but not build) the export/crypt source tree.
386# usage: set_up_source_build CODEMGR_WS DESTDIR MAKE_TARGET
387# Sets SRC to the modified source tree, for use by the caller when it
388# builds the tree.
389#
390function set_up_source_build {
391	WS=$1
392	DEST=$2
393	MAKETARG=$3
394
395	copy_source $WS $DEST $MAKETARG usr
396	if (( $? != 0 )); then
397	    echo "\nCould not copy source tree for source build." |
398		tee -a $mail_msg_file >> $LOGFILE
399	    build_ok=n
400	    return
401	fi
402
403	SRC=${DEST}/usr/src
404
405	cd $SRC
406	rm -f ${MAKETARG}.out
407	echo "making ${MAKETARG} in ${SRC}." >> $LOGFILE
408	/bin/time $MAKE -e ${MAKETARG} 2>&1 | \
409	    tee -a $SRC/${MAKETARG}.out >> $LOGFILE
410	echo "\n==== ${MAKETARG} build errors ====\n" >> $mail_msg_file
411	egrep ":" $SRC/${MAKETARG}.out | \
412		egrep -e "(^${MAKE}:|[ 	]error[: 	\n])" | \
413		egrep -v "Ignoring unknown host" | \
414		egrep -v "warning" >> $mail_msg_file
415
416	echo "clearing state files." >> $LOGFILE
417	find . -name '.make*' -exec rm -f {} \;
418
419	cd ${DEST}
420	if [ "${MAKETARG}" = "CRYPT_SRC" ]; then
421		rm -f ${CODEMGR_WS}/crypt_files.cpio.Z
422		echo "\n==== xmod/cry_files that don't exist ====\n" | \
423		    tee -a $mail_msg_file >> $LOGFILE
424		CRYPT_FILES=${WS}/usr/src/xmod/cry_files
425		for i in `cat ${CRYPT_FILES}`
426		do
427			# make sure the files exist
428			if [ -f "$i" ]; then
429				continue
430			fi
431			if [ -d "$i" ]; then
432				continue
433			fi
434			echo "$i" | tee -a $mail_msg_file >> $LOGFILE
435		done
436		find `cat ${CRYPT_FILES}` -print 2>/dev/null | \
437		    cpio -ocB 2>/dev/null | \
438		    compress > ${CODEMGR_WS}/crypt_files.cpio.Z
439	fi
440
441	if [ "${MAKETARG}" = "EXPORT_SRC" ]; then
442		# rename first, since we might restore a file
443		# of the same name (mapfiles)
444		rename_files ${EXPORT_SRC} EXPORT_SRC
445		if [ "$SH_FLAG" = "y" ]; then
446			hybridize_files ${EXPORT_SRC} EXPORT_SRC
447		fi
448	fi
449
450	# save the cleartext
451	echo "\n==== Creating ${MAKETARG}.cpio.Z ====\n" | \
452	    tee -a $mail_msg_file >> $LOGFILE
453	cd ${DEST}
454	rm -f ${MAKETARG}.cpio.Z
455	find usr -depth -print | \
456	    grep -v usr/src/${MAKETARG}.out | \
457	    cpio -ocB 2>/dev/null | \
458	    compress > ${CODEMGR_WS}/${MAKETARG}.cpio.Z
459	if [ "${MAKETARG}" = "EXPORT_SRC" ]; then
460		restore_binaries ${EXPORT_SRC} EXPORT_SRC
461	fi
462
463	if [ "${MAKETARG}" = "CRYPT_SRC" ]; then
464		restore_binaries ${CRYPT_SRC} CRYPT_SRC
465	fi
466
467}
468
469# Return library search directive as function of given root.
470function myldlibs {
471	echo "-L$1/lib -L$1/usr/lib"
472}
473
474# Return header search directive as function of given root.
475function myheaders {
476	echo "-I$1/usr/include"
477}
478
479#
480# Function to do the build, including package generation.
481# usage: build LABEL SUFFIX ND MULTIPROTO
482# - LABEL is used to tag build output.
483# - SUFFIX is used to distinguish files (e.g., DEBUG vs non-DEBUG,
484#   open-only vs full tree).
485# - ND is "-nd" (non-DEBUG builds) or "" (DEBUG builds).
486# - If MULTIPROTO is "yes", it means to name the proto area according to
487#   SUFFIX.  Otherwise ("no"), (re)use the standard proto area.
488#
489function build {
490	LABEL=$1
491	SUFFIX=$2
492	ND=$3
493	MULTIPROTO=$4
494	INSTALLOG=install${SUFFIX}-${MACH}
495	NOISE=noise${SUFFIX}-${MACH}
496	PKGARCHIVE=${PKGARCHIVE_ORIG}${SUFFIX}
497
498	ORIGROOT=$ROOT
499	[ $MULTIPROTO = no ] || export ROOT=$ROOT$SUFFIX
500
501	if [[ "$O_FLAG" = y ]]; then
502		echo "\nSetting CLOSEDROOT= ${ROOT}-closed\n" >> $LOGFILE
503		export CLOSEDROOT=${ROOT}-closed
504	fi
505
506	export ENVLDLIBS1=`myldlibs $ROOT`
507	export ENVCPPFLAGS1=`myheaders $ROOT`
508
509	this_build_ok=y
510	#
511	#	Build OS-Networking source
512	#
513	echo "\n==== Building OS-Net source at `date` ($LABEL) ====\n" \
514		>> $LOGFILE
515
516	rm -f $SRC/${INSTALLOG}.out
517	cd $SRC
518	/bin/time $MAKE -e install 2>&1 | \
519	    tee -a $SRC/${INSTALLOG}.out >> $LOGFILE
520
521	if [[ "$SCM_TYPE" = teamware ]]; then
522		echo "\n==== SCCS Noise ($LABEL) ====\n" >> $mail_msg_file
523		egrep 'sccs(check:| *get)' $SRC/${INSTALLOG}.out >> \
524			$mail_msg_file
525	fi
526
527	echo "\n==== Build errors ($LABEL) ====\n" >> $mail_msg_file
528	egrep ":" $SRC/${INSTALLOG}.out |
529		egrep -e "(^${MAKE}:|[ 	]error[: 	\n])" | \
530		egrep -v "Ignoring unknown host" | \
531		egrep -v "cc .* -o error " | \
532		egrep -v "warning" >> $mail_msg_file
533	if [ "$?" = "0" ]; then
534		build_ok=n
535		this_build_ok=n
536	fi
537	grep "bootblock image is .* bytes too big" $SRC/${INSTALLOG}.out \
538		>> $mail_msg_file
539	if [ "$?" = "0" ]; then
540		build_ok=n
541		this_build_ok=n
542	fi
543
544	if [ "$W_FLAG" = "n" ]; then
545		echo "\n==== Build warnings ($LABEL) ====\n" >>$mail_msg_file
546		egrep -i warning: $SRC/${INSTALLOG}.out \
547			| egrep -v '^tic:' \
548			| egrep -v "symbol (\`|')timezone' has differing types:" \
549		        | egrep -v "parameter <PSTAMP> set to" \
550			| egrep -v "Ignoring unknown host" \
551			| egrep -v "redefining segment flags attribute for" \
552			>> $mail_msg_file
553	fi
554
555	echo "\n==== Ended OS-Net source build at `date` ($LABEL) ====\n" \
556		>> $LOGFILE
557
558	echo "\n==== Elapsed build time ($LABEL) ====\n" >>$mail_msg_file
559	tail -3  $SRC/${INSTALLOG}.out >>$mail_msg_file
560
561	if [ "$i_FLAG" = "n" -a "$W_FLAG" = "n" ]; then
562		rm -f $SRC/${NOISE}.ref
563		if [ -f $SRC/${NOISE}.out ]; then
564			mv $SRC/${NOISE}.out $SRC/${NOISE}.ref
565		fi
566		grep : $SRC/${INSTALLOG}.out \
567			| egrep -v '^/' \
568			| egrep -v '^(Start|Finish|real|user|sys|./bld_awk)' \
569			| egrep -v '^tic:' \
570			| egrep -v '^mcs' \
571			| egrep -v '^LD_LIBRARY_PATH=' \
572			| egrep -v 'ar: creating' \
573			| egrep -v 'ar: writing' \
574			| egrep -v 'conflicts:' \
575			| egrep -v ':saved created' \
576			| egrep -v '^stty.*c:' \
577			| egrep -v '^mfgname.c:' \
578			| egrep -v '^uname-i.c:' \
579			| egrep -v '^volumes.c:' \
580			| egrep -v '^lint library construction:' \
581			| egrep -v 'tsort: INFORM:' \
582			| egrep -v 'stripalign:' \
583			| egrep -v 'chars, width' \
584			| egrep -v "symbol (\`|')timezone' has differing types:" \
585			| egrep -v 'PSTAMP' \
586			| egrep -v '|%WHOANDWHERE%|' \
587			| egrep -v '^Manifying' \
588			| egrep -v 'Ignoring unknown host' \
589			| egrep -v 'Processing method:' \
590			| egrep -v '^Writing' \
591			| egrep -v 'spellin1:' \
592			| egrep -v '^adding:' \
593			| egrep -v "^echo 'msgid" \
594			| egrep -v '^echo ' \
595			| egrep -v '\.c:$' \
596			| egrep -v '^Adding file:' \
597			| egrep -v 'CLASSPATH=' \
598			| egrep -v '\/var\/mail\/:saved' \
599			| egrep -v -- '-DUTS_VERSION=' \
600			| egrep -v '^Running Mkbootstrap' \
601			| egrep -v '^Applet length read:' \
602			| egrep -v 'bytes written:' \
603			| egrep -v '^File:SolarisAuthApplet.bin' \
604			| egrep -v -i 'jibversion' \
605			| egrep -v '^Output size:' \
606			| egrep -v '^Solo size statistics:' \
607			| egrep -v '^Using ROM API Version' \
608			| egrep -v '^Zero Signature length:' \
609			| egrep -v '^Note \(probably harmless\):' \
610			| egrep -v '::' \
611			| egrep -v -- '-xcache' \
612			| egrep -v '^\+' \
613			| egrep -v '^cc1: note: -fwritable-strings' \
614			| egrep -v 'svccfg-native -s svc:/' \
615			| sort | uniq >$SRC/${NOISE}.out
616		if [ ! -f $SRC/${NOISE}.ref ]; then
617			cp $SRC/${NOISE}.out $SRC/${NOISE}.ref
618		fi
619		echo "\n==== Build noise differences ($LABEL) ====\n" \
620			>>$mail_msg_file
621		diff $SRC/${NOISE}.ref $SRC/${NOISE}.out >>$mail_msg_file
622	fi
623
624	#
625	#	Re-sign selected binaries using signing server
626	#	(gatekeeper builds only)
627	#
628	if [ -n "$CODESIGN_USER" -a "$this_build_ok" = "y" ]; then
629		echo "\n==== Signing proto area at `date` ====\n" >> $LOGFILE
630		signing_file="${TMPDIR}/signing"
631		rm -f ${signing_file}
632		export CODESIGN_USER
633		signproto $SRC/tools/codesign/creds 2>&1 | \
634			tee -a ${signing_file} >> $LOGFILE
635		echo "\n==== Finished signing proto area at `date` ====\n" \
636		    >> $LOGFILE
637		echo "\n==== Crypto module signing errors ($LABEL) ====\n" \
638		    >> $mail_msg_file
639		egrep 'WARNING|ERROR' ${signing_file} >> $mail_msg_file
640		if (( $? == 0 )) ; then
641			build_ok=n
642			this_build_ok=n
643		fi
644	fi
645
646	#
647	#	Building Packages
648	#
649	if [ "$p_FLAG" = "y" -a "$this_build_ok" = "y" ]; then
650		if [ -d $SRC/pkg -o -d $SRC/pkgdefs ]; then
651			echo "\n==== Creating $LABEL packages at `date` ====\n" \
652				>> $LOGFILE
653			echo "Clearing out $PKGARCHIVE ..." >> $LOGFILE
654			rm -rf $PKGARCHIVE >> "$LOGFILE" 2>&1
655			mkdir -p $PKGARCHIVE >> "$LOGFILE" 2>&1
656
657			for d in pkg pkgdefs; do
658				if [ ! -f "$SRC/$d/Makefile" ]; then
659					continue
660				fi
661				rm -f $SRC/$d/${INSTALLOG}.out
662				cd $SRC/$d
663				/bin/time $MAKE -e install 2>&1 | \
664					tee -a $SRC/$d/${INSTALLOG}.out >> $LOGFILE
665			done
666
667			echo "\n==== package build errors ($LABEL) ====\n" \
668				>> $mail_msg_file
669
670			for d in pkg pkgdefs; do
671				if [ ! -f "$SRC/$d/Makefile" ]; then
672					continue
673				fi
674
675				egrep "${MAKE}|ERROR|WARNING" $SRC/$d/${INSTALLOG}.out | \
676					grep ':' | \
677					grep -v PSTAMP | \
678					egrep -v "Ignoring unknown host" \
679					>> $mail_msg_file
680			done
681		else
682			#
683			# Handle it gracefully if -p was set but there are
684			# neither pkg nor pkgdefs directories.
685			#
686			echo "\n==== No $LABEL packages to build ====\n" \
687				>> $LOGFILE
688		fi
689	else
690		echo "\n==== Not creating $LABEL packages ====\n" >> $LOGFILE
691	fi
692
693	ROOT=$ORIGROOT
694}
695
696# Usage: dolint /dir y|n
697# Arg. 2 is a flag to turn on/off the lint diff output
698function dolint {
699	if [ ! -d "$1" ]; then
700		echo "dolint error: $1 is not a directory"
701		exit 1
702	fi
703
704	if [ "$2" != "y" -a "$2" != "n" ]; then
705		echo "dolint internal error: $2 should be 'y' or 'n'"
706		exit 1
707	fi
708
709	lintdir=$1
710	dodiff=$2
711	base=`basename $lintdir`
712	LINTOUT=$lintdir/lint-${MACH}.out
713	LINTNOISE=$lintdir/lint-noise-${MACH}
714	export ENVLDLIBS1=`myldlibs $ROOT`
715	export ENVCPPFLAGS1=`myheaders $ROOT`
716
717	set_debug_build_flags
718
719	#
720	#	'$MAKE lint' in $lintdir
721	#
722	echo "\n==== Begin '$MAKE lint' of $base at `date` ====\n" >> $LOGFILE
723
724	# remove old lint.out
725	rm -f $lintdir/lint.out $lintdir/lint-noise.out
726	if [ -f $lintdir/lint-noise.ref ]; then
727		mv $lintdir/lint-noise.ref ${LINTNOISE}.ref
728	fi
729
730	rm -f $LINTOUT
731	cd $lintdir
732	#
733	# Remove all .ln files to ensure a full reference file
734	#
735	rm -f Nothing_to_remove \
736	    `find . \( -name SCCS -o -name .hg -o -name .svn -o -name .git \) \
737	    	-prune -o -type f -name '*.ln' -print `
738
739	/bin/time $MAKE -ek lint 2>&1 | \
740	    tee -a $LINTOUT >> $LOGFILE
741	echo "\n==== '$MAKE lint' of $base ERRORS ====\n" >> $mail_msg_file
742	grep "$MAKE:" $LINTOUT |
743		egrep -v "Ignoring unknown host" \
744		>> $mail_msg_file
745
746	echo "\n==== Ended '$MAKE lint' of $base at `date` ====\n" >> $LOGFILE
747
748	echo "\n==== Elapsed time of '$MAKE lint' of $base ====\n" \
749		>>$mail_msg_file
750	tail -3  $LINTOUT >>$mail_msg_file
751
752	rm -f ${LINTNOISE}.ref
753	if [ -f ${LINTNOISE}.out ]; then
754		mv ${LINTNOISE}.out ${LINTNOISE}.ref
755	fi
756        grep : $LINTOUT | \
757		egrep -v '^(real|user|sys)' |
758		egrep -v '(library construction)' | \
759		egrep -v ': global crosschecks' | \
760		egrep -v 'Ignoring unknown host' | \
761		egrep -v '\.c:$' | \
762		sort | uniq > ${LINTNOISE}.out
763	if [ ! -f ${LINTNOISE}.ref ]; then
764		cp ${LINTNOISE}.out ${LINTNOISE}.ref
765	fi
766	if [ "$dodiff" != "n" ]; then
767		echo "\n==== lint warnings $base ====\n" \
768			>>$mail_msg_file
769		# should be none, though there are a few that were filtered out
770		# above
771		egrep -i '(warning|lint):' ${LINTNOISE}.out \
772			| sort | uniq >> $mail_msg_file
773		echo "\n==== lint noise differences $base ====\n" \
774			>> $mail_msg_file
775		diff ${LINTNOISE}.ref ${LINTNOISE}.out \
776			>> $mail_msg_file
777	fi
778}
779
780# Install proto area from IHV build
781
782function copy_ihv_proto {
783
784	echo "\n==== Installing IHV proto area ====\n" \
785		>> $LOGFILE
786	if [ -d "$IA32_IHV_ROOT" ]; then
787		if [ ! -d "$ROOT" ]; then
788			echo "mkdir -p $ROOT" >> $LOGFILE
789			mkdir -p $ROOT
790		fi
791		echo "copying $IA32_IHV_ROOT to $ROOT\n" >> $LOGFILE
792		cd $IA32_IHV_ROOT
793		tar cf - . | (cd $ROOT; umask 0; tar xpf - ) 2>&1 >> $LOGFILE
794	else
795		echo "$IA32_IHV_ROOT: not found" >> $LOGFILE
796	fi
797
798	if [ "$MULTI_PROTO" = yes ]; then
799		if [ ! -d "$ROOT-nd" ]; then
800			echo "mkdir -p $ROOT-nd" >> $LOGFILE
801			mkdir -p $ROOT-nd
802		fi
803		# If there's a non-DEBUG version of the IHV proto area,
804		# copy it, but copy something if there's not.
805		if [ -d "$IA32_IHV_ROOT-nd" ]; then
806			echo "copying $IA32_IHV_ROOT-nd to $ROOT-nd\n" >> $LOGFILE
807			cd $IA32_IHV_ROOT-nd
808		elif [ -d "$IA32_IHV_ROOT" ]; then
809			echo "copying $IA32_IHV_ROOT to $ROOT-nd\n" >> $LOGFILE
810			cd $IA32_IHV_ROOT
811		else
812			echo "$IA32_IHV_ROOT{-nd,}: not found" >> $LOGFILE
813			return
814		fi
815		tar cf - . | (cd $ROOT-nd; umask 0; tar xpf - ) 2>&1 >> $LOGFILE
816	fi
817}
818
819# Install IHV packages in PKGARCHIVE
820# usage: copy_ihv_pkgs LABEL SUFFIX
821function copy_ihv_pkgs {
822	LABEL=$1
823	SUFFIX=$2
824	# always use non-DEBUG IHV packages
825	IA32_IHV_PKGS=${IA32_IHV_PKGS_ORIG}-nd
826	PKGARCHIVE=${PKGARCHIVE_ORIG}${SUFFIX}
827
828	echo "\n==== Installing IHV packages from $IA32_IHV_PKGS ($LABEL) ====\n" \
829		>> $LOGFILE
830	if [ -d "$IA32_IHV_PKGS" ]; then
831		cd $IA32_IHV_PKGS
832		tar cf - * | \
833		   (cd $PKGARCHIVE; umask 0; tar xpf - ) 2>&1 >> $LOGFILE
834	else
835		echo "$IA32_IHV_PKGS: not found" >> $LOGFILE
836	fi
837
838	echo "\n==== Installing IHV packages from $IA32_IHV_BINARY_PKGS ($LABEL) ====\n" \
839		>> $LOGFILE
840	if [ -d "$IA32_IHV_BINARY_PKGS" ]; then
841		cd $IA32_IHV_BINARY_PKGS
842		tar cf - * | \
843		    (cd $PKGARCHIVE; umask 0; tar xpf - ) 2>&1 >> $LOGFILE
844	else
845		echo "$IA32_IHV_BINARY_PKGS: not found" >> $LOGFILE
846	fi
847}
848
849#
850# Build and install the onbld tools.
851#
852# usage: build_tools DESTROOT
853#
854# returns non-zero status if the build was successful.
855#
856function build_tools {
857	DESTROOT=$1
858
859	INSTALLOG=install-${MACH}
860
861	echo "\n==== Building tools at `date` ====\n" \
862		>> $LOGFILE
863
864	rm -f ${TOOLS}/${INSTALLOG}.out
865	cd ${TOOLS}
866	/bin/time $MAKE TOOLS_PROTO=${DESTROOT} -e install 2>&1 | \
867	    tee -a ${TOOLS}/${INSTALLOG}.out >> $LOGFILE
868
869	echo "\n==== Tools build errors ====\n" >> $mail_msg_file
870
871	egrep ":" ${TOOLS}/${INSTALLOG}.out |
872		egrep -e "(${MAKE}:|[ 	]error[: 	\n])" | \
873		egrep -v "Ignoring unknown host" | \
874		egrep -v warning >> $mail_msg_file
875	return $?
876}
877
878#
879# Set up to use locally installed tools.
880#
881# usage: use_tools TOOLSROOT
882#
883function use_tools {
884	TOOLSROOT=$1
885
886	#
887	# If we're not building ON workspace, then the TOOLSROOT
888	# settings here are clearly ignored by the workspace
889	# makefiles, prepending nonexistent directories to PATH is
890	# harmless, and we clearly do not wish to override
891	# ONBLD_TOOLS.
892	#
893	# If we're building an ON workspace, then the prepended PATH
894	# elements should supercede the preexisting ONBLD_TOOLS paths,
895	# and we want to override ONBLD_TOOLS to catch the tools that
896	# don't have specific path env vars here.
897	#
898	# So the only conditional behavior is overriding ONBLD_TOOLS,
899	# and we check for "an ON workspace" by looking for
900	# ${TOOLSROOT}/opt/onbld.
901	#
902
903	STABS=${TOOLSROOT}/opt/onbld/bin/${MACH}/stabs
904	export STABS
905	CTFSTABS=${TOOLSROOT}/opt/onbld/bin/${MACH}/ctfstabs
906	export CTFSTABS
907	GENOFFSETS=${TOOLSROOT}/opt/onbld/bin/genoffsets
908	export GENOFFSETS
909
910	CTFCONVERT=${TOOLSROOT}/opt/onbld/bin/${MACH}/ctfconvert
911	export CTFCONVERT
912	CTFMERGE=${TOOLSROOT}/opt/onbld/bin/${MACH}/ctfmerge
913	export CTFMERGE
914
915	CTFCVTPTBL=${TOOLSROOT}/opt/onbld/bin/ctfcvtptbl
916	export CTFCVTPTBL
917	CTFFINDMOD=${TOOLSROOT}/opt/onbld/bin/ctffindmod
918	export CTFFINDMOD
919
920	if [ "$VERIFY_ELFSIGN" = "y" ]; then
921		ELFSIGN=${TOOLSROOT}/opt/onbld/bin/elfsigncmp
922	else
923		ELFSIGN=${TOOLSROOT}/opt/onbld/bin/${MACH}/elfsign
924	fi
925	export ELFSIGN
926
927	PATH="${TOOLSROOT}/opt/onbld/bin/${MACH}:${PATH}"
928	PATH="${TOOLSROOT}/opt/onbld/bin:${PATH}"
929	export PATH
930
931	if [ -d "${TOOLSROOT}/opt/onbld" ]; then
932		ONBLD_TOOLS=${TOOLSROOT}/opt/onbld
933		export ONBLD_TOOLS
934	fi
935
936	echo "\n==== New environment settings. ====\n" >> $LOGFILE
937	echo "STABS=${STABS}" >> $LOGFILE
938	echo "CTFSTABS=${CTFSTABS}" >> $LOGFILE
939	echo "CTFCONVERT=${CTFCONVERT}" >> $LOGFILE
940	echo "CTFMERGE=${CTFMERGE}" >> $LOGFILE
941	echo "CTFCVTPTBL=${CTFCVTPTBL}" >> $LOGFILE
942	echo "CTFFINDMOD=${CTFFINDMOD}" >> $LOGFILE
943	echo "ELFSIGN=${ELFSIGN}" >> $LOGFILE
944	echo "PATH=${PATH}" >> $LOGFILE
945	echo "ONBLD_TOOLS=${ONBLD_TOOLS}" >> $LOGFILE
946}
947
948function staffer {
949	if [ $ISUSER -ne 0 ]; then
950		"$@"
951	else
952		arg="\"$1\""
953		shift
954		for i
955		do
956			arg="$arg \"$i\""
957		done
958		eval su $STAFFER -c \'$arg\'
959	fi
960}
961
962#
963# Verify that the closed tree is present if it needs to be.
964# Sets CLOSED_IS_PRESENT for future use.
965#
966function check_closed_tree {
967	if [ -z "$CLOSED_IS_PRESENT" ]; then
968		if [ -d $CODEMGR_WS/usr/closed ]; then
969			CLOSED_IS_PRESENT="yes"
970		else
971			CLOSED_IS_PRESENT="no"
972		fi
973		export CLOSED_IS_PRESENT
974	fi
975	if [[ "$CLOSED_IS_PRESENT" = no && ! -d "$ON_CLOSED_BINS" ]]; then
976		#
977		# If it's an old (pre-split) tree or an empty
978		# workspace, don't complain.
979		#
980		if grep -s CLOSED_BUILD $SRC/Makefile.master > /dev/null; then
981			echo "If the closed sources are not present," \
982			    "ON_CLOSED_BINS"
983			echo "must point to the closed binaries tree."
984			build_ok=n
985			exit 1
986		fi
987	fi
988}
989
990function obsolete_build {
991    	echo "WARNING: Obsolete $1 build requested; request will be ignored"
992}
993
994#
995# wrapper over wsdiff.
996# usage: do_wsdiff LABEL OLDPROTO NEWPROTO
997#
998function do_wsdiff {
999	label=$1
1000	oldproto=$2
1001	newproto=$3
1002
1003	wsdiff="wsdiff"
1004	[ "$t_FLAG" = y ] && wsdiff="wsdiff -t"
1005
1006	echo "\n==== Getting object changes since last build at `date`" \
1007	    "($label) ====\n" | tee -a $LOGFILE >> $mail_msg_file
1008	$wsdiff -s -r ${TMPDIR}/wsdiff.results $oldproto $newproto 2>&1 | \
1009		    tee -a $LOGFILE >> $mail_msg_file
1010	echo "\n==== Object changes determined at `date` ($label) ====\n" | \
1011	    tee -a $LOGFILE >> $mail_msg_file
1012}
1013
1014#
1015# Functions for setting build flags (DEBUG/non-DEBUG).  Keep them
1016# together.
1017#
1018
1019function set_non_debug_build_flags {
1020	export INTERNAL_RELEASE_BUILD ; INTERNAL_RELEASE_BUILD=
1021	export RELEASE_BUILD ; RELEASE_BUILD=
1022	unset EXTRA_OPTIONS
1023	unset EXTRA_CFLAGS
1024}
1025
1026function set_debug_build_flags {
1027	export INTERNAL_RELEASE_BUILD ; INTERNAL_RELEASE_BUILD=
1028	unset RELEASE_BUILD
1029	unset EXTRA_OPTIONS
1030	unset EXTRA_CFLAGS
1031}
1032
1033
1034MACH=`uname -p`
1035
1036if [ "$OPTHOME" = "" ]; then
1037	OPTHOME=/opt
1038	export OPTHOME
1039fi
1040if [ "$TEAMWARE" = "" ]; then
1041	TEAMWARE=$OPTHOME/teamware
1042	export TEAMWARE
1043fi
1044
1045USAGE='Usage: nightly [-in] [+t] [-V VERS ] [ -S E|D|H|O ] <env_file>
1046
1047Where:
1048	-i	Fast incremental options (no clobber, lint, check)
1049	-n      Do not do a bringover
1050	+t	Use the build tools in $ONBLD_TOOLS/bin
1051	-V VERS set the build version string to VERS
1052	-S	Build a variant of the source product
1053		E - build exportable source
1054		D - build domestic source (exportable + crypt)
1055		H - build hybrid source (binaries + deleted source)
1056		O - build (only) open source
1057
1058	<env_file>  file in Bourne shell syntax that sets and exports
1059	variables that configure the operation of this script and many of
1060	the scripts this one calls. If <env_file> does not exist,
1061	it will be looked for in $OPTHOME/onbld/env.
1062
1063non-DEBUG is the default build type. Build options can be set in the
1064NIGHTLY_OPTIONS variable in the <env_file> as follows:
1065
1066	-A	check for ABI differences in .so files
1067	-C	check for cstyle/hdrchk errors
1068	-D	do a build with DEBUG on
1069	-F	do _not_ do a non-DEBUG build
1070	-G	gate keeper default group of options (-au)
1071	-I	integration engineer default group of options (-ampu)
1072	-M	do not run pmodes (safe file permission checker)
1073	-N	do not run protocmp
1074	-O	generate OpenSolaris deliverables
1075	-R	default group of options for building a release (-mp)
1076	-U	update proto area in the parent
1077	-V VERS set the build version string to VERS
1078	-X	copy x86 IHV proto area
1079	-f	find unreferenced files
1080	-i	do an incremental build (no "make clobber")
1081	-l	do "make lint" in $LINTDIRS (default: $SRC y)
1082	-m	send mail to $MAILTO at end of build
1083	-n      do not do a bringover
1084	-o	build using root privileges to set OWNER/GROUP (old style)
1085	-p	create packages
1086	-r	check ELF runtime attributes in the proto area
1087	-t	build and use the tools in $SRC/tools (default setting)
1088	+t	Use the build tools in $ONBLD_TOOLS/bin
1089	-u	update proto_list_$MACH and friends in the parent workspace;
1090		when used with -f, also build an unrefmaster.out in the parent
1091	-w	report on differences between previous and current proto areas
1092	-z	compress cpio archives with gzip
1093	-W	Do not report warnings (freeware gate ONLY)
1094	-S	Build a variant of the source product
1095		E - build exportable source
1096		D - build domestic source (exportable + crypt)
1097		H - build hybrid source (binaries + deleted source)
1098		O - build (only) open source
1099'
1100#
1101#	-x	less public handling of xmod source for the source product
1102#
1103#	A log file will be generated under the name $LOGFILE
1104#	for partially completed build and log.`date '+%F'`
1105#	in the same directory for fully completed builds.
1106#
1107
1108# default values for low-level FLAGS; G I R are group FLAGS
1109A_FLAG=n
1110C_FLAG=n
1111D_FLAG=n
1112F_FLAG=n
1113f_FLAG=n
1114i_FLAG=n; i_CMD_LINE_FLAG=n
1115l_FLAG=n
1116M_FLAG=n
1117m_FLAG=n
1118N_FLAG=n
1119n_FLAG=n
1120O_FLAG=n
1121o_FLAG=n
1122P_FLAG=n
1123p_FLAG=n
1124r_FLAG=n
1125T_FLAG=n
1126t_FLAG=y
1127U_FLAG=n
1128u_FLAG=n
1129V_FLAG=n
1130W_FLAG=n
1131w_FLAG=n
1132X_FLAG=n
1133SD_FLAG=n
1134SE_FLAG=n
1135SH_FLAG=n
1136SO_FLAG=n
1137#
1138XMOD_OPT=
1139#
1140build_ok=y
1141
1142function is_source_build {
1143	[ "$SE_FLAG" = "y" -o "$SD_FLAG" = "y" -o \
1144	    "$SH_FLAG" = "y" -o "$SO_FLAG" = "y" ]
1145	return $?
1146}
1147
1148#
1149# examine arguments
1150#
1151
1152#
1153# single function for setting -S flag and doing error checking.
1154# usage: set_S_flag <type>
1155# where <type> is the source build type ("E", "D", ...).
1156#
1157function set_S_flag {
1158	if is_source_build; then
1159		echo "Can only build one source variant at a time."
1160		exit 1
1161	fi
1162	if [ "$1" = "E" ]; then
1163		SE_FLAG=y
1164	elif [ "$1" = "D" ]; then
1165		SD_FLAG=y
1166	elif [ "$1" = "H" ]; then
1167		SH_FLAG=y
1168	elif [ "$1" = "O" ]; then
1169		SO_FLAG=y
1170	else
1171		echo "$USAGE"
1172		exit 1
1173	fi
1174}
1175
1176OPTIND=1
1177while getopts +inS:tV: FLAG
1178do
1179	case $FLAG in
1180	  i )	i_FLAG=y; i_CMD_LINE_FLAG=y
1181		;;
1182	  n )	n_FLAG=y
1183		;;
1184	  S )
1185		set_S_flag $OPTARG
1186		;;
1187	 +t )	t_FLAG=n
1188		;;
1189	  V )	V_FLAG=y
1190		V_ARG="$OPTARG"
1191		;;
1192	 \? )	echo "$USAGE"
1193		exit 1
1194		;;
1195	esac
1196done
1197
1198# correct argument count after options
1199shift `expr $OPTIND - 1`
1200
1201# test that the path to the environment-setting file was given
1202if [ $# -ne 1 ]; then
1203	echo "$USAGE"
1204	exit 1
1205fi
1206
1207# check if user is running nightly as root
1208# ISUSER is set non-zero if an ordinary user runs nightly, or is zero
1209# when root invokes nightly.
1210/usr/bin/id | grep '^uid=0(' >/dev/null 2>&1
1211ISUSER=$?;	export ISUSER
1212
1213#
1214# force locale to C
1215LC_COLLATE=C;	export LC_COLLATE
1216LC_CTYPE=C;	export LC_CTYPE
1217LC_MESSAGES=C;	export LC_MESSAGES
1218LC_MONETARY=C;	export LC_MONETARY
1219LC_NUMERIC=C;	export LC_NUMERIC
1220LC_TIME=C;	export LC_TIME
1221
1222# clear environment variables we know to be bad for the build
1223unset LD_OPTIONS
1224unset LD_AUDIT		LD_AUDIT_32		LD_AUDIT_64
1225unset LD_BIND_NOW	LD_BIND_NOW_32		LD_BIND_NOW_64
1226unset LD_BREADTH	LD_BREADTH_32		LD_BREADTH_64
1227unset LD_CONFIG		LD_CONFIG_32		LD_CONFIG_64
1228unset LD_DEBUG		LD_DEBUG_32		LD_DEBUG_64
1229unset LD_DEMANGLE	LD_DEMANGLE_32		LD_DEMANGLE_64
1230unset LD_FLAGS		LD_FLAGS_32		LD_FLAGS_64
1231unset LD_LIBRARY_PATH	LD_LIBRARY_PATH_32	LD_LIBRARY_PATH_64
1232unset LD_LOADFLTR	LD_LOADFLTR_32		LD_LOADFLTR_64
1233unset LD_NOAUDIT	LD_NOAUDIT_32		LD_NOAUDIT_64
1234unset LD_NOAUXFLTR	LD_NOAUXFLTR_32		LD_NOAUXFLTR_64
1235unset LD_NOCONFIG	LD_NOCONFIG_32		LD_NOCONFIG_64
1236unset LD_NODIRCONFIG	LD_NODIRCONFIG_32	LD_NODIRCONFIG_64
1237unset LD_NODIRECT	LD_NODIRECT_32		LD_NODIRECT_64
1238unset LD_NOLAZYLOAD	LD_NOLAZYLOAD_32	LD_NOLAZYLOAD_64
1239unset LD_NOOBJALTER	LD_NOOBJALTER_32	LD_NOOBJALTER_64
1240unset LD_NOVERSION	LD_NOVERSION_32		LD_NOVERSION_64
1241unset LD_ORIGIN		LD_ORIGIN_32		LD_ORIGIN_64
1242unset LD_PRELOAD	LD_PRELOAD_32		LD_PRELOAD_64
1243unset LD_PROFILE	LD_PROFILE_32		LD_PROFILE_64
1244
1245unset CONFIG
1246unset GROUP
1247unset OWNER
1248unset REMOTE
1249unset ENV
1250unset ARCH
1251unset CLASSPATH
1252unset NAME
1253
1254#
1255# To get ONBLD_TOOLS from the environment, it must come from the env file.
1256# If it comes interactively, it is generally TOOLS_PROTO, which will be
1257# clobbered before the compiler version checks, which will therefore fail.
1258#
1259unset ONBLD_TOOLS
1260
1261#
1262#	Setup environmental variables
1263#
1264if [ -f /etc/nightly.conf ]; then
1265	. /etc/nightly.conf
1266fi
1267
1268if [ -f $1 ]; then
1269	if [[ $1 = */* ]]; then
1270		. $1
1271	else
1272		. ./$1
1273	fi
1274else
1275	if [ -f $OPTHOME/onbld/env/$1 ]; then
1276		. $OPTHOME/onbld/env/$1
1277	else
1278		echo "Cannot find env file as either $1 or $OPTHOME/onbld/env/$1"
1279		exit 1
1280	fi
1281fi
1282
1283# contents of stdenv.sh inserted after next line:
1284# STDENV_START
1285# STDENV_END
1286
1287# Check if we have sufficient data to continue...
1288[[ -v CODEMGR_WS ]] || fatal_error "Error: Variable CODEMGR_WS not set."
1289if  [[ "${NIGHTLY_OPTIONS}" == ~(F)n ]] ; then
1290	# Check if the gate data are valid if we don't do a "bringover" below
1291	[[ -d "${CODEMGR_WS}" ]] || \
1292		fatal_error "Error: ${CODEMGR_WS} is not a directory."
1293	[[ -f "${CODEMGR_WS}/usr/src/Makefile" ]] || \
1294		fatal_error "Error: ${CODEMGR_WS}/usr/src/Makefile not found."
1295fi
1296
1297#
1298# place ourselves in a new task, respecting BUILD_PROJECT if set.
1299#
1300if [ -z "$BUILD_PROJECT" ]; then
1301	/usr/bin/newtask -c $$
1302else
1303	/usr/bin/newtask -c $$ -p $BUILD_PROJECT
1304fi
1305
1306ps -o taskid= -p $$ | read build_taskid
1307ps -o project= -p $$ | read build_project
1308
1309#
1310# See if NIGHTLY_OPTIONS is set
1311#
1312if [ "$NIGHTLY_OPTIONS" = "" ]; then
1313	NIGHTLY_OPTIONS="-aBm"
1314fi
1315
1316#
1317# If BRINGOVER_WS was not specified, let it default to CLONE_WS
1318#
1319if [ "$BRINGOVER_WS" = "" ]; then
1320	BRINGOVER_WS=$CLONE_WS
1321fi
1322
1323#
1324# If CLOSED_BRINGOVER_WS was not specified, let it default to CLOSED_CLONE_WS
1325#
1326if [ "$CLOSED_BRINGOVER_WS" = "" ]; then
1327	CLOSED_BRINGOVER_WS=$CLOSED_CLONE_WS
1328fi
1329
1330#
1331# If BRINGOVER_FILES was not specified, default to usr
1332#
1333if [ "$BRINGOVER_FILES" = "" ]; then
1334	BRINGOVER_FILES="usr"
1335fi
1336
1337#
1338# If the closed sources are not present, the closed binaries must be
1339# present for the build to succeed.  If there's no pointer to the
1340# closed binaries, flag that now, rather than forcing the user to wait
1341# a couple hours (or more) to find out.
1342#
1343orig_closed_is_present="$CLOSED_IS_PRESENT"
1344check_closed_tree
1345
1346#
1347# Note: changes to the option letters here should also be applied to the
1348#	bldenv script.  `d' is listed for backward compatibility.
1349#
1350NIGHTLY_OPTIONS=-${NIGHTLY_OPTIONS#-}
1351OPTIND=1
1352while getopts +ABCDdFfGIilMmNnOoPpRrS:TtUuWwXxz FLAG $NIGHTLY_OPTIONS
1353do
1354	case $FLAG in
1355	  A )	A_FLAG=y
1356		#
1357		# If ELF_DATA_BASELINE_DIR is not defined, and we are on SWAN
1358		# (based on CLOSED_IS_PRESENT), then refuse to run. The value
1359		# of ELF version checking is greatly enhanced by including
1360		# the baseline gate comparison.
1361		if [ "$CLOSED_IS_PRESENT" = 'yes' -a \
1362		     "$ELF_DATA_BASELINE_DIR" = '' ]; then
1363			echo "ELF_DATA_BASELINE_DIR must be set if the A" \
1364			    "flag is present in\nNIGHTLY_OPTIONS and closed" \
1365			    "sources are present. Update environment file."
1366			exit 1;
1367		fi
1368		;;
1369	  B )	D_FLAG=y
1370		;; # old version of D
1371	  C )	C_FLAG=y
1372		;;
1373	  D )	D_FLAG=y
1374		;;
1375	  F )	F_FLAG=y
1376		;;
1377	  f )	f_FLAG=y
1378		;;
1379	  G )   u_FLAG=y
1380		;;
1381	  I )	m_FLAG=y
1382		p_FLAG=y
1383		u_FLAG=y
1384		;;
1385	  i )	i_FLAG=y
1386		;;
1387	  l )	l_FLAG=y
1388		;;
1389	  M )	M_FLAG=y
1390		;;
1391	  m )	m_FLAG=y
1392		;;
1393	  N )	N_FLAG=y
1394		;;
1395	  n )	n_FLAG=y
1396		;;
1397	  O )	O_FLAG=y
1398		;;
1399	  o )	o_FLAG=y
1400		;;
1401	  P )	P_FLAG=y
1402		;; # obsolete
1403	  p )	p_FLAG=y
1404		;;
1405	  R )	m_FLAG=y
1406		p_FLAG=y
1407		;;
1408	  r )	r_FLAG=y
1409		;;
1410	  S )
1411		set_S_flag $OPTARG
1412		;;
1413	  T )	T_FLAG=y
1414		;; # obsolete
1415	 +t )	t_FLAG=n
1416		;;
1417	  U )   if [ -z "${PARENT_ROOT}" ]; then
1418			echo "PARENT_ROOT must be set if the U flag is" \
1419			    "present in NIGHTLY_OPTIONS."
1420			exit 1
1421		fi
1422		NIGHTLY_PARENT_ROOT=$PARENT_ROOT
1423		if [ -n "${PARENT_TOOLS_ROOT}" ]; then
1424			NIGHTLY_PARENT_TOOLS_ROOT=$PARENT_TOOLS_ROOT
1425		fi
1426		U_FLAG=y
1427		;;
1428	  u )	u_FLAG=y
1429		;;
1430	  W )	W_FLAG=y
1431		;;
1432
1433	  w )	w_FLAG=y
1434		;;
1435	  X )	# now that we no longer need realmode builds, just
1436		# copy IHV packages.  only meaningful on x86.
1437		if [ "$MACH" = "i386" ]; then
1438			X_FLAG=y
1439		fi
1440		;;
1441	  x )	XMOD_OPT="-x"
1442		;;
1443	 \? )	echo "$USAGE"
1444		exit 1
1445		;;
1446	esac
1447done
1448
1449if [ $ISUSER -ne 0 ]; then
1450	if [ "$o_FLAG" = "y" ]; then
1451		echo "Old-style build requires root permission."
1452		exit 1
1453	fi
1454
1455	# Set default value for STAFFER, if needed.
1456	if [ -z "$STAFFER" -o "$STAFFER" = "nobody" ]; then
1457		STAFFER=`/usr/xpg4/bin/id -un`
1458		export STAFFER
1459	fi
1460fi
1461
1462if [ -z "$MAILTO" -o "$MAILTO" = "nobody" ]; then
1463	MAILTO=$STAFFER
1464	export MAILTO
1465fi
1466
1467PATH="$OPTHOME/onbld/bin:$OPTHOME/onbld/bin/${MACH}:/usr/ccs/bin"
1468PATH="$PATH:$OPTHOME/SUNWspro/bin:$TEAMWARE/bin:/usr/bin:/usr/sbin:/usr/ucb"
1469PATH="$PATH:/usr/openwin/bin:/usr/sfw/bin:/opt/sfw/bin:."
1470export PATH
1471
1472# roots of source trees, both relative to $SRC and absolute.
1473relsrcdirs="."
1474if [[ -d $CODEMGR_WS/usr/closed && "$CLOSED_IS_PRESENT" != no ]]; then
1475	relsrcdirs="$relsrcdirs ../closed"
1476fi
1477abssrcdirs=""
1478for d in $relsrcdirs; do
1479	abssrcdirs="$abssrcdirs $SRC/$d"
1480done
1481
1482unset CH
1483if [ "$o_FLAG" = "y" ]; then
1484# root invoked old-style build -- make sure it works as it always has
1485# by exporting 'CH'.  The current Makefile.master doesn't use this, but
1486# the old ones still do.
1487	PROTOCMPTERSE="protocmp.terse"
1488	CH=
1489	export CH
1490else
1491	PROTOCMPTERSE="protocmp.terse -gu"
1492fi
1493POUND_SIGN="#"
1494# have we set RELEASE_DATE in our env file?
1495if [ -z "$RELEASE_DATE" ]; then
1496	RELEASE_DATE=$(LC_ALL=C date +"%B %Y")
1497fi
1498BUILD_DATE=$(LC_ALL=C date +%Y-%b-%d)
1499BASEWSDIR=$(basename $CODEMGR_WS)
1500DEV_CM="\"@(#)SunOS Internal Development: $LOGNAME $BUILD_DATE [$BASEWSDIR]\""
1501
1502# we export POUND_SIGN, RELEASE_DATE and DEV_CM to speed up the build process
1503# by avoiding repeated shell invocations to evaluate Makefile.master definitions.
1504# we export o_FLAG and X_FLAG for use by makebfu, and by usr/src/pkg/Makefile
1505export o_FLAG X_FLAG POUND_SIGN RELEASE_DATE DEV_CM
1506
1507maketype="distributed"
1508MAKE=dmake
1509# get the dmake version string alone
1510DMAKE_VERSION=$( $MAKE -v )
1511DMAKE_VERSION=${DMAKE_VERSION#*: }
1512# focus in on just the dotted version number alone
1513DMAKE_MAJOR=$( echo $DMAKE_VERSION | \
1514	sed -e 's/.*\<\([^.]*\.[^   ]*\).*$/\1/' )
1515# extract the second (or final) integer
1516DMAKE_MINOR=${DMAKE_MAJOR#*.}
1517DMAKE_MINOR=${DMAKE_MINOR%%.*}
1518# extract the first integer
1519DMAKE_MAJOR=${DMAKE_MAJOR%%.*}
1520CHECK_DMAKE=${CHECK_DMAKE:-y}
1521# x86 was built on the 12th, sparc on the 13th.
1522if [ "$CHECK_DMAKE" = "y" -a \
1523     "$DMAKE_VERSION" != "Sun Distributed Make 7.3 2003/03/12" -a \
1524     "$DMAKE_VERSION" != "Sun Distributed Make 7.3 2003/03/13" -a \( \
1525     "$DMAKE_MAJOR" -lt 7 -o \
1526     "$DMAKE_MAJOR" -eq 7 -a "$DMAKE_MINOR" -lt 4 \) ]; then
1527	if [ -z "$DMAKE_VERSION" ]; then
1528		echo "$MAKE is missing."
1529		exit 1
1530	fi
1531	echo `whence $MAKE`" version is:"
1532	echo "  ${DMAKE_VERSION}"
1533	cat <<EOF
1534
1535This version may not be safe for use.  Either set TEAMWARE to a better
1536path or (if you really want to use this version of dmake anyway), add
1537the following to your environment to disable this check:
1538
1539  CHECK_DMAKE=n
1540EOF
1541	exit 1
1542fi
1543export PATH
1544export MAKE
1545
1546if [[ "$O_FLAG" = y ]]; then
1547	export TONICBUILD=""
1548else
1549	export TONICBUILD="#"
1550fi
1551
1552if [ "${SUNWSPRO}" != "" ]; then
1553	PATH="${SUNWSPRO}/bin:$PATH"
1554	export PATH
1555fi
1556
1557hostname=$(uname -n)
1558if [[ $DMAKE_MAX_JOBS != +([0-9]) || $DMAKE_MAX_JOBS -eq 0 ]]
1559then
1560	maxjobs=
1561	if [[ -f $HOME/.make.machines ]]
1562	then
1563		# Note: there is a hard tab and space character in the []s
1564		# below.
1565		egrep -i "^[ 	]*$hostname[ 	\.]" \
1566			$HOME/.make.machines | read host jobs
1567		maxjobs=${jobs##*=}
1568	fi
1569
1570	if [[ $maxjobs != +([0-9]) || $maxjobs -eq 0 ]]
1571	then
1572		# default
1573		maxjobs=4
1574	fi
1575
1576	export DMAKE_MAX_JOBS=$maxjobs
1577fi
1578
1579DMAKE_MODE=parallel;
1580export DMAKE_MODE
1581
1582if [ -z "${ROOT}" ]; then
1583	echo "ROOT must be set."
1584	exit 1
1585fi
1586
1587#
1588# if -V flag was given, reset VERSION to V_ARG
1589#
1590if [ "$V_FLAG" = "y" ]; then
1591	VERSION=$V_ARG
1592fi
1593
1594#
1595# Check for IHV root for copying ihv proto area
1596#
1597if [ "$X_FLAG" = "y" ]; then
1598        if [ "$IA32_IHV_ROOT" = "" ]; then
1599		echo "IA32_IHV_ROOT: must be set for copying ihv proto"
1600		args_ok=n
1601        fi
1602        if [ ! -d "$IA32_IHV_ROOT" ]; then
1603                echo "$IA32_IHV_ROOT: not found"
1604                args_ok=n
1605        fi
1606        if [ "$IA32_IHV_WS" = "" ]; then
1607		echo "IA32_IHV_WS: must be set for copying ihv proto"
1608		args_ok=n
1609        fi
1610        if [ ! -d "$IA32_IHV_WS" ]; then
1611                echo "$IA32_IHV_WS: not found"
1612                args_ok=n
1613        fi
1614fi
1615
1616# Append source version
1617if [ "$SE_FLAG" = "y" ]; then
1618	VERSION="${VERSION}:EXPORT"
1619fi
1620
1621if [ "$SD_FLAG" = "y" ]; then
1622	VERSION="${VERSION}:DOMESTIC"
1623fi
1624
1625if [ "$SH_FLAG" = "y" ]; then
1626	VERSION="${VERSION}:MODIFIED_SOURCE_PRODUCT"
1627fi
1628
1629if [ "$SO_FLAG" = "y" ]; then
1630	VERSION="${VERSION}:OPEN_ONLY"
1631fi
1632
1633TMPDIR="/tmp/nightly.tmpdir.$$"
1634export TMPDIR
1635rm -rf ${TMPDIR}
1636mkdir -p $TMPDIR || exit 1
1637chmod 777 $TMPDIR
1638
1639#
1640# Keep elfsign's use of pkcs11_softtoken from looking in the user home
1641# directory, which doesn't always work.   Needed until all build machines
1642# have the fix for 6271754
1643#
1644SOFTTOKEN_DIR=$TMPDIR
1645export SOFTTOKEN_DIR
1646
1647#
1648# Tools should only be built non-DEBUG.  Keep track of the tools proto
1649# area path relative to $TOOLS, because the latter changes in an
1650# export build.
1651#
1652# TOOLS_PROTO is included below for builds other than usr/src/tools
1653# that look for this location.  For usr/src/tools, this will be
1654# overridden on the $MAKE command line in build_tools().
1655#
1656TOOLS=${SRC}/tools
1657TOOLS_PROTO_REL=proto/root_${MACH}-nd
1658TOOLS_PROTO=${TOOLS}/${TOOLS_PROTO_REL};	export TOOLS_PROTO
1659
1660unset   CFLAGS LD_LIBRARY_PATH LDFLAGS
1661
1662# create directories that are automatically removed if the nightly script
1663# fails to start correctly
1664function newdir {
1665	dir=$1
1666	toadd=
1667	while [ ! -d $dir ]; do
1668		toadd="$dir $toadd"
1669		dir=`dirname $dir`
1670	done
1671	torm=
1672	newlist=
1673	for dir in $toadd; do
1674		if staffer mkdir $dir; then
1675			newlist="$ISUSER $dir $newlist"
1676			torm="$dir $torm"
1677		else
1678			[ -z "$torm" ] || staffer rmdir $torm
1679			return 1
1680		fi
1681	done
1682	newdirlist="$newlist $newdirlist"
1683	return 0
1684}
1685newdirlist=
1686
1687[ -d $CODEMGR_WS ] || newdir $CODEMGR_WS || exit 1
1688
1689# since this script assumes the build is from full source, it nullifies
1690# variables likely to have been set by a "ws" script; nullification
1691# confines the search space for headers and libraries to the proto area
1692# built from this immediate source.
1693ENVLDLIBS1=
1694ENVLDLIBS2=
1695ENVLDLIBS3=
1696ENVCPPFLAGS1=
1697ENVCPPFLAGS2=
1698ENVCPPFLAGS3=
1699ENVCPPFLAGS4=
1700PARENT_ROOT=
1701
1702export ENVLDLIBS3 ENVCPPFLAGS1 ENVCPPFLAGS2 ENVCPPFLAGS3 ENVCPPFLAGS4 \
1703	PARENT_ROOT
1704
1705PKGARCHIVE_ORIG=$PKGARCHIVE
1706IA32_IHV_PKGS_ORIG=$IA32_IHV_PKGS
1707
1708#
1709# Juggle the logs and optionally send mail on completion.
1710#
1711
1712function logshuffle {
1713    	LLOG="$ATLOG/log.`date '+%F.%H:%M'`"
1714	if [ -f $LLOG -o -d $LLOG ]; then
1715	    	LLOG=$LLOG.$$
1716	fi
1717	mkdir $LLOG
1718	export LLOG
1719
1720	if [ "$build_ok" = "y" ]; then
1721		mv $ATLOG/proto_list_${MACH} $LLOG
1722
1723		if [ -f $ATLOG/proto_list_tools_${MACH} ]; then
1724			mv $ATLOG/proto_list_tools_${MACH} $LLOG
1725	        fi
1726
1727		if [ -f $TMPDIR/wsdiff.results ]; then
1728		    	mv $TMPDIR/wsdiff.results $LLOG
1729		fi
1730
1731		if [ -f $TMPDIR/wsdiff-nd.results ]; then
1732			mv $TMPDIR/wsdiff-nd.results $LLOG
1733		fi
1734	fi
1735
1736	#
1737	# Now that we're about to send mail, it's time to check the noise
1738	# file.  In the event that an error occurs beyond this point, it will
1739	# be recorded in the nightly.log file, but nowhere else.  This would
1740	# include only errors that cause the copying of the noise log to fail
1741	# or the mail itself not to be sent.
1742	#
1743
1744	exec >>$LOGFILE 2>&1
1745	if [ -s $build_noise_file ]; then
1746	    	echo "\n==== Nightly build noise ====\n" |
1747		    tee -a $LOGFILE >>$mail_msg_file
1748		cat $build_noise_file >>$LOGFILE
1749		cat $build_noise_file >>$mail_msg_file
1750		echo | tee -a $LOGFILE >>$mail_msg_file
1751	fi
1752	rm -f $build_noise_file
1753
1754	case "$build_ok" in
1755		y)
1756			state=Completed
1757			;;
1758		i)
1759			state=Interrupted
1760			;;
1761		*)
1762	    		state=Failed
1763			;;
1764	esac
1765	NIGHTLY_STATUS=$state
1766	export NIGHTLY_STATUS
1767
1768	run_hook POST_NIGHTLY $state
1769	run_hook SYS_POST_NIGHTLY $state
1770
1771	#
1772	# mailx(1) sets From: based on the -r flag
1773	# if it is given.
1774	#
1775	mailx_r=
1776	if [[ -n "${MAILFROM}" ]]; then
1777		mailx_r="-r ${MAILFROM}"
1778	fi
1779
1780	cat $build_time_file $build_environ_file $mail_msg_file \
1781	    > ${LLOG}/mail_msg
1782	if [ "$m_FLAG" = "y" ]; then
1783	    	cat ${LLOG}/mail_msg | /usr/bin/mailx ${mailx_r} -s \
1784	"Nightly ${MACH} Build of `basename ${CODEMGR_WS}` ${state}." \
1785			${MAILTO}
1786	fi
1787
1788	if [ "$u_FLAG" = "y" -a "$build_ok" = "y" ]; then
1789	    	staffer cp ${LLOG}/mail_msg $PARENT_WS/usr/src/mail_msg-${MACH}
1790		staffer cp $LOGFILE $PARENT_WS/usr/src/nightly-${MACH}.log
1791	fi
1792
1793	mv $LOGFILE $LLOG
1794}
1795
1796#
1797#	Remove the locks and temporary files on any exit
1798#
1799function cleanup {
1800    	logshuffle
1801
1802	[ -z "$lockfile" ] || staffer rm -f $lockfile
1803	[ -z "$atloglockfile" ] || rm -f $atloglockfile
1804	[ -z "$ulockfile" ] || staffer rm -f $ulockfile
1805	[ -z "$Ulockfile" ] || rm -f $Ulockfile
1806
1807	set -- $newdirlist
1808	while [ $# -gt 0 ]; do
1809		ISUSER=$1 staffer rmdir $2
1810		shift; shift
1811	done
1812	rm -rf $TMPDIR
1813}
1814
1815function cleanup_signal {
1816    	build_ok=i
1817	# this will trigger cleanup(), above.
1818	exit 1
1819}
1820
1821trap cleanup 0
1822trap cleanup_signal 1 2 3 15
1823
1824#
1825# Generic lock file processing -- make sure that the lock file doesn't
1826# exist.  If it does, it should name the build host and PID.  If it
1827# doesn't, then make sure we can create it.  Clean up locks that are
1828# known to be stale (assumes host name is unique among build systems
1829# for the workspace).
1830#
1831function create_lock {
1832	lockf=$1
1833	lockvar=$2
1834
1835	ldir=`dirname $lockf`
1836	[ -d $ldir ] || newdir $ldir || exit 1
1837	eval $lockvar=$lockf
1838
1839	while ! staffer ln -s $hostname.$STAFFER.$$ $lockf 2> /dev/null; do
1840		basews=`basename $CODEMGR_WS`
1841		ls -l $lockf | nawk '{print $NF}' | IFS=. read host user pid
1842		if [ "$host" != "$hostname" ]; then
1843			echo "$MACH build of $basews apparently" \
1844			    "already started by $user on $host as $pid."
1845			exit 1
1846		elif kill -s 0 $pid 2>/dev/null; then
1847			echo "$MACH build of $basews already started" \
1848			    "by $user as $pid."
1849			exit 1
1850		else
1851			# stale lock; clear it out and try again
1852			rm -f $lockf
1853		fi
1854	done
1855}
1856
1857#
1858# Return the list of interesting proto areas, depending on the current
1859# options.
1860#
1861function allprotos {
1862	typeset roots="$ROOT"
1863
1864	if [[ "$F_FLAG" = n && "$MULTI_PROTO" = yes ]]; then
1865		roots="$roots $ROOT-nd"
1866	fi
1867
1868	if [[ $O_FLAG = y ]]; then
1869		roots="$roots $ROOT-closed"
1870		[ $MULTI_PROTO = yes ] && roots="$roots $ROOT-nd-closed"
1871	fi
1872
1873	echo $roots
1874}
1875
1876# Ensure no other instance of this script is running on this host.
1877# LOCKNAME can be set in <env_file>, and is by default, but is not
1878# required due to the use of $ATLOG below.
1879if [ -n "$LOCKNAME" ]; then
1880	create_lock /tmp/$LOCKNAME "lockfile"
1881fi
1882#
1883# Create from one, two, or three other locks:
1884#	$ATLOG/nightly.lock
1885#		- protects against multiple builds in same workspace
1886#	$PARENT_WS/usr/src/nightly.$MACH.lock
1887#		- protects against multiple 'u' copy-backs
1888#	$NIGHTLY_PARENT_ROOT/nightly.lock
1889#		- protects against multiple 'U' copy-backs
1890#
1891# Overriding ISUSER to 1 causes the lock to be created as root if the
1892# script is run as root.  The default is to create it as $STAFFER.
1893ISUSER=1 create_lock $ATLOG/nightly.lock "atloglockfile"
1894if [ "$u_FLAG" = "y" ]; then
1895	create_lock $PARENT_WS/usr/src/nightly.$MACH.lock "ulockfile"
1896fi
1897if [ "$U_FLAG" = "y" ]; then
1898	# NIGHTLY_PARENT_ROOT is written as root if script invoked as root.
1899	ISUSER=1 create_lock $NIGHTLY_PARENT_ROOT/nightly.lock "Ulockfile"
1900fi
1901
1902# Locks have been taken, so we're doing a build and we're committed to
1903# the directories we may have created so far.
1904newdirlist=
1905
1906#
1907# Create mail_msg_file
1908#
1909mail_msg_file="${TMPDIR}/mail_msg"
1910touch $mail_msg_file
1911build_time_file="${TMPDIR}/build_time"
1912build_environ_file="${TMPDIR}/build_environ"
1913touch $build_environ_file
1914#
1915#	Move old LOGFILE aside
1916#	ATLOG directory already made by 'create_lock' above
1917#
1918if [ -f $LOGFILE ]; then
1919	mv -f $LOGFILE ${LOGFILE}-
1920fi
1921#
1922#	Build OsNet source
1923#
1924START_DATE=`date`
1925SECONDS=0
1926echo "\n==== Nightly $maketype build started:   $START_DATE ====" \
1927    | tee -a $LOGFILE > $build_time_file
1928
1929echo "\nBuild project:  $build_project\nBuild taskid:   $build_taskid" | \
1930    tee -a $mail_msg_file >> $LOGFILE
1931
1932# make sure we log only to the nightly build file
1933build_noise_file="${TMPDIR}/build_noise"
1934exec </dev/null >$build_noise_file 2>&1
1935
1936run_hook SYS_PRE_NIGHTLY
1937run_hook PRE_NIGHTLY
1938
1939echo "\n==== list of environment variables ====\n" >> $LOGFILE
1940env >> $LOGFILE
1941
1942echo "\n==== Nightly argument issues ====\n" | tee -a $mail_msg_file >> $LOGFILE
1943
1944if [ "$P_FLAG" = "y" ]; then
1945	obsolete_build GPROF | tee -a $mail_msg_file >> $LOGFILE
1946fi
1947
1948if [ "$T_FLAG" = "y" ]; then
1949	obsolete_build TRACE | tee -a $mail_msg_file >> $LOGFILE
1950fi
1951
1952if is_source_build; then
1953	if [ "$i_FLAG" = "y" -o "$i_CMD_LINE_FLAG" = "y" ]; then
1954		echo "WARNING: the -S flags do not support incremental" \
1955		    "builds; forcing clobber\n" | tee -a $mail_msg_file >> $LOGFILE
1956		i_FLAG=n
1957		i_CMD_LINE_FLAG=n
1958	fi
1959	if [ "$N_FLAG" = "n" ]; then
1960		echo "WARNING: the -S flags do not support protocmp;" \
1961		    "protocmp disabled\n" | \
1962		    tee -a $mail_msg_file >> $LOGFILE
1963		N_FLAG=y
1964	fi
1965	if [ "$l_FLAG" = "y" ]; then
1966		echo "WARNING: the -S flags do not support lint;" \
1967		    "lint disabled\n" | tee -a $mail_msg_file >> $LOGFILE
1968		l_FLAG=n
1969	fi
1970	if [ "$C_FLAG" = "y" ]; then
1971		echo "WARNING: the -S flags do not support cstyle;" \
1972		    "cstyle check disabled\n" | tee -a $mail_msg_file >> $LOGFILE
1973		C_FLAG=n
1974	fi
1975else
1976	if [ "$N_FLAG" = "y" ]; then
1977		if [ "$p_FLAG" = "y" ]; then
1978			cat <<EOF | tee -a $mail_msg_file >> $LOGFILE
1979WARNING: the p option (create packages) is set, but so is the N option (do
1980         not run protocmp); this is dangerous; you should unset the N option
1981EOF
1982		else
1983			cat <<EOF | tee -a $mail_msg_file >> $LOGFILE
1984Warning: the N option (do not run protocmp) is set; it probably shouldn't be
1985EOF
1986		fi
1987		echo "" | tee -a $mail_msg_file >> $LOGFILE
1988	fi
1989fi
1990
1991if [ "$D_FLAG" = "n" -a "$l_FLAG" = "y" ]; then
1992	#
1993	# In the past we just complained but went ahead with the lint
1994	# pass, even though the proto area was built non-DEBUG.  It's
1995	# unlikely that non-DEBUG headers will make a difference, but
1996	# rather than assuming it's a safe combination, force the user
1997	# to specify a DEBUG build.
1998	#
1999	echo "WARNING: DEBUG build not requested; disabling lint.\n" \
2000	    | tee -a $mail_msg_file >> $LOGFILE
2001	l_FLAG=n
2002fi
2003
2004if [ "$f_FLAG" = "y" ]; then
2005	if [ "$i_FLAG" = "y" ]; then
2006		echo "WARNING: the -f flag cannot be used during incremental" \
2007		    "builds; ignoring -f\n" | tee -a $mail_msg_file >> $LOGFILE
2008		f_FLAG=n
2009	fi
2010	if [ "${l_FLAG}${p_FLAG}" != "yy" ]; then
2011		echo "WARNING: the -f flag requires -l, and -p;" \
2012		    "ignoring -f\n" | tee -a $mail_msg_file >> $LOGFILE
2013		f_FLAG=n
2014	fi
2015fi
2016
2017if [ "$w_FLAG" = "y" -a ! -d $ROOT ]; then
2018	echo "WARNING: -w specified, but $ROOT does not exist;" \
2019	    "ignoring -w\n" | tee -a $mail_msg_file >> $LOGFILE
2020	w_FLAG=n
2021fi
2022
2023if [ "$t_FLAG" = "n" ]; then
2024	#
2025	# We're not doing a tools build, so make sure elfsign(1) is
2026	# new enough to safely sign non-crypto binaries.  We test
2027	# debugging output from elfsign to detect the old version.
2028	#
2029	newelfsigntest=`SUNW_CRYPTO_DEBUG=stderr /usr/bin/elfsign verify \
2030	    -e /usr/lib/security/pkcs11_softtoken.so.1 2>&1 \
2031	    | egrep algorithmOID`
2032	if [ -z "$newelfsigntest" ]; then
2033		echo "WARNING: /usr/bin/elfsign out of date;" \
2034		    "will only sign crypto modules\n" | \
2035		    tee -a $mail_msg_file >> $LOGFILE
2036		export ELFSIGN_OBJECT=true
2037	elif [ "$VERIFY_ELFSIGN" = "y" ]; then
2038		echo "WARNING: VERIFY_ELFSIGN=y requires" \
2039		    "the -t flag; ignoring VERIFY_ELFSIGN\n" | \
2040		    tee -a $mail_msg_file >> $LOGFILE
2041	fi
2042fi
2043
2044[ "$O_FLAG" = y ] && MULTI_PROTO=yes
2045
2046case $MULTI_PROTO in
2047yes|no)	;;
2048*)
2049	echo "WARNING: MULTI_PROTO is \"$MULTI_PROTO\"; " \
2050	    "should be \"yes\" or \"no\"." | tee -a $mail_msg_file >> $LOGFILE
2051	echo "Setting MULTI_PROTO to \"no\".\n" | \
2052	    tee -a $mail_msg_file >> $LOGFILE
2053	export MULTI_PROTO=no
2054	;;
2055esac
2056
2057echo "\n==== Build version ====\n" | tee -a $mail_msg_file >> $LOGFILE
2058echo $VERSION | tee -a $mail_msg_file >> $LOGFILE
2059
2060# Save the current proto area if we're comparing against the last build
2061if [ "$w_FLAG" = "y" -a -d "$ROOT" ]; then
2062    if [ -d "$ROOT.prev" ]; then
2063	rm -rf $ROOT.prev
2064    fi
2065    mv $ROOT $ROOT.prev
2066fi
2067
2068# Same for non-DEBUG proto area
2069if [ "$w_FLAG" = "y" -a "$MULTI_PROTO" = yes -a -d "$ROOT-nd" ]; then
2070	if [ -d "$ROOT-nd.prev" ]; then
2071		rm -rf $ROOT-nd.prev
2072	fi
2073	mv $ROOT-nd $ROOT-nd.prev
2074fi
2075
2076#
2077# Echo the SCM type of the parent workspace, this can't just be which_scm
2078# as that does not know how to identify various network repositories.
2079#
2080function parent_wstype {
2081	typeset scm_type junk
2082
2083	CODEMGR_WS="$BRINGOVER_WS" "$WHICH_SCM" 2>/dev/null \
2084	    | read scm_type junk
2085	if [[ -z "$scm_type" || "$scm_type" == unknown ]]; then
2086		# Probe BRINGOVER_WS to determine its type
2087		if [[ $BRINGOVER_WS == svn*://* ]]; then
2088			scm_type="subversion"
2089		elif [[ $BRINGOVER_WS == file://* ]] &&
2090		    egrep -s "This is a Subversion repository" \
2091		    ${BRINGOVER_WS#file://}/README.txt 2> /dev/null; then
2092			scm_type="subversion"
2093		elif [[ $BRINGOVER_WS == ssh://* ]]; then
2094			scm_type="mercurial"
2095		elif [[ $BRINGOVER_WS == http://* ]] && \
2096		    wget -q -O- --save-headers "$BRINGOVER_WS/?cmd=heads" | \
2097		    egrep -s "application/mercurial" 2> /dev/null; then
2098			scm_type="mercurial"
2099		elif svn info $BRINGOVER_WS > /dev/null 2>&1; then
2100			scm_type="subversion"
2101		else
2102			scm_type="none"
2103		fi
2104	fi
2105
2106	# fold both unsupported and unrecognized results into "none"
2107	case "$scm_type" in
2108	none|subversion|teamware|mercurial)
2109		;;
2110	*)	scm_type=none
2111		;;
2112	esac
2113
2114	echo $scm_type
2115}
2116
2117# Echo the SCM types of $CODEMGR_WS and $BRINGOVER_WS
2118function child_wstype {
2119	typeset scm_type junk
2120
2121	# Probe CODEMGR_WS to determine its type
2122	if [[ -d $CODEMGR_WS ]]; then
2123		$WHICH_SCM | read scm_type junk || exit 1
2124	fi
2125
2126	case "$scm_type" in
2127	none|subversion|teamware|mercurial)
2128		;;
2129	*)	scm_type=none
2130		;;
2131	esac
2132
2133	echo $scm_type
2134}
2135
2136SCM_TYPE=$(child_wstype)
2137
2138#
2139#	Decide whether to clobber
2140#
2141if [ "$i_FLAG" = "n" -a -d "$SRC" ]; then
2142	echo "\n==== Make clobber at `date` ====\n" >> $LOGFILE
2143
2144	cd $SRC
2145	# remove old clobber file
2146	rm -f $SRC/clobber.out
2147	rm -f $SRC/clobber-${MACH}.out
2148
2149	# Remove all .make.state* files, just in case we are restarting
2150	# the build after having interrupted a previous 'make clobber'.
2151	find . \( -name SCCS -o -name .hg -o -name .svn -o -name .git \
2152		-o -name 'interfaces.*' \) -prune \
2153		-o -name '.make.*' -print | xargs rm -f
2154
2155	$MAKE -ek clobber 2>&1 | tee -a $SRC/clobber-${MACH}.out >> $LOGFILE
2156	echo "\n==== Make clobber ERRORS ====\n" >> $mail_msg_file
2157	grep "$MAKE:" $SRC/clobber-${MACH}.out |
2158		egrep -v "Ignoring unknown host" \
2159		>> $mail_msg_file
2160
2161	if [[ "$t_FLAG" = "y" || "$O_FLAG" = "y" ]]; then
2162		echo "\n==== Make tools clobber at `date` ====\n" >> $LOGFILE
2163		cd ${TOOLS}
2164		rm -f ${TOOLS}/clobber-${MACH}.out
2165		$MAKE TOOLS_PROTO=$TOOLS_PROTO -ek clobber 2>&1 | \
2166			tee -a ${TOOLS}/clobber-${MACH}.out >> $LOGFILE
2167		echo "\n==== Make tools clobber ERRORS ====\n" \
2168			>> $mail_msg_file
2169		grep "$MAKE:" ${TOOLS}/clobber-${MACH}.out \
2170			>> $mail_msg_file
2171		rm -rf ${TOOLS_PROTO}
2172		mkdir -p ${TOOLS_PROTO}
2173	fi
2174
2175	typeset roots=$(allprotos)
2176	echo "\n\nClearing $roots" >> "$LOGFILE"
2177	rm -rf $roots
2178
2179	# Get back to a clean workspace as much as possible to catch
2180	# problems that only occur on fresh workspaces.
2181	# Remove all .make.state* files, libraries, and .o's that may
2182	# have been omitted from clobber.  A couple of libraries are
2183	# under source code control, so leave them alone.
2184	# We should probably blow away temporary directories too.
2185	cd $SRC
2186	find $relsrcdirs \( -name SCCS -o -name .hg -o -name .svn \
2187	    -o -name .git -o -name 'interfaces.*' \) -prune -o \
2188	    \( -name '.make.*' -o -name 'lib*.a' -o -name 'lib*.so*' -o \
2189	       -name '*.o' \) -print | \
2190	    grep -v 'tools/ctf/dwarf/.*/libdwarf' | xargs rm -f
2191else
2192	echo "\n==== No clobber at `date` ====\n" >> $LOGFILE
2193fi
2194
2195type bringover_teamware > /dev/null 2>&1 || function bringover_teamware {
2196	# sleep on the parent workspace's lock
2197	while egrep -s write $BRINGOVER_WS/Codemgr_wsdata/locks
2198	do
2199		sleep 120
2200	done
2201
2202	if [[ -z $BRINGOVER ]]; then
2203		BRINGOVER=$TEAMWARE/bin/bringover
2204	fi
2205
2206	staffer $BRINGOVER -c "nightly update" -p $BRINGOVER_WS \
2207	    -w $CODEMGR_WS $BRINGOVER_FILES < /dev/null 2>&1 ||
2208		touch $TMPDIR/bringover_failed
2209
2210        staffer bringovercheck $CODEMGR_WS >$TMPDIR/bringovercheck.out 2>&1
2211	if [ -s $TMPDIR/bringovercheck.out ]; then
2212		echo "\n==== POST-BRINGOVER CLEANUP NOISE ====\n"
2213		cat $TMPDIR/bringovercheck.out
2214	fi
2215}
2216
2217type bringover_mercurial > /dev/null 2>&1 || function bringover_mercurial {
2218	typeset -x PATH=$PATH
2219
2220	# If the repository doesn't exist yet, then we want to populate it.
2221	if [[ ! -d $CODEMGR_WS/.hg ]]; then
2222		staffer hg init $CODEMGR_WS
2223		staffer echo "[paths]" > $CODEMGR_WS/.hg/hgrc
2224		staffer echo "default=$BRINGOVER_WS" >> $CODEMGR_WS/.hg/hgrc
2225		touch $TMPDIR/new_repository
2226	fi
2227
2228	#
2229	# If the user set CLOSED_BRINGOVER_WS and didn't set CLOSED_IS_PRESENT
2230	# to "no," then we'll want to initialise the closed repository
2231	#
2232	# We use $orig_closed_is_present instead of $CLOSED_IS_PRESENT,
2233	# because for newly-created source trees, the latter will be "no"
2234	# until after the bringover completes.
2235	#
2236	if [[ "$orig_closed_is_present" != "no" && \
2237	    -n "$CLOSED_BRINGOVER_WS" && \
2238	    ! -d $CODEMGR_WS/usr/closed/.hg ]]; then
2239		staffer mkdir -p $CODEMGR_WS/usr/closed
2240		staffer hg init $CODEMGR_WS/usr/closed
2241		staffer echo "[paths]" > $CODEMGR_WS/usr/closed/.hg/hgrc
2242		staffer echo "default=$CLOSED_BRINGOVER_WS" >> $CODEMGR_WS/usr/closed/.hg/hgrc
2243		touch $TMPDIR/new_closed
2244		export CLOSED_IS_PRESENT=yes
2245	fi
2246
2247	typeset -x HGMERGE="/bin/false"
2248
2249	#
2250	# If the user has changes, regardless of whether those changes are
2251	# committed, and regardless of whether those changes conflict, then
2252	# we'll attempt to merge them either implicitly (uncommitted) or
2253	# explicitly (committed).
2254	#
2255	# These are the messages we'll use to help clarify mercurial output
2256	# in those cases.
2257	#
2258	typeset mergefailmsg="\
2259***\n\
2260*** nightly was unable to automatically merge your changes.  You should\n\
2261*** redo the full merge manually, following the steps outlined by mercurial\n\
2262*** above, then restart nightly.\n\
2263***\n"
2264	typeset mergepassmsg="\
2265***\n\
2266*** nightly successfully merged your changes.  This means that your working\n\
2267*** directory has been updated, but those changes are not yet committed.\n\
2268*** After nightly completes, you should validate the results of the merge,\n\
2269*** then use hg commit manually.\n\
2270***\n"
2271
2272	#
2273	# For each repository in turn:
2274	#
2275	# 1. Do the pull.  If this fails, dump the output and bail out.
2276	#
2277	# 2. If the pull resulted in an extra head, do an explicit merge.
2278	#    If this fails, dump the output and bail out.
2279	#
2280	# Because we can't rely on Mercurial to exit with a failure code
2281	# when a merge fails (Mercurial issue #186), we must grep the
2282	# output of pull/merge to check for attempted and/or failed merges.
2283	#
2284	# 3. If a merge failed, set the message and fail the bringover.
2285	#
2286	# 4. Otherwise, if a merge succeeded, set the message
2287	#
2288	# 5. Dump the output, and any message from step 3 or 4.
2289	#
2290
2291	typeset HG_SOURCE=$BRINGOVER_WS
2292	if [ ! -f $TMPDIR/new_repository ]; then
2293		HG_SOURCE=$TMPDIR/open_bundle.hg
2294		staffer hg --cwd $CODEMGR_WS incoming --bundle $HG_SOURCE \
2295		    -v $BRINGOVER_WS > $TMPDIR/incoming_open.out
2296
2297		#
2298		# If there are no incoming changesets, then incoming will
2299		# fail, and there will be no bundle file.  Reset the source,
2300		# to allow the remaining logic to complete with no false
2301		# negatives.  (Unlike incoming, pull will return success
2302		# for the no-change case.)
2303		#
2304		if (( $? != 0 )); then
2305			HG_SOURCE=$BRINGOVER_WS
2306		fi
2307	fi
2308
2309	staffer hg --cwd $CODEMGR_WS pull -u $HG_SOURCE \
2310	    > $TMPDIR/pull_open.out 2>&1
2311	if (( $? != 0 )); then
2312		printf "%s: pull failed as follows:\n\n" "$CODEMGR_WS"
2313		cat $TMPDIR/pull_open.out
2314		if grep "^merging.*failed" $TMPDIR/pull_open.out > /dev/null 2>&1; then
2315			printf "$mergefailmsg"
2316		fi
2317		touch $TMPDIR/bringover_failed
2318		return
2319	fi
2320
2321	if grep "not updating" $TMPDIR/pull_open.out > /dev/null 2>&1; then
2322		staffer hg --cwd $CODEMGR_WS merge \
2323		    >> $TMPDIR/pull_open.out 2>&1
2324		if (( $? != 0 )); then
2325			printf "%s: merge failed as follows:\n\n" \
2326			    "$CODEMGR_WS"
2327			cat $TMPDIR/pull_open.out
2328			if grep "^merging.*failed" $TMPDIR/pull_open.out \
2329			    > /dev/null 2>&1; then
2330				printf "$mergefailmsg"
2331			fi
2332			touch $TMPDIR/bringover_failed
2333			return
2334		fi
2335	fi
2336
2337	printf "updated %s with the following results:\n" "$CODEMGR_WS"
2338	cat $TMPDIR/pull_open.out
2339	if grep "^merging" $TMPDIR/pull_open.out >/dev/null 2>&1; then
2340		printf "$mergepassmsg"
2341	fi
2342	printf "\n"
2343
2344	#
2345	# We only want to update usr/closed if it exists, and we haven't been
2346	# told not to via $CLOSED_IS_PRESENT, and we actually know where to
2347	# pull from ($CLOSED_BRINGOVER_WS).
2348	#
2349	if [[ $CLOSED_IS_PRESENT = yes && \
2350	    -d $CODEMGR_WS/usr/closed/.hg && \
2351	    -n $CLOSED_BRINGOVER_WS ]]; then
2352
2353		HG_SOURCE=$CLOSED_BRINGOVER_WS
2354		if [ ! -f $TMPDIR/new_closed ]; then
2355			HG_SOURCE=$TMPDIR/closed_bundle.hg
2356			staffer hg --cwd $CODEMGR_WS/usr/closed incoming \
2357			    --bundle $HG_SOURCE -v $CLOSED_BRINGOVER_WS \
2358			    > $TMPDIR/incoming_closed.out
2359
2360			#
2361			# If there are no incoming changesets, then incoming will
2362			# fail, and there will be no bundle file.  Reset the source,
2363			# to allow the remaining logic to complete with no false
2364			# negatives.  (Unlike incoming, pull will return success
2365			# for the no-change case.)
2366			#
2367			if (( $? != 0 )); then
2368				HG_SOURCE=$CLOSED_BRINGOVER_WS
2369			fi
2370		fi
2371
2372		staffer hg --cwd $CODEMGR_WS/usr/closed pull -u \
2373			$HG_SOURCE > $TMPDIR/pull_closed.out 2>&1
2374		if (( $? != 0 )); then
2375			printf "closed pull failed as follows:\n\n"
2376			cat $TMPDIR/pull_closed.out
2377			if grep "^merging.*failed" $TMPDIR/pull_closed.out \
2378			    > /dev/null 2>&1; then
2379				printf "$mergefailmsg"
2380			fi
2381			touch $TMPDIR/bringover_failed
2382			return
2383		fi
2384
2385		if grep "not updating" $TMPDIR/pull_closed.out > /dev/null 2>&1; then
2386			staffer hg --cwd $CODEMGR_WS/usr/closed merge \
2387			    >> $TMPDIR/pull_closed.out 2>&1
2388			if (( $? != 0 )); then
2389				printf "closed merge failed as follows:\n\n"
2390				cat $TMPDIR/pull_closed.out
2391				if grep "^merging.*failed" $TMPDIR/pull_closed.out > /dev/null 2>&1; then
2392					printf "$mergefailmsg"
2393				fi
2394				touch $TMPDIR/bringover_failed
2395				return
2396			fi
2397		fi
2398
2399		printf "updated %s with the following results:\n" \
2400		    "$CODEMGR_WS/usr/closed"
2401		cat $TMPDIR/pull_closed.out
2402		if grep "^merging" $TMPDIR/pull_closed.out > /dev/null 2>&1; then
2403			printf "$mergepassmsg"
2404		fi
2405	fi
2406
2407	#
2408	# Per-changeset output is neither useful nor manageable for a
2409	# newly-created repository.
2410	#
2411	if [ -f $TMPDIR/new_repository ]; then
2412		return
2413	fi
2414
2415	printf "\nadded the following changesets to open repository:\n"
2416	cat $TMPDIR/incoming_open.out
2417
2418	#
2419	# The closed repository could have been newly created, even though
2420	# the open one previously existed...
2421	#
2422	if [ -f $TMPDIR/new_closed ]; then
2423		return
2424	fi
2425
2426	if [ -f $TMPDIR/incoming_closed.out ]; then
2427		printf "\nadded the following changesets to closed repository:\n"
2428		cat $TMPDIR/incoming_closed.out
2429	fi
2430}
2431
2432type bringover_subversion > /dev/null 2>&1 || function bringover_subversion {
2433	typeset -x PATH=$PATH
2434
2435	if [[ ! -d $CODEMGR_WS/.svn ]]; then
2436		staffer svn checkout $BRINGOVER_WS $CODEMGR_WS ||
2437			touch $TMPDIR/bringover_failed
2438	else
2439		typeset root
2440		root=$(staffer svn info $CODEMGR_WS |
2441			nawk '/^Repository Root:/ {print $NF}')
2442		if [[ $root != $BRINGOVER_WS ]]; then
2443			# We fail here because there's no way to update
2444			# from a named repo.
2445			cat <<-EOF
2446			\$BRINGOVER_WS doesn't match repository root:
2447			  \$BRINGOVER_WS:  $BRINGOVER_WS
2448			  Repository root: $root
2449			EOF
2450			touch $TMPDIR/bringover_failed
2451		else
2452			# If a conflict happens, svn still exits 0.
2453			staffer svn update $CODEMGR_WS | tee $TMPDIR/pull.out ||
2454				touch $TMPDIR/bringover_failed
2455			if grep "^C" $TMPDIR/pull.out > /dev/null 2>&1; then
2456				touch $TMPDIR/bringover_failed
2457			fi
2458		fi
2459	fi
2460}
2461
2462type bringover_none > /dev/null 2>&1 || function bringover_none {
2463	echo "Couldn't figure out what kind of SCM to use for $BRINGOVER_WS."
2464	touch $TMPDIR/bringover_failed
2465}
2466
2467#
2468#	Decide whether to bringover to the codemgr workspace
2469#
2470if [ "$n_FLAG" = "n" ]; then
2471	PARENT_SCM_TYPE=$(parent_wstype)
2472
2473	if [[ $SCM_TYPE != none && $SCM_TYPE != $PARENT_SCM_TYPE ]]; then
2474		echo "cannot bringover from $PARENT_SCM_TYPE to $SCM_TYPE, " \
2475		    "quitting at `date`." | tee -a $mail_msg_file >> $LOGFILE
2476		exit 1
2477	fi
2478
2479	run_hook PRE_BRINGOVER
2480
2481	echo "\n==== bringover to $CODEMGR_WS at `date` ====\n" >> $LOGFILE
2482	echo "\n==== BRINGOVER LOG ====\n" >> $mail_msg_file
2483
2484	eval "bringover_${PARENT_SCM_TYPE}" 2>&1 |
2485		tee -a $mail_msg_file >> $LOGFILE
2486
2487	if [ -f $TMPDIR/bringover_failed ]; then
2488		rm -f $TMPDIR/bringover_failed
2489		build_ok=n
2490		echo "trouble with bringover, quitting at `date`." |
2491			tee -a $mail_msg_file >> $LOGFILE
2492		exit 1
2493	fi
2494
2495	#
2496	# It's possible that we used the bringover above to create
2497	# $CODEMGR_WS.  If so, then SCM_TYPE was previously "none,"
2498	# but should now be the same as $BRINGOVER_WS.
2499	#
2500	[[ $SCM_TYPE = none ]] && SCM_TYPE=$PARENT_SCM_TYPE
2501
2502	run_hook POST_BRINGOVER
2503
2504	#
2505	# Possible transition from pre-split workspace to split
2506	# workspace.  See if the bringover changed anything.
2507	#
2508	CLOSED_IS_PRESENT="$orig_closed_is_present"
2509	check_closed_tree
2510
2511else
2512	echo "\n==== No bringover to $CODEMGR_WS ====\n" >> $LOGFILE
2513fi
2514
2515if [[ "$O_FLAG" = y && "$CLOSED_IS_PRESENT" != "yes" ]]; then
2516	build_ok=n
2517	echo "OpenSolaris binary deliverables need usr/closed." \
2518	    | tee -a "$mail_msg_file" >> $LOGFILE
2519	exit 1
2520fi
2521
2522# Safeguards
2523[[ -v CODEMGR_WS ]] || fatal_error "Error: Variable CODEMGR_WS not set."
2524[[ -d "${CODEMGR_WS}" ]] || fatal_error "Error: ${CODEMGR_WS} is not a directory."
2525[[ -f "${CODEMGR_WS}/usr/src/Makefile" ]] || fatal_error "Error: ${CODEMGR_WS}/usr/src/Makefile not found."
2526
2527echo "\n==== Build environment ====\n" | tee -a $build_environ_file >> $LOGFILE
2528
2529# System
2530whence uname | tee -a $build_environ_file >> $LOGFILE
2531uname -a 2>&1 | tee -a $build_environ_file >> $LOGFILE
2532echo | tee -a $build_environ_file >> $LOGFILE
2533
2534# make
2535whence $MAKE | tee -a $build_environ_file >> $LOGFILE
2536$MAKE -v | tee -a $build_environ_file >> $LOGFILE
2537echo "number of concurrent jobs = $DMAKE_MAX_JOBS" |
2538    tee -a $build_environ_file >> $LOGFILE
2539
2540#
2541# Report the compiler versions.
2542#
2543
2544if [[ ! -f $SRC/Makefile ]]; then
2545	build_ok=n
2546	echo "\nUnable to find \"Makefile\" in $SRC." | \
2547	    tee -a $build_environ_file >> $LOGFILE
2548	exit 1
2549fi
2550
2551( cd $SRC
2552  for target in cc-version cc64-version java-version; do
2553	echo
2554	#
2555	# Put statefile somewhere we know we can write to rather than trip
2556	# over a read-only $srcroot.
2557	#
2558	rm -f $TMPDIR/make-state
2559	export SRC
2560	if $MAKE -K $TMPDIR/make-state -e $target 2>/dev/null; then
2561		continue
2562	fi
2563	touch $TMPDIR/nocompiler
2564  done
2565  echo
2566) | tee -a $build_environ_file >> $LOGFILE
2567
2568if [ -f $TMPDIR/nocompiler ]; then
2569	rm -f $TMPDIR/nocompiler
2570	build_ok=n
2571	echo "Aborting due to missing compiler." |
2572		tee -a $build_environ_file >> $LOGFILE
2573	exit 1
2574fi
2575
2576# as
2577whence as | tee -a $build_environ_file >> $LOGFILE
2578as -V 2>&1 | head -1 | tee -a $build_environ_file >> $LOGFILE
2579echo | tee -a $build_environ_file >> $LOGFILE
2580
2581# Check that we're running a capable link-editor
2582whence ld | tee -a $build_environ_file >> $LOGFILE
2583LDVER=`ld -V 2>&1`
2584echo $LDVER | tee -a $build_environ_file >> $LOGFILE
2585LDVER=`echo $LDVER | sed -e "s/.*-1\.//" -e "s/:.*//"`
2586if [ `expr $LDVER \< 422` -eq 1 ]; then
2587	echo "The link-editor needs to be at version 422 or higher to build" | \
2588	    tee -a $build_environ_file >> $LOGFILE
2589	echo "the latest stuff.  Hope your build works." | \
2590	    tee -a $build_environ_file >> $LOGFILE
2591fi
2592
2593#
2594# Build and use the workspace's tools if requested
2595#
2596if [[ "$t_FLAG" = "y" || "$O_FLAG" = y ]]; then
2597	set_non_debug_build_flags
2598
2599	build_tools ${TOOLS_PROTO}
2600	if [[ $? != 0  && "$t_FLAG" = y ]]; then
2601		use_tools $TOOLS_PROTO
2602	fi
2603fi
2604
2605#
2606# copy ihv proto area in addition to the build itself
2607#
2608if [ "$X_FLAG" = "y" ]; then
2609	copy_ihv_proto
2610fi
2611
2612if [ "$i_FLAG" = "y" -a "$SH_FLAG" = "y" ]; then
2613	echo "\n==== NOT Building base OS-Net source ====\n" | \
2614	    tee -a $LOGFILE >> $mail_msg_file
2615else
2616	# timestamp the start of the normal build; the findunref tool uses it.
2617	touch $SRC/.build.tstamp
2618
2619	normal_build
2620fi
2621
2622#
2623# Generate the THIRDPARTYLICENSE files if needed.  This is done after
2624# the build, so that dynamically-created license files are there.
2625# It's done before findunref to help identify license files that need
2626# to be added to tools/opensolaris/license-list.
2627#
2628if [ "$O_FLAG" = y -a "$build_ok" = y ]; then
2629	echo "\n==== Generating THIRDPARTYLICENSE files ====\n" |
2630	    tee -a "$mail_msg_file" >> "$LOGFILE"
2631
2632	if [ -d $ROOT/licenses/usr ]; then
2633		( cd $ROOT/licenses ; \
2634		    mktpl $SRC/pkg/license-list ) >> "$LOGFILE" 2>&1
2635		if (( $? != 0 )) ; then
2636			echo "Couldn't create THIRDPARTYLICENSE files" |
2637			    tee -a "$mail_msg_file" >> "$LOGFILE"
2638		fi
2639	else
2640		echo "No licenses found under $ROOT/licenses" |
2641		    tee -a "$mail_msg_file" >> "$LOGFILE"
2642	fi
2643fi
2644
2645ORIG_SRC=$SRC
2646BINARCHIVE=${CODEMGR_WS}/bin-${MACH}.cpio.Z
2647
2648if [ "$SE_FLAG" = "y" -o "$SD_FLAG" = "y" -o "$SH_FLAG" = "y" ]; then
2649	save_binaries
2650fi
2651
2652
2653# EXPORT_SRC comes after CRYPT_SRC since a domestic build will need
2654# $SRC pointing to the export_source usr/src.
2655
2656if [ "$SE_FLAG" = "y" -o "$SD_FLAG" = "y" -o "$SH_FLAG" = "y" ]; then
2657	if [ "$SD_FLAG" = "y" -a $build_ok = y ]; then
2658	    set_up_source_build ${CODEMGR_WS} ${CRYPT_SRC} CRYPT_SRC
2659	fi
2660
2661	if [ $build_ok = y ]; then
2662	    set_up_source_build ${CODEMGR_WS} ${EXPORT_SRC} EXPORT_SRC
2663	fi
2664fi
2665
2666if [ "$SD_FLAG" = "y" -a $build_ok = y ]; then
2667	# drop the crypt files in place.
2668	cd ${EXPORT_SRC}
2669	echo "\nextracting crypt_files.cpio.Z onto export_source.\n" \
2670	    >> ${LOGFILE}
2671	zcat ${CODEMGR_WS}/crypt_files.cpio.Z | \
2672	    cpio -idmucvB 2>/dev/null >> ${LOGFILE}
2673	if [ "$?" = "0" ]; then
2674		echo "\n==== DOMESTIC extraction succeeded ====\n" \
2675		    >> $mail_msg_file
2676	else
2677		echo "\n==== DOMESTIC extraction failed ====\n" \
2678		    >> $mail_msg_file
2679	fi
2680
2681fi
2682
2683if [ "$SO_FLAG" = "y" -a "$build_ok" = y ]; then
2684	#
2685	# Copy the open sources into their own tree.
2686	# If copy_source fails, it will have already generated an
2687	# error message and set build_ok=n, so we don't need to worry
2688	# about that here.
2689	#
2690	copy_source $CODEMGR_WS $OPEN_SRCDIR OPEN_SOURCE usr/src
2691fi
2692
2693if [ "$SO_FLAG" = "y" -a "$build_ok" = y ]; then
2694	SRC=$OPEN_SRCDIR/usr/src
2695	export CLOSED_IS_PRESENT=no
2696fi
2697
2698if is_source_build && [ $build_ok = y ] ; then
2699	# remove proto area(s) here, since we don't clobber
2700	rm -rf `allprotos`
2701	if [ "$t_FLAG" = "y" ]; then
2702		set_non_debug_build_flags
2703		ORIG_TOOLS=$TOOLS
2704		#
2705		# SRC was set earlier to point to the source build
2706		# source tree (e.g., $EXPORT_SRC).
2707		#
2708		TOOLS=${SRC}/tools
2709		TOOLS_PROTO=${TOOLS}/${TOOLS_PROTO_REL}; export TOOLS_PROTO
2710		build_tools ${TOOLS_PROTO}
2711		if [[ $? != 0 ]]; then
2712			use_tools ${TOOLS_PROTO}
2713		fi
2714	fi
2715
2716	export EXPORT_RELEASE_BUILD ; EXPORT_RELEASE_BUILD=#
2717	normal_build
2718fi
2719
2720#
2721# There are several checks that need to look at the proto area, but
2722# they only need to look at one, and they don't care whether it's
2723# DEBUG or non-DEBUG.
2724#
2725if [[ "$MULTI_PROTO" = yes && "$D_FLAG" = n ]]; then
2726	checkroot=$ROOT-nd
2727else
2728	checkroot=$ROOT
2729fi
2730
2731if [ "$build_ok" = "y" ]; then
2732	echo "\n==== Creating protolist system file at `date` ====" \
2733		>> $LOGFILE
2734	protolist $checkroot > $ATLOG/proto_list_${MACH}
2735	echo "==== protolist system file created at `date` ====\n" \
2736		>> $LOGFILE
2737
2738	if [ "$N_FLAG" != "y" ]; then
2739
2740		E1=
2741		f1=
2742		if [ -d "$SRC/pkgdefs" ]; then
2743			f1="$SRC/pkgdefs/etc/exception_list_$MACH"
2744			if [ "$X_FLAG" = "y" ]; then
2745				f1="$f1 $IA32_IHV_WS/usr/src/pkgdefs/etc/exception_list_$MACH"
2746			fi
2747		fi
2748
2749		for f in $f1; do
2750			if [ -f "$f" ]; then
2751				E1="$E1 -e $f"
2752			fi
2753		done
2754
2755		E2=
2756		f2=
2757		if [ -d "$SRC/pkg" ]; then
2758			f2="$f2 exceptions/packaging"
2759		fi
2760
2761		for f in $f2; do
2762			if [ -f "$f" ]; then
2763				E2="$E2 -e $f"
2764			fi
2765		done
2766
2767		if [ -f "$REF_PROTO_LIST" ]; then
2768			#
2769			# For builds that copy the IHV proto area (-X), add the
2770			# IHV proto list to the reference list if the reference
2771			# was built without -X.
2772			#
2773			# For builds that don't copy the IHV proto area, add the
2774			# IHV proto list to the build's proto list if the
2775			# reference was built with -X.
2776			#
2777			# Use the presence of the first file entry of the cached
2778			# IHV proto list in the reference list to determine
2779			# whether it was built with -X or not.
2780			#
2781			IHV_REF_PROTO_LIST=$SRC/pkg/proto_list_ihv_$MACH
2782			grepfor=$(nawk '$1 == "f" { print $2; exit }' \
2783				$IHV_REF_PROTO_LIST 2> /dev/null)
2784			if [ $? = 0 -a -n "$grepfor" ]; then
2785				if [ "$X_FLAG" = "y" ]; then
2786					grep -w "$grepfor" \
2787						$REF_PROTO_LIST > /dev/null
2788					if [ ! "$?" = "0" ]; then
2789						REF_IHV_PROTO="-d $IHV_REF_PROTO_LIST"
2790					fi
2791				else
2792					grep -w "$grepfor" \
2793						$REF_PROTO_LIST > /dev/null
2794					if [ "$?" = "0" ]; then
2795						IHV_PROTO_LIST="$IHV_REF_PROTO_LIST"
2796					fi
2797				fi
2798			fi
2799		fi
2800	fi
2801
2802	if [ "$N_FLAG" != "y" -a -f $SRC/pkgdefs/Makefile ]; then
2803		echo "\n==== Impact on SVr4 packages ====\n" >> $mail_msg_file
2804		#
2805		# Compare the build's proto list with current package
2806		# definitions to audit the quality of package
2807		# definitions and makefile install targets. Use the
2808		# current exception list.
2809		#
2810		PKGDEFS_LIST=""
2811		for d in $abssrcdirs; do
2812			if [ -d $d/pkgdefs ]; then
2813				PKGDEFS_LIST="$PKGDEFS_LIST -d $d/pkgdefs"
2814			fi
2815		done
2816		if [ "$X_FLAG" = "y" -a \
2817		    -d $IA32_IHV_WS/usr/src/pkgdefs ]; then
2818			PKGDEFS_LIST="$PKGDEFS_LIST -d $IA32_IHV_WS/usr/src/pkgdefs"
2819		fi
2820		$PROTOCMPTERSE \
2821		    "Files missing from the proto area:" \
2822		    "Files missing from packages:" \
2823		    "Inconsistencies between pkgdefs and proto area:" \
2824		    ${E1} \
2825		    ${PKGDEFS_LIST} \
2826		    $ATLOG/proto_list_${MACH} \
2827		    >> $mail_msg_file
2828	fi
2829
2830	if [ "$N_FLAG" != "y" -a -d $SRC/pkg ]; then
2831		echo "\n==== Validating manifests against proto area ====\n" \
2832		    >> $mail_msg_file
2833		( cd $SRC/pkg ; $MAKE -e protocmp ROOT="$checkroot" ) \
2834		    >> $mail_msg_file
2835
2836	fi
2837
2838	if [ "$N_FLAG" != "y" -a -f "$REF_PROTO_LIST" ]; then
2839		echo "\n==== Impact on proto area ====\n" >> $mail_msg_file
2840		if [ -n "$E2" ]; then
2841			ELIST=$E2
2842		else
2843			ELIST=$E1
2844		fi
2845		$PROTOCMPTERSE \
2846			"Files in yesterday's proto area, but not today's:" \
2847			"Files in today's proto area, but not yesterday's:" \
2848			"Files that changed between yesterday and today:" \
2849			${ELIST} \
2850			-d $REF_PROTO_LIST \
2851			$REF_IHV_PROTO \
2852			$ATLOG/proto_list_${MACH} \
2853			$IHV_PROTO_LIST \
2854			>> $mail_msg_file
2855	fi
2856fi
2857
2858if [ "$u_FLAG" = "y"  -a "$build_ok" = "y" ]; then
2859	staffer cp $ATLOG/proto_list_${MACH} \
2860		$PARENT_WS/usr/src/proto_list_${MACH}
2861fi
2862
2863# Update parent proto area if necessary. This is done now
2864# so that the proto area has either DEBUG or non-DEBUG kernels.
2865# Note that this clears out the lock file, so we can dispense with
2866# the variable now.
2867if [ "$U_FLAG" = "y" -a "$build_ok" = "y" ]; then
2868	echo "\n==== Copying proto area to $NIGHTLY_PARENT_ROOT ====\n" | \
2869	    tee -a $LOGFILE >> $mail_msg_file
2870	rm -rf $NIGHTLY_PARENT_ROOT/*
2871	unset Ulockfile
2872	mkdir -p $NIGHTLY_PARENT_ROOT
2873	if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
2874		( cd $ROOT; tar cf - . |
2875		    ( cd $NIGHTLY_PARENT_ROOT;  umask 0; tar xpf - ) ) 2>&1 |
2876		    tee -a $mail_msg_file >> $LOGFILE
2877	fi
2878	if [[ "$MULTI_PROTO" = yes && "$F_FLAG" = n ]]; then
2879		rm -rf $NIGHTLY_PARENT_ROOT-nd/*
2880		mkdir -p $NIGHTLY_PARENT_ROOT-nd
2881		cd $ROOT-nd
2882		( tar cf - . |
2883		    ( cd $NIGHTLY_PARENT_ROOT-nd; umask 0; tar xpf - ) ) 2>&1 |
2884		    tee -a $mail_msg_file >> $LOGFILE
2885	fi
2886	if [ -n "${NIGHTLY_PARENT_TOOLS_ROOT}" ]; then
2887		echo "\n==== Copying tools proto area to $NIGHTLY_PARENT_TOOLS_ROOT ====\n" | \
2888		    tee -a $LOGFILE >> $mail_msg_file
2889		rm -rf $NIGHTLY_PARENT_TOOLS_ROOT/*
2890		mkdir -p $NIGHTLY_PARENT_TOOLS_ROOT
2891		if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
2892			( cd $TOOLS_PROTO; tar cf - . |
2893			    ( cd $NIGHTLY_PARENT_TOOLS_ROOT;
2894			    umask 0; tar xpf - ) ) 2>&1 |
2895			    tee -a $mail_msg_file >> $LOGFILE
2896		fi
2897	fi
2898fi
2899
2900#
2901# ELF verification: ABI (-A) and runtime (-r) checks
2902#
2903if [[ ($build_ok = y) && ( ($A_FLAG = y) || ($r_FLAG = y) ) ]]; then
2904	# Directory ELF-data.$MACH holds the files produced by these tests.
2905	elf_ddir=$SRC/ELF-data.$MACH
2906
2907	# If there is a previous ELF-data backup directory, remove it. Then,
2908	# rotate current ELF-data directory into its place and create a new
2909	# empty directory
2910	rm -rf $elf_ddir.ref
2911	if [[ -d $elf_ddir ]]; then
2912		mv $elf_ddir $elf_ddir.ref
2913	fi
2914	mkdir -p $elf_ddir
2915
2916	# Call find_elf to produce a list of the ELF objects in the proto area.
2917	# This list is passed to check_rtime and interface_check, preventing
2918	# them from separately calling find_elf to do the same work twice.
2919	find_elf -fr $checkroot > $elf_ddir/object_list
2920
2921	if [[ $A_FLAG = y ]]; then
2922	       	echo "\n==== Check versioning and ABI information ====\n"  | \
2923		    tee -a $LOGFILE >> $mail_msg_file
2924
2925		# Produce interface description for the proto. Report errors.
2926		interface_check -o -w $elf_ddir -f object_list \
2927			-i interface -E interface.err
2928		if [[ -s $elf_ddir/interface.err ]]; then
2929			tee -a $LOGFILE < $elf_ddir/interface.err \
2930				>> $mail_msg_file
2931		fi
2932
2933		# If ELF_DATA_BASELINE_DIR is defined, compare the new interface
2934		# description file to that from the baseline gate. Issue a
2935		# warning if the baseline is not present, and keep going.
2936		if [[ "$ELF_DATA_BASELINE_DIR" != '' ]]; then
2937			base_ifile="$ELF_DATA_BASELINE_DIR/interface"
2938
2939		       	echo "\n==== Compare versioning and ABI information" \
2940			    "to baseline ====\n"  | \
2941			    tee -a $LOGFILE >> $mail_msg_file
2942		       	echo "Baseline:  $base_ifile\n" >> $LOGFILE
2943
2944			if [[ -f $base_ifile ]]; then
2945				interface_cmp -d -o $base_ifile \
2946				    $elf_ddir/interface > $elf_ddir/interface.cmp
2947				if [[ -s $elf_ddir/interface.cmp ]]; then
2948					echo | tee -a $LOGFILE >> $mail_msg_file
2949					tee -a $LOGFILE < \
2950					    $elf_ddir/interface.cmp \
2951					    >> $mail_msg_file
2952				fi
2953			else
2954			       	echo "baseline not available. comparison" \
2955                                    "skipped" | \
2956				    tee -a $LOGFILE >> $mail_msg_file
2957			fi
2958
2959		fi
2960	fi
2961
2962	if [[ $r_FLAG = y ]]; then
2963		echo "\n==== Check ELF runtime attributes ====\n" | \
2964		    tee -a $LOGFILE >> $mail_msg_file
2965
2966		# If we're doing a DEBUG build the proto area will be left
2967		# with debuggable objects, thus don't assert -s.
2968		if [[ $D_FLAG = y ]]; then
2969			rtime_sflag=""
2970		else
2971			rtime_sflag="-s"
2972		fi
2973		check_rtime -i -m -v $rtime_sflag -o -w $elf_ddir \
2974			-D object_list  -f object_list -E runtime.err \
2975			-I runtime.attr.raw
2976
2977		# check_rtime -I output needs to be sorted in order to
2978		# compare it to that from previous builds.
2979		sort $elf_ddir/runtime.attr.raw > $elf_ddir/runtime.attr
2980		rm $elf_ddir/runtime.attr.raw
2981
2982		# Report errors
2983		if [[ -s $elf_ddir/runtime.err ]]; then
2984			tee -a $LOGFILE < $elf_ddir/runtime.err \
2985				>> $mail_msg_file
2986		fi
2987
2988		# If there is an ELF-data directory from a previous build,
2989		# then diff the attr files. These files contain information
2990		# about dependencies, versioning, and runpaths. There is some
2991		# overlap with the ABI checking done above, but this also
2992		# flushes out non-ABI interface differences along with the
2993		# other information.
2994		echo "\n==== Diff ELF runtime attributes" \
2995		    "(since last build) ====\n" | \
2996		    tee -a $LOGFILE >> $mail_msg_file >> $mail_msg_file
2997
2998		if [[ -f $elf_ddir.ref/runtime.attr ]]; then
2999			diff $elf_ddir.ref/runtime.attr \
3000				$elf_ddir/runtime.attr \
3001				>> $mail_msg_file
3002		fi
3003	fi
3004
3005	# If -u set, copy contents of ELF-data.$MACH to the parent workspace.
3006	if [[ "$u_FLAG" = "y" ]]; then
3007		p_elf_ddir=$PARENT_WS/usr/src/ELF-data.$MACH
3008
3009		# If parent lacks the ELF-data.$MACH directory, create it
3010		if [[ ! -d $p_elf_ddir ]]; then
3011			staffer mkdir -p $p_elf_ddir
3012		fi
3013
3014		# These files are used asynchronously by other builds for ABI
3015		# verification, as above for the -A option. As such, we require
3016		# the file replacement to be atomic. Copy the data to a temp
3017		# file in the same filesystem and then rename into place.
3018		(
3019			cd $elf_ddir
3020			for elf_dfile in *; do
3021				staffer cp $elf_dfile \
3022				    ${p_elf_ddir}/${elf_dfile}.new
3023				staffer mv -f ${p_elf_ddir}/${elf_dfile}.new \
3024				    ${p_elf_ddir}/${elf_dfile}
3025			done
3026		)
3027	fi
3028fi
3029
3030# DEBUG lint of kernel begins
3031
3032if [ "$i_CMD_LINE_FLAG" = "n" -a "$l_FLAG" = "y" ]; then
3033	if [ "$LINTDIRS" = "" ]; then
3034		# LINTDIRS="$SRC/uts y $SRC/stand y $SRC/psm y"
3035		LINTDIRS="$SRC y"
3036	fi
3037	set $LINTDIRS
3038	while [ $# -gt 0 ]; do
3039		dolint $1 $2; shift; shift
3040	done
3041else
3042	echo "\n==== No '$MAKE lint' ====\n" >> $LOGFILE
3043fi
3044
3045# "make check" begins
3046
3047if [ "$i_CMD_LINE_FLAG" = "n" -a "$C_FLAG" = "y" ]; then
3048	# remove old check.out
3049	rm -f $SRC/check.out
3050
3051	rm -f $SRC/check-${MACH}.out
3052	cd $SRC
3053	$MAKE -ek check ROOT="$checkroot" 2>&1 | tee -a $SRC/check-${MACH}.out \
3054	    >> $LOGFILE
3055	echo "\n==== cstyle/hdrchk errors ====\n" >> $mail_msg_file
3056
3057	grep ":" $SRC/check-${MACH}.out |
3058		egrep -v "Ignoring unknown host" | \
3059		sort | uniq >> $mail_msg_file
3060else
3061	echo "\n==== No '$MAKE check' ====\n" >> $LOGFILE
3062fi
3063
3064echo "\n==== Find core files ====\n" | \
3065    tee -a $LOGFILE >> $mail_msg_file
3066
3067find $abssrcdirs -name core -a -type f -exec file {} \; | \
3068	tee -a $LOGFILE >> $mail_msg_file
3069
3070if [ "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then
3071	echo "\n==== Diff unreferenced files (since last build) ====\n" \
3072	    | tee -a $LOGFILE >>$mail_msg_file
3073	rm -f $SRC/unref-${MACH}.ref
3074	if [ -f $SRC/unref-${MACH}.out ]; then
3075		mv $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref
3076	fi
3077
3078	findunref -S $SCM_TYPE -t $SRC/.build.tstamp -s usr $CODEMGR_WS \
3079	    ${TOOLS}/findunref/exception_list 2>> $mail_msg_file | \
3080	    sort > $SRC/unref-${MACH}.out
3081
3082	if [ ! -f $SRC/unref-${MACH}.ref ]; then
3083		cp $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref
3084	fi
3085
3086	diff $SRC/unref-${MACH}.ref $SRC/unref-${MACH}.out >>$mail_msg_file
3087fi
3088
3089#
3090# Generate the OpenSolaris deliverables if requested.  Some of these
3091# steps need to come after findunref and are commented below.
3092#
3093
3094# If we are doing an OpenSolaris _source_ build (-S O) then we do
3095# not have usr/closed available to us to generate closedbins from,
3096# so skip this part.
3097if [ "$SO_FLAG" = n -a "$O_FLAG" = y -a "$build_ok" = y ]; then
3098	echo "\n==== Generating OpenSolaris tarballs ====\n" | \
3099	    tee -a $mail_msg_file >> $LOGFILE
3100
3101	cd $CODEMGR_WS
3102
3103	#
3104	# This step grovels through the package manifests, so it
3105	# must come after findunref.
3106	#
3107	# We assume no DEBUG vs non-DEBUG package content variation
3108	# here; if that changes, then the "make all" in $SRC/pkg will
3109	# need to be moved into the conditionals and repeated for each
3110	# different build.
3111	#
3112	echo "Generating closed binaries tarball(s)..." >> $LOGFILE
3113	closed_basename=on-closed-bins
3114	if [ "$D_FLAG" = y ]; then
3115		bindrop "$closed_basename" >>"$LOGFILE" 2>&1
3116		if (( $? != 0 )) ; then
3117			echo "Couldn't create DEBUG closed binaries." |
3118			    tee -a $mail_msg_file >> $LOGFILE
3119			build_ok=n
3120		fi
3121	fi
3122	if [ "$F_FLAG" = n ]; then
3123		bindrop -n "$closed_basename-nd" >>"$LOGFILE" 2>&1
3124		if (( $? != 0 )) ; then
3125			echo "Couldn't create non-DEBUG closed binaries." |
3126			    tee -a $mail_msg_file >> $LOGFILE
3127			build_ok=n
3128		fi
3129	fi
3130
3131	echo "Generating README.opensolaris..." >> $LOGFILE
3132	cat $SRC/tools/opensolaris/README.opensolaris.tmpl | \
3133	    mkreadme_osol $CODEMGR_WS/README.opensolaris >> $LOGFILE 2>&1
3134	if (( $? != 0 )) ; then
3135		echo "Couldn't create README.opensolaris." |
3136		    tee -a $mail_msg_file >> $LOGFILE
3137		build_ok=n
3138	fi
3139fi
3140
3141# Verify that the usual lists of files, such as exception lists,
3142# contain only valid references to files.  If the build has failed,
3143# then don't check the proto area.
3144CHECK_PATHS=${CHECK_PATHS:-y}
3145if [ "$CHECK_PATHS" = y -a "$N_FLAG" != y ]; then
3146	echo "\n==== Check lists of files ====\n" | tee -a $LOGFILE \
3147		>>$mail_msg_file
3148	arg=-b
3149	[ "$build_ok" = y ] && arg=
3150	checkpaths $arg $checkroot 2>&1 | tee -a $LOGFILE >>$mail_msg_file
3151fi
3152
3153if [ "$M_FLAG" != "y" -a "$build_ok" = y ]; then
3154	echo "\n==== Impact on file permissions ====\n" \
3155		>> $mail_msg_file
3156
3157	abspkgdefs=
3158	abspkg=
3159	for d in $abssrcdirs; do
3160		if [ -d "$d/pkgdefs" ]; then
3161			abspkgdefs="$abspkgdefs $d"
3162		fi
3163		if [ -d "$d/pkg" ]; then
3164			abspkg="$abspkg $d"
3165		fi
3166	done
3167
3168	if [ -n "$abspkgdefs" ]; then
3169		pmodes -qvdP \
3170		    `find $abspkgdefs -name pkginfo.tmpl -print -o \
3171		    -name .del\* -prune | sed -e 's:/pkginfo.tmpl$::' | \
3172		    sort -u` >> $mail_msg_file
3173	fi
3174
3175	if [ -n "$abspkg" ]; then
3176		for d in "$abspkg"; do
3177			( cd $d/pkg ; $MAKE -e pmodes ) >> $mail_msg_file
3178		done
3179	fi
3180fi
3181
3182if [ "$w_FLAG" = "y" -a "$build_ok" = "y" ]; then
3183	if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
3184		do_wsdiff DEBUG $ROOT.prev $ROOT
3185	fi
3186
3187	if [[ "$MULTI_PROTO" = yes && "$F_FLAG" = n ]]; then
3188		do_wsdiff non-DEBUG $ROOT-nd.prev $ROOT-nd
3189	fi
3190fi
3191
3192END_DATE=`date`
3193echo "==== Nightly $maketype build completed: $END_DATE ====" | \
3194    tee -a $LOGFILE >> $build_time_file
3195
3196typeset -i10 hours
3197typeset -Z2 minutes
3198typeset -Z2 seconds
3199
3200elapsed_time=$SECONDS
3201((hours = elapsed_time / 3600 ))
3202((minutes = elapsed_time / 60  % 60))
3203((seconds = elapsed_time % 60))
3204
3205echo "\n==== Total build time ====" | \
3206    tee -a $LOGFILE >> $build_time_file
3207echo "\nreal    ${hours}:${minutes}:${seconds}" | \
3208    tee -a $LOGFILE >> $build_time_file
3209
3210if [ "$u_FLAG" = "y" -a "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then
3211	staffer cp ${SRC}/unref-${MACH}.out $PARENT_WS/usr/src/
3212
3213	#
3214	# Produce a master list of unreferenced files -- ideally, we'd
3215	# generate the master just once after all of the nightlies
3216	# have finished, but there's no simple way to know when that
3217	# will be.  Instead, we assume that we're the last nightly to
3218	# finish and merge all of the unref-${MACH}.out files in
3219	# $PARENT_WS/usr/src/.  If we are in fact the final ${MACH} to
3220	# finish, then this file will be the authoritative master
3221	# list.  Otherwise, another ${MACH}'s nightly will eventually
3222	# overwrite ours with its own master, but in the meantime our
3223	# temporary "master" will be no worse than any older master
3224	# which was already on the parent.
3225	#
3226
3227	set -- $PARENT_WS/usr/src/unref-*.out
3228	cp "$1" ${TMPDIR}/unref.merge
3229	shift
3230
3231	for unreffile; do
3232		comm -12 ${TMPDIR}/unref.merge "$unreffile" > ${TMPDIR}/unref.$$
3233		mv ${TMPDIR}/unref.$$ ${TMPDIR}/unref.merge
3234	done
3235
3236	staffer cp ${TMPDIR}/unref.merge $PARENT_WS/usr/src/unrefmaster.out
3237fi
3238
3239#
3240# All done save for the sweeping up.
3241# (whichever exit we hit here will trigger the "cleanup" trap which
3242# optionally sends mail on completion).
3243#
3244if [ "$build_ok" = "y" ]; then
3245	exit 0
3246fi
3247exit 1
3248