diff options
Diffstat (limited to 'contrib/sendmail/src/err.c')
| -rw-r--r-- | contrib/sendmail/src/err.c | 421 | 
1 files changed, 274 insertions, 147 deletions
diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c index d259db2ed0e6a..484af9e85ddd7 100644 --- a/contrib/sendmail/src/err.c +++ b/contrib/sendmail/src/err.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.   *	All rights reserved.   * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.   * Copyright (c) 1988, 1993 @@ -11,42 +11,97 @@   *   */ -#ifndef lint -static char id[] = "@(#)$Id: err.c,v 8.120.4.5 2001/08/17 22:09:40 ca Exp $"; -#endif /* ! lint */ -  #include <sendmail.h> -#ifdef LDAPMAP + +SM_RCSID("@(#)$Id: err.c,v 8.189 2002/01/09 18:52:30 ca Exp $") + +#if LDAPMAP  # include <lber.h>  # include <ldap.h>			/* for LDAP error codes */  #endif /* LDAPMAP */ -  static void	putoutmsg __P((char *, bool, bool));  static void	puterrmsg __P((char *));  static char	*fmtmsg __P((char *, const char *, const char *, const char *,  			     int, const char *, va_list));  /* +**  FATAL_ERROR -- handle a fatal exception +** +**	This function is installed as the default exception handler +**	in the main sendmail process, and in all child processes +**	that we create.  Its job is to handle exceptions that are not +**	handled at a lower level. +** +**	The theory is that unhandled exceptions will be 'fatal' class +**	exceptions (with an "F:" prefix), such as the out-of-memory +**	exception "F:sm.heap".  As such, they are handled by exiting +**	the process in exactly the same way that xalloc() in Sendmail 8.10 +**	exits the process when it fails due to lack of memory: +**	we call syserr with a message beginning with "!". +** +**	Parameters: +**		exc -- exception which is terminating this process +** +**	Returns: +**		none +*/ + +void +fatal_error(exc) +	SM_EXC_T *exc; +{ +	static char buf[256]; +	SM_FILE_T f; + +	/* +	**  This function may be called when the heap is exhausted. +	**  The following code writes the message for 'exc' into our +	**  static buffer without allocating memory or raising exceptions. +	*/ + +	sm_strio_init(&f, buf, sizeof(buf)); +	sm_exc_write(exc, &f); +	(void) sm_io_flush(&f, SM_TIME_DEFAULT); + +	/* +	**  Terminate the process after logging an error and cleaning up. +	**  Problems: +	**  - syserr decides what class of error this is by looking at errno. +	**    That's no good; we should look at the exc structure. +	**  - The cleanup code should be moved out of syserr +	**    and into individual exception handlers +	**    that are part of the module they clean up after. +	*/ + +	errno = ENOMEM; +	syserr("!%s", buf); +} + +/*  **  SYSERR -- Print error message.  ** -**	Prints an error message via printf to the diagnostic output. +**	Prints an error message via sm_io_printf to the diagnostic output.  **  **	If the first character of the syserr message is `!' it will  **	log this as an ALERT message and exit immediately.  This can  **	leave queue files in an indeterminate state, so it should not  **	be used lightly.  ** +**	If the first character of the syserr message is '!' or '@' +**	then syserr knows that the process is about to be terminated, +**	so the SMTP reply code defaults to 421.  Otherwise, the +**	reply code defaults to 451 or 554, depending on errno. +**  **	Parameters: -**		fmt -- the format string.  If it does not begin with -**			a three-digit SMTP reply code, either 554 or -**			451 is assumed depending on whether errno -**			is set. +**		fmt -- the format string.  An optional '!' or '@', +**			followed by an optional three-digit SMTP +**			reply code, followed by message text.  **		(others) -- parameters  **  **	Returns:  **		none -**		Through TopFrame if QuickAbort is set. +**		Raises E:mta.quickabort if QuickAbort is set.  **  **	Side Effects:  **		increments Errors. @@ -73,22 +128,45 @@ syserr(fmt, va_alist)  	register char *p;  	int save_errno = errno;  	bool panic; +	bool exiting;  	char *user;  	char *enhsc;  	char *errtxt;  	struct passwd *pw;  	char ubuf[80]; -	VA_LOCAL_DECL +	SM_VA_LOCAL_DECL -	panic = *fmt == '!'; -	if (panic) +	switch (*fmt)  	{ -		fmt++; -		HoldErrs = FALSE; +	  case '!': +		++fmt; +		panic = true; +		exiting = true; +		break; +	  case '@': +		++fmt; +		panic = false; +		exiting = true; +		break; +	  default: +		panic = false; +		exiting = false; +		break;  	}  	/* format and output the error message */ -	if (save_errno == 0) +	if (exiting) +	{ +		/* +		**  Since we are terminating the process, +		**  we are aborting the entire SMTP session, +		**  rather than just the current transaction. +		*/ + +		p = "421"; +		enhsc = "4.0.0"; +	} +	else if (save_errno == 0)  	{  		p = "554";  		enhsc = "5.0.0"; @@ -98,17 +176,19 @@ syserr(fmt, va_alist)  		p = "451";  		enhsc = "4.0.0";  	} -	VA_START(fmt); +	SM_VA_START(ap, fmt);  	errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap); -	VA_END; +	SM_VA_END(ap);  	puterrmsg(MsgBuf);  	/* save this message for mailq printing */  	if (!panic && CurEnv != NULL)  	{ -		if (CurEnv->e_message != NULL) +		char *nmsg = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); + +		if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)  			sm_free(CurEnv->e_message); -		CurEnv->e_message = newstr(errtxt); +		CurEnv->e_message = nmsg;  	}  	/* determine exit status if not already set */ @@ -119,7 +199,7 @@ syserr(fmt, va_alist)  		else  			ExitStat = EX_OSERR;  		if (tTd(54, 1)) -			dprintf("syserr: ExitStat = %d\n", ExitStat); +			sm_dprintf("syserr: ExitStat = %d\n", ExitStat);  	}  	pw = sm_getpwuid(RealUid); @@ -128,7 +208,7 @@ syserr(fmt, va_alist)  	else  	{  		user = ubuf; -		snprintf(ubuf, sizeof ubuf, "UID%d", (int) RealUid); +		(void) sm_snprintf(ubuf, sizeof ubuf, "UID%d", (int) RealUid);  	}  	if (LogLevel > 0) @@ -157,13 +237,13 @@ syserr(fmt, va_alist)  #ifdef ESTALE  	  case ESTALE:  #endif /* ESTALE */ -		printopenfds(TRUE); -		mci_dump_all(TRUE); +		printopenfds(true); +		mci_dump_all(true);  		break;  	}  	if (panic)  	{ -#ifdef XLA +#if XLA  		xla_all_end();  #endif /* XLA */  		sync_queue_time(); @@ -173,21 +253,21 @@ syserr(fmt, va_alist)  	}  	errno = 0;  	if (QuickAbort) -		longjmp(TopFrame, 2); +		sm_exc_raisenew_x(&EtypeQuickAbort, 2);  } -/* +/*  **  USRERR -- Signal user error.  **  **	This is much like syserr except it is for user errors.  **  **	Parameters:  **		fmt -- the format string.  If it does not begin with -**			a three-digit SMTP reply code, 501 is assumed. -**		(others) -- printf strings +**			a three-digit SMTP reply code, 550 is assumed. +**		(others) -- sm_io_printf strings  **  **	Returns:  **		none -**		Through TopFrame if QuickAbort is set. +**		Raises E:mta.quickabort if QuickAbort is set.  **  **	Side Effects:  **		increments Errors. @@ -205,7 +285,7 @@ usrerr(fmt, va_alist)  {  	char *enhsc;  	char *errtxt; -	VA_LOCAL_DECL +	SM_VA_LOCAL_DECL  	if (fmt[0] == '5' || fmt[0] == '6')  		enhsc = "5.0.0"; @@ -215,9 +295,9 @@ usrerr(fmt, va_alist)  		enhsc = "2.0.0";  	else  		enhsc = NULL; -	VA_START(fmt); -	errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap); -	VA_END; +	SM_VA_START(ap, fmt); +	errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap); +	SM_VA_END(ap);  	if (SuprErrs)  		return; @@ -234,32 +314,33 @@ usrerr(fmt, va_alist)  	  case '5':  	  case '6': -		if (CurEnv->e_message != NULL) +		if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)  			sm_free(CurEnv->e_message);  		if (MsgBuf[0] == '6')  		{  			char buf[MAXLINE]; -			snprintf(buf, sizeof buf, "Postmaster warning: %.*s", -				(int) sizeof buf - 22, errtxt); -			CurEnv->e_message = newstr(buf); +			(void) sm_snprintf(buf, sizeof buf, +					   "Postmaster warning: %.*s", +					   (int) sizeof buf - 22, errtxt); +			CurEnv->e_message = +				sm_rpool_strdup_x(CurEnv->e_rpool, buf);  		}  		else  		{ -			CurEnv->e_message = newstr(errtxt); +			CurEnv->e_message = +				sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);  		}  		break;  	}  	puterrmsg(MsgBuf); -  	if (LogLevel > 3 && LogUsrErrs)  		sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); -  	if (QuickAbort) -		longjmp(TopFrame, 1); +		sm_exc_raisenew_x(&EtypeQuickAbort, 1);  } -/* +/*  **  USRERRENH -- Signal user error.  **  **	Same as usrerr but with enhanced status code. @@ -267,12 +348,12 @@ usrerr(fmt, va_alist)  **	Parameters:  **		enhsc -- the enhanced status code.  **		fmt -- the format string.  If it does not begin with -**			a three-digit SMTP reply code, 501 is assumed. -**		(others) -- printf strings +**			a three-digit SMTP reply code, 550 is assumed. +**		(others) -- sm_io_printf strings  **  **	Returns:  **		none -**		Through TopFrame if QuickAbort is set. +**		Raises E:mta.quickabort if QuickAbort is set.  **  **	Side Effects:  **		increments Errors. @@ -290,7 +371,7 @@ usrerrenh(enhsc, fmt, va_alist)  #endif /* __STDC__ */  {  	char *errtxt; -	VA_LOCAL_DECL +	SM_VA_LOCAL_DECL  	if (enhsc == NULL || *enhsc == '\0')  	{ @@ -301,9 +382,9 @@ usrerrenh(enhsc, fmt, va_alist)  		else if (fmt[0] == '2')  			enhsc = "2.0.0";  	} -	VA_START(fmt); -	errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap); -	VA_END; +	SM_VA_START(ap, fmt); +	errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap); +	SM_VA_END(ap);  	if (SuprErrs)  		return; @@ -320,38 +401,39 @@ usrerrenh(enhsc, fmt, va_alist)  	  case '5':  	  case '6': -		if (CurEnv->e_message != NULL) +		if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)  			sm_free(CurEnv->e_message);  		if (MsgBuf[0] == '6')  		{  			char buf[MAXLINE]; -			snprintf(buf, sizeof buf, "Postmaster warning: %.*s", -				(int) sizeof buf - 22, errtxt); -			CurEnv->e_message = newstr(buf); +			(void) sm_snprintf(buf, sizeof buf, +					   "Postmaster warning: %.*s", +					   (int) sizeof buf - 22, errtxt); +			CurEnv->e_message = +				sm_rpool_strdup_x(CurEnv->e_rpool, buf);  		}  		else  		{ -			CurEnv->e_message = newstr(errtxt); +			CurEnv->e_message = +				sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);  		}  		break;  	}  	puterrmsg(MsgBuf); -  	if (LogLevel > 3 && LogUsrErrs)  		sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); -  	if (QuickAbort) -		longjmp(TopFrame, 1); +		sm_exc_raisenew_x(&EtypeQuickAbort, 1);  } -/* +/*  **  MESSAGE -- print message (not necessarily an error)  **  **	Parameters: -**		msg -- the message (printf fmt) -- it can begin with +**		msg -- the message (sm_io_printf fmt) -- it can begin with  **			an SMTP reply code.  If not, 050 is assumed. -**		(others) -- printf arguments +**		(others) -- sm_io_printf arguments  **  **	Returns:  **		none @@ -371,13 +453,13 @@ message(msg, va_alist)  #endif /* __STDC__ */  {  	char *errtxt; -	VA_LOCAL_DECL +	SM_VA_LOCAL_DECL  	errno = 0; -	VA_START(msg); +	SM_VA_START(ap, msg);  	errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap); -	VA_END; -	putoutmsg(MsgBuf, FALSE, FALSE); +	SM_VA_END(ap); +	putoutmsg(MsgBuf, false, false);  	/* save this message for mailq printing */  	switch (MsgBuf[0]) @@ -389,22 +471,23 @@ message(msg, va_alist)  		/* FALLTHROUGH */  	  case '5': -		if (CurEnv->e_message != NULL) +		if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)  			sm_free(CurEnv->e_message); -		CurEnv->e_message = newstr(errtxt); +		CurEnv->e_message = +			sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);  		break;  	}  } -/* +/*  **  NMESSAGE -- print message (not necessarily an error)  **  **	Just like "message" except it never puts the to... tag on.  **  **	Parameters: -**		msg -- the message (printf fmt) -- if it begins +**		msg -- the message (sm_io_printf fmt) -- if it begins  **			with a three digit SMTP reply code, that is used,  **			otherwise 050 is assumed. -**		(others) -- printf arguments +**		(others) -- sm_io_printf arguments  **  **	Returns:  **		none @@ -424,14 +507,14 @@ nmessage(msg, va_alist)  #endif /* __STDC__ */  {  	char *errtxt; -	VA_LOCAL_DECL +	SM_VA_LOCAL_DECL  	errno = 0; -	VA_START(msg); +	SM_VA_START(ap, msg);  	errtxt = fmtmsg(MsgBuf, (char *) NULL, "050",  			(char *) NULL, 0, msg, ap); -	VA_END; -	putoutmsg(MsgBuf, FALSE, FALSE); +	SM_VA_END(ap); +	putoutmsg(MsgBuf, false, false);  	/* save this message for mailq printing */  	switch (MsgBuf[0]) @@ -443,20 +526,21 @@ nmessage(msg, va_alist)  		/* FALLTHROUGH */  	  case '5': -		if (CurEnv->e_message != NULL) +		if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)  			sm_free(CurEnv->e_message); -		CurEnv->e_message = newstr(errtxt); +		CurEnv->e_message = +			sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);  		break;  	}  } -/* +/*  **  PUTOUTMSG -- output error message to transcript and channel  **  **	Parameters:  **		msg -- message to output (in SMTP format). -**		holdmsg -- if TRUE, don't output a copy of the message to +**		holdmsg -- if true, don't output a copy of the message to  **			our output channel. -**		heldmsg -- if TRUE, this is a previously held message; +**		heldmsg -- if true, this is a previously held message;  **			don't log it to the transcript file.  **  **	Returns: @@ -479,7 +563,7 @@ putoutmsg(msg, holdmsg, heldmsg)  	/* display for debugging */  	if (tTd(54, 8)) -		dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "", +		sm_dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",  			heldmsg ? " (held)" : "");  	/* map warnings to something SMTP can handle */ @@ -491,12 +575,13 @@ putoutmsg(msg, holdmsg, heldmsg)  	/* output to transcript if serious */  	if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&  	    strchr("45", msg[0]) != NULL) -		fprintf(CurEnv->e_xfp, "%s\n", msg); +		(void) sm_io_fprintf(CurEnv->e_xfp, SM_TIME_DEFAULT, "%s\n", +				     msg); -	if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) +	if (LogLevel > 14 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))  		sm_syslog(LOG_INFO, CurEnv->e_id, -			  "--> %s%s", -			  msg, holdmsg ? " (held)" : ""); +			  "--- %s%s%s", msg, holdmsg ? " (hold)" : "", +			  heldmsg ? " (held)" : "");  	if (msgcode == '8')  		msg[0] = '0'; @@ -510,11 +595,11 @@ putoutmsg(msg, holdmsg, heldmsg)  		msg[0] = msgcode;  		if (HeldMessageBuf[0] == '5' && msgcode == '4')  			return; -		snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg); +		(void) sm_strlcpy(HeldMessageBuf, msg, sizeof HeldMessageBuf);  		return;  	} -	(void) fflush(stdout); +	(void) sm_io_flush(smioout, SM_TIME_DEFAULT);  	if (OutChannel == NULL)  		return; @@ -535,15 +620,21 @@ putoutmsg(msg, holdmsg, heldmsg)  	/* if DisConnected, OutChannel now points to the transcript */  	if (!DisConnected &&  	    (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP)) -		fprintf(OutChannel, "%s\r\n", msg); +		(void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\r\n", +				     msg);  	else -		fprintf(OutChannel, "%s\n", errtxt); +		(void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\n", +				     errtxt);  	if (TrafficLogFile != NULL) -		fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(), -			(OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : errtxt); +		(void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, +				     "%05d >>> %s\n", (int) CurrentPid, +				     (OpMode == MD_SMTP || OpMode == MD_DAEMON) +					? msg : errtxt); +#if !PIPELINING +	/* XXX can't flush here for SMTP pipelining */  	if (msg[3] == ' ') -		(void) fflush(OutChannel); -	if (!ferror(OutChannel) || DisConnected) +		(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT); +	if (!sm_io_error(OutChannel) || DisConnected)  		return;  	/* @@ -552,19 +643,20 @@ putoutmsg(msg, holdmsg, heldmsg)  	**	rude servers don't read result.  	*/ -	if (InChannel == NULL || feof(InChannel) || ferror(InChannel) || -	    strncmp(msg, "221", 3) == 0) +	if (InChannel == NULL || sm_io_eof(InChannel) || +	    sm_io_error(InChannel) || strncmp(msg, "221", 3) == 0)  		return;  	/* can't call syserr, 'cause we are using MsgBuf */ -	HoldErrs = TRUE; +	HoldErrs = true;  	if (LogLevel > 0)  		sm_syslog(LOG_CRIT, CurEnv->e_id,  			  "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", -			  CurHostName == NULL ? "NO-HOST" : CurHostName, -			  shortenstring(msg, MAXSHORTSTR), errstring(errno)); +			  CURHOSTNAME, +			  shortenstring(msg, MAXSHORTSTR), sm_errstring(errno)); +#endif /* !PIPELINING */  } -/* +/*  **  PUTERRMSG -- like putoutmsg, but does special processing for error messages  **  **	Parameters: @@ -584,11 +676,11 @@ puterrmsg(msg)  	char msgcode = msg[0];  	/* output the message as usual */ -	putoutmsg(msg, HoldErrs, FALSE); +	putoutmsg(msg, HoldErrs, false);  	/* be careful about multiple error messages */  	if (OnlyOneError) -		HoldErrs = TRUE; +		HoldErrs = true;  	/* signal the error */  	Errors++; @@ -607,7 +699,7 @@ puterrmsg(msg)  		CurEnv->e_flags |= EF_FATALERRS;  	}  } -/* +/*  **  ISENHSC -- check whether a string contains an enhanced status code  **  **	Parameters: @@ -646,7 +738,7 @@ isenhsc(s, delim)  		return 0;  	return l + h;  } -/* +/*  **  EXTENHSC -- check and extract an enhanced status code  **  **	Parameters: @@ -663,6 +755,7 @@ isenhsc(s, delim)  **	Side Effects:  **		fills e with enhanced status code.  */ +  int  extenhsc(s, delim, e)  	const char *s; @@ -699,7 +792,7 @@ extenhsc(s, delim, e)  	e[l + h] = '\0';  	return l + h;  } -/* +/*  **  FMTMSG -- format a message into buffer.  **  **	Parameters: @@ -726,7 +819,7 @@ fmtmsg(eb, to, num, enhsc, eno, fmt, ap)  	const char *enhsc;  	int eno;  	const char *fmt; -	va_list ap; +	SM_VA_LOCAL_DECL  {  	char del;  	int l; @@ -743,7 +836,15 @@ fmtmsg(eb, to, num, enhsc, eno, fmt, ap)  		del = '-';  	else  		del = ' '; -	(void) snprintf(eb, spaceleft, "%3.3s%c", num, del); +#if _FFR_SOFT_BOUNCE +	if (SoftBounce && num[0] == '5') +	{ +		/* replace 5 by 4 */ +		(void) sm_snprintf(eb, spaceleft, "4%2.2s%c", num + 1, del); +	} +	else +#endif /* _FFR_SOFT_BOUNCE */ +	(void) sm_snprintf(eb, spaceleft, "%3.3s%c", num, del);  	eb += 4;  	spaceleft -= 4; @@ -751,7 +852,7 @@ fmtmsg(eb, to, num, enhsc, eno, fmt, ap)  	{  		/* copy enh.status code including trailing blank */  		l++; -		(void) strlcpy(eb, fmt, l + 1); +		(void) sm_strlcpy(eb, fmt, l + 1);  		eb += l;  		spaceleft -= l;  		fmt += l; @@ -759,19 +860,26 @@ fmtmsg(eb, to, num, enhsc, eno, fmt, ap)  	else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4)  	{  		/* copy enh.status code */ -		(void) strlcpy(eb, enhsc, l + 1); +		(void) sm_strlcpy(eb, enhsc, l + 1);  		eb[l] = ' ';  		eb[++l] = '\0';  		eb += l;  		spaceleft -= l;  	} +#if _FFR_SOFT_BOUNCE +	if (SoftBounce && eb[-l] == '5') +	{ +		/* replace 5 by 4 */ +		eb[-l] = '4'; +	} +#endif /* _FFR_SOFT_BOUNCE */  	errtxt = eb;  	/* output the file name and line number */  	if (FileName != NULL)  	{ -		(void) snprintf(eb, spaceleft, "%s: line %d: ", -			shortenstring(FileName, 83), LineNumber); +		(void) sm_snprintf(eb, spaceleft, "%s: line %d: ", +				   shortenstring(FileName, 83), LineNumber);  		eb += (l = strlen(eb));  		spaceleft -= l;  	} @@ -798,26 +906,26 @@ fmtmsg(eb, to, num, enhsc, eno, fmt, ap)  	     strncmp(num, "550", 3) == 0 ||  	     strncmp(num, "553", 3) == 0))  	{ -		(void) snprintf(eb, spaceleft, "%s... ", -			shortenstring(to, MAXSHORTSTR)); +		(void) sm_strlcpyn(eb, spaceleft, 2, +				   shortenstring(to, MAXSHORTSTR), "... ");  		spaceleft -= strlen(eb);  		while (*eb != '\0')  			*eb++ &= 0177;  	}  	/* output the message */ -	(void) vsnprintf(eb, spaceleft, fmt, ap); +	(void) sm_vsnprintf(eb, spaceleft, fmt, ap);  	spaceleft -= strlen(eb);  	while (*eb != '\0')  		*eb++ &= 0177;  	/* output the error code, if any */  	if (eno != 0) -		(void) snprintf(eb, spaceleft, ": %s", errstring(eno)); +		(void) sm_strlcpyn(eb, spaceleft, 2, ": ", sm_errstring(eno));  	return errtxt;  } -/* +/*  **  BUFFER_ERRORS -- arrange to buffer future error messages  **  **	Parameters: @@ -831,9 +939,9 @@ void  buffer_errors()  {  	HeldMessageBuf[0] = '\0'; -	HoldErrs = TRUE; +	HoldErrs = true;  } -/* +/*  **  FLUSH_ERRORS -- flush the held error message buffer  **  **	Parameters: @@ -849,12 +957,12 @@ flush_errors(print)  	bool print;  {  	if (print && HeldMessageBuf[0] != '\0') -		putoutmsg(HeldMessageBuf, FALSE, TRUE); +		putoutmsg(HeldMessageBuf, false, true);  	HeldMessageBuf[0] = '\0'; -	HoldErrs = FALSE; +	HoldErrs = false;  } -/* -**  ERRSTRING -- return string description of error code +/* +**  SM_ERRSTRING -- return string description of error code  **  **	Parameters:  **		errnum -- the error number to translate @@ -867,12 +975,16 @@ flush_errors(print)  */  const char * -errstring(errnum) +sm_errstring(errnum)  	int errnum;  {  	char *dnsmsg;  	char *bp;  	static char buf[MAXLINE]; +#if HASSTRERROR +	char *err; +	char errbuf[30]; +#endif /* HASSTRERROR */  #if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)  	extern char *sys_errlist[];  	extern int sys_nerr; @@ -887,58 +999,67 @@ errstring(errnum)  	dnsmsg = NULL;  	switch (errnum)  	{ -#if defined(DAEMON) && defined(ETIMEDOUT)  	  case ETIMEDOUT:  	  case ECONNRESET:  		bp = buf; -# if HASSTRERROR -		snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum)); -# else /* HASSTRERROR */ +#if HASSTRERROR +		err = strerror(errnum); +		if (err == NULL) +		{ +			(void) sm_snprintf(errbuf, sizeof errbuf, +					   "Error %d", errnum); +			err = errbuf; +		} +		(void) sm_strlcpy(bp, err, SPACELEFT(buf, bp)); +#else /* HASSTRERROR */  		if (errnum >= 0 && errnum < sys_nerr) -			snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]); +			(void) sm_strlcpy(bp, sys_errlist[errnum], +					  SPACELEFT(buf, bp));  		else -			snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum); -# endif /* HASSTRERROR */ +			(void) sm_snprintf(bp, SPACELEFT(buf, bp), +				"Error %d", errnum); +#endif /* HASSTRERROR */  		bp += strlen(bp);  		if (CurHostName != NULL)  		{  			if (errnum == ETIMEDOUT)  			{ -				snprintf(bp, SPACELEFT(buf, bp), " with "); +				(void) sm_snprintf(bp, SPACELEFT(buf, bp), +					" with ");  				bp += strlen(bp);  			}  			else  			{  				bp = buf; -				snprintf(bp, SPACELEFT(buf, bp), +				(void) sm_snprintf(bp, SPACELEFT(buf, bp),  					"Connection reset by ");  				bp += strlen(bp);  			} -			snprintf(bp, SPACELEFT(buf, bp), "%s", -				shortenstring(CurHostName, MAXSHORTSTR)); +			(void) sm_strlcpy(bp, +					shortenstring(CurHostName, MAXSHORTSTR), +					SPACELEFT(buf, bp));  			bp += strlen(buf);  		}  		if (SmtpPhase != NULL)  		{ -			snprintf(bp, SPACELEFT(buf, bp), " during %s", -				SmtpPhase); +			(void) sm_snprintf(bp, SPACELEFT(buf, bp), +				" during %s", SmtpPhase);  		}  		return buf;  	  case EHOSTDOWN:  		if (CurHostName == NULL)  			break; -		(void) snprintf(buf, sizeof buf, "Host %s is down", +		(void) sm_snprintf(buf, sizeof buf, "Host %s is down",  			shortenstring(CurHostName, MAXSHORTSTR));  		return buf;  	  case ECONNREFUSED:  		if (CurHostName == NULL)  			break; -		(void) snprintf(buf, sizeof buf, "Connection refused by %s", +		(void) sm_strlcpyn(buf, sizeof buf, 2, "Connection refused by ",  			shortenstring(CurHostName, MAXSHORTSTR));  		return buf; -#endif /* defined(DAEMON) && defined(ETIMEDOUT) */  #if NAMED_BIND  	  case HOST_NOT_FOUND + E_DNSBASE: @@ -1006,29 +1127,35 @@ errstring(errnum)  	if (dnsmsg != NULL)  	{  		bp = buf; -		bp += strlcpy(bp, "Name server: ", sizeof buf); +		bp += sm_strlcpy(bp, "Name server: ", sizeof buf);  		if (CurHostName != NULL)  		{ -			snprintf(bp, SPACELEFT(buf, bp), "%s: ", -				shortenstring(CurHostName, MAXSHORTSTR)); +			(void) sm_strlcpyn(bp, SPACELEFT(buf, bp), 2, +				shortenstring(CurHostName, MAXSHORTSTR), ": ");  			bp += strlen(bp);  		} -		snprintf(bp, SPACELEFT(buf, bp), "%s", dnsmsg); +		(void) sm_strlcpy(bp, dnsmsg, SPACELEFT(buf, bp));  		return buf;  	} -#ifdef LDAPMAP +#if LDAPMAP  	if (errnum >= E_LDAPBASE)  		return ldap_err2string(errnum - E_LDAPBASE);  #endif /* LDAPMAP */  #if HASSTRERROR -	return strerror(errnum); +	err = strerror(errnum); +	if (err == NULL) +	{ +		(void) sm_snprintf(buf, sizeof buf, "Error %d", errnum); +		return buf; +	} +	return err;  #else /* HASSTRERROR */  	if (errnum > 0 && errnum < sys_nerr)  		return sys_errlist[errnum]; -	(void) snprintf(buf, sizeof buf, "Error %d", errnum); +	(void) sm_snprintf(buf, sizeof buf, "Error %d", errnum);  	return buf;  #endif /* HASSTRERROR */  }  | 
