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