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

##### Functions

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

#### Defined functions

greettimeout defined in line 220; used 2 times

- in line 82, 137

reply defined in line 376; used 9 times

- in line 139, 151, 168, 174, 196, 250, 292, 312, 347

smtpdata defined in line 275; used 1 times

- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 450

smtpinit defined in line 75; used 1 times

- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 417

smtpmessage defined in line 487; used 8 times

- in line 149, 167, 173, 188-192(2), 247, 290, 346

smtpquit defined in line 334; used 6 times

- in line 205-215(3), 425, 461
- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 454

smtprcpt defined in line 240; used 1 times

- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 431

#### Defined variables

CtxGreeting defined in line 73; used 2 times

- in line 135, 224

SmtpError defined in line 44; used 3 times

- in line 95, 465-466(2)

SmtpMsgBuffer defined in line 42; used 6 times

- in line 433-435(3), 491-495(3)

SmtpPid defined in line 47; used 3 times

- in line 97-98(2), 359

SmtpReplyBuffer defined in line 43; used 11 times

- in line 402(2), 428-430(2), 438-450(5), 465-466(2)

SmtpState defined in line 50; used 11 times

- in line 89-94(2), 127, 344-348(3), 356, 398, 424, 457-460(2)

sccsid defined in line 23; never used

#### Defined macros

REPLYCLASS defined in line 39; never used
REPLYTYPE defined in line 38; used 8 times

- in line 141, 154-156(2), 197, 251-253(2), 293, 313

SMTPCLOSING defined in line 40; used 2 times

- in line 399, 457

SMTP_CLOSED defined in line 52; used 5 times

- in line 94, 348, 356, 398, 424

SMTP_OPEN defined in line 53; used 3 times

- in line 89, 127, 344

SMTP_SSD defined in line 54; used 3 times

- in line 344, 457-460(2)

Last modified: 1997-10-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1828 |