Gilles Chehade <[email protected]> writes:
>> > Turns out it's a bit more than compat getopt(), we do accept and ignore
>> > those flags however.
>> >
>> > With 'sendmail -bs' MUA expects STMP dialog over stdin/stdout, which
>> > means, MUA will wait for the greeting on stdout while smtpctl waits for
>> > text on stdin and they are now deadlocked.
>> >
>> > The following diff bridges the enqueuer fd and stdout/stdin by writing
>> > output from fd to stdout and commands from stdin to fd.
>> >
>> > I can send mails with apline now without any config modifications and
>> > also enqueue via plain 'sendmail -bs'.
>> >
>> > Tests and comments welcome.
>>
>> Revised diff. Ignore rest of '-b' options instead of returning an error.
>>
>
> I really dislike this but I understand there's not much you can
> do to achieve it differently :-/
>
> one comment inline
Revised diff to move exit() out of the function.
>
> did you get a feedback from the original poster ?
Not yet.
diff --git a/smtpd/enqueue.c b/smtpd/enqueue.c
index 3fd7fbd6..c7c008d0 100644
--- a/smtpd/enqueue.c
+++ b/smtpd/enqueue.c
@@ -31,6 +31,7 @@
#include <grp.h>
#include <imsg.h>
#include <inttypes.h>
+#include <poll.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
@@ -46,6 +47,7 @@ extern struct imsgbuf *ibuf;
void usage(void);
static void build_from(char *, struct passwd *);
+static void handle_bs(void);
static int parse_message(FILE *, int, int, FILE *);
static void parse_addr(char *, size_t, int);
static void parse_addr_terminal(int);
@@ -171,6 +173,7 @@ enqueue(int argc, char *argv[], FILE *ofp)
FILE *fp = NULL, *fout;
size_t sz = 0, envid_sz = 0;
ssize_t len;
+ int bs_flag = 0;
int fd;
char sfn[] = "/tmp/smtpd.XXXXXXXXXX";
char *line;
@@ -216,10 +219,13 @@ enqueue(int argc, char *argv[], FILE *ofp)
case 'V':
msg.dsn_envid = optarg;
break;
+ case 'b':
+ if (strcmp(optarg, "s") == 0)
+ bs_flag = 1;
+ break;
/* all remaining: ignored, sendmail compat */
case 'A':
case 'B':
- case 'b':
case 'E':
case 'e':
case 'i':
@@ -240,6 +246,11 @@ enqueue(int argc, char *argv[], FILE *ofp)
argc -= optind;
argv += optind;
+ if (bs_flag) {
+ handle_bs();
+ exit(EX_OK);
+ }
+
if (getmailname(host, sizeof(host)) == -1)
errx(EX_NOHOST, "getmailname");
if (no_getlogin) {
@@ -458,6 +469,54 @@ fail:
exit(EX_SOFTWARE);
}
+/*
+ * sendmail -bs requires STMP dialog over stdin/stdout.
+ * Bridge stdin/stdout with enqueuer fd.
+ */
+static void
+handle_bs(void)
+{
+ char buf[LINE_MAX];
+ struct pollfd pfd[2];
+ nfds_t nfds;
+ size_t i;
+ ssize_t nr;
+ int fd, nready, outfd;
+
+ if (!srv_connected())
+ errx(EX_UNAVAILABLE, "Server offline");
+
+ if ((fd = open_connection()) == -1)
+ errx(EX_UNAVAILABLE, "server too busy");
+
+ pfd[0].fd = STDIN_FILENO;
+ pfd[1].fd = fd;
+ pfd[0].events = pfd[1].events = POLLIN;
+ nfds = 2;
+ while ((nready = poll(pfd, nfds, INFTIM))) {
+ if (nready == -1)
+ err(1, "poll");
+
+ for (i = 0; i < nfds; i++) {
+ if (pfd[i].revents & (POLLERR|POLLNVAL))
+ errx(1, "bsd fd %d", pfd[i].fd);
+
+ if ((pfd[i].revents & (POLLIN|POLLHUP))) {
+ nr = read(pfd[i].fd, buf, sizeof buf);
+ if (nr == -1)
+ err(1, "read");
+ else if (nr == 0)
+ return;
+
+ outfd = pfd[i].fd == STDIN_FILENO ?
+ fd : STDOUT_FILENO;
+ if (write(outfd, buf, nr) == -1)
+ err(1, "write");
+ }
+ }
+ }
+}
+
static int
get_responses(FILE *fin, int n)
{
--
You received this mail because you are subscribed to [email protected]
To unsubscribe, send a mail to: [email protected]