extern void esmtp_check(); extern void helo_options();
extern void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); extern void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
extern int	reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)()));/***  SMTPINIT -- initialize SMTP.****	Opens the connection and sends the initial protocol.****	Parameters:**		m -- mailer to create connection to.**		pvp -- pointer to parameter vector to pass to**			the mailer.****	Returns:**		none.****	Side Effects:**		creates connection and sends initial protocol.*/voidsmtpinit(m, mci, e)	MAILER *m;	register MCI *mci;	ENVELOPE *e;{	register int r;	register char *p;	extern void esmtp_check();	extern void helo_options();	if (tTd(18, 1))	{		printf("smtpinit ");		mci_dump(mci, FALSE);	}	/*	**  Open the connection to the mailer.	*/	SmtpError[0] = '\0';	CurHostName = mci->mci_host;		/* XXX UGLY XXX */	if (CurHostName == NULL)		CurHostName = MyHostName;	SmtpNeedIntro = TRUE;	switch (mci->mci_state)	{	  case MCIS_ACTIVE:		/* need to clear old information */		smtprset(m, mci, e);		/* fall through */	  case MCIS_OPEN:		return;	  case MCIS_ERROR:	  case MCIS_SSD:		/* shouldn't happen */		smtpquit(m, mci, e);		/* fall through */	  case MCIS_CLOSED:		syserr("451 smtpinit: state CLOSED");		return;	  case MCIS_OPENING:		break;	}	mci->mci_state = MCIS_OPENING;	/*	**  Get the greeting message.	**	This should appear spontaneously.  Give it five minutes to	**	happen.	*/	SmtpPhase = mci->mci_phase = "client greeting";	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);	r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);	if (r < 0)		goto tempfail1;	if (REPLYTYPE(r) == 4)		goto tempfail2;	if (REPLYTYPE(r) != 2)		goto unavailable;	/*	**  Send the HELO command.	**	My mother taught me to always introduce myself.	*/#if _FFR_LMTP	if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))#else	if (bitnset(M_ESMTP, m->m_flags))#endif		mci->mci_flags |= MCIF_ESMTP;tryhelo:#if _FFR_LMTP	if (bitnset(M_LMTP, m->m_flags))	{		smtpmessage("LHLO %s", m, mci, MyHostName);		SmtpPhase = mci->mci_phase = "client LHLO";	}	else if (bitset(MCIF_ESMTP, mci->mci_flags))#else	if (bitset(MCIF_ESMTP, mci->mci_flags))#endif	{		smtpmessage("EHLO %s", m, mci, MyHostName);		SmtpPhase = mci->mci_phase = "client EHLO";	}	else	{		smtpmessage("HELO %s", m, mci, MyHostName);		SmtpPhase = mci->mci_phase = "client HELO";	}	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);	r = reply(m, mci, e, TimeOuts.to_helo, helo_options);	if (r < 0)		goto tempfail1;	else if (REPLYTYPE(r) == 5)	{#if _FFR_LMTP		if (bitset(MCIF_ESMTP, mci->mci_flags) &&		    !bitnset(M_LMTP, m->m_flags))#else		if (bitset(MCIF_ESMTP, mci->mci_flags))#endif		{			/* try old SMTP instead */			mci->mci_flags &= ~MCIF_ESMTP;			goto tryhelo;		}		goto unavailable;	}	else if (REPLYTYPE(r) != 2)		goto tempfail2;	/*	**  Check to see if we actually ended up talking to ourself.	**  This means we didn't know about an alias or MX, or we managed	**  to connect to an echo server.	*/	p = strchr(&SmtpReplyBuffer[4], ' ');	if (p != NULL)		*p = '\0';	if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&#if _FFR_LMTP	    !bitnset(M_LMTP, m->m_flags) &&#endif	    strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)	{		syserr("553 %s config error: mail loops back to me (MX problem?)",			mci->mci_host);		mci_setstat(mci, EX_CONFIG, NULL, NULL);		mci->mci_errno = 0;		smtpquit(m, mci, e);		return;	}	/*	**  If this is expected to be another sendmail, send some internal	**  commands.	*/	if (bitnset(M_INTERNAL, m->m_flags))	{		/* tell it to be verbose */		smtpmessage("VERB", m, mci);		r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);		if (r < 0)			goto tempfail1;	}	if (mci->mci_state != MCIS_CLOSED)	{		mci->mci_state = MCIS_OPEN;		return;	}	/* got a 421 error code during startup */  tempfail1:	if (mci->mci_errno == 0)		mci->mci_errno = errno;	mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);	if (mci->mci_state != MCIS_CLOSED)		smtpquit(m, mci, e);	return;  tempfail2:	if (mci->mci_errno == 0)		mci->mci_errno = errno;	/* XXX should use code from other end iff ENHANCEDSTATUSCODES */	mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);	if (mci->mci_state != MCIS_CLOSED)		smtpquit(m, mci, e);	return;  unavailable:	mci->mci_errno = errno;	mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);	smtpquit(m, mci, e);	return;}