]> git.donarmstrong.com Git - debbugs.git/commitdiff
[project @ 1999-09-02 19:25:01 by gecko]
authorgecko <>
Fri, 3 Sep 1999 02:25:01 +0000 (18:25 -0800)
committergecko <>
Fri, 3 Sep 1999 02:25:01 +0000 (18:25 -0800)
Initial revision

32 files changed:
cgi/bugs-fetch2.pl.in [new file with mode: 0644]
cgi/cgi-lib.pl [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/debbugs-maketxt [new file with mode: 0755]
debian/dirs [new file with mode: 0644]
html/Access.html.in [new file with mode: 0644]
html/Developer.html.in [new file with mode: 0644]
html/Reporting.html.in [new file with mode: 0644]
html/index.html.in [new file with mode: 0644]
html/lynx-cfg [new file with mode: 0644]
html/server-control.html.in [new file with mode: 0644]
html/server-refcard.html.in [new file with mode: 0644]
html/server-request.html.in [new file with mode: 0644]
misc/Maintainers [new file with mode: 0644]
misc/crontab.in [new file with mode: 0644]
scripts/age-1.in [new file with mode: 0755]
scripts/config.debian [new file with mode: 0644]
scripts/config.in [new file with mode: 0644]
scripts/config.in.default [new file with mode: 0644]
scripts/db2html.in [new file with mode: 0755]
scripts/errorlib.in [new file with mode: 0755]
scripts/expire.in [new file with mode: 0755]
scripts/html-control.in [new file with mode: 0755]
scripts/html-install.in [new file with mode: 0755]
scripts/mailsummary.in [new file with mode: 0755]
scripts/process.in [new file with mode: 0755]
scripts/processall.in [new file with mode: 0755]
scripts/receive.in [new file with mode: 0755]
scripts/service.in [new file with mode: 0755]
scripts/summary.in [new file with mode: 0755]
scripts/text.in [new file with mode: 0644]

diff --git a/cgi/bugs-fetch2.pl.in b/cgi/bugs-fetch2.pl.in
new file mode 100644 (file)
index 0000000..24c7021
--- /dev/null
@@ -0,0 +1,80 @@
+#!/usr/bin/perl
+
+require '/etc/debbugs/config';
+require '/var/lib/debbugs/www/cgi/cgi-lib.pl';
+
+%map= ($gMirrors);
+
+ReadParse() or CgiDie("need form data");
+
+if ($in{'type'} eq 'ref') {
+    $_= $in{'ref'};
+    s/^\s+//; s/^\#//; s/^\s+//; s/^0*//; s/\s+$//;
+
+    if (m/\D/ || !m/\d/) {
+        print <<END;
+Content-Type: text/html
+
+<html><head><title>Bug number not numeric</title>
+</head><body>
+<h1>Invalid input to specific bug fetch form</h1>
+
+You must type a number, being the bug reference number.
+There should be no nondigits in your entry.
+</html>
+END
+        exit(0);
+    }
+    $suburl= $_;
+    $suburl =~ s,^..,$&/$&,;
+    $suburl.= '.html';
+} elsif ($in{'type'} eq 'package') {
+    $_= $in{'package'};
+    s/^\s+//; s/\s+$//; y/A-Z/a-z/;
+    if (m/^[^0-9a-z]/ || m/[^-+.0-9a-z]/) {
+        print <<END;
+Content-Type: text/html
+
+<html><head><title>Package name contains invalid characters</title>
+</head><body>
+<h1>Invalid input to package buglist fetch form</h1>
+
+You must type a package name.  Package names start with a letter
+or digit and contain only letters, digits and the characters
+- + . (hyphen, plus, full stop).
+</html>
+END
+        exit(0);
+    }
+    $suburl= "pa/l$_.html";
+} else {
+    print <<END;
+Content-Type: text/plain
+
+Please use the real DBC_WHO form. (invalid type value)
+END
+    exit(0);
+}
+
+$base= $ENV{'HTTP_REFERER'};
+if ($base =~ s:/Bugs/.*$::) {
+    for $y (keys %map) {
+       $base= $map{$y} if $base eq $y;
+    }
+} else {
+    $base= $in{'base'};
+}
+
+$newurl= "$base/Bugs/db/$suburl";
+print <<END;
+Status: 301 Redirect
+Location: $newurl
+
+The bug report data you are looking for ($suburl)
+is available <A href="$newurl">here</A>.
+
+(If this link does not work then the bug or package does not exist in
+the tracking system any more, or does not yet, or never did.)
+END
+
+exit(0);
diff --git a/cgi/cgi-lib.pl b/cgi/cgi-lib.pl
new file mode 100644 (file)
index 0000000..bc35ed9
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/perl
+
+# Perl Routines to Manipulate CGI input
+#
+# Copyright (c) 1995 Steven E. Brenner
+# Permission granted to use and modify this library so long as the
+# copyright above is maintained, modifications are documented, and
+# credit is given for any use of the library.
+#
+# Thanks are due to many people for reporting bugs and suggestions
+# especially Meng Weng Wong, Maki Watanabe, Bo Frese Rasmussen,
+# Andrew Dalke, Mark-Jason Dominus, Dave Dittrich, Jason Mathews
+
+# For more information, see:
+#     http://www.bio.cam.ac.uk/web/form.html
+#     http://www.seas.upenn.edu/~mengwong/forms/
+
+# Minimalist http form and script (http://www.bio.cam.ac.uk/web/minimal.cgi):
+#
+# require "cgi-lib.pl";
+# if (&ReadParse(*input)) {
+#    print &PrintHeader, &PrintVariables(%input);
+# } else {
+#   print &PrintHeader,'<form><input type="submit"> Data: <input name="myfield">';
+#}
+
+# ReadParse
+# Reads in GET or POST data, converts it to unescaped text,
+# creates key/value pairs in %in, using '\0' to separate multiple
+# selections
+
+# Returns TRUE if there was input, FALSE if there was no input
+# UNDEF may be used in the future to indicate some failure.
+
+# Now that cgi scripts can be put in the normal file space, it is useful
+# to combine both the form and the script in one place.  If no parameters
+# are given (i.e., ReadParse returns FALSE), then a form could be output.
+
+# If a variable-glob parameter (e.g., *cgi_input) is passed to ReadParse,
+# information is stored there, rather than in $in, @in, and %in.
+
+sub ReadParse {
+  local (*in) = @_ if @_;
+  local ($i, $key, $val);
+
+  # Read in text
+  if (&MethGet) {
+    $in = $ENV{'QUERY_STRING'};
+  } elsif (&MethPost) {
+    read(STDIN,$in,$ENV{'CONTENT_LENGTH'});
+  }
+
+  @in = split(/[&;]/,$in);
+
+  foreach $i (0 .. $#in) {
+    # Convert plus's to spaces
+    $in[$i] =~ s/\+/ /g;
+
+    # Split into key and value.
+    ($key, $val) = split(/=/,$in[$i],2); # splits on the first =.
+
+    # Convert %XX from hex numbers to alphanumeric
+    $key =~ s/%(..)/pack("c",hex($1))/ge;
+    $val =~ s/%(..)/pack("c",hex($1))/ge;
+
+    # Associate key and value
+    $in{$key} .= "\0" if (defined($in{$key})); # \0 is the multiple separator
+    $in{$key} .= $val;
+
+  }
+
+  return scalar(@in);
+}
+
+
+# PrintHeader
+# Returns the magic line which tells WWW that we're an HTML document
+
+sub PrintHeader {
+  return "Content-type: text/html\n\n";
+}
+
+
+# HtmlTop
+# Returns the <head> of a document and the beginning of the body
+# with the title and a body <h1> header as specified by the parameter
+
+sub HtmlTop
+{
+  local ($title) = @_;
+
+  return <<END_OF_TEXT;
+<html>
+<head>
+<title>$title</title>
+</head>
+<body>
+<h1>$title</h1>
+END_OF_TEXT
+}
+
+# Html Bot
+# Returns the </body>, </html> codes for the bottom of every HTML page
+
+sub HtmlBot
+{
+   return "</body>\n</html>\n";
+ }
+
+
+# MethGet
+# Return true if this cgi call was using the GET request, false otherwise
+
+sub MethGet {
+  return ($ENV{'REQUEST_METHOD'} eq "GET");
+}
+
+
+# MethPost
+# Return true if this cgi call was using the POST request, false otherwise
+
+sub MethPost {
+  return ($ENV{'REQUEST_METHOD'} eq "POST");
+}
+
+
+# MyURL
+# Returns a URL to the script
+
+sub MyURL  {
+  local ($port);
+  $port = ":" . $ENV{'SERVER_PORT'} if  $ENV{'SERVER_PORT'} != 80;
+  return  'http://' . $ENV{'SERVER_NAME'} .  $port . $ENV{'SCRIPT_NAME'};
+}
+
+
+# CgiError
+# Prints out an error message which which containes appropriate headers,
+# markup, etcetera.
+# Parameters:
+#  If no parameters, gives a generic error message
+#  Otherwise, the first parameter will be the title and the rest will
+#  be given as different paragraphs of the body
+
+sub CgiError {
+  local (@msg) = @_;
+  local ($i,$name);
+
+  if (!@msg) {
+    $name = &MyURL;
+    @msg = ("Error: script $name encountered fatal error");
+  };
+
+  print &PrintHeader;
+  print "<html><head><title>$msg[0]</title></head>\n";
+  print "<body><h1>$msg[0]</h1>\n";
+  foreach $i (1 .. $#msg) {
+    print "<p>$msg[$i]</p>\n";
+  }
+  print "</body></html>\n";
+}
+
+
+# CgiDie
+# Identical to CgiError, but also quits with the passed error message.
+
+sub CgiDie {
+  local (@msg) = @_;
+  &CgiError (@msg);
+  die @msg;
+}
+
+
+# PrintVariables
+# Nicely formats variables in an associative array passed as a parameter
+# And returns the HTML string.
+sub PrintVariables {
+  local (%in) = @_;
+  local ($old, $out, $output);
+  $old = $*;  $* =1;
+  $output .=  "\n<dl compact>\n";
+  foreach $key (sort keys(%in)) {
+    foreach (split("\0", $in{$key})) {
+      ($out = $_) =~ s/\n/<br>\n/g;
+      $output .=  "<dt><b>$key</b>\n <dd><i>$out</i><br>\n";
+    }
+  }
+  $output .=  "</dl>\n";
+  $* = $old;
+
+  return $output;
+}
+
+# PrintVariablesShort
+# Now obsolete; just calls PrintVariables
+
+sub PrintVariablesShort {
+  return &PrintVariables(@_);
+}
+
+1; #return true
+
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..b9d2b6b
--- /dev/null
@@ -0,0 +1,70 @@
+debbugs (2.2-3) unstable; urgency=low
+
+  * Perl Depends change
+
+ -- Darren Benham <gecko@debian.org>  Tue, 27 Jul 1999 11:27:22 -0700
+
+debbugs (2.2-2) unstable; urgency=low
+
+  * Added mailtools to dependency
+
+ -- Darren Benham <gecko@debian.org>  Thu, 13 May 1999 13:13:15 -0700
+
+debbugs (2.2-1) unstable; urgency=low
+
+  * NATIVE Qmail (mailer) support!  No more "other MTA" needed
+       for Qmail users!
+  * Improved sendmail support.
+  * Changed lynx dependancies to simply "lynx"
+  * fixed bad spelling in service script (fixes #36205)
+
+ -- Darren Benham <gecko@debian.org>  Thu,  8 Apr 1999 16:00:32 -0700
+
+debbugs (2.1-1) unstable; urgency=low
+
+  * Added variable in "bad email" message (receive)
+  * Fixed SUBSTITUTE_DTIME in main html pages
+  * Changed crontab sample (had bad directories)
+  * Added some documentation for MTA setup
+  * Added support for sendmail
+  * Removed use of btoa to move change around.  It's non-free.
+
+ -- Darren Benham <gecko@debian.org>  Thu,  1 Apr 1999 14:17:01 -0800
+
+debbugs (2.0-1) unstable; urgency=low
+
+  * First public release of deb
+  * Config modification implemented
+
+ -- Darren Benham <gecko@debian.org>  Sat, 27 Mar 1999 10:37:37 -0800
+
+debbugs (1.0-4) unstable; urgency=low
+
+  * Tried a stopgap measure for config files
+
+ -- Darren Benham <gecko@debian.org>  Mon, 15 Feb 1999 22:11:08 -0800
+
+debbugs (1.0-3) unstable; urgency=low
+
+  * $gListDomain yet again
+  * removed nextnumber, config and text from deb for time bing
+
+ -- Darren Benham <gecko@debian.org>  Wed, 10 Feb 1999 11:09:47 -0800
+
+debbugs (1.0-2) unstable; urgency=low
+
+  * internal release
+  * fixed scripting bugs in list email
+
+ -- Darren Benham <gecko@debian.org>  Wed, 10 Feb 1999 10:39:18 -0800
+
+debbugs (1.0-1) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Darren Benham <gecko@debian.org>  Thu, 21 Jan 1999 20:55:51 -0800
+
+Local variables:
+mode: debian-changelog
+add-log-mailing-address: "gecko@debian.org"
+End:
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..76e68b6
--- /dev/null
@@ -0,0 +1,36 @@
+This package was debianized by Johnie Ingram (johnie@debian.org)
+on Tue Jan  6 10:20:12 EST 1998.
+
+It was downloaded from:
+       http://www.chiark.greenend.org.uk/~ian/debbugs/
+
+
+COPYRIGHT AND LACK-OF-WARRANTY NOTICE
+
+Copyright 1994,1995,1996,1997 Ian Jackson <ijackson@chiark.greenend.org.uk>
+Copyright 1997 nCipher Corporation Limited
+Copyright 1995 Steven Brenner (for cgi-lib.pl).
+
+This bug system is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+This program and documentation is distributed in the hope that it will be
+useful, but without any warranty; without even the implied warranty of
+merchantability or fitness for a particular purpose. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program, or one should be available above; if not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA, or email debbugs-maint@chiark.greenend.org.uk.
+
+ - Ian Jackson 30.10.1997
+
+Modifications from version 1.0 to 2.0 are
+Copyright (C) 1999 Darren Benham <gecko@debian.org>
+and released under the terms of the GPL -- version 2.
+
+On Debian/GNU Linux systems, the text of the GPL can be found in
+/usr/doc/copyright/GPL.
diff --git a/debian/debbugs-maketxt b/debian/debbugs-maketxt
new file mode 100755 (executable)
index 0000000..cbb6c00
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -e
+
+cwd="`pwd`"
+date="`date +'%d %h %Y'`"
+
+txtconvert () {
+       src=$1; dst=$2
+       echo "  generating $dst from $src ..."
+       rm -f /var/lib/debbugs/www/txt/$dst.html /var/lib/debbugs/www/txt/$dst
+       perl -ne 'print unless m/^Other pages:$/ .. /^\<hr\>/' \
+               /var/lib/debbugs/www/$src > /var/lib/debbugs/www/txt/$dst.html
+       HOME=/dev/null lynx -nolist -dump -cfg=/etc/debbugs/lynx-cfg \
+               file://localhost/var/lib/debbugs/www/txt/$dst.html > /var/lib/debbugs/www/txt/$dst
+       rm /var/lib/debbugs/www/txt/$dst.html
+}
+
+echo "documentation conversion ..."
+txtconvert Reporting.html bug-reporting.txt
+txtconvert Access.html bug-log-access.txt
+txtconvert server-request.html bug-log-mailserver.txt
+txtconvert Developer.html bug-maint-info.txt
+txtconvert server-control.html bug-maint-mailcontrol.txt
+txtconvert server-refcard.html bug-mailserver-refcard.txt
+
+exit 0
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..aa96c6e
--- /dev/null
@@ -0,0 +1,12 @@
+/etc/debbugs/html
+usr/lib/debbugs
+usr/sbin
+usr/doc/debbugs/examples
+var/lib/debbugs/indices
+var/lib/debbugs/www/cgi
+var/lib/debbugs/www/db
+var/lib/debbugs/www/txt
+var/lib/debbugs/spool/lock
+var/lib/debbugs/spool/archive
+var/lib/debbugs/spool/incoming
+var/lib/debbugs/spool/db
diff --git a/html/Access.html.in b/html/Access.html.in
new file mode 100644 (file)
index 0000000..aa28c60
--- /dev/null
@@ -0,0 +1,42 @@
+$gAccessHtml = <<HTML_END
+<HTML>
+<HEAD>
+       <TITLE>$gProject $gBugs - Accessing the logs</TITLE>
+       <LINK REV="made" HREF="mailto:$gMaintainerEmail">
+</HEAD>
+<BODY>
+<A NAME="developers"> 
+       <H1>Accessing $gBug reports in the tracking system logs</H1>
+</A>
+
+Each message received at or sent by the $gBug processing system is
+logged and made available in a number of ways.
+<P>
+
+$gHTMLCopies
+
+There is a <A HREF="server-request.html">mailserver</A> which can send
+$gBug reports as plain text on request.  To use it send the word
+<CODE>help</CODE> as the sole contents of an email to
+<CODE>request</CODE> (the <CODE>Subject</CODE> of the
+message is ignored), or read the instructions on the World Wide Web or
+in the file <CODE>bug-log-mailserver.txt</CODE>.
+
+<HR>
+
+Other pages:
+<UL>
+       <LI><A href="./">$gBug tracking system main contents page.</A>
+       <LI><A href="Reporting.html">Instructions for reporting $gBugs.</A>
+       <LI><A href="Developer.html">Developers' information regarding the $gBug processing system.</A>
+       <LI><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+       <LI><A href="db/ix/packages.html">Packages with $gBug reports.</A>
+       <LI><A href="db/ix/maintainers.html">Maintainers of packages with $gBug reports.</A>
+
+$gHTMLOtherPageList
+
+</ul>
+
+$gHTMLTail
+
+HTML_END
diff --git a/html/Developer.html.in b/html/Developer.html.in
new file mode 100644 (file)
index 0000000..d19d3b0
--- /dev/null
@@ -0,0 +1,193 @@
+$gDeveloperHtml = <<HTML_END
+<HTML>
+<HEAD>
+       <title>$gProject - Developers' information</title>
+       <link rev="made" href="mailto:$gMaintainerEmail">
+</head>
+<body>
+       <h1><A name="developers">Developers' information regarding the $gBug processing system</A></h1>
+
+Initially, a $gBug report is submitted by a user as an ordinary mail
+message to <code>submit\@$gEmailDomain</code>.  This will then be
+given a number, acknowledged to the user, and forwarded to a mailing 
+list (if configured).  If the submitter included a <code>Package</code>
+line listing a package with a known maintainer the maintainer will get
+a copy too.
+<p>
+
+The <code>Subject</code> line will have
+<code>$gBug#</code><var>nnn</var><code>:</code> added, and the
+<code>Reply-To</code> will be set to include both the submitter of the
+report and <var>nnn</var><code>\@$gEmailDomain</code>.
+<p>
+
+<h2>Closing $gBug reports</h2>
+
+A developer who receives a $gBug from the tracking system, or sees it on
+the mailing list, and takes responsibility for it should hit Reply in
+their favourite mailreader,
+and then edit the <code>To</code> field to say
+<var>nnn</var><code>-done\@$gEmailDomain</code> instead of
+<var>nnn</var><code>\@$gEmailDomain</code>
+(<var>nnn</var><code>-close</code> is provided as an alias for
+<var>nnn</var><code>-done</code>).
+<p>
+
+The address of the original submitter of the $gBug report will be
+included in the default <code>To</code> field, because the $gBug system
+included it in the <code>Reply-To</code>.
+<p>
+
+`Done' messages are forwarded to a mailing list if the mailing list has been
+set up.
+<P>
+
+The person closing the $gBug and the person who submitted it will each
+get a notification about the change in status of the report.
+
+<h2>Followup messages</h2>
+
+If a developer wishes to reply to a $gBug report without marking the $gBug
+as done they may simply reply to the message.  Their reply will (by
+default) go to <var>nnn</var><code>\@$gEmailDomain</code> and to the original
+submitter of the $gBug report.  The $gBug tracking system will file the
+reply with the rest of the logs for that $gBug report and forward it to
+a designated mailing list.  The $gBug will not be marked as done.
+<p>
+
+If you wish to send a followup message which is not appropriate for
+any mailing list you can do so by sending it to
+<var>nnn</var><code>-quiet\@$gEmailDomain</code> or
+<var>nnn</var><code>-maintonly\@$gEmailDomain</code>, which only file it (not
+forwarding it anywhere) and send it on only to the maintainer of the
+package in question, respectively.
+<p>
+
+Do <em>not</em> use the `reply to all recipients' or `followup'
+feature of your mailer unless you intend to edit down the recipients
+substantially.  In particular, don't send a followup message both to
+<var>nnn</var><code>\@$gEmailDomain</code> and to
+<code>submit\@$gEmailDomain</code>, because the $gBug system will then
+get two copies of it and each one will be forwarded to the designated
+mailing list separately.
+<p>
+
+<h2><A name="severities">Severity levels</A></h2>
+
+The $gBug system records a severity level with each $gBug report.  This is
+set to <code>$gDefaultSeverity</code> by default, but can be overridden either by
+supplying a <code>Severity</code> line in the psuedo-header when the
+$gBug is submitted (see the
+<A href="Reporting.html#psuedoheader">instructions for reporting
+$gBugs</A>), or by using the <code>severity</code> command with the
+<A href="#requestserv">control request server</A>.
+
+<p>
+
+The severity levels are:
+
+<dl>
+$gHTMLSeverityDesc
+</dl>
+
+<h2><A name="forward">Recording that you have passed on a $gBug report</A></h2>
+
+When a developer forwards a $gBug report to the developer of the
+upstream source package from which the $gProject package is derived,
+they should note this in the $gBug tracking system as follows:
+<p>
+
+Make sure that the <code>To</code> field of your message to the author
+to has only the author(s) address(es) in it; put both the person who
+reported the $gBug and
+<var>nnn</var><code>-forwarded\@$gEmailDomain</code> in the
+<code>CC</code> field.
+<p>
+
+Ask the author to preserve the <code>CC</code> to
+<var>nnn</var><code>-forwarded\@$gEmailDomain</code> when they reply, so that
+the $gBug tracking system will file their reply with the original
+report.
+<p>
+
+When the $gBug tracking system gets a message at
+<var>nnn</var><code>-forwarded</code> it will mark the relevant $gBug as
+having been forwarded to the address(es) in the <code>To</code> field
+of the message it gets.
+<p>
+
+You can also manipulate the `forwarded to' information by sending messages to
+<A href="server-control.html"><code>control\@$gEmailDomain</code></A>.
+
+<h2>Summary postings</h2>
+
+Every Friday, a list of outstanding $gBug reports is posted to a summary mailing
+list (if set up), sorted by age of report.
+Every Tuesday, a list of $gBug reports that have gone unanswered too long is
+posted, sorted by package maintainer.
+<p>
+
+$gBadMaintHtml
+
+<h2><A name="requestserv">Reopening, reassigning and manipulating $gBugs</A></h2>
+
+It is possible to reassign $gBug reports to other packages, to reopen
+erroneously-closed ones, to modify the information saying to where, if
+anywhere, a $gBug report has been forwarded, to change the severities
+and titles of reports and to merge and unmerge $gBug reports.  This is
+done by sending mail to <code>control\@$gEmailDomain</code>.
+<p>
+
+The <A href="server-control.html">format of these messages</A> is
+described in another document available on the World Wide Web or in
+the file <code>bug-maint-mailcontrol.txt</code>.  A plain text version
+can also be obtained by mailing the word <code>help</code> to the
+server at the address above.
+
+<h2>More-or-less obsolete subject-scanning feature</h2>
+(this is likely to be removed the next version)<BR>
+Messages that arrive at <code>submit</code> or <code>$gBugs</code> whose
+Subject starts <code>Bug#</code><var>nnn</var> will be treated as
+having been sent to <var>nnn</var><code>\@$gEmailDomain</code>.  This is both
+for backwards compatibility with mail forwarded from the old
+addresses, and to catch followup mail sent to <code>submit</code> by
+mistake (for example, by using reply to all recipients).
+
+<p>
+
+A similar scheme operates for <code>maintonly</code>,
+<code>done</code>, <code>quiet</code> and <code>forwarded</code>,
+which treat mail arriving with a Subject tag as having been sent to
+the corresponding <var>nnn-whatever</var><code>\@$gEmailDomain</code> address.
+
+<p>
+
+Messages arriving at plain <code>forwarded</code> and
+<code>done</code> - ie, with no $gBug report number in the address - and
+without a $gBug number in the Subject will be filed under `junk' and
+kept for a few weeks, but otherwise ignored.
+
+<h2><A name="future">Future plans</A></h2>
+
+At some point the <code>Package:</code> secondary header field may
+become mandatory - at the moment omitting it just produces a warning
+message.
+
+<hr>
+Other pages:
+<ul>
+<li><A href="./">$gBug tracking system main contents page.</A>
+<li><A href="Reporting.html">Instructions for reporting $gBugs.</A>
+<li><A href="Access.html">Accessing the $gBug tracking logs other than by WWW.</A>
+<li><A href="server-refcard.html">Mailservers' reference card.</A>
+<li><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+<li><A href="db/ix/packages.html">Packages with $gBug reports.</A>
+<li><A href="db/ix/maintainers.html">Maintainers of packages with $gBug reports.</A>
+
+$gHTMLOtherPageList
+
+</ul>
+
+$gHTMLTail
+
+HTML_END
diff --git a/html/Reporting.html.in b/html/Reporting.html.in
new file mode 100644 (file)
index 0000000..b4f76f2
--- /dev/null
@@ -0,0 +1,191 @@
+$gReportingHtml = <<HTML_END
+<html><head><title>$gProject $gBugs - how to report a $gBug</title>
+<link rev="made" href="mailto:$gMaintainerEmail">
+</head><body>
+<h1>How to report a $gBug in $gProject</h1>
+
+Send mail to
+<A href="mailto:submit\@$gEmailDomain"><code>submit\@$gEmailDomain</code></A>,
+as described below.
+<p>
+
+Please don't report several unrelated $gBugs - especially ones in
+different packages - in one message.  Also, please don't mail your $gBug
+report to any mailing lists or recipients other than
+<code>submit\@$gEmailDomain</code> (for details of how to do this right, see
+<A href="#xcc">below</A>).
+<p>
+
+Lists of currently-outstanding $gBugs are available <A href="./">on
+the World Wide Web</A> and <A href="Access.html">elsewhere</A> - see
+other documents for details.
+<p>
+
+You should put a pseudo-header at the start of the body of the
+message, with the <code>Package:</code> and <code>Version:</code>
+lines giving the name and version of the package which has the $gBug.
+(The pseudo-header fields must start at the very start of their lines,
+and the $gBug system does not currently understand them if they're
+buried in MIMEd or PGPd mail.)
+
+$gHTMLFindPackage
+
+<em>See below for <A href="#details">further requirements</A></em>.
+<p>
+
+$gHTMLPseudoDesc
+
+<h2><A name="example">Example</A></h2>
+
+A $gBug report, with mail header, looks something like this:
+<pre>
+  To: submit\@$gEmailDomain
+  From: diligent\@testing.linux.org
+  Subject: Hello says `goodbye'
+<A name="psuedoheader">
+  Package: hello</A>
+  Version: 1.3-2
+
+  When I invoke `hello' without arguments from an ordinary shell
+  prompt it prints `goodbye', rather than the expected `hello, world'.
+  Here is a transcript:
+
+  $ hello
+  goodbye
+  $ /usr/bin/hello
+  goodbye
+  $
+
+  I suggest that the output string, in hello.c, be corrected.
+
+  I am using Debian 1.1, kernel version 1.3.99.15z
+  and libc 5.2.18.3.2.1.3-beta.
+</pre>
+
+<h2><A name="details">Please include in your report:</A></h2>
+
+<ul>
+<li>The <em>exact</em> and <em>complete</em> text of any error
+messages printed or logged.  This is very important!
+<li>Exactly what you typed or did to demonstrate the problem.
+<li>A description of the incorrect behaviour: exactly what behaviour
+you were expecting, and what you observed.  A transcript of an
+example session is a good way of showing this.
+<li>A suggested fix, or even a patch, if you have one.
+<li>Details of the configuration of the program with the problem.
+Include the complete text of its configuration files.
+$gXtraBugInfo
+</ul>
+
+Include any detail that seems relevant - you are in very little danger
+of making your report too long by including too much information.  If
+they are small please include in your report any files you were using
+to reproduce the problem (uuencoding them if they may contain odd
+characters etc.).
+
+<p>
+
+Of course, like any email, you should include a clear, descriptive
+<code>Subject</code> line in your main mail header.  The subject you
+give will be used as the initial $gBug title in the tracking system, so
+please try to make it informative !
+
+<h2><A name="xcc">Sending copies of $gBug reports to other addresses</A></h2>
+
+Sometimes it is necessary to send a copy of a $gBug report to somewhere
+else besides the mailing list and the package maintainer, which is where they
+are normally sent.
+<p>
+
+You could do this by CC'ing your $gBug report to the other address(es),
+but then the other copies would not have the $gBug report number put in
+the <code>Reply-To</code> field and the <code>Subject</code> line.
+When the recipients reply they will probably preserve the
+<code>submit\@$gEmailDomain</code> entry in the header and have their
+message filed as a new $gBug report.  This leads to many duplicated
+reports.
+<p>
+
+The <em>right</em> way to do this is to use the
+<code>X-$gProject-CC</code> header.  Add a line like this to your
+message's mail header (not to the psuedo header with the
+<code>Package</code> field):
+<pre>
+ X-$gProject-CC: other-list\@cosmic.edu
+</pre>
+This will cause the $gBug tracking system to send a copy of your report
+to the address(es) in the <code>X-$gProject-CC</code> line as well as to
+any mailing list.
+<p>
+
+This feature can often be combined usefully with mailing
+<code>quiet</code> - see below.
+
+
+<h2><A name="severities">Severity levels</A></h2>
+
+If a report is of a particularly serious $gBug, or is merely a feature
+request that, you can set the severity level of the $gBug as you report
+it.  This is not required, however, and the developers will assign an
+appropriate severity level to your report if you do not.
+<p>
+
+To assign a severity level put a
+<code>Severity: <var>severity</var></code> line in the psuedo-header,
+together with <code>Package</code> and <code>Version</code>.  The
+severity levels available are described in the
+<A href="Developer.html#severities">developers' documentation</A>.
+
+
+<h2>Not forwarding to the mailing list - minor $gBug reports</h2>
+
+If a $gBug report is minor (for example, a documentation typo or other
+trivial build problem), or you're submitting many reports at once,
+send them to <code>maintonly\@$gEmailDomain</code> or <code>quiet\@$gEmailDomain</code>.
+<code>maintonly</code> will send the report on to the package
+maintainer (provided you supply a correct <code>Package</code> line in
+the pseudo-header and the maintainer is known), and <code>quiet</code>
+will not forward it anywhere at all but only file it as a $gBug (useful
+if, for example, you are submitting many similar $gBugs and want to post
+only a summary).
+<p>
+
+If you do this the $gBug system will set the <code>Reply-To</code> of
+any forwarded message so that replies will by default be processed in
+the same way as the original report.
+
+<h3>Unknown packages or $gBugs with no <code>Package</code> key</h3>
+
+If the $gBug tracking system doesn't know who the maintainer of the
+relevant package is it'll forward the report to
+the mailing list even if <code>maintonly</code> was used.
+<p>
+
+When sending to <code>maintonly\@$gEmailDomain</code> or
+<var>nnn</var><code>-maintonly\@$gEmailDomain</code> you should make sure that
+the $gBug report is assigned to the right package, by putting a correct
+<code>Package</code> at the top of an original submission of a report,
+or by using <A href="server-control.html">the
+<code>control\@$gEmailDomain</code> service</A> to (re)assign the report
+appropriately first if it isn't correct already.
+
+$gXtraReportingInfo
+
+<hr>
+Other pages:
+<ul>
+<li><A href="./">Bug tracking system main contents page.</A>
+<li><A href="Developer.html">Developers'
+information regarding the $gBug processing system.</A>
+<li><A href="Access.html">Accessing the $gBug tracking logs other than by WWW.</A>
+<li><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+<li><A href="db/ix/packages.html">Packages with $gBug reports.</A>
+<li><A href="db/ix/maintainers.html">Maintainers of packages with $gBug reports.</A>
+
+$gHTMLOtherPageList
+
+</ul>
+
+$gHTMLEnd
+
+HTML_END
diff --git a/html/index.html.in b/html/index.html.in
new file mode 100644 (file)
index 0000000..4fce7c2
--- /dev/null
@@ -0,0 +1,85 @@
+$gIndexHtml = <<HTML_END
+<html><head>
+<title>$gProject $gBug tracking system</title>
+<link rev="made" href="mailto:$gMaintainerEmail">
+</head><body>
+<h1>$gProject $gBug tracking system main contents page</h1>
+
+$gProjectTitle has a $gBug tracking system which files
+details of $gBugs reported by users and developers.  Each $gBug is given a
+number, and is kept on file until it is marked as having been dealt
+with.
+
+$gHTMLCopies
+
+<h2>Documentation about the $gBug tracking system</h2>
+
+<ul>
+<li><A href="Reporting.html">Instructions for reporting a $gBug.</A>
+<li><A href="Access.html">Ways of accessing the $gBug reporting logs.</A>
+<li><A href="server-request.html">Requesting $gBug reports by email.</A>
+<li><A href="Developer.html">Developers' information on how to use the system.</A>
+<li><A href="server-control.html">Developers' information on
+manipulating $gBugs by email.</A>
+<li><A href="server-refcard.html">Mailservers' reference card.</A>
+</ul>
+
+<h2>Reviewing $gBug reports on the WWW</h2>
+
+<ul>
+<li><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+<li><A href="db/ix/packages.html">Index of packages with $gBug reports.</A>
+<li><A href="db/ix/maintainers.html">Index of maintainers of packages with $gBug reports.</A>
+<li>Outstanding
+<A href="db/si/pendingcritical.html">critical</A>,
+<A href="db/si/pendinggrave.html">grave</A> and
+<A href="db/si/pendingnormal.html">normal</A> $gBugs and
+<A href="db/si/pendingwishlist.html">wishlist</A> items.
+<li>Forwarded
+<A href="db/si/forwardedcritical.html">critical</A>,
+<A href="db/si/forwardedgrave.html">grave</A> and
+<A href="db/si/forwardednormal.html">normal</A> $gBugs and
+<A href="db/si/forwardedwishlist.html">wishlist</A> items.
+<li>Resolved
+<A href="db/si/donecritical.html">critical</A>,
+<A href="db/si/donegrave.html">grave</A> and
+<A href="db/si/donenormal.html">normal</A> $gBugs and
+<A href="db/si/donewishlist.html">wishlist</A> items.
+<li><A href="db/ix/psummary.html">Summary of outstanding reports, sorted by package.</A>
+<li><A href="db/ix/summary.html">Summary of outstanding reports, sorted by number.</A>
+<li><A href="db/ju/junk.html">Logs not associated with a particular $gBug report.</A>
+<li><A href="db/ix/zstamp.html">Time stamp page (for checking that mirror is current).</A>
+</ul>
+
+Each closed $gBug report is expired from these logs $gRemoveAge days after the
+last message relating to it is received and filed.
+
+<h3>Find a $gBug report by reference number</h2>
+
+<form method="get" action="$gCGIDomain/bugs-fetch2.pl">
+<input type="hidden" name="type" value="ref">
+<input type="text" size="10" name="ref" value="">
+<input type="hidden" name="base" value="http://$gWebDomain">
+<input type="submit" value="Fetch">
+</form>
+`Not found' means that the $gBug was closed and expired or
+never existed, or that this mirror has not yet recorded that $gBug - see
+also the <A href="db/ix/zstamp.html">timestamp page</A>.
+
+<h3>Find a $gBug report by package</h2>
+
+<form method="get" action="$gCGIDomain/bugs-fetch2.pl">
+<input type="hidden" name="type" value="package">
+<input type="text" size="30" name="package" value="">
+<input type="hidden" name="base" value="http://$gWebDomain">
+<input type="submit" value="Fetch">
+</form>
+`Not found' means that that package does not exist or does not have
+any outstanding or recently closed $gBug reports.
+
+$gHTMLOtherPages
+
+$gHTMLTail
+
+HTML_END
+
diff --git a/html/lynx-cfg b/html/lynx-cfg
new file mode 100644 (file)
index 0000000..792d600
--- /dev/null
@@ -0,0 +1 @@
+#
diff --git a/html/server-control.html.in b/html/server-control.html.in
new file mode 100644 (file)
index 0000000..5ba35c6
--- /dev/null
@@ -0,0 +1,202 @@
+$gControlHtml = <<HTML_END
+<html><head>
+<html><head>
+<title>$gProject $gBug system - control mail server commands</title>
+<link rev="made" href="mailto:$gMaintainerEmail">
+</head><body>
+<h1>Introduction to the $gBug control and manipulation mailserver</h1>
+
+In addition to the mailserver on <code>request\@$gEmailDomain</code>
+which allows the retrieval of $gBug data and documentation by email,
+there is another server on <code>control\@$gEmailDomain</code> which
+also allows $gBug reports to be manipulated in various ways.
+<p>
+
+The control server works just like the request server, except that it
+has some additional commands; in fact, it's the same program.  The two
+addresses are only separated to avoid users making mistakes and
+causing problems while merely trying to request information.
+<p>
+
+Please see the
+<A href="server-request.html#introduction">introduction to
+the request server</A>
+available on the World Wide Web, in the file
+<code>bug-maint-mailcontrol.txt</code>, or by sending
+<code>help</code> to either mailserver, for details of the basics of
+operating the mailservers and the common commands available when
+mailing either address.
+<p>
+
+The <A href="server-refcard.html">reference card</A> for the
+mailservers is available via the WWW, in
+<code>bug-mailserver-refcard.txt</code> or by email using the
+<code>refcard</code> command).
+
+<h1>Commands available only at the control mailserver</h1>
+
+<dl>
+
+<dt><code>close</code> <var>bugnumber</var>
+<dd>
+
+Close $gBug report #<var>bugnumber</var>.
+<p>
+
+A notification is sent to the user who reported the $gBug, but (in
+contrast to mailing <var>bugnumber</var><code>-done@$gEmailDomain</code>) the
+text of the mail which caused the $gBug to be closed is <em>not</em>
+included in that notification.  The maintainer who closes a report
+should ensure, probably by sending a separate message, that the user
+who reported the $gBug knows why it is being closed.
+
+<dt><code>reassign</code> <var>bugnumber</var> <var>package</var>
+<dd>
+
+Records that $gBug #<var>$gBugnumber</var> is a $gBug in <var>package</var>.
+This can be used to set the package if the user forgot the
+pseudo-header, or to change an earlier assignment.  No notifications
+are sent to anyone (other than the usual information in the processing
+transcript).
+
+<dt><code>reopen</code> <var>bugnumber</var>
+ [ <var>originator-address</var> | <code>=</code> | <code>!</code> ]
+<dd>
+
+Reopens #<var>bugnumber</var> if it is closed.
+<p>
+
+By default, or if you specify <code>=</code>, the original submitter is
+still as the originator of the report, so that they will get the ack
+when it is closed again.
+<p>
+
+If you supply an <var>originator-address</var> the originator will be
+set to the address you supply.  If you wish to become the new
+originator of the reopened report you can use the <code>!</code>
+shorthand or specify your own email address.
+<p>
+
+It is usually a good idea to tell the person who is about to be
+recorded as the originator that you're reopening the report, so that
+they will know to expect the ack which they'll get when it is closed
+again.
+<p>
+
+If the $gBug is not closed then reopen won't do anything, not even
+change the originator.  There is no way to change the originator of an
+open $gBug report (this is deliberate, so that you can't have a $gBug be
+closed and then deleted $gRemoveAge days later without someone being told about
+it).
+
+<dt><code>forwarded</code> <var>bugnumber</var> <var>address</var>
+<dd>
+
+Notes that <var>bugnumber</var> has been forwarded to the upstream
+maintainer at <var>address</var>.  This does not actually forward the
+report.  This can be used to change an existing incorrect forwarded-to
+address, or to record a new one for a $gBug that wasn't previously noted
+as having been forwarded.
+
+<dt><code>notforwarded</code> <var>bugnumber</var>
+<dd>
+
+Forgets any idea that <var>bugnumber</var> has been forwarded to any
+upstream maintainer.  If the $gBug was not recorded as having been
+forwarded then this will do nothing.
+
+<dt><code>retitle</code> <var>bugnumber</var> <var>new-title</var>
+<dd>
+
+Changes the title of a $gBug report to that specified (the default is
+the <code>Subject</code> mail header from the original report.
+<p>
+
+Unlike most of the other $gBug-manipulation commands when used on one of
+a set of merged reports this will change the title of only the
+individual $gBug requested, and not all those with which it is merged.
+
+<dt><code>severity</code> <var>bugnumber</var> <var>severity</var>
+<dd>
+
+Set the severity level for $gBug report #<var>bugnumber</var> to
+<var>severity</var>.  No notification is sent to the user who reported
+the $gBug.
+<p>
+
+For <A href="Developer.html#severities">their meanings</A> please
+consult the general developers' documentation for the $gBug system.
+
+<dt><code>merge</code> <var>bugnumber</var> <var>bugnumber</var> ...
+<dd>
+
+Merges two or more $gBug reports.  When reports are merged opening,
+closing, marking or unmarking as forwarded and reassigning any of the
+$gBugs to a new package will have an identical effect on all of the
+merged reports.
+<p>
+
+Before $gBugs can be merged they must be in exactly the same state:
+either all open or all closed, with the same forwarded-to upstream
+author address or all not marked as forwarded, and all assigned to the
+same package or package(s) (an exact string comparison is done on the
+package to which the $gBug is assigned).  If they don't start out in the
+same state you should use <code>reassign</code>, <code>reopen</code>
+and so forth to make sure that they are before using
+<code>merge</code>.
+<p>
+
+If any of the $gBugs listed in a <code>merge</code> command is already
+merged with another $gBug then all the reports merged with any of the
+ones listed will all be merged together.  Merger is like equality: it
+is reflexive, transitive and symmetric.
+<p>
+
+Merging reports causes a note to appear on each report's logs; on the
+WWW pages this is includes links to the other $gBugs.
+<p>
+
+Merged reports are all expired simultaneously, and only when all of
+the reports each separately meet the criteria for expiry.
+
+<dt><code>unmerge</code> <var>bugnumber</var>
+<dd>
+
+Disconnects a $gBug report from any other reports with which it may have
+been merged.  If the report listed is merged with several others then
+they are all left merged with each other; only their associations with
+the $gBug explicitly named are removed.
+<p>
+
+If many $gBug reports are merged and you wish to split them into two
+separate groups of merged reports you must unmerge each report in one
+of the new groups separately and then merge them into the required new
+group.
+<p>
+
+You can only unmerge one report with each <code>unmerge</code>
+command; if you want to disconnect more than one $gBug simply include
+several <code>unmerge</code> commands in your message.
+
+</dl>
+
+<hr>
+Other pages:
+<ul>
+<li><A href="./">$gBug tracking system main contents page.</A>
+<li><A href="Reporting.html">Instructions for reporting $gBugs.</A>
+<li><A href="Access.html">Accessing the $gBug tracking logs other than by WWW.</A>
+<li><A href="Developer.html">Developers'
+information regarding the $gBug processing system.</A>
+<li><A href="server-request.html">Fundamentals of the mailserver
+and commands for retrieving $gBugs.</A>
+<li><A href="server-refcard.html">Mailservers' reference card.</A>
+<li><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+<li><A href="db/ix/packages.html">Packages with $gBug reports.</A>
+<li><A href="db/ix/maintainers.html">Maintainers of packages with $gBug reports.</A>
+ $gHTMLOtherPageList
+</ul>
+
+$gHTMLTail
+
+HTML_END
diff --git a/html/server-refcard.html.in b/html/server-refcard.html.in
new file mode 100644 (file)
index 0000000..892e2e6
--- /dev/null
@@ -0,0 +1,90 @@
+$gRefcardHtml = <<HTML_END
+<html><head>
+<title>$gProject $gBug system - mail servers' reference card</title>
+<link rev="made" href="mailto:$gMaintainerEmail">
+</head><body>
+<h1>Mail servers' reference card</h1>
+
+Full documentation of the mail servers is available on the WWW, in the
+files
+<A href="server-request.html">bug-log-mailserver.txt</A> and
+<A href="server-control.html">bug-maint-mailcontrol.txt</A> or by
+sending the word <code>help</code> to each mailserver.
+
+<h2>Synopsis of commands available at <code>request@$gEmailDomain</code></h2>
+
+<ul compact>
+<li><code>send</code> <var>bugnumber</var>
+<li><code>send-detail</code> <var>bugnumber</var>
+<li><code>index</code> [<code>full</code>]
+<li><code>index-summary by-package</code>
+<li><code>index-summary by-number</code>
+<li><code>index-maint</code>
+<li><code>index maint</code> <var>maintainer-substring</var>
+<li><code>index-packages</code>
+<li><code>index packages</code> <var>package-substring</var>
+<li><code>send-unmatched</code> [<code>this</code>|<code>0</code>]
+<li><code>send-unmatched</code> <code>last</code>|<code>-1</code>
+<li><code>send-unmatched</code> <code>old</code>|<code>-2</code>
+<li><code>getinfo</code> <var>filename</var> <em>(see below)</em>
+<li><code>help</code>
+<li><code>refcard</code>
+<li><code>quit</code>|<code>stop</code>|<code>thank</code>...|<code>--</code>...
+<li><code>#</code>... <em>(comment)</em>
+<li><code>debug</code> <var>level</var>
+</ul>
+
+<h3>List of info files for <code>getinfo</code></h3>
+<ul compact>
+<li><code>maintainers</code>
+<li><code>override.stable</code>
+<li><code>override.development</code>
+<li><code>override.contrib</code>
+<li><code>override.non-free</code>
+<li><code>override.experimental</code>
+<li><code>override.</code><var>codeword</var>
+<li><code>pseudo-packages.description</code>
+<li><code>pseudo-packages.maintainers</code>
+</ul>
+
+<h2>Synopsis of extra commands available at control mailserver</h2>
+
+<ul compact>
+<li><code>close</code> <var>bugnumber</var>
+ <em>(you must separately tell originator why)</em>
+<li><code>reassign</code> <var>bugnumber</var> <var>package</var>
+<li><code>severity</code> <var>bugnumber</var> <var>severity</var>
+<li><code>reopen</code> <var>bugnumber</var>
+ [ <var>originator-address</var> | <code>=</code> | <code>!</code> ]
+<li><code>forwarded</code> <var>bugnumber</var> <var>address</var>
+<li><code>notforwarded</code> <var>bugnumber</var>
+<li><code>retitle</code> <var>bugnumber</var> <var>new-title</var>
+<li><code>merge</code> <var>bugnumber</var> <var>bugnumber</var> ...
+<li><code>unmerge</code> <var>bugnumber</var>
+</ul>
+<code>reopen</code> with <code>=</code> or no originator address leaves
+the originator as the original submitter; <code>!</code> sets it to
+you, the person doing the reopen.
+<p>
+
+$gHTMLSeverityDesc
+
+<hr>
+Other pages:
+<ul>
+<li><A href="./">$gBug tracking system main contents page.</A>
+<li><A href="server-request.html">Full documentation of the request mailserver.</A>
+<li><A href="server-control.html">Full documentation of the control mailserver.</A>
+<li><A href="Reporting.html">Instructions for reporting $gBugs.</A>
+<li><A href="Access.html">Accessing the $gBug tracking logs other than by WWW.</A>
+<li><A href="Developer.html">Developers'
+information regarding the $gBug processing system.</A>
+<li><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+<li><A href="db/ix/packages.html">Packages with $gBug reports.</A>
+<li><A href="db/ix/maintainers.html">Maintainers of packages with $gBug reports.</A>
+$gHTMLOtherPageList
+</ul>
+
+$gHTMLTail
+
+HTML_END
diff --git a/html/server-request.html.in b/html/server-request.html.in
new file mode 100644 (file)
index 0000000..7136cb3
--- /dev/null
@@ -0,0 +1,190 @@
+$gRequestHtml = <<HTML_END
+<html><head>
+<title>$gProject $gBug system - $gBug logs by mail server</title>
+<link rev="made" href="mailto:$gMaintainerEmail">
+</head><body>
+<A name="introduction">
+<h1>Introduction to the $gBug system request server</h1>
+</A>
+
+There is a mailserver which can send the $gBug reports and
+indices as plain text on request.
+<p>
+
+To use it you send a mail message to
+<A href="mailto:request\@$gEmailDomain"><code>request\@$gEmailDomain</code></A>.
+The <code>Subject</code> of the message is ignored, except
+for generating the <code>Subject</code> of the reply.
+<p>
+
+The body you send should be a series of commands, one per line.
+You'll receive a reply which looks like a transcript of your message
+being interpreted, with a response to each command.  No notifications
+are sent to anyone for most commands; however, the messages are logged
+and made available in the WWW pages.
+<p>
+
+Any text on a line starting with a hash sign <code>#</code> is
+ignored; the server will stop processing when it finds a line starting
+with <code>quit</code>, <code>stop</code>, <code>thank</code> or two
+hyphens (to avoid parsing a signature).  It will also stop if it
+encounters too many unrecognised or badly-formatted commands.  If no
+commands are successfully handled it will send the help text for the
+server.
+
+<h1>Commands available</h1>
+
+<dl>
+<dt><code>send</code> <var>bugnumber</var>
+<dt><code>send-detail</code> <var>bugnumber</var>
+<dd>
+
+Requests the transcript for the $gBug report in question.
+<code>send-detail</code> sends all of the `boring' messages in the
+transcript, such as the various auto-acks (you should usually use
+<code>send</code> as well, as the interesting messages are not sent by
+<code>send-detail</code>).
+
+<dt><code>index</code> [<code>full</code>]
+<dt><code>index-summary by-package</code>
+<dt><code>index-summary by-number</code>
+<dd>
+
+Request the full index (with full details, and including done and
+forwarded reports), or the summary sorted by package or by number,
+respectively.
+
+<dt><code>index-maint</code>
+<dd>
+
+Requests the index page giving the list of maintainers with $gBugs (open
+and recently-closed) in the tracking sytem.
+
+<dt><code>index maint</code> <var>maintainer</var>
+<dd>
+
+Requests the index pages of $gBugs in the system for all maintainers
+containing the string <var>maintainer</var>.  The search term is a
+case insensitive substring.  The $gBug index for each matching
+maintainer will be sent in a separate message.
+
+<dt><code>index-packages</code>
+<dd>
+
+Requests the index page giving the list of packages with $gBugs (open
+and recently-closed) in the tracking sytem.
+
+<dt><code>index packages</code> <var>package</var>
+<dd>
+
+Requests the index pages of $gBugs in the system for all packages
+containing the string <var>package</var>.  The search term is a case
+insensitive substring.  The $gBug index for each matching package will
+be sent in a separate message.
+
+<dt><code>send-unmatched</code> [<code>this</code>|<code>0</code>]
+<dt><code>send-unmatched</code> <code>last</code>|<code>-1</code>
+<dt><code>send-unmatched</code> <code>old</code>|<code>-2</code>
+<dd>
+
+Requests logs of messages not matched to a particular $gBug report, for
+this week, last week and the week before.  (Each week ends on a
+Wednesday.)
+
+<dt><code>getinfo</code> <var>filename</var>
+<dd>
+
+Request a file containing information about package(s) and or
+maintainer(s) - the files available are:
+<dl compact>
+<dt><code>maintainers</code>
+<dd>
+The unified list of packages' maintainers, as used by the tracking
+system.
+
+$gCreateMaintainers
+
+<!-- Override file quivilent information -->
+
+<dt><code>pseudo-packages.description</code>
+<dt><code>pseudo-packages.maintainers</code>
+<dd>
+List of descriptions and maintainers respectively for pseudo-packages.
+</dl>
+
+<dt><code>refcards</code>
+<dd>
+Requests that the mailservers' reference card be sent in plain ASCII.
+
+<dt><code>help</code>
+<dd>
+Requests that this help document be sent by email in plain ASCII.
+
+<dt><code>quit</code>
+<dt><code>stop</code>
+<dt><code>thank</code>...
+<dt><code>--</code>...
+<dd>
+
+Stops processing at this point of the message.  After this you may
+include any text you like, and it will be ignored.  You can use this
+to include longer comments than are suitable for <code>#</code>, for
+example for the benefit of human readers of your message (reading it
+via the tracking system logs or due to a <code>CC</code> or
+<code>BCC</code>).
+
+<dt><code>#</code>...
+<dd>
+
+One-line comment.  The <code>#</code> must be at the start of the
+line.
+
+<dt><code>debug</code> <var>level</var>
+<dd>
+
+Sets the debugging level to <var>level</var>, which should be a
+nonnegative integer.  0 is no debugging; 1 is usually sufficient.  The
+debugging output appears in the transcript.  It is not likely to be
+useful to general users of the $gBug system.
+
+</dl>
+
+There is a <A href="server-refcard.html">reference card</A> for the
+mailservers, available via the WWW, in
+<code>bug-mailserver-refcard.txt</code> or by email using the
+<code>refcard</code> command (see above).
+<p>
+
+If you wish to manipulate $gBug reports you should use the
+<code>control\@gEmailDomain</code> address, which understands a
+<A href="server-control.html">superset of the commands listed
+above</A>.  This is described in another document, available on the
+WWW</A>, in the file <code>bug-maint-mailcontrol.txt</code>, or by
+sending <code>help</code> to <code>control\@$gEmailDomain</code>.
+<p>
+
+In case you are reading this as a plain text file or via email: an
+HTML version is available via the $gBug system main contents page
+<code>http://$gWebDomain/</code>.
+<p>
+
+<hr>
+Other pages:
+<ul>
+<li><A href="./">$gBug tracking system main contents page.</A>
+<li><A href="Reporting.html">Instructions for reporting $gBugs.</A>
+<li><A href="Access.html">Accessing the $gBug tracking logs other than by WWW.</A>
+<li><A href="Developer.html">Developers'
+information regarding the $gBug processing system.</A>
+<li><A href="server-control.html">Developers'
+information - $gBug manipulation using the email control interface.</A>
+<li><A href="server-refcard.html">Mailservers' reference card.</A>
+<li><A href="db/ix/full.html">Full list of outstanding and recent $gBug reports.</A>
+<li><A href="db/ix/packages.html">Packages with $gBug reports.</A>
+<li><A href="db/ix/maintainers.html">Maintainers of packages with $gBug reports.</A>
+$gHTMLOtherPageList
+</ul>
+
+$gHTMLTail
+
+HTML_END
diff --git a/misc/Maintainers b/misc/Maintainers
new file mode 100644 (file)
index 0000000..2bb65d9
--- /dev/null
@@ -0,0 +1,2 @@
+sample                                 John Smith <gecko@benham.net>
+test                                   Mary Jane <gecko@benham.net>
diff --git a/misc/crontab.in b/misc/crontab.in
new file mode 100644 (file)
index 0000000..ebedc46
--- /dev/null
@@ -0,0 +1,10 @@
+# Example crontab for bugs system.  You can just install the crontab.out
+# version of this file if you like.
+DBC_CRONTAB_MAILTO
+DBC_PROCESS_FREQ       * * *   DBC_SCRIPT_PATH/processall >/dev/null
+DBC_HTMLCHECK_FREQ     * * *   DBC_SCRIPT_PATH/html-control >/dev/null
+22 7                   * * *   touch DBC_SPOOL_PATH/db
+23 7                   * * 3   DBC_SCRIPT_PATH/age-1
+24 7                   * * *   DBC_SCRIPT_PATH/expire >/dev/null
+23 16                  * * 5   DBC_SCRIPT_PATH/mailsummary undone >/dev/null
+23 16                  * * 2   DBC_SCRIPT_PATH/mailsummary bymaint >/dev/null
diff --git a/scripts/age-1.in b/scripts/age-1.in
new file mode 100755 (executable)
index 0000000..704f320
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -e
+cd /var/lib/debbugs/spool
+test -f ./-3.log && rm ./-3.log
+test -f ./-2.log && mv ./-2.log ./-3.log
+test -f ./-1.log && mv ./-1.log ./-2.log
+rm -f ../stamp.html
diff --git a/scripts/config.debian b/scripts/config.debian
new file mode 100644 (file)
index 0000000..83c141a
--- /dev/null
@@ -0,0 +1,65 @@
+#domains
+$gEmailDomain = "bugs.benham";         #bugs.debian.org
+$gListDomain = "lists.benham";         #lists.debian.org
+$gWebDomain = "localhost/Bugs";                        #www.debian.org/Bugs
+$gCGIDomain = "/Bugs/cgi";                     #cgi.debian.org
+$gMirrors = "";                                                #comma seperated list
+
+#Identification
+$gProject = "Benham";                                  #Debian
+$gProjectTitle = "Benham DebBug Test";         #Debian GNU/Linux
+
+#person responsible for this installation
+$gMaintainer = "owner";                                        #Ian Jackson
+$gMaintainerWebpage = "http://localhost/benham";                       #http://www.debian.org/~iwj
+$gMaintainerEmail = "root\@benham";                    #ownder@bugs.debian.org
+
+#directories
+#don't change location of dirs.  They are currently hardcoded.  Variables are
+#for future expantion.
+$gSpoolDir = "/var/lib/debbugs/spool"; #working directory
+$gIncomingDir = "incoming";                            #unprocessed emails
+$gWebDir = "/var/lib/debbugs/www";             #base location of web pages
+$gDocDir = "/var/lib/debbugs/www/txt";         #location of doc files
+
+#data files
+$gMaintainerFile = "/etc/debbugs/Maintainers";
+$gPseudoDescFile = "/etc/debbugs/pseudo-packages.description";
+
+#lists
+$gSubmitList = "submit.list";                  #debian-bugs-dist@lists
+$gMaintList = "maint.list";                            #
+$gQuietList = "quiet.list";                            #
+$gFowardList = "foward.list";                  #debian-bugs-fowarded@lists
+$gDoneList = "done.list";                              #debian-bugs-closed@lists
+$gRequestList = "request.list";
+$gSubmitterList = "submitter.list";
+$gControlList = "control.list";
+$gMirrorList = "mirrors.list";          #sends to all mirrors
+
+#config
+$gMailer='exim';
+$gBug='bug';
+$gBugs='bugs';
+$gRemoveAge = 28;                                              #days
+$gDefaultSeverity = 'normal';
+@gStrongSeverities= ('critical','grave');
+@gSeverityList= ('critical','grave','','wishlist');
+%gSeverityDisplay=('critical',"Critical $gBugs",
+                                       'grave',"Grave $gBugs",
+                                       'normal',"Normal $gBugs",,
+                                       'wishlist','Wishlist items');
+
+$gTextInstructions = "Instructions are available from ftp.debian.org 
+and at all Debian mirror sites, in the files:
+   debian/doc/bug-reporting.txt
+   debian/doc/bug-log-access.txt
+   debian/doc/bug-maint-info.txt";
+
+
+
+
+
+
+#dont change
+$gBounceFroms = "^mailer|^da?emon|^post.*mast|^root|^wpuser|^mmdf|^smt.*|\\$emd|^mrgate|^vmmail|^mail.*system|^uucp|-maiser-|^mal\@|^mail.*agent|^tcpmail|^bitmail|^mailman";
diff --git a/scripts/config.in b/scripts/config.in
new file mode 100644 (file)
index 0000000..034e53f
--- /dev/null
@@ -0,0 +1,66 @@
+#domains
+$gEmailDomain = "bugs.benham";         #bugs.debian.org
+$gListDomain = "lists.benham";         #lists.debian.org
+$gWebDomain = "localhost/Bugs";                        #www.debian.org/Bugs
+$gDBPath = "Reports";
+$gCGIDomain = "/Bugs/cgi";                     #cgi.debian.org
+$gMirrors = "";                                                #comma seperated list
+
+#Identification
+$gProject = "Benham";                                  #Debian
+$gProjectTitle = "Benham DebBug Test";         #Debian GNU/Linux
+
+#person responsible for this installation
+$gMaintainer = "owner";                                        #Ian Jackson
+$gMaintainerWebpage = "http://localhost/benham";                       #http://www.debian.org/~iwj
+$gMaintainerEmail = "root\@benham";                    #ownder@bugs.debian.org
+
+#directories
+#don't change location of dirs.  They are currently hardcoded.  Variables are
+#for future expantion.
+$gSpoolDir = "/var/lib/debbugs/spool"; #working directory
+$gIncomingDir = "incoming";                            #unprocessed emails
+$gWebDir = "/var/lib/debbugs/www";             #base location of web pages
+$gDocDir = "/var/lib/debbugs/www/txt";         #location of doc files
+
+#data files
+$gMaintainerFile = "/etc/debbugs/Maintainers";
+$gPseudoDescFile = "/etc/debbugs/pseudo-packages.description";
+
+#lists
+$gSubmitList = "submit.list";                  #debian-bugs-dist@lists
+$gMaintList = "maint.list";                            #
+$gQuietList = "quiet.list";                            #
+$gFowardList = "foward.list";                  #debian-bugs-fowarded@lists
+$gDoneList = "done.list";                              #debian-bugs-closed@lists
+$gRequestList = "request.list";
+$gSubmitterList = "submitter.list";
+$gControlList = "control.list";
+$gMirrorList = "mirrors.list";          #sends to all mirrors
+
+#config
+$gMailer='exim';                                               #valid: exim, qmail and sendmail
+$gBug='bug';
+$gBugs='bugs';
+$gRemoveAge = 28;                                              #days
+$gDefaultSeverity = 'normal';
+@gStrongSeverities= ('critical','grave');
+@gSeverityList= ('critical','grave','','wishlist');
+%gSeverityDisplay=('critical',"Critical $gBugs",
+                                       'grave',"Grave $gBugs",
+                                       'normal',"Normal $gBugs",,
+                                       'wishlist','Wishlist items');
+
+$gTextInstructions = "Instructions are available from ftp.debian.org 
+and at all Debian mirror sites, in the files:
+   debian/doc/bug-reporting.txt
+   debian/doc/bug-log-access.txt
+   debian/doc/bug-maint-info.txt";
+
+
+
+
+
+
+#dont change
+$gBounceFroms = "^mailer|^da?emon|^post.*mast|^root|^wpuser|^mmdf|^smt.*|\\$emd|^mrgate|^vmmail|^mail.*system|^uucp|-maiser-|^mal\@|^mail.*agent|^tcpmail|^bitmail|^mailman";
diff --git a/scripts/config.in.default b/scripts/config.in.default
new file mode 100644 (file)
index 0000000..8a5be18
--- /dev/null
@@ -0,0 +1,55 @@
+#domains
+$gEmailDomain = "bugs.top.domain";             #bugs.debian.org
+$gListDomain = "lists.top.domain";             #lists.debian.org
+$gWebDomain = "www.top.domain";                        #www.debian.org/Bugs
+$gCGIDomain = "cgi.top.domain";                        #cgi.debian.org
+
+#Identification
+$gProject = "project";                                 #Debian
+$gProjectTitle = "project title";              #Debian GNU/Linux
+
+#person responsible for this installation
+$gMaintainer = "name";                                 #Ian Jackson
+$gMaintainerWebpage = "url";                   #http://www.debian.org/~iwj
+$gMaintainerEmail = "address";                 #ownder@bugs.debian.org
+
+#directories
+$gSpoolDir = "/var/lib/debbugs/spool"; #working directory
+$gIncomingDir = "incoming";                            #unprocessed emails
+$gWebDir = "/var/lib/debbugs/www";             #base location of web pages
+$gDocDir = "/usr/lib/debbugs";                 #location of doc files
+
+#data files
+$gMaintainerFile = "/etc/debbugs/Maintainers";
+$gPseudoDescFile = "/etc/debbugs/pseudo-packages.description";
+
+#lists
+$gSubmitList = "submit.list";                  #debian-bugs-dist@lists
+$gMaintList = "maint.list";                            #
+$gQuietList = "quiet.list";                            #
+$gFowardList = "foward.list";                  #debian-bugs-fowarded@lists
+$gDoneList = "done.list";                              #debian-bugs-closed@lists
+$gRequestList = "request.list";
+$gSubmitterList = "submitter.list";
+$gControlList = "control.list";
+$gMirrorList = "mirrors.list";          #sends to all mirrors
+
+#config
+$gMailer='exim';
+$gRemoveAge = 28;                                              #days
+$gDefaultSeverity = 'normal';
+@gStrongSeverities= ('critical','grave');
+@gSeverityList= ('critical','grave','','wishlist');
+%gSeverityDisplay=('critical','Critical bugs',
+                                       'grave','Grave bugs',
+                                       'normal','Normal bugs',
+                                       'wishlist','Wishlist items');
+
+
+
+
+
+
+
+#dont change
+$gBounceFroms = "^mailer|^da?emon|^post.*mast|^root|^wpuser|^mmdf|^smt.*|\\$emd|^mrgate|^vmmail|^mail.*system|^uucp|-maiser-|^mal\@|^mail.*agent|^tcpmail|^bitmail|^mailman";
diff --git a/scripts/db2html.in b/scripts/db2html.in
new file mode 100755 (executable)
index 0000000..938f57f
--- /dev/null
@@ -0,0 +1,638 @@
+#!/usr/bin/perl
+# $Id: db2html.in,v 1.1 1999/09/02 19:25:01 gecko Exp $
+# usage: db2html [-diff] [-stampfile=<stampfile>] [-lastrun=<days>] <wwwbase>
+
+require('/etc/debbugs/config');
+require('/etc/debbugs/text');
+require('/usr/lib/debbugs/errorlib');
+$ENV{'PATH'}= '/usr/lib/debbugs'.$ENV{'PATH'};
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+#push(@INC,'/usr/lib/debbugs');
+
+chop($dtime=`date -u '+%H:%M:%S GMT %a %d %h'`); $? and die $?;
+
+%displayshowpendings= ('pending','outstanding',
+                       'done','resolved',
+                       'forwarded','forwarded to upstream software authors');
+
+$diff=0;
+$stampfile= 'stamp.html';
+$tail_html= $gHTMLTail; $tail_html =~ s/SUBSTITUTE_DTIME/$dtime/;
+$expirynote_html= $gHTMLExpireNote;
+
+while (@ARGV && $ARGV[0] =~ m/^-/) {
+    if ($ARGV[0] eq '-diff') { $diff=1; }
+    elsif ($ARGV[0] =~ m/^-lastrun\=([0-9.]+)$/) { $lastrun= $1; undef $stampfile; }
+    elsif ($ARGV[0] =~ m/^-full$/) { undef $lastrun; undef $stampfile; }
+    elsif ($ARGV[0] =~ m/^-stampfile\=(\S+)$/) { $stampfile= $1; }
+    else { &quit("bad usage"); }
+    shift;
+}
+
+@ARGV==1 or die;
+$wwwbase= shift(@ARGV);
+
+defined($startdate= time) || &quit("failed to get time: $!");
+
+$|=1;
+
+if (defined($stampfile)) {
+    if (open(X,"< $stampfile")) {
+        $lastrun= -M X;
+        close(X);
+        printf "progress last run %.7f days\n",$lastrun;
+    } else {
+        print "progress stamp file $stampfile: $! - full\n";
+    }
+}
+
+if (defined($lastrun) && -M "db" > $lastrun) {
+    $_= $gHTMLStamp;
+    s/SUBSTITUTE_DTIME/$dtime/o;
+    s/\<\!\-\-updateupdate\-\-\>.*\<\!\-\-\/updateupdate\-\-\>/check/;
+    &file('ix/zstamp.html','non',$_."</body></html>\n");
+    print "noremoves\n";
+    exit 0;
+}
+
+open(MM,"$gMaintainerFile") || &quit("open $gMaintainerFile: $!");
+while(<MM>) {
+    m/^(\S+)\s+(\S.*\S)\s*$/ || &quit("$gMaintainerFile: \`$_'");
+    ($a,$b)=($1,$2);
+    $a =~ y/A-Z/a-z/;
+    $maintainer{$a}= $b;
+}
+close(MM);
+
+opendir(D,'db') || &quit("opendir db: $!");
+@files= sort { $a <=> $b } readdir(D);
+closedir(D);
+
+$shorthead=' Ref   Package    Keywords/Subject                    Submitter';
+$shortindex=''; $amonths=-1;
+$indexunmatched='';
+for $pending (qw(pending done forwarded)) {
+    for $severity (@showseverities) {
+        eval "\$index${pending}${severity}= \$iiindex${pending}${severity}= ''; 1;"
+            or &quit("reset \$index${pending}${severity}: $@");
+    }
+}
+
+for $f (@files) {
+    next unless $f =~ m/^(-?\d+)\.log$/;
+    $ref= $1;
+#((print STDERR "$ref\n"),
+#next
+#)
+# unless $ref =~ m/^-/ || $ref =~ m/^124/;
+    &filelock("lock/$ref");
+    $preserveonly= defined($lastrun) && -M "db/$ref.log" > $lastrun;
+    if ($ref =~ m/^-\d$/) {
+        $week= $ref eq '-1' ? 'this week' :
+               $ref eq '-2' ? 'last week' :
+               $ref eq '-3' ? 'two weeks ago' :
+                              ($ref-1)." weeks ago";
+        $linkto= "ju/unmatched$ref";
+        $short= "junk, $week";
+        $descriptivehead=
+            "This includes messages sent to <code>done\@$gEmailDomain</code>\n".
+            "which did not have a $gBug reference number in the Subject line\n".
+            "or which contained an\n".
+            "unknown or out of date $gBug report number (these cause a warning\n".
+            "to be sent to the sender) and details about the messages\n".
+            "sent to <code>request@$gEmailDomain</code> (all of which".
+            "produce replies).\n";
+        $indexlink= "Messages not matched to a specific $gBug report - $week";
+        $s_subject= '';
+        $indexentry= '';
+        undef $tpack;
+        undef $tmaint;
+        undef $iiref;
+        $tpackfile= "pnone.html";
+        $indexpart= 'unmatched';
+    } else {
+        open(S,"db/$ref.status") || &quit("open db/$ref.status: $!");
+        chomp($s_originator= <S>);
+        chomp($s_date= <S>);
+        chomp($s_subject= <S>);
+        chomp($s_msgid= <S>);
+        chomp($s_package= <S>);
+        chomp($s_keywords= <S>);
+        chomp($s_done= <S>);
+        chomp($s_forwarded= <S>);
+        chomp($s_mergedwith= <S>);
+        chomp($s_severity= <S>);
+        $_= $s_package; y/A-Z/a-z/; $_= $` if m/[^-+._a-z0-9()]/;
+        $tpack= $_;
+        if ($s_severity eq '' || $s_severity eq 'normal') {
+            $showseverity= '';
+            $addseverity= $gDefaultSeverity;
+        } elsif (grep($s_severity eq $_, @strongseverities)) {
+            $showseverity= "<strong>Severity: $s_severity</strong>;\n";
+            $addseverity= $s_severity;
+        } else {
+            $showseverity= "Severity: <em>$s_severity</em>;\n";
+            $addseverity= $s_severity;
+        }
+        $days= int(($startdate - $s_date)/86400); close(S);
+        $indexlink= "#$ref: ".&sani($s_subject);
+        $indexentry= '';
+        $packfile= length($tpack) ? "pa/l$tpack.html" : "pa/none.html";
+        $indexentry .= "Package: <A href=\"../$packfile\"><strong>".
+                        &sani($s_package)."</strong></A>;\n"
+            if length($s_package);
+        $indexentry .= $showseverity;
+        $indexentry .= "Reported by: ".&sani($s_originator);
+        $indexentry .= ";\nKeywords: ".&sani($s_keywords)
+            if length($s_keywords);
+        $linkto= $ref; $linkto =~ s,^..,$&/$&,;
+        @merged= split(/ /,$s_mergedwith);
+        if (@merged) {
+            $mseparator= ";\nmerged with ";
+            for $m (@merged) {
+                $mfile= $m; $mfile =~ s,^..,$&/$&,;
+                $indexentry .= $mseparator."<A href=\"../$mfile.html\">#$m</A>";
+                $mseparator= ",\n";
+            }
+        }
+        $daysold=$submitted='';
+        if (length($s_done)) {
+            $indexentry .= ";\n<strong>Done:</strong> ".&sani($s_done);
+            $indexpart= "done$addseverity";
+        } elsif (length($s_forwarded)) {
+            $indexentry .= ";\n<strong>Forwarded</strong> to ".&sani($s_forwarded);
+            $indexpart= "forwarded$addseverity";
+        } else {
+            $cmonths= int($days/30);
+            if ($cmonths != $amonths) {
+        $msg= $cmonths == 0 ? "Submitted in the last month" :
+        $cmonths == 1 ? "Over one month old" :
+        $cmonths == 2 ? "Over two months old - attention is required" :
+        "OVER $cmonths MONTHS OLD - ATTENTION IS REQUIRED";
+                $shortindex .= "</pre><h2>$msg:</h2><pre>\n$shorthead\n";
+                $amonths= $cmonths;
+            }
+            $pad= 6-length(sprintf("%d",$f));
+            $thissient=
+                ($pad>0 ? ' 'x$pad : '').
+                sprintf("<A href=\"../%s.html\">%d</A>",$linkto,$ref).
+                &sani(sprintf(" %-10.10s %-35.35s %-.25s\n",
+                        $s_package,
+                        (length($s_keywords) ? $s_keywords.'/' : '').
+                        $s_subject, $s_originator));
+            $shortindex.= $thissient;
+            $sient{"$ref $s_package"}= $thissient;
+            if ($days >= 7) {
+                $font= $days <= 30 ? '' :
+                       $days <= 60 ? 'em' :
+                                     'strong';
+                $efont= length($font) ? "</$font>" : '';
+                $font= length($font) ? "<$font>" : '';
+                $daysold= "; $font$days days old$efont";
+            }
+            if ($preserveonly) {
+                $submitted= 'THIS IS A BUG IN THE BUG PROCESSOR';
+            } else {
+                $submitted= `TZ=GMT LANG=C \\
+                             date -d '1 Jan 1970 00:00:00 + $s_date seconds' \\
+                                     '+ %a, %d %b %Y %T %Z'`;
+                $? and die $?;
+            }
+            $submitted =~ s/\n$//; $submitted =~ s/, 0/, /g;
+            $submitted= "; dated $submitted";
+            $indexpart= "pending$addseverity";
+        }
+        $iiref= $ref;
+        $short= $ref; $short =~ s/^\d+/#$&/;
+        $tmaint= defined($maintainer{$tpack}) ? $maintainer{$tpack} : '(unknown)';
+        $qpackage= &sani($_);
+        $descriptivehead= $indexentry.$submitted.";\nMaintainer for $qpackage is\n".
+            '<A href="../ma/l'.&maintencoded($tmaint).'.html">'.&sani($tmaint).'</A>.';
+        $indexentry .= $daysold;
+        $indexentry .= ".";
+    }
+    $indexadd='';
+    $indexadd .= "<!--iid $iiref-->" if defined($iiref);
+    $indexadd .= "<li><A href=\"../$linkto.html\">".$indexlink."</A>";
+    $indexadd .=  "<br>\n".$indexentry if length($indexentry);
+    $indexadd .= "<!--/iid-->" if defined($iiref);
+    $indexadd .= "\n";
+    $estr= "\$index$indexpart = \$indexadd.\$index$indexpart; 1;";
+    eval($estr) || &quit("eval add to \$index$indexpart ($estr) failed: $@");
+#print STDERR ">$estr|$indexadd<\n";
+    $indexadd= "<!--ii $iiref-->\n" if defined($iiref);
+    eval("\$iiindex$indexpart = \$indexadd.\$iiindex$indexpart; 1;") ||
+        &quit("eval add to \$iiindex$indexpart failed: $@");
+    if (defined($tmaint)) {
+        $countpermaint{$tmaint} += length($s_done) ? 0 : length($s_forwarded) ? 0 : 1;
+        eval("\$permaint${indexpart}{\$tmaint} .= \$indexadd; 1;") ||
+            &quit("eval add to \$permaint${indexpart}{\$tmaint} failed: $@");
+    }
+    if (defined($tpack)) {
+        $countperpack{$tpack} += length($s_done) ? 0 : length($s_forwarded) ? 0 : 1;
+        eval("\$perpack${indexpart}{\$tpack} .= \$indexadd; 1;") ||
+            &quit("eval add to \$perpack${indexpart}{\$tpack} failed: $@");
+    }
+    if ($preserveonly) {
+        &preserve("$linkto.html"); &preserve("$linkto-b.html"); &unfilelock; next;
+    }
+    open(L,"db/$ref.log") || &quit("open db/$ref.log: $!");
+    $log='';
+    $boring=''; $xmessage= 0;
+    $normstate= 'kill-init';
+    $suppressnext= 0;
+    while(<L>) {
+        if (m/^\07$/) {
+            $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+                &quit("$ref ^G in state $normstate");
+            $normstate= 'incoming-recv';
+        } elsif (m/^\01$/) {
+            $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+                &quit("$ref ^A in state $normstate");
+            $normstate= 'autocheck';
+        } elsif (m/^\02$/) {
+            $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+                &quit("$ref ^B in state $normstate");
+            $normstate= 'recips';
+        } elsif (m/^\03$/) {
+            $normstate eq 'go' || $normstate eq 'go-nox' || $normstate eq 'html' ||
+                &quit("$ref ^C in state $normstate");
+            $this .= "</pre>\n" if $normstate eq 'go' || $normstate eq 'go-nox';
+            if ($normstate eq 'html') {
+                $xmessage++;
+                $this .= "  <em><A href=\"../$linkto-b.html#m$xmessage\">Full text</A>".
+                         " available.</em>";
+            }
+            if ($suppressnext && $normstate ne 'html') {
+                $ntis= $this; $ntis =~ s:\<pre\>:</A><pre>:i;
+                $boring .= "<hr><A name=\"m$xmessage\">\n$ntis\n";
+            } else {
+                $log = $this. "<hr>\n". $log;
+            }
+            $suppressnext= $normstate eq 'html';
+            $normstate= 'kill-end';
+        } elsif (m/^\05$/) {
+            $normstate eq 'kill-body' || &quit("^E in state $normstate");
+            $this .= "<pre>\n";
+            $normstate= 'go';
+        } elsif (m/^\06$/) {
+            $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+                &quit("$ref ^F in state $normstate");
+            $normstate= 'html'; $this= '';
+        } elsif ($normstate eq 'incoming-recv') {
+            $pl= $_; $pl =~ s/\n+$//;
+            m/^Received: \(at (\S+)\) by (\S+)\;/ ||
+                &quit("bad line \`$pl' in state incoming-recv");
+            $this = "<h2>Message received at ".&sani("$1\@$2").":</h2><br>\n".
+                    "<pre>\n".
+                    "$_";
+            $normstate= 'go';
+        } elsif ($normstate eq 'html') {
+            $this .= $_;
+        } elsif ($normstate eq 'go') {
+            $this .= &sani($_);
+        } elsif ($normstate eq 'go-nox') {
+            next if !s/^X//;
+            $this .= &sani($_);
+        } elsif ($normstate eq 'recips') {
+            if (m/^-t$/) {
+                $this = "<h2>Message sent:</h2><br>\n";
+            } else {
+                s/\04/, /g; s/\n$//;
+                $this = "<h2>Message sent to ".&sani($_).":</h2><br>\n";
+            }
+            $normstate= 'kill-body';
+        } elsif ($normstate eq 'autocheck') {
+            next if !m/^X-Debian-Bugs(-\w+)?: This is an autoforward from (\S+)/;
+            $normstate= 'autowait';
+            $this = "<h2>Message received at $2:</h2><br>\n";
+        } elsif ($normstate eq 'autowait') {
+            next if !m/^$/;
+            $normstate= 'go-nox';
+            $this .= "<pre>\n";
+        } else {
+            &quit("$ref state $normstate line \`$_'");
+        }
+    }
+    &quit("$ref state $normstate at end") unless $normstate eq 'kill-end';
+    close(L);
+    if (length($boring)) {
+        &file("$linkto-b.html",'non',
+              "<html><head><title>$gProject $gBug report logs - ".
+              "$short, boring messages</title>\n".
+              "<link rev=\"made\" href=\"mailto:$gMaintainerEmail)\">\n".
+              "</head><body><h1>$gProject $gBugreport logs -".
+              "\n <A href=\"../$linkto.html\">$short</A>,".
+              " boring messages</h1>\n$boring\n<hr>\n".
+              $tail_html."</body></html>\n");
+    }
+    &file("$linkto.html",'non',
+          "<html><head><title>$gProject $gBug report logs - ".
+          "$short</title>\n".
+          "<link rev=\"made\" href=\"mailto:$gMaintainerEmail)\">\n".
+          "</head><body><h1>$gProject) $gBug report logs -  $short<br>\n".
+          &sani($s_subject)."</h1>".
+          "$descriptivehead\n".
+          "\n<hr>\n".
+          $log.
+          $tail_html."</body></html>\n");
+    &unfilelock;
+}
+
+sub maintsort {
+    $_= $_[0];
+    s/([^<>()]+) \(([^()<>]+)\)/$2 \<$1\>/;
+    
+    s/\s+/ /g;
+    s/^\s*//;
+    $email= s/ *\<[^<>()]+\>$//g ? $& : '';
+    $_= "$1 $_" if s/ (\S+)$//;
+    $_.= $email;
+    $_;
+}
+
+sub maintencoded {
+    return $maintencoded{$_[0]} if defined($maintencoded{$_[0]});
+    local ($input)= @_;
+    local ($todo,$encoded)= ($input);
+    while ($todo =~ m/\W/) {
+        $encoded.=$`.sprintf("-%02x_",unpack("C",$&));
+        $todo= $';
+    }
+    $encoded.= $todo;
+    $encoded =~ s/-2e_/\./g;
+    $encoded =~ s/^([^,]+)-20_-3c_(.*)-40_(.*)-3e_/$1,$2,$3,/;
+    $encoded =~ s/^(.*)-40_(.*)-20_-28_([^,]+)-29_$/,$1,$2,$3/;
+    $encoded =~ s/-20_/_/g;
+    $encoded =~ s/-([^_]+)_-/-$1/g;
+    $maintencoded{$input}= $encoded;
+}
+
+for $tmaint (keys %countpermaint) {
+    $_= $tmaint;
+    $after=$before=$sort2d=$sort2s=$sort1d=$sort1s='';
+    $after= "$&$after" if s/\s*\<[^<>()]+\>\s*$//;
+    $after= "$&$after" if s/\s*\)\s*$//;
+    $after= "$&$after" if s/\s*,.*$//;
+    $before.= $& if s/^.*\(\s*//;
+    $sort2d= $& if s/\S+$//;
+    $sort1d= $_;
+    while (s/^([^()<>]+)\. */$1 /) { };
+    s/\s+$//; y/A-Za-z/a-zA-Z/; $sort1s= $_;
+    $sort2s= $sort2d; $sort2s =~ y/A-Za-z/a-zA-Z/;
+    $maintsort{$tmaint}= $sort2s.' '.$sort1s.' '.$before.$sort1d.$sort2d.$after;
+    $maintdisplay{$tmaint}=
+        &sani($before).'<strong>'.&sani($sort1d.$sort2d).'</strong>'.&sani($after);
+}
+
+sub heading ($$) {
+    my ($pt,$sv) = @_;
+    return $displayshowseverities{$sv}.' - '.$displayshowpendings{$pt};
+}
+
+sub makeindex ($$$) {
+    my ($varprefix,$varsuffix,$tkey) = @_;
+    my ($pending,$severity,$anydone,$text);
+    $anydone= 0;
+    $text= '';
+    for $pending (qw(pending forwarded done)) {
+        for $severity (@showseverities) {
+            $estr= "\$value= \\${varprefix}${pending}${severity}${varsuffix}; 1;";
+#print STDERR $estr;
+            eval $estr
+                or &quit("eval get \$${varprefix}${pending}${severity} failed: $@");
+#print STDERR ">$$value<\n";
+            next unless length($$value);
+            $text.= "<hr>\n<h2>".&heading($pending,$severity).":</h2>\n".
+                    "(List of <A href=\"../si/$pending$severity.html\">all".
+                    " such $gBugs</A> is available.)\n<ul>\n".
+                    $$value.
+                    "</ul>\n";
+            $anydone=1 if $pending eq 'done';
+        }
+    }
+    $text.= $expirynote_html if $anydone;
+    return $text;
+}        
+
+&file("ix/full.html",'def',
+      $gFullIndex.
+      makeindex('$index',"",'').
+      "<hr>\n".
+      $tail_html."</body><html>\n");
+
+&file("ju/junk.html",'non',
+      $gJunkIndex.
+      "<hr>\n<h2>Junk (messages without a specific $gBug report number):</h2>\n".
+      "(\`this week' is everything since last Wednesday.)\n<ul>\n".
+      $indexunmatched.
+      "</ul><hr>\n".
+      $tail_html."</body><html>\n");
+
+$nobugs_html= "No reports are currently in this state.";
+$who_html= $gProject;
+$owner_addr= $gMaintainerEmail;
+$otherindex_html= "For other kinds of index or for other information about
+$gProject and the $gBug system, see the <A HREF\"../../\">$gBug system top-level
+contents WWW page</A>.
+
+";
+
+for $pending (qw(pending forwarded done)) {
+    for $severity (@showseverities) {
+        eval "\$value= \\\$iiindex${pending}${severity}; 1;"
+            or &quit("eval get \$iiindex${pendingtype}${severity} failed: $@");
+        $value= \$nobugs_html if !length($$value);
+        $headstring= &heading($pending,$severity);
+        &file("si/$pending$severity.html",'ref',
+              "<html><head><title>$who_html $gBug reports: $headstring</title>\n".
+              "<link rev=\"made\" href=\"mailto:".&sani($owner_addr)."\">\n".
+              "</head><body><h1>$who_html $gBug reports: $headstring</h1>\n".
+              $otherindex_html.
+              ($pending eq 'done' ? "<P>\n$expirynote_html" : '').
+              "<hr>\n".
+              $$value.
+              "<hr>\n".
+              $tail_html."</body></html>\n");
+    }
+}
+
+sub individualindexes ($\@&\%&&$$$$$&&) {
+    my ($filename,$keysref,$getfilenameref,$countref,$getdisplayref,
+        $getsimpledisplayref,$what,$caveat,$whatplural,$abbrev,$ihead,
+        $getxinforef,$getxindexref) = @_;
+    my ($itext,$i,$tkey,$sani,$count,$tfilename,$refto,$backnext,$xitext,$bugbugs);
+    $itext='';
+    for ($i=0; $i<=$#$keysref; $i++) {
+        $tkey= $$keysref[$i];
+        $tfilename= &$getfilenameref($tkey);
+        $sani= &$getsimpledisplayref($tkey);
+        $count= $$countref{$tkey};
+        $count= $count >= 1 ? "$count" : "no";
+        $bugbugs= $count == 1 ? "$gBug" : "$gBugs";
+        $xitext= &$getxindexref($tkey);
+        $xitext= length($xitext) ? "$count $bugbugs; $xitext"
+                                 : "$count outstanding $bugbugs";
+        $itext .= "<li><A href=\"../$tfilename\">".&$getdisplayref($tkey)."</A>"."\n".
+                  "  ($xitext)\n";
+        $backnext= '';
+        if ($i>0) {
+            $refto= $$keysref[$i-1];
+            $xitext= &$getxindexref($refto);
+            $xitext= " ($xitext)" if length($xitext);
+            $backnext .= "<br>\nPrevious $what in list, <A href=\"../".
+                         &$getfilenameref($refto)."\">".&$getdisplayref($refto)."</A>".
+                         "$xitext\n";
+        }
+        if ($i<$#$keysref) {
+            $refto= $$keysref[$i+1];
+            $xitext= &$getxindexref($refto);
+            $xitext= " ($xitext)" if length($xitext);
+            $backnext .= "<br>\nNext $what in list, <A href=\"../".
+                         &$getfilenameref($refto)."\">".&$getdisplayref($refto)."</A>".
+                         "$xitext\n";
+        }
+        &file($tfilename,'ref',
+              "<html><head><title>$gProject $gBug reports: $what $sani</title>\n".
+              "<link rev=\"made\" href=\"mailto:$gMaintainerEmail\">\n".
+              "</head><body><h1>$gProject $gBug reports: $what $sani</h1>\n".
+              &$getxinforef($tkey).
+              $caveat.
+              "See the <A href=\"../$filename\">listing of $whatplural</A>.\n".
+              $backnext.
+              &makeindex("\$per${abbrev}","{\$tkey}",$tkey).
+              "<hr>\n".
+              $tail_html."</body></html>\n");
+    }
+    &file($filename,'non',
+          $ihead.
+          "<hr><ul>\n".
+          $itext.
+          "</ul><hr>\n".
+          $tail_html."</body></html>\n");
+}
+
+@maintainers= sort { $maintsort{$a} cmp $maintsort{$b}; } keys %countpermaint;
+individualindexes('ix/maintainers.html',
+                  @maintainers,
+                  sub { 'ma/l'.&maintencoded($_[0]).'.html'; },
+                  %countpermaint,
+                  sub { $maintdisplay{$_[0]}; },
+                  sub { &sani($_[0]); },
+                  'maintainer',
+                  "Note that there may be other reports filed under different
+                                 variations on the maintainer\'s name and email address.<P>",
+                  'maintainers',
+                  'maint',
+                  $gMaintIndex,
+                  sub { return ''; },
+                  sub { return ''; });
+
+@packages= sort keys %countperpack;
+individualindexes('ix/packages.html',
+                  @packages,
+                  sub { length($_[0]) ? "pa/l$_[0].html" : 'pa/none.html'; },
+                  %countperpack,
+                  sub { length($_[0]) ? $_[0] : 'not specified'; },
+                  sub { &sani(length($_[0]) ? $_[0] : 'not specified'); },
+                  'package',
+                  "Note that with multi-binary packages there may be other
+                                 reports filed under the different binary package names.<P>",
+                  'packages',
+                  'pack',
+                  $gPackageIndex,
+                  sub {
+                      return unless defined($maintainer{$_[0]});
+                      $tmaint= $maintainer{$_[0]};
+                      return "Maintainer for $_[0] is <A href=\"../ma/l".
+                             &maintencoded($tmaint).
+                             ".html\">".&sani($tmaint)."</A>.\n<p>\n";
+                  },
+                  sub {
+                      return unless defined($maintainer{$_[0]});
+                      $tmaint= $maintainer{$_[0]};
+                      return "<A href=\"../ma/l".
+                             &maintencoded($tmaint).
+                             ".html\">".&sani($tmaint)."</A>";
+                  });
+
+&file('ix/summary.html','non',
+      $gSummaryIndex.
+      "<hr><pre>\n".
+      $shortindex.
+      "</pre><hr>\n".
+      $tail_html."</body></html>\n");
+
+$bypackageindex='';
+for $k (map {$_->[0] }
+       sort { $a->[2] cmp $b->[2]  ||  $a->[1] <=> $b->[1] }
+       map { [$_, split(' ',$_,2)] } keys %sient)
+    { $bypackageindex.= $sient{$k}; }
+&file('ix/psummary.html','non',
+      $gPackageLog.
+      "<hr><pre>\n$shorthead\n".
+      $bypackageindex.
+      "</pre><hr>\n".
+      $tail_html."</body></html>\n");
+
+open(P,"$gPseudoDescFile") ||
+    &quit("$gPseudoDescFile: $!");
+$ppd=''; while(<P>) { s/\s*\n$//; $ppd.= &sani($_)."\n"; } close(P);
+&file('ix/pseudopackages.html','non',
+      $gPseudoIndex.
+      "<hr><pre>\n$ppd".
+      "</pre><hr>\n".
+      $tail_html."</body></html>\n");
+
+$_= $gHTMLStamp; s/SUBSTITUTE_DTIME/$dtime/o;
+
+&file('ix/zstamp.html','non',$_."</body></html>\n");
+
+sub notimestamp ($) {
+    $_= $_[0];
+    s/\<\!\-\-timestamp\-\-\>\n.*\n\<\!\-\-\/timestamp\-\-\>\n//;
+    return $_;
+}
+
+sub file {
+    local ($name,$ii,$file)= @_;
+    if ($diff) {
+        $cmppath= "$wwwbase/$name".($ii eq 'ref' ? '.ref' : '');
+        if (open(ORIG,"$cmppath")) {
+            undef $/; $orig= <ORIG>; $/= "\n";
+            close(ORIG);
+            if (&notimestamp($orig) eq &notimestamp($file)) {
+               print "preserve $name\n";
+               return;
+           }
+            defined($c= open(P,"-|")) or &quit("pipe/fork for diff: $!");
+            if (!$c) {
+                open(Q,"|diff -e $cmppath -") or die "pipe/fork II for diff: $!\n";
+                print Q $file or die "write orig to diff: $!\n";
+                close(Q); $?==0 || $?==256 or die "diff gave $?\n";
+                exit($?>>8);
+            }
+            undef $/; $difftxt= <P>; $/= "\n";
+            close(P); $?==0 || $?==256 or die "diff fork gave $?\n";
+            if ($?==0) {
+                print "preserve $name\n";
+                return;
+            }
+            $v= (split(/\n/,$difftxt));
+            print "diff $v $ii $name\n${difftxt}thatdiff $name\n"
+                or &quit("stdout (diff): $!");
+            return;
+        }
+    } 
+    $v= (split(/\n/,$file));
+    print "file $v $ii $name\n${file}thatfile $name\n" or &quit("stdout: $!");
+}
+
+sub preserve {
+    print "preserve $_[0]\n";
+}
+
+print "end\n";
+
+while ($u= $cleanups[$#cleanups]) { &$u; }
+exit 0;
diff --git a/scripts/errorlib.in b/scripts/errorlib.in
new file mode 100755 (executable)
index 0000000..3c36796
--- /dev/null
@@ -0,0 +1,104 @@
+# -*- perl -*-
+
+sub F_SETLK { 6; } sub F_WRLCK{ 1; }
+$flockstruct= 'sslll'; # And there ought to be something for this too.
+
+sub unlockreadbugmerge {
+    local ($rv) = @_;
+    &unfilelock if $rv >= 2;
+    &unfilelock if $rv >= 1;
+}
+
+sub lockreadbugmerge {
+    local ($lref) = @_;
+    if (!&lockreadbug($lref)) { return 0; }
+    if (!length($s_mergedwith)) { return 1; }
+    &unfilelock;
+    &filelock('lock/merge');
+    if (!&lockreadbug($lref)) { &unfilelock; return 0; }
+    return 2;
+}
+
+sub lockreadbug {
+    local ($lref) = @_;
+    &filelock("lock/$lref");
+    if (!open(S,"db/$lref.status")) { &unfilelock; return 0; }
+    chop($s_originator= <S>);
+    chop($s_date= <S>);
+    chop($s_subject= <S>);
+    chop($s_msgid= <S>);
+    chop($s_package= <S>);
+    chop($s_keywords= <S>);
+    chop($s_done= <S>);
+    chop($s_forwarded= <S>);
+    chop($s_mergedwith= <S>);
+    chop($s_severity= <S>);
+    close(S);
+    return 1;
+}
+
+sub filelock {
+    # NB - NOT COMPATIBLE WITH `with-lock'
+    local ($lockfile,$flockpushno,$evalstring,$count,$errors,@s1,@s2) = @_;
+    $flockpushno= $#filelocks+1;
+    $count= 10; $errors= '';
+    for (;;) {
+        $evalstring= "
+            open(FLOCK${flockpushno},\"> \$lockfile\") || die \"open: \$!\";
+            \$flockwant= pack(\$flockstruct,&F_WRLCK,0,0,1,0);".
+                ($] >= 5.000 ? "
+            fcntl(FLOCK$flockpushno,&F_SETLK,\$flockwant) || die \"setlk: \$!\";" : "
+            \$z= syscall(&SYS_fcntl,fileno(FLOCK$flockpushno),&F_SETLK,\$flockwant) < 0
+                 && die \"syscall fcntl setlk: \$!\";") ."
+            (\@s1= lstat(\$lockfile)) || die \"lstat: \$!\";
+            (\@s2= stat(FLOCK$flockpushno)) || die \"fstat: \$!\";
+            join(',',\@s1) eq join(',',\@s2) || die \"file switched\";
+            1;
+        ";
+        last if eval $evalstring;
+        $errors .= $@;
+        eval "close(FLOCK$flockpushno);";
+        if (--$count <=0) {
+            $errors =~ s/\n+$//;
+            &quit("failed to get lock on file $lockfile: $errors // $evalstring");
+        }
+        sleep 10;
+    }
+    push(@cleanups,'unfilelock');
+    push(@filelocks,$lockfile);
+}
+
+sub unfilelock {
+    local ($lockfile) = pop(@filelocks);
+    pop(@cleanups);
+    eval 'close(FLOCK'.($#filelocks+1).');' || warn "failed to close lock file: $!";
+    unlink($lockfile) || warn "failed to remove lock file: $!";
+}
+
+sub quit {
+    print DEBUG "quitting >$_[0]<\n";
+    local ($u);
+    while ($u= $cleanups[$#cleanups]) { &$u; }
+    die "*** $_[0]\n";
+}
+
+%saniarray= ('<','lt', '>','gt', '&','amp', '"','quot');
+
+sub sani {
+    local ($in) = @_;
+    local ($out);
+    while ($in =~ m/[<>&"]/) {
+        $out.= $`. '&'. $saniarray{$&}. ';';
+        $in=$';
+    }
+    $out.= $in;
+    $out;
+}
+
+@severities= @gSeverityList;
+@showseverities= @severities;
+grep ($_= $_ eq '' ? $gDefaultSeverity : $_, @showseverities);
+@strongseverities= @gStrongSeverities;
+%displayshowseverities= %gSeverityDisplay;
+
+1;
diff --git a/scripts/expire.in b/scripts/expire.in
new file mode 100755 (executable)
index 0000000..c8da4dd
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+require('/etc/debbugs/config');
+require('/usr/lib/debbugs/errorlib');
+$ENV{'PATH'}= '/usr/lib/debbugs'.$ENV{'PATH'};
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+#push(@INC,'/usr/lib/debbugs');
+
+#open(DEBUG,">&4");
+
+defined($startdate= time) || &quit("failed to get time: $!");
+
+opendir(DIR,"db") || &quit("opendir db: $!\n");
+@list= grep(m/^\d+\.status$/,readdir(DIR));
+grep(s/\.status$//,@list);
+@list= sort { $a <=> $b } @list;
+
+while (length($ref=shift(@list))) {
+#print DEBUG "$ref $considering\n";
+    $bfound= &lockreadbugmerge($ref);
+#print DEBUG "$ref read $bfound\n";
+    $bfound || next;
+#print DEBUG "$ref read ok (done $s_done)\n";
+    (&unlockreadbugmerge($bfound), next) unless length($s_done);
+#print DEBUG "$ref read done\n";
+    @aref= ($ref);
+    if (length($s_mergedwith)) { push(@aref,split/ /,$s_mergedwith); }
+#print DEBUG "$ref aref @aref\n";
+    $oktoremove= 1;
+    for $mref (@aref) {
+#print DEBUG "$ref $mref check\n";
+        if ($mref != $ref) {
+#print DEBUG "$ref $mref reading\n";
+            &lockreadbug($mref) || die "huh ?";
+#print DEBUG "$ref $mref read ok\n";
+            $bfound++;
+        }
+#print DEBUG "$ref $mref read/not\n";
+        $expectmerge= join(' ',grep($_ != $mref, sort { $a <=> $b } @aref));
+        $s_mergedwith eq $expectmerge ||
+            die "$ref -> $mref: ($s_mergedwith) vs. ($expectmerge) (@aref)";
+#print DEBUG "$ref $mref merge-ok\n";
+        length($s_done) || die "$ref -> $mref";
+#print DEBUG "$ref $mref done-ok\n";
+        $days= -M "db/$mref.log";
+#print DEBUG "$ref $mref days $days\n";
+        if ($days <= $gRemoveAge) {
+#print DEBUG "$ref $mref saved\n";
+            $oktoremove= 0;
+        }
+    }
+    if ($oktoremove) {
+#print DEBUG "$ref removing\n";
+        for $mref (@aref) {
+#print DEBUG "$ref removing $mref\n";
+            unlink("db/$mref.log", "db/$mref.status", "db/$mref.report");
+            print("deleted $mref (from $ref)\n") || &quit("output old: $!");
+        }
+    }
+#print DEBUG "$ref unlocking $bfound\n";
+    for ($i=0; $i<$bfound; $i++) { &unfilelock; }
+#print DEBUG "$ref unlocking done\n";
+}
+
+close(STDOUT) || &quit("close stdout: $!");
diff --git a/scripts/html-control.in b/scripts/html-control.in
new file mode 100755 (executable)
index 0000000..3e0a538
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/perl
+
+use POSIX;
+
+require '/etc/debbugs/config';
+require '/usr/lib/debbugs/errorlib';
+$ENV{'PATH'}= '/usr/lib/debbugs'.$ENV{'PATH'};
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+#push(@INC,'/usr/lib/debbugs');
+
+&filelock("html.fcntl-lock");
+
+unlink("html-data.gz") || $!==&ENOENT or &quit("remove html-data.gz: $!");
+
+sub nonawful ($) {
+    rename("stamp.html.run","stamp.html") or warn "warning: put back stamp.html: $!";
+    &quit($_[0]);
+}
+
+if (open(US,'updateseqs') && -f 'stamp.html') {
+    chop($lastmain=<US>);
+    chop($lastsub=<US>);
+    close(US);
+
+    $lastsub++;
+    $args= "-diff -stampfile=stamp.html.run";
+    rename("stamp.html","stamp.html.run") or &quit("rename stamp.html: $!");
+} else {
+    $lastsub=0;
+    chop($lastmain=`TZ=GMT date '+%Y%m%d%H%M%S'`);
+    $args= '-full';
+    unlink('stamp.html') || $!==&ENOENT or &quit("excise stale stamp.html: $!");
+}
+
+open(X,">stamp.html.new") or &quit("stamp.html.new: $!");
+close(X) or &quit("close stamp.html.new: $!");
+
+open(US,'>updateseqs.new') || &quit("create updateseqs.new: $!");
+print(US "$lastmain\n$lastsub\n") || &quit("write updateseqs.new: $!");
+close(US) || &quit("close updateseqs.new: $!");
+rename('updateseqs.new','updateseqs') or nonawful("install updateseqs: $!");
+
+sub runshell ($&) {
+    my ($cmd,$errhref) = @_;
+    print "xx $cmd\n";
+    system $cmd;
+    !$? && !length($stderr) or &$errhref("$cmd failed - gave $? / $stderr");
+}
+
+$sequences="$lastmain $lastsub";
+$seqmid= $sequences; $seqmid =~ y/ /-/;
+open(MM,">html-data.mail") or nonawful("open html-data.mail: $!");
+if ( length( $gListDomain ) > 0 && length( $gMirrorList ) > 0 ) {
+print(MM <<END
+From: $gMaintainerEmail ($gMaintainer)
+To: $gMirrorList\@$gListDomain
+Subject: $gProject $gBugs autoupdate 259012
+Message-ID: <handle.htmlup.$seqmid\@gEmailDebian>
+X-$gProject=PR: update $sequences
+
+END
+      ) or nonawful("write html-data.mail header: $!");
+} else {
+print(MM <<END
+From: $gMaintainerEmail ($gMaintainer)
+To: $gMaintainerEmail
+Subject: $gProject $gBugs autoupdate 259012
+Message-ID: <handle.htmlup.$seqmid\@gEmailDebian>
+X-$gProject=PR: update $sequences
+
+END
+      ) or nonawful("write html-data.mail header: $!");
+}
+close(MM) or nonawful("close html-data.mail: $!");
+
+runshell("/usr/lib/debbugs/db2html $args 2>&1 >html-data $gWebDir/db",
+         sub { &nonawful; });
+runshell("/usr/lib/debbugs/html-install $gWebDir/db <html-data 2>&1",sub { &quit; });
+runshell("gzip -9 html-data 2>&1",sub { &quit; });
+#runshell("btoa 2>&1 <html-data.gz >>html-data.mail",sub { &quit; });
+#runshell('2>&1 '.join(' ',('/usr/lib/sendmail','-f'."$gMaintainerEmail")).' -oem -oi -t <html-data.mail',
+#         sub { &quit; });
+
+rename("stamp.html.new","stamp.html") or &quit("install new stamp.html: $!");
+
+unlink("html-data.gz") or warn "remove html-data.gz: $!";
+unlink("html-data.mail") or warn "remove html-data.mail: $!";
+unlink("stamp.html.run") || $!==&ENOENT or warn "remove stamp.html.run: $!";
+
+print "sequences $lastmain $lastsub\n";
+
+&unfilelock();
+exit(0);
diff --git a/scripts/html-install.in b/scripts/html-install.in
new file mode 100755 (executable)
index 0000000..9211c60
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/perl
+# Takes 1 argument - directory tree to install into
+# Tree _must_ be synch'd with one used by db2html to generate file
+
+use POSIX;
+require( '/etc/debbugs/config' );
+
+$dirtree= shift(@ARGV);
+defined($dirtree) or die 'usage';
+chdir $dirtree or die $!;
+
+$filenamere= '[0-9a-z]{2}/[0-9a-z][-+_:,.0-9a-zA-Z]*';
+
+opendir(D,".") or die " opendir: $!";
+while ($dir=readdir(D)) {
+    next if $dir =~ m/^\.\.?$/;
+    if (-f $dir) {
+        $remove{$dir}= 1;
+    } else {
+        opendir(E,"$dir") or die " opendir $dir: $!";
+        while ($_=readdir(E)) {
+            next if $_ =~ m/^\.\.?$/;
+            $remove{"$dir/$_"}= 1;
+        }
+        closedir(E) or die " closedir $dir: $!";
+        $rmdir{$dir}= 1;
+    }
+}
+closedir(D) or die " closedir: $!";
+
+while(<>) {
+    chomp;
+    if (m/^end$/) {
+       print "end, removing\n";
+        for $k (keys %remove) { unlink($k) || $!==&ENOENT or die "$k: $!"; }
+        for $k (keys %rmdir) { rmdir($k) || $!==&ENOTEMPTY || $!==EEXIST or die "$k: $!"; }
+        exit 0;
+    } elsif (s/^progress //) {
+        y/-+:._!#=,0-9a-zA-Z //cd;
+        print " progress $_\n";
+    } elsif (m/^preserve ($filenamere)$/o) {
+        delete $remove{$1};
+        delete $remove{"$1.ref"};
+        print " preserve $1\n";
+    } elsif (m/^(file|diff) (\d+) (ref|def|non) ($filenamere)$/o) {
+        $filediff= $1; $linestodo= $2; $ii= $3; $file= $4;
+        print " $filediff $ii $file\n";
+        delete $remove{$file};
+        delete $remove{"$file.ref"} if $ii eq 'ref';
+        $file =~ m,^(..)/, or die $file;
+        mkdir($1,0777) || $!==EEXIST or die $!;
+        $tranfile= $file;
+        $tranfile.= '.ref' if $ii eq 'ref';
+        open(DT,"> recv.tmp") or die $!;
+        if ($filediff eq 'diff') { print DT "r $tranfile\n" or die $!; }
+        $indata= 0;
+        while ($linestodo--) {
+            $z=<STDIN>;
+            if ($filediff eq 'diff') {
+                if ($indata) { $indata=0 if $incmd && m/^\.$/; }
+                elsif ($z =~ m/^[0-9,]+[ac]/) { $indata= 1; }
+                elsif ($z !~ m/^[0-9,]+[ds]/) { die "SECURITY $file >$z<"; }
+            }
+            print DT $z or die $!;
+        }
+        if ($filediff eq 'diff') { print DT "w new.tmp\nq\n" or die $!; }
+        close(DT) or die $!;
+        ($z=<STDIN>) eq "that$filediff $file\n" or die die "not confirmed >$z<";
+        if ($filediff eq 'diff') {
+            $q= `ed -s <recv.tmp 2>&1`;
+            length($q) || $? and die "ed $q $?";
+            rename("new.tmp","$tranfile") or die "$tranfile $!";
+            unlink("recv.tmp") or die $!;
+        } else {
+            rename("recv.tmp","$tranfile") or die "$tranfile $!";
+        }
+        if ($ii eq 'ref') {
+            open(I,"$tranfile") or die $!;
+            open(O,"> ref.tmp") or die $!;
+            while (<I>) {
+                if (m/^\<\!\-\-ii (\d+)\-\-\>$/) {
+                    defined($iival{$1}) or die "$tranfile $1";
+                    print O $iival{$1} or die $!;
+                } else {
+                    print O or die $!;
+                }
+            }
+            close(I) or die $!;
+            close(O) or die $!;
+            rename("ref.tmp","$file") or die $!;
+        } elsif ($ii eq 'def') {
+            open(I,"$file") or die $!;
+            undef $cdef; $ctext= '';
+            while (<I>) {
+                if (s/^\<\!\-\-iid (\d+)\-\-\>//) {
+                    defined($cdef) and die $file;
+                    $cdef= $1;
+                    $ctext= $_;
+                } elsif (s/\<\!\-\-\/iid\-\-\>\n$//) {
+                    defined($cdef) or die $file;
+                    $iival{$cdef}= $ctext.$_."\n";
+                    $ctext=''; undef $cdef;
+                } else {
+                    $ctext.= $_ if defined($cdef);
+                }
+            }
+        }
+    } elsif (m/^noremoves$/) {
+       print "noremoves\n";
+        exit 0;
+    } else {
+        die " huh ? $_";
+    }
+}
+
+die "eof $!";
diff --git a/scripts/mailsummary.in b/scripts/mailsummary.in
new file mode 100755 (executable)
index 0000000..eca80a3
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+require( '/etc/debbugs/config' );
+
+$ENV{'PATH'}= '/usr/lib/debbugs'.$ENV{'PATH'};
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+
+#open(DEBUG,">&4");
+
+if ($ARGV[0] eq 'undone') {
+    $vdef= "(no outstanding $gBug reports on file, or problem running script)\n";
+    $subject= "Unanswered problem reports by date";
+    $intro=
+"The following problem reports have not yet been marked as `taken up\' by a
+message to done\@$gEmailDomain or or `forwarded\' by a
+message to fowarded\@$gEmailDomain."
+    ;
+} elsif ($ARGV[0] eq 'bymaint') {
+    $vdef= "(no outstanding $gBug reports on file, or problem running script)\n";
+    $subject= "Unanswered problem reports by maintainer and package";
+    $intro=
+"The following problem reports have not yet been marked as `taken up\' by a
+message to done\@$gEmailDomain or or `forwarded\' by a
+message to forwarded\@$gEmailDomain.
+The maintainer listed against each package is derived from the Maintainer
+field of the package found in the development tree; there is an override file
+that can be amended to get the right results if you have taken over a package
+and do not expect to issue a new version soon.
+
+Variant versions of the Maintainer field for the same actual package
+maintainer will be listed separately.
+
+Maintainers with few outstanding $gBug appear first, to avoid those with few
+$gBugs being lost deep in the message.
+"
+    ;
+} elsif ($ARGV[0] eq 'veryold') {
+    $vdef= '';
+    $subject= "Overdue problem reports by age";
+    $intro=
+"The following problem reports are very old but have not yet been marked
+as `taken up\' by a message to done\@$gEmailDomain as forwarded
+to a developer by CCing a message to fowarded\@$gEmailDomain.
+Please help ensure that these $gBugs are dealt with quickly, even if you
+are not the package maintainer in question.  (NB a full list of outstanding
+$gBug reports is posted periodically - this is a partial list only!)
+"
+} else {
+    die "urgk, wrong argument @ARGV";
+}
+
+$v=`/usr/lib/debbugs/summary $ARGV[0]`; $? && die "undone failed $?: $!\n";
+
+$v= $vdef if $v eq '';
+exit 0 if $v eq '';
+
+open(D, '| '.join(' ',('/usr/lib/sendmail','-f'.$gMaintainerEmail)).' -odi -oem -oi -t') ||
+    die "start sendmail: $!";
+
+print D <<END || die "complete sendmail";
+From: $gMaintainerEmail ($gMaintainer)
+To: submit\@$gListDomain
+Subject: $subject
+
+$intro
+$v
+Every Tuesday, the listing by package maintainer is posted.
+Every Frideay, the listing by age of the report is posted.
+
+Please see the documentation for more information about how to
+use the $gBug tracking system.  It is available on the WWW at
+<A HREF=\"http://$gWebUrl/txt/\">$gWebUrl/txt</A>
+END
+
+close(D);
+$? && die "sendmail failed $?: $!\n";
+
+print length($v)," bytes of summary posted.\n";
diff --git a/scripts/process.in b/scripts/process.in
new file mode 100755 (executable)
index 0000000..68ad5df
--- /dev/null
@@ -0,0 +1,837 @@
+#!/usr/bin/perl
+#
+# Usage: process nn
+# Temps:  incoming/Pnn
+
+use Mail::Address;
+require( '/etc/debbugs/config' );
+require( '/usr/lib/debbugs/errorlib' );
+chdir( "$gSpoolDir" ) || die 'chdir spool: $!\n';
+@showseverities=();
+
+#open(DEBUG,"> /tmp/debbugs.debug");
+
+defined( $intdate= time ) || &quit( "failed to get time: $!" );
+
+$_=shift;
+m/^([BMQFDU])(\d*)\.\d+$/ || &quit("bad argument");
+$codeletter= $1;
+$tryref= length($2) ? $2+0 : -1;
+$nn= $_;
+
+if (!rename("incoming/G$nn","incoming/P$nn")) {
+    $_=$!.'';  m/no such file or directory/i && exit 0;
+    &quit("renaming to lock: $!");
+}    
+
+$baddress= 'bugs' if $codeletter eq 'B';
+$baddress= 'maintonly' if $codeletter eq 'M';
+$baddress= 'quiet' if $codeletter eq 'Q';
+$baddress= 'forwarded' if $codeletter eq 'F';
+$baddress= 'done' if $codeletter eq 'D';
+$baddress= 'submitter' if $codeletter eq 'U';
+$baddress || &quit("bad codeletter $codeletter");
+$baddressroot= $baddress;
+$baddress= "$tryref-$baddress" if $tryref>=0;
+
+open(M,"incoming/P$nn");
+@log=<M>;
+close(M);
+
+@msg=@log;
+grep(s/\n+$//,@msg);
+
+print DEBUG "###\n",join("##\n",@msg),"\n###\n";
+
+chop($tdate= `date -u '+%a, %d %h 19%y %T GMT'`);
+$fwd= <<END;
+X-Loop: $gMaintainerEmail
+Received: via spool by $baddress\@$gEmailDomain id=$nn
+          (code $codeletter ref $tryref); $tdate
+END
+
+for ($i=0; $i<=$#msg; $i++) {
+    $_ = $msg[$i];
+    last unless length($_);
+    &quit("looping detected") if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
+    $ins= !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
+       && !m/^From / && !m/^X-$gProjct-Message:/i && !m/^received:/i;
+    $fwd .= $_."\n" if $ins;
+    while ($msg[$i+1] =~ m/^\s/) {
+        $i++;
+        $fwd .= $msg[$i]."\n" if $ins;
+        $_ .= ' '.$msg[$i];
+    }
+# print DEBUG ">$_<\n";
+    if (s/^(\S+):\s*//) {
+        $v= $1; $v =~ y/A-Z/a-z/;
+print DEBUG ">$v=$_<\n";
+        $header{$v}= $_;
+    } else {
+print DEBUG "!>$_<\n";
+    }
+}
+
+while ($i <= $#msg && !length($msg[$i])) { $fwd .= "\n"; $i++; }
+
+while ($msg[$i] =~ m/^(\w+):\s*/) {
+    $fn=$1; $fv = $';
+print DEBUG ">$fn|$'|\n";
+    $fwd .= $fn.': '.$fv."\n";
+    while ($msg[++$i] =~ m/^\s/) { $fwd .= $msg[$i]."\n"; $fv .= ' '.$msg[$i]; }
+    $fn =~ y/A-Z/a-z/;
+    $pheader{$fn}= $fv;
+print DEBUG ">$fn~$fv<\n";
+}
+
+$fwd .= join("\n",@msg[$i..$#msg]);
+
+print DEBUG "***\n$fwd\n***\n";
+
+defined($header{'from'}) || &quit("no From header");
+$replyto= defined($header{'reply-to'}) ? $header{'reply-to'} : $header{'from'};
+
+$_= $replyto;
+$_= "$2 <$1>" if m/^([^\<\> \t\n\(\)]+) \(([^\(\)\<\>]+)\)$/;
+$replytocompare= $_;
+print DEBUG "replytocompare >$replytocompare<\n";
+    
+if (!defined($header{'subject'})) {
+    $brokenness.= <<END;
+
+Your message did not contain a Subject field.  This is broken, I am
+afraid - the Subject: line is a Required Header according to RFC822.
+Please remember to include a Subject field in your messages in future.
+If you did so the fact that it got lost probably indicates a poorly
+configured mail system at your site or an intervening one.
+END
+    $subject= '(no subject)';
+} else {
+    $subject= $header{'subject'};
+}
+
+$ref=-1;
+$subject =~ s/^Re:\s*//i; $_= $subject."\n";
+if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
+    $tryref= $1+0;
+}
+if ($tryref >= 0) {
+    $bfound= &lockreadbugmerge($tryref);
+    if ($bfound) {
+       $ref= $tryref;
+    } else {
+               &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
+        &sendmessage(<<END, '');
+From: $gMaintainerEmail ($Maintainer)
+To: $replyto
+Subject: Unknown problem report $gBug#$tryref ($subject)
+Message-ID: <handler.x.$nn.unknown\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'} $s_msgid
+X-$gProject-PR-Message: error
+
+You sent a message to the $gBug tracking system which gave (in the
+Subject line or encoded into the recipient at $gEmailDomain),
+the number of a nonexistent $gBug report (#$tryref).
+
+This may be because that $gBug report has been resolved for more than $gRemoveAge
+days, and the record of it has been expunged, or because you mistyped
+the $gBug report number.
+
+Your message was dated $header{'date'} and was sent to
+$baddress\@$gEmailDomain.  It had
+Message-ID $header{'message-id'}
+and Subject $subject.
+
+It has been filed (under junk) but otherwise ignored.
+
+Please consult your records to find the correct $gBug report number, or
+contact me, the system administrator, for assistance.
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+
+(NB: If you are a system administrator and have no idea what I am
+talking about this indicates a serious mail system misconfiguration
+somewhere.  Please contact me immediately.)
+
+END
+               &appendlog;
+        &finish;
+    }
+} else {
+    &filelock('lock/-1');
+}
+
+if ($codeletter eq 'D' || $codeletter eq 'F') {
+    if ($replyto =~ m/$gBounceFroms/o ||
+       $header{'from'} =~ m/$gBounceFroms/o) {
+               &quit("bounce detected !  Mwaap! Mwaap!");
+    }
+    $markedby= $header{'from'} eq $replyto ? $replyto :
+               "$header{'from'} (reply to $replyto)";
+    if ($codeletter eq 'F') {
+        (&appendlog,&finish) if length($s_forwarded);
+        $receivedat= "forwarded\@$gEmailDomain";
+        $markaswhat= 'forwarded';
+        $set_forwarded= $header{'to'};
+               if ( length( $gListDomain ) > 0 && length( $gFowardList ) > 0 ) {
+               $generalcc= "$gFowardList\@$gListDomain";
+               } else {
+                       $generalcc='';
+               }
+    } else {
+        (&appendlog,&finish) if length($s_done);
+        $receivedat= "done\@$gEmailDomain";
+        $markaswhat= 'done';
+        $set_done= $header{'from'};
+               if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
+               $generalcc= "$gDoneList\@$gListDomain";
+               } else {
+                       $generalcc='';
+               }
+    }
+    if ($ref<0) {
+        &htmllog("Warning","sent",$replyto,"Message ignored.");
+        &sendmessage(<<END, '');
+From: $gMaintainerEmail
+To: $replyto
+Subject: Message with no $gBug number ignored by $receivedat
+         ($subject)
+Message-ID: <header.x.$nn.warnignore\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'} $s_msgid
+X-$gProject-PR-Message: error
+
+You sent a message to the $gProject $gBug tracking system old-style
+unified mark as $markaswhat address ($receivedat),
+without a recognisable $gBug number in the Subject.
+Your message has been filed under junk but otherwise ignored.
+
+If you don't know what I'm talking about then probably either:
+
+(a) you unwittingly sent a message to done\@$gEmailDomain
+because you replied to all recipients of the message a developer used
+to mark a $gBug as done and you modified the Subject.  In this case,
+please do not be alarmed.  To avoid confusion do not do it again, but
+there is no need to apologise or mail anyone asking for an explanation.
+
+(b) you are a system administrator, reading this because the $gBug 
+tracking system is responding to a misdirected bounce message.  In this
+case there is a serious mail system misconfiguration somewhere - please
+contact me immediately.
+
+Your message was dated $header{'date'} and had
+message-id $header{'message-id'}
+and subject $subject.
+
+If you need any assistance or explanation please contact me.
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+
+END
+               &appendlog;
+               &finish;
+    }
+    &checkmaintainers;
+    $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs));
+    $noticeccval =~ s/\s+\n\s+/ /g; $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
+    if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; }
+       if (length($generalcc)) { $noticecc.= "Bcc: $generalcc\n"; }
+    @process= ($ref,split(/ /,$s_mergedwith));
+    $orgref= $ref;
+    for $ref (@process) {
+       if ($ref != $orgref) {
+           &unfilelock;
+           &lockreadbug($ref) || die "huh ? $ref from $orgref out of @process";
+       }
+        $s_done= $set_done if defined($set_done);
+        $s_forwarded= $set_forwarded if defined($set_forwarded);
+               &overwrite("db/$ref.status",
+                  "$s_originator\n$s_date\n$s_subject\n$s_msgid\n".
+                   "$s_package\n$s_keywords\n$s_done\n$s_forwarded\n$s_mergedwith\n$s_severity\n");
+        open(O,"db/$ref.report") || &quit("read original report: $!");
+        $x= join('',<O>); close(O);
+        if ($codeletter eq 'F') {
+            &htmllog("Reply","sent",$replyto,"You have marked $gBug as forwarded.");
+            &sendmessage(<<END.$x, '');
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+${noticecc}Subject: $gBug#$ref: marked as forwarded ($s_subject)
+Message-ID: <header.$ref.$nn.ackfwdd\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'} $s_msgid
+X-$gProject-PR-Message: forwarded $ref
+
+Your message dated $header{'date'}
+with message-id $header{'message-id'}
+and subject line $subject
+has caused the $gProject $gBug report #$ref,
+regarding $s_subject
+to be marked as having been forwarded to the upstream software
+author(s) $s_forwarded.
+
+(NB: If you are a system administrator and have no idea what I am
+talking about this indicates a serious mail system misconfiguration
+somewhere.  Please contact me immediately.)
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+
+END
+        } else {    
+            &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
+            &sendmessage(<<END.$x, '');
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+${noticecc}Subject: $gBug#$ref: marked as done ($s_subject)
+Message-ID: <handler.$ref.$nn.ackdone\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'} $s_msgid
+X-$gProject-PR-Message: closed $ref
+
+Your message dated $header{'date'}
+with message-id $header{'message-id'}
+and subject line $subject
+has caused the attached $gBug report to be marked as done.
+
+This means that you claim that the problem has been dealt with.
+If this is not the case it is now your responsibility to reopen the
+$gBug report if necessary, and/or fix the problem forthwith.
+
+(NB: If you are a system administrator and have no idea what I am
+talking about this indicates a serious mail system misconfiguration
+somewhere.  Please contact me immediately.)
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+
+END
+            &htmllog("Notification","sent",$s_originator,
+                    "$gBug acknowledged by developer.");
+            &sendmessage(<<END.join("\n",@msg),'');
+From: $gMaintainerEmail ($gMaintainer)
+To: $s_originator
+Subject: $gBug#$ref acknowledged by developer ($s_subject)
+Message-ID: <handler.$ref.$nn.notifdone\@$gEmailDomain>
+In-Reply-To: $s_msgid
+References: $header{'message-id'} $s_msgid
+X-$gProject-PR-Message: they-closed $ref
+
+This is an automatic notification regarding your $gBug report.
+
+It has been closed by one of the developers, namely
+$markedby.
+
+Their explanation is attached below.  If this explanation is
+unsatisfactory and you have not received a better one in a separate
+message then please contact the developer directly, or email
+submit\@$gEmailDomain or me.
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+
+END
+        }
+       &appendlog;
+    }
+    &finish;
+}
+
+if ($ref<0) {
+    if ($codeletter eq 'U') {
+        &htmllog("Warning","sent",$replyto,"Message not forwarded.");
+        &sendmessage(<<END, '');
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: Message with no $gBug number cannot be sent to submitter !
+         ($subject)
+Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'} $s_msgid
+X-$gProject-PR-Message: error
+
+You sent a message to the $gProject $gBug tracking system send to $gBug 
+report submitter address $baddress\@$gEmailDomain, without a
+recognisable $gBug number in the Subject.  Your message has been filed
+under junk but otherwise ignored.
+
+If you don't know what I'm talking about then probably either:
+
+(a) you unwittingly sent a message to $baddress\@$gEmailDomain
+because you replied to all recipients of the message a developer sent
+to a $gBug's submitter and you modified the Subject.  In this case,
+please do not be alarmed.  To avoid confusion don't do it again, but
+there is no need to apologise or mail anyone asking for an
+explanation.
+
+(b) you are a system administrator, reading this because the $gBug 
+tracking system is responding to a misdirected bounce message.  In this
+case there is a serious mail system misconfiguration somewhere - please
+contact me immediately.
+
+Your message was dated $header{'date'} and had
+message-id $header{'message-id'}
+and subject $subject.
+
+If you need any assistance or explanation please contact me.
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+
+END
+       &appendlog;
+       &finish;
+    }
+    if (!defined($pheader{'package'})) {
+        $brokenness.= <<END;
+
+Your message didn't have a Package: line at the start (in the
+pseudo-header following the real mail header), or didn't have a
+psuedo-header at all.
+
+This makes it much harder for us to categorise and deal with your
+problem report; please ensure that you say which package(s) and
+version(s) the problem is with next time.  Some time in the future the
+problem reports system may start rejecting such messages.
+END
+    } else {
+        $s_package= $pheader{'package'};
+    }
+    if (defined($pheader{'keywords'})) {
+        $s_keywords= $pheader{'keywords'};
+    }
+    $s_severity= '';
+    if (defined($pheader{'severity'})) {
+        $s_severity= $pheader{'severity'};
+       if (!grep($_ eq $s_severity, @severities, "$gDefaultSeverity")) {
+            $brokenness.= <<END;
+
+Your message specified a Severity: in the psuedo-header, but
+the severity value $s_severity was not recognised.
+The default severity $gDefaultSeverity is being used instead.
+The recognised values are: @showseverities.
+END
+            $s_severity= '';
+        }
+    }
+    &filelock("nextnumber.lock");
+    open(N,"nextnumber") || &quit("nextnumber: read: $!");
+    $v=<N>; $v =~ s/\n$// || &quit("nextnumber bad format");
+    $ref= $v+0;  $v += 1;  $newref=1;
+    &overwrite('nextnumber', "$v\n");
+    &unfilelock;
+    &overwrite("db/$ref.log",'');
+    &overwrite("db/$ref.status",
+               "$replyto\n$intdate\n$subject\n$header{'message-id'}\n".
+               "$s_package\n$s_keywords\n\n\n\n$s_severity\n");
+    &overwrite("db/$ref.report",
+               join("\n",@msg)."\n");
+}
+
+&checkmaintainers;
+
+print DEBUG "maintainers >@maintaddrs<\n";
+
+$orgsender= defined($header{'sender'}) ? "Orignal-Sender: $header{'sender'}\n" : '';
+$newsubject= $subject;  $newsubject =~ s/^$gBug#$ref\W*\s*//;
+
+$xcchdr= $header{dbc_xcc_hdr};
+if ($xcchdr =~ m/\S/) {
+    push(@resentccs,$xcchdr);
+    $resentccexplain.= <<END;
+
+As you requested using X-$gProject-CC, your message was also forwarded to
+   $xcchdr
+(after having been given a $gBug report number, if it did not have one).
+END
+}
+
+if (@maintaddrs && ($codeletter eq 'B' || $codeletter eq 'M')) {
+    push(@resentccs,@maintaddrs);
+    $resentccexplain.= <<END." ".join("\n ",@maintaddrs)."\n";
+
+Your message has been sent to the package maintainer(s):
+END
+}
+
+$veryquiet= $codeletter eq 'Q';
+if ($codeletter eq 'M' && !@maintaddrs) {
+    $veryquiet= 1;
+    $brokenness.= <<END;
+
+You requested that the message be sent to the package maintainer(s)
+but either the $gBug report is not associated with any package (probably
+because of a missing Package psuedo-header field in the original $gBug
+report), or the package(s) specified do not have any maintainer(s).
+
+Your message has *not* been sent to any package maintainers; it has
+merely been filed in the $gBug tracking system.  If you require assistance
+please contact $gMaintainerEmail quoting the $gBug number $ref.
+END
+}
+
+$resentccval.= join(', ',@resentccs);
+$resentccval =~ s/\s+\n\s+/ /g; $resentccval =~ s/^\s+/ /; $resentccval =~ s/\s+$//;
+if (length($resentccval)) { $resentcc= "Resent-CC: $resentccval\n"; }
+
+if ($codeletter eq 'U') {
+    &htmllog("Message", "sent on", $s_originator, "$gBug#$ref.");
+    &sendmessage(<<END,$s_originator,@resentccs);
+Subject: $gBug#$ref: $newsubject
+Reply-To: $replyto, $ref-quiet\@$gEmailDomain
+${orgsender}Resent-To: $s_originator
+${resentcc}Resent-Date: $tdate
+Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
+Resent-Sender: $gMaintainerEmail
+X-$gProject-PR-Message: report $ref
+X-$gProject-PR-Package: $s_package
+X-$gProject-PR-Keywords: $s_keywords
+$fwd
+END
+} elsif ($codeletter eq 'B') {
+    &htmllog($newref ? "Report" : "Information", "forwarded",
+             join(', ',"$gSubmitList\@$gListDomain",@resentccs),
+             "<code>$gBug#$ref</code>".
+             (length($s_package)? "; Package <code>".&sani($s_package)."</code>" : '').
+             (length($s_keywords)? "; Keywords <code>".&sani($s_keywords)."</code>":'').
+             ".");
+    &sendmessage(<<END,"$gSubmitList\@$gListDomain",@resentccs);
+Subject: $gBug#$ref: $newsubject
+Reply-To: $replyto, $ref\@$gEmailDomain
+Resent-From: $header{'from'}
+${orgsender}Resent-To: $gSubmitList\@$gListDomain
+${resentcc}Resent-Date: $tdate
+Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
+Resent-Sender: $gMaintainerEmail
+X-$gProject-PR-Message: report $ref
+X-$gProject-PR-Package: $s_package
+X-$gProject-PR-Keywords: $s_keywords
+$fwd
+END
+} elsif (@resentccs) {
+    # D and F done far earlier; B just done - so this must be M or Q
+    # We preserve whichever it was in the Reply-To (possibly adding
+    # the $gBug#).
+    &htmllog($newref ? "Report" : "Information", "forwarded",
+             $resentccval,
+             "<code>$gBug#$ref</code>".
+             (length($s_package)? "; Package <code>".&sani($s_package)."</code>" : '').
+             (length($s_keywords)? "; Keywords <code>".&sani($s_keywords)."</code>":'').
+             ".");
+    &sendmessage(<<END,@resentccs);
+Subject: $gBug#$ref: $newsubject
+Reply-To: $replyto, $ref-$baddressroot\@$gEmailDomain
+Resent-From: $header{'from'}
+${orgsender}Resent-To: $resentccval
+Resent-Date: $tdate
+Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
+Resent-Sender: $gMaintainerEmail
+X-$gProject-PR-Message: report $ref
+X-$gProject-PR-Package: $s_package
+X-$gProject-PR-Keywords: $s_keywords
+$fwd
+END
+}
+
+$htmlbreak= length($brokenness) ? "<p>\n".&sani($brokenness)."\n<p>\n" : '';
+$htmlbreak =~ s/\n\n/\n<P>\n\n/g;
+if (length($resentccval)) {
+    $htmlbreak =
+        "  Copy sent to <code>".&sani($resentccval)."</code>.".
+        $htmlbreak;
+}
+if ($newref) {
+    &htmllog("Acknowledgement","sent",$replyto,
+             ($veryquiet ?
+              "New $gBug report received and filed, but not forwarded." :
+              "New $gBug report received and forwarded."). $htmlbreak);
+    &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gBug#$ref: Acknowledgement of QUIET report
+         ($subject)
+Message-ID: <handler.$ref.$nn.ackquiet\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+X-$gProject-PR-Message: ack-quiet $ref
+
+Thank you for the problem report you have sent regarding $gProject.
+This is an automatically generated reply, to let you know your message
+has been received.  It has not been forwarded to the developers or
+their mailing list; you should ensure that the developers are aware of
+the problem you have entered into the system - preferably quoting the
+$gBug reference number, #$ref.
+$resentccexplain
+If you wish to submit further information on your problem, please send it
+to $ref-$baddressroot\@$gEmailDomain (and *not*
+to $baddress\@$gEmailDomain).
+
+Please do not reply to the address at the top of this message,
+unless you wish to report a problem with the $gBug-tracking system.
+$brokenness
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gBug#$ref: Acknowledgement of maintainer-only report
+         ($subject)
+Message-ID: <handler.$ref.$nn.ackmaint\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+X-$gProject-PR-Message: ack-maintonly $ref
+
+Thank you for the problem report you have sent regarding $gProject.
+This is an automatically generated reply, to let you know your message has
+been received.  It is being forwarded to the developers (but not the mailing
+list, as you requested) for their attention; they will reply in due course.
+$resentccexplain
+If you wish to submit further information on your problem, please send
+it to $ref-$baddressroot\@$gEmailDomain (and *not*
+to $baddress\@$gEmailDomain).
+
+Please do not reply to the address at the top of this message,
+unless you wish to report a problem with the $gBug-tracking system.
+$brokenness
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gBug#$ref: Acknowledgement ($subject)
+Message-ID: <handler.$ref.$nn.ack\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+X-$gProject-PR-Message: ack $ref
+
+Thank you for the problem report you have sent regarding $gProject.
+This is an automatically generated reply, to let you know your message has
+been received.  It is being forwarded to the developers mailing list for
+their attention; they will reply in due course.
+$resentccexplain
+If you wish to submit further information on your problem, please send
+it to $ref\@$gEmailDomain (and *not* to
+$baddress\@$gEmailDomain).
+
+Please do not reply to the address at the top of this message,
+unless you wish to report a problem with the $gBug-tracking system.
+$brokenness
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+} elsif ($codeletter ne 'U') {
+    &htmllog("Acknowledgement","sent",$replyto,
+             ($veryquiet ? "Extra info received and filed, but not forwarded." :
+              $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
+              "Extra info received and forwarded to list."). $htmlbreak);
+    &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gBug#$ref: Info received and FILED only
+         (was $subject)
+Message-ID: <handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+X-$gProject-PR-Message: ack-info-quiet $ref
+
+Thank you for the additional information you have supplied regarding
+this problem report.  It has NOT been forwarded to the developers, but
+will accompany the original report in the $gBug tracking system.  Please
+ensure that you yourself have sent a copy of the additional
+information to any relevant developers or mailing lists.
+$resentccexplain
+If you wish to continue to submit further information on your problem,
+please send it to $ref-$baddressroot\@$gEmailDomain, as before.
+
+Please do not reply to the address at the top of this message,
+unless you wish to report a problem with the $gBug-tracking system.
+$brokenness
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gBug#$ref: Info received for maintainer only
+         (was $subject)
+Message-ID: <handler.$ref.$nn.ackinfomaint\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+X-$gProject-PR-Message: ack-info $ref
+
+Thank you for the additional information you have supplied regarding
+this problem report.  It has been forwarded to the developer(s) (but
+not to the mailing list) to accompany the original report.
+$resentccexplain
+If you wish to continue to submit further information on your problem,
+please send it to $ref-$baddressroot\@$gEmailDomain, as before.
+
+Please do not reply to the address at the top of this message,
+unless you wish to report a problem with the $gBug-tracking system.
+$brokenness
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gBug#$ref: Info received (was $subject)
+Message-ID: <handler.$ref.$nn.ackinfo\@$gEmailDomain>
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+X-$gProject-PR-Message: ack-info-maintonly $ref
+
+Thank you for the additional information you have supplied regarding
+this problem report.  It has been forwarded to the developer(s) and
+to the developers mailing list to accompany the original report.
+$resentccexplain
+If you wish to continue to submit further information on your problem,
+please send it to $ref\@$gEmailDomain, as before.
+
+Please do not reply to the address at the top of this message,
+unless you wish to report a problem with the $gBug-tracking system.
+$brokenness
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+}
+
+&appendlog;
+&finish;
+
+sub overwrite {
+    local ($f,$v) = @_;
+    open(NEW,">$f.new") || &quit("$f.new: create: $!");
+    print(NEW "$v") || &quit("$f.new: write: $!");
+    close(NEW) || &quit("$f.new: close: $!");
+    rename("$f.new","$f") || &quit("rename $f.new to $f: $!");
+}
+
+sub appendlog {
+    if (!open(AP,">>db/$ref.log")) {
+        print DEBUG "failed open log<\n";
+        print DEBUG "failed open log err $!<\n";
+        &quit("opening db/$ref.log (li): $!");
+    }
+    print(AP "\7\n",@log,"\n\3\n") || &quit("writing db/$ref.log (li): $!");
+    close(AP) || &quit("closing db/$ref.log (li): $!");
+}
+
+sub finish {
+    utime(time,time,"db");
+    local ($u);
+    while ($u= $cleanups[$#cleanups]) { &$u; }
+    unlink("incoming/P$nn") || &quit("unlinking incoming/P$nn: $!");
+    exit $_[0];
+}
+
+&quit("wot no exit");
+
+sub chldhandle { $chldexit = 'yes'; }
+
+sub htmllog {
+    local ($whatobj,$whatverb,$where,$desc) = @_;
+    open(AP,">>db/$ref.log") || &quit("opening db/$ref.log (lh): $!");
+    print(AP
+          "\6\n".
+          "<strong>$whatobj $whatverb</strong> to <code>".&sani($where).
+          "</code>:<br>\n". $desc.
+          "\n\3\n") || &quit("writing db/$ref.log (lh): $!");
+    close(AP) || &quit("closing db/$ref.log (lh): $!");
+}    
+
+sub get_addresses {
+       return
+               map { $_->address() }
+               map { Mail::Address->parse($_) } @_;
+}
+
+
+sub sendmessage {
+    local ($msg,@recips) = @_;
+    if ($recips[0] eq '' && $#recips == 0) { @recips= ('-t'); }
+    open(AP,">>db/$ref.log") || &quit("opening db/$ref.log (lo): $!");
+    print(AP "\2\n",join("\4",@recips),"\n\5\n$msg\n\3\n") ||
+        &quit("writing db/$ref.log (lo): $!");
+    close(AP) || &quit("closing db/$ref.log (lo): $!");
+    
+    print DEBUG "mailing to >",join('|',@recips),"<\n";
+    $SIG{'CHLD'}='chldhandle';
+       #print DEBUG "mailing sigchild set up<\n";
+       $chldexit = 'no';
+    $c= open(U,"-|");
+       #print DEBUG "mailing opened pipe fork<\n";
+    defined($c) || die $!;
+       #print DEBUG "mailing opened pipe fork ok $c<\n";
+    if (!$c) { # ie, we are in the child process
+               #print DEBUG "mailing child<\n";
+        unless (open(STDERR,">&STDOUT")) {
+                       #print DEBUG "mailing child opened stderr<\n";
+            print STDOUT "redirect stderr: $!\n";
+                       #print DEBUG "mailing child opened stderr fail<\n";
+            exit 1;
+                       #print DEBUG "mailing child opened stderr fail exit !?<\n";
+        }
+               #print DEBUG "mailing child opened stderr ok<\n";
+        $c= open(D,"|-");
+               #print DEBUG "mailing child forked again<\n";
+        defined($c) || die $!;
+               #print DEBUG "mailing child forked again ok $c<\n";
+        if (!$c) { # ie, we are the child process
+                       #print DEBUG "mailing grandchild<\n";
+            exec '/usr/lib/sendmail','-f'."$gMaintainerEmail",'-odi','-oem','-oi',get_addresses(@recips);
+                       #print DEBUG "mailing grandchild exec failed<\n";
+            die $!;
+                       #print DEBUG "mailing grandchild died !?<\n";
+        }
+               #print DEBUG "mailing child not grandchild<\n";
+        print(D $msg) || die $!;
+               #print DEBUG "mailing child printed msg<\n";
+        close(D);
+               #print DEBUG "mailing child closed pipe<\n";
+        die "\n*** command returned exit status $?\n" if $?;
+               #print DEBUG "mailing child exit status ok<\n";
+        exit 0;
+               #print DEBUG "mailing child exited ?!<\n";
+    }
+       #print DEBUG "mailing parent<\n";
+    $results='';
+       #print DEBUG "mailing parent results emptied<\n";
+    while( $chldexit eq 'no' ) { $results.= $_; }
+       #print DEBUG "mailing parent results read >$results<\n";
+    close(U);
+       #print DEBUG "mailing parent results closed<\n";
+    $results.= "\n*** child returned exit status $?\n" if $?;
+       #print DEBUG "mailing parent exit status ok<\n";
+    $SIG{'CHLD'}='DEFAULT';
+       #print DEBUG "mailing parent sigchild default<\n";
+    if (length($results)) { &quit("running sendmail: $results"); }
+       #print DEBUG "mailing parent results ok<\n";
+}
+
+sub checkmaintainers {
+    return if $maintainerschecked++;
+    return if !length($s_package);
+    open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
+    while (<MAINT>) {
+        m/^(\S+)\s+(\S.*\S)\n$/ || &quit("maintainers bogus \`$_'");
+        $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
+        $maintainerof{$1}= $2;
+    }
+    close(MAINT);
+    $anymaintfound=0; $anymaintnotfound=0;
+    for $p (split(m/[ \t?,()]+/,$s_package)) {
+        $p =~ y/A-Z/a-z/;
+        if (defined($maintainerof{$p})) {
+print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
+            $addmaint= $maintainerof{$p};
+            push(@maintaddrs,$addmaint) unless
+                $addmaint eq $replyto || grep($_ eq $addmaint, @maintaddrs);
+            $anymaintfound++;
+        } else {
+print DEBUG "maintainer none >$p<\n";
+            $anymaintnotfound++;
+            last;
+        }
+    }
+}
diff --git a/scripts/processall.in b/scripts/processall.in
new file mode 100755 (executable)
index 0000000..1ae25e0
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+#
+# Usage: processall
+#
+# Uses up: incoming/I<code><bugnum>.nn
+# Temps:   incoming/[GP].nn
+# Creates: incoming/E.nn
+# Stop;    process/stop
+
+require( '/etc/debbugs/config' );
+$ENV{'PATH'} = '/usr/lib/debbugs'.$ENV{'PATH'};
+chdir( "$gSpoolDir" ) || die 'chdir spool: $!\n';
+push( @INC, '/usr/lib/debbugs' );
+
+#open(DEBUG,">&4");
+
+$|=1;
+undef %fudged;
+
+for (;;) {
+    if (-f 'stop') {
+        print(STDERR "stop file created\n") || die $!;
+        last;
+    }
+    if (!@ids) {
+        opendir(DIR,"incoming") || die $!;
+        while ($_= readdir(DIR)) { push(@ids,$_) if s/^I//; }
+        last unless @ids;
+        @ids= sort(@ids);
+    }
+    stat("$gMaintainerFile") || die "stat $gMaintainerFile: $!\n";
+    $nf= @ids;
+    $id= shift(@ids);
+    unless (rename("incoming/I$id","incoming/G$id")) {
+        if ($fudged{$id}) {
+            die "$id already fudged once! $!\n";
+        }
+        $fudged{$id}= 1;
+        next;
+    }
+    if ($id =~ m/^[RC]/) {
+        print(STDOUT "[$nf] $id service ...") || die $!;
+        defined($c=fork) || die $!;
+        if (!$c) { exec("/usr/lib/debbugs/service",$id); die $!; }
+    } elsif ($id =~ m/^[BMQFDU]/) {
+        print(STDOUT "[$nf] $id process ...") || die $!;
+        defined($c=fork) || die $!;
+        if (!$c) { exec("/usr/lib/debbugs/process",$id); die $!; }
+    } else {
+        die "bad name $id";
+    }
+    $cc=waitpid($c,0); $cc == $c || die "$cc $c $!";
+    $status=$?;
+    if ($status) {
+        print(STDERR "$id: process failed ($status $!) - now in [PG]$id\n") || die $!;
+    }
+    print(STDOUT " done\n") || die $!;
+    $ndone++;
+}
+
+exit(0);
diff --git a/scripts/receive.in b/scripts/receive.in
new file mode 100755 (executable)
index 0000000..72f6cb1
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/perl
+
+#load configuration file
+require( '/etc/debbugs/config' );
+
+#set source of mail delivery
+#sets any prefix needed to get mailer to add it to error mail
+if ( $gMailer eq 'exim' ) 
+{      $gBadEmailPrefix = '';
+       $_ = $ENV{'LOCAL_PART'};
+} elsif ( $gMailer eq 'qmail' )
+{      $gBadEmailPrefix = '//';
+       $_ = $ENV{'DEFAULT'};
+#      $_ = $ENV{'RECIPIENT'};
+#      s/^\w+-bugs--?//;
+} else 
+{      $gBadEmailPrefix = '';
+       $_ = $ARGV[0];
+       s/\>//;
+       s/\<//;
+}
+
+
+#remove everything from @ to end of line
+s/\@.*$//;
+
+#convert remaining upper case to lower case
+y/A-Z/a-z/;
+
+#set up to determine command
+%withnaddressmap= ('-submit',     'B',
+                   '',            'B',
+                   '-maintonly',  'M',
+                   '-quiet',      'Q',
+                   '-forwarded',  'F',
+                   '-done',       'D',
+                   '-close',      'D',
+                   '-submitter',  'U');
+
+%withoutnaddressmap= ('submit',     'B',
+                      'bugs',       'B',
+                      'maintonly',  'M',
+                      'quiet',      'Q',
+                      'forwarded',  'F',
+                      'done',       'D',
+                      'close',      'D',
+                      'request',    'R',
+                      'submitter',  'U',
+                      'control',    'C');
+
+#determine command
+if (s/^(\d{1,9})\b//) {
+    $bugnumber= $1;
+    $map= $withnaddressmap{$_};
+    $addrrec= "$bugnumber$_";
+} else {
+    $bugnumber= '';
+    $map= $withoutnaddressmap{$_};
+    $addrrec= "$_";
+}
+
+#print no command received
+if (!defined($map)) {
+    print STDERR <<ENDTEXT;
+$gBadEmailPrefix
+$gBadEmailPrefix Unknown $gBug service address $_\@$gEmailDomain.
+$gBadEmailPrefix Recognised addresses are:
+$gBadEmailPrefix
+$gBadEmailPrefix     General:       Read $gBug# in Subject:    $gBug# is NNNN:
+$gBadEmailPrefix
+$gBadEmailPrefix      request        submit  $gBug             NNNN  NNNN-submit
+$gBadEmailPrefix      control        maintonly                NNNN-maintonly
+$gBadEmailPrefix      owner          quiet                    NNNN-quiet
+$gBadEmailPrefix      postmaster     forwarded                NNNN-forwarded
+$gBadEmailPrefix                     done  close              NNNN-done  NNNN-close
+$gBadEmailPrefix                     submitter                NNNN-submitter
+$gBadEmailPrefix
+$gBadEmailPrefix (all \@$gEmailDomain.)
+$gBadEmailPrefix
+$gBadEmailPrefix For instructions via the WWW see:
+$gBadEmailPrefix   http://$gWebDomain/
+$gBadEmailPrefix   http://$gWebDomain/Reporting.html
+$gBadEmailPrefix   http://$gWebDomain/Developer.html
+$gBadEmailPrefix   http://$gWebDomain/Access.html
+$gBadEmailPrefix $gTextInstructions
+$gBadEmailPrefix For details of how to access $gBug report logs by email:
+$gBadEmailPrefix   send \`request\@$gEmailDomain' the word \`help'
+$gBadEmailPrefix
+ENDTEXT
+    exit(100);
+}
+
+@months=qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+($sec,$min,$hour,$mday,$mon,$year)= gmtime(time);
+
+$queue= "$map$bugnumber";
+
+chdir("$gSpoolDir/incoming") || &failure("chdir to spool: $!");
+
+$id= time.$$;
+open(FILE,">T.$id") || &failure("open temporary file: $!");
+printf(FILE "Received: (at %s) by $gEmailDomain; %d %s %d %02d:%02d:%02d +0000\n",
+       $addrrec, $mday,$months[$mon],$year+1900, $hour,$min,$sec) ||
+    &failure("write header to temporary file: $!");
+while(<STDIN>) { print(FILE) || &failure("write temporary file: $!"); }
+close(FILE) || &failure("close temporary file: $!");
+
+rename("T.$id","I$queue.$id") || &failure("rename spool message: $!");
+
+exit(0);
+
+sub failure {
+    length($id) && unlink("T.$id");
+    print STDERR "bugs receive failure: @_\n";
+    exit(75); # EX_TEMPFAIL
+}
diff --git a/scripts/service.in b/scripts/service.in
new file mode 100755 (executable)
index 0000000..93954b6
--- /dev/null
@@ -0,0 +1,805 @@
+#!/usr/bin/perl
+#
+# Usage: service <code>.nn
+# Temps:  incoming/P<code>.nn
+
+use Mail::Address;
+require('/etc/debbugs/config');
+require('/usr/lib/debbugs/errorlib');
+$ENV{'PATH'}= '/usr/lib/debbugs'.$ENV{'PATH'};;
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+
+# open(DEBUG,">&4");
+
+$wwwbase= "$gWebDir";
+
+# defined($intdate= time) || &quit("failed to get time: $!");
+
+$_=shift;
+m/^[RC]\.\d+$/ || &quit("bad argument");
+$control= m/C/;
+$nn= $_;
+if (!rename("incoming/G$nn","incoming/P$nn")) {
+    $_=$!.'';  m/no such file or directory/i && exit 0;
+    &quit("renaming to lock: $!");
+}    
+
+open(M,"incoming/P$nn");
+@log=<M>;
+@msg=@log;
+close(M);
+
+grep((s/\n$//,s/\s+$//),@msg);
+
+print DEBUG "###\n",join("##\n",@msg),"\n###\n";
+
+chop($tdate= `date -u '+%a, %d %h 19%y %T GMT'`);
+$fwd= <<END;
+Received: via spool for service; $tdate
+END
+
+for ($i=0; $i<=$#msg; $i++) {
+    $_ = $msg[$i];
+    last unless length($_);
+    $fwd .= $_."\n";
+    while ($msg[$i+1] =~ m/^\s/) {
+        $i++;
+        $fwd .= $msg[$i]."\n" if $ins; # Huh ? Where is ins set ?
+        $_ .= ' '.$msg[$i];
+    }
+# print DEBUG ">$_<\n";
+    if (s/^(\S+):\s*//) {
+        $v= $1; $v =~ y/A-Z/a-z/;
+print DEBUG ">$v=$_<\n";
+        $header{$v}= $_;
+    } else {
+print DEBUG "!>$_<\n";
+    }
+}
+
+defined($header{'from'}) || &quit("no From header");
+$replyto= defined($header{'reply-to'}) ? $header{'reply-to'} : $header{'from'};
+
+$controlrequestaddr= $control ? "control\@$gEmailDomain" : "request\@$gEmailDomain";
+$transcript='';
+&transcript("Processing commands for $controlrequestaddr:\n\n");
+
+$dl= 0;
+$state= 'idle';
+$lowstate= 'idle';
+$mergelowstate= 'idle';
+$midix=0;    
+
+for ($procline=$i; $procline<=$#msg; $procline++) {
+    $state eq 'idle' || "$state ?";
+    $lowstate eq 'idle' || "$lowstate ?";
+    $mergelowstate eq 'idle' || "$mergelowstate ?";
+    $_= $msg[$procline]; s/\s+$//;
+    next unless m/\S/; next if m/^\s*\#/;
+    &transcript("> $_\n");
+    $action= '';
+    if (m/^stop$/ || m/^quit$/ || m/^--/ || m/^thank/) {
+        &transcript("Stopping processing here.\n\n");
+        last;
+    } elsif (m/^debug\s+(\d+)$/ && $1 >= 0 && $1 <= 1000) {
+        $dl= $1+0;
+        &transcript("Debug level $dl.\n\n");
+    } elsif (m/^(send|get)\s+\#?(\d{3,})$/) {
+        $ref= $2+0; $reffile= $ref; $reffile =~ s,^..,$&/$&,;
+        &sendlynxdoc("db/$reffile.html","logs for $gBug#$ref");
+    } elsif (m/^send-detail\s+\#?(\d+)$/) {
+        $ref= $1+0; $reffile= $ref; $reffile =~ s,^..,$&/$&,;
+        &sendlynxdoc("db/$reffile-b.html","additional logs for $gBug#$ref");
+    } elsif (m/^index(\s+full)?$/) {
+        &sendlynxdoc("db/ix/full.html",'full index');
+    } elsif (m/^index-summary\s+by-package$/) {
+        &sendlynxdoc("db/ix/psummary.html",'summary index sorted by package/title');
+    } elsif (m/^index-summary(\s+by-number)?$/) {
+        &sendlynxdoc("db/ix/summary.html",'summary index sorted by number/date');
+    } elsif (m/^index(\s+|-)pack(age)?s?$/) {
+        &sendlynxdoc("db/ix/packages.html",'index of packages');
+    } elsif (m/^index(\s+|-)maints?$/) {
+        &sendlynxdoc("db/ix/maintainers.html",'index of maintainers');
+    } elsif (m/^index(\s+|-)maint\s+(\S.*\S)$/) {
+        $substrg= $2; $matches=0;
+        opendir(DBD,"$gWebDir/db/ma") || die $!;
+        while (defined($_=readdir(DBD))) {
+            next unless m/^l/ && m/\.html$/;
+            &transcript("F|$_\n") if $dl>1;
+            $filename= $_; s/^l//; s/\.html$//;
+            &transcript("P|$_\n") if $dl>2;
+            while (s/-(..)([^_])/-$1_-$2/) { }
+            &transcript("P|$_\n") if $dl>2;
+            s/^(.{0,2})_/$1-20_/g; while (s/([^-]..)_/$1-20_/) { };
+            &transcript("P|$_\n") if $dl>2;
+            s/^,(.*),(.*),([^,]+)$/$1-40_$2-20_-28_$3-29_/;
+            &transcript("P|$_\n") if $dl>2;
+            s/^([^,]+),(.*),(.*),$/$1-20_-3c_$2-40_$3-3e_/;
+            &transcript("P|$_\n") if $dl>2;
+            s/\./-2e_/g;
+            &transcript("P|$_\n") if $dl>2;
+            $out='';
+            while (m/-(..)_/) { $out.= $`.sprintf("%c",hex($1)); $_=$'; }
+            $out.=$_;
+            &transcript("M|$out\n") if $dl>1;
+            next unless index(lc $out, lc $substrg)>=0;
+            &transcript("S|$filename\n") if $dl>0;
+            &transcript("S|$out\n") if $dl>0;
+            $matches++;
+            &sendlynxdocraw("db/ma/$filename","$gBug list for maintainer \`$out'");
+        }
+        if ($matches) {
+            &transcript("$gBug list(s) for $matches maintainer(s) sent.\n\n");
+        } else {
+            &transcript("No maintainers found containing \`$substrg'.\n".
+                        "Use \`index-maint' to get list of maintainers.\n\n");
+        }
+        $ok++;
+    } elsif (m/^index(\s+|-)pack(age)?s?\s+(\S.*\S)$/) {
+        $substrg= $+; $matches=0;
+        opendir(DBD,"$gWebDir/db/pa") || die $!;
+        while (defined($_=readdir(DBD))) {
+            next unless m/^l/ && m/\.html$/;
+            &transcript("F|$_\n") if $dl>1;
+            $filename= $_; s/^l//; s/\.html$//;
+            next unless index(lc $_, lc $substrg)>=0;
+            &transcript("S|$filename\n") if $dl>0;
+            &transcript("S|$out\n") if $dl>0;
+            $matches++;
+            &sendlynxdocraw("db/pa/$filename","$gBug list for package \`$_'");
+        }
+        if ($matches) {
+            &transcript("$gBug list(s) for $matches package(s) sent.\n\n");
+        } else {
+            &transcript("No packages found containing \`$substrg'.\n".
+                        "Use \`index-packages' to get list of packages.\n\n");
+        }
+        $ok++;
+    } elsif (m/^send-unmatched(\s+this|\s+-?0)?$/) {
+        &sendlynxdoc("db/ju/unmatched-1.html","junk (this week)");
+    } elsif (m/^send-unmatched\s+(last|-1)$/) {
+        &sendlynxdoc("db/ju/unmatched-2.html","junk (last week)");
+    } elsif (m/^send-unmatched\s+(old|-2)$/) {
+        &sendlynxdoc("db/ju/unmatched-3.html","junk (two weeks ago)");
+    } elsif (m/^getinfo\s+(\S+)$/) {
+        $file= $1;
+        if ($file =~ m/^\./ || $file !~ m/^[-.0-9a-z]+$/ || $file =~ m/\.gz$/) {
+            &transcript("Filename $file is badly formatted.\n\n");
+        } elsif (open(P,"$gDocDir/$file")) {
+            $ok++;
+            &transcript("Info file $file appears below.\n\n");
+            $extras.= "\n---------- Info file $file follows:\n\n";
+            while(<P>) { $extras.= $_; }
+            close(P);
+        } else {
+            &transcript("Info file $file does not exist.\n\n");
+         }
+    } elsif (m/^help$/) {
+        &sendhelp;
+        &transcript("\n");
+        $ok++;
+    } elsif (m/^refcard$/) {
+        &sendtxthelp("bug-mailserver-refcard.txt","mailservers' reference card");
+    } elsif (m/^subscribe/) {
+        &transcript(<<END);
+There is no $gProject $gBug mailing list.  If you wish to review bug reports
+please do so via http://$gWebUrl/ or ask this mailserver
+to send them to you.
+soon: MAILINGLISTS_TEXT
+END
+    } elsif (m/^unsubscribe/) {
+        &transcript(<<END);
+soon: UNSUBSCRIBE_TEXT
+soon: MAILINGLISTS_TEXT
+END
+    } elsif (!$control) {
+        &transcript(<<END);
+Unknown command or malformed arguments to command.
+(Use control\@$gEmailDomain to manipulate reports.)
+
+END
+        if (++$unknowns >= 3) {
+            &transcript("Too many unknown commands, stopping here.\n\n");
+            last;
+        }
+    } elsif (m/^close\s+\#?(\d+)$/) {
+       $ok++;
+       $ref= $1;
+       if (&setbug) {
+           if (length($s_done)) {
+               &transcript("$gBug is already closed, cannot re-close.\n\n");
+                &nochangebug;
+            } else {
+                $action= "$gBug closed, ack sent to submitter - they'd better know why !";
+                do {
+                    &addmaintainers($s_package);
+                                       if ( length( $gDoneList ) > 0 && length( $gListDomain ) >
+                                       0 ) { &addccaddress("$gDoneList\@$gListDomain"); }
+                    $s_done= $replyto;
+                   $message= <<END;
+From: $gMaintainerEmail ($gMaintainer)
+To: $s_originator
+Subject: $gBug#$ref acknowledged by developer
+         ($s_subject)
+References: $header{'message-id'} $s_msgid
+In-Reply-To: $s_msgid
+Message-ID: <handler.$ref.$nn.notifdonectrl.$midix\@$gEmailDomain>
+
+This is an automatic notification regarding your $gBug report.
+
+It has been marked as closed by one of the developers, namely
+$replyto.
+
+You should be hearing from them with a substantive response shortly,
+if you have not already done so.  If not, please contact them
+directly, or email DB_SUBMIT_ADDRPQ or myself.
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+END
+                    &sendmailmessage($message,$s_originator);
+                } while (&getnextbug);
+            }
+        }
+    } elsif (m/^reassign\s+\#?(\d+)\s+(\S.*\S)$/) {
+        $ok++;
+        $ref= $1; $newpackage= $2;
+        if (&setbug) {
+            if (length($s_package)) {
+                $action= "$gBug reassigned from package \`$s_package'".
+                         " to \`$newpackage'.";
+            } else {
+                $action= "$gBug assigned to package \`$newpackage'.";
+            }
+            do {
+                &addmaintainers($s_package);
+                &addmaintainers($newpackage);
+                $s_package= $newpackage;
+            } while (&getnextbug);
+        }
+    } elsif (m/^reopen\s+\#?(\d+)$/ ? ($noriginator='', 1) :
+             m/^reopen\s+\#?(\d+)\s+\=$/ ? ($noriginator='', 1) :
+             m/^reopen\s+\#?(\d+)\s+\!$/ ? ($noriginator=$replyto, 1) :
+             m/^reopen\s+\#?(\d+)\s+(\S.*\S)$/ ? ($noriginator=$2, 1) : 0) {
+        $ok++;
+        $ref= $1;
+        if (&setbug) {
+            if (!length($s_done)) {
+                &transcript("$gByg is already open, cannot reopen.\n\n");
+                &nochangebug;
+            } else {
+                $action=
+                    $noriginator eq '' ? "$gBug reopened, originator not changed." :
+                        "$gBug reopened, originator set to $noriginator.";
+                do {
+                    &addmaintainers($s_package);
+                    $s_originator= $noriginator eq '' ?  $s_originator : $noriginator;
+                    $s_done= '';
+                } while (&getnextbug);
+            }
+        }
+    } elsif (m/^forwarded\s+\#?(\d+)\s+(\S.*\S)$/) {
+        $ok++;
+        $ref= $1; $whereto= $2;
+        if (&setbug) {
+            if (length($s_forwarded)) {
+    $action= "Forwarded-to-address changed from $s_forwarded to $whereto.";
+            } else {
+    $action= "Noted your statement that $gBug has been forwarded to $whereto.";
+            }
+            if (length($s_done)) {
+                $extramessage= "(By the way, this $gBug is currently marked as done.)\n";
+            }
+            do {
+                &addmaintainers($s_package);
+                               if (length($gFowardList)>0 && length($gListDomain)>0 )
+                { &addccaddress("$gFowardList\@$gListDomain"); }
+                $s_forwarded= $whereto;
+            } while (&getnextbug);
+        }
+    } elsif (m/^notforwarded\s+\#?(\d+)$/) {
+        $ok++;
+        $ref= $1;
+        if (&setbug) {
+            if (!length($s_forwarded)) {
+                &transcript("$gBug is not marked as having been forwarded.\n\n");
+                &nochangebug;
+            } else {
+    $action= "Removed annotation that $gBug had been forwarded to $s_forwarded.";
+                do {
+                    &addmaintainers($s_package);
+                    $s_forwarded= '';
+                } while (&getnextbug);
+            }
+        }
+    } elsif (m/^severity\s+\#?(\d+)\s+([-0-9a-z]+)$/) {
+        $ok++;
+        $ref= $1;
+        $newseverity= $2;
+        if (!grep($_ eq $newseverity, @severities, "$gDefaultSeverity")) {
+            &transcript("Severity level \`$newseverity' is not known.\n".
+                       "Recognised are: ".join(' ',@showseverities).".\n\n");
+        } elsif (&setbug) {
+            $printseverity= $s_severity;
+            $printseverity= "$gDefaultSeverity" if $printseverity eq '';
+           $action= "Severity set to \`$newseverity'.";
+           do {
+                &addmaintainers($s_package);
+                $s_severity= $newseverity;
+            } while (&getnextbug);
+        }
+    } elsif (m/^retitle\s+\#?(\d+)\s+(\S.*\S)\s*$/) {
+        $ok++;
+        $ref= $1; $newtitle= $2;
+        if (&getbug) {
+            &foundbug;
+            &addmaintainers($s_package);
+            $s_subject= $newtitle;
+            $action= "Changed $gBug title.";
+            &savebug;
+            &transcript("$action\n");
+            if (length($s_done)) {
+                &transcript("(By the way, that $gBug is currently marked as done.)\n");
+            }
+            &transcript("\n");
+        } else {
+            &notfoundbug;
+        }
+    } elsif (m/^unmerge\s+\#?(\d+)$/) {
+       $ok++;
+       $ref= $1;
+       if (&setbug) {
+           if (!length($s_mergedwith)) {
+               &transcript("$gBug is not marked as being merged with any others.\n\n");
+               &nochangebug;
+           } else {
+                $mergelowstate eq 'locked' || die "$mergelowstate ?";
+               $action= "Disconnected #$ref from all other report(s).";
+               @newmergelist= split(/ /,$s_mergedwith);
+                $discref= $ref;
+                do {
+                    &addmaintainers($s_package);
+                   $s_mergedwith= ($ref == $discref) ? ''
+                        : join(' ',grep($_ ne $ref,@newmergelist));
+                } while (&getnextbug);
+           }
+       }
+    } elsif (m/^merge\s(\d+(\s+\d+)+)\s*$/) {
+       $ok++;
+        @tomerge= sort { $a <=> $b } split(/\s+/,$1);
+        @newmergelist= ();
+        &getmerge;
+        while (defined($ref= shift(@tomerge))) {
+            &transcript("D| checking merge $ref\n") if $dl;
+           $ref+= 0;
+           next if grep($_ eq $ref,@newmergelist);
+           if (!&getbug) { &notfoundbug; @newmergelist=(); last }
+            &foundbug;
+            &transcript("D| adding $ref ($s_mergewith)\n") if $dl;
+           $mismatch= '';
+           &checkmatch('package','m_package',$s_package);
+           &checkmatch('forwarded addr','m_forwarded',$s_forwarded);
+           &checkmatch('severity','m_severity',$s_severity);
+           &checkmatch('done mark','m_done',length($s_done) ? 'done' : 'open');
+           if (length($mismatch)) {
+               &transcript("Mismatch - only $Bugs in same state can be merged:\n".
+                            $mismatch."\n");
+               &cancelbug; @newmergelist=(); last;
+           }
+            push(@newmergelist,$ref);
+            push(@tomerge,split(/ /,$s_mergedwith));
+           &cancelbug;
+       }
+       if (@newmergelist) {
+            @newmergelist= sort { $a <=> $b } @newmergelist;
+            $action= "Merged @newmergelist.";
+           for $ref (@newmergelist) {
+               &getbug || die "huh ?  $gBug $ref disappeared during merge";
+                &addmaintainers($s_package);
+               $s_mergedwith= join(' ',grep($_ ne $ref,@newmergelist));
+               &savebug;
+           }
+           &transcript("$action\n\n");
+       }
+        &endmerge;
+    } else {
+        &transcript("Unknown command or malformed arguments to command.\n\n");
+        if (++$unknowns >= 5) {
+            &transcript("Too many unknown commands, stopping here.\n\n");
+            last;
+        }
+    }
+}
+if ($procline>$#msg) {
+    &transcript(">\nEnd of message, stopping processing here.\n\n");
+}
+if (!$ok) {
+    &transcript("No commands successfully parsed; sending the help text(s).\n");
+    &sendhelp;
+    &transcript("\n");
+}
+
+&transcript("MC\n") if $dl>1;
+@maintccs= ();
+for $maint (keys %maintccreasons) {
+&transcript("MM|$maint|\n") if $dl>1;
+    next if $maint eq $replyto;
+    $reasonstring= '';
+    $reasonsref= $maintccreasons{$maint};
+&transcript("MY|$maint|\n") if $dl>2;
+    for $p (sort keys %$reasonsref) {
+&transcript("MP|$p|\n") if $dl>2;
+        $reasonstring.= ', ' if length($reasonstring);
+        $reasonstring.= $p.' ' if length($p);
+        $reasonstring.= join(' ',map("#$_",sort keys %{$$reasonsref{$p}}));
+    }
+    push(@maintccs,"$maint ($reasonstring)");
+    push(@maintccaddrs,"$maint");
+}
+if (@maintccs) {
+    &transcript("MC|@maintccs|\n") if $dl>2;
+    $maintccs= "Cc: ".join(",\n    ",@maintccs)."\n";
+}
+
+$reply= <<END;
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+${maintccs}Subject: Processed: $header{'subject'}
+In-Reply-To: $header{'message-id'}
+References: $header{'message-id'}
+Message-ID: <handler.s.$nn.transcript\@$gEmailDomain>
+
+${transcript}Please contact me if you need assistance.
+
+$gMaintainer
+(administrator, $gProject $gBugs database)
+$extras
+END
+
+$repliedshow= join(', ',$replyto,@maintccaddrs);
+&filelock("lock/-1");
+open(AP,">>db/-1.log") || &quit("open db/-1.log: $!");
+print(AP
+      "\2\n$repliedshow\n\5\n$reply\n\3\n".
+      "\6\n".
+      "<strong>Request received</strong> from <code>".
+      &sani($header{'from'})."</code>\n".
+      "to <code>".&sani($controlrequestaddr)."</code>\n".
+      "\3\n".
+      "\7\n",@log,"\n\3\n") || &quit("writing db/-1.log: $!");
+close(AP) || &quit("open db/-1.log: $!");
+&unfilelock;
+utime(time,time,"db");
+
+&sendmailmessage($reply,$replyto,@maintccaddrs);
+
+unlink("incoming/P$nn") || &quit("unlinking incoming/P$nn: $!");
+
+sub get_addresses {
+    return
+       map { $_->address() }
+       map { Mail::Address->parse($_) } @_;
+}
+
+sub sendmailmessage {
+    local ($message,@recips) = @_;
+    print DEBUG "mailing to >@recips<\n";
+    $c= open(D,"|-");
+    defined($c) || &quit("mailing forking for sendmail: $!");
+    if (!$c) { # ie, we are the child process
+        exec '/usr/lib/sendmail','-f'."$gMaintainerEmail",'-odi','-oem','-oi',get_addresses(@recips);
+        die $!;
+    }
+    print(D $message) || &quit("writing to sendmail process: $!");
+    $!=0; close(D); $? && &quit("sendmail gave exit status $? ($!)");
+    $midix++;
+}
+
+sub sendhelp {
+        &sendtxthelpraw("bug-log-mailserver.txt","instructions for request\@$gEmailDomain");
+        &sendtxthelpraw("bug-maint-mailcontrol.txt","instructions for control\@$gEmailDomain")
+            if $control;
+}
+
+#sub unimplemented {
+#    &transcript("Sorry, command $_[0] not yet implemented.\n\n");
+#}
+
+sub checkmatch {
+    local ($string,$mvarname,$svarvalue) = @_;
+    local ($mvarvalue);
+    if (@newmergelist) {
+        eval "\$mvarvalue= \$$mvarname";
+        &transcript("D| checkmatch \`$string' /$mvarname/$mvarvalue/$svarvalue/\n")
+            if $dl;
+        $mismatch .=
+            "Values for \`$string' don't match:\n".
+            " #$newmergelist[0] has \`$mvarvalue';\n".
+            " #$ref has \`$svarvalue'\n"
+            if $mvarvalue ne $svarvalue;
+    } else {
+        &transcript("D| setupmatch \`$string' /$mvarname/$svarvalue/\n")
+            if $dl;
+        eval "\$$mvarname= \$svarvalue";
+    }
+}
+
+# High-level bug manipulation calls
+# Do announcements themselves
+#
+# Possible calling sequences:
+#    setbug (returns 0)
+#    
+#    setbug (returns 1)
+#    &transcript(something)
+#    nochangebug
+#
+#    setbug (returns 1)
+#    $action= (something)
+#    do {
+#      (modify s_* variables)
+#    } while (getnextbug);
+
+sub nochangebug {
+    &dlen("nochangebug");
+    $state eq 'single' || $state eq 'multiple' || die "$state ?";
+    &cancelbug;
+    &endmerge if $manybugs;
+    $state= 'idle';
+    &dlex("nochangebug");
+}
+
+sub setbug {
+    &dlen("setbug $ref");
+    $state eq 'idle' || die "$state ?";
+    if (!&getbug) {
+        &notfoundbug;
+        &dlex("setbug => 0s");
+        return 0;
+    }
+    @thisbugmergelist= split(/ /,$s_mergedwith);
+    if (!@thisbugmergelist) {
+        &foundbug;
+        $manybugs= 0;
+        $state= 'single';
+        $sref=$ref;
+        &dlex("setbug => 1s");
+        return 1;
+    }
+    &cancelbug;
+    &getmerge;
+    $manybugs= 1;
+    if (!&getbug) {
+        &notfoundbug;
+        &endmerge;
+        &dlex("setbug => 0mc");
+        return 0;
+    }
+    &foundbug;
+    $state= 'multiple'; $sref=$ref;
+    &dlex("setbug => 1m");
+    return 1;
+}
+
+sub getnextbug {
+    &dlen("getnextbug");
+    $state eq 'single' || $state eq 'multiple' || die "$state ?";
+    &savebug;
+    if (!$manybugs || !@thisbugmergelist) {
+        length($action) || die;
+        &transcript("$action\n$extramessage\n");
+        &endmerge if $manybugs;
+        $state= 'idle';
+        &dlex("getnextbug => 0");
+        return 0;
+    }
+    $ref= shift(@thisbugmergelist);
+    &getbug || die "bug $ref disappeared";
+    &foundbug;
+    &dlex("getnextbug => 1");
+    return 1;
+}
+
+# Low-level bug-manipulation calls
+# Do no announcements
+#
+#    getbug (returns 0)
+#
+#    getbug (returns 1)
+#    cancelbug
+#
+#    getmerge
+#    $action= (something)
+#    getbug (returns 1)
+#    savebug/cancelbug
+#    getbug (returns 1)
+#    savebug/cancelbug
+#    [getbug (returns 0)]
+#    &transcript("$action\n\n")
+#    endmerge
+
+sub notfoundbug { &transcript("$gBug number $ref not found.\n\n"); }
+sub foundbug { &transcript("$gBug#$ref: $s_subject\n"); }
+
+sub getmerge {
+    &dlen("getmerge");
+    $mergelowstate eq 'idle' || die "$mergelowstate ?";
+    &filelock('lock/merge');
+    $mergelowstate='locked';
+    &dlex("getmerge");
+}
+
+sub endmerge {
+    &dlen("endmerge");
+    $mergelowstate eq 'locked' || die "$mergelowstate ?";
+    &unfilelock;
+    $mergelowstate='idle';
+    &dlex("endmerge");
+}
+
+sub getbug {
+    &dlen("getbug $ref");
+    $lowstate eq 'idle' || die "$state ?";
+    if (&lockreadbug($ref)) {
+        $sref= $ref;
+        $lowstate= "open";
+        &dlex("getbug => 1");
+        $extramessage='';
+        return 1;
+    }
+    $lowstate= 'idle';
+    &dlex("getbug => 0");
+    return 0;
+}
+
+sub cancelbug {
+    &dlen("cancelbug");
+    $lowstate eq 'open' || die "$state ?";
+    &unfilelock;
+    $lowstate= 'idle';
+    &dlex("cancelbug");
+}
+
+sub savebug {
+    &dlen("savebug $ref");
+    $lowstate eq 'open' || die "$lowstate ?";
+    length($action) || die;
+    $ref == $sref || die "read $sref but saving $ref ?";
+    open(L,">>db/$ref.log") || &quit("opening db/$ref.log: $!");
+    print(L
+          "\6\n".
+          "<strong>".&sani($action)."</strong>\n".
+          "Request was from <code>".&sani($header{'from'})."</code>\n".
+          "to <code>".&sani($controlrequestaddr)."</code>. \n".
+          "\3\n".
+          "\7\n",@log,"\n\3\n") || &quit("writing db/$ref.log: $!");
+    close(L) || &quit("closing db/$ref.log: $!");
+    open(S,">db/$ref.status.new") || &quit("opening db/$ref.status.new: $!");
+    print(S
+          "$s_originator\n".
+          "$s_date\n".
+          "$s_subject\n".
+          "$s_msgid\n".
+          "$s_package\n".
+          "$s_keywords\n".
+          "$s_done\n".
+          "$s_forwarded\n".
+          "$s_mergedwith\n".
+         "$s_severity\n") || &quit("writing db/$ref.status.new: $!");
+    close(S) || &quit("closing db/$ref.status.new: $!");
+    rename("db/$ref.status.new","db/$ref.status") ||
+        &quit("installing new db/$ref.status: $!");
+    &unfilelock;
+    $lowstate= "idle";
+    &dlex("savebug");
+}
+
+sub dlen {
+    return if !$dl;
+    &transcript("C> @_ ($state $lowstate $mergelowstate)\n");
+}
+
+sub dlex {
+    return if !$dl;
+    &transcript("R> @_ ($state $lowstate $mergelowstate)\n");
+}
+
+sub transcript {
+    print(DEBUG $_[0]);
+    $transcript.= $_[0];
+}
+
+sub sendlynxdoc {
+    &sendlynxdocraw;
+    &transcript("\n");
+    $ok++;
+}
+
+sub sendtxthelp {
+    &sendtxthelpraw;
+    &transcript("\n");
+    $ok++;
+}
+
+sub sendtxthelpraw {
+    local ($relpath,$description) = @_;
+    $doc='';
+    open(D,"$gDocDir/$relpath") || &quit("open doc file $relpath: $!");
+    while(<D>) { $doc.=$_; }
+    close(D);
+    &transcript("Sending $description in separate message.\n");
+    &sendmailmessage(<<END.$doc,$replyto);
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gProject $gBug help: $description
+References: $header{'message-id'}
+In-Reply-To: $header{'message-id'}
+Message-ID: <handler.s.$nn.help.$midix\@$gEmailDomain>
+
+END
+    $ok++;
+}
+
+sub sendlynxdocraw {
+    local ($relpath,$description) = @_;
+    $doc='';
+    open(L,"lynx -nolist -dump $wwwbase/$relpath 2>&1 |") || &quit("fork for lynx: $!");
+    while(<L>) { $doc.=$_; }
+    $!=0; close(L);
+    if ($? == 255 && $doc =~ m/^\n*lynx: Can\'t access start file/) {
+        &transcript("Information ($description) is not available -\n".
+                    "perhaps the $gBug does not exist or is not on the WWW yet.\n");
+         $ok++;
+    } elsif ($?) {
+        &transcript("Error getting $description (code $? $!):\n$doc\n");
+    } else {
+        &transcript("Sending $description.\n");
+        &sendmailmessage(<<END.$doc,$replyto);
+From: $gMaintainerEmail ($gMaintainer)
+To: $replyto
+Subject: $gProject $gBugs information: $description
+References: $header{'message-id'}
+In-Reply-To: $header{'message-id'}
+Message-ID: <handler.s.$nn.info.$midix\@$gEmailDomain>
+
+END
+         $ok++;
+    }
+}
+
+sub addccaddress {
+    my ($cca) = @_;
+    $maintccreasons{$cca}{''}{$ref}= 1;
+}
+
+sub addmaintainers {
+    # Data structure is:
+    #   maintainer email address &c -> assoc of packages -> assoc of bug#'s
+    my $p, $addmaint, $pshow;
+    &ensuremaintainersloaded;
+    $anymaintfound=0; $anymaintnotfound=0;
+    for $p (split(m/[ \t?,()]+/,$_[0])) {
+        $p =~ y/A-Z/a-z/;
+        $pshow= ($p =~ m/[-+.a-z0-9]+/ ? $& : '');
+        if (defined($maintainerof{$p})) {
+            $addmaint= $maintainerof{$p};
+&transcript("MR|$addmaint|$p|$ref|\n") if $dl>2;
+            $maintccreasons{$addmaint}{$p}{$ref}= 1;
+print DEBUG "maintainer add >$p|$addmaint<\n";
+        } else {
+print DEBUG "maintainer none >$p<\n";
+        }
+    }
+}
+
+sub ensuremaintainersloaded {
+    my $a,$b;
+    return if $maintainersloaded++;
+    open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
+    while (<MAINT>) {
+        m/^(\S+)\s+(\S.*\S)\n$/ || &quit("maintainers bogus \`$_'");
+        $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
+        $maintainerof{$1}= $2;
+    }
+    close(MAINT);
+}
diff --git a/scripts/summary.in b/scripts/summary.in
new file mode 100755 (executable)
index 0000000..7dbb185
--- /dev/null
@@ -0,0 +1,88 @@
+#!/usr/bin/perl
+
+require('/etc/debbugs/config');
+require('/usr/lib/debbugs/errorlib');
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+
+#open(DEBUG,">&4");
+
+$mode= shift(@ARGV);
+
+open(M,"$gMaintainerFile") || &quit("open $gMaintainerFile: $!");
+while (<M>) {
+    m/^(\S+)\s+(\S.*\S)\s*$/ || warn "$_ ?";
+    ($a,$b)=($1,$2);
+    $a =~ y/A-Z/a-z/;
+    $maintainer{$a}= $b;
+}
+close(M);
+
+defined($startdate= time) || &quit("failed to get time: $!");
+
+opendir(DIR,"db") || &quit("opendir db: $!\n");
+@list= grep(m/^\d+\.status$/,readdir(DIR));
+grep(s/\.status$//,@list);
+@list= sort { $a <=> $b } @list;
+
+$head= $mode eq 'bymaint'
+    ? ' Package     Ref    Subject'
+    : ' Ref   Package    Keywords/Subject               Package maintainer';
+$amonths=-1;
+
+while (length($f=shift(@list))) {
+    &filelock("lock/$f");
+    if (!open(S,"db/$f.status")) { &unlinklock; next; }
+    chop($s_originator= <S>);
+    chop($s_date= <S>);
+    chop($s_subject= <S>);
+    chop($s_msgid= <S>);
+    chop($s_package= <S>);
+    chop($s_keywords= <S>);
+    chop($s_done= <S>);
+    chop($s_forwarded= <S>);
+    $_= $s_package; y/A-Z/a-z/; $_= $` if m/[^-+._a-z0-9]/;
+    $s_maintainer=
+        defined($maintainer{$_}) ? $maintainer{$_} :
+        length($_) ? "(unknown -- \`$_')" :
+        "(unknown)";
+    if ($mode eq 'undone' || $mode eq 'veryold') {
+        &unfilelock;
+        next if length($s_done) || length($s_forwarded);
+        $cmonths= int(($startdate - $s_date)/2592000); # 3600*24*30 (30 days)
+        next if $mode eq 'veryold' && $cmonths < 2;
+        if ($cmonths != $amonths) {
+            $msg= $cmonths == 0 ? "Submitted in the last month" :
+                  $cmonths == 1 ? "Over one month old" :
+                  $cmonths == 2 ? "Over two months old - attention is required" :
+                                  "OVER $cmonths MONTHS OLD - ATTENTION IS REQUIRED";
+            print "\n$msg:\n$head\n";
+            $amonths= $cmonths;
+        }
+        printf("%6d %-10.10s %-30.30s %-.31s\n", $f, $s_package,
+               (length($s_keywords) ? $s_keywords.'/' : '').$s_subject,
+               $s_maintainer) || &quit("output undone: $!");
+    } elsif ($mode eq 'bymaint') {
+        &unfilelock;
+        next if length($s_done) || length($s_forwarded);
+        $string{$f}=
+            sprintf(" %-10.10s %6d  %-.59s\n", $s_package, $f, $s_subject);
+        $s_maintainer= "(unknown)" if $s_maintainer =~ m/^\(unknown \-\-/;
+        $maintainercnt{$s_maintainer}++;
+        $maintainerlist{$s_maintainer}.= " $f";
+    } else {
+        &quit("badmode $mode");
+    }
+}
+
+if ($mode eq 'bymaint') {
+    print("$head\n") || &quit("output head: $!");
+    for $m (sort { $maintainercnt{$a} <=> $maintainercnt{$b} } keys %maintainercnt) {
+        printf("\n%s (%d $gBugs):\n",$m,$maintainercnt{$m})
+            || &quit("output mainthead: $!");
+        for $i (sort { $string{$a} cmp $string{$b} } split(/ /,$maintainerlist{$m})) {
+            printf($string{$i}) || &quit("output 1bymaint: $!");
+        }
+    }
+}
+
+close(STDOUT) || &quit("close stdout: $!");
diff --git a/scripts/text.in b/scripts/text.in
new file mode 100644 (file)
index 0000000..d70377a
--- /dev/null
@@ -0,0 +1,265 @@
+############################################################################
+# Here is a blurb for any mirrors of the web site.  Here's a sample:
+#
+#$gHTMLCopies = "Copies of the logs are available on the World Wide Web at<BR>
+# <A HREF=\"http://mirror1.domain\"><CODE>http://mirror1.domain</CODE></A><BR>
+# <A HREF=\"http://mirror2.domain\"><CODE>http://mirror2.domain</CODE></A>";
+############################################################################
+$gHTMLCopies = "";
+
+
+############################################################################
+# notice other links you want to note, like your list archives or project
+# home page.
+#
+#$gHTMLOtherPages = "Other Links of note:<BR>
+#      <A HREF=\"http://www.debian.org/\">The Debian Project</A><BR>
+#      <A HREF=\"http://another.domain\">Description of URL</A>";
+############################################################################
+$gHTMLOtherPages = "";
+
+
+############################################################################
+# list of other links you want to note, like your list archives or project
+# home page.  Some pages already have links in a list, this adds them to 
+# the end of the list.
+#
+#$gHTMLOtherPageList = "<LI><A HREF=\"http://www.debian.org/\">
+#      The Debian Project</A>
+#      <LI><A HREF=\"http://another.domain\">Description of URL</A>";
+############################################################################
+$gHTMLOtherPageList = "";
+
+
+############################################################################
+# gives explanation of bad maintainer situation and instructions on how to
+# correct.
+############################################################################
+$gBadMaintHtml = "";
+
+
+############################################################################
+# give directions here for how to find the proper title for Package:
+# pseudo header line.
+############################################################################
+$gHTMLFindPackage = "";
+
+
+############################################################################
+# If you have pseudo packages, place a blurb here.  For example:
+# $gHTMLPseudoDesc = "There are some pseudo-packages available for putting in
+# the <CODE>Package</CODE> line when reporting a $gBug in something other than an
+# actual $gProject software package.  There is 
+# <A HREF="db/ix/pseudopackages.html"> a list of these</A> on the $gBugs WWW 
+# pages.";
+############################################################################
+$gHTMLPseudoDesc = "";
+
+
+############################################################################
+# List any extra information you would like included in bug reports
+############################################################################
+$gXtraBugInfo = "";
+
+
+############################################################################
+# List any extra information you would like about reporting bugs
+############################################################################
+$gXtraReportingInfo = "";
+
+
+############################################################################
+# Process used by system to create Maintainers index file
+############################################################################
+$gCreateMaintainers = "";
+
+
+###########################################################################
+# You shouldn't have to modify anything below here unless it's for personal
+# preference.  Be very careful and don't touch unless you *know* what
+# you're doing.  Much of the stuff has hardcoded duplicates elsewhere.
+
+
+############################################################################
+# Description of the severities
+############################################################################
+$gHTMLSeverityDesc = "<DT><CODE>critical</CODE>
+       <DD>makes unrelated software on the system (or the whole system) break, or
+       causes serious data loss, or introduces a security hole on systems where
+       you install the package.
+
+       <DT><CODE>grave</CODE>
+       <DD>makes the package in question unuseable or mostly so, or causes data
+       loss, or introduces a security hole allowing access to the accounts of
+       users who use the package.
+
+       <DT><CODE>normal</CODE>
+       <DD>the default value, for normal $gBugs.
+
+       <DT><CODE>wishlist</CODE>
+       <DD>for any feature request, and also for any $gBugs that are very difficult
+       to fix due to major design considerations.";
+
+############################################################################
+# shows up at the end of (most) html pages.  You shouldn't have
+############################################################################
+$gHTMLTail = "<HR><ADDRESS><A HREF=\"$gMaintainerWebpage\">$gMaintainer</A> /
+ <A HREF=\"mailto:$gMaintainerEmail\">$gMaintainerEmail</A>.  Last modifed:
+ <!--timestamp-->
+ SUBSTITUTE_DTIME
+ <!--timestamp-->
+ (<A HREF=\"$gWebDomain/ix/zstamp.html\">timestamp page</A> available).
+         
+ <P>
+ Debian $gBug tracking system<BR>
+ copyright 1997 nCipher Corporation Ltd,<BR>
+ copyright 1994-1997 Ian Jackson,<BR>
+ copyright 1995 Steven Brenner.<BR>
+ <A HREF=\"http://www.chiark.greenend.org.uk/~ian/debbugs/\">
+ Available under the GPL.</A>
+ </ADDRESS>
+ </BODY>
+ </HTML>";
+
+############################################################################
+# Message on when reports are purged.  28 days is hardcoded.
+############################################################################
+$gHTMLExpireNote = "(Closed $gBugs are cleaned out 28 days after the last related message is received.)";
+
+############################################################################
+# Makeup of the stamp page
+############################################################################
+$gHTMLStamp = "<HTML><HEAD><TITLE>$gProject $gBugs - timestamp page</TITLE>
+       <LINK REV=\"made\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>Is this $gBug log or mirror up to date?</H1>
+
+       Unlike all the other $gBug pages, this small timestamp page is updated every
+       time the update check job runs.  If the timestamp here is recent it\'s
+       likely that the mirror in which you\'re reading it is up to date.
+       <P>
+       The last
+       <!--updateupdate-->update<!--/updateupdate-->
+       was at 
+       <STRONG><!--updatetime-->SUBSTITUTE_DTIME<!--/updatetime--></STRONG>;
+       The logs are usually checked every hour and updated if necessary.
+       <P>
+       For the $gBug index or for other information about $gProject and the $gBug 
+       system, see the <A HREF=\"../../\">$gBug system main contents page</A>.
+
+       <HR>
+       <ADDRESS>
+       <A HREF=\"mailto:$gMaintainerEmail\">$gMaintainerEmail</A>,
+       through the <A HREF=\"../../\">$gProject $gBug database</a>
+       </ADDRESS>
+       <!--version 1.0-4.3-->";
+
+############################################################################
+# Makeup of the indices pages
+############################################################################
+$gFullIndex = "<HTML><HEAD><TITLE>$gProject $gBugs - full index</TITLE>
+       <LINK REV=\"make\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug report logs - index</H1>
+
+       This index gives access to $gBugs sent to <CODE>submit\@$gEmailDomain</CODE>
+       but not yet marked as done, and to $gBugs marked as done but not yet purged
+       from the database (this happens 28 days after the last message relating to
+       the report).
+       <P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\">$gBug system top-level contents WWW
+       page</A>.
+
+
+       ";
+
+$gJunkIndex = "<HTML><HEAD><TITLE>$gProject $gBug reports - Junk</TITLE>
+       <LINK REV=\"made\" HREF=\"$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug reports - Junk</H1>
+
+       This is the index page for logs of messages not associated with a specific
+       $gBug report.
+       <P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\"> $gBug system top-level contents WWW
+       page</A>.
+
+
+       ";
+
+$gMaintIndex = "<HTML><HEAD><TITLE>$gProject $gBug reports by maintainer</TITLE>
+       <LINK REF=\"made\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug reports by maintainer</H1>
+
+       This page lists the package maintainers against whose packages there are
+       outstanding, fowarded or recently-closed $gBug reports.  A maintainer who
+       has several versions of their email address in the <CODE>Maintainer</CODE>
+       package control file field may appear several times.<P>
+       If the maintainers information here is not accurate, please see 
+       <A HREF=\"../../Developer.html#maintincorrect\">the developers\'
+       instructions</A> to find how this can happen and what to do about it. <P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\">$gBug system top-level contents WWW
+       page</A>.
+
+
+       ";
+
+$gPackageIndex = "<HTML><HEAD><TITLE>$gProject $gBug reports by package</TITLE>
+       <LINK REF=\"made\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug reports by package</H1>
+
+       This page lists the package against which there are outstanding, fowarded or
+       recently-closed $gBug reports.  A multi-binary package may appear several
+       times, once for each binary package name and once for the source package
+       name (if it is different).<P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\">$gBug system top-level contents WWW
+       page</A>.
+
+
+       ";
+
+$gSummaryIndex = "<HTML><HEAD><TITLE>$gProject $gBug report logs - summary index</TITLE>
+       <LINK REF=\"made\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug report logs - summary index</H1>
+
+       This summary index breiefly lists $gBugs sent to <CODE>submit\@$gEmailDomain
+       </CODE> but not yet marked as done, or as fowarded to an upstream author.  
+       Here they are sorted by reference number (and therefore by submission date, 
+       too).<P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\">$gBug system top-level contents WWW
+       page</A>.
+
+
+       ";
+
+$gPackageLog = "<HTML><HEAD><TITLE>$gProject $gBug report logs - index by package</TITLE>
+       <LINK REF=\"made\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug report logs - index by package</H1>
+
+       This summary index breiefly lists $gBugs sent to <CODE>submit\@$gEmailDomain
+       </CODE> but not yet marked as done, or as fowarded to an upstream author.  
+       Here they are sorted by package name.<P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\">$gBug system top-level contents WWW
+       page</A>.
+
+
+       ";
+
+$gPseudoIndex = "<HTML><HEAD><TITLE>$gProject $gBug report pseudo-packages</TITLE>
+       <LINK REF=\"made\" HREF=\"mailto:$gMaintainerEmail\">
+       </HEAD><BODY><H1>$gProject $gBug report pseudo-packages</H1>
+
+       This page lists the pseudo-packages available for use in the
+       <CODE>Package:</CODE> line in $gBug reports.<P>
+
+       See the <A HREF=\"../../Reporting.html\">instructions for reporting a
+       $gBug</A> for details of how to specify a <CODE>Package:</CODE> line.<P>
+       For other kinds of indices or for other information about $gProject and
+       the $gBug system, see <A HREF=\"../../\">$gBug system top-level contents WWW
+       page</A>.
+
+
+       ";