From f96288efc416089567dac7bcfa674b1cd6931c97 Mon Sep 17 00:00:00 2001
From: John Denker <jsd@av8n.com>
Date: Sun, 15 Jul 2012 05:22:05 -0700
Subject: untested possible implementation of exeunt ... kill peers as soon as
 we know the msg is spam

---
 tools/hi-q.c   | 58 +++++++++++++++++++++++++++++++++++-----------------------
 tools/skrewt.c | 45 ++++++++++++++++++++++++++++++++++++---------
 2 files changed, 71 insertions(+), 32 deletions(-)

(limited to 'tools')

diff --git a/tools/hi-q.c b/tools/hi-q.c
index 9d85b7a..8107e27 100644
--- a/tools/hi-q.c
+++ b/tools/hi-q.c
@@ -22,7 +22,8 @@ using namespace std;
 #include <vector>
 #include <sstream>
 
-//  error exit codes, as stated in qmail.c
+//  error exit codes, mostly as stated in qmail.c
+const int ex_good = 0;
 const int ex_spam = 21;
 const int ex_syserr = 71;
 const int ex_comerr = 74;
@@ -392,7 +393,7 @@ int main(int argc, char** argv) {
   close(sync[rEnd]);
 
   close(0);             // Housecleaning: the reading end of stdin was
-                        // delegated to the first child, 
+                        // delegated to the first child,
                         // so we don't need it.
 
   if (verbose) for (unsigned int ii = 0; ii < nkids; ii++) {
@@ -406,33 +407,44 @@ int main(int argc, char** argv) {
     cerr << endl;
   }
 
-  for (unsigned int ii=0; ii<nkids-1; ii++){        /* loop over N-1 kids */
-                                                /* _not_ including last kid */
+// loop over N-1 kids ... _not_ including last kid
+  for (unsigned int ii=0; ii<nkids-1; ii++){
 #ifdef testing
     blurb(ii, kidpid);
 #else
-    somekid = waitpid(kidpid[ii], &kidstatus, WUNTRACED);
-    if (somekid) {}             // avoid silly compiler warning
-    if (WIFEXITED(kidstatus)) {
-      int sts = WEXITSTATUS(kidstatus);
-      if (sts == 1) {
-        cerr << "hi-q says: kid " << ii
-             << " i.e. '" << filter[ii][0] << "' reports spam."
-             << endl;
-        panic(ex_spam);
-      }
-      if (sts != 0) {
-        cerr << "hi-q says: kid " << ii
-             << " i.e. '" << filter[ii][0] << "'"
-             << " suffered an error: " << sts
-             << endl;
-        panic(ex_syserr);
+    for (;;){
+      somekid = waitpid(kidpid[ii], &kidstatus, WUNTRACED);
+      if (somekid) {}             // avoid silly compiler warning
+      if (WIFEXITED(kidstatus)) {
+        int sts = WEXITSTATUS(kidstatus);
+        if (sts == 1) {
+          cerr << "hi-q says: kid " << ii
+               << " i.e. '" << filter[ii][0] << "' reports spam."
+               << endl;
+          panic(ex_spam);
+        }
+        if (sts != 0) {
+          cerr << "hi-q says: kid " << ii
+               << " i.e. '" << filter[ii][0] << "'"
+               << " exited with bad status: " << sts
+               << endl;
+          panic(ex_syserr);
+        }
+        break;                 // kidstatus==0 means clean exit;
+                               // go check other kids
+      } else if (WIFSIGNALED(kidstatus)) {
+          cerr << "hi-q says: kid " << ii
+               << " i.e. '" << filter[ii][0] << "'"
+               << " was killed by signal: " << WTERMSIG(kidstatus)
+               << endl;
+
+        panic(ex_syserr);      // any kill, not a normal exit
+      } else {
+        // some status change other than exit or kill
+        // perhaps stopped for terminal input
       }
-      /* otherwise kidstatus==0 and we fall through */
     }
-    else panic(ex_syserr);      // any kill, not a normal exit
 #endif
-
   }
 
 //xx fprintf(stderr, "slurping %d %d\n", 1, loose_end);
diff --git a/tools/skrewt.c b/tools/skrewt.c
index b81f0ea..2ca32a4 100644
--- a/tools/skrewt.c
+++ b/tools/skrewt.c
@@ -8,6 +8,9 @@
 #include <stdlib.h>             /* for exit() */
 #include <string>               /* for strcmp() */
 #include <ctype.h>              /* toupper */
+#include <signal.h>
+
+#include <stdio.h>              /* perror */
 
 using namespace std;
 
@@ -30,6 +33,11 @@ void usage(const int sts){
   exit(sts);
 }
 
+// exit codes, compatible with spamassassin (not with qmail-queue)
+const int sa_good(0);
+const int sa_spam(1);
+const int sa_usage(64);
+
 /////////////////////////////////////////////////////////
 // Case insensitive comparison of strings
 
@@ -97,6 +105,25 @@ int prefix(const string shorter, const string longer){
   return shorter == longer.substr(0, shorter.length());
 }
 
+void exeunt(const int sts){
+  if (sts == sa_good) exit(sts);
+
+  const char* foo = getenv("HI_Q_GROUP");
+  if (!foo) exit(sts);
+
+// No point in signalling ourself:
+  sighandler_t rslt = signal(SIGUSR1, SIG_IGN);
+  if (rslt == SIG_ERR) {
+    cerr << "error setting signal" << endl;
+  }
+  int k = kill(-atoi(foo), SIGUSR1);
+  if (k) {
+    cerr << "kill failed on group " << atoi(foo) << " ... ";
+    perror(0);
+  }
+  exit(sts);
+}
+
 ////////////////////////////////////////////////////////////
 int main(int _argc, const char** _argv){
 ////  pid_t pid = getpid();
@@ -117,18 +144,18 @@ int main(int _argc, const char** _argv){
     if (prefix(arg, "-maxsize")) {
       if (!argc) {
         cerr << "Option -maxsize requires an argument" << endl;
-        exit(1);
+        exit(sa_usage);
       }
       maxsize = atoi(*argv); argv++; argc--;
     }
     if (arg.substr(0,1) == "-") {
       cerr << "Unrecognized option '" << arg << "'" << endl;
       cerr << "For help, try:  " << progname << " -help" << endl;
-      exit(1);
+      exit(sa_usage);
     } else {
       cerr << "Extraneous verbiage '" << arg << "'" << endl;
       cerr << "For help, try:  " << progname << " -help" << endl;
-      exit(1);
+      exit(sa_usage);
     }
   }
 
@@ -157,14 +184,14 @@ int main(int _argc, const char** _argv){
         msgsize += line.length()+1;
         if (msgsize > maxsize) {
           cerr << "skrewt rejection: bigger than " << maxsize << endl;
-          exit(1);
+          exeunt(sa_spam);
         }
         header += "\n" + line;
       }
       if (header.length() == 0) {
         if (!gotdate) {
           cerr << "skrewt rejection: no date" << endl;
-          exit(1);              // disallow mail with no date
+          exeunt(sa_spam);              // disallow mail with no date
         }
         inheads = 0;
       }
@@ -212,7 +239,7 @@ int main(int _argc, const char** _argv){
         } else if (headword == "subject") {
           if (rest.find("-please-bounce-this-") != string::npos) {
             cerr << "skrewt rejection: by request" << endl;
-            exit(1);
+            exeunt(sa_spam);
           }
         }
       }
@@ -223,7 +250,7 @@ int main(int _argc, const char** _argv){
         msgsize += line.length()+1;
         if (msgsize > maxsize) {
           cerr << "skrewt rejection: bigger than " << maxsize << endl;
-          exit(1);
+          exeunt(sa_spam);
         }
         if (line == "--" + boundary) {
           inheads = 1;
@@ -239,8 +266,8 @@ int main(int _argc, const char** _argv){
   if (0) cerr << "textlines: " << textlines << endl;
   if (!textlines) {
     cerr << "skrewt rejection: no text" << endl;
-    exit(1);
+    exeunt(sa_spam);
   }
   cerr << "skrewt normal completion" << endl;
-  return 0;
+  exit(sa_good);
 }
-- 
cgit v1.2.3