Re: sendbug(1) patch
On 12/04/08 23:50 -0400, Ray wrote:
>Sendbug was rewritten some time ago, so your patch doesn't apply, sorry.
>
>I was unaware of problems people had with sendmail, is this a
>widespread problem?
>
>-Ray-
>
I'm still in obsd 4.1, thanks for your pointer.
When I use the sendmail to deliver messages to some mail servers, I got
the message returned with errors like:
> Diagnostic-Code: SMTP; 550 The IP address x.x.x.x has been listed on a
> realtime blacklist ...
I suppose my ISP's NAT allocated a notorious address for me. So I have
to use an alternative SMTP server to send the mail.
The following patch against the new (rewritten) sendbug (v4.2), with the
PR_AGENT feature and a few minor fixes.
Anyway, another use of the 'PR_AGENT' feature is, to help test sendbug's
send-outs, like:
$ export PR_AGENT="tee mail.out"
$ ./sendbug
:)
diff -u /usr/src/usr.bin/sendbug/sendbug.1 sendbug/sendbug.1
--- /usr/src/usr.bin/sendbug/sendbug.1 Fri Jun 1 03:20:16 2007
+++ sendbug/sendbug.1 Tue Apr 15 18:47:53 2008
@@ -91,6 +91,8 @@
Filename of PR form to use instead of using the built-in form.
Such a PR form can be partially pre-completed to make the
process faster.
+.It Ev PR_AGENT
+Specifies an alternate Mail Transfer Agent to send the PR
.It Ev TMPDIR
Specifies a directory for temporary files to be created.
The default is
@@ -103,7 +105,8 @@
.El
.Sh SEE ALSO
.Xr crash 8 ,
-.Xr dmesg 8
+.Xr dmesg 8 ,
+.Xr sendmail 8
.Sh AUTHORS
.Nm
was written from scratch for the public domain by
diff -u /usr/src/usr.bin/sendbug/sendbug.c sendbug/sendbug.c
--- /usr/src/usr.bin/sendbug/sendbug.c Fri Jan 4 08:50:09 2008
+++ sendbug/sendbug.c Tue Apr 15 18:53:29 2008
@@ -303,39 +303,81 @@
sendmail(const char *pathname)
{
int filedes[2];
+ pid_t pid;
if (pipe(filedes) == -1) {
warn("pipe: unsent report in %s", pathname);
return (-1);
}
- switch (fork()) {
+
+ pid = fork();
+
+ switch (pid) {
case -1:
warn("fork error: unsent report in %s",
pathname);
return (-1);
case 0:
close(filedes[1]);
- if (dup2(filedes[0], STDIN_FILENO) == -1) {
- warn("dup2 error: unsent report in %s",
- pathname);
- return (-1);
+
+ if (filedes[0] != STDIN_FILENO) { /* defensive measure */
+ if (dup2(filedes[0], STDIN_FILENO) == -1) {
+ warn("dup2 error: unsent report in %s",
+ pathname);
+ return (-1);
+ }
+ close(filedes[0]);
}
+
+ char *mta_cmd;
+
+ if ( (mta_cmd = getenv("PR_AGENT")) == NULL ) {
+ execl("/usr/sbin/sendmail", "sendmail",
+ "-oi", "-t", (void *)NULL);
+ } else {
+ execl(_PATH_BSHELL, "sh", "-c", mta_cmd,
+ (void *) NULL);
+ }
+
+ /* shouldn't reach here */
+ warn("exec error: unsent report in %s", pathname);
+ _exit(127);
+
+ default:
close(filedes[0]);
- execl("/usr/sbin/sendmail", "sendmail",
- "-oi", "-t", (void *)NULL);
- warn("sendmail error: unsent report in %s",
- pathname);
- return (-1);
- default:
- close(filedes[0]);
/* Pipe into sendmail. */
if (send_file(pathname, filedes[1]) == -1) {
+ wantcleanup = 0;
warn("send_file error: unsent report in %s",
pathname);
return (-1);
}
+
close(filedes[1]);
- wait(NULL);
+
+ /* We should check the return value of MTA to see whether the
+ * PR has been sent successfully, if not, save the user's work
+ * (unsent report).
+ */
+
+ int status, ret_child = 0; /* the return value of MTA */
+ while (waitpid(pid, &status, 0) == -1)
+ if (errno != EINTR)
+ return(-1);
+
+ ret_child = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+
+ if (ret_child != 0) {
+ wantcleanup = 0;
+ /*
+ * warn("sendmail error: unsent report in %s",
+ * pathname);
+ */
+ fprintf(stderr, "MTA error (%d returned):"
+ " unsent report in %s", ret_child,
+ pathname);
+ return(-1);
+ }
break;
}
return (0);
@@ -467,7 +509,9 @@
if (ep)
copylen = sp - buf;
else
- copylen = len;
+ /* The final newline has been stripped,
+ * so minus 1. */
+ copylen = len - 1;
if (atomicio(vwrite, dst, buf, copylen) != copylen ||
atomicio(vwrite, dst, "\n", 1) != 1)
goto end;
--
Dasn