The tinderbox has moved to projcvs.

This commit is contained in:
des 2006-05-30 14:31:09 +00:00
parent b96008e410
commit a693fbc197
25 changed files with 0 additions and 2554 deletions

View File

@ -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.

View File

@ -1,2 +0,0 @@
tbmaster.1.gz
tinderbox.1.gz

View File

@ -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>

View File

@ -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>

View File

@ -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%%

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -1,4 +0,0 @@
# $FreeBSD$
branches = HEAD
platforms = amd64, i386/i386, i386/pc98, sparc64
targets = update

View File

@ -1,4 +0,0 @@
# $FreeBSD$
branches = RELENG_4_11, RELENG_4
platforms = alpha, i386/i386, i386/pc98
targets = update

View File

@ -1,4 +0,0 @@
# $FreeBSD$
branches = RELENG_5_4, RELENG_5_5, RELENG_5
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
targets = update

View File

@ -1,4 +0,0 @@
# $FreeBSD$
branches = RELENG_6_0, RELENG_6_1, RELENG_6
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
targets = update

View File

@ -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

View File

@ -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!

View File

@ -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);
}

View File

@ -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.

View File

@ -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);
}

View File

@ -1,3 +0,0 @@
daemon.png
valid-css.png
valid-xhtml10.png

View File

@ -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>

View File

@ -1,144 +0,0 @@
begin 644 daemon.png
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
3V`AEKF[CM`````!)14Y$KD)@@@``
`
end

View File

@ -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&nbsp;UTC", gmtime($stat[9])) .
"</span><br />";
my $size = sprintf("[%.1f&nbsp;kB]", $stat[7] / 1024);
$links .= " <span class='tiny'>" .
"<a target='_top' href='$log.brief'>summary&nbsp;$size</a>" .
"</span><br />";
}
if (-f "$DIR/$log.full") {
my @stat = stat("$DIR/$log.full");
my $size = sprintf("[%.1f&nbsp;MB]", $stat[7] / 1048576);
$links .= " <span class='tiny'>" .
"<a target='_top' href='$log.full'>full&nbsp;log&nbsp;$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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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/______________________________________
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
=09^18?I-$_X7HLFJ[CL9`)L`````245.1*Y"8((`
`
end