--- qmail-dk.c.orig	2006-11-26 07:48:06.000000000 +0300
+++ qmail-dk.c	2006-11-26 07:45:28.000000000 +0300
@@ -25,6 +25,38 @@
 #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
 #define ADDR 1003
 
+/* qmail-queue exit codes defines: */
+
+#define EXIT_TMP_ERR_UNDEF_12      12  /* qq: UNDEFINED, treated as temporary error. */
+#define EXIT_TMP_ERR_UNDEF_13      13  /* qq: UNDEFINED, treated as temporary error. */
+#define EXIT_500                   31  /* qq: permanent refusal to accept message SMTP: 5XX code */
+#define EXIT_TMP_ERR_UNDEF_32      32  /* qq: UNDEFINED, treated as temporary error. */
+#define EXIT_400                   71  /* qq: temporary refusal to accept message */
+#define EXIT_OUT_OF_MEM            51  /* qq: exit due to out of memory */
+#define EXIT_TIMEOUT               52  /* qq: Timeout error */ 
+#define EXIT_WRITE_ERR             53  /* qq: exit with message about write error */ 
+#define EXIT_READ_MSG_ENV_ERR      54  /* qq: "Unable to read the message or envelope" */ 
+#define EXIT_NO_CFG                55  /* qq: Unable to read a configuration file. */ 
+#define EXIT_TMP_ERR_UNDEF_59      59  /* qq: UNDEFINED, treated as temporary error. */
+#define EXIT_QMAIL_DIR_ERR         61  /* qq: Problem with the qmail home directory. */
+#define EXIT_FILE_PID_ERR          63  /* qq: Problem with queue/pid.  */
+#define EXIT_FILE_MESS_ERR         64  /* qq: Problem with queue/mess. */
+#define EXIT_FILE_INTD_ERR         65  /* qq: Problem with queue/intd. */
+#define EXIT_FILE_TODO_ERR         66  /* qq: Problem with queue/todo. */
+#define EXIT_COMM_ERROR            74  /* qq: Connection to mail server succeeded, but communication failed. */ 
+#define EXIT_BUG                   81  /* qq: exit due to internal bug */ 
+#define EXIT_MSG                   82  /* qq: exit with custom error message */ 
+#define EXIT_TMP_ERR_UNDEF_120    120  /* qq: UNDEFINED, treated as temporary error. */
+
+
+char RejectMsg[500];
+
+void log_message( message )
+char *message;
+{
+     fprintf(stderr, "qmail-dk:[%d]: %s\n", getppid(), message);
+}
+
 char inbuf[2048];
 struct substdio ssin;
 char outbuf[256];
@@ -39,18 +71,55 @@
 int readfd;
 
 void die(e) int e; { _exit(e); }
-void die_write() { die(53); }
-void die_read() { die(54); }
-void sigalrm() { /* thou shalt not clean up here */ die(52); }
-void sigbug() { die(81); }
-void maybe_die_dk(e) DK_STAT e; {
+void die_write() { 
+     log_message(" Dying due to write operation error (disk full?)."); 
+     die(EXIT_WRITE_ERR); 
+}
+void die_read() { die(EXIT_READ_MSG_ENV_ERR); }
+void die_out_of_mem() { 
+     log_message(" Dying due to out-of-memory condition."); 
+     die(EXIT_OUT_OF_MEM); 
+}
+
+void die_custom_msg(msg, fatal) 
+char *msg; 
+int fatal;
+{
+    if(fatal)
+     snprintf(RejectMsg,sizeof(RejectMsg), "D%s", msg);
+    else
+     snprintf(RejectMsg,sizeof(RejectMsg), "Z%s", msg);
+    write(4, RejectMsg, strlen(RejectMsg));
+    
+    die(EXIT_MSG);
+}
+
+void sigalrm() { /* thou shalt not clean up here */ die(EXIT_TIMEOUT); }
+void sigbug() { die(EXIT_BUG); }
+
+void maybe_die_dk(e, vrfy) 
+DK_STAT e; 
+int vrfy;
+{
   switch(e) {
-  case DK_STAT_BADKEY: _exit(55);
-  case DK_STAT_CANTVRFY: _exit(74);
-  case DK_STAT_NORESOURCE: _exit(51);
-  case DK_STAT_ARGS: _exit(12);
-  case DK_STAT_SYNTAX: _exit(31);
-  case DK_STAT_INTERNAL: _exit(81);
+  case DK_STAT_BADKEY: 
+       if(vrfy) { die_custom_msg("DomainKeys: Unusable public key. (temporary failure).", 0); }
+       else { 
+            log_message(" Cannot sign message due to unusable private key."); 
+            _exit(EXIT_NO_CFG); 
+       }
+  case DK_STAT_CANTVRFY: 
+       die_custom_msg("DomainKeys: Cannot get domain key to verify signature (temporary failure).", 0);
+  case DK_STAT_NORESOURCE:
+       log_message(" Dying due to out-of-memory condition."); 
+       die_out_of_mem();
+  case DK_STAT_ARGS: 
+       _exit(EXIT_TMP_ERR_UNDEF_12);
+  case DK_STAT_SYNTAX: 
+       log_message(" Dropping message due to invalid syntax."); 
+       die_custom_msg("DomainKeys: Message is not valid syntax. Signature could not be checked.", 1);
+  case DK_STAT_INTERNAL: 
+       _exit(EXIT_BUG);
   }
 }
 
@@ -81,17 +150,17 @@
  seq = 1;
  len = pidfmt((char *) 0,seq);
  pidfn = alloc(len);
- if (!pidfn) die(51);
+ if (!pidfn) die_out_of_mem();
 
  for (seq = 1;seq < 10;++seq)
   {
-   if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
+   if (pidfmt((char *) 0,seq) > len) die(EXIT_BUG); /* paranoia */
    pidfmt(pidfn,seq);
    messfd = open_excl(pidfn);
    if (messfd != -1) return;
   }
 
- die(63);
+ die(EXIT_FILE_PID_ERR);
 }
 
 char tmp[FMT_ULONG];
@@ -117,50 +186,50 @@
  from = dk_from(dk);
  i = str_chr(keyfn, '%');
  if (keyfn[i]) {
-   if (!stralloc_copyb(&keyfnfrom,keyfn,i)) die(51);
-   if (!stralloc_cats(&keyfnfrom,from)) die(51);
-   if (!stralloc_cats(&keyfnfrom,keyfn + i + 1)) die(51);
+   if (!stralloc_copyb(&keyfnfrom,keyfn,i)) die_out_of_mem();
+   if (!stralloc_cats(&keyfnfrom,from)) die_out_of_mem();
+   if (!stralloc_cats(&keyfnfrom,keyfn + i + 1)) die_out_of_mem();
  } else {
-   if (!stralloc_copys(&keyfnfrom,keyfn)) die(51);
+   if (!stralloc_copys(&keyfnfrom,keyfn)) die_out_of_mem();
  }
- if (!stralloc_0(&keyfnfrom)) die(51);
+ if (!stralloc_0(&keyfnfrom)) die_out_of_mem();
 
  switch(control_readfile(&dksignature,keyfnfrom.s,0)) {
  case 0:
    if (keyfn[i]) return;
-   die(32);
+   die(EXIT_TMP_ERR_UNDEF_32);
  case 1: break;
- default: die(31);
+ default: die(EXIT_500);
  }
  for(i=0; i < dksignature.len; i++)
    if (dksignature.s[i] == '\0') dksignature.s[i] = '\n';
- if (!stralloc_0(&dksignature)) die(51);
+ if (!stralloc_0(&dksignature)) die_out_of_mem();
 
  st = dk_getsig(dk, dksignature.s, advice, sizeof(advice));
- maybe_die_dk(st);
+ maybe_die_dk(st, 0);
 
  if (!stralloc_cats(&dkoutput,
    "Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys\n"
 	   "DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;\n"
-	   "  s=")) die(51);
+	   "  s=")) die_out_of_mem();
  selector = keyfn;
  while (*keyfn) {
    if (*keyfn == '/') selector = keyfn+1;
     keyfn++;
  }
- if (!stralloc_cats(&dkoutput,selector)) die(51);
- if (!stralloc_cats(&dkoutput,"; d=")) die(51);
+ if (!stralloc_cats(&dkoutput,selector)) die_out_of_mem();
+ if (!stralloc_cats(&dkoutput,"; d=")) die_out_of_mem();
  if (from) {
-   if (!stralloc_cats(&dkoutput,from)) die(51);
- } else if (!stralloc_cats(&dkoutput,"unknown")) die(51);
- if (!stralloc_cats(&dkoutput,";\n  b=")) die(51);
- if (!stralloc_cats(&dkoutput,advice)) die(51);
- if (!stralloc_cats(&dkoutput,"  ;\n")) die(51);
+   if (!stralloc_cats(&dkoutput,from)) die_out_of_mem();
+ } else if (!stralloc_cats(&dkoutput,"unknown")) die_out_of_mem();
+ if (!stralloc_cats(&dkoutput,";\n  b=")) die_out_of_mem();
+ if (!stralloc_cats(&dkoutput,advice)) die_out_of_mem();
+ if (!stralloc_cats(&dkoutput,"  ;\n")) die_out_of_mem();
 }
 
 static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
 
-void main(int argc, char *argv[])
+int main(int argc, char *argv[])
 {
  unsigned int len;
  char ch;
@@ -187,14 +256,14 @@
 
  if (dksign || dkverify) {
    dklib = dk_init(0);
-   if (!dklib) die(51);
+   if (!dklib) die_out_of_mem();
  }
  if (dksign) {
     dk = dk_sign(dklib, &st, DK_CANON_NOFWS);
-    if (!dk) die(31);
+    if (!dk) die(EXIT_500);
  } else if (dkverify) {
     dk = dk_verify(dklib, &st);
-    if (!dk) die(31);
+    if (!dk) die(EXIT_500);
  }
 
  mypid = getpid();
@@ -211,7 +280,7 @@
 
  pidopen();
  readfd = open_read(pidfn);
- if (unlink(pidfn) == -1) die(63);
+ if (unlink(pidfn) == -1) die(EXIT_FILE_PID_ERR);
 
  substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
  substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
@@ -229,7 +298,7 @@
      for(i=0; i < n; i++) {
        if (x[i] == '\n') st = dk_message(dk, "\r\n", 2);
        else st = dk_message(dk, x+i, 1);
-       maybe_die_dk(st);
+       maybe_die_dk(st, dkverify);
       }
    if (substdio_put(&ssout,x,n) == -1) die_write();
    substdio_SEEK(&ssin,n);
@@ -239,12 +308,12 @@
 
  if (dksign || dkverify) {
    st = dk_eom(dk, (void *)0);
-   maybe_die_dk(st);
+   maybe_die_dk(st, dkverify);
    if (dksign) {
      write_signature(dk, dksign);
    } else if (dkverify) {
      char *status;
-     if (!stralloc_copys(&dkoutput,"DomainKey-Status: ")) die(51);
+     if (!stralloc_copys(&dkoutput,"DomainKey-Status: ")) die_out_of_mem();
      switch(st) {
      case DK_STAT_OK:         status = "good        "; break;
      case DK_STAT_BADSIG:     status = "bad         "; break;
@@ -258,14 +327,14 @@
      case DK_STAT_NORESOURCE: status = "no resources"; break;
      case DK_STAT_REVOKED:    status = "revoked     "; break;
      }
-     if (!stralloc_cats(&dkoutput,status)) die(51);
-     if (!stralloc_cats(&dkoutput,"\n")) die(51);
-     if (dkverify[str_chr(dkverify, 'A'+st)]) die(13);
-     if (dkverify[str_chr(dkverify, 'a'+st)]) die(82);
+     if (!stralloc_cats(&dkoutput,status)) die_out_of_mem();
+     if (!stralloc_cats(&dkoutput,"\n")) die_out_of_mem();
+     if (dkverify[str_chr(dkverify, 'A'+st)]) die(EXIT_TMP_ERR_UNDEF_13);
+     if (dkverify[str_chr(dkverify, 'a'+st)]) die(EXIT_MSG);
    }
  }
 
- if (pipe(pim) == -1) die(59);
+ if (pipe(pim) == -1) die(EXIT_TMP_ERR_UNDEF_59);
  
  switch(pid = vfork()) {
  case -1:
@@ -273,10 +342,10 @@
    die(58);
  case 0:
    close(pim[1]);
-   if (fd_move(0,pim[0]) == -1) die(120);
-   if (chdir(auto_qmail) == -1) die(61);
+   if (fd_move(0,pim[0]) == -1) die(EXIT_TMP_ERR_UNDEF_120);
+   if (chdir(auto_qmail) == -1) die(EXIT_QMAIL_DIR_ERR);
    execv(*binqqargs,binqqargs);
-   die(120);
+   die(EXIT_TMP_ERR_UNDEF_120);
  }
 
  close(pim[0]);
