xref: /illumos-gate/usr/src/tools/scripts/nightly (revision be0ffda9)
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# Copyright (c) 2017 by Delphix. All rights reserved.
29# Copyright 2019 Joyent, Inc.
30# Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
31# Copyright 2019 Peter Trible.
32#
33# Based on the nightly script from the integration folks,
34# Mostly modified and owned by mike_s.
35# Changes also by kjc, dmk.
36#
37# BRINGOVER_WS may be specified in the env file.
38# The default is the old behavior of CLONE_WS
39#
40# -i on the command line, means fast options, so when it's on the
41# command line (only), check builds are skipped no matter what
42# the setting of their individual flags are in NIGHTLY_OPTIONS.
43#
44# OPTHOME  may be set in the environment to override /opt
45#
46
47#
48# The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
49# under certain circumstances, which can really screw things up; unset it.
50#
51unset CDPATH
52
53# Get the absolute path of the nightly script that the user invoked.  This
54# may be a relative path, and we need to do this before changing directory.
55nightly_path=`whence $0`
56
57#
58# Keep track of where we found nightly so we can invoke the matching
59# which_scm script.  If that doesn't work, don't go guessing, just rely
60# on the $PATH settings, which will generally give us either /opt/onbld
61# or the user's workspace.
62#
63WHICH_SCM=$(dirname $nightly_path)/which_scm
64if [[ ! -x $WHICH_SCM ]]; then
65	WHICH_SCM=which_scm
66fi
67
68function fatal_error
69{
70	print -u2 "nightly: $*"
71	exit 1
72}
73
74#
75# Function to do a DEBUG and non-DEBUG build. Needed because we might
76# need to do another for the source build, and since we only deliver DEBUG or
77# non-DEBUG packages.
78#
79# usage: normal_build
80#
81function normal_build {
82
83	typeset orig_p_FLAG="$p_FLAG"
84	typeset crypto_signer="$CODESIGN_USER"
85
86	suffix=""
87
88	# non-DEBUG build begins
89
90	if [ "$F_FLAG" = "n" ]; then
91		set_non_debug_build_flags
92		CODESIGN_USER="$crypto_signer" \
93		    build "non-DEBUG" "$suffix-nd" "-nd" "$MULTI_PROTO"
94	else
95		echo "\n==== No non-DEBUG $open_only build ====\n" >> "$LOGFILE"
96	fi
97
98	# non-DEBUG build ends
99
100	# DEBUG build begins
101
102	if [ "$D_FLAG" = "y" ]; then
103		set_debug_build_flags
104		CODESIGN_USER="$crypto_signer" \
105		    build "DEBUG" "$suffix" "" "$MULTI_PROTO"
106	else
107		echo "\n==== No DEBUG $open_only build ====\n" >> "$LOGFILE"
108	fi
109
110	# DEBUG build ends
111
112	p_FLAG="$orig_p_FLAG"
113}
114
115#
116# usage: run_hook HOOKNAME ARGS...
117#
118# If variable "$HOOKNAME" is defined, insert a section header into
119# our logs and then run the command with ARGS
120#
121function run_hook {
122	HOOKNAME=$1
123	eval HOOKCMD=\$$HOOKNAME
124	shift
125
126	if [ -n "$HOOKCMD" ]; then
127		(
128			echo "\n==== Running $HOOKNAME command: $HOOKCMD ====\n"
129			( $HOOKCMD "$@" 2>&1 )
130			if [ "$?" -ne 0 ]; then
131				# Let exit status propagate up
132				touch $TMPDIR/abort
133			fi
134		) | tee -a $mail_msg_file >> $LOGFILE
135
136		if [ -f $TMPDIR/abort ]; then
137			build_ok=n
138			echo "\nAborting at request of $HOOKNAME" |
139				tee -a $mail_msg_file >> $LOGFILE
140			exit 1
141		fi
142	fi
143}
144
145# Return library search directive as function of given root.
146function myldlibs {
147	echo "-L$1/lib -L$1/usr/lib"
148}
149
150# Return header search directive as function of given root.
151function myheaders {
152	echo "-I$1/usr/include"
153}
154
155#
156# Function to do the build, including package generation.
157# usage: build LABEL SUFFIX ND MULTIPROTO
158# - LABEL is used to tag build output.
159# - SUFFIX is used to distinguish files (e.g., DEBUG vs non-DEBUG,
160#   open-only vs full tree).
161# - ND is "-nd" (non-DEBUG builds) or "" (DEBUG builds).
162# - If MULTIPROTO is "yes", it means to name the proto area according to
163#   SUFFIX.  Otherwise ("no"), (re)use the standard proto area.
164#
165function build {
166	LABEL=$1
167	SUFFIX=$2
168	ND=$3
169	MULTIPROTO=$4
170	INSTALLOG=install${SUFFIX}-${MACH}
171	NOISE=noise${SUFFIX}-${MACH}
172	PKGARCHIVE=${PKGARCHIVE_ORIG}${SUFFIX}
173
174	ORIGROOT=$ROOT
175	[ $MULTIPROTO = no ] || export ROOT=$ROOT$SUFFIX
176
177	export ENVLDLIBS1=`myldlibs $ROOT`
178	export ENVCPPFLAGS1=`myheaders $ROOT`
179
180	this_build_ok=y
181	#
182	#	Build OS-Networking source
183	#
184	echo "\n==== Building OS-Net source at `date` ($LABEL) ====\n" \
185		>> $LOGFILE
186
187	rm -f $SRC/${INSTALLOG}.out
188	cd $SRC
189	/bin/time $MAKE -e install 2>&1 | \
190	    tee -a $SRC/${INSTALLOG}.out >> $LOGFILE
191
192	echo "\n==== Build errors ($LABEL) ====\n" >> $mail_msg_file
193	egrep ":" $SRC/${INSTALLOG}.out |
194	    egrep -e "(^${MAKE}:|[ 	]error[: 	\n])" | \
195	    egrep -v "Ignoring unknown host" | \
196	    egrep -v "cc .* -o error " | \
197	    egrep -v "warning" | tee $TMPDIR/build_errs${SUFFIX} \
198	    >> $mail_msg_file
199	    sed -n "/^Undefined[ 	]*first referenced$/,/^ld: fatal:/p" \
200	    < $SRC/${INSTALLOG}.out >> $mail_msg_file
201	if [[ -s $TMPDIR/build_errs${SUFFIX} ]]; then
202		build_ok=n
203		this_build_ok=n
204	fi
205	grep "bootblock image is .* bytes too big" $SRC/${INSTALLOG}.out \
206		>> $mail_msg_file
207	if [ "$?" = "0" ]; then
208		build_ok=n
209		this_build_ok=n
210	fi
211
212	echo "\n==== Build warnings ($LABEL) ====\n" >>$mail_msg_file
213	egrep -i 'warn:|warning:' $SRC/${INSTALLOG}.out \
214		| egrep -v '^tic:' \
215		| egrep -v "symbol (\`|')timezone' has differing types:" \
216		| egrep -v "parameter <PSTAMP> set to" \
217		| egrep -v "Ignoring unknown host" \
218		| egrep -v "redefining segment flags attribute for" \
219		| tee $TMPDIR/build_warnings${SUFFIX} >> $mail_msg_file
220	if [[ -s $TMPDIR/build_warnings${SUFFIX} ]]; then
221		build_ok=n
222		this_build_ok=n
223	fi
224
225	echo "\n==== Ended OS-Net source build at `date` ($LABEL) ====\n" \
226		>> $LOGFILE
227
228	echo "\n==== Elapsed build time ($LABEL) ====\n" >>$mail_msg_file
229	tail -3  $SRC/${INSTALLOG}.out >>$mail_msg_file
230
231	if [ "$i_FLAG" = "n" ]; then
232		rm -f $SRC/${NOISE}.ref
233		if [ -f $SRC/${NOISE}.out ]; then
234			mv $SRC/${NOISE}.out $SRC/${NOISE}.ref
235		fi
236		grep : $SRC/${INSTALLOG}.out \
237			| egrep -v '^/' \
238			| egrep -v '^(Start|Finish|real|user|sys|./bld_awk)' \
239			| egrep -v '^tic:' \
240			| egrep -v '^mcs' \
241			| egrep -v '^LD_LIBRARY_PATH=' \
242			| egrep -v 'ar: creating' \
243			| egrep -v 'ar: writing' \
244			| egrep -v 'conflicts:' \
245			| egrep -v ':saved created' \
246			| egrep -v '^stty.*c:' \
247			| egrep -v '^mfgname.c:' \
248			| egrep -v '^uname-i.c:' \
249			| egrep -v '^volumes.c:' \
250			| egrep -v '^lint library construction:' \
251			| egrep -v 'tsort: INFORM:' \
252			| egrep -v 'stripalign:' \
253			| egrep -v 'chars, width' \
254			| egrep -v "symbol (\`|')timezone' has differing types:" \
255			| egrep -v 'PSTAMP' \
256			| egrep -v '^Manifying' \
257			| egrep -v 'Ignoring unknown host' \
258			| egrep -v 'Processing method:' \
259			| egrep -v '^Writing' \
260			| egrep -v 'spellin1:' \
261			| egrep -v '^adding:' \
262			| egrep -v "^echo 'msgid" \
263			| egrep -v '^echo ' \
264			| egrep -v '\.c:$' \
265			| egrep -v '^Adding file:' \
266			| egrep -v 'CLASSPATH=' \
267			| egrep -v '\/var\/mail\/:saved' \
268			| egrep -v -- '-DUTS_VERSION=' \
269			| egrep -v '^Running Mkbootstrap' \
270			| egrep -v '^Applet length read:' \
271			| egrep -v 'bytes written:' \
272			| egrep -v '^File:SolarisAuthApplet.bin' \
273			| egrep -v -i 'jibversion' \
274			| egrep -v '^Output size:' \
275			| egrep -v '^Solo size statistics:' \
276			| egrep -v '^Using ROM API Version' \
277			| egrep -v '^Zero Signature length:' \
278			| egrep -v '^Note \(probably harmless\):' \
279			| egrep -v '::' \
280			| egrep -v '^\+' \
281			| egrep -v 'svccfg-native -s svc:/' \
282			| sort | uniq >$SRC/${NOISE}.out
283		if [ ! -f $SRC/${NOISE}.ref ]; then
284			cp $SRC/${NOISE}.out $SRC/${NOISE}.ref
285		fi
286		echo "\n==== Build noise differences ($LABEL) ====\n" \
287			>>$mail_msg_file
288		diff $SRC/${NOISE}.ref $SRC/${NOISE}.out >>$mail_msg_file
289	fi
290
291	#
292	#	Re-sign selected binaries using signing server
293	#	(gatekeeper builds only)
294	#
295	if [ -n "$CODESIGN_USER" -a "$this_build_ok" = "y" ]; then
296		echo "\n==== Signing proto area at `date` ====\n" >> $LOGFILE
297		signing_file="${TMPDIR}/signing"
298		rm -f ${signing_file}
299		export CODESIGN_USER
300		signproto $SRC/tools/codesign/creds 2>&1 | \
301			tee -a ${signing_file} >> $LOGFILE
302		echo "\n==== Finished signing proto area at `date` ====\n" \
303		    >> $LOGFILE
304		echo "\n==== Crypto module signing errors ($LABEL) ====\n" \
305		    >> $mail_msg_file
306		egrep 'WARNING|ERROR' ${signing_file} >> $mail_msg_file
307		if (( $? == 0 )) ; then
308			build_ok=n
309			this_build_ok=n
310		fi
311	fi
312
313	#
314	#	Building Packages
315	#
316	if [ "$p_FLAG" = "y" -a "$this_build_ok" = "y" ]; then
317		if [ -d $SRC/pkg ]; then
318			echo "\n==== Creating $LABEL packages at `date` ====\n" \
319				>> $LOGFILE
320			echo "Clearing out $PKGARCHIVE ..." >> $LOGFILE
321			rm -rf $PKGARCHIVE >> "$LOGFILE" 2>&1
322			mkdir -p $PKGARCHIVE >> "$LOGFILE" 2>&1
323
324			rm -f $SRC/pkg/${INSTALLOG}.out
325			cd $SRC/pkg
326			/bin/time $MAKE -e install 2>&1 | \
327			    tee -a $SRC/pkg/${INSTALLOG}.out >> $LOGFILE
328
329			echo "\n==== package build errors ($LABEL) ====\n" \
330				>> $mail_msg_file
331
332			egrep "${MAKE}|ERROR|WARNING" $SRC/pkg/${INSTALLOG}.out | \
333				grep ':' | \
334				grep -v PSTAMP | \
335				egrep -v "Ignoring unknown host" | \
336				tee $TMPDIR/package >> $mail_msg_file
337			if [[ -s $TMPDIR/package ]]; then
338				build_extras_ok=n
339				this_build_ok=n
340			fi
341		else
342			#
343			# Handle it gracefully if -p was set but there so
344			# no pkg directory.
345			#
346			echo "\n==== No $LABEL packages to build ====\n" \
347				>> $LOGFILE
348		fi
349	else
350		echo "\n==== Not creating $LABEL packages ====\n" >> $LOGFILE
351	fi
352
353	ROOT=$ORIGROOT
354}
355
356#
357# Build and install the onbld tools.
358#
359# usage: build_tools DESTROOT
360#
361# returns non-zero status if the build was successful.
362#
363function build_tools {
364	DESTROOT=$1
365
366	INSTALLOG=install-${MACH}
367
368	echo "\n==== Building tools at `date` ====\n" \
369		>> $LOGFILE
370
371	rm -f ${TOOLS}/${INSTALLOG}.out
372	cd ${TOOLS}
373	/bin/time $MAKE TOOLS_PROTO=${DESTROOT} -e install 2>&1 | \
374	    tee -a ${TOOLS}/${INSTALLOG}.out >> $LOGFILE
375
376	echo "\n==== Tools build errors ====\n" >> $mail_msg_file
377
378	egrep ":" ${TOOLS}/${INSTALLOG}.out |
379		egrep -e "(${MAKE}:|[ 	]error[: 	\n])" | \
380		egrep -v "Ignoring unknown host" | \
381		egrep -v warning | tee $TMPDIR/tools_errors >> $mail_msg_file
382
383	if [[ -s $TMPDIR/tools_errors ]]; then
384		return 1
385	fi
386	return 0
387}
388
389function staffer {
390	if [ $ISUSER -ne 0 ]; then
391		"$@"
392	else
393		arg="\"$1\""
394		shift
395		for i
396		do
397			arg="$arg \"$i\""
398		done
399		eval su $STAFFER -c \'$arg\'
400	fi
401}
402
403#
404# Verify that the closed bins are present
405#
406function check_closed_bins {
407	if [[ -n "$ON_CLOSED_BINS" && ! -d "$ON_CLOSED_BINS" ]]; then
408		echo "ON_CLOSED_BINS must point to the closed binaries tree."
409		build_ok=n
410		exit 1
411	fi
412}
413
414#
415# wrapper over wsdiff.
416# usage: do_wsdiff LABEL OLDPROTO NEWPROTO
417#
418function do_wsdiff {
419	label=$1
420	oldproto=$2
421	newproto=$3
422
423	wsdiff="wsdiff"
424	[ "$t_FLAG" = y ] && wsdiff="wsdiff -t"
425
426	echo "\n==== Getting object changes since last build at `date`" \
427	    "($label) ====\n" | tee -a $LOGFILE >> $mail_msg_file
428	$wsdiff -s -r ${TMPDIR}/wsdiff.results $oldproto $newproto 2>&1 | \
429		    tee -a $LOGFILE >> $mail_msg_file
430	echo "\n==== Object changes determined at `date` ($label) ====\n" | \
431	    tee -a $LOGFILE >> $mail_msg_file
432}
433
434#
435# Functions for setting build flags (DEBUG/non-DEBUG).  Keep them
436# together.
437#
438
439function set_non_debug_build_flags {
440	export RELEASE_BUILD ; RELEASE_BUILD=
441	unset EXTRA_OPTIONS
442	unset EXTRA_CFLAGS
443	if [ -n "$RELEASE_CONSOLE_COLOR" ]; then
444		export DEFAULT_CONSOLE_COLOR="$RELEASE_CONSOLE_COLOR"
445	fi
446}
447
448function set_debug_build_flags {
449	unset RELEASE_BUILD
450	unset EXTRA_OPTIONS
451	unset EXTRA_CFLAGS
452
453	if [ -n "$DEBUG_CONSOLE_COLOR" ]; then
454		export DEFAULT_CONSOLE_COLOR="$DEBUG_CONSOLE_COLOR"
455	fi
456}
457
458
459MACH=`uname -p`
460
461if [ "$OPTHOME" = "" ]; then
462	OPTHOME=/opt
463	export OPTHOME
464fi
465
466USAGE='Usage: nightly [-in] [+t] [-V VERS ] <env_file>
467
468Where:
469	-i	Fast incremental options (no clobber, check)
470	-n      Do not do a bringover
471	+t	Use the build tools in $ONBLD_TOOLS/bin
472	-V VERS set the build version string to VERS
473
474	<env_file>  file in Bourne shell syntax that sets and exports
475	variables that configure the operation of this script and many of
476	the scripts this one calls. If <env_file> does not exist,
477	it will be looked for in $OPTHOME/onbld/env.
478
479non-DEBUG is the default build type. Build options can be set in the
480NIGHTLY_OPTIONS variable in the <env_file> as follows:
481
482	-A	check for ABI differences in .so files
483	-C	check for cstyle/hdrchk errors
484	-D	do a build with DEBUG on
485	-F	do _not_ do a non-DEBUG build
486	-G	gate keeper default group of options (-au)
487	-I	integration engineer default group of options (-ampu)
488	-M	do not run pmodes (safe file permission checker)
489	-N	do not run protocmp
490	-R	default group of options for building a release (-mp)
491	-U	update proto area in the parent
492	-V VERS set the build version string to VERS
493	-f	find unreferenced files
494	-i	do an incremental build (no "make clobber")
495	-m	send mail to $MAILTO at end of build
496	-n      do not do a bringover
497	-p	create packages
498	-r	check ELF runtime attributes in the proto area
499	-t	build and use the tools in $SRC/tools (default setting)
500	+t	Use the build tools in $ONBLD_TOOLS/bin
501	-u	update proto_list_$MACH and friends in the parent workspace;
502		when used with -f, also build an unrefmaster.out in the parent
503	-w	report on differences between previous and current proto areas
504'
505#
506#	A log file will be generated under the name $LOGFILE
507#	for partially completed build and log.`date '+%F'`
508#	in the same directory for fully completed builds.
509#
510
511# default values for low-level FLAGS; G I R are group FLAGS
512A_FLAG=n
513C_FLAG=n
514D_FLAG=n
515F_FLAG=n
516f_FLAG=n
517i_FLAG=n; i_CMD_LINE_FLAG=n
518M_FLAG=n
519m_FLAG=n
520N_FLAG=n
521n_FLAG=n
522p_FLAG=n
523r_FLAG=n
524t_FLAG=y
525U_FLAG=n
526u_FLAG=n
527V_FLAG=n
528w_FLAG=n
529W_FLAG=n
530#
531build_ok=y
532build_extras_ok=y
533
534#
535# examine arguments
536#
537
538OPTIND=1
539while getopts +intV:W FLAG
540do
541	case $FLAG in
542	  i )	i_FLAG=y; i_CMD_LINE_FLAG=y
543		;;
544	  n )	n_FLAG=y
545		;;
546	 +t )	t_FLAG=n
547		;;
548	  V )	V_FLAG=y
549		V_ARG="$OPTARG"
550		;;
551	  W )   W_FLAG=y
552		;;
553	 \? )	echo "$USAGE"
554		exit 1
555		;;
556	esac
557done
558
559# correct argument count after options
560shift `expr $OPTIND - 1`
561
562# test that the path to the environment-setting file was given
563if [ $# -ne 1 ]; then
564	echo "$USAGE"
565	exit 1
566fi
567
568# check if user is running nightly as root
569# ISUSER is set non-zero if an ordinary user runs nightly, or is zero
570# when root invokes nightly.
571/usr/bin/id | grep '^uid=0(' >/dev/null 2>&1
572ISUSER=$?;	export ISUSER
573
574#
575# force locale to C
576LANG=C;		export LANG
577LC_ALL=C;	export LC_ALL
578LC_COLLATE=C;	export LC_COLLATE
579LC_CTYPE=C;	export LC_CTYPE
580LC_MESSAGES=C;	export LC_MESSAGES
581LC_MONETARY=C;	export LC_MONETARY
582LC_NUMERIC=C;	export LC_NUMERIC
583LC_TIME=C;	export LC_TIME
584
585# clear environment variables we know to be bad for the build
586unset LD_OPTIONS
587unset LD_AUDIT		LD_AUDIT_32		LD_AUDIT_64
588unset LD_BIND_NOW	LD_BIND_NOW_32		LD_BIND_NOW_64
589unset LD_BREADTH	LD_BREADTH_32		LD_BREADTH_64
590unset LD_CONFIG		LD_CONFIG_32		LD_CONFIG_64
591unset LD_DEBUG		LD_DEBUG_32		LD_DEBUG_64
592unset LD_DEMANGLE	LD_DEMANGLE_32		LD_DEMANGLE_64
593unset LD_FLAGS		LD_FLAGS_32		LD_FLAGS_64
594unset LD_LIBRARY_PATH	LD_LIBRARY_PATH_32	LD_LIBRARY_PATH_64
595unset LD_LOADFLTR	LD_LOADFLTR_32		LD_LOADFLTR_64
596unset LD_NOAUDIT	LD_NOAUDIT_32		LD_NOAUDIT_64
597unset LD_NOAUXFLTR	LD_NOAUXFLTR_32		LD_NOAUXFLTR_64
598unset LD_NOCONFIG	LD_NOCONFIG_32		LD_NOCONFIG_64
599unset LD_NODIRCONFIG	LD_NODIRCONFIG_32	LD_NODIRCONFIG_64
600unset LD_NODIRECT	LD_NODIRECT_32		LD_NODIRECT_64
601unset LD_NOLAZYLOAD	LD_NOLAZYLOAD_32	LD_NOLAZYLOAD_64
602unset LD_NOOBJALTER	LD_NOOBJALTER_32	LD_NOOBJALTER_64
603unset LD_NOVERSION	LD_NOVERSION_32		LD_NOVERSION_64
604unset LD_ORIGIN		LD_ORIGIN_32		LD_ORIGIN_64
605unset LD_PRELOAD	LD_PRELOAD_32		LD_PRELOAD_64
606unset LD_PROFILE	LD_PROFILE_32		LD_PROFILE_64
607
608unset CONFIG
609unset GROUP
610unset OWNER
611unset REMOTE
612unset ENV
613unset ARCH
614unset CLASSPATH
615unset NAME
616
617#
618# To get ONBLD_TOOLS from the environment, it must come from the env file.
619# If it comes interactively, it is generally TOOLS_PROTO, which will be
620# clobbered before the compiler version checks, which will therefore fail.
621#
622unset ONBLD_TOOLS
623
624#
625#	Setup environmental variables
626#
627if [ -f /etc/nightly.conf ]; then
628	. /etc/nightly.conf
629fi
630
631if [ -f $1 ]; then
632	if [[ $1 = */* ]]; then
633		. $1
634	else
635		. ./$1
636	fi
637else
638	if [ -f $OPTHOME/onbld/env/$1 ]; then
639		. $OPTHOME/onbld/env/$1
640	else
641		echo "Cannot find env file as either $1 or $OPTHOME/onbld/env/$1"
642		exit 1
643	fi
644fi
645
646# contents of stdenv.sh inserted after next line:
647# STDENV_START
648# STDENV_END
649
650# Check if we have sufficient data to continue...
651[[ -v CODEMGR_WS ]] || fatal_error "Error: Variable CODEMGR_WS not set."
652if  [[ "${NIGHTLY_OPTIONS}" == ~(F)n ]] ; then
653	# Check if the gate data are valid if we don't do a "bringover" below
654	[[ -d "${CODEMGR_WS}" ]] || \
655		fatal_error "Error: ${CODEMGR_WS} is not a directory."
656	[[ -f "${CODEMGR_WS}/usr/src/Makefile" ]] || \
657		fatal_error "Error: ${CODEMGR_WS}/usr/src/Makefile not found."
658fi
659
660#
661# place ourselves in a new task, respecting BUILD_PROJECT if set.
662#
663if [ -z "$BUILD_PROJECT" ]; then
664	/usr/bin/newtask -c $$
665else
666	/usr/bin/newtask -c $$ -p $BUILD_PROJECT
667fi
668
669ps -o taskid= -p $$ | read build_taskid
670ps -o project= -p $$ | read build_project
671
672#
673# See if NIGHTLY_OPTIONS is set
674#
675if [ "$NIGHTLY_OPTIONS" = "" ]; then
676	NIGHTLY_OPTIONS="-aBm"
677fi
678
679#
680# If BRINGOVER_WS was not specified, let it default to CLONE_WS
681#
682if [ "$BRINGOVER_WS" = "" ]; then
683	BRINGOVER_WS=$CLONE_WS
684fi
685
686#
687# If BRINGOVER_FILES was not specified, default to usr
688#
689if [ "$BRINGOVER_FILES" = "" ]; then
690	BRINGOVER_FILES="usr"
691fi
692
693check_closed_bins
694
695#
696# Note: changes to the option letters here should also be applied to the
697#	bldenv script.  `d' is listed for backward compatibility.
698#
699NIGHTLY_OPTIONS=-${NIGHTLY_OPTIONS#-}
700OPTIND=1
701while getopts +ABCDdFfGIiMmNnpRrtUuwW FLAG $NIGHTLY_OPTIONS
702do
703	case $FLAG in
704	  A )	A_FLAG=y
705		;;
706	  B )	D_FLAG=y
707		;; # old version of D
708	  C )	C_FLAG=y
709		;;
710	  D )	D_FLAG=y
711		;;
712	  F )	F_FLAG=y
713		;;
714	  f )	f_FLAG=y
715		;;
716	  G )   u_FLAG=y
717		;;
718	  I )	m_FLAG=y
719		p_FLAG=y
720		u_FLAG=y
721		;;
722	  i )	i_FLAG=y
723		;;
724	  M )	M_FLAG=y
725		;;
726	  m )	m_FLAG=y
727		;;
728	  N )	N_FLAG=y
729		;;
730	  n )	n_FLAG=y
731		;;
732	  p )	p_FLAG=y
733		;;
734	  R )	m_FLAG=y
735		p_FLAG=y
736		;;
737	  r )	r_FLAG=y
738		;;
739	 +t )	t_FLAG=n
740		;;
741	  U )   if [ -z "${PARENT_ROOT}" ]; then
742			echo "PARENT_ROOT must be set if the U flag is" \
743			    "present in NIGHTLY_OPTIONS."
744			exit 1
745		fi
746		NIGHTLY_PARENT_ROOT=$PARENT_ROOT
747		if [ -n "${PARENT_TOOLS_ROOT}" ]; then
748			NIGHTLY_PARENT_TOOLS_ROOT=$PARENT_TOOLS_ROOT
749		fi
750		U_FLAG=y
751		;;
752	  u )	u_FLAG=y
753		;;
754	  w )	w_FLAG=y
755		;;
756	  W )   W_FLAG=y
757		;;
758	 \? )	echo "$USAGE"
759		exit 1
760		;;
761	esac
762done
763
764if [ $ISUSER -ne 0 ]; then
765	# Set default value for STAFFER, if needed.
766	if [ -z "$STAFFER" -o "$STAFFER" = "nobody" ]; then
767		STAFFER=`/usr/xpg4/bin/id -un`
768		export STAFFER
769	fi
770fi
771
772if [ -z "$MAILTO" -o "$MAILTO" = "nobody" ]; then
773	MAILTO=$STAFFER
774	export MAILTO
775fi
776
777PATH="$OPTHOME/onbld/bin:$OPTHOME/onbld/bin/${MACH}:/usr/ccs/bin"
778PATH="$PATH:$OPTHOME/SUNWspro/bin:/usr/bin:/usr/sbin:/usr/ucb"
779PATH="$PATH:/usr/openwin/bin:/usr/sfw/bin:/opt/sfw/bin:."
780export PATH
781
782# roots of source trees, both relative to $SRC and absolute.
783relsrcdirs="."
784abssrcdirs="$SRC"
785
786PROTOCMPTERSE="protocmp.terse -gu"
787POUND_SIGN="#"
788# have we set RELEASE_DATE in our env file?
789if [ -z "$RELEASE_DATE" ]; then
790	RELEASE_DATE=$(LC_ALL=C date +"%B %Y")
791fi
792BUILD_DATE=$(LC_ALL=C date +%Y-%b-%d)
793BASEWSDIR=$(basename $CODEMGR_WS)
794DEV_CM="\"@(#)SunOS Internal Development: $LOGNAME $BUILD_DATE [$BASEWSDIR]\""
795
796# we export POUND_SIGN, RELEASE_DATE and DEV_CM to speed up the build process
797# by avoiding repeated shell invocations to evaluate Makefile.master
798# definitions.
799export POUND_SIGN RELEASE_DATE DEV_CM
800
801maketype="distributed"
802if [[ -z "$MAKE" ]]; then
803	MAKE=dmake
804elif [[ ! -x "$MAKE" ]]; then
805	echo "\$MAKE is set to garbage in the environment"
806	exit 1
807fi
808export PATH
809export MAKE
810
811if [ "${SUNWSPRO}" != "" ]; then
812	PATH="${SUNWSPRO}/bin:$PATH"
813	export PATH
814fi
815
816hostname=$(uname -n)
817if [[ $DMAKE_MAX_JOBS != +([0-9]) || $DMAKE_MAX_JOBS -eq 0 ]]
818then
819	maxjobs=
820	if [[ -f $HOME/.make.machines ]]
821	then
822		# Note: there is a hard tab and space character in the []s
823		# below.
824		egrep -i "^[ 	]*$hostname[ 	\.]" \
825			$HOME/.make.machines | read host jobs
826		maxjobs=${jobs##*=}
827	fi
828
829	if [[ $maxjobs != +([0-9]) || $maxjobs -eq 0 ]]
830	then
831		# default
832		maxjobs=4
833	fi
834
835	export DMAKE_MAX_JOBS=$maxjobs
836fi
837
838DMAKE_MODE=parallel;
839export DMAKE_MODE
840
841if [ -z "${ROOT}" ]; then
842	echo "ROOT must be set."
843	exit 1
844fi
845
846#
847# if -V flag was given, reset VERSION to V_ARG
848#
849if [ "$V_FLAG" = "y" ]; then
850	VERSION=$V_ARG
851fi
852
853TMPDIR="/tmp/nightly.tmpdir.$$"
854export TMPDIR
855rm -rf ${TMPDIR}
856mkdir -p $TMPDIR || exit 1
857chmod 777 $TMPDIR
858
859#
860# Work around folks who have historically used GCC_ROOT and convert it to
861# GNUC_ROOT. We leave GCC_ROOT in the environment for now (though this could
862# mess up the case where multiple different gcc versions are being used to
863# shadow).
864#
865if [[ -n "${GCC_ROOT}" ]]; then
866	export GNUC_ROOT=${GCC_ROOT}
867fi
868
869#
870# Tools should only be built non-DEBUG.  Keep track of the tools proto
871# area path relative to $TOOLS, because the latter changes in an
872# export build.
873#
874# TOOLS_PROTO is included below for builds other than usr/src/tools
875# that look for this location.  For usr/src/tools, this will be
876# overridden on the $MAKE command line in build_tools().
877#
878TOOLS=${SRC}/tools
879TOOLS_PROTO_REL=proto/root_${MACH}-nd
880TOOLS_PROTO=${TOOLS}/${TOOLS_PROTO_REL};	export TOOLS_PROTO
881
882unset   CFLAGS LD_LIBRARY_PATH LDFLAGS
883
884# create directories that are automatically removed if the nightly script
885# fails to start correctly
886function newdir {
887	dir=$1
888	toadd=
889	while [ ! -d $dir ]; do
890		toadd="$dir $toadd"
891		dir=`dirname $dir`
892	done
893	torm=
894	newlist=
895	for dir in $toadd; do
896		if staffer mkdir $dir; then
897			newlist="$ISUSER $dir $newlist"
898			torm="$dir $torm"
899		else
900			[ -z "$torm" ] || staffer rmdir $torm
901			return 1
902		fi
903	done
904	newdirlist="$newlist $newdirlist"
905	return 0
906}
907newdirlist=
908
909[ -d $CODEMGR_WS ] || newdir $CODEMGR_WS || exit 1
910
911# since this script assumes the build is from full source, it nullifies
912# variables likely to have been set by a "ws" script; nullification
913# confines the search space for headers and libraries to the proto area
914# built from this immediate source.
915ENVLDLIBS1=
916ENVLDLIBS2=
917ENVLDLIBS3=
918ENVCPPFLAGS1=
919ENVCPPFLAGS2=
920ENVCPPFLAGS3=
921ENVCPPFLAGS4=
922PARENT_ROOT=
923
924export ENVLDLIBS3 ENVCPPFLAGS1 ENVCPPFLAGS2 ENVCPPFLAGS3 ENVCPPFLAGS4 \
925	ENVLDLIBS1 ENVLDLIBS2 PARENT_ROOT
926
927PKGARCHIVE_ORIG=$PKGARCHIVE
928
929#
930# Juggle the logs and optionally send mail on completion.
931#
932
933function logshuffle {
934	LLOG="$ATLOG/log.`date '+%F.%H:%M'`"
935	if [ -f $LLOG -o -d $LLOG ]; then
936		LLOG=$LLOG.$$
937	fi
938
939	rm -f "$ATLOG/latest" 2>/dev/null
940	mkdir -p $LLOG
941	export LLOG
942
943	if [ "$build_ok" = "y" ]; then
944		mv $ATLOG/proto_list_${MACH} $LLOG
945
946		if [ -f $ATLOG/proto_list_tools_${MACH} ]; then
947			mv $ATLOG/proto_list_tools_${MACH} $LLOG
948	        fi
949
950		if [ -f $TMPDIR/wsdiff.results ]; then
951			mv $TMPDIR/wsdiff.results $LLOG
952		fi
953
954		if [ -f $TMPDIR/wsdiff-nd.results ]; then
955			mv $TMPDIR/wsdiff-nd.results $LLOG
956		fi
957	fi
958
959	#
960	# Now that we're about to send mail, it's time to check the noise
961	# file.  In the event that an error occurs beyond this point, it will
962	# be recorded in the nightly.log file, but nowhere else.  This would
963	# include only errors that cause the copying of the noise log to fail
964	# or the mail itself not to be sent.
965	#
966
967	exec >>$LOGFILE 2>&1
968	if [ -s $build_noise_file ]; then
969		echo "\n==== Nightly build noise ====\n" |
970		    tee -a $LOGFILE >>$mail_msg_file
971		cat $build_noise_file >>$LOGFILE
972		cat $build_noise_file >>$mail_msg_file
973		echo | tee -a $LOGFILE >>$mail_msg_file
974	fi
975	rm -f $build_noise_file
976
977	case "$build_ok" in
978		y)
979			state=Completed
980			;;
981		i)
982			state=Interrupted
983			;;
984		*)
985			state=Failed
986			;;
987	esac
988
989	if [[ $state != "Interrupted" && $build_extras_ok != "y" ]]; then
990		state=Failed
991	fi
992
993	NIGHTLY_STATUS=$state
994	export NIGHTLY_STATUS
995
996	run_hook POST_NIGHTLY $state
997	run_hook SYS_POST_NIGHTLY $state
998
999	#
1000	# mailx(1) sets From: based on the -r flag
1001	# if it is given.
1002	#
1003	mailx_r=
1004	if [[ -n "${MAILFROM}" ]]; then
1005		mailx_r="-r ${MAILFROM}"
1006	fi
1007
1008	cat $build_time_file $build_environ_file $mail_msg_file \
1009	    > ${LLOG}/mail_msg
1010	if [ "$m_FLAG" = "y" ]; then
1011		cat ${LLOG}/mail_msg | /usr/bin/mailx ${mailx_r} -s \
1012	"Nightly ${MACH} Build of `basename ${CODEMGR_WS}` ${state}." \
1013			${MAILTO}
1014	fi
1015
1016	if [ "$u_FLAG" = "y" -a "$build_ok" = "y" ]; then
1017		staffer cp ${LLOG}/mail_msg $PARENT_WS/usr/src/mail_msg-${MACH}
1018		staffer cp $LOGFILE $PARENT_WS/usr/src/nightly-${MACH}.log
1019	fi
1020
1021	mv $LOGFILE $LLOG
1022
1023	ln -s "$LLOG" "$ATLOG/latest"
1024}
1025
1026#
1027#	Remove the locks and temporary files on any exit
1028#
1029function cleanup {
1030	logshuffle
1031
1032	[ -z "$lockfile" ] || staffer rm -f $lockfile
1033	[ -z "$atloglockfile" ] || rm -f $atloglockfile
1034	[ -z "$ulockfile" ] || staffer rm -f $ulockfile
1035	[ -z "$Ulockfile" ] || rm -f $Ulockfile
1036
1037	set -- $newdirlist
1038	while [ $# -gt 0 ]; do
1039		ISUSER=$1 staffer rmdir $2
1040		shift; shift
1041	done
1042	rm -rf $TMPDIR
1043}
1044
1045function cleanup_signal {
1046	build_ok=i
1047	# this will trigger cleanup(), above.
1048	exit 1
1049}
1050
1051trap cleanup 0
1052trap cleanup_signal 1 2 3 15
1053
1054#
1055# Generic lock file processing -- make sure that the lock file doesn't
1056# exist.  If it does, it should name the build host and PID.  If it
1057# doesn't, then make sure we can create it.  Clean up locks that are
1058# known to be stale (assumes host name is unique among build systems
1059# for the workspace).
1060#
1061function create_lock {
1062	lockf=$1
1063	lockvar=$2
1064
1065	ldir=`dirname $lockf`
1066	[ -d $ldir ] || newdir $ldir || exit 1
1067	eval $lockvar=$lockf
1068
1069	while ! staffer ln -s $hostname.$STAFFER.$$ $lockf 2> /dev/null; do
1070		basews=`basename $CODEMGR_WS`
1071		ls -l $lockf | nawk '{print $NF}' | IFS=. read host user pid
1072		if [ "$host" != "$hostname" ]; then
1073			echo "$MACH build of $basews apparently" \
1074			    "already started by $user on $host as $pid."
1075			exit 1
1076		elif kill -s 0 $pid 2>/dev/null; then
1077			echo "$MACH build of $basews already started" \
1078			    "by $user as $pid."
1079			exit 1
1080		else
1081			# stale lock; clear it out and try again
1082			rm -f $lockf
1083		fi
1084	done
1085}
1086
1087#
1088# Return the list of interesting proto areas, depending on the current
1089# options.
1090#
1091function allprotos {
1092	typeset roots="$ROOT"
1093
1094	if [[ "$F_FLAG" = n && "$MULTI_PROTO" = yes ]]; then
1095		roots="$roots $ROOT-nd"
1096	fi
1097
1098	echo $roots
1099}
1100
1101# Ensure no other instance of this script is running on this host.
1102# LOCKNAME can be set in <env_file>, and is by default, but is not
1103# required due to the use of $ATLOG below.
1104if [ -n "$LOCKNAME" ]; then
1105	create_lock /tmp/$LOCKNAME "lockfile"
1106fi
1107#
1108# Create from one, two, or three other locks:
1109#	$ATLOG/nightly.lock
1110#		- protects against multiple builds in same workspace
1111#	$PARENT_WS/usr/src/nightly.$MACH.lock
1112#		- protects against multiple 'u' copy-backs
1113#	$NIGHTLY_PARENT_ROOT/nightly.lock
1114#		- protects against multiple 'U' copy-backs
1115#
1116# Overriding ISUSER to 1 causes the lock to be created as root if the
1117# script is run as root.  The default is to create it as $STAFFER.
1118ISUSER=1 create_lock $ATLOG/nightly.lock "atloglockfile"
1119if [ "$u_FLAG" = "y" ]; then
1120	create_lock $PARENT_WS/usr/src/nightly.$MACH.lock "ulockfile"
1121fi
1122if [ "$U_FLAG" = "y" ]; then
1123	# NIGHTLY_PARENT_ROOT is written as root if script invoked as root.
1124	ISUSER=1 create_lock $NIGHTLY_PARENT_ROOT/nightly.lock "Ulockfile"
1125fi
1126
1127# Locks have been taken, so we're doing a build and we're committed to
1128# the directories we may have created so far.
1129newdirlist=
1130
1131#
1132# Create mail_msg_file
1133#
1134mail_msg_file="${TMPDIR}/mail_msg"
1135touch $mail_msg_file
1136build_time_file="${TMPDIR}/build_time"
1137build_environ_file="${TMPDIR}/build_environ"
1138touch $build_environ_file
1139#
1140#	Move old LOGFILE aside
1141#	ATLOG directory already made by 'create_lock' above
1142#
1143if [ -f $LOGFILE ]; then
1144	mv -f $LOGFILE ${LOGFILE}-
1145fi
1146#
1147#	Build OsNet source
1148#
1149START_DATE=`date`
1150SECONDS=0
1151echo "\n==== Nightly $maketype build started:   $START_DATE ====" \
1152    | tee -a $LOGFILE > $build_time_file
1153
1154echo "\nBuild project:  $build_project\nBuild taskid:   $build_taskid" | \
1155    tee -a $mail_msg_file >> $LOGFILE
1156
1157# make sure we log only to the nightly build file
1158build_noise_file="${TMPDIR}/build_noise"
1159exec </dev/null >$build_noise_file 2>&1
1160
1161run_hook SYS_PRE_NIGHTLY
1162run_hook PRE_NIGHTLY
1163
1164echo "\n==== list of environment variables ====\n" >> $LOGFILE
1165env >> $LOGFILE
1166
1167echo "\n==== Nightly argument issues ====\n" | tee -a $mail_msg_file >> $LOGFILE
1168
1169if [ "$N_FLAG" = "y" ]; then
1170	if [ "$p_FLAG" = "y" ]; then
1171		cat <<EOF | tee -a $mail_msg_file >> $LOGFILE
1172WARNING: the p option (create packages) is set, but so is the N option (do
1173         not run protocmp); this is dangerous; you should unset the N option
1174EOF
1175	else
1176		cat <<EOF | tee -a $mail_msg_file >> $LOGFILE
1177Warning: the N option (do not run protocmp) is set; it probably shouldn't be
1178EOF
1179	fi
1180	echo "" | tee -a $mail_msg_file >> $LOGFILE
1181fi
1182
1183if [ "$f_FLAG" = "y" ]; then
1184	if [ "$i_FLAG" = "y" ]; then
1185		echo "WARNING: the -f flag cannot be used during incremental" \
1186		    "builds; ignoring -f\n" | tee -a $mail_msg_file >> $LOGFILE
1187		f_FLAG=n
1188	fi
1189	if [ "${p_FLAG}" != "y" ]; then
1190		echo "WARNING: the -f flag requires -p;" \
1191		    "ignoring -f\n" | tee -a $mail_msg_file >> $LOGFILE
1192		f_FLAG=n
1193	fi
1194fi
1195
1196if [ "$w_FLAG" = "y" -a ! -d $ROOT ]; then
1197	echo "WARNING: -w specified, but $ROOT does not exist;" \
1198	    "ignoring -w\n" | tee -a $mail_msg_file >> $LOGFILE
1199	w_FLAG=n
1200fi
1201
1202case $MULTI_PROTO in
1203yes|no)	;;
1204*)
1205	echo "WARNING: MULTI_PROTO is \"$MULTI_PROTO\"; " \
1206	    "should be \"yes\" or \"no\"." | tee -a $mail_msg_file >> $LOGFILE
1207	echo "Setting MULTI_PROTO to \"no\".\n" | \
1208	    tee -a $mail_msg_file >> $LOGFILE
1209	export MULTI_PROTO=no
1210	;;
1211esac
1212
1213echo "\n==== Build version ====\n" | tee -a $mail_msg_file >> $LOGFILE
1214echo $VERSION | tee -a $mail_msg_file >> $LOGFILE
1215
1216# Save the current proto area if we're comparing against the last build
1217if [ "$w_FLAG" = "y" -a -d "$ROOT" ]; then
1218    if [ -d "$ROOT.prev" ]; then
1219	rm -rf $ROOT.prev
1220    fi
1221    mv $ROOT $ROOT.prev
1222fi
1223
1224# Same for non-DEBUG proto area
1225if [ "$w_FLAG" = "y" -a "$MULTI_PROTO" = yes -a -d "$ROOT-nd" ]; then
1226	if [ -d "$ROOT-nd.prev" ]; then
1227		rm -rf $ROOT-nd.prev
1228	fi
1229	mv $ROOT-nd $ROOT-nd.prev
1230fi
1231
1232#
1233# Echo the SCM type of the parent workspace, this can't just be which_scm
1234# as that does not know how to identify various network repositories.
1235#
1236function parent_wstype {
1237	typeset scm_type junk
1238
1239	CODEMGR_WS="$BRINGOVER_WS" "$WHICH_SCM" 2>/dev/null \
1240	    | read scm_type junk
1241	if [[ -z "$scm_type" || "$scm_type" == unknown ]]; then
1242		# Probe BRINGOVER_WS to determine its type
1243		if [[ $BRINGOVER_WS == ssh://* ]]; then
1244			scm_type="mercurial"
1245		elif [[ $BRINGOVER_WS == http://* ]] && \
1246		    wget -q -O- --save-headers "$BRINGOVER_WS/?cmd=heads" | \
1247		    egrep -s "application/mercurial" 2> /dev/null; then
1248			scm_type="mercurial"
1249		else
1250			scm_type="none"
1251		fi
1252	fi
1253
1254	# fold both unsupported and unrecognized results into "none"
1255	case "$scm_type" in
1256	mercurial)
1257		;;
1258	*)	scm_type=none
1259		;;
1260	esac
1261
1262	echo $scm_type
1263}
1264
1265# Echo the SCM types of $CODEMGR_WS and $BRINGOVER_WS
1266function child_wstype {
1267	typeset scm_type junk
1268
1269	# Probe CODEMGR_WS to determine its type
1270	if [[ -d $CODEMGR_WS ]]; then
1271		$WHICH_SCM | read scm_type junk || exit 1
1272	fi
1273
1274	case "$scm_type" in
1275	none|git|mercurial)
1276		;;
1277	*)	scm_type=none
1278		;;
1279	esac
1280
1281	echo $scm_type
1282}
1283
1284SCM_TYPE=$(child_wstype)
1285
1286#
1287#	Decide whether to clobber
1288#
1289if [ "$i_FLAG" = "n" -a -d "$SRC" ]; then
1290	echo "\n==== Make clobber at `date` ====\n" >> $LOGFILE
1291
1292	cd $SRC
1293	# remove old clobber file
1294	rm -f $SRC/clobber.out
1295	rm -f $SRC/clobber-${MACH}.out
1296
1297	# Remove all .make.state* files, just in case we are restarting
1298	# the build after having interrupted a previous 'make clobber'.
1299	find . \( -name SCCS -o -name .hg -o -name .svn -o -name .git \
1300		-o -name 'interfaces.*' \) -prune \
1301		-o -name '.make.*' -print | xargs rm -f
1302
1303	$MAKE -ek clobber 2>&1 | tee -a $SRC/clobber-${MACH}.out >> $LOGFILE
1304	echo "\n==== Make clobber ERRORS ====\n" >> $mail_msg_file
1305	grep "$MAKE:" $SRC/clobber-${MACH}.out |
1306		egrep -v "Ignoring unknown host" | \
1307		tee $TMPDIR/clobber_errs >> $mail_msg_file
1308
1309	if [[ -s $TMPDIR/clobber_errs ]]; then
1310		build_extras_ok=n
1311	fi
1312
1313	if [[ "$t_FLAG" = "y" ]]; then
1314		echo "\n==== Make tools clobber at `date` ====\n" >> $LOGFILE
1315		cd ${TOOLS}
1316		rm -f ${TOOLS}/clobber-${MACH}.out
1317		$MAKE TOOLS_PROTO=$TOOLS_PROTO -ek clobber 2>&1 | \
1318			tee -a ${TOOLS}/clobber-${MACH}.out >> $LOGFILE
1319		echo "\n==== Make tools clobber ERRORS ====\n" \
1320			>> $mail_msg_file
1321		grep "$MAKE:" ${TOOLS}/clobber-${MACH}.out \
1322			>> $mail_msg_file
1323		if (( $? == 0 )); then
1324			build_extras_ok=n
1325		fi
1326		rm -rf ${TOOLS_PROTO}
1327		mkdir -p ${TOOLS_PROTO}
1328	fi
1329
1330	typeset roots=$(allprotos)
1331	echo "\n\nClearing $roots" >> "$LOGFILE"
1332	rm -rf $roots
1333
1334	# Get back to a clean workspace as much as possible to catch
1335	# problems that only occur on fresh workspaces.
1336	# Remove all .make.state* files, libraries, and .o's that may
1337	# have been omitted from clobber.  A couple of libraries are
1338	# under source code control, so leave them alone.
1339	# We should probably blow away temporary directories too.
1340	cd $SRC
1341	find $relsrcdirs \( -name SCCS -o -name .hg -o -name .svn \
1342	    -o -name .git -o -name 'interfaces.*' \) -prune -o \
1343	    \( -name '.make.*' -o -name 'lib*.a' -o -name 'lib*.so*' -o \
1344	       -name '*.o' \) -print | \
1345	    grep -v 'tools/ctf/dwarf/.*/libdwarf' | xargs rm -f
1346else
1347	echo "\n==== No clobber at `date` ====\n" >> $LOGFILE
1348fi
1349
1350type bringover_mercurial > /dev/null 2>&1 || function bringover_mercurial {
1351	typeset -x PATH=$PATH
1352
1353	# If the repository doesn't exist yet, then we want to populate it.
1354	if [[ ! -d $CODEMGR_WS/.hg ]]; then
1355		staffer hg init $CODEMGR_WS
1356		staffer echo "[paths]" > $CODEMGR_WS/.hg/hgrc
1357		staffer echo "default=$BRINGOVER_WS" >> $CODEMGR_WS/.hg/hgrc
1358		touch $TMPDIR/new_repository
1359	fi
1360
1361	typeset -x HGMERGE="/bin/false"
1362
1363	#
1364	# If the user has changes, regardless of whether those changes are
1365	# committed, and regardless of whether those changes conflict, then
1366	# we'll attempt to merge them either implicitly (uncommitted) or
1367	# explicitly (committed).
1368	#
1369	# These are the messages we'll use to help clarify mercurial output
1370	# in those cases.
1371	#
1372	typeset mergefailmsg="\
1373***\n\
1374*** nightly was unable to automatically merge your changes.  You should\n\
1375*** redo the full merge manually, following the steps outlined by mercurial\n\
1376*** above, then restart nightly.\n\
1377***\n"
1378	typeset mergepassmsg="\
1379***\n\
1380*** nightly successfully merged your changes.  This means that your working\n\
1381*** directory has been updated, but those changes are not yet committed.\n\
1382*** After nightly completes, you should validate the results of the merge,\n\
1383*** then use hg commit manually.\n\
1384***\n"
1385
1386	#
1387	# For each repository in turn:
1388	#
1389	# 1. Do the pull.  If this fails, dump the output and bail out.
1390	#
1391	# 2. If the pull resulted in an extra head, do an explicit merge.
1392	#    If this fails, dump the output and bail out.
1393	#
1394	# Because we can't rely on Mercurial to exit with a failure code
1395	# when a merge fails (Mercurial issue #186), we must grep the
1396	# output of pull/merge to check for attempted and/or failed merges.
1397	#
1398	# 3. If a merge failed, set the message and fail the bringover.
1399	#
1400	# 4. Otherwise, if a merge succeeded, set the message
1401	#
1402	# 5. Dump the output, and any message from step 3 or 4.
1403	#
1404
1405	typeset HG_SOURCE=$BRINGOVER_WS
1406	if [ ! -f $TMPDIR/new_repository ]; then
1407		HG_SOURCE=$TMPDIR/open_bundle.hg
1408		staffer hg --cwd $CODEMGR_WS incoming --bundle $HG_SOURCE \
1409		    -v $BRINGOVER_WS > $TMPDIR/incoming_open.out
1410
1411		#
1412		# If there are no incoming changesets, then incoming will
1413		# fail, and there will be no bundle file.  Reset the source,
1414		# to allow the remaining logic to complete with no false
1415		# negatives.  (Unlike incoming, pull will return success
1416		# for the no-change case.)
1417		#
1418		if (( $? != 0 )); then
1419			HG_SOURCE=$BRINGOVER_WS
1420		fi
1421	fi
1422
1423	staffer hg --cwd $CODEMGR_WS pull -u $HG_SOURCE \
1424	    > $TMPDIR/pull_open.out 2>&1
1425	if (( $? != 0 )); then
1426		printf "%s: pull failed as follows:\n\n" "$CODEMGR_WS"
1427		cat $TMPDIR/pull_open.out
1428		if grep "^merging.*failed" $TMPDIR/pull_open.out > /dev/null 2>&1; then
1429			printf "$mergefailmsg"
1430		fi
1431		touch $TMPDIR/bringover_failed
1432		return
1433	fi
1434
1435	if grep "not updating" $TMPDIR/pull_open.out > /dev/null 2>&1; then
1436		staffer hg --cwd $CODEMGR_WS merge \
1437		    >> $TMPDIR/pull_open.out 2>&1
1438		if (( $? != 0 )); then
1439			printf "%s: merge failed as follows:\n\n" \
1440			    "$CODEMGR_WS"
1441			cat $TMPDIR/pull_open.out
1442			if grep "^merging.*failed" $TMPDIR/pull_open.out \
1443			    > /dev/null 2>&1; then
1444				printf "$mergefailmsg"
1445			fi
1446			touch $TMPDIR/bringover_failed
1447			return
1448		fi
1449	fi
1450
1451	printf "updated %s with the following results:\n" "$CODEMGR_WS"
1452	cat $TMPDIR/pull_open.out
1453	if grep "^merging" $TMPDIR/pull_open.out >/dev/null 2>&1; then
1454		printf "$mergepassmsg"
1455	fi
1456	printf "\n"
1457
1458	#
1459	# Per-changeset output is neither useful nor manageable for a
1460	# newly-created repository.
1461	#
1462	if [ -f $TMPDIR/new_repository ]; then
1463		return
1464	fi
1465
1466	printf "\nadded the following changesets to open repository:\n"
1467	cat $TMPDIR/incoming_open.out
1468}
1469
1470type bringover_none > /dev/null 2>&1 || function bringover_none {
1471	echo "Couldn't figure out what kind of SCM to use for $BRINGOVER_WS."
1472	touch $TMPDIR/bringover_failed
1473}
1474
1475#
1476#	Decide whether to bringover to the codemgr workspace
1477#
1478if [ "$n_FLAG" = "n" ]; then
1479	PARENT_SCM_TYPE=$(parent_wstype)
1480
1481	if [[ $SCM_TYPE != none && $SCM_TYPE != $PARENT_SCM_TYPE ]]; then
1482		echo "cannot bringover from $PARENT_SCM_TYPE to $SCM_TYPE, " \
1483		    "quitting at `date`." | tee -a $mail_msg_file >> $LOGFILE
1484		exit 1
1485	fi
1486
1487	run_hook PRE_BRINGOVER
1488
1489	echo "\n==== bringover to $CODEMGR_WS at `date` ====\n" >> $LOGFILE
1490	echo "\n==== BRINGOVER LOG ====\n" >> $mail_msg_file
1491
1492	eval "bringover_${PARENT_SCM_TYPE}" 2>&1 |
1493		tee -a $mail_msg_file >> $LOGFILE
1494
1495	if [ -f $TMPDIR/bringover_failed ]; then
1496		rm -f $TMPDIR/bringover_failed
1497		build_ok=n
1498		echo "trouble with bringover, quitting at `date`." |
1499			tee -a $mail_msg_file >> $LOGFILE
1500		exit 1
1501	fi
1502
1503	#
1504	# It's possible that we used the bringover above to create
1505	# $CODEMGR_WS.  If so, then SCM_TYPE was previously "none,"
1506	# but should now be the same as $BRINGOVER_WS.
1507	#
1508	[[ $SCM_TYPE = none ]] && SCM_TYPE=$PARENT_SCM_TYPE
1509
1510	run_hook POST_BRINGOVER
1511
1512	check_closed_bins
1513
1514else
1515	echo "\n==== No bringover to $CODEMGR_WS ====\n" >> $LOGFILE
1516fi
1517
1518# Safeguards
1519[[ -v CODEMGR_WS ]] || fatal_error "Error: Variable CODEMGR_WS not set."
1520[[ -d "${CODEMGR_WS}" ]] || fatal_error "Error: ${CODEMGR_WS} is not a directory."
1521[[ -f "${CODEMGR_WS}/usr/src/Makefile" ]] || fatal_error "Error: ${CODEMGR_WS}/usr/src/Makefile not found."
1522
1523if [[ "$t_FLAG" = "y" ]]; then
1524	echo "\n==== Bootstrapping cw ====\n" >> $LOGFILE
1525	( cd ${TOOLS}
1526	  set_non_debug_build_flags
1527	  rm -f $TMPDIR/make-state
1528	  $MAKE -K $TMPDIR/make-state -e TARGET=install cw 2>&1 >> $LOGFILE
1529	  [[ "$?" -ne 0 ]] && fatal_error "Error: could not bootstrap cw"
1530	)
1531
1532	# Switch ONBLD_TOOLS early if -t is specified so that
1533	# we could use bootstrapped cw for compiler checks.
1534	ONBLD_TOOLS=${TOOLS_PROTO}/opt/onbld
1535	export ONBLD_TOOLS
1536fi
1537
1538echo "\n==== Build environment ====\n" | tee -a $build_environ_file >> $LOGFILE
1539
1540# System
1541whence uname | tee -a $build_environ_file >> $LOGFILE
1542uname -a 2>&1 | tee -a $build_environ_file >> $LOGFILE
1543echo | tee -a $build_environ_file >> $LOGFILE
1544
1545# make
1546whence $MAKE | tee -a $build_environ_file >> $LOGFILE
1547$MAKE -v | tee -a $build_environ_file >> $LOGFILE
1548echo "number of concurrent jobs = $DMAKE_MAX_JOBS" |
1549    tee -a $build_environ_file >> $LOGFILE
1550
1551#
1552# Report the compiler versions.
1553#
1554
1555if [[ ! -f $SRC/Makefile ]]; then
1556	build_ok=n
1557	echo "\nUnable to find \"Makefile\" in $SRC." | \
1558	    tee -a $build_environ_file >> $LOGFILE
1559	exit 1
1560fi
1561
1562( cd $SRC
1563  for target in cc-version java-version openssl-version; do
1564	echo
1565	#
1566	# Put statefile somewhere we know we can write to rather than trip
1567	# over a read-only $srcroot.
1568	#
1569	rm -f $TMPDIR/make-state
1570	export SRC
1571	if $MAKE -K $TMPDIR/make-state -e $target 2>/dev/null; then
1572		continue
1573	fi
1574	touch $TMPDIR/nocompiler
1575  done
1576  echo
1577) | tee -a $build_environ_file >> $LOGFILE
1578
1579if [ -f $TMPDIR/nocompiler ]; then
1580	rm -f $TMPDIR/nocompiler
1581	build_ok=n
1582	echo "Aborting due to missing compiler." |
1583		tee -a $build_environ_file >> $LOGFILE
1584	exit 1
1585fi
1586
1587# as
1588whence as | tee -a $build_environ_file >> $LOGFILE
1589as -V 2>&1 | head -1 | tee -a $build_environ_file >> $LOGFILE
1590echo | tee -a $build_environ_file >> $LOGFILE
1591
1592# Check that we're running a capable link-editor
1593whence ld | tee -a $build_environ_file >> $LOGFILE
1594LDVER=`ld -V 2>&1`
1595echo $LDVER | tee -a $build_environ_file >> $LOGFILE
1596LDVER=`echo $LDVER | sed -e "s/.*-1\.\([0-9]*\).*/\1/"`
1597if [ `expr $LDVER \< 422` -eq 1 ]; then
1598	echo "The link-editor needs to be at version 422 or higher to build" | \
1599	    tee -a $build_environ_file >> $LOGFILE
1600	echo "the latest stuff.  Hope your build works." | \
1601	    tee -a $build_environ_file >> $LOGFILE
1602fi
1603
1604#
1605# Build and use the workspace's tools if requested
1606#
1607if [[ "$t_FLAG" = "y" ]]; then
1608	set_non_debug_build_flags
1609
1610	build_tools ${TOOLS_PROTO}
1611	if (( $? != 0 )); then
1612		build_ok=n
1613	else
1614		STABS=${TOOLS_PROTO}/opt/onbld/bin/${MACH}/stabs
1615		export STABS
1616		CTFSTABS=${TOOLS_PROTO}/opt/onbld/bin/${MACH}/ctfstabs
1617		export CTFSTABS
1618		GENOFFSETS=${TOOLS_PROTO}/opt/onbld/bin/genoffsets
1619		export GENOFFSETS
1620
1621		CTFCONVERT=${TOOLS_PROTO}/opt/onbld/bin/${MACH}/ctfconvert
1622		export CTFCONVERT
1623		CTFMERGE=${TOOLS_PROTO}/opt/onbld/bin/${MACH}/ctfmerge
1624		export CTFMERGE
1625
1626		PATH="${TOOLS_PROTO}/opt/onbld/bin/${MACH}:${PATH}"
1627		PATH="${TOOLS_PROTO}/opt/onbld/bin:${PATH}"
1628		export PATH
1629
1630		echo "\n==== New environment settings. ====\n" >> $LOGFILE
1631		echo "STABS=${STABS}" >> $LOGFILE
1632		echo "CTFSTABS=${CTFSTABS}" >> $LOGFILE
1633		echo "CTFCONVERT=${CTFCONVERT}" >> $LOGFILE
1634		echo "CTFMERGE=${CTFMERGE}" >> $LOGFILE
1635		echo "PATH=${PATH}" >> $LOGFILE
1636		echo "ONBLD_TOOLS=${ONBLD_TOOLS}" >> $LOGFILE
1637	fi
1638fi
1639
1640# timestamp the start of the normal build; the findunref tool uses it.
1641touch $SRC/.build.tstamp
1642
1643normal_build
1644
1645ORIG_SRC=$SRC
1646BINARCHIVE=${CODEMGR_WS}/bin-${MACH}.cpio.Z
1647
1648
1649#
1650# There are several checks that need to look at the proto area, but
1651# they only need to look at one, and they don't care whether it's
1652# DEBUG or non-DEBUG.
1653#
1654if [[ "$MULTI_PROTO" = yes && "$D_FLAG" = n ]]; then
1655	checkroot=$ROOT-nd
1656else
1657	checkroot=$ROOT
1658fi
1659
1660if [ "$build_ok" = "y" ]; then
1661	echo "\n==== Creating protolist system file at `date` ====" \
1662		>> $LOGFILE
1663	protolist $checkroot > $ATLOG/proto_list_${MACH}
1664	echo "==== protolist system file created at `date` ====\n" \
1665		>> $LOGFILE
1666
1667	if [ "$N_FLAG" != "y" ]; then
1668
1669		E1=
1670		f1=
1671		for f in $f1; do
1672			if [ -f "$f" ]; then
1673				E1="$E1 -e $f"
1674			fi
1675		done
1676
1677		E2=
1678		f2=
1679		if [ -d "$SRC/pkg" ]; then
1680			f2="$f2 exceptions/packaging"
1681		fi
1682
1683		for f in $f2; do
1684			if [ -f "$f" ]; then
1685				E2="$E2 -e $f"
1686			fi
1687		done
1688	fi
1689
1690	if [ "$N_FLAG" != "y" -a -d $SRC/pkg ]; then
1691		echo "\n==== Validating manifests against proto area ====\n" \
1692		    >> $mail_msg_file
1693		( cd $SRC/pkg ; $MAKE -e protocmp ROOT="$checkroot" ) | \
1694		    tee $TMPDIR/protocmp_noise >> $mail_msg_file
1695		if [[ -s $TMPDIR/protocmp_noise ]]; then
1696			build_extras_ok=n
1697		fi
1698	fi
1699
1700	if [ "$N_FLAG" != "y" -a -f "$REF_PROTO_LIST" ]; then
1701		echo "\n==== Impact on proto area ====\n" >> $mail_msg_file
1702		if [ -n "$E2" ]; then
1703			ELIST=$E2
1704		else
1705			ELIST=$E1
1706		fi
1707		$PROTOCMPTERSE \
1708			"Files in yesterday's proto area, but not today's:" \
1709			"Files in today's proto area, but not yesterday's:" \
1710			"Files that changed between yesterday and today:" \
1711			${ELIST} \
1712			-d $REF_PROTO_LIST \
1713			$ATLOG/proto_list_${MACH} \
1714			>> $mail_msg_file
1715	fi
1716fi
1717
1718if [[ "$u_FLAG" == "y" && "$build_ok" == "y" && \
1719    "$build_extras_ok" == "y" ]]; then
1720	staffer cp $ATLOG/proto_list_${MACH} \
1721		$PARENT_WS/usr/src/proto_list_${MACH}
1722fi
1723
1724# Update parent proto area if necessary. This is done now
1725# so that the proto area has either DEBUG or non-DEBUG kernels.
1726# Note that this clears out the lock file, so we can dispense with
1727# the variable now.
1728if [ "$U_FLAG" = "y" -a "$build_ok" = "y" ]; then
1729	echo "\n==== Copying proto area to $NIGHTLY_PARENT_ROOT ====\n" | \
1730	    tee -a $LOGFILE >> $mail_msg_file
1731	rm -rf $NIGHTLY_PARENT_ROOT/*
1732	unset Ulockfile
1733	mkdir -p $NIGHTLY_PARENT_ROOT
1734	if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
1735		( cd $ROOT; tar cf - . |
1736		    ( cd $NIGHTLY_PARENT_ROOT;  umask 0; tar xpf - ) ) 2>&1 |
1737		    tee -a $mail_msg_file >> $LOGFILE
1738	fi
1739	if [[ "$MULTI_PROTO" = yes && "$F_FLAG" = n ]]; then
1740		rm -rf $NIGHTLY_PARENT_ROOT-nd/*
1741		mkdir -p $NIGHTLY_PARENT_ROOT-nd
1742		cd $ROOT-nd
1743		( tar cf - . |
1744		    ( cd $NIGHTLY_PARENT_ROOT-nd; umask 0; tar xpf - ) ) 2>&1 |
1745		    tee -a $mail_msg_file >> $LOGFILE
1746	fi
1747	if [ -n "${NIGHTLY_PARENT_TOOLS_ROOT}" ]; then
1748		echo "\n==== Copying tools proto area to $NIGHTLY_PARENT_TOOLS_ROOT ====\n" | \
1749		    tee -a $LOGFILE >> $mail_msg_file
1750		rm -rf $NIGHTLY_PARENT_TOOLS_ROOT/*
1751		mkdir -p $NIGHTLY_PARENT_TOOLS_ROOT
1752		if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
1753			( cd $TOOLS_PROTO; tar cf - . |
1754			    ( cd $NIGHTLY_PARENT_TOOLS_ROOT;
1755			    umask 0; tar xpf - ) ) 2>&1 |
1756			    tee -a $mail_msg_file >> $LOGFILE
1757		fi
1758	fi
1759fi
1760
1761#
1762# ELF verification: ABI (-A) and runtime (-r) checks
1763#
1764if [[ ($build_ok = y) && (($A_FLAG = y) || ($r_FLAG = y)) ]]; then
1765	# Directory ELF-data.$MACH holds the files produced by these tests.
1766	elf_ddir=$SRC/ELF-data.$MACH
1767
1768	# If there is a previous ELF-data backup directory, remove it. Then,
1769	# rotate current ELF-data directory into its place and create a new
1770	# empty directory
1771	rm -rf $elf_ddir.ref
1772	if [[ -d $elf_ddir ]]; then
1773		mv $elf_ddir $elf_ddir.ref
1774	fi
1775	mkdir -p $elf_ddir
1776
1777	# Call find_elf to produce a list of the ELF objects in the proto area.
1778	# This list is passed to check_rtime and interface_check, preventing
1779	# them from separately calling find_elf to do the same work twice.
1780	find_elf -fr $checkroot > $elf_ddir/object_list
1781
1782	if [[ $A_FLAG = y ]]; then
1783		echo "\n==== Check versioning and ABI information ====\n"  | \
1784		    tee -a $LOGFILE >> $mail_msg_file
1785
1786		# Produce interface description for the proto. Report errors.
1787		interface_check -o -w $elf_ddir -f object_list \
1788			-i interface -E interface.err
1789		if [[ -s $elf_ddir/interface.err ]]; then
1790			tee -a $LOGFILE < $elf_ddir/interface.err \
1791			    >> $mail_msg_file
1792			build_extras_ok=n
1793		fi
1794
1795		# If ELF_DATA_BASELINE_DIR is defined, compare the new interface
1796		# description file to that from the baseline gate. Issue a
1797		# warning if the baseline is not present, and keep going.
1798		if [[ "$ELF_DATA_BASELINE_DIR" != '' ]]; then
1799			base_ifile="$ELF_DATA_BASELINE_DIR/interface"
1800
1801			echo "\n==== Compare versioning and ABI information" \
1802			    "to baseline ====\n"  | \
1803			    tee -a $LOGFILE >> $mail_msg_file
1804			echo "Baseline:	 $base_ifile\n" >> $LOGFILE
1805
1806			if [[ -f $base_ifile ]]; then
1807				interface_cmp -d -o $base_ifile \
1808				    $elf_ddir/interface > $elf_ddir/interface.cmp
1809				if [[ -s $elf_ddir/interface.cmp ]]; then
1810					echo | tee -a $LOGFILE >> $mail_msg_file
1811					tee -a $LOGFILE < \
1812					    $elf_ddir/interface.cmp \
1813					    >> $mail_msg_file
1814					build_extras_ok=n
1815				fi
1816			else
1817				echo "baseline not available. comparison" \
1818                                    "skipped" | \
1819				    tee -a $LOGFILE >> $mail_msg_file
1820			fi
1821
1822		fi
1823	fi
1824
1825	if [[ $r_FLAG = y ]]; then
1826		echo "\n==== Check ELF runtime attributes ====\n" | \
1827		    tee -a $LOGFILE >> $mail_msg_file
1828
1829		# If we're doing a DEBUG build the proto area will be left
1830		# with debuggable objects, thus don't assert -s.
1831		if [[ $D_FLAG = y ]]; then
1832			rtime_sflag=""
1833		else
1834			rtime_sflag="-s"
1835		fi
1836		check_rtime -i -m -v $rtime_sflag -o -w $elf_ddir \
1837			-D object_list  -f object_list -E runtime.err \
1838			-I runtime.attr.raw
1839		if (( $? != 0 )); then
1840			build_extras_ok=n
1841		fi
1842
1843		# check_rtime -I output needs to be sorted in order to
1844		# compare it to that from previous builds.
1845		sort $elf_ddir/runtime.attr.raw > $elf_ddir/runtime.attr
1846		rm $elf_ddir/runtime.attr.raw
1847
1848		# Report errors
1849		if [[ -s $elf_ddir/runtime.err ]]; then
1850			tee -a $LOGFILE < $elf_ddir/runtime.err \
1851				>> $mail_msg_file
1852			build_extras_ok=n
1853		fi
1854
1855		# If there is an ELF-data directory from a previous build,
1856		# then diff the attr files. These files contain information
1857		# about dependencies, versioning, and runpaths. There is some
1858		# overlap with the ABI checking done above, but this also
1859		# flushes out non-ABI interface differences along with the
1860		# other information.
1861		echo "\n==== Diff ELF runtime attributes" \
1862		    "(since last build) ====\n" | \
1863		    tee -a $LOGFILE >> $mail_msg_file >> $mail_msg_file
1864
1865		if [[ -f $elf_ddir.ref/runtime.attr ]]; then
1866			diff $elf_ddir.ref/runtime.attr \
1867				$elf_ddir/runtime.attr \
1868				>> $mail_msg_file
1869		fi
1870	fi
1871
1872	# If -u set, copy contents of ELF-data.$MACH to the parent workspace.
1873	if [[ "$u_FLAG" = "y" ]]; then
1874		p_elf_ddir=$PARENT_WS/usr/src/ELF-data.$MACH
1875
1876		# If parent lacks the ELF-data.$MACH directory, create it
1877		if [[ ! -d $p_elf_ddir ]]; then
1878			staffer mkdir -p $p_elf_ddir
1879		fi
1880
1881		# These files are used asynchronously by other builds for ABI
1882		# verification, as above for the -A option. As such, we require
1883		# the file replacement to be atomic. Copy the data to a temp
1884		# file in the same filesystem and then rename into place.
1885		(
1886			cd $elf_ddir
1887			for elf_dfile in *; do
1888				staffer cp $elf_dfile \
1889				    ${p_elf_ddir}/${elf_dfile}.new
1890				staffer mv -f ${p_elf_ddir}/${elf_dfile}.new \
1891				    ${p_elf_ddir}/${elf_dfile}
1892			done
1893		)
1894	fi
1895fi
1896
1897# "make check" begins
1898
1899if [ "$i_CMD_LINE_FLAG" = "n" -a "$C_FLAG" = "y" ]; then
1900	# remove old check.out
1901	rm -f $SRC/check.out
1902
1903	rm -f $SRC/check-${MACH}.out
1904	cd $SRC
1905	$MAKE -ek check ROOT="$checkroot" 2>&1 | tee -a $SRC/check-${MACH}.out \
1906	    >> $LOGFILE
1907	echo "\n==== cstyle/hdrchk errors ====\n" >> $mail_msg_file
1908
1909	grep ":" $SRC/check-${MACH}.out |
1910		egrep -v "Ignoring unknown host" | \
1911		sort | uniq | tee $TMPDIR/check_errors >> $mail_msg_file
1912
1913	if [[ -s $TMPDIR/check_errors ]]; then
1914		build_extras_ok=n
1915	fi
1916else
1917	echo "\n==== No '$MAKE check' ====\n" >> $LOGFILE
1918fi
1919
1920echo "\n==== Find core files ====\n" | \
1921    tee -a $LOGFILE >> $mail_msg_file
1922
1923find $abssrcdirs -name core -a -type f -exec file {} \; | \
1924	tee -a $LOGFILE >> $mail_msg_file
1925
1926if [ "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then
1927	echo "\n==== Diff unreferenced files (since last build) ====\n" \
1928	    | tee -a $LOGFILE >>$mail_msg_file
1929	rm -f $SRC/unref-${MACH}.ref
1930	if [ -f $SRC/unref-${MACH}.out ]; then
1931		mv $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref
1932	fi
1933
1934	findunref -S $SCM_TYPE -t $SRC/.build.tstamp -s usr $CODEMGR_WS \
1935	    ${TOOLS}/findunref/exception_list 2>> $mail_msg_file | \
1936	    sort > $SRC/unref-${MACH}.out
1937
1938	if [ ! -f $SRC/unref-${MACH}.ref ]; then
1939		cp $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref
1940	fi
1941
1942	diff $SRC/unref-${MACH}.ref $SRC/unref-${MACH}.out >>$mail_msg_file
1943fi
1944
1945# Verify that the usual lists of files, such as exception lists,
1946# contain only valid references to files.  If the build has failed,
1947# then don't check the proto area.
1948CHECK_PATHS=${CHECK_PATHS:-y}
1949if [ "$CHECK_PATHS" = y -a "$N_FLAG" != y ]; then
1950	echo "\n==== Check lists of files ====\n" | tee -a $LOGFILE \
1951		>>$mail_msg_file
1952	arg=-b
1953	[ "$build_ok" = y ] && arg=
1954	checkpaths $arg $checkroot > $SRC/check-paths.out 2>&1
1955	if [[ -s $SRC/check-paths.out ]]; then
1956		tee -a $LOGFILE < $SRC/check-paths.out >> $mail_msg_file
1957		build_extras_ok=n
1958	fi
1959fi
1960
1961if [ "$M_FLAG" != "y" -a "$build_ok" = y ]; then
1962	echo "\n==== Impact on file permissions ====\n" \
1963		>> $mail_msg_file
1964
1965	abspkg=
1966	for d in $abssrcdirs; do
1967		if [ -d "$d/pkg" ]; then
1968			abspkg="$abspkg $d"
1969		fi
1970	done
1971
1972	if [ -n "$abspkg" ]; then
1973		for d in "$abspkg"; do
1974			( cd $d/pkg ; $MAKE -e pmodes ) >> $mail_msg_file
1975		done
1976	fi
1977fi
1978
1979if [ "$w_FLAG" = "y" -a "$build_ok" = "y" ]; then
1980	if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
1981		do_wsdiff DEBUG $ROOT.prev $ROOT
1982	fi
1983
1984	if [[ "$MULTI_PROTO" = yes && "$F_FLAG" = n ]]; then
1985		do_wsdiff non-DEBUG $ROOT-nd.prev $ROOT-nd
1986	fi
1987fi
1988
1989END_DATE=`date`
1990echo "==== Nightly $maketype build completed: $END_DATE ====" | \
1991    tee -a $LOGFILE >> $build_time_file
1992
1993typeset -i10 hours
1994typeset -Z2 minutes
1995typeset -Z2 seconds
1996
1997elapsed_time=$SECONDS
1998((hours = elapsed_time / 3600 ))
1999((minutes = elapsed_time / 60  % 60))
2000((seconds = elapsed_time % 60))
2001
2002echo "\n==== Total build time ====" | \
2003    tee -a $LOGFILE >> $build_time_file
2004echo "\nreal    ${hours}:${minutes}:${seconds}" | \
2005    tee -a $LOGFILE >> $build_time_file
2006
2007if [ "$u_FLAG" = "y" -a "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then
2008	staffer cp ${SRC}/unref-${MACH}.out $PARENT_WS/usr/src/
2009
2010	#
2011	# Produce a master list of unreferenced files -- ideally, we'd
2012	# generate the master just once after all of the nightlies
2013	# have finished, but there's no simple way to know when that
2014	# will be.  Instead, we assume that we're the last nightly to
2015	# finish and merge all of the unref-${MACH}.out files in
2016	# $PARENT_WS/usr/src/.  If we are in fact the final ${MACH} to
2017	# finish, then this file will be the authoritative master
2018	# list.  Otherwise, another ${MACH}'s nightly will eventually
2019	# overwrite ours with its own master, but in the meantime our
2020	# temporary "master" will be no worse than any older master
2021	# which was already on the parent.
2022	#
2023
2024	set -- $PARENT_WS/usr/src/unref-*.out
2025	cp "$1" ${TMPDIR}/unref.merge
2026	shift
2027
2028	for unreffile; do
2029		comm -12 ${TMPDIR}/unref.merge "$unreffile" > ${TMPDIR}/unref.$$
2030		mv ${TMPDIR}/unref.$$ ${TMPDIR}/unref.merge
2031	done
2032
2033	staffer cp ${TMPDIR}/unref.merge $PARENT_WS/usr/src/unrefmaster.out
2034fi
2035
2036#
2037# All done save for the sweeping up.
2038# (whichever exit we hit here will trigger the "cleanup" trap which
2039# optionally sends mail on completion).
2040#
2041if [[ "$build_ok" == "y" ]]; then
2042	if [[ "$W_FLAG" == "y" || "$build_extras_ok" == "y" ]]; then
2043		exit 0
2044	fi
2045fi
2046
2047exit 1
2048