# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/src/usersmtp.c

##### Functions

    greettimeout      X
    reply             X
    smtpdata          X
    smtpinit          X
    smtpmessage       X
    smtpquit          X
    smtprcpt          X

##### Variables

    CtxGreeting       X
    SmtpError         X
    SmtpMsgBuffer     X
    SmtpPid           X
    SmtpReplyBuffer   X
    SmtpState         X

##### Macros

    REPLYCLASS        X
    REPLYTYPE         X
    SMTPCLOSING       X
    SMTP_CLOSED       X
    SMTP_OPEN         X
    SMTP_SSD          X

       1: /*
       2: **  Sendmail
       3: **  Copyright (c) 1983  Eric P. Allman
       4: **  Berkeley, California
       5: **
       6: **  Copyright (c) 1983 Regents of the University of California.
       7: **  All rights reserved.  The Berkeley software License Agreement
       8: **  specifies the terms and conditions for redistribution.
       9: */
      10:
      11:
      12: # include <ctype.h>
      13: # include <sysexits.h>
      14: # include <errno.h>
      15: # include "sendmail.h"
      16:
      17: # ifndef SMTP
      18: #if !defined(lint) && !defined(NOSCCS)
      19: static char SccsId[] = "@(#)usersmtp.c	5.7.2 (2.11BSD GTE) 1996/3/10(no SMTP)";
      20: # endif
      21: # else SMTP
      22:
      23: #if !defined(lint) && !defined(NOSCCS)
      24: static char SccsId[] = "@(#)usersmtp.c	5.7.2 (2.11BSD GTE) 1996/3/10";
      25: # endif
      26:
      27:
      28: /*
      29: **  USERSMTP -- run SMTP protocol from the user end.
      30: **
      31: **	This protocol is described in RFC821.
      32: */
      33:
      34: #define REPLYTYPE(r)    ((r) / 100)     /* first digit of reply code */
      35: #define REPLYCLASS(r)   (((r) / 10) % 10)   /* second digit of reply code */
      36: #define SMTPCLOSING 421         /* "Service Shutting Down" */
      37:
      38: char    SmtpMsgBuffer[MAXLINE];     /* buffer for commands */
      39: char    SmtpReplyBuffer[MAXLINE];   /* buffer for replies */
      40: char    SmtpError[MAXLINE];     /* save failure error messages */
      41: FILE    *SmtpOut;           /* output file */
      42: FILE    *SmtpIn;            /* input file */
      43: int SmtpPid;            /* pid of mailer */
      44:
      45: /* following represents the state of the SMTP connection */
      46: int SmtpState;          /* connection state, see below */
      47:
      48: #define SMTP_CLOSED 0       /* connection is closed */
      49: #define SMTP_OPEN   1       /* connection is open for business */
      50: #define SMTP_SSD    2       /* service shutting down */
      51: /*
      52: **  SMTPINIT -- initialize SMTP.
      53: **
      54: **	Opens the connection and sends the initial protocol.
      55: **
      56: **	Parameters:
      57: **		m -- mailer to create connection to.
      58: **		pvp -- pointer to parameter vector to pass to
      59: **			the mailer.
      60: **
      61: **	Returns:
      62: **		appropriate exit status -- EX_OK on success.
      63: **		If not EX_OK, it should close the connection.
      64: **
      65: **	Side Effects:
      66: **		creates connection and sends initial protocol.
      67: */
      68:
      69: jmp_buf CtxGreeting;
      70:
      71: smtpinit(m, pvp)
      72:     struct mailer *m;
      73:     char **pvp;
      74: {
      75:     register int r;
      76:     EVENT *gte;
      77:     char buf[MAXNAME];
      78:     int greettimeout();
      79:
      80:     /*
      81: 	**  Open the connection to the mailer.
      82: 	*/
      83:
      84: #ifdef DEBUG
      85:     if (SmtpState == SMTP_OPEN)
      86:         syserr("smtpinit: already open");
      87: #endif DEBUG
      88:
      89:     SmtpIn = SmtpOut = NULL;
      90:     SmtpState = SMTP_CLOSED;
      91:     SmtpError[0] = '\0';
      92:     SmtpPhase = "user open";
      93:     SmtpPid = openmailer(m, pvp, (ADDRESS *) NULL, TRUE, &SmtpOut, &SmtpIn);
      94:     if (SmtpPid < 0)
      95:     {
      96: # ifdef DEBUG
      97:         if (tTd(18, 1))
      98:             printf("smtpinit: cannot open %s: stat %d errno %d\n",
      99:                pvp[0], ExitStat, errno);
     100: # endif DEBUG
     101:         if (CurEnv->e_xfp != NULL)
     102:         {
     103:             register char *p;
     104:             extern char *errstring();
     105:             extern char *statstring();
     106:
     107:             if (errno == 0)
     108:             {
     109:                 p = statstring(ExitStat);
     110:                 fprintf(CurEnv->e_xfp,
     111:                     "%.3s %s.%s... %s\n",
     112:                     p, pvp[1], m->m_name, p);
     113:             }
     114:             else
     115:             {
     116:                 fprintf(CurEnv->e_xfp,
     117:                     "421 %s.%s... Deferred: %s\n",
     118:                     pvp[1], m->m_name, errstring(errno));
     119:             }
     120:         }
     121:         return (ExitStat);
     122:     }
     123:     SmtpState = SMTP_OPEN;
     124:
     125:     /*
     126: 	**  Get the greeting message.
     127: 	**	This should appear spontaneously.  Give it five minutes to
     128: 	**	happen.
     129: 	*/
     130:
     131:     if (setjmp(CtxGreeting) != 0)
     132:         goto tempfail;
     133:     gte = setevent((time_t) 300, greettimeout, 0);
     134:     SmtpPhase = "greeting wait";
     135:     r = reply(m);
     136:     clrevent(gte);
     137:     if (r < 0 || REPLYTYPE(r) != 2)
     138:         goto tempfail;
     139:
     140:     /*
     141: 	**  Send the HELO command.
     142: 	**	My mother taught me to always introduce myself.
     143: 	*/
     144:
     145:     smtpmessage("HELO %s", m, MyHostName);
     146:     SmtpPhase = "HELO wait";
     147:     r = reply(m);
     148:     if (r < 0)
     149:         goto tempfail;
     150:     else if (REPLYTYPE(r) == 5)
     151:         goto unavailable;
     152:     else if (REPLYTYPE(r) != 2)
     153:         goto tempfail;
     154:
     155:     /*
     156: 	**  If this is expected to be another sendmail, send some internal
     157: 	**  commands.
     158: 	*/
     159:
     160:     if (bitnset(M_INTERNAL, m->m_flags))
     161:     {
     162:         /* tell it to be verbose */
     163:         smtpmessage("VERB", m);
     164:         r = reply(m);
     165:         if (r < 0)
     166:             goto tempfail;
     167:
     168:         /* tell it we will be sending one transaction only */
     169:         smtpmessage("ONEX", m);
     170:         r = reply(m);
     171:         if (r < 0)
     172:             goto tempfail;
     173:     }
     174:
     175:     /*
     176: 	**  Send the MAIL command.
     177: 	**	Designates the sender.
     178: 	*/
     179:
     180:     expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);
     181:     if (CurEnv->e_from.q_mailer == LocalMailer ||
     182:         !bitnset(M_FROMPATH, m->m_flags))
     183:     {
     184:         smtpmessage("MAIL From:<%s>", m, buf);
     185:     }
     186:     else
     187:     {
     188:         smtpmessage("MAIL From:<@%s%c%s>", m, MyHostName,
     189:             buf[0] == '@' ? ',' : ':', buf);
     190:     }
     191:     SmtpPhase = "MAIL wait";
     192:     r = reply(m);
     193:     if (r < 0 || REPLYTYPE(r) == 4)
     194:         goto tempfail;
     195:     else if (r == 250)
     196:         return (EX_OK);
     197:     else if (r == 552)
     198:         goto unavailable;
     199:
     200:     /* protocol error -- close up */
     201:     smtpquit(m);
     202:     return (EX_PROTOCOL);
     203:
     204:     /* signal a temporary failure */
     205:   tempfail:
     206:     smtpquit(m);
     207:     return (EX_TEMPFAIL);
     208:
     209:     /* signal service unavailable */
     210:   unavailable:
     211:     smtpquit(m);
     212:     return (EX_UNAVAILABLE);
     213: }
     214:
     215:
     216: greettimeout()
     217: {
     218:     /* timeout reading the greeting message */
     219:     longjmp(CtxGreeting, 1);
     220: }
     221: /*
     222: **  SMTPRCPT -- designate recipient.
     223: **
     224: **	Parameters:
     225: **		to -- address of recipient.
     226: **		m -- the mailer we are sending to.
     227: **
     228: **	Returns:
     229: **		exit status corresponding to recipient status.
     230: **
     231: **	Side Effects:
     232: **		Sends the mail via SMTP.
     233: */
     234:
     235: smtprcpt(to, m)
     236:     ADDRESS *to;
     237:     register MAILER *m;
     238: {
     239:     register int r;
     240:     extern char *remotename();
     241:
     242:     smtpmessage("RCPT To:<%s>", m, remotename(to->q_user, m, FALSE, TRUE));
     243:
     244:     SmtpPhase = "RCPT wait";
     245:     r = reply(m);
     246:     if (r < 0 || REPLYTYPE(r) == 4)
     247:         return (EX_TEMPFAIL);
     248:     else if (REPLYTYPE(r) == 2)
     249:         return (EX_OK);
     250:     else if (r == 550 || r == 551 || r == 553)
     251:         return (EX_NOUSER);
     252:     else if (r == 552 || r == 554)
     253:         return (EX_UNAVAILABLE);
     254:     return (EX_PROTOCOL);
     255: }
     256: /*
     257: **  SMTPDATA -- send the data and clean up the transaction.
     258: **
     259: **	Parameters:
     260: **		m -- mailer being sent to.
     261: **		e -- the envelope for this message.
     262: **
     263: **	Returns:
     264: **		exit status corresponding to DATA command.
     265: **
     266: **	Side Effects:
     267: **		none.
     268: */
     269:
     270: smtpdata(m, e)
     271:     struct mailer *m;
     272:     register ENVELOPE *e;
     273: {
     274:     register int r;
     275:
     276:     /*
     277: 	**  Send the data.
     278: 	**	First send the command and check that it is ok.
     279: 	**	Then send the data.
     280: 	**	Follow it up with a dot to terminate.
     281: 	**	Finally get the results of the transaction.
     282: 	*/
     283:
     284:     /* send the command and check ok to proceed */
     285:     smtpmessage("DATA", m);
     286:     SmtpPhase = "DATA wait";
     287:     r = reply(m);
     288:     if (r < 0 || REPLYTYPE(r) == 4)
     289:         return (EX_TEMPFAIL);
     290:     else if (r == 554)
     291:         return (EX_UNAVAILABLE);
     292:     else if (r != 354)
     293:         return (EX_PROTOCOL);
     294:
     295:     /* now output the actual message */
     296:     (*e->e_puthdr)(SmtpOut, m, CurEnv);
     297:     putline("\n", SmtpOut, m);
     298:     (*e->e_putbody)(SmtpOut, m, CurEnv);
     299:
     300:     /* terminate the message */
     301:     fprintf(SmtpOut, ".%s", m->m_eol);
     302:     if (Verbose && !HoldErrs)
     303:         nmessage(Arpa_Info, ">>> .");
     304:
     305:     /* check for the results of the transaction */
     306:     SmtpPhase = "result wait";
     307:     r = reply(m);
     308:     if (r < 0 || REPLYTYPE(r) == 4)
     309:         return (EX_TEMPFAIL);
     310:     else if (r == 250)
     311:         return (EX_OK);
     312:     else if (r == 552 || r == 554)
     313:         return (EX_UNAVAILABLE);
     314:     return (EX_PROTOCOL);
     315: }
     316: /*
     317: **  SMTPQUIT -- close the SMTP connection.
     318: **
     319: **	Parameters:
     320: **		m -- a pointer to the mailer.
     321: **
     322: **	Returns:
     323: **		none.
     324: **
     325: **	Side Effects:
     326: **		sends the final protocol and closes the connection.
     327: */
     328:
     329: smtpquit(m)
     330:     register MAILER *m;
     331: {
     332:     int i;
     333:
     334:     /* if the connection is already closed, don't bother */
     335:     if (SmtpIn == NULL)
     336:         return;
     337:
     338:     /* send the quit message if not a forced quit */
     339:     if (SmtpState == SMTP_OPEN || SmtpState == SMTP_SSD)
     340:     {
     341:         smtpmessage("QUIT", m);
     342:         (void) reply(m);
     343:         if (SmtpState == SMTP_CLOSED)
     344:             return;
     345:     }
     346:
     347:     /* now actually close the connection */
     348:     (void) fclose(SmtpIn);
     349:     (void) fclose(SmtpOut);
     350:     SmtpIn = SmtpOut = NULL;
     351:     SmtpState = SMTP_CLOSED;
     352:
     353:     /* and pick up the zombie */
     354:     i = endmailer(SmtpPid, m->m_argv[0]);
     355:     if (i != EX_OK)
     356:         syserr("smtpquit %s: stat %d", m->m_argv[0], i);
     357: }
     358: /*
     359: **  REPLY -- read arpanet reply
     360: **
     361: **	Parameters:
     362: **		m -- the mailer we are reading the reply from.
     363: **
     364: **	Returns:
     365: **		reply code it reads.
     366: **
     367: **	Side Effects:
     368: **		flushes the mail file.
     369: */
     370:
     371: reply(m)
     372:     MAILER *m;
     373: {
     374:     (void) fflush(SmtpOut);
     375:
     376:     if (tTd(18, 1))
     377:         printf("reply\n");
     378:
     379:     /*
     380: 	**  Read the input line, being careful not to hang.
     381: 	*/
     382:
     383:     for (;;)
     384:     {
     385:         register int r;
     386:         register char *p;
     387:
     388:         /* actually do the read */
     389:         if (CurEnv->e_xfp != NULL)
     390:             (void) fflush(CurEnv->e_xfp);   /* for debugging */
     391:
     392:         /* if we are in the process of closing just give the code */
     393:         if (SmtpState == SMTP_CLOSED)
     394:             return (SMTPCLOSING);
     395:
     396:         /* get the line from the other side */
     397:         p = sfgets(SmtpReplyBuffer, sizeof SmtpReplyBuffer, SmtpIn);
     398:         if (p == NULL)
     399:         {
     400:             extern char MsgBuf[];       /* err.c */
     401:             extern char *Arpa_TSyserr;  /* conf.c */
     402:
     403:             /* if the remote end closed early, fake an error */
     404:             if (errno == 0)
     405: # ifdef ECONNRESET
     406:                 errno = ECONNRESET;
     407: # else ECONNRESET
     408:                 errno = EPIPE;
     409: # endif ECONNRESET
     410:
     411:             message(Arpa_TSyserr, "reply: read error");
     412: # ifdef DEBUG
     413:             /* if debugging, pause so we can see state */
     414:             if (tTd(18, 100))
     415:                 pause();
     416: # endif DEBUG
     417: # ifdef LOG
     418:             syslog(LOG_ERR, "%s", &MsgBuf[4]);
     419: # endif LOG
     420:             SmtpState = SMTP_CLOSED;
     421:             smtpquit(m);
     422:             return (-1);
     423:         }
     424:         fixcrlf(SmtpReplyBuffer, TRUE);
     425:
     426:         if (CurEnv->e_xfp != NULL && index("45", SmtpReplyBuffer[0]) != NULL)
     427:         {
     428:             /* serious error -- log the previous command */
     429:             if (SmtpMsgBuffer[0] != '\0')
     430:                 fprintf(CurEnv->e_xfp, ">>> %s\n", SmtpMsgBuffer);
     431:             SmtpMsgBuffer[0] = '\0';
     432:
     433:             /* now log the message as from the other side */
     434:             fprintf(CurEnv->e_xfp, "<<< %s\n", SmtpReplyBuffer);
     435:         }
     436:
     437:         /* display the input for verbose mode */
     438:         if (Verbose && !HoldErrs)
     439:             nmessage(Arpa_Info, "%s", SmtpReplyBuffer);
     440:
     441:         /* if continuation is required, we can go on */
     442:         if (SmtpReplyBuffer[3] == '-' || !isdigit(SmtpReplyBuffer[0]))
     443:             continue;
     444:
     445:         /* decode the reply code */
     446:         r = atoi(SmtpReplyBuffer);
     447:
     448:         /* extra semantics: 0xx codes are "informational" */
     449:         if (r < 100)
     450:             continue;
     451:
     452:         /* reply code 421 is "Service Shutting Down" */
     453:         if (r == SMTPCLOSING && SmtpState != SMTP_SSD)
     454:         {
     455:             /* send the quit protocol */
     456:             SmtpState = SMTP_SSD;
     457:             smtpquit(m);
     458:         }
     459:
     460:         /* save temporary failure messages for posterity */
     461:         if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
     462:             (void) strcpy(SmtpError, &SmtpReplyBuffer[4]);
     463:
     464:         return (r);
     465:     }
     466: }
     467: /*
     468: **  SMTPMESSAGE -- send message to server
     469: **
     470: **	Parameters:
     471: **		f -- format
     472: **		m -- the mailer to control formatting.
     473: **		a, b, c -- parameters
     474: **
     475: **	Returns:
     476: **		none.
     477: **
     478: **	Side Effects:
     479: **		writes message to SmtpOut.
     480: */
     481:
     482: /*VARARGS1*/
     483: smtpmessage(f, m, a, b, c)
     484:     char *f;
     485:     MAILER *m;
     486: {
     487:     (void) sprintf(SmtpMsgBuffer, f, a, b, c);
     488:     if (tTd(18, 1) || (Verbose && !HoldErrs))
     489:         nmessage(Arpa_Info, ">>> %s", SmtpMsgBuffer);
     490:     if (SmtpOut != NULL)
     491:         fprintf(SmtpOut, "%s%s", SmtpMsgBuffer, m->m_eol);
     492: }
     493:
     494: # endif SMTP

#### Defined functions

greettimeout defined in line 216; used 2 times

- in line 78, 133

reply defined in line 371; used 9 times

- in line 135, 147, 164, 170, 192, 245, 287, 307, 342

smtpdata defined in line 270; used 1 times

- in /usr/src/usr.sbin/sendmail/src/deliver.c line 395

smtpinit defined in line 71; used 1 times

- in /usr/src/usr.sbin/sendmail/src/deliver.c line 365

smtpmessage defined in line 483; used 8 times

- in line 145, 163, 169, 184-188(2), 242, 285, 341

smtpquit defined in line 329; used 6 times

- in line 201-211(3), 421, 457
- in /usr/src/usr.sbin/sendmail/src/deliver.c line 399

smtprcpt defined in line 235; used 1 times

- in /usr/src/usr.sbin/sendmail/src/deliver.c line 376

#### Defined variables

CtxGreeting defined in line 69; used 2 times

- in line 131, 219

SccsId defined in line 24; never used
SmtpError defined in line 40; used 3 times

- in line 91, 461-462(2)

SmtpMsgBuffer defined in line 38; used 6 times

- in line 429-431(3), 487-491(3)

SmtpPid defined in line 43; used 3 times

- in line 93-94(2), 354

SmtpReplyBuffer defined in line 39; used 11 times

- in line 397(2), 424-426(2), 434-446(5), 461-462(2)

SmtpState defined in line 46; used 11 times

- in line 85-90(2), 123, 339-343(3), 351, 393, 420, 453-456(2)

#### Defined macros

REPLYCLASS defined in line 35; never used
REPLYTYPE defined in line 34; used 8 times

- in line 137, 150-152(2), 193, 246-248(2), 288, 308

SMTPCLOSING defined in line 36; used 2 times

- in line 394, 453

SMTP_CLOSED defined in line 48; used 5 times

- in line 90, 343, 351, 393, 420

SMTP_OPEN defined in line 49; used 3 times

- in line 85, 123, 339

SMTP_SSD defined in line 50; used 3 times

- in line 339, 453-456(2)

Last modified: 1996-03-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2471 |