The tinderbox has moved to projcvs.
This commit is contained in:
parent
b96008e410
commit
a693fbc197
@ -50,7 +50,6 @@ recoverdisk Copy as much data as possible from a deffective disk.
|
|||||||
scsi-defects Get at the primary or grown defect list of a SCSI disk.
|
scsi-defects Get at the primary or grown defect list of a SCSI disk.
|
||||||
sysdoc Build a manual page with available sysctls for a specific
|
sysdoc Build a manual page with available sysctls for a specific
|
||||||
kernel configuration.
|
kernel configuration.
|
||||||
tinderbox Sample script for nightly test builds.
|
|
||||||
vop_table Generates a HTML document that shows all the VOP's in
|
vop_table Generates a HTML document that shows all the VOP's in
|
||||||
the kernel.
|
the kernel.
|
||||||
whereintheworld Summarizes "make world" output.
|
whereintheworld Summarizes "make world" output.
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
tbmaster.1.gz
|
|
||||||
tinderbox.1.gz
|
|
@ -1,15 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
BINDIR ?= ${HOME}/bin
|
|
||||||
BINOWN ?= ${USER}
|
|
||||||
BINGRP ?= ${USER}
|
|
||||||
SCRIPTS = tbmaster.pl tinderbox.pl
|
|
||||||
|
|
||||||
MANDIR ?= ${HOME}/man/man
|
|
||||||
MANOWN ?= ${USER}
|
|
||||||
MANGRP ?= ${USER}
|
|
||||||
MAN = tbmaster.1 tinderbox.1
|
|
||||||
|
|
||||||
SUBDIR = etc www
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
@ -1,18 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
ETCFILES =
|
|
||||||
ETCFILES += default.rc
|
|
||||||
ETCFILES += releng_4.rc update_releng_4.rc
|
|
||||||
ETCFILES += releng_5.rc update_releng_5.rc
|
|
||||||
ETCFILES += releng_6.rc update_releng_6.rc
|
|
||||||
ETCFILES += head.rc update_head.rc
|
|
||||||
ETCDIR ?= ${HOME}/etc
|
|
||||||
ETCOWN ?= ${USER}
|
|
||||||
ETCGRP ?= ${USER}
|
|
||||||
|
|
||||||
realinstall:
|
|
||||||
.for FILE in ${ETCFILES}
|
|
||||||
${INSTALL} -m0644 -o${ETCOWN} -g${ETCGRP} ${.CURDIR}/${FILE} ${ETCDIR}
|
|
||||||
.endfor
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
@ -1,21 +0,0 @@
|
|||||||
#
|
|
||||||
# Tinderbox defaults
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
comment = %%branch%% tinderbox
|
|
||||||
|
|
||||||
# Paths
|
|
||||||
sandbox = %%HOME%%
|
|
||||||
logdir = %%HOME%%/logs
|
|
||||||
|
|
||||||
# Tinderbox options
|
|
||||||
options = --verbose
|
|
||||||
targets = cleanobj, update, world, lint, kernel:GENERIC
|
|
||||||
#timeout = 7200
|
|
||||||
|
|
||||||
# Reporting
|
|
||||||
sender = FreeBSD Tinderbox <tinderbox@freebsd.org>
|
|
||||||
recipient = %%SENDER%%
|
|
||||||
subject = [%%COMMENT%%] failure on %%arch%%/%%machine%%
|
|
@ -1,12 +0,0 @@
|
|||||||
#
|
|
||||||
# HEAD tinderbox setup
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
branches = HEAD
|
|
||||||
platforms = amd64, i386/i386, i386/pc98, sparc64
|
|
||||||
cflags = -O2 -pipe
|
|
||||||
coptflags = %%CFLAGS%%
|
|
||||||
targets += kernel:PAE
|
|
||||||
recipient = %%SENDER%%,<current@freebsd.org>,<%%arch%%@freebsd.org>
|
|
@ -1,9 +0,0 @@
|
|||||||
#
|
|
||||||
# RELENG_4 tinderbox setup
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
branches = RELENG_4_11, RELENG_4
|
|
||||||
platforms = alpha, i386/i386, i386/pc98
|
|
||||||
recipient = %%SENDER%%,<stable@freebsd.org>,<%%arch%%@freebsd.org>
|
|
@ -1,9 +0,0 @@
|
|||||||
#
|
|
||||||
# RELENG_5 tinderbox setup
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
branches = RELENG_5_4, RELENG_5_5, RELENG_5
|
|
||||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
|
||||||
recipient = %%SENDER%%,<stable@freebsd.org>,<%%arch%%@freebsd.org>
|
|
@ -1,11 +0,0 @@
|
|||||||
#
|
|
||||||
# RELENG_6 tinderbox setup
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
branches = RELENG_6_0, RELENG_6_1, RELENG_6
|
|
||||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
|
||||||
cflags = -O2 -pipe
|
|
||||||
coptflags = %%CFLAGS%%
|
|
||||||
recipient = %%SENDER%%,<stable@freebsd.org>,<%%arch%%@freebsd.org>
|
|
@ -1,4 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
branches = HEAD
|
|
||||||
platforms = amd64, i386/i386, i386/pc98, sparc64
|
|
||||||
targets = update
|
|
@ -1,4 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
branches = RELENG_4_11, RELENG_4
|
|
||||||
platforms = alpha, i386/i386, i386/pc98
|
|
||||||
targets = update
|
|
@ -1,4 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
branches = RELENG_5_4, RELENG_5_5, RELENG_5
|
|
||||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
|
||||||
targets = update
|
|
@ -1,4 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
branches = RELENG_6_0, RELENG_6_1, RELENG_6
|
|
||||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
|
||||||
targets = update
|
|
@ -1,59 +0,0 @@
|
|||||||
$FreeBSD$
|
|
||||||
|
|
||||||
Index: contrib/gcc/config/rs6000/freebsd.h
|
|
||||||
===================================================================
|
|
||||||
RCS file: /home/ncvs/src/contrib/gcc/config/rs6000/freebsd.h,v
|
|
||||||
retrieving revision 1.1.1.2
|
|
||||||
diff -u -r1.1.1.2 freebsd.h
|
|
||||||
--- contrib/gcc/config/rs6000/freebsd.h 11 Jul 2003 03:40:53 -0000 1.1.1.2
|
|
||||||
+++ contrib/gcc/config/rs6000/freebsd.h 9 Sep 2003 06:51:49 -0000
|
|
||||||
@@ -43,6 +43,23 @@
|
|
||||||
#undef LINK_SHLIB_SPEC
|
|
||||||
#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
|
|
||||||
|
|
||||||
+/* We don't want _BIG_ENDIAN or _LITTLE_ENDIAN to be defined. */
|
|
||||||
+#undef RS6000_CPU_CPP_ENDIAN_BUILTINS
|
|
||||||
+#define RS6000_CPU_CPP_ENDIAN_BUILTINS() \
|
|
||||||
+ do \
|
|
||||||
+ { \
|
|
||||||
+ if (BYTES_BIG_ENDIAN) \
|
|
||||||
+ { \
|
|
||||||
+ builtin_define ("__BIG_ENDIAN__"); \
|
|
||||||
+ builtin_assert ("machine=bigendian"); \
|
|
||||||
+ } \
|
|
||||||
+ else \
|
|
||||||
+ { \
|
|
||||||
+ builtin_define ("__LITTLE_ENDIAN__"); \
|
|
||||||
+ builtin_assert ("machine=littleendian"); \
|
|
||||||
+ } \
|
|
||||||
+ } \
|
|
||||||
+ while (0)
|
|
||||||
|
|
||||||
/************************[ Target stuff ]***********************************/
|
|
||||||
|
|
||||||
@@ -58,6 +75,9 @@
|
|
||||||
|
|
||||||
#undef WCHAR_TYPE_SIZE
|
|
||||||
#define WCHAR_TYPE_SIZE 32
|
|
||||||
+
|
|
||||||
+#undef DEFAULT_SIGNED_CHAR
|
|
||||||
+#define DEFAULT_SIGNED_CHAR 1
|
|
||||||
|
|
||||||
#undef TARGET_VERSION
|
|
||||||
#define TARGET_VERSION fprintf (stderr, " (FreeBSD/PowerPC ELF)");
|
|
||||||
Index: contrib/gcc/config/rs6000/sysv4.h
|
|
||||||
===================================================================
|
|
||||||
RCS file: /home/ncvs/src/contrib/gcc/config/rs6000/sysv4.h,v
|
|
||||||
retrieving revision 1.1.1.6
|
|
||||||
diff -u -r1.1.1.6 sysv4.h
|
|
||||||
--- contrib/gcc/config/rs6000/sysv4.h 11 Jul 2003 03:40:53 -0000 1.1.1.6
|
|
||||||
+++ contrib/gcc/config/rs6000/sysv4.h 9 Sep 2003 06:51:49 -0000
|
|
||||||
@@ -21,8 +21,6 @@
|
|
||||||
Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
|
|
||||||
-/* Header files should be C++ aware in general. */
|
|
||||||
-#define NO_IMPLICIT_EXTERN_C
|
|
||||||
|
|
||||||
/* Yes! We are ELF. */
|
|
||||||
#define TARGET_OBJECT_FORMAT OBJECT_ELF
|
|
@ -1,289 +0,0 @@
|
|||||||
.\"-
|
|
||||||
.\" Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted provided that the following conditions
|
|
||||||
.\" are met:
|
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
.\" SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.\" $FreeBSD$
|
|
||||||
.\"
|
|
||||||
.Dd March 2, 2006
|
|
||||||
.Dt TBMASTER 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm tbmaster
|
|
||||||
.Nd manage tinderbox runs
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op options
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script manages
|
|
||||||
.Xr tinderbox 1
|
|
||||||
runs, generates log summaries, and mails out failure reports.
|
|
||||||
.Pp
|
|
||||||
The following options are recognized:
|
|
||||||
.Bl -tag -width 12n
|
|
||||||
.It Fl c Ar NAME , Fl -config Ns = Ns Ar NAME
|
|
||||||
The name of the configuration to use.
|
|
||||||
If specified multiple times, all listed configurations will be run in
|
|
||||||
sequence.
|
|
||||||
The default is the hostname minus the domain part.
|
|
||||||
.It Fl d , Fl -dump
|
|
||||||
Dumps the configuration and exits without running the tinderbox.
|
|
||||||
.It Fl e Ar DIR , Fl -etcdir Ns = Ns Ar DIR
|
|
||||||
The directory where configuration files are located.
|
|
||||||
The default is
|
|
||||||
.Pa $HOME/etc .
|
|
||||||
.It Fl l Ar FILE
|
|
||||||
The name of a file to lock upon startup.
|
|
||||||
If the lock is already held by another process,
|
|
||||||
.Nm
|
|
||||||
will terminate immediately rather than block.
|
|
||||||
.El
|
|
||||||
.Ss Configuration
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script uses named configurations located in individual files named for
|
|
||||||
the setup they describe, with a
|
|
||||||
.Pa .rc
|
|
||||||
suffix.
|
|
||||||
For instance, the
|
|
||||||
.Dq snoosnoo
|
|
||||||
configuration is contained in
|
|
||||||
.Pa snoosnoo.rc .
|
|
||||||
.Pp
|
|
||||||
In addition,
|
|
||||||
.Nm
|
|
||||||
attempts to read
|
|
||||||
.Pa default.rc
|
|
||||||
and
|
|
||||||
.Pa site.rc
|
|
||||||
before reading the actual configuration file; thus, these files may be
|
|
||||||
used to specify default values shared by multiple configurations.
|
|
||||||
.Pp
|
|
||||||
The configuration consists of a list of single- or multiple-value
|
|
||||||
variable assignments:
|
|
||||||
.Bl -tag
|
|
||||||
.It Va single_variable = Ar value
|
|
||||||
.It Va multi_variable = Ar value1 , Ar value2, ...
|
|
||||||
.It Va multi_variable += Ar value3 , ...
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
Whitespace around the equal sign and around the commas separating
|
|
||||||
multiple values is optional.
|
|
||||||
.Pp
|
|
||||||
Blank lines are ignored, as is anything following a hash sign
|
|
||||||
.Pq Dq # .
|
|
||||||
.Pp
|
|
||||||
The following configuration variables are defined:
|
|
||||||
.Bl -tag -width 12n
|
|
||||||
.It ARCH
|
|
||||||
.Pq Vt single
|
|
||||||
The architecture currently being built for.
|
|
||||||
Read-only.
|
|
||||||
.It BRANCH
|
|
||||||
.Pq Vt single
|
|
||||||
The branch currently being built.
|
|
||||||
Read-only.
|
|
||||||
.It BRANCHES
|
|
||||||
.Pq Vt multiple
|
|
||||||
A list of source branches to build.
|
|
||||||
The default value is
|
|
||||||
.Dq HEAD .
|
|
||||||
.It CFLAGS
|
|
||||||
.Pq Vt single
|
|
||||||
The desired value for the
|
|
||||||
.Va CFLAGS
|
|
||||||
.Xr make 1
|
|
||||||
variable.
|
|
||||||
This is equivalent to specifying
|
|
||||||
.Va CFLAGS
|
|
||||||
in
|
|
||||||
.Va ENV .
|
|
||||||
No default value.
|
|
||||||
.It COPTFLAGS
|
|
||||||
.Pq Vt single
|
|
||||||
The desired value for the
|
|
||||||
.Va COPTFLAGS
|
|
||||||
.Xr make 1
|
|
||||||
variable.
|
|
||||||
This is equivalent to specifying
|
|
||||||
.Va COPTFLAGS
|
|
||||||
in
|
|
||||||
.Va ENV .
|
|
||||||
No default value.
|
|
||||||
.It COMMENT
|
|
||||||
.Pq Vt single
|
|
||||||
A terse comment describing the setup.
|
|
||||||
No default value.
|
|
||||||
.It CVSUP
|
|
||||||
.Pq Vt single
|
|
||||||
The name of the
|
|
||||||
.Xr cvsup 1
|
|
||||||
server to use.
|
|
||||||
No default value.
|
|
||||||
.It DATE
|
|
||||||
.Pq Vt single
|
|
||||||
The date to use when checking out sources, or
|
|
||||||
.Dq today
|
|
||||||
for today's sources.
|
|
||||||
If left undefined, the top of each branch is used.
|
|
||||||
No default value.
|
|
||||||
.It ENV
|
|
||||||
.Pq Vt multiple
|
|
||||||
A list of environment variables to pass to the
|
|
||||||
.Xr tinderbox 1
|
|
||||||
script.
|
|
||||||
Each value is the name and value of an environment variable, separated
|
|
||||||
by an equal sign
|
|
||||||
.Pq Dq = .
|
|
||||||
No default value.
|
|
||||||
.It HOME
|
|
||||||
.Pq Vt single
|
|
||||||
The current user's home directory, as specified by the
|
|
||||||
.Ev HOME
|
|
||||||
environment variable.
|
|
||||||
Note that it will not be defined unless it passes some simple sanity
|
|
||||||
checks.
|
|
||||||
Read-only.
|
|
||||||
.It HOSTNAME
|
|
||||||
.Pq Vt single
|
|
||||||
The name of the host running the tinderbox.
|
|
||||||
This defaults to the name reported by the
|
|
||||||
.Fl n
|
|
||||||
option of the
|
|
||||||
.Xr uname 1
|
|
||||||
command, and is only used for cosmetic purposes.
|
|
||||||
.It JOBS
|
|
||||||
The maximum number of concurrent
|
|
||||||
.Xr make 1
|
|
||||||
jobs to run.
|
|
||||||
No default value.
|
|
||||||
.It LOGDIR
|
|
||||||
.Pq Vt single
|
|
||||||
The location of the log directory.
|
|
||||||
The default value is
|
|
||||||
.Pa %%SANDBOX%%/logs .
|
|
||||||
.It MACHINE
|
|
||||||
.Pq Vt single
|
|
||||||
The machine currently being built for.
|
|
||||||
Read-only.
|
|
||||||
.It OPTIONS
|
|
||||||
.Pq Vt multiple
|
|
||||||
A list of additional options to pass to the
|
|
||||||
.Xr tinderbox 1
|
|
||||||
script.
|
|
||||||
No default value.
|
|
||||||
.It PATCH
|
|
||||||
.Pq Vt single
|
|
||||||
The file name (either absolute, or relative to the sandbox directory)
|
|
||||||
of the patch to apply if the
|
|
||||||
.Dq patch
|
|
||||||
command is specified.
|
|
||||||
No default value.
|
|
||||||
.It PLATFORMS
|
|
||||||
.Pq Vt multiple
|
|
||||||
Which architectures and machines to build for.
|
|
||||||
Each value is the name of an architecture, optionally followed by a
|
|
||||||
forward slash
|
|
||||||
.Pq Dq /
|
|
||||||
and a machine name.
|
|
||||||
If the machine name is not specified, it is assumed to be identical to
|
|
||||||
the architecture name.
|
|
||||||
The default value is
|
|
||||||
.Dq i386 .
|
|
||||||
.It RECIPIENT
|
|
||||||
.Pq Vt single
|
|
||||||
The address to which failure reports should be mailed.
|
|
||||||
No default value.
|
|
||||||
.It REPOSITORY
|
|
||||||
.Pq Vt single
|
|
||||||
The location of the
|
|
||||||
.Xr cvs 1
|
|
||||||
repository.
|
|
||||||
No default value.
|
|
||||||
.It SANDBOX
|
|
||||||
.Pq Vt single
|
|
||||||
The location of the sandbox directory.
|
|
||||||
The default value is
|
|
||||||
.Pa /tmp/tinderbox .
|
|
||||||
.It SENDER
|
|
||||||
.Pq Vt single
|
|
||||||
The envelope sender to use when mailing out failure reports.
|
|
||||||
This should be a single email address.
|
|
||||||
No default value.
|
|
||||||
.It SUBJECT
|
|
||||||
.Pq Vt single
|
|
||||||
The subject to use on failure reports.
|
|
||||||
The default value is
|
|
||||||
.Dq Tinderbox failure on %%arch%%/%%machine%% .
|
|
||||||
.It TARGETS
|
|
||||||
.Pq Vt multiple
|
|
||||||
A list of targets (commands) to specify to the
|
|
||||||
.Xr tinderbox 1
|
|
||||||
script.
|
|
||||||
The default is
|
|
||||||
.Dq world .
|
|
||||||
.It TIMEOUT
|
|
||||||
The number of seconds after which each tinderbox invocation will time
|
|
||||||
out.
|
|
||||||
No default value.
|
|
||||||
.It TINDERBOX
|
|
||||||
The location of the
|
|
||||||
.Xr tinderbox 1
|
|
||||||
script.
|
|
||||||
The default value is
|
|
||||||
.Dq %%HOME%%/bin/tinderbox .
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
Fields which are left undefined are filled in from the
|
|
||||||
.Dq global
|
|
||||||
setup.
|
|
||||||
.Ss Variable Substitution
|
|
||||||
All single-valued configuration variables are subject to variable
|
|
||||||
substitution immediately before use.
|
|
||||||
If a variable's value contains strings of the form
|
|
||||||
.Va %%VAR%%
|
|
||||||
or
|
|
||||||
.Va %%var%% ,
|
|
||||||
those strings are replaced with the values of the corresponding
|
|
||||||
variables.
|
|
||||||
The difference between the first and the second form is that the
|
|
||||||
latter expands to lower-case.
|
|
||||||
For instance,
|
|
||||||
.Dq %%BRANCH%%
|
|
||||||
might expand to
|
|
||||||
.Dq RELENG_4
|
|
||||||
while
|
|
||||||
.Dq %%branch%%
|
|
||||||
would expand to
|
|
||||||
.Dq releng_4 .
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr perl 1 ,
|
|
||||||
.Xr tinderbox 1
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Nm
|
|
||||||
was written by
|
|
||||||
.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org .
|
|
||||||
.Sh BUGS
|
|
||||||
- part of a complete breakfast!
|
|
@ -1,590 +0,0 @@
|
|||||||
#!/usr/bin/perl -Tw
|
|
||||||
#-
|
|
||||||
# Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer
|
|
||||||
# in this position and unchanged.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
use 5.006_001;
|
|
||||||
use strict;
|
|
||||||
use Fcntl qw(:DEFAULT :flock);
|
|
||||||
use POSIX;
|
|
||||||
use Getopt::Long;
|
|
||||||
|
|
||||||
my $VERSION = "2.3";
|
|
||||||
my $COPYRIGHT = "Copyright (c) 2003-2006 Dag-Erling Smørgrav. " .
|
|
||||||
"All rights reserved.";
|
|
||||||
|
|
||||||
my @configs; # Names of requested configations
|
|
||||||
my $dump; # Dump configuration and exit
|
|
||||||
my $etcdir; # Configuration directory
|
|
||||||
my $lockfile; # Lock file name
|
|
||||||
my $lock; # Lock file descriptor
|
|
||||||
|
|
||||||
my %INITIAL_CONFIG = (
|
|
||||||
'BRANCHES' => [ 'HEAD' ],
|
|
||||||
'CFLAGS' => '',
|
|
||||||
'COPTFLAGS' => '',
|
|
||||||
'COMMENT' => '',
|
|
||||||
'CVSUP' => '',
|
|
||||||
'DATE' => '',
|
|
||||||
'ENV' => [],
|
|
||||||
'HOSTNAME' => '',
|
|
||||||
'JOBS' => '',
|
|
||||||
'LOGDIR' => '%%SANDBOX%%/logs',
|
|
||||||
'OPTIONS' => [],
|
|
||||||
'PATCH' => '',
|
|
||||||
'PLATFORMS' => [ 'i386' ],
|
|
||||||
'RECIPIENT' => '',
|
|
||||||
'REPOSITORY'=> '',
|
|
||||||
'SANDBOX' => '/tmp/tinderbox',
|
|
||||||
'SENDER' => '',
|
|
||||||
'SUBJECT' => 'Tinderbox failure on %%arch%%/%%machine%%',
|
|
||||||
'TARGETS' => [ 'update', 'world' ],
|
|
||||||
'TIMEOUT' => '',
|
|
||||||
'TINDERBOX' => '%%HOME%%/bin/tinderbox',
|
|
||||||
);
|
|
||||||
my %CONFIG;
|
|
||||||
|
|
||||||
###
|
|
||||||
### Expand a path
|
|
||||||
###
|
|
||||||
sub realpath($;$);
|
|
||||||
sub realpath($;$) {
|
|
||||||
my $path = shift;
|
|
||||||
my $base = shift || "";
|
|
||||||
|
|
||||||
my $realpath = ($path =~ m|^/|) ? "" : $base;
|
|
||||||
my @parts = split('/', $path);
|
|
||||||
while (defined(my $part = shift(@parts))) {
|
|
||||||
if ($part eq '' || $part eq '.') {
|
|
||||||
# nothing
|
|
||||||
} elsif ($part eq '..') {
|
|
||||||
$realpath =~ s|/[^/]+$||
|
|
||||||
or die("'$path' is not a valid path relative to '$base'\n");
|
|
||||||
} elsif (-l "$realpath/$part") {
|
|
||||||
my $target = readlink("$realpath/$part")
|
|
||||||
or die("unable to resolve symlink '$realpath/$part': $!\n");
|
|
||||||
$realpath = realpath($target, $realpath);
|
|
||||||
} else {
|
|
||||||
$part =~ m/^([\w.-]+)$/
|
|
||||||
or die("unsafe path '$realpath/$part'\n");
|
|
||||||
$realpath .= "/$1";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $realpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Perform variable expansion
|
|
||||||
###
|
|
||||||
sub expand($);
|
|
||||||
sub expand($) {
|
|
||||||
my $key = shift;
|
|
||||||
|
|
||||||
return "??$key??"
|
|
||||||
unless exists($CONFIG{uc($key)});
|
|
||||||
return $CONFIG{uc($key)}
|
|
||||||
if (ref($CONFIG{uc($key)}));
|
|
||||||
my $str = $CONFIG{uc($key)};
|
|
||||||
while ($str =~ s/\%\%(\w+)\%\%/expand($1)/eg) {
|
|
||||||
# nothing
|
|
||||||
}
|
|
||||||
return ($key =~ m/[A-Z]/) ? $str : lc($str);
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Reset the configuration to initial values
|
|
||||||
###
|
|
||||||
sub clearconf() {
|
|
||||||
|
|
||||||
%CONFIG = %INITIAL_CONFIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Read in a configuration file
|
|
||||||
###
|
|
||||||
sub readconf($) {
|
|
||||||
my $fn = shift;
|
|
||||||
|
|
||||||
local *CONF;
|
|
||||||
sysopen(CONF, $fn, O_RDONLY)
|
|
||||||
or return undef;
|
|
||||||
my $line = "";
|
|
||||||
my $n = 0;
|
|
||||||
while (<CONF>) {
|
|
||||||
++$n;
|
|
||||||
chomp();
|
|
||||||
s/\s*(\#.*)?$//;
|
|
||||||
$line .= $_;
|
|
||||||
if (length($line) && $line !~ s/\\$/ /) {
|
|
||||||
die("$fn: syntax error on line $n\n")
|
|
||||||
unless ($line =~ m/^(\w+)\s*([+]?=)\s*(.*)$/);
|
|
||||||
my ($key, $op, $val) = (uc($1), $2, $3);
|
|
||||||
$val = ''
|
|
||||||
unless defined($val);
|
|
||||||
die("$fn: unknown keyword on line $n\n")
|
|
||||||
unless (exists($CONFIG{$key}));
|
|
||||||
if (ref($CONFIG{$key})) {
|
|
||||||
my @a = split(/\s*,\s*/, $val);
|
|
||||||
foreach (@a) {
|
|
||||||
s/^\'([^\']*)\'$/$1/;
|
|
||||||
}
|
|
||||||
if ($op eq '=') {
|
|
||||||
$CONFIG{$key} = \@a;
|
|
||||||
} elsif ($op eq '+=') {
|
|
||||||
push(@{$CONFIG{$key}}, @a);
|
|
||||||
} else {
|
|
||||||
die("can't happen\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$val =~ s/^\'([^\']*)\'$/$1/;
|
|
||||||
if ($op eq '=') {
|
|
||||||
$CONFIG{$key} = $val;
|
|
||||||
} elsif ($op eq '+=') {
|
|
||||||
die("$fn: invalid operator on line $n\n");
|
|
||||||
} else {
|
|
||||||
die("can't happen\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$line = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(CONF);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Record a tinderbox result in the history file
|
|
||||||
###
|
|
||||||
sub history($$$) {
|
|
||||||
my $start = shift;
|
|
||||||
my $end = shift;
|
|
||||||
my $success = shift;
|
|
||||||
|
|
||||||
my $history = expand('HOSTNAME') . "\t";
|
|
||||||
$history .= expand('CONFIG') . "\t";
|
|
||||||
$history .= strftime("%Y-%m-%d %H:%M:%S\t", localtime($start));
|
|
||||||
$history .= strftime("%Y-%m-%d %H:%M:%S\t", localtime($end));
|
|
||||||
$history .= expand('ARCH') . "\t";
|
|
||||||
$history .= expand('MACHINE') . "\t";
|
|
||||||
my $date = expand('DATE');
|
|
||||||
if ($date) {
|
|
||||||
$date =~ s/\s+/ /g;
|
|
||||||
$history .= expand('BRANCH') . ":" . expand('DATE') . "\t";
|
|
||||||
} else {
|
|
||||||
$history .= expand('BRANCH') . "\t";
|
|
||||||
}
|
|
||||||
$history .= $success ? "OK\n" : "FAIL\n";
|
|
||||||
|
|
||||||
my $fn = expand('LOGDIR') . "/history";
|
|
||||||
local *HISTORY;
|
|
||||||
if (sysopen(HISTORY, $fn, O_WRONLY|O_APPEND|O_CREAT, 0644)) {
|
|
||||||
syswrite(HISTORY, $history, length($history));
|
|
||||||
close(HISTORY);
|
|
||||||
} else {
|
|
||||||
print(STDERR "failed to record result to history file:\n$history\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Report a tinderbox failure
|
|
||||||
###
|
|
||||||
sub report($$$$) {
|
|
||||||
my $sender = shift;
|
|
||||||
my $recipient = shift;
|
|
||||||
my $subject = shift;
|
|
||||||
my $message = shift;
|
|
||||||
|
|
||||||
if (!$message) {
|
|
||||||
print(STDERR "[empty report, not sent by email]\n\n]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (length($message) < 128) {
|
|
||||||
print(STDERR "[suspiciously short report, not sent by email]\n\n");
|
|
||||||
print(STDERR $message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
local *PIPE;
|
|
||||||
if (open(PIPE, "|-", "/usr/sbin/sendmail", "-i", "-t", "-f$sender")) {
|
|
||||||
print(PIPE "Sender: $sender\n");
|
|
||||||
print(PIPE "From: $sender\n");
|
|
||||||
print(PIPE "To: $recipient\n");
|
|
||||||
print(PIPE "Subject: $subject\n");
|
|
||||||
print(PIPE "Precedence: bulk\n");
|
|
||||||
print(PIPE "\n");
|
|
||||||
print(PIPE "$message\n");
|
|
||||||
close(PIPE);
|
|
||||||
} else {
|
|
||||||
print(STDERR "[failed to send report by email]\n\n");
|
|
||||||
print(STDERR $message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Run the tinderbox
|
|
||||||
###
|
|
||||||
sub tinderbox($$$) {
|
|
||||||
my $branch = shift;
|
|
||||||
my $arch = shift;
|
|
||||||
my $machine = shift;
|
|
||||||
|
|
||||||
my $config = expand('CONFIG');
|
|
||||||
my $start = time();
|
|
||||||
|
|
||||||
$0 = "tbmaster: building $branch for $arch/$machine";
|
|
||||||
|
|
||||||
$CONFIG{'BRANCH'} = $branch;
|
|
||||||
$CONFIG{'ARCH'} = $arch;
|
|
||||||
$CONFIG{'MACHINE'} = $machine;
|
|
||||||
|
|
||||||
# Open log files: one for the full log and one for the summary
|
|
||||||
my $logfile = expand('LOGDIR') .
|
|
||||||
"/tinderbox-$config-$branch-$arch-$machine";
|
|
||||||
local (*FULL, *BRIEF);
|
|
||||||
if (!open(FULL, ">", "$logfile.full.$$")) {
|
|
||||||
warn("$logfile.full.$$: $!\n");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
select(FULL);
|
|
||||||
$| = 1;
|
|
||||||
select(STDOUT);
|
|
||||||
if (!open(BRIEF, ">", "$logfile.brief.$$")) {
|
|
||||||
warn("$logfile.brief.$$: $!\n");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
select(BRIEF);
|
|
||||||
$| = 1;
|
|
||||||
select(STDOUT);
|
|
||||||
|
|
||||||
# Open a pipe for the tinderbox process
|
|
||||||
local (*RPIPE, *WPIPE);
|
|
||||||
if (!pipe(RPIPE, WPIPE)) {
|
|
||||||
warn("pipe(): $!\n");
|
|
||||||
unlink("$logfile.brief.$$");
|
|
||||||
close(BRIEF);
|
|
||||||
unlink("$logfile.full.$$");
|
|
||||||
close(FULL);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Fork and start the tinderbox
|
|
||||||
my @args = @{$CONFIG{'OPTIONS'}};
|
|
||||||
push(@args, "--hostname=" . expand('HOSTNAME'));
|
|
||||||
push(@args, "--sandbox=" . realpath(expand('SANDBOX')));
|
|
||||||
push(@args, "--arch=$arch");
|
|
||||||
push(@args, "--machine=$machine");
|
|
||||||
push(@args, "--cvsup=" . expand('CVSUP'))
|
|
||||||
if ($CONFIG{'CVSUP'});
|
|
||||||
push(@args, "--repository=" . expand('REPOSITORY'))
|
|
||||||
if ($CONFIG{'REPOSITORY'});
|
|
||||||
push(@args, "--branch=$branch");
|
|
||||||
push(@args, "--date=" . expand('DATE'))
|
|
||||||
if ($CONFIG{'DATE'});
|
|
||||||
push(@args, "--patch=" . expand('PATCH'))
|
|
||||||
if ($CONFIG{'PATCH'});
|
|
||||||
push(@args, "--jobs=" . expand('JOBS'))
|
|
||||||
if ($CONFIG{'JOBS'});
|
|
||||||
push(@args, "--timeout=" . expand('TIMEOUT'))
|
|
||||||
if ($CONFIG{'TIMEOUT'});
|
|
||||||
push(@args, @{$CONFIG{'TARGETS'}});
|
|
||||||
push(@args, @{$CONFIG{'ENV'}});
|
|
||||||
push(@args, "CFLAGS=" . expand('CFLAGS'))
|
|
||||||
if ($CONFIG{'CFLAGS'});
|
|
||||||
push(@args, "COPTFLAGS=" . expand('COPTFLAGS'))
|
|
||||||
if ($CONFIG{'COPTFLAGS'});
|
|
||||||
my $pid = fork();
|
|
||||||
if (!defined($pid)) {
|
|
||||||
warn("fork(): $!\n");
|
|
||||||
unlink("$logfile.brief.$$");
|
|
||||||
close(BRIEF);
|
|
||||||
unlink("$logfile.full.$$");
|
|
||||||
close(FULL);
|
|
||||||
return undef;
|
|
||||||
} elsif ($pid == 0) {
|
|
||||||
close(RPIPE);
|
|
||||||
open(STDOUT, ">&WPIPE");
|
|
||||||
open(STDERR, ">&WPIPE");
|
|
||||||
$| = 1;
|
|
||||||
exec(expand('TINDERBOX'), @args);
|
|
||||||
die("child: exec(): $!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Process the output
|
|
||||||
close(WPIPE);
|
|
||||||
my @lines = ();
|
|
||||||
my $error = 0;
|
|
||||||
my $summary = "";
|
|
||||||
my $root = realpath(expand('SANDBOX') . "/$branch/$arch/$machine");
|
|
||||||
while (<RPIPE>) {
|
|
||||||
s/\Q$root\E\/(src|obj)/\/$1/g;
|
|
||||||
print(FULL $_);
|
|
||||||
if (/^TB ---/ || /^>>> /) {
|
|
||||||
if ($error) {
|
|
||||||
$summary .= join('', @lines);
|
|
||||||
print(BRIEF join('', @lines));
|
|
||||||
@lines = ();
|
|
||||||
$error = 0;
|
|
||||||
}
|
|
||||||
$summary .= $_;
|
|
||||||
print(BRIEF $_);
|
|
||||||
@lines = ();
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if (/^Stop in /) {
|
|
||||||
$error = 1;
|
|
||||||
}
|
|
||||||
if (@lines > 10 && !$error) {
|
|
||||||
shift(@lines);
|
|
||||||
$lines[0] = "[...]\n";
|
|
||||||
}
|
|
||||||
push(@lines, $_);
|
|
||||||
}
|
|
||||||
close(RPIPE);
|
|
||||||
if ($error) {
|
|
||||||
$summary .= join('', @lines);
|
|
||||||
print(BRIEF join('', @lines));
|
|
||||||
}
|
|
||||||
|
|
||||||
# Done...
|
|
||||||
if (waitpid($pid, 0) == -1) {
|
|
||||||
warn("waitpid(): $!\n");
|
|
||||||
} elsif ($? & 0xff) {
|
|
||||||
my $msg = "tinderbox caught signal " . ($? & 0x7f) . "\n";
|
|
||||||
print(BRIEF $msg);
|
|
||||||
print(FULL $msg);
|
|
||||||
$error = 1;
|
|
||||||
} elsif ($? >> 8) {
|
|
||||||
my $msg = "tinderbox returned exit code " . ($? >> 8) . "\n";
|
|
||||||
print(BRIEF $msg);
|
|
||||||
print(FULL $msg);
|
|
||||||
$error = 1;
|
|
||||||
}
|
|
||||||
close(BRIEF);
|
|
||||||
close(FULL);
|
|
||||||
|
|
||||||
my $end = time();
|
|
||||||
|
|
||||||
# Record result in history file
|
|
||||||
history($start, $end, !$error);
|
|
||||||
|
|
||||||
# Mail out error reports
|
|
||||||
if ($error && $CONFIG{'RECIPIENT'}) {
|
|
||||||
my $sender = expand('SENDER');
|
|
||||||
my $recipient = expand('RECIPIENT');
|
|
||||||
my $subject = expand('SUBJECT');
|
|
||||||
report($sender, $recipient, $subject, $summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
rename("$logfile.full.$$", "$logfile.full");
|
|
||||||
rename("$logfile.brief.$$", "$logfile.brief");
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Open and lock a file reliably
|
|
||||||
###
|
|
||||||
sub open_locked($;$$) {
|
|
||||||
my $fn = shift; # File name
|
|
||||||
my $flags = shift; # Open flags
|
|
||||||
my $mode = shift; # File mode
|
|
||||||
|
|
||||||
local *FILE; # File handle
|
|
||||||
my (@sb1, @sb2); # File status
|
|
||||||
|
|
||||||
for (;; close(FILE)) {
|
|
||||||
sysopen(FILE, $fn, $flags || O_RDONLY, $mode || 0640)
|
|
||||||
or last;
|
|
||||||
if (!(@sb1 = stat(FILE))) {
|
|
||||||
# Huh? shouldn't happen
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
if (!flock(FILE, LOCK_EX|LOCK_NB)) {
|
|
||||||
# A failure here means the file can't be locked, or
|
|
||||||
# something really weird happened, so just give up.
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
if (!(@sb2 = stat($fn))) {
|
|
||||||
# File was pulled from under our feet, though it may
|
|
||||||
# reappear in the next pass
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($sb1[0] != $sb2[0] || $sb1[1] != $sb2[1]) {
|
|
||||||
# File changed under our feet, try again
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
return *FILE{IO};
|
|
||||||
}
|
|
||||||
close(FILE);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Print a usage message and exit
|
|
||||||
###
|
|
||||||
sub usage() {
|
|
||||||
|
|
||||||
print(STDERR "This is the FreeBSD tinderbox manager, version $VERSION.
|
|
||||||
$COPYRIGHT
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$0 [options] [parameters]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-d, --dump Dump the processed configuration
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
-c, --config=NAME Configuration name
|
|
||||||
-e, --etcdir=DIR Configuration directory
|
|
||||||
-l, --lockfile=FILE Lock file name
|
|
||||||
|
|
||||||
Report bugs to <des\@freebsd.org>.
|
|
||||||
");
|
|
||||||
print(STDERR "usage: tbmaster\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Main loop
|
|
||||||
###
|
|
||||||
sub tbmaster($) {
|
|
||||||
my $config = shift;
|
|
||||||
|
|
||||||
clearconf();
|
|
||||||
readconf('default.rc');
|
|
||||||
readconf('site.rc');
|
|
||||||
readconf("$config.rc")
|
|
||||||
or die("$config.rc: $!\n");
|
|
||||||
$CONFIG{'CONFIG'} = $config;
|
|
||||||
$CONFIG{'ETCDIR'} = $etcdir;
|
|
||||||
|
|
||||||
if ($dump) {
|
|
||||||
foreach my $key (sort(keys(%CONFIG))) {
|
|
||||||
printf("%-12s = ", uc($key));
|
|
||||||
if (!defined($CONFIG{$key})) {
|
|
||||||
print("(undef)");
|
|
||||||
} elsif (ref($CONFIG{$key})) {
|
|
||||||
print(join(", ", @{$CONFIG{$key}}));
|
|
||||||
} else {
|
|
||||||
print($CONFIG{$key});
|
|
||||||
}
|
|
||||||
print("\n");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!length(expand('TINDERBOX')) || !-x expand('TINDERBOX')) {
|
|
||||||
die("Where is the tinderbox script?\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $stopfile = expand('SANDBOX') . "/stop";
|
|
||||||
foreach my $branch (@{$CONFIG{'BRANCHES'}}) {
|
|
||||||
foreach my $platform (@{$CONFIG{'PLATFORMS'}}) {
|
|
||||||
if (-e $stopfile || -e "$stopfile.$config") {
|
|
||||||
die("stop file found, aborting\n");
|
|
||||||
}
|
|
||||||
my ($arch, $machine) = split('/', $platform, 2);
|
|
||||||
$machine = $arch
|
|
||||||
unless defined($machine);
|
|
||||||
if (-e "$stopfile.$arch" || -e "$stopfile.$arch.$machine") {
|
|
||||||
warn("stop file for $arch/$machine found, skipping\n");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
tinderbox($branch, $arch, $machine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
### Main
|
|
||||||
###
|
|
||||||
MAIN:{
|
|
||||||
# Set defaults
|
|
||||||
$ENV{'TZ'} = "UTC";
|
|
||||||
$ENV{'PATH'} = "/usr/bin:/usr/sbin:/bin:/sbin";
|
|
||||||
$INITIAL_CONFIG{'HOSTNAME'} = `/usr/bin/uname -n`;
|
|
||||||
if ($INITIAL_CONFIG{'HOSTNAME'} =~ m/^([0-9a-z-]+(?:\.[0-9a-z-]+)*)$/) {
|
|
||||||
$INITIAL_CONFIG{'HOSTNAME'} = $1;
|
|
||||||
} else {
|
|
||||||
$INITIAL_CONFIG{'HOSTNAME'} = 'unknown';
|
|
||||||
}
|
|
||||||
if ($ENV{'HOME'} =~ m/^((?:\/[\w\.-]+)+)\/*$/) {
|
|
||||||
$INITIAL_CONFIG{'HOME'} = realpath($1);
|
|
||||||
$etcdir = "$1/etc";
|
|
||||||
$ENV{'PATH'} = "$1/bin:$ENV{'PATH'}"
|
|
||||||
if (-d "$1/bin");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get options
|
|
||||||
{Getopt::Long::Configure("auto_abbrev", "bundling");}
|
|
||||||
GetOptions(
|
|
||||||
"c|config=s" => \@configs,
|
|
||||||
"d|dump" => \$dump,
|
|
||||||
"e|etcdir=s" => \$etcdir,
|
|
||||||
"l|lockfile=s" => \$lockfile,
|
|
||||||
) or usage();
|
|
||||||
if (@ARGV) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check options
|
|
||||||
if (@configs) {
|
|
||||||
@configs = split(/,/, join(',', @configs));
|
|
||||||
} else {
|
|
||||||
$configs[0] = `/usr/bin/uname -n`;
|
|
||||||
chomp($configs[0]);
|
|
||||||
$configs[0] =~ s/^(\w+)(\..*)?/$1/;
|
|
||||||
}
|
|
||||||
if (defined($etcdir)) {
|
|
||||||
if ($etcdir !~ m/^([\w\/\.-]+)$/) {
|
|
||||||
die("invalid etcdir\n");
|
|
||||||
}
|
|
||||||
$etcdir = $1;
|
|
||||||
chdir($etcdir)
|
|
||||||
or die("$etcdir: $!\n");
|
|
||||||
}
|
|
||||||
for (my $n = 0; $n < @configs; ++$n) {
|
|
||||||
$configs[$n] =~ m/^(\w+)$/
|
|
||||||
or die("invalid config: $configs[$n]\n");
|
|
||||||
$configs[$n] = $1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Acquire lock
|
|
||||||
if (defined($lockfile)) {
|
|
||||||
if ($lockfile !~ m/^([\w\/\.-]+)$/) {
|
|
||||||
die("invalid lockfile\n");
|
|
||||||
}
|
|
||||||
$lockfile = $1;
|
|
||||||
$lock = open_locked($lockfile, O_WRONLY|O_CREAT, 0600)
|
|
||||||
or die("unable to acquire lock on $lockfile\n");
|
|
||||||
# Lock will be released upon termination.
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run all specified or implied configurations
|
|
||||||
foreach my $config (@configs) {
|
|
||||||
tbmaster($config);
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,319 +0,0 @@
|
|||||||
.\"-
|
|
||||||
.\" Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted provided that the following conditions
|
|
||||||
.\" are met:
|
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
.\" SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.\" $FreeBSD$
|
|
||||||
.\"
|
|
||||||
.Dd April 7, 2006
|
|
||||||
.Dt TINDERBOX 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm tinderbox
|
|
||||||
.Nd build and release testing
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op options
|
|
||||||
.Ar command Op ...
|
|
||||||
.Op Ar variable Ns = Ns Ar value ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script tests the
|
|
||||||
.Fx
|
|
||||||
build and release system by performing a cross-build (and optionally a
|
|
||||||
cross-release) of an arbitrary branch of the source tree for an
|
|
||||||
arbitrary target platform.
|
|
||||||
.Pp
|
|
||||||
The following options are recognized:
|
|
||||||
.Bl -tag -width 12n
|
|
||||||
.It Fl a Ar ARCH , Fl -arch Ns = Ns Ar ARCH
|
|
||||||
Specifies the target architecture.
|
|
||||||
The default value is whatever the host system's
|
|
||||||
.Xr uname 1
|
|
||||||
reports.
|
|
||||||
.It Fl b Ar BRANCH , Fl -branch Ns = Ns Ar BRANCH
|
|
||||||
The branch to specify to
|
|
||||||
.Xr cvs 1
|
|
||||||
or
|
|
||||||
.Xr cvsup 1
|
|
||||||
when updating the source tree.
|
|
||||||
The default is to use
|
|
||||||
.Fl A
|
|
||||||
instead, to get the head.
|
|
||||||
Specifying
|
|
||||||
.Va HEAD
|
|
||||||
as the argument to
|
|
||||||
.Fl -branch
|
|
||||||
is equivalent to leaving it unspecified.
|
|
||||||
.It Fl c Ar NAME , Fl -cvsup Ns = Ns Ar NAME
|
|
||||||
The name of the
|
|
||||||
.Xr cvsup 1
|
|
||||||
server from which to update the source tree
|
|
||||||
.Cm update
|
|
||||||
command is specified.
|
|
||||||
The default is to use
|
|
||||||
.Xr cvs 1
|
|
||||||
instead.
|
|
||||||
.It Fl d Ar DATE , Fl -date Ns = Ns Ar DATE
|
|
||||||
The date to specify to
|
|
||||||
.Xr cvs 1
|
|
||||||
or
|
|
||||||
.Xr cvsup 1
|
|
||||||
when updating the source tree.
|
|
||||||
As a special case, the value
|
|
||||||
.Dq today
|
|
||||||
corresponds to midnight UTC the day the run starts.
|
|
||||||
The default is to use the top of whichever branch was specified.
|
|
||||||
.It Fl h Ar NAME , Fl -hostname Ns = Ns Ar NAME
|
|
||||||
The name of the host running the tinderbox.
|
|
||||||
This defaults to the name reported by the
|
|
||||||
.Fl n
|
|
||||||
option of the
|
|
||||||
.Xr uname 1
|
|
||||||
command, and is only used for cosmetic purposes.
|
|
||||||
.It Fl j Ar NUM , Fl -jobs Ns = Ns Ar NUM
|
|
||||||
The maximum number of paralell jobs, as specified to
|
|
||||||
.Xr make 1
|
|
||||||
using the
|
|
||||||
.Fl j
|
|
||||||
option.
|
|
||||||
The default is 1.
|
|
||||||
.It Fl l Ar FILE , Fl -logfile Ns = Ns Ar FILE
|
|
||||||
The name of a file to which the output and error messages produced by
|
|
||||||
the build should be written.
|
|
||||||
Note that this file can grow quite large.
|
|
||||||
The default is to redirect all output to
|
|
||||||
.Pa /dev/stdout .
|
|
||||||
.It Fl m Ar MACHINE , Fl -machine Ns = Ns Ar MACHINE
|
|
||||||
Specifies the target machine.
|
|
||||||
The default value is whatever the host system's
|
|
||||||
.Xr uname 1
|
|
||||||
reports, unless a target architecture was specified with the
|
|
||||||
.It Fl a
|
|
||||||
option, in which case the target machine is set to the same value.
|
|
||||||
.It Fl p Ar PATCH , Fl -patch Ns = Ns Ar PATCH
|
|
||||||
The file name of a patch to apply to the source tree before building
|
|
||||||
if the
|
|
||||||
.Cm patch
|
|
||||||
command is specified.
|
|
||||||
The patch should be relative to the root of the source tree.
|
|
||||||
When building a release, the patch is passed to the release process
|
|
||||||
through the
|
|
||||||
.Ev LOCAL_PATCHES
|
|
||||||
environment variable (see
|
|
||||||
.Xr release 7
|
|
||||||
for more information), regardless of whether the
|
|
||||||
.Cm patch
|
|
||||||
command was specified.
|
|
||||||
The default is to not apply any patches.
|
|
||||||
.It Fl r Ar DIR , Fl -repository Ns = Ns Ar DIR
|
|
||||||
The location of the
|
|
||||||
.Xr cvs 1
|
|
||||||
repository from which to update the source tree if the
|
|
||||||
.Cm update
|
|
||||||
command is specified.
|
|
||||||
The default is
|
|
||||||
.Pa /home/ncvs .
|
|
||||||
.It Fl s Ar DIR , Fl -sandbox Ns = Ns Ar DIR
|
|
||||||
The location of the sandbox in which the builds are to take place.
|
|
||||||
This directory should reside on a reasonably fast disk with at least
|
|
||||||
1.5 GB available (3 GB if building a release).
|
|
||||||
.It Fl t Ar NUM , Fl -timeout Ns = Ns Ar NUM
|
|
||||||
The maximum wall-time duration of the run, in seconds.
|
|
||||||
The default is to continue until all targets are completed.
|
|
||||||
.It Fl v , Fl -verbose
|
|
||||||
Enable additional debugging output.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
Following the options on the command line, at least one of the
|
|
||||||
following commands must be specified:
|
|
||||||
.Bl -tag -width 12n
|
|
||||||
.It Cm clean
|
|
||||||
Delete the source and object trees.
|
|
||||||
This is highly recommended when sources are patched, as successive
|
|
||||||
builds will fail due to repeated application of the same patch to the
|
|
||||||
same sources.
|
|
||||||
.Pp
|
|
||||||
Note that this does not remove the chroot tree created and populated
|
|
||||||
by the release build.
|
|
||||||
.It Cm update
|
|
||||||
Update the sources using
|
|
||||||
.Xr cvs 1 .
|
|
||||||
This is highly recommended, for obvious reasons, if the
|
|
||||||
.Cm clean
|
|
||||||
command is specified.
|
|
||||||
.It Cm patch
|
|
||||||
Apply the patch specified with the
|
|
||||||
.Fl -patch
|
|
||||||
option to the source tree.
|
|
||||||
If the specified patch file does not exist, the
|
|
||||||
.Cm patch
|
|
||||||
command will fail gracefully.
|
|
||||||
.It Cm world
|
|
||||||
Build the world.
|
|
||||||
.It Cm lint
|
|
||||||
Build a LINT kernel if available.
|
|
||||||
In
|
|
||||||
.Fx
|
|
||||||
5 and newer, the
|
|
||||||
.Pa LINT
|
|
||||||
configuration file will first be generated from the corresponding
|
|
||||||
.Pa NOTES
|
|
||||||
file.
|
|
||||||
If neither
|
|
||||||
.Pa LINT
|
|
||||||
nor
|
|
||||||
.Pa NOTES
|
|
||||||
exist in the kernel configuration directory, the
|
|
||||||
.Cm lint
|
|
||||||
command will fail gracefully.
|
|
||||||
.It Cm kernel: Ns Ar CONF
|
|
||||||
Build the
|
|
||||||
.Ar CONF
|
|
||||||
kernel.
|
|
||||||
If a file named
|
|
||||||
.Ar CONF
|
|
||||||
does not exist in the kernel configuration directory, this command
|
|
||||||
will fail gracefully.
|
|
||||||
.It Cm generic
|
|
||||||
Equivalent to
|
|
||||||
.Cm kernel: Ns Ar GENERIC ,
|
|
||||||
for backward compatibility.
|
|
||||||
.It Cm release
|
|
||||||
Build a release by following the procedure described in
|
|
||||||
.Xr release 7 .
|
|
||||||
Note that this is a lengthy process which requires root privileges.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
The commands are executed in the order in which they are listed above,
|
|
||||||
regardless of the order in which they are listed on the command line.
|
|
||||||
.Pp
|
|
||||||
Finally, any arguments of the form
|
|
||||||
.Ar variable Ns = Ns Ar value
|
|
||||||
are interpreted as environment variables which are exported into the
|
|
||||||
build environment.
|
|
||||||
These variables are not allowed to override those set by the script
|
|
||||||
itself (see
|
|
||||||
.Sx ENVIRONMENT
|
|
||||||
below).
|
|
||||||
.Sh NOTES
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script was originally written to perform daily build testing of
|
|
||||||
.Fx
|
|
||||||
4 and 5.
|
|
||||||
It is not intended for use with older releases, and probably will not
|
|
||||||
work with anything older than
|
|
||||||
.Fx 4.2 .
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script clears its environment at startup and provides its child
|
|
||||||
processes with a tailored environment.
|
|
||||||
The following variables are set for all builds:
|
|
||||||
.Bl -tag -width 18n
|
|
||||||
.It PATH
|
|
||||||
.Va /usr/bin:/usr/sbin:/bin:/sbin
|
|
||||||
.It TZ
|
|
||||||
.Va UTC
|
|
||||||
.It __MAKE_CONF
|
|
||||||
.Va /dev/null
|
|
||||||
.It CFLAGS
|
|
||||||
.Va -O -pipe
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
In addition, if one or more of the
|
|
||||||
.Cm generic ,
|
|
||||||
.Cm lint
|
|
||||||
or
|
|
||||||
.Cm release
|
|
||||||
command was specified, the following variables, which affect kernel
|
|
||||||
builds, are set:
|
|
||||||
.Bl -tag -width 18n
|
|
||||||
.It COPTFLAGS
|
|
||||||
.Va -O -pipe
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
Finally, the following variables are set for release builds:
|
|
||||||
.Bl -tag -width 18n
|
|
||||||
.It CHROOTDIR
|
|
||||||
.Va $SANDBOX/root
|
|
||||||
.It CVSROOT
|
|
||||||
As specified with the
|
|
||||||
.Fl -repository
|
|
||||||
option.
|
|
||||||
.It RELEASETAG
|
|
||||||
.Va -rBRANCH
|
|
||||||
if
|
|
||||||
.Fl -branch Ns = Ns Ar BRANCH
|
|
||||||
was specified, or
|
|
||||||
.Va -A
|
|
||||||
otherwise.
|
|
||||||
.It CVSCMDARGS
|
|
||||||
.Va -DDATE
|
|
||||||
if
|
|
||||||
.Fl -date Ns = Ns Ar DATE
|
|
||||||
was specified.
|
|
||||||
.It WORLD_FLAGS , KERNEL_FLAGS
|
|
||||||
Both of these are set to
|
|
||||||
.Va -jN
|
|
||||||
if
|
|
||||||
.Fl -jobs Ns = Ns Ar N
|
|
||||||
was specified, or
|
|
||||||
.Va -B
|
|
||||||
otherwise.
|
|
||||||
.It LOCAL_PATCHES
|
|
||||||
Set to the path of the patch that was specified with the
|
|
||||||
.Fl -patch
|
|
||||||
option, if any.
|
|
||||||
.It PATCH_FLAGS
|
|
||||||
Set to
|
|
||||||
.Va -fs
|
|
||||||
if a patch was specified.
|
|
||||||
.It NOCDROM
|
|
||||||
.Va YES
|
|
||||||
.It NODOC
|
|
||||||
.Va YES
|
|
||||||
.It NOPORTS
|
|
||||||
.Va YES
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
Except for
|
|
||||||
.Va CFLAGS
|
|
||||||
and
|
|
||||||
.Va COPTFLAGS ,
|
|
||||||
none of these variables may be overridden by command-line arguments.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr cvs 1 ,
|
|
||||||
.Xr make 1 ,
|
|
||||||
.Xr patch 1 ,
|
|
||||||
.Xr tbmaster 1 ,
|
|
||||||
.Xr build 7 ,
|
|
||||||
.Xr release 7
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Nm
|
|
||||||
was written by
|
|
||||||
.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org .
|
|
||||||
.Sh BUGS
|
|
||||||
are crunchy and nutritious.
|
|
@ -1,663 +0,0 @@
|
|||||||
#!/usr/bin/perl -Tw
|
|
||||||
#-
|
|
||||||
# Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer
|
|
||||||
# in this position and unchanged.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
use 5.006_001;
|
|
||||||
use strict;
|
|
||||||
use Fcntl qw(:DEFAULT :flock);
|
|
||||||
use POSIX;
|
|
||||||
use Getopt::Long;
|
|
||||||
|
|
||||||
my $VERSION = "2.3";
|
|
||||||
my $COPYRIGHT = "Copyright (c) 2003-2006 Dag-Erling Smørgrav. " .
|
|
||||||
"All rights reserved.";
|
|
||||||
|
|
||||||
my $arch; # Target architecture
|
|
||||||
my $branch; # CVS branch to check out
|
|
||||||
my $cvsup; # Name of CVSup server
|
|
||||||
my $date; # Date of sources to check out
|
|
||||||
my $jobs; # Number of paralell jobs
|
|
||||||
my $hostname; # Name of the host running the tinderbox
|
|
||||||
my $logfile; # Path to log file
|
|
||||||
my $machine; # Target machine
|
|
||||||
my $patch; # Patch to apply before building
|
|
||||||
my $repository; # Location of CVS repository
|
|
||||||
my $sandbox; # Location of sandbox
|
|
||||||
my $timeout; # Timeout in seconds
|
|
||||||
my $verbose; # Verbose mode
|
|
||||||
|
|
||||||
my %children;
|
|
||||||
|
|
||||||
my %userenv;
|
|
||||||
|
|
||||||
my %cmds = (
|
|
||||||
'clean' => 0,
|
|
||||||
'cleansrc' => 0,
|
|
||||||
'cleanobj' => 0,
|
|
||||||
'cleanroot' => 0,
|
|
||||||
'update' => 0,
|
|
||||||
'patch' => 0,
|
|
||||||
'world' => 0,
|
|
||||||
'lint' => 0,
|
|
||||||
'release' => 0,
|
|
||||||
);
|
|
||||||
my %kernels;
|
|
||||||
|
|
||||||
my $starttime;
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
($starttime) = POSIX::times();
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
|
||||||
my ($endtime, $user, $system) = POSIX::times();
|
|
||||||
my $ticks = POSIX::sysconf(&POSIX::_SC_CLK_TCK);
|
|
||||||
printf(STDERR "TB --- %.2f user %.2f system %.2f real\n",
|
|
||||||
$user / $ticks, $system / $ticks, ($endtime - $starttime) / $ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub message(@) {
|
|
||||||
|
|
||||||
my $msg = join(' ', @_);
|
|
||||||
chomp($msg);
|
|
||||||
warn("$msg\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub warning(@) {
|
|
||||||
|
|
||||||
my $msg = join(' ', "WARNING:", @_);
|
|
||||||
chomp($msg);
|
|
||||||
warn("$msg\n");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub error(@) {
|
|
||||||
|
|
||||||
my $msg = join(' ', "ERROR:", @_);
|
|
||||||
chomp($msg);
|
|
||||||
die("$msg\n");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Open and lock a file reliably
|
|
||||||
#
|
|
||||||
sub open_locked($;$$) {
|
|
||||||
my $fn = shift; # File name
|
|
||||||
my $flags = shift; # Open flags
|
|
||||||
my $mode = shift; # File mode
|
|
||||||
|
|
||||||
local *FILE; # File handle
|
|
||||||
my (@sb1, @sb2); # File status
|
|
||||||
|
|
||||||
for (;; close(FILE)) {
|
|
||||||
sysopen(FILE, $fn, $flags || O_RDONLY, $mode || 0640)
|
|
||||||
or last;
|
|
||||||
if (!(@sb1 = stat(FILE))) {
|
|
||||||
# Huh? shouldn't happen
|
|
||||||
warning("$fn: stat(): $!");
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
if (!flock(FILE, LOCK_EX|LOCK_NB)) {
|
|
||||||
# A failure here means the file can't be locked, or
|
|
||||||
# something really weird happened, so just give up.
|
|
||||||
warning("$fn: flock(): $!");
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
if (!(@sb2 = stat($fn))) {
|
|
||||||
# File was pulled from under our feet, though it may
|
|
||||||
# reappear in the next pass
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($sb1[0] != $sb2[0] || $sb1[1] != $sb2[1]) {
|
|
||||||
# File changed under our feet, try again
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
return *FILE{IO};
|
|
||||||
}
|
|
||||||
close(FILE);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Remove a directory and all its subdirectories
|
|
||||||
#
|
|
||||||
sub remove_dir($);
|
|
||||||
sub remove_dir($) {
|
|
||||||
my $dir = shift;
|
|
||||||
|
|
||||||
if (-l $dir || !-d $dir) {
|
|
||||||
print("rm $dir\n")
|
|
||||||
if ($verbose);
|
|
||||||
if (!unlink($dir) && $! != ENOENT) {
|
|
||||||
return warning("$dir: $!");
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
local *DIR;
|
|
||||||
opendir(DIR, $dir)
|
|
||||||
or return warning("$dir: $!");
|
|
||||||
my @entries = readdir(DIR);
|
|
||||||
closedir(DIR)
|
|
||||||
or return warning("$dir: $!");
|
|
||||||
foreach my $ent (@entries) {
|
|
||||||
next if ($ent eq '.' || $ent eq '..');
|
|
||||||
$ent =~ m/(.*)/;
|
|
||||||
remove_dir("$dir/$1")
|
|
||||||
or return undef;
|
|
||||||
}
|
|
||||||
print("rmdir $dir\n")
|
|
||||||
if ($verbose);
|
|
||||||
rmdir($dir)
|
|
||||||
or return warning("$dir: $!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub make_dir($);
|
|
||||||
sub make_dir($) {
|
|
||||||
my $dir = shift;
|
|
||||||
|
|
||||||
if (!-d $dir && $dir =~ m|^(\S*)/([^\s/]+)$|) {
|
|
||||||
make_dir($1)
|
|
||||||
or return undef;
|
|
||||||
message("mkdir $dir");
|
|
||||||
mkdir("$dir")
|
|
||||||
or return undef;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cd($) {
|
|
||||||
my $dir = shift;
|
|
||||||
|
|
||||||
message("cd $dir");
|
|
||||||
chdir($dir)
|
|
||||||
or error("$dir: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Spawn a child and wait for it to finish
|
|
||||||
#
|
|
||||||
sub spawn($@) {
|
|
||||||
my $cmd = shift; # Command to run
|
|
||||||
my @args = @_; # Arguments
|
|
||||||
|
|
||||||
message($cmd, @args);
|
|
||||||
my $pid = fork();
|
|
||||||
if (!defined($pid)) {
|
|
||||||
return warning("fork(): $!");
|
|
||||||
} elsif ($pid == 0) {
|
|
||||||
exec($cmd, @args);
|
|
||||||
die("child: exec(): $!\n");
|
|
||||||
}
|
|
||||||
$children{$pid} = $pid;
|
|
||||||
my $ret = waitpid($pid, 0);
|
|
||||||
delete $children{$pid};
|
|
||||||
if ($ret == -1) {
|
|
||||||
return warning("waitpid(): $!\n");
|
|
||||||
} elsif ($? & 0xff) {
|
|
||||||
return warning("$cmd caught signal ", $? & 0x7f, "\n");
|
|
||||||
} elsif ($? >> 8) {
|
|
||||||
return warning("$cmd returned exit code ", $? >> 8, "\n");
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub make($) {
|
|
||||||
my $target = shift;
|
|
||||||
|
|
||||||
return spawn('/usr/bin/make',
|
|
||||||
($jobs > 1) ? "-j$jobs" : "-B",
|
|
||||||
$target);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub logstage($) {
|
|
||||||
my $msg = shift;
|
|
||||||
|
|
||||||
chomp($msg);
|
|
||||||
$0 = "tinderbox: [$branch $arch/$machine] $msg";
|
|
||||||
print(STDERR strftime("TB --- %Y-%m-%d %H:%M:%S - $msg\n", localtime()));
|
|
||||||
}
|
|
||||||
|
|
||||||
sub sigwarn {
|
|
||||||
|
|
||||||
logstage(shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub sigdie {
|
|
||||||
|
|
||||||
logstage(shift);
|
|
||||||
logstage("tinderbox aborted");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub timeout() {
|
|
||||||
kill(15, keys(%children))
|
|
||||||
if (%children);
|
|
||||||
error("timed out after $timeout seconds");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub usage() {
|
|
||||||
|
|
||||||
print(STDERR "This is the FreeBSD tinderbox script, version $VERSION.
|
|
||||||
$COPYRIGHT
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$0 [options] [parameters] command [...]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-v, --verbose Verbose mode
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
-a, --arch=ARCH Target architecture (e.g. i386)
|
|
||||||
-b, --branch=BRANCH CVS branch to check out
|
|
||||||
-d, --date=DATE Date of sources to check out
|
|
||||||
-j, --jobs=NUM Maximum number of paralell jobs
|
|
||||||
-h, --hostname=NAME Name of the host running the tinderbox
|
|
||||||
-l, --logfile=FILE Path to log file
|
|
||||||
-m, --machine=MACHINE Target machine (e.g. pc98)
|
|
||||||
-p, --patch=PATCH Patch to apply before building
|
|
||||||
-r, --repository=DIR Location of CVS repository
|
|
||||||
-s, --sandbox=DIR Location of sandbox
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
clean Clean the sandbox
|
|
||||||
update Update the source tree
|
|
||||||
patch Patch the source tree
|
|
||||||
world Build the world
|
|
||||||
generic Build the GENERIC kernel
|
|
||||||
lint Build the LINT kernel
|
|
||||||
release Build a full release (run as root!)
|
|
||||||
|
|
||||||
Report bugs to <des\@freebsd.org>.
|
|
||||||
");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
MAIN:{
|
|
||||||
# Clear environment and set timezone
|
|
||||||
%ENV = (
|
|
||||||
'TZ' => "UTC",
|
|
||||||
'PATH' => "/usr/bin:/usr/sbin:/bin:/sbin",
|
|
||||||
);
|
|
||||||
tzset();
|
|
||||||
|
|
||||||
# Set defaults
|
|
||||||
$hostname = `/usr/bin/uname -n`;
|
|
||||||
chomp($hostname);
|
|
||||||
$branch = "HEAD";
|
|
||||||
$jobs = 0;
|
|
||||||
$repository = "/home/ncvs";
|
|
||||||
$sandbox = "/tmp/tinderbox";
|
|
||||||
$timeout = 0;
|
|
||||||
|
|
||||||
# Get options
|
|
||||||
{Getopt::Long::Configure("auto_abbrev", "bundling");}
|
|
||||||
GetOptions(
|
|
||||||
"a|arch=s" => \$arch,
|
|
||||||
"b|branch=s" => \$branch,
|
|
||||||
"c|cvsup=s" => \$cvsup,
|
|
||||||
"d|date=s" => \$date,
|
|
||||||
"j|jobs=i" => \$jobs,
|
|
||||||
"l|logfile=s" => \$logfile,
|
|
||||||
"h|hostname=s" => \$hostname,
|
|
||||||
"m|machine=s" => \$machine,
|
|
||||||
"p|patch=s" => \$patch,
|
|
||||||
"r|repository=s" => \$repository,
|
|
||||||
"s|sandbox=s" => \$sandbox,
|
|
||||||
"t|timeout=i" => \$timeout,
|
|
||||||
"v|verbose+" => \$verbose,
|
|
||||||
) or usage();
|
|
||||||
|
|
||||||
if ($jobs < 0) {
|
|
||||||
error("invalid number of jobs");
|
|
||||||
}
|
|
||||||
if ($timeout < 0) {
|
|
||||||
error("invalid timeout");
|
|
||||||
}
|
|
||||||
if ($branch !~ m|^(\w+)$|) {
|
|
||||||
error("invalid source branch");
|
|
||||||
}
|
|
||||||
$branch = ($1 eq 'CURRENT') ? 'HEAD' : $1;
|
|
||||||
if (!defined($arch)) {
|
|
||||||
$arch = `/usr/bin/uname -p`;
|
|
||||||
chomp($arch);
|
|
||||||
if (!defined($machine)) {
|
|
||||||
$machine = `/usr/bin/uname -m`;
|
|
||||||
chomp($machine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($arch !~ m|^(\w+)$|) {
|
|
||||||
error("invalid target architecture");
|
|
||||||
}
|
|
||||||
$arch = $1;
|
|
||||||
if (!defined($machine)) {
|
|
||||||
$machine = $arch;
|
|
||||||
}
|
|
||||||
if ($machine !~ m|^(\w+)$|) {
|
|
||||||
error("invalid target machine");
|
|
||||||
}
|
|
||||||
$machine = $1;
|
|
||||||
if (defined($date)) {
|
|
||||||
if ($date eq 'today') {
|
|
||||||
$date = strftime("%Y-%m-%d", localtime());
|
|
||||||
} elsif ($date !~ m/^(\d{4}-\d{2}-\d{2})$/) {
|
|
||||||
error("invalid checkout date");
|
|
||||||
} else {
|
|
||||||
$date = $1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!@ARGV) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set up a timeout
|
|
||||||
if ($timeout > 0) {
|
|
||||||
$SIG{ALRM} = \&timeout;
|
|
||||||
alarm($timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find out what we're expected to do
|
|
||||||
foreach my $cmd (@ARGV) {
|
|
||||||
if ($cmd =~ m/^([0-9A-Z_]+)=(.*)\s*$/) {
|
|
||||||
$userenv{$1} = $2;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($cmd =~ m/^kernel:(\w+)$/) {
|
|
||||||
$kernels{$1} = 1;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
# backward compatibility
|
|
||||||
# note that LINT is special, GENERIC is not
|
|
||||||
if ($cmd eq 'generic') {
|
|
||||||
$kernels{'GENERIC'} = 1;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if (!exists($cmds{$cmd})) {
|
|
||||||
error("unrecognized command: '$cmd'");
|
|
||||||
}
|
|
||||||
$cmds{$cmd} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Open logfile
|
|
||||||
open(STDIN, '<', "/dev/null")
|
|
||||||
or error("/dev/null: $!\n");
|
|
||||||
if (defined($logfile)) {
|
|
||||||
if ($logfile !~ m|([\w./-]+)$|) {
|
|
||||||
error("invalid log file name");
|
|
||||||
}
|
|
||||||
$logfile = $1;
|
|
||||||
unlink($logfile);
|
|
||||||
open(STDOUT, '>', $logfile)
|
|
||||||
or error("$logfile: $!");
|
|
||||||
}
|
|
||||||
open(STDERR, ">&STDOUT");
|
|
||||||
$| = 1;
|
|
||||||
logstage("tinderbox $VERSION running on $hostname");
|
|
||||||
logstage("starting $branch tinderbox run for $arch/$machine");
|
|
||||||
$SIG{__DIE__} = \&sigdie;
|
|
||||||
$SIG{__WARN__} = \&sigwarn;
|
|
||||||
|
|
||||||
# Take control of our sandbox
|
|
||||||
if ($sandbox !~ m|^(/[\w./-]+)$|) {
|
|
||||||
error("invalid sandbox directory");
|
|
||||||
}
|
|
||||||
$sandbox = "$1/$branch/$arch/$machine";
|
|
||||||
$ENV{'HOME'} = $sandbox;
|
|
||||||
make_dir($sandbox)
|
|
||||||
or error("$sandbox: $!");
|
|
||||||
my $lockfile = open_locked("$sandbox/lock", O_RDWR|O_CREAT);
|
|
||||||
if (!defined($lockfile)) {
|
|
||||||
error("unable to lock sandbox");
|
|
||||||
}
|
|
||||||
truncate($lockfile, 0);
|
|
||||||
print($lockfile "$$\n");
|
|
||||||
|
|
||||||
# Clean up remains from old runs
|
|
||||||
if ($cmds{'clean'} || $cmds{'cleansrc'}) {
|
|
||||||
logstage("cleaning the source tree");
|
|
||||||
if (-e "$sandbox/src") {
|
|
||||||
remove_dir("$sandbox/src")
|
|
||||||
or error("unable to remove old source directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($cmds{'clean'} || $cmds{'cleanobj'}) {
|
|
||||||
logstage("cleaning the object tree");
|
|
||||||
if (-e "$sandbox/obj") {
|
|
||||||
remove_dir("$sandbox/obj")
|
|
||||||
or error("unable to remove old object directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($cmds{'clean'} || $cmds{'cleanroot'}) {
|
|
||||||
logstage("cleaning the chroot tree");
|
|
||||||
if (-e "$sandbox/root") {
|
|
||||||
spawn('/bin/chflags', '-R', '0', "$sandbox/root");
|
|
||||||
remove_dir("$sandbox/root")
|
|
||||||
or error("unable to remove old chroot directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check out new source tree
|
|
||||||
if ($cmds{'update'}) {
|
|
||||||
if (defined($cvsup)) {
|
|
||||||
logstage("cvsupping the source tree");
|
|
||||||
local *SUPFILE;
|
|
||||||
open(SUPFILE, ">", "$sandbox/supfile")
|
|
||||||
or error("$sandbox/supfile: $!");
|
|
||||||
print(SUPFILE "*default host=$cvsup\n");
|
|
||||||
print(SUPFILE "*default base=$sandbox\n");
|
|
||||||
print(SUPFILE "*default prefix=$sandbox\n");
|
|
||||||
print(SUPFILE "*default delete use-rel-suffix\n");
|
|
||||||
print(SUPFILE "src-all release=cvs");
|
|
||||||
if ($branch eq 'HEAD') {
|
|
||||||
print(SUPFILE " tag=.");
|
|
||||||
} else {
|
|
||||||
print(SUPFILE " tag=$branch");
|
|
||||||
}
|
|
||||||
print(SUPFILE " date=$date")
|
|
||||||
if defined($date);
|
|
||||||
print(SUPFILE "\n");
|
|
||||||
close(SUPFILE);
|
|
||||||
my @cvsupargs = (
|
|
||||||
"-1",
|
|
||||||
"-g",
|
|
||||||
"-L", ($verbose ? 2 : 1),
|
|
||||||
"$sandbox/supfile"
|
|
||||||
);
|
|
||||||
spawn('/usr/local/bin/cvsup', @cvsupargs)
|
|
||||||
or error("unable to cvsup the source tree");
|
|
||||||
} else {
|
|
||||||
logstage("checking out the source tree");
|
|
||||||
cd("$sandbox");
|
|
||||||
my @cvsargs = (
|
|
||||||
"-f",
|
|
||||||
"-R",
|
|
||||||
$verbose ? "-q" : "-Q",
|
|
||||||
"-d$repository",
|
|
||||||
);
|
|
||||||
if (-d "$sandbox/src") {
|
|
||||||
push(@cvsargs, "update", "-Pd");
|
|
||||||
} else {
|
|
||||||
push(@cvsargs, "checkout", "-P");
|
|
||||||
};
|
|
||||||
push(@cvsargs, ($branch eq 'HEAD') ? "-A" : "-r$branch")
|
|
||||||
if defined($branch);
|
|
||||||
push(@cvsargs, "-D$date")
|
|
||||||
if defined($date);
|
|
||||||
push(@cvsargs, "src");
|
|
||||||
spawn('/usr/bin/cvs', @cvsargs)
|
|
||||||
or error("unable to check out the source tree");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Patch sources
|
|
||||||
if ($cmds{'patch'} && !defined($patch)) {
|
|
||||||
warning("no patch specified");
|
|
||||||
$cmds{'patch'} = 0;
|
|
||||||
}
|
|
||||||
if ($cmds{'patch'}) {
|
|
||||||
$patch = "$sandbox/$patch"
|
|
||||||
unless ($patch =~ m|^/|);
|
|
||||||
if ($patch !~ m|^(/[\w./-]+)$|) {
|
|
||||||
error("invalid patchfile path");
|
|
||||||
}
|
|
||||||
$patch = $1;
|
|
||||||
if (-f $patch) {
|
|
||||||
logstage("patching the sources");
|
|
||||||
cd("$sandbox/src");
|
|
||||||
spawn('/usr/bin/patch', "-f", "-s", "-i$patch")
|
|
||||||
or error("failed to apply patch to source tree");
|
|
||||||
} else {
|
|
||||||
warning("$patch does not exist");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Prepare environment for make(1);
|
|
||||||
%ENV = (
|
|
||||||
'TZ' => "UTC",
|
|
||||||
'PATH' => "/usr/bin:/usr/sbin:/bin:/sbin",
|
|
||||||
|
|
||||||
'__MAKE_CONF' => "/dev/null",
|
|
||||||
'MAKEOBJDIRPREFIX' => "$sandbox/obj",
|
|
||||||
|
|
||||||
'TARGET' => $machine,
|
|
||||||
'TARGET_ARCH' => $arch,
|
|
||||||
);
|
|
||||||
|
|
||||||
# Kernel-specific variables
|
|
||||||
if (%kernels || $cmds{'lint'} || $cmds{'release'}) {
|
|
||||||
# None at the moment
|
|
||||||
}
|
|
||||||
|
|
||||||
# Release-specific variables
|
|
||||||
if ($cmds{'release'}) {
|
|
||||||
$ENV{'CHROOTDIR'} = "$sandbox/root";
|
|
||||||
$ENV{'CVSROOT'} = $repository;
|
|
||||||
$ENV{'RELEASETAG'} = $branch
|
|
||||||
if $branch ne 'HEAD';
|
|
||||||
$ENV{'CVSCMDARGS'} = "-D$date"
|
|
||||||
if defined($date);
|
|
||||||
$ENV{'WORLD_FLAGS'} = $ENV{'KERNEL_FLAGS'} =
|
|
||||||
($jobs > 1) ? "-j$jobs" : "-B";
|
|
||||||
if ($patch) {
|
|
||||||
$ENV{'LOCAL_PATCHES'} = $patch;
|
|
||||||
$ENV{'PATCH_FLAGS'} = "-fs";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Save time and space
|
|
||||||
$ENV{'NOCDROM'} = "YES";
|
|
||||||
$ENV{'NODOC'} = "YES";
|
|
||||||
$ENV{'NOPORTS'} = "YES";
|
|
||||||
}
|
|
||||||
|
|
||||||
# User-supplied variables
|
|
||||||
foreach my $key (keys(%userenv)) {
|
|
||||||
if (exists($ENV{$key})) {
|
|
||||||
warning("will not allow override of $key");
|
|
||||||
} else {
|
|
||||||
$ENV{$key} = $userenv{$key};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Defaults for overridable variables
|
|
||||||
if (!exists($ENV{'CFLAGS'})) {
|
|
||||||
$ENV{'CFLAGS'} = "-O -pipe";
|
|
||||||
}
|
|
||||||
if (%kernels || $cmds{'lint'} || $cmds{'release'}) {
|
|
||||||
if (!exists($ENV{'COPTFLAGS'})) {
|
|
||||||
$ENV{'COPTFLAGS'} = "-O -pipe";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# List the environment when verbose
|
|
||||||
if ($verbose && $verbose > 1) {
|
|
||||||
foreach my $key (sort(keys(%ENV))) {
|
|
||||||
message("$key=$ENV{$key}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build the world, or at least the kernel toolchain
|
|
||||||
if ($cmds{'world'}) {
|
|
||||||
logstage("building world (CFLAGS=$ENV{'CFLAGS'})");
|
|
||||||
cd("$sandbox/src");
|
|
||||||
make('buildworld')
|
|
||||||
or error("failed to build world");
|
|
||||||
} elsif (%kernels || $cmds{'lint'}) {
|
|
||||||
logstage("building kernel toolchain (CFLAGS=$ENV{'CFLAGS'})");
|
|
||||||
cd("$sandbox/src");
|
|
||||||
make('kernel-toolchain')
|
|
||||||
or error("failed to build kernel toolchain");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build LINT if requested
|
|
||||||
if ($cmds{'lint'}) {
|
|
||||||
if (-f "$sandbox/src/sys/$machine/conf/NOTES") {
|
|
||||||
logstage("generating LINT kernel config");
|
|
||||||
cd("$sandbox/src/sys/$machine/conf");
|
|
||||||
make('LINT')
|
|
||||||
or error("failed to generate LINT kernel config");
|
|
||||||
}
|
|
||||||
if (! -f "$sandbox/src/sys/$machine/conf/LINT") {
|
|
||||||
warning("no kernel config for LINT");
|
|
||||||
$cmds{'lint'} = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($cmds{'lint'}) {
|
|
||||||
logstage("building LINT kernel (COPTFLAGS=$ENV{'COPTFLAGS'})");
|
|
||||||
cd("$sandbox/src");
|
|
||||||
spawn('/usr/bin/make', 'buildkernel', 'KERNCONF=LINT')
|
|
||||||
or error("failed to build lint kernel");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build additional kernels
|
|
||||||
foreach my $kernel (sort(keys(%kernels))) {
|
|
||||||
if (! -f "$sandbox/src/sys/$machine/conf/$kernel") {
|
|
||||||
warning("no kernel config for $kernel");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
logstage("building $kernel kernel (COPTFLAGS=$ENV{'COPTFLAGS'})");
|
|
||||||
cd("$sandbox/src");
|
|
||||||
spawn('/usr/bin/make', 'buildkernel', "KERNCONF=$kernel")
|
|
||||||
or error("failed to build $kernel kernel");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build a release if requested
|
|
||||||
if ($cmds{'release'}) {
|
|
||||||
logstage("building a release");
|
|
||||||
cd("$sandbox/src/release");
|
|
||||||
make('release')
|
|
||||||
or error("failed to build release");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Exiting releases the lock file
|
|
||||||
logstage("tinderbox run completed");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
daemon.png
|
|
||||||
valid-css.png
|
|
||||||
valid-xhtml10.png
|
|
@ -1,25 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
CGI = index.cgi
|
|
||||||
DATA = tb.css
|
|
||||||
IMAGES = daemon.png valid-css.png valid-xhtml10.png
|
|
||||||
CLEANFILES += ${IMAGES}
|
|
||||||
WWWDIR ?= ${HOME}/public_html
|
|
||||||
WWWOWN ?= ${USER}
|
|
||||||
WWWGRP ?= ${USER}
|
|
||||||
|
|
||||||
all: ${IMAGES}
|
|
||||||
|
|
||||||
realinstall:
|
|
||||||
${INSTALL} -m0755 -o${WWWOWN} -g${WWWGRP} ${.CURDIR}/${CGI} ${WWWDIR}
|
|
||||||
.for _data in ${DATA}
|
|
||||||
${INSTALL} -m0644 -o${WWWOWN} -g${WWWGRP} ${.CURDIR}/${_data} ${WWWDIR}
|
|
||||||
.endfor
|
|
||||||
.for _image in ${IMAGES}
|
|
||||||
${INSTALL} -m0644 -o${WWWOWN} -g${WWWGRP} ${_image} ${WWWDIR}
|
|
||||||
.endfor
|
|
||||||
|
|
||||||
${IMAGES}: ${.TARGET}.uu
|
|
||||||
uudecode ${.ALLSRC}
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
@ -1,144 +0,0 @@
|
|||||||
begin 644 daemon.png
|
|
||||||
MB5!.1PT*&@H````-24A$4@```%````!,"`8```#Z!3!-````!F)+1T0`_P#_
|
|
||||||
M`/^@O:>3````"7!(67,```L2```+$@'2W7[\````!W1)344'TP8#"@(%BD"-
|
|
||||||
MM```&#Q)1$%4>)SMG'E\'-65[[]5W:WNJNINJ;NU6K(LRPM&PF#`+`X$;-X`
|
|
||||||
M!L*$$&P@@01",B2&,$`RGB3O@0,9>"],6$+&3#(A3!@@R8!9!H8EP,2.V10+
|
|
||||||
M@HTMC['19EE;2]TM]5)5K:ZN^_ZH5MO"SL002=9\,K_/1Q]]JKKJUKV_.N>>
|
|
||||||
M<\\YM^!_\.>-^^Z]3ZR^8)5XY+$GQ)'NRW];?/V&;XH5S<O$Z@M6B=:6UC\/
|
|
||||||
M(M]]Y65QS^W_=](&>\655XD5S<O$Q4VGB'5K;YDV$N7I>M"!N/WV.\03W_M[
|
|
||||||
M1H<')ZW-1Q_YN12N#).09`:>?XDUJ[XD^O?VK)FT!_P!3#N!Z];>(LQ7-Q$U
|
|
||||||
MQOC6S7_[P&2V_86;KF4$BR$A4[:KC=O7?&/]5),XK02N_]FC8O/SKT(BR=QC
|
|
||||||
MFE`::JZ;S/9/7G+\=:6*GX0D$[-M%N[MX4<W_.WZR7S&A^&>RL8/1$=WU\9+
|
|
||||||
M+KZ2!F%3(<F$/G$B_//AW[OYY5>7=^[I9C`6)9@'I;*24$V$,X]IXOBSSY$`
|
|
||||||
MMN]H6S\X`J7Y$?9@$_&7L6CW+NZX^FOB?__S/TI3,:XI:?106+WJ,C&TLYMR
|
|
||||||
M/<D"(?C,KQ[FI%-/^B^??]^]]XG7GGV%6$IGU$CCU=.(C$FE7,FLB%V\[GW%
|
|
||||||
MSYF?.(X=V_?0$8WBU=.HV)SJ+V-1/L=`F9\5]]S]1Y_W<3`M*KQI\^MB^[N#
|
|
||||||
M&/H(I;)$U"63&<O^P>M__M,'Q8KF9>)7]_^$WJX.C+X>2H:&40T#2?.144;H
|
|
||||||
MU77RI@%`12S*KY_[-;U='83T)``Z,E&?#SMK43DXPI9'GYB2L4V+"C^YX1EJ
|
|
||||||
M\GWTNV8QF-99[$OQ^TVO'?+:KUYSK?CQG7<CLCD2EDD(#YHL0(:,[$8"(K@I
|
|
||||||
ME?<+TP(A*'6Y:-8"`.S*6VS3T[AT'0!/)D/O>^].R=BF10*WO_D..C)!O0<`
|
|
||||||
M%8GAAQ[AZV>>)Y[ZY8:BN[%N[2UBZV\V.S=9>4)XBFUD9#<I#\Q&Y@+9Q>G(
|
|
||||||
MG.$MX6@]Q\*:<EP^A39O"4-E?A:YW)PE)/*JBNQU9"1JC$W)V*9E#ES1O$SH
|
|
||||||
MB2&P\N!V46E'6>`I!PR_145Y%75>(9DQ%CA$PVCV9;^(4;(4601(Q!D4?2
|
|
||||||
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
|
|
||||||
3V`AEKF[CM`````!)14Y$KD)@@@``
|
|
||||||
`
|
|
||||||
end
|
|
@ -1,201 +0,0 @@
|
|||||||
#!/usr/bin/perl -Tw
|
|
||||||
#-
|
|
||||||
# Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer
|
|
||||||
# in this position and unchanged.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
|
|
||||||
use 5.006_001;
|
|
||||||
use strict;
|
|
||||||
use POSIX qw(strftime);
|
|
||||||
|
|
||||||
my %CONFIGS;
|
|
||||||
my %ARCHES;
|
|
||||||
|
|
||||||
my $DIR = ".";
|
|
||||||
|
|
||||||
sub success($) {
|
|
||||||
my $log = shift;
|
|
||||||
|
|
||||||
local *FILE;
|
|
||||||
if (open(FILE, "<", $log)) {
|
|
||||||
while (<FILE>) {
|
|
||||||
if (m/tinderbox run completed/) {
|
|
||||||
close(FILE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(FILE);
|
|
||||||
}
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub branch_sort($$) {
|
|
||||||
my ($a, $b) = @_;
|
|
||||||
|
|
||||||
my @a = split('_', $a);
|
|
||||||
my @b = split('_', $b);
|
|
||||||
while (@a || @b) {
|
|
||||||
($a, $b) = (shift(@a), shift(@b));
|
|
||||||
return 1 unless defined($a);
|
|
||||||
return -1 unless defined($b);
|
|
||||||
next if $a eq $b;
|
|
||||||
if ($a =~ m/^\d+$/ && $b =~ m/^\d+$/) {
|
|
||||||
return $a <=> $b;
|
|
||||||
} else {
|
|
||||||
return $a cmp $b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub inverse_branch_sort($$) {
|
|
||||||
my ($a, $b) = @_;
|
|
||||||
|
|
||||||
return branch_sort($b, $a);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_config($) {
|
|
||||||
my $config = shift;
|
|
||||||
|
|
||||||
my %branches = %{$CONFIGS{$config}};
|
|
||||||
|
|
||||||
print " <tr>
|
|
||||||
<th>$config</th>
|
|
||||||
";
|
|
||||||
foreach my $arch (sort(keys(%ARCHES))) {
|
|
||||||
foreach my $machine (sort(keys(%{$ARCHES{$arch}}))) {
|
|
||||||
if ($arch eq $machine) {
|
|
||||||
print " <th>$arch</th>\n";
|
|
||||||
} else {
|
|
||||||
print " <th>$arch<br />$machine</th>\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print " </tr>\n";
|
|
||||||
|
|
||||||
my $now = time();
|
|
||||||
|
|
||||||
foreach my $branch (sort(inverse_branch_sort keys(%branches))) {
|
|
||||||
my $html = " <tr>
|
|
||||||
<th>$branch</th>
|
|
||||||
";
|
|
||||||
foreach my $arch (sort(keys(%ARCHES))) {
|
|
||||||
foreach my $machine (sort(keys(%{$ARCHES{$arch}}))) {
|
|
||||||
my $log = "tinderbox-$config-$branch-$arch-$machine";
|
|
||||||
my $links = "";
|
|
||||||
if (-f "$DIR/$log.brief") {
|
|
||||||
my @stat = stat("$DIR/$log.brief");
|
|
||||||
my $class = success("$DIR/$log.brief") ? "ok" : "fail";
|
|
||||||
my $age = int(($now - $stat[9]) / 1800);
|
|
||||||
$age = 9
|
|
||||||
if ($age > 9);
|
|
||||||
$class .= "-$age";
|
|
||||||
$links .= "<span class='$class'>" .
|
|
||||||
strftime("%Y-%m-%d %H:%M UTC", gmtime($stat[9])) .
|
|
||||||
"</span><br />";
|
|
||||||
my $size = sprintf("[%.1f kB]", $stat[7] / 1024);
|
|
||||||
$links .= " <span class='tiny'>" .
|
|
||||||
"<a target='_top' href='$log.brief'>summary $size</a>" .
|
|
||||||
"</span><br />";
|
|
||||||
}
|
|
||||||
if (-f "$DIR/$log.full") {
|
|
||||||
my @stat = stat("$DIR/$log.full");
|
|
||||||
my $size = sprintf("[%.1f MB]", $stat[7] / 1048576);
|
|
||||||
$links .= " <span class='tiny'>" .
|
|
||||||
"<a target='_top' href='$log.full'>full log $size</a>" .
|
|
||||||
"</span><br />";
|
|
||||||
}
|
|
||||||
if ($links eq "") {
|
|
||||||
$html .= " <td>n/a</td>\n";
|
|
||||||
} else {
|
|
||||||
$html .= " <td>$links</td>\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$html .= " </tr>\n";
|
|
||||||
print $html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MAIN:{
|
|
||||||
if ($ENV{'GATEWAY_INTERFACE'}) {
|
|
||||||
$| = 1;
|
|
||||||
print "Content-Type: text/html\n\n";
|
|
||||||
} else {
|
|
||||||
if ($0 =~ m|^(/[\w/._-]+)/[^/]+$|) {
|
|
||||||
$DIR = $1;
|
|
||||||
}
|
|
||||||
open(STDOUT, ">", "$DIR/index.html")
|
|
||||||
or die("index.html: $!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
local *DIR;
|
|
||||||
opendir(DIR, $DIR)
|
|
||||||
or die("$DIR: $!\n");
|
|
||||||
foreach (readdir(DIR)) {
|
|
||||||
next unless m/^tinderbox-(\w+)-(\w+)-(\w+)-(\w+)\.(brief|full)$/;
|
|
||||||
$CONFIGS{$1}->{$2} = $ARCHES{$3}->{$4} = 1;
|
|
||||||
}
|
|
||||||
closedir(DIR);
|
|
||||||
|
|
||||||
print "<?xml version='1.0' encoding='iso-8859-1'?>
|
|
||||||
<!DOCTYPE html
|
|
||||||
PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
|
|
||||||
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
|
||||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
|
||||||
<head>
|
|
||||||
<title>FreeBSD tinderbox logs</title>
|
|
||||||
<meta name='robots' content='nofollow' />
|
|
||||||
<meta http-equiv='refresh' content='600' />
|
|
||||||
<link rel='stylesheet' type='text/css' media='screen' href='tb.css' />
|
|
||||||
<link rel='shortcut icon' type='image/png' href='daemon.png' />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- h1>FreeBSD tinderbox logs</h1 -->
|
|
||||||
|
|
||||||
<table border='1' cellpadding='3'>
|
|
||||||
";
|
|
||||||
foreach my $config (sort(keys(%CONFIGS))) {
|
|
||||||
next if $config =~ m/^update_/;
|
|
||||||
do_config($config);
|
|
||||||
}
|
|
||||||
my $date = strftime("%Y-%m-%d %H:%M UTC", gmtime());
|
|
||||||
print "
|
|
||||||
</table>
|
|
||||||
<!-- p class='update'>Last updated: $date</p -->
|
|
||||||
<!-- p>
|
|
||||||
<a target='_top' href='http://validator.w3.org/check/referer'><img
|
|
||||||
src='valid-xhtml10.png'
|
|
||||||
alt='Valid XHTML 1.0!' height='31' width='88' /></a>
|
|
||||||
<a target='_top' href='http://jigsaw.w3.org/css-validator/check/referer'><img
|
|
||||||
src='valid-css.png'
|
|
||||||
alt='Valid CSS!' height='31' width='88' /></a>
|
|
||||||
</p -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* $FreeBSD$
|
|
||||||
*/
|
|
||||||
|
|
||||||
BODY, H1, H2, H3, H4, H5, H6, LI {
|
|
||||||
font-family: Helvetica, sans-serif;
|
|
||||||
font-style: normal;
|
|
||||||
background-color: white;
|
|
||||||
color: navy;
|
|
||||||
}
|
|
||||||
|
|
||||||
A:link {
|
|
||||||
background-color: white;
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
A:visited {
|
|
||||||
background-color: white;
|
|
||||||
color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
A:active {
|
|
||||||
background-color: white;
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tiny {
|
|
||||||
font-size: x-small;
|
|
||||||
}
|
|
||||||
|
|
||||||
.update {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ok-0 { background-color: white; color: #007700; }
|
|
||||||
.ok-1 { background-color: white; color: #117B11; }
|
|
||||||
.ok-2 { background-color: white; color: #227F22; }
|
|
||||||
.ok-3 { background-color: white; color: #338333; }
|
|
||||||
.ok-4 { background-color: white; color: #448744; }
|
|
||||||
.ok-5 { background-color: white; color: #558B55; }
|
|
||||||
.ok-6 { background-color: white; color: #668F66; }
|
|
||||||
.ok-7 { background-color: white; color: #779377; }
|
|
||||||
.ok-8 { background-color: white; color: #889788; }
|
|
||||||
.ok-9 { background-color: white; color: #999B99; }
|
|
||||||
|
|
||||||
.fail-0 { background-color: white; color: #ff0000; }
|
|
||||||
.fail-1 { background-color: white; color: #ff1111; }
|
|
||||||
.fail-2 { background-color: white; color: #ff2222; }
|
|
||||||
.fail-3 { background-color: white; color: #ff3333; }
|
|
||||||
.fail-4 { background-color: white; color: #ff4444; }
|
|
||||||
.fail-5 { background-color: white; color: #ff5555; }
|
|
||||||
.fail-6 { background-color: white; color: #ff6666; }
|
|
||||||
.fail-7 { background-color: white; color: #ff7777; }
|
|
||||||
.fail-8 { background-color: white; color: #ff8888; }
|
|
||||||
.fail-9 { background-color: white; color: #ff9999; }
|
|
||||||
|
|
||||||
TD, TH {
|
|
||||||
width: 16ex;
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMG {
|
|
||||||
border: none;
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
begin 644 valid-css.png
|
|
||||||
MB5!.1PT*&@H````-24A$4@```%@````?"`,```!4%OK2````]E!,5$5CI<9S
|
|
||||||
ME,<,1YTV9*Y4?+K?YO+N[NY,3$RNKJZ=G9V^OKZQP^"AM]F2J],L+"P```!]
|
|
||||||
M?7T<'!SN\O@A5:;!S^:-C8T,#`P73:)DB,$+1)V.I]+.SLY=75W0V^PF6:B#
|
|
||||||
MG\U%<+0\/#QL>I%M;6W,S,S_S&;___\`9ID8>ZU*E+WG[_=*2DJ]O<:9F9FU
|
|
||||||
MUN>$M=8S,S.$A(0C'`X/#`9:G+UF9F;OOU^);38\,!AM5RO?LEFOC$9,/![`
|
|
||||||
MF4S/I5);2"0L(Q$,"02<?#XQC+4Y.3D<%@O#G$[KO%Z9``!F,P#TPV&5``#,
|
|
||||||
MF3.YE$KAM%K>L5A[<V8H(!`(-YOM`````7123E,`0.;89@````%B2T=$`(@%
|
|
||||||
M'4@```)@241!5'B<[95M<Y-`$,>;32!)\[`-DA)MGJJ]?5/?^"9W!`*!T8JQ
|
|
||||||
M6OW^7\:]`QR(G4G&1%\X[@1F`W,_[O[WW[V+N_/'A8D[.B+$\?'QX?X_^%\`
|
|
||||||
M-Z#)@UO0T@P+BB"RV^T.=2]_']P#L(CZFD4T*+A-LH>(>#6Z.D$*@#Z1`]`S
|
|
||||||
M$W_AN@T`E\9XW1XA=D\`YRIX,-$?>?F*'$\_&%[?$$U'IVQ>'SRB&<#<R.+0
|
|
||||||
MPFB#8WYE7Q;@E51*^6O.@E"I<,-)%',2/`/.2K"E56`:S&C"XO+?!3]%N^**
|
|
||||||
MU1:1?\E:;/BN$#=BG9@DW0=_RK*LM%L3&GQY,*`Y7RV>N\M25.TF,8G$2F&L
|
|
||||||
MLT!(E7*"4@1J'RRSS)`->`%SWCNVW4S/>JE=X=)M%1RB7XP,V"N8Q"L1Z03#
|
|
||||||
MJ`[.N4PV8.8MH*DET#H3N1XL:5P%QP:\D:F(I*\^,%"L9:RT0#5N6G*+RO-8
|
|
||||||
MAP6K`<89Q%*#<U,%IY@P<\MXI3\1HF(I0B%\3)[G%N")V3FVK_&RJ1:W7M*Q
|
|
||||||
M6?AVE4N!&(@H,8E>B4Q_X19@=EGN.*`2_#K/[+*D`U_%9GS$QI/:;FL9*C_(
|
|
||||||
M>>ENCUN`G5P#71B-N656T.V:-],W!PLDY^U*[N=:=VL9#29<VTMHNNSI)8W&
|
|
||||||
MN@_AP5[Q6,RSG&^];0ZXX+0"%EF>:4(SZN#H%G%XN*1+8AY?ZF#+]$Q']\^>
|
|
||||||
M+A`]_PZWH*E]1*^HDK_N-WJK<G=F5(\#X)]JL-)G/D%*\N[L1]-CP3W_F?>4
|
|
||||||
M<__`8?HD-?>OG-)O#\?#\?'N6PF^/W.\_VZX/P">K(-C3;4/#@````!)14Y$
|
|
||||||
$KD)@@@``
|
|
||||||
`
|
|
||||||
end
|
|
@ -1,57 +0,0 @@
|
|||||||
begin 644 valid-xhtml10.png
|
|
||||||
MB5!.1PT*&@H````-24A$4@```%@````?"`,```$C$<I$```"B%!,5$4```#>
|
|
||||||
MY^?.>SFMK:W>C$*EA$+OO6.]6EK>A$+.>WO>I:6<E'O>M5+&<W/>K5*<"`CW
|
|
||||||
MO5J4C'.4>U)CE+TQ.4ICC+V4``"]UN>,K<[OK5*EO=;6WN^$I<;.WN?.UN<8
|
|
||||||
M6I2,*0B]2B%[>WM:6DH0$`B,<SD02HQ:4DIS<W.UE$H("`"$:S$A&`@(``"$
|
|
||||||
M8S%K:VNMC$+6<SG&G$K_[^]C8V/.:S'.8S&M:V-2A+5KE+TY.4J<M=:<"`#&
|
|
||||||
M:VN<``#&I5J4M<ZU.1@Y.3FE4BD8&`B4>SE[8S$8$`B4<SDQ,3&]G$JM(1#>
|
|
||||||
MWMX`,7N]E$H0"`",:S$`*7LI*2FEC%K6UM:UC$+.SL[G[_?&QL:]I5J$.2DI
|
|
||||||
M8YQSG+V]M9Q:A+7.I5K_]]9K8U+_[]9C4BEC2BD`.83OQF,`,82<>SF<A%J4
|
|
||||||
M<S&ME%I[<VNMC%J4E)2MQM[W___W]_]">ZU"2DJ]QL9SG,;6Y^]"<ZV,C(Q"
|
|
||||||
M0DKO]_?O[_?.SL;GE$K6C(S_WFM".1AS:U(I(1!S6C'_UFM",1AS8U+_SFOG
|
|
||||||
MO5I20B'.I5)K4BGGM5KWSF.$<U+WQF-:6EJUG%HY0DK&6BFUE%H(2I124E*U
|
|
||||||
MSMXA6IP`2HS_______\Q:Z64:RD`0HQ*>ZU*2DI[G,;6M6/>Y^]C6E+W]_?W
|
|
||||||
M]_?6K6-"0D+>K:WGO6/O[^\Y,1CGM6/>M5I[<U(Q*1"4E'M*.1A[:U(Q(1"4
|
|
||||||
MC'M:2B'6K5(I(0AS6BGOO5I:0B'_UF/6I5*,>U+_SF/_QF-K4B&$K<X8&!C_
|
|
||||||
M[W/&UN<06I3_YW.]G%H04I2U2B$0$!"]SMZ]O;TY<Z4(2HQ24DHY:Z4("`A2
|
|
||||||
M2DHA4I2UM;7>M6,`0H24@#^D````V'123E/_________B/]L2?__=/______
|
|
||||||
M__________________________________________\,____________>?__
|
|
||||||
M____________________________________________________________
|
|
||||||
M______________________]=____________________________________
|
|
||||||
M`/______________"/__1/______________________________________
|
|
||||||
M______________________]Q/IU@```%O4E$051XVI56BU\411P?R[OL84;:
|
|
||||||
MBJ!1!%F("40&5*<9<D0>:1)04"+>R<,2?*&'TNHY-$+I(O&0&SHDO33`\Y5'
|
|
||||||
M*3I;1H>)G/GH_IU^,[MWMQCVT>_-SN[.?O>[O_D]9@X5<^P10,6T>R+QU92`
|
|
||||||
M->!#Q5FQ992P$48D&`>PFU>(!.,1OAOU4`^J\*7(5NQ&=">E%8PQ`GQ.KQ@;
|
|
||||||
M8\3BUMX5`T0'8SXQW%G5"\.5+7O]?D*&26#H6_XE&Z5;=M!;E>L.L^,CF$FS
|
|
||||||
M)*-()6%$?$03"6-/%*O<*$RFC+.U;\;P80=UA"BB#"EY*LK#"(EACX?2NO<I
|
|
||||||
M?2I@)FROZ=S>9O^G,/QW=A;M]X((T[_)9EB$MFU-V1(8/D38LAP8FVXY:_SD
|
|
||||||
M6C)P<R%AZ9(<8QQFJB:#28QA.A%4LJG@BW%S<CWEC=8#-$]NS`U8#_Y,AGS6
|
|
||||||
MU*1J%[F8&\C%87+<?+IC.>V+`T?N&J0K0'EUTL=*TL%<%2.2ES%T!@70']AW
|
|
||||||
M09#!(T<<-$A?MC7NBII!##V_>,1B$3FPP-$8'RJA=#RHVVP^W0'N-;=O>Y:[
|
|
||||||
M>.D'F#5)TBQ-F?;SUATJH_0Z&N2!VP0)0;I.C.0`E[PH621)TFV>PAO`.4B8
|
|
||||||
M8M9M:9+T"99FMF5.0MM+?K_=;O>+9H=K?K+[6[YP&_)CJD0QH-3M-L3*$+0I
|
|
||||||
M0+Z_#YEH:2FR33\34ALFB\B%`TA9BREM?[.B-*=:K1FYPV2HVE3-=/+N(S1^
|
|
||||||
M`B+C\531):CT+F7X5A)V[?_5)5_RR<BE6/.KD\-D7B[0JFCY;'J59E)*9(1D
|
|
||||||
MUP%S*KMT64;G7,/)U?DX3)YH6!`ZUIU5[Z#>(LT,7^LW&Q1E`UOMP\W*A@-I
|
|
||||||
MA<UGR$K+.YS<O;.LKJ^L<;9GIS<Z05%/>G+P&QF"^!.?8(^#-YY08==AX0_-
|
|
||||||
M$_R&88CX3.&-G@0:O`9GSS3HO$`^D<,)^VX[N8>Q-`^X%LOCFNOZZVCL6Q/9
|
|
||||||
MQVQ@\]T;8,8G3@R:[;CF"B$8TJ@)TO,%W<^-H%=/RSQSZ5W4QLW`.6"#<A1O
|
|
||||||
M.L0M!K;%LK3V?A'$<[!R&SN_=`X(.T`W'=?>/]R,J`P/Z-/$;Z<;PGT/654U
|
|
||||||
M[_%#!0A_"/(K;?<@TV[(9KL`3_!?W%-6RG]121X<OOPGW>X'%F8/#E_MA8<1
|
|
||||||
M5B\J/$H7546!EZ%3!%3MGJF**@YPGE%XP9UR>+O[3BP7*>DM$^B#!-B<6$R+
|
|
||||||
MIG%A?#DI)<WJVDA2/R0!;$T=,)G.H#S3P&L([<=R,D+Y@6J4C"%Z3QLM_MPQ
|
|
||||||
M"OU6SS'HRVU9#0UQGN#S=/#61XDGKUXOTM8GW(Q:,%%=B,.E$.)'PUC.0XL6
|
|
||||||
MMYK0HI1D79A,$B[IF>#"56!E?4*PA,9[KL%Z>E*LO;PB*Q@Q(=>P:W$KL:8H
|
|
||||||
MF"59%8);T&4NW)J&4-HIE!Q8B8;R\O+!%6>?^"KBX_(UL;0_U.M83K-M=72^
|
|
||||||
MK2>[D0YV>2.;+]]_B$K"64C"RY6X)+R@F"HN&?&]Q]?FQU[7A!N#":.>K;MY
|
|
||||||
MW\>KM:[3%DM+O='@A9<";</0.WWS()&]DQ%YAH57GS3S1STKYCL\H3CZNR/D
|
|
||||||
M&1?WXZ'.+<:L@%>QN>-46%/MN%*SCH2%88>=AP5EAL15866)IEMOU7/03U1E
|
|
||||||
MT;C9(!E;U7NC5#S8_*CXDZ*NW^9TCHUHPC5S#I%37>UCNO!26-%F-6&9R\+O
|
|
||||||
MS4EY/-X)"PR-#S;0T:`CX9KCST%:M&))8AOJXC[F&2IORM&%E9M'?V"XH_V\
|
|
||||||
M9N\S[PH[>8/?7RLG%TB]-G/AUMUS1[5!;]&J:.7AM3F'0=@,%7$^9ZT\<GI.
|
|
||||||
M#=9=C+^3N#8XX0W\D)7'A<<6+H.=]NOU`PPO.^X\NN^?:"2)/)U;FRZ3AROI
|
|
||||||
MBO!F86@CQ/#/`I[)3>F8_R&*%$B1M_C&_V/[]L\*"PH+"@H+"_DA4!`Y%T2?
|
|
||||||
=09^18?I-$_X7HLFJ[CL9`)L`````245.1*Y"8((`
|
|
||||||
`
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user