From: Sven M. Hallberg Subject: vacation(1): consume all input To: tech@openbsd.org Date: Thu, 22 Aug 2024 09:45:31 +0200 Another problem with vacation, at least in combination with smtpd(8) is that it will exit(0) when it determines that it wants to do nothing with the particular message. This happens, typically, after inspecting the headers and finding that this message is not directly addressed (via To: or Cc:) to the user. So it exits without consuming the rest of the message. OpenSMTPd will interpret this as "mda terminated prematurely", treat the message as not delivered, keep it in the queue, and report warnings and eventual failure to its unsuspecting originator. Should smtpd be okay with an early exit(0) or should vacation always fully consume its input? Patch for the latter case below; applies on top of my previous one. --- vacation.c.bak Thu Aug 22 09:32:39 2024 +++ vacation.c Wed Aug 21 10:45:09 2024 @@ -73,6 +73,7 @@ char from[MAXLINE]; char subj[MAXLINE]; +void done(void); int junkmail(void); int nsearch(char *, char *); void readheaders(void); @@ -175,11 +176,28 @@ sendmessage(pw->pw_name); } else (void)(db->close)(db); - exit(0); + done(); /* NOTREACHED */ } /* + * done -- + * consume all remaining input and exit with success + * + * This is a waste, but smtpd might interpret anything else as "premature + * termination" and keep the message queued as undelivered. + */ +void +done(void) +{ + char buf[MAXLINE]; + + while (fgets(buf, sizeof(buf), stdin) != NULL) + ; + exit(0); +} + +/* * readheaders -- * read mail headers */ @@ -213,7 +231,7 @@ if (*p == '\0') break; /* Auto-Submitted: no */ } - exit(0); + done(); case 'F': /* "From " */ case 'f': cont = 0; @@ -224,7 +242,7 @@ (void)strlcpy(from, buf + 5, sizeof(from)); from[strcspn(from, "\n")] = '\0'; if (junkmail()) - exit(0); + done(); } break; case 'L': /* "List-Id:" */ @@ -235,7 +253,7 @@ * mailing list, cf. RFC2919. */ if (strncasecmp(buf, "List-Id:", 8) == 0) - exit(0); + done(); break; case 'R': /* "Return-Path:" */ case 'r': @@ -257,7 +275,7 @@ } from[strcspn(from, "\n")] = '\0'; if (junkmail()) - exit(0); + done(); break; case 'P': /* "Precedence:" */ case 'p': @@ -269,7 +287,7 @@ if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4) || !strncasecmp(p, "list", 4)) - exit(0); + done(); break; case 'S': /* Subject: */ case 's': @@ -308,7 +326,7 @@ tome += nsearch(cur->name, buf); } if (!tome) - exit(0); + done(); if (!*from) { /* * No initial "From " line or "Return-Path:" header. @@ -316,7 +334,7 @@ * NB: Return-Path is optional. If it is not present, we * shall not respond, cf. RFC 3834. */ - exit(0); + done(); } }