gecko-dev/webtools/bugzilla/processmail
1998-09-15 21:49:26 +00:00

278 lines
6.7 KiB
Perl
Executable File

#!/usr/bonsaitools/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.0 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are Copyright (C) 1998
# Netscape Communications Corporation. All Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# To recreate the shadow database, run "processmail regenerate" .
use diagnostics;
use strict;
require "globals.pl";
$| = 1;
umask(0);
$::lockcount = 0;
sub Lock {
if ($::lockcount <= 0) {
$::lockcount = 0;
if (!open(LOCKFID, ">>data/maillock")) {
mkdir "data", 0777;
chmod 0777, "data";
open(LOCKFID, ">>data/maillock") || die "Can't open lockfile.";
}
my $val = flock(LOCKFID,2);
if (!$val) { # '2' is magic 'exclusive lock' const.
print "Lock failed: $val\n";
}
chmod 0666, "data/maillock";
}
$::lockcount++;
}
sub Unlock {
$::lockcount--;
if ($::lockcount <= 0) {
flock(LOCKFID,8); # '8' is magic 'unlock' const.
close LOCKFID;
}
}
sub FileSize {
my ($filename) = (@_);
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks)
= stat($filename);
if (defined $size) {
return $size;
}
return -1;
}
sub Different {
my ($file1, $file2) = (@_);
my $size1 = FileSize($file1);
my $size2 = FileSize($file2);
if ($size1 != $size2) {
return 1;
}
open(FID1, "<$file1") || die "Can't open $file1";
open(FID2, "<$file2") || die "Can't open $file2";
my $d1;
my $d2;
if (read(FID1, $d1, $size1) ne $size1) {
die "Can't read $size1 bytes from $file1";
}
if (read(FID2, $d2, $size2) ne $size2) {
die "Can't read $size2 bytes from $file2";
}
close FID1;
close FID2;
return ($d1 ne $d2);
}
sub DescCC {
my ($cclist) = (@_);
if (scalar(@$cclist) <= 0) {
return "";
}
return "Cc: " . join(", ", $cclist) . "\n";
}
sub GetBugText {
my ($id) = (@_);
undef %::bug;
my @collist = ("bug_id", "product", "version", "rep_platform", "op_sys",
"bug_status", "resolution", "priority", "bug_severity",
"area", "assigned_to", "reporter", "bug_file_loc",
"short_desc", "component");
my $query = "select " . join(", ", @collist) .
" from bugs where bug_id = $id";
SendSQL($query);
my @row;
if (!(@row = FetchSQLData())) {
return "";
}
foreach my $field (@collist) {
$::bug{$field} = shift @row;
if (!defined $::bug{$field}) {
$::bug{$field} = "";
}
}
$::bug{'assigned_to'} = DBID_to_name($::bug{'assigned_to'});
$::bug{'reporter'} = DBID_to_name($::bug{'reporter'});
$::bug{'long_desc'} = GetLongDescription($id);
my @cclist;
@cclist = split(/,/, ShowCcList($id));
$::bug{'cclist'} = \@cclist;
return "Bug\#: $id
Product: $::bug{'product'}
Version: $::bug{'version'}
Platform: $::bug{'rep_platform'}
OS/Version: $::bug{'op_sys'}
Status: $::bug{'bug_status'}
Resolution: $::bug{'resolution'}
Severity: $::bug{'bug_severity'}
Priority: $::bug{'priority'}
Component: $::bug{'component'}
Area: $::bug{'area'}
AssignedTo: $::bug{'assigned_to'}
ReportedBy: $::bug{'reporter'}
URL: $::bug{'bug_file_loc'}
" . DescCC($::bug{'cclist'}) . "Summary: $::bug{'short_desc'}
$::bug{'long_desc'}
";
}
sub fixaddresses {
my ($list) = (@_);
my @result;
my %seen;
foreach my $i (@$list) {
if (!defined $::nomail{$i} && !defined $seen{$i}) {
push @result, $i;
$seen{$i} = 1;
}
}
return join(", ", @result);
}
sub Log {
my ($str) = (@_);
Lock();
open(FID, ">>data/maillog") || die "Can't write to data/maillog";
print FID time2str("%D %H:%M", time()) . ": $str\n";
close FID;
Unlock();
}
ConnectToDatabase();
Lock();
# foreach i [split [read_file -nonewline "okmail"] "\n"] {
# set okmail($i) 1
# }
if (open(FID, "<data/nomail")) {
while (<FID>) {
$::nomail{trim($_)} = 1;
}
close FID;
}
my $regenerate = 0;
if ($ARGV[0] eq "regenerate") {
$regenerate = 1;
$#ARGV = -1;
SendSQL("select bug_id from bugs order by bug_id");
my @row;
while (@row = FetchSQLData()) {
push @ARGV, $row[0];
}
}
foreach my $i (@ARGV) {
my $old = "shadow/$i";
my $new = "shadow/$i.tmp.$$";
my $diffs = "shadow/$i.diffs.$$";
my $verb = "Changed";
if (!stat($old)) {
mkdir "shadow", 0777;
chmod 0777, "shadow";
open(OLD, ">$old") || die "Couldn't create null $old";
close OLD;
$verb = "New";
}
my $text = GetBugText($i);
if ($text eq "") {
die "Couldn't find bug $i.";
}
open(FID, ">$new") || die "Couldn't create $new";
print FID $text;
close FID;
if (Different($old, $new)) {
system("diff -c $old $new > $diffs");
my $tolist = fixaddresses([$::bug{'assigned_to'}, $::bug{'reporter'}]);
my $cclist = fixaddresses($::bug{'cclist'});
my $logstr = "Bug $i changed";
if ($tolist ne "" || $cclist ne "") {
my %substs;
$substs{"to"} = $tolist;
$substs{"cc"} = $cclist;
$substs{"bugid"} = $i;
$substs{"diffs"} = "";
open(DIFFS, "<$diffs") || die "Can't open $diffs";
while (<DIFFS>) {
$substs{"diffs"} .= $_;
}
close DIFFS;
$substs{"neworchanged"} = $verb;
$substs{"summary"} = $::bug{'short_desc'};
my $msg = PerformSubsts(Param("changedmail"), \%substs);
if (!$regenerate) {
open(SENDMAIL, "|/usr/lib/sendmail -t") ||
die "Can't open sendmail";
print SENDMAIL $msg;
close SENDMAIL;
$logstr = "$logstr; mail sent to $tolist $cclist";
}
}
unlink($diffs);
Log($logstr);
}
rename($new, $old) || die "Can't rename $new to $old";
chmod 0666, $old;
if ($regenerate) {
print "$i ";
}
}
exit;