1Message-ID: <wgKo1lW00WBw46OU8k@andrew.cmu.edu>
2Date: Sun,  1 Aug 1993 00:02:57 -0400 (EDT)
3From: John Gardiner Myers <jgm+@CMU.EDU>
4To: sendmail@cs.berkeley.edu
5Subject: contrib/rcpt-streaming
6Beak: Is
7
8This patch implements "RCPT streaming" in sendmail version 8.  This
9patch is not an official part of sendmail.  Please report all problems
10with this patch to jgm+@cmu.edu.
11
12RCPT streming avoids network round trips by sending all RCPT commands
13for a single SMTP transaction together.  Sendmail then waits for all
14the replies, matching them up with the apropriate addresses.
15
16Apply to the sendmail src directory (your line numbers may vary) and
17compile with -DRCPTSTREAM
18
19diff -cr ./src/deliver.c /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/deliver.c
20*** ./src/deliver.c	Thu Jul 22 14:28:19 1993
21--- /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/deliver.c	Fri Jul 30 21:11:16 1993
22***************
23*** 1334,1339 ****
24--- 1334,1354 ----
25  			register int i;
26
27  			/* send the recipient list */
28+ #ifdef RCPTSTREAM
29+ /***********************************************************************
30+  *
31+  * RCPT streaming code by John G Myers, jgm+@cmu.edu
32+  * This is not supported by the maintainer of sendmail.
33+  * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
34+  *
35+  ***********************************************************************
36+  */
37+ 			for (to = tochain; to != NULL; to = to->q_tchain)
38+ 			{
39+ 				smtpstreammessage("RCPT To:<%s>", m, mci,
40+ 						  to->q_user);
41+ 			}
42+ #endif
43  			tobuf[0] = '\0';
44  			for (to = tochain; to != NULL; to = to->q_tchain)
45  			{
46diff -cr ./src/usersmtp.c /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/usersmtp.c
47*** ./src/usersmtp.c	Mon Jul 19 23:50:43 1993
48--- /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/usersmtp.c	Fri Jul 30 21:12:00 1993
49***************
50*** 44,49 ****
51--- 44,61 ----
52
53  # include <sysexits.h>
54  # include <errno.h>
55+ #ifdef RCPTSTREAM
56+ /***********************************************************************
57+  *
58+  * RCPT streaming code by John G Myers, jgm+@cmu.edu
59+  * This is not supported by the maintainer of sendmail.
60+  * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
61+  *
62+  ***********************************************************************
63+  */
64+ # include <sys/types.h>
65+ # include <sys/time.h>
66+ #endif
67
68  # ifdef SMTP
69
70***************
71*** 62,67 ****
72--- 74,87 ----
73  char	SmtpError[MAXLINE] = "";	/* save failure error messages */
74  int	SmtpPid;			/* pid of mailer */
75
76+ #ifdef RCPTSTREAM
77+ char	*SmtpStreamBuf;			/* buffer for streaming output */
78+ int	SmtpStreamBufSize = 0;		/* allocated size of buffer */
79+ char	*SmtpStreamStart;		/* pointer to text not yet written */
80+ int	SmtpStreamLen = 0;		/* # chars not yet written */
81+ #endif
82+
83+
84  #ifdef __STDC__
85  extern	smtpmessage(char *f, MAILER *m, MCI *mci, ...);
86  #endif
87***************
88*** 404,410 ****
89--- 424,434 ----
90  {
91  	register int r;
92
93+ #ifdef RCPTSTREAM
94+ 	sprintf(SmtpMsgBuffer, "RCPT To:<%s>", to->q_user);
95+ #else
96  	smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
97+ #endif
98
99  	SmtpPhase = mci->mci_phase = "client RCPT";
100  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
101***************
102*** 667,672 ****
103--- 694,703 ----
104  	bool firstline = TRUE;
105  	char junkbuf[MAXLINE];
106
107+ #ifdef RCPTSTREAM
108+ 	extern char MsgBuf[];		/* err.c */
109+ #endif
110+
111  	if (mci->mci_out != NULL)
112  		(void) fflush(mci->mci_out);
113
114***************
115*** 682,687 ****
116--- 713,755 ----
117  		register char *p;
118  		extern time_t curtime();
119
120+ #ifdef RCPTSTREAM
121+ 		if (SmtpStreamLen > 0) {
122+ 		    int outfd;
123+
124+ 		    outfd = fileno(mci->mci_out);
125+
126+ 		    nonblock(outfd, TRUE);
127+ 		    r = write(outfd, SmtpStreamStart, SmtpStreamLen);
128+ 		    nonblock(outfd, FALSE);
129+ 		    if (r == -1 && errno != EAGAIN
130+ #ifdef EWOULDBLOCK
131+ 			&& errno != EWOULDBLOCK
132+ #endif
133+ 			) {
134+
135+ 			mci->mci_errno = errno;
136+ 			message("451 streamreply: write error to %s",
137+ 				mci->mci_host);
138+
139+ 			/* if debugging, pause so we can see state */
140+ 			if (tTd(18, 100))
141+ 			  pause();
142+ # ifdef LOG
143+ 			if (LogLevel > 0)
144+ 			  syslog(LOG_INFO, "%s", &MsgBuf[4]);
145+ # endif /* LOG */
146+ 			/* stop trying to write output */
147+ 			SmtpStreamLen = 0;
148+ 			continue;
149+ 		    }
150+ 		    if (r > 0) {
151+ 			SmtpStreamStart += r;
152+ 			SmtpStreamLen -= r;
153+ 		    }
154+ 		}
155+ #endif /* RCPTSTREAM */
156+
157  		/* actually do the read */
158  		if (e->e_xfp != NULL)
159  			(void) fflush(e->e_xfp);	/* for debugging */
160***************
161*** 792,797 ****
162--- 860,937 ----
163
164  	return (r);
165  }
166+
167+ #ifdef RCPTSTREAM
168+ /*
169+ **  SMTPSTREAMMESSAGE -- buffer message to be streamed to server
170+ **
171+ **	Parameters:
172+ **		f -- format
173+ **		m -- the mailer to control formatting.
174+ **		a, b, c -- parameters
175+ **
176+ **	Returns:
177+ **		none.
178+ **
179+ **	Side Effects:
180+ **		stores message in SmtpStreamBuf
181+ */
182+
183+ /*VARARGS1*/
184+ #ifdef __STDC__
185+ smtpstreammessage(char *f, MAILER *m, MCI *mci, ...)
186+ #else
187+ smtpstreammessage(f, m, mci, va_alist)
188+ 	char *f;
189+ 	MAILER *m;
190+ 	MCI *mci;
191+ 	va_dcl
192+ #endif
193+ {
194+ 	VA_LOCAL_DECL
195+ 	int len;
196+
197+ 	VA_START(mci);
198+ 	(void) vsprintf(SmtpMsgBuffer, f, ap);
199+ 	VA_END;
200+
201+ 	if (tTd(18, 1) || Verbose)
202+ 		nmessage(">>> %s", SmtpMsgBuffer);
203+ 	if (TrafficLogFile != NULL)
204+ 		fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(), SmtpMsgBuffer);
205+
206+ 	if (mci->mci_out == NULL) {
207+ 	    if (tTd(18, 1)) printf("smtpstreammessage: NULL mci_out\n");
208+ 	    return;
209+ 	}
210+
211+ 	strcat(SmtpMsgBuffer, m == NULL ? "\r\n" : m->m_eol);
212+ 	len = strlen(SmtpMsgBuffer);
213+
214+ 	if (SmtpStreamLen == 0) {
215+ 	    if (SmtpStreamBufSize == 0) {
216+ 		SmtpStreamBufSize = MAXLINE;
217+ 		SmtpStreamBuf = xalloc(SmtpStreamBufSize);
218+ 	    }
219+ 	    SmtpStreamStart = SmtpStreamBuf;
220+ 	}
221+
222+ 	if (SmtpStreamBufSize - SmtpStreamLen < len + 1) {
223+ 	    int start = SmtpStreamStart - SmtpStreamBuf;
224+ 	    SmtpStreamBufSize += MAXLINE;
225+ 	    SmtpStreamBuf = realloc(SmtpStreamBuf, SmtpStreamBufSize);
226+ 	    if (!SmtpStreamBuf) {
227+ 		syserr("Out of memory!!");
228+ 		abort();
229+ 		/* exit(EX_UNAVAILABLE); */
230+ 	    }
231+ 	    SmtpStreamStart = SmtpStreamBuf + start;
232+ 	}
233+
234+ 	strcpy(SmtpStreamBuf + SmtpStreamLen, SmtpMsgBuffer);
235+ 	SmtpStreamLen += len;
236+ }
237+ #endif /* RCPTSTREAM */
238  /*
239  **  SMTPMESSAGE -- send message to server
240  **
241Only in /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src: usersmtp.c~
242diff -cr ./src/util.c /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/util.c
243*** ./src/util.c	Mon Jul 19 23:50:45 1993
244--- /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/util.c	Mon Jul 26 17:17:10 1993
245***************
246*** 1034,1039 ****
247--- 1034,1091 ----
248  			return (FALSE);
249  	return (TRUE);
250  }
251+
252+ #ifdef RCPTSTREAM
253+ /***********************************************************************
254+  *
255+  * RCPT streaming code by John G Myers, jgm+@cmu.edu
256+  * This is not supported by the maintainer of sendmail.
257+  * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
258+  *
259+  ***********************************************************************
260+  */
261+
262+ #include <fcntl.h>
263+
264+ /*
265+ **  NONBLOCK -- set or clear non-blocking mode on file descriptor
266+ **
267+ **	Parameters:
268+ **		fd -- the file descriptor
269+ **		mode -- TRUE to set non-blocking mode
270+ **			FALSE to clear non-blocking mode
271+ **
272+ **	Returns:
273+ **		none
274+ **
275+ **	Side Effects:
276+ **		modifies nonblocking status of fd
277+ */
278+
279+ nonblock(fd, mode)
280+ int fd;
281+ bool mode;
282+ {
283+     int flags;
284+
285+     flags = fcntl(fd, F_GETFL, 0);
286+     if (mode) {
287+ #ifdef FNONBIO
288+ 	flags |= FNONBIO;
289+ #else
290+ 	flags |= O_NDELAY;
291+ #endif
292+     }
293+     else {
294+ #ifdef FNONBIO
295+ 	flags &= ~FNONBIO;
296+ #else
297+ 	flags &= ~O_NDELAY;
298+ #endif
299+     }
300+     fcntl(fd, F_SETFL, flags);
301+ }
302+ #endif
303  /*
304  **  STRCONTAINEDIN -- tell if one string is contained in another
305  **
306