+For removal/archival purposes, all bugs with strong severity are
+assumed to have these tags set.
+
+Default: qw(unstable testing stable);
+
+=cut
+
+set_default(\%config,'removal_strong_severity_default_distribution_tags',
+ [qw(unstable testing stable)]
+ );
+
+
+=item removal_architectures
+
+For removal/archival purposes, these architectures are consulted if
+there is more than one architecture applicable. If the bug is in a
+package not in any of these architectures, the architecture actually
+checked is undefined.
+
+Default: value of default_architectures
+
+=cut
+
+set_default(\%config,'removal_architectures',
+ $config{default_architectures},
+ );
+
+
+=item package_name_re
+
+The regex which will match a package name
+
+Default: '[a-z0-9][a-z0-9\.+-]+'
+
+=cut
+
+set_default(\%config,'package_name_re',
+ '[a-z0-9][a-z0-9\.+-]+');
+
+=item package_version_re
+
+The regex which will match a package version
+
+Default: '[A-Za-z0-9:+\.-]+'
+
+=cut
+
+
+set_default(\%config,'package_version_re',
+ '[A-Za-z0-9:+\.~-]+');
+
+
+=item default_package
+
+This is the name of the default package. If set, bugs assigned to
+packages without a maintainer and bugs missing a Package: psuedoheader
+will be assigned to this package instead.
+
+Defaults to unset, which is the traditional debbugs behavoir
+
+=cut
+
+set_default(\%config,'default_package',
+ undef
+ );
+
+
+=item control_internal_requester
+
+This address is used by Debbugs::Control as the request address which
+sent a control request for faked log messages.
+
+Default:"Debbugs Internal Request <$config{maintainer_email}>"
+
+=cut
+
+set_default(\%config,'control_internal_requester',
+ "Debbugs Internal Request <$config{maintainer_email}>",
+ );
+
+=item control_internal_request_addr
+
+This address is used by Debbugs::Control as the address to which a
+faked log message request was sent.
+
+Default: "internal_control\@$config{email_domain}";
+
+=cut
+
+set_default(\%config,'control_internal_request_addr',
+ 'internal_control@'.$config{email_domain},
+ );
+
+
+=item exclude_from_control
+
+Addresses which are not allowed to send messages to control
+
+=cut
+
+set_default(\%config,'exclude_from_control',[]);
+
+
+
+=item default_severity
+
+The default severity of bugs which have no severity set
+
+Default: normal
+
+=cut
+
+set_default(\%config,'default_severity','normal');
+
+=item severity_display
+
+A hashref of severities and the informative text which describes them.
+
+Default:
+
+ {critical => "Critical $config{bugs}",
+ grave => "Grave $config{bugs}",
+ normal => "Normal $config{bugs}",
+ wishlist => "Wishlist $config{bugs}",
+ }
+
+=cut
+
+set_default(\%config,'severity_display',{critical => "Critical $config{bugs}",
+ grave => "Grave $config{bugs}",
+ serious => "Serious $config{bugs}",
+ important=> "Important $config{bugs}",
+ normal => "Normal $config{bugs}",
+ minor => "Minor $config{bugs}",
+ wishlist => "Wishlist $config{bugs}",
+ });
+
+=item show_severities
+
+A scalar list of the severities to show
+
+Defaults to the concatenation of the keys of the severity_display
+hashlist with ', ' above.
+
+=cut
+
+set_default(\%config,'show_severities',join(', ',keys %{$config{severity_display}}));
+
+=item strong_severities
+
+An arrayref of the serious severities which shoud be emphasized
+
+Default: [qw(critical grave)]
+
+=cut
+
+set_default(\%config,'strong_severities',[qw(critical grave)]);
+
+=item severity_list
+
+An arrayref of a list of the severities
+
+Defaults to the keys of the severity display hashref
+
+=cut
+
+set_default(\%config,'severity_list',[keys %{$config{severity_display}}]);
+
+=item obsolete_severities
+
+A hashref of obsolete severities with the replacing severity
+
+Default: {}
+
+=cut
+
+set_default(\%config,'obsolete_severities',{});
+
+=item tags
+
+An arrayref of the tags used
+
+Default: [qw(patch wontfix moreinfo unreproducible fixed)] and also
+includes the distributions.
+
+=cut
+
+set_default(\%config,'tags',[qw(patch wontfix moreinfo unreproducible fixed),
+ @{$config{distributions}}
+ ]);
+
+set_default(\%config,'tags_single_letter',
+ {patch => '+',
+ wontfix => '',
+ moreinfo => 'M',
+ unreproducible => 'R',
+ fixed => 'F',
+ }
+ );
+
+set_default(\%config,'bounce_froms','^mailer|^da?emon|^post.*mast|^root|^wpuser|^mmdf|^smt.*|'.
+ '^mrgate|^vmmail|^mail.*system|^uucp|-maiser-|^mal\@|'.
+ '^mail.*agent|^tcpmail|^bitmail|^mailman');
+
+set_default(\%config,'config_dir',dirname(exists $ENV{DEBBUGS_CONFIG_FILE}?$ENV{DEBBUGS_CONFIG_FILE}:'/etc/debbugs/config'));
+set_default(\%config,'spool_dir','/var/lib/debbugs/spool');
+
+=item usertag_dir
+
+Directory which contains the usertags
+
+Default: $config{spool_dir}/user
+
+=cut
+
+set_default(\%config,'usertag_dir',$config{spool_dir}.'/user');
+set_default(\%config,'incoming_dir','incoming');
+set_default(\%config,'web_dir','/var/lib/debbugs/www');
+set_default(\%config,'doc_dir','/var/lib/debbugs/www/txt');
+set_default(\%config,'lib_path','/usr/lib/debbugs');
+
+
+=item template_dir
+
+directory of templates; defaults to /usr/share/debbugs/templates.
+
+=cut
+
+set_default(\%config,'template_dir','/usr/share/debbugs/templates');
+
+
+set_default(\%config,'maintainer_file',$config{config_dir}.'/Maintainers');
+set_default(\%config,'maintainer_file_override',$config{config_dir}.'/Maintainers.override');
+set_default(\%config,'source_maintainer_file',$config{config_dir}.'/Source_maintainers');
+set_default(\%config,'source_maintainer_file_override',undef);
+set_default(\%config,'pseudo_maint_file',$config{config_dir}.'/pseudo-packages.maintainers');
+set_default(\%config,'pseudo_desc_file',$config{config_dir}.'/pseudo-packages.description');
+set_default(\%config,'package_source',$config{config_dir}.'/indices/sources');
+
+
+=item simple_versioning
+
+If true this causes debbugs to ignore version information and just
+look at whether a bug is done or not done. Primarily of interest for
+debbugs installs which don't track versions. defaults to false.
+
+=cut
+
+set_default(\%config,'simple_versioning',0);
+
+
+=item version_packages_dir
+
+Location where the version package information is kept; defaults to
+spool_dir/../versions/pkg
+
+=cut
+
+set_default(\%config,'version_packages_dir',$config{spool_dir}.'/../versions/pkg');
+
+=item version_time_index
+
+Location of the version/time index file. Defaults to
+spool_dir/../versions/idx/versions_time.idx if spool_dir/../versions
+exists; otherwise defaults to undef.
+
+=cut
+
+
+set_default(\%config,'version_time_index', -d $config{spool_dir}.'/../versions' ? $config{spool_dir}.'/../versions/indices/versions_time.idx' : undef);
+
+=item version_index
+
+Location of the version index file. Defaults to
+spool_dir/../versions/indices/versions.idx if spool_dir/../versions
+exists; otherwise defaults to undef.
+
+=cut
+
+set_default(\%config,'version_index',-d $config{spool_dir}.'/../versions' ? $config{spool_dir}.'/../versions/indices/versions.idx' : undef);
+
+=item binary_source_map
+
+Location of the binary -> source map. Defaults to
+spool_dir/../versions/indices/bin2src.idx if spool_dir/../versions
+exists; otherwise defaults to undef.
+
+=cut
+
+set_default(\%config,'binary_source_map',-d $config{spool_dir}.'/../versions' ? $config{spool_dir}.'/../versions/indices/binsrc.idx' : undef);
+
+=item source_binary_map
+
+Location of the source -> binary map. Defaults to
+spool_dir/../versions/indices/src2bin.idx if spool_dir/../versions
+exists; otherwise defaults to undef.
+
+=cut
+
+set_default(\%config,'source_binary_map',-d $config{spool_dir}.'/../versions' ? $config{spool_dir}.'/../versions/indices/srcbin.idx' : undef);
+
+
+
+set_default(\%config,'post_processall',[]);
+
+=item sendmail
+
+Sets the sendmail binary to execute; defaults to /usr/lib/sendmail
+
+=cut
+
+set_default(\%config,'sendmail','/usr/lib/sendmail');
+
+=item sendmail_arguments
+
+Default arguments to pass to sendmail. Defaults to C<qw(-oem -oi)>.
+
+=cut
+
+set_default(\%config,'sendmail_arguments',[qw(-oem -oi)]);
+
+=item spam_scan
+
+Whether or not spamscan is being used; defaults to 0 (not being used
+
+=cut
+
+set_default(\%config,'spam_scan',0);
+
+=item spam_crossassassin_db
+
+Location of the crosassassin database, defaults to
+spool_dir/../CrossAssassinDb
+
+=cut
+
+set_default(\%config,'spam_crossassassin_db',$config{spool_dir}.'/../CrossAssassinDb');
+
+=item spam_max_cross
+
+Maximum number of cross-posted messages
+
+=cut
+
+set_default(\%config,'spam_max_cross',6);
+
+
+=item spam_spams_per_thread
+
+Number of spams for each thread (on average). Defaults to 200
+
+=cut
+
+set_default(\%config,'spam_spams_per_thread',200);
+
+=item spam_max_threads
+
+Maximum number of threads to start. Defaults to 20
+
+=cut
+
+set_default(\%config,'spam_max_threads',20);
+
+=item spam_keep_running
+
+Maximum number of seconds to run without restarting. Defaults to 3600.
+
+=cut
+
+set_default(\%config,'spam_keep_running',3600);
+
+=item spam_mailbox
+
+Location to store spam messages; is run through strftime to allow for
+%d,%m,%Y, et al. Defaults to 'spool_dir/../mail/spam/assassinated.%Y-%m-%d'
+
+=cut
+
+set_default(\%config,'spam_mailbox',$config{spool_dir}.'/../mail/spam/assassinated.%Y-%m-%d');
+
+=item spam_crossassassin_mailbox
+
+Location to store crossassassinated messages; is run through strftime
+to allow for %d,%m,%Y, et al. Defaults to
+'spool_dir/../mail/spam/crossassassinated.%Y-%m-%d'
+
+=cut
+
+set_default(\%config,'spam_crossassassin_mailbox',$config{spool_dir}.'/../mail/spam/crossassassinated.%Y-%m-%d');
+
+=item spam_local_tests_only
+
+Whether only local tests are run, defaults to 0
+
+=cut
+
+set_default(\%config,'spam_local_tests_only',0);
+
+=item spam_user_prefs
+
+User preferences for spamassassin, defaults to $ENV{HOME}/.spamassassin/user_prefs
+
+=cut
+
+set_default(\%config,'spam_user_prefs',"$ENV{HOME}/.spamassassin/user_prefs");
+
+=item spam_rules_dir
+
+Site rules directory for spamassassin, defaults to
+'/usr/share/spamassassin'
+
+=cut
+
+set_default(\%config,'spam_rules_dir','/usr/share/spamassassin');
+
+=back
+
+
+=head2 Text Fields
+
+The following are the only text fields in general use in the scripts;
+a few additional text fields are defined in text.in, but are only used
+in db2html and a few other specialty scripts.
+
+Earlier versions of debbugs defined these values in /etc/debbugs/text,
+but now they are required to be in the configuration file. [Eventually
+the longer ones will move out into a fully fledged template system.]
+
+=cut
+
+=over
+
+=item bad_email_prefix
+
+This prefixes the text of all lines in a bad e-mail message ack.
+
+=cut
+
+set_default(\%config,'bad_email_prefix','');
+
+
+=item text_instructions
+
+This gives more information about bad e-mails to receive.in
+
+=cut
+
+set_default(\%config,'text_instructions',$config{bad_email_prefix});
+
+=item html_tail
+
+This shows up at the end of (most) html pages
+
+In many pages this has been replaced by the html/tail template.
+
+=cut
+
+set_default(\%config,'html_tail',<<END);
+ <ADDRESS>$config{maintainer} <<A HREF=\"mailto:$config{maintainer_email}\">$config{maintainer_email}</A>>.
+ Last modified:
+ <!--timestamp-->
+ SUBSTITUTE_DTIME
+ <!--timestamp-->
+ <P>
+ <A HREF=\"http://$config{web_domain}/\">Debian $config{bug} tracking system</A><BR>
+ Copyright (C) 1999 Darren O. Benham,
+ 1997,2003 nCipher Corporation Ltd,
+ 1994-97 Ian Jackson.
+ </ADDRESS>
+END
+
+
+=item html_expire_note
+
+This message explains what happens to archive/remove-able bugs
+
+=cut
+
+set_default(\%config,'html_expire_note',
+ "(Closed $config{bugs} are archived $config{remove_age} days after the last related message is received.)");
+
+=back
+
+=cut
+
+
+sub read_config{
+ my ($conf_file) = @_;
+ if (not -e $conf_file) {
+ print STDERR "configuration file '$conf_file' doesn't exist; skipping it\n" if $DEBUG;
+ return;
+ }
+ # first, figure out what type of file we're reading in.
+ my $fh = new IO::File $conf_file,'r'
+ or die "Unable to open configuration file $conf_file for reading: $!";
+ # A new version configuration file must have a comment as its first line
+ my $first_line = <$fh>;
+ my ($version) = defined $first_line?$first_line =~ /VERSION:\s*(\d+)/i:undef;
+ if (defined $version) {
+ if ($version == 1) {
+ # Do something here;
+ die "Version 1 configuration files not implemented yet";
+ }
+ else {
+ die "Version $version configuration files are not supported";
+ }
+ }
+ else {
+ # Ugh. Old configuration file
+ # What we do here is we create a new Safe compartment
+ # so fucked up crap in the config file doesn't sink us.
+ my $cpt = new Safe or die "Unable to create safe compartment";
+ # perldoc Opcode; for details
+ $cpt->permit('require',':filesys_read','entereval','caller','pack','unpack','dofile');
+ $cpt->reval(qq(require '$conf_file';));
+ die "Error in configuration file: $@" if $@;
+ # Now what we do is check out the contents of %EXPORT_TAGS to see exactly which variables
+ # we want to glob in from the configuration file
+ for my $variable (@{$EXPORT_TAGS{globals}}) {
+ my ($hash_name,$glob_name,$glob_type) = __convert_name($variable);
+ my $var_glob = $cpt->varglob($glob_name);
+ my $value; #= $cpt->reval("return $variable");
+ # print STDERR "$variable $value",qq(\n);
+ if (defined $var_glob) {{
+ no strict 'refs';
+ if ($glob_type eq '%') {
+ $value = {%{*{$var_glob}}} if defined *{$var_glob}{HASH};
+ }
+ elsif ($glob_type eq '@') {
+ $value = [@{*{$var_glob}}] if defined *{$var_glob}{ARRAY};
+ }
+ else {
+ $value = ${*{$var_glob}};
+ }
+ # We punt here, because we can't tell if the value was
+ # defined intentionally, or if it was just left alone;
+ # this tries to set sane defaults.
+ set_default(\%config,$hash_name,$value) if defined $value;
+ }}
+ }
+ }