xref: /freebsd/contrib/sendmail/src/err.c (revision c2aa98e247e56d5266d789dfc9b90b524b0019fe)
1c2aa98e2SPeter Wemm /*
2c2aa98e2SPeter Wemm  * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3c2aa98e2SPeter Wemm  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1988, 1993
5c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
6c2aa98e2SPeter Wemm  *
7c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
8c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
9c2aa98e2SPeter Wemm  * the sendmail distribution.
10c2aa98e2SPeter Wemm  *
11c2aa98e2SPeter Wemm  */
12c2aa98e2SPeter Wemm 
13c2aa98e2SPeter Wemm #ifndef lint
14c2aa98e2SPeter Wemm static char sccsid[] = "@(#)err.c	8.74 (Berkeley) 6/4/98";
15c2aa98e2SPeter Wemm #endif /* not lint */
16c2aa98e2SPeter Wemm 
17c2aa98e2SPeter Wemm # include "sendmail.h"
18c2aa98e2SPeter Wemm # include <errno.h>
19c2aa98e2SPeter Wemm 
20c2aa98e2SPeter Wemm /*
21c2aa98e2SPeter Wemm **  SYSERR -- Print error message.
22c2aa98e2SPeter Wemm **
23c2aa98e2SPeter Wemm **	Prints an error message via printf to the diagnostic output.
24c2aa98e2SPeter Wemm **
25c2aa98e2SPeter Wemm **	If the first character of the syserr message is `!' it will
26c2aa98e2SPeter Wemm **	log this as an ALERT message and exit immediately.  This can
27c2aa98e2SPeter Wemm **	leave queue files in an indeterminate state, so it should not
28c2aa98e2SPeter Wemm **	be used lightly.
29c2aa98e2SPeter Wemm **
30c2aa98e2SPeter Wemm **	Parameters:
31c2aa98e2SPeter Wemm **		fmt -- the format string.  If it does not begin with
32c2aa98e2SPeter Wemm **			a three-digit SMTP reply code, either 554 or
33c2aa98e2SPeter Wemm **			451 is assumed depending on whether errno
34c2aa98e2SPeter Wemm **			is set.
35c2aa98e2SPeter Wemm **		(others) -- parameters
36c2aa98e2SPeter Wemm **
37c2aa98e2SPeter Wemm **	Returns:
38c2aa98e2SPeter Wemm **		none
39c2aa98e2SPeter Wemm **		Through TopFrame if QuickAbort is set.
40c2aa98e2SPeter Wemm **
41c2aa98e2SPeter Wemm **	Side Effects:
42c2aa98e2SPeter Wemm **		increments Errors.
43c2aa98e2SPeter Wemm **		sets ExitStat.
44c2aa98e2SPeter Wemm */
45c2aa98e2SPeter Wemm 
46c2aa98e2SPeter Wemm char	MsgBuf[BUFSIZ*2];		/* text of most recent message */
47c2aa98e2SPeter Wemm char	HeldMessageBuf[sizeof MsgBuf];	/* for held messages */
48c2aa98e2SPeter Wemm 
49c2aa98e2SPeter Wemm extern void	putoutmsg __P((char *, bool, bool));
50c2aa98e2SPeter Wemm extern void	puterrmsg __P((char *));
51c2aa98e2SPeter Wemm static void	fmtmsg __P((char *, const char *, const char *, int, const char *, va_list));
52c2aa98e2SPeter Wemm 
53c2aa98e2SPeter Wemm #if NAMED_BIND && !defined(NO_DATA)
54c2aa98e2SPeter Wemm # define NO_DATA	NO_ADDRESS
55c2aa98e2SPeter Wemm #endif
56c2aa98e2SPeter Wemm 
57c2aa98e2SPeter Wemm void
58c2aa98e2SPeter Wemm /*VARARGS1*/
59c2aa98e2SPeter Wemm #ifdef __STDC__
60c2aa98e2SPeter Wemm syserr(const char *fmt, ...)
61c2aa98e2SPeter Wemm #else
62c2aa98e2SPeter Wemm syserr(fmt, va_alist)
63c2aa98e2SPeter Wemm 	const char *fmt;
64c2aa98e2SPeter Wemm 	va_dcl
65c2aa98e2SPeter Wemm #endif
66c2aa98e2SPeter Wemm {
67c2aa98e2SPeter Wemm 	register char *p;
68c2aa98e2SPeter Wemm 	int olderrno = errno;
69c2aa98e2SPeter Wemm 	bool panic;
70c2aa98e2SPeter Wemm 	char *uname;
71c2aa98e2SPeter Wemm 	struct passwd *pw;
72c2aa98e2SPeter Wemm 	char ubuf[80];
73c2aa98e2SPeter Wemm 	VA_LOCAL_DECL
74c2aa98e2SPeter Wemm 
75c2aa98e2SPeter Wemm 	panic = *fmt == '!';
76c2aa98e2SPeter Wemm 	if (panic)
77c2aa98e2SPeter Wemm 	{
78c2aa98e2SPeter Wemm 		fmt++;
79c2aa98e2SPeter Wemm 		HoldErrs = FALSE;
80c2aa98e2SPeter Wemm 	}
81c2aa98e2SPeter Wemm 
82c2aa98e2SPeter Wemm 	/* format and output the error message */
83c2aa98e2SPeter Wemm 	if (olderrno == 0)
84c2aa98e2SPeter Wemm 		p = "554";
85c2aa98e2SPeter Wemm 	else
86c2aa98e2SPeter Wemm 		p = "451";
87c2aa98e2SPeter Wemm 	VA_START(fmt);
88c2aa98e2SPeter Wemm 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
89c2aa98e2SPeter Wemm 	VA_END;
90c2aa98e2SPeter Wemm 	puterrmsg(MsgBuf);
91c2aa98e2SPeter Wemm 
92c2aa98e2SPeter Wemm 	/* save this message for mailq printing */
93c2aa98e2SPeter Wemm 	if (!panic && CurEnv != NULL)
94c2aa98e2SPeter Wemm 	{
95c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
96c2aa98e2SPeter Wemm 			free(CurEnv->e_message);
97c2aa98e2SPeter Wemm 		CurEnv->e_message = newstr(MsgBuf + 4);
98c2aa98e2SPeter Wemm 	}
99c2aa98e2SPeter Wemm 
100c2aa98e2SPeter Wemm 	/* determine exit status if not already set */
101c2aa98e2SPeter Wemm 	if (ExitStat == EX_OK)
102c2aa98e2SPeter Wemm 	{
103c2aa98e2SPeter Wemm 		if (olderrno == 0)
104c2aa98e2SPeter Wemm 			ExitStat = EX_SOFTWARE;
105c2aa98e2SPeter Wemm 		else
106c2aa98e2SPeter Wemm 			ExitStat = EX_OSERR;
107c2aa98e2SPeter Wemm 		if (tTd(54, 1))
108c2aa98e2SPeter Wemm 			printf("syserr: ExitStat = %d\n", ExitStat);
109c2aa98e2SPeter Wemm 	}
110c2aa98e2SPeter Wemm 
111c2aa98e2SPeter Wemm 	pw = sm_getpwuid(getuid());
112c2aa98e2SPeter Wemm 	if (pw != NULL)
113c2aa98e2SPeter Wemm 		uname = pw->pw_name;
114c2aa98e2SPeter Wemm 	else
115c2aa98e2SPeter Wemm 	{
116c2aa98e2SPeter Wemm 		uname = ubuf;
117c2aa98e2SPeter Wemm 		snprintf(ubuf, sizeof ubuf, "UID%d", getuid());
118c2aa98e2SPeter Wemm 	}
119c2aa98e2SPeter Wemm 
120c2aa98e2SPeter Wemm 	if (LogLevel > 0)
121c2aa98e2SPeter Wemm 		sm_syslog(panic ? LOG_ALERT : LOG_CRIT,
122c2aa98e2SPeter Wemm 			  CurEnv == NULL ? NOQID : CurEnv->e_id,
123c2aa98e2SPeter Wemm 			  "SYSERR(%s): %.900s",
124c2aa98e2SPeter Wemm 			  uname, &MsgBuf[4]);
125c2aa98e2SPeter Wemm 	switch (olderrno)
126c2aa98e2SPeter Wemm 	{
127c2aa98e2SPeter Wemm 	  case EBADF:
128c2aa98e2SPeter Wemm 	  case ENFILE:
129c2aa98e2SPeter Wemm 	  case EMFILE:
130c2aa98e2SPeter Wemm 	  case ENOTTY:
131c2aa98e2SPeter Wemm #ifdef EFBIG
132c2aa98e2SPeter Wemm 	  case EFBIG:
133c2aa98e2SPeter Wemm #endif
134c2aa98e2SPeter Wemm #ifdef ESPIPE
135c2aa98e2SPeter Wemm 	  case ESPIPE:
136c2aa98e2SPeter Wemm #endif
137c2aa98e2SPeter Wemm #ifdef EPIPE
138c2aa98e2SPeter Wemm 	  case EPIPE:
139c2aa98e2SPeter Wemm #endif
140c2aa98e2SPeter Wemm #ifdef ENOBUFS
141c2aa98e2SPeter Wemm 	  case ENOBUFS:
142c2aa98e2SPeter Wemm #endif
143c2aa98e2SPeter Wemm #ifdef ESTALE
144c2aa98e2SPeter Wemm 	  case ESTALE:
145c2aa98e2SPeter Wemm #endif
146c2aa98e2SPeter Wemm 		printopenfds(TRUE);
147c2aa98e2SPeter Wemm 		mci_dump_all(TRUE);
148c2aa98e2SPeter Wemm 		break;
149c2aa98e2SPeter Wemm 	}
150c2aa98e2SPeter Wemm 	if (panic)
151c2aa98e2SPeter Wemm 	{
152c2aa98e2SPeter Wemm #ifdef XLA
153c2aa98e2SPeter Wemm 		xla_all_end();
154c2aa98e2SPeter Wemm #endif
155c2aa98e2SPeter Wemm 		if (tTd(0, 1))
156c2aa98e2SPeter Wemm 			abort();
157c2aa98e2SPeter Wemm 		exit(EX_OSERR);
158c2aa98e2SPeter Wemm 	}
159c2aa98e2SPeter Wemm 	errno = 0;
160c2aa98e2SPeter Wemm 	if (QuickAbort)
161c2aa98e2SPeter Wemm 		longjmp(TopFrame, 2);
162c2aa98e2SPeter Wemm }
163c2aa98e2SPeter Wemm /*
164c2aa98e2SPeter Wemm **  USRERR -- Signal user error.
165c2aa98e2SPeter Wemm **
166c2aa98e2SPeter Wemm **	This is much like syserr except it is for user errors.
167c2aa98e2SPeter Wemm **
168c2aa98e2SPeter Wemm **	Parameters:
169c2aa98e2SPeter Wemm **		fmt -- the format string.  If it does not begin with
170c2aa98e2SPeter Wemm **			a three-digit SMTP reply code, 501 is assumed.
171c2aa98e2SPeter Wemm **		(others) -- printf strings
172c2aa98e2SPeter Wemm **
173c2aa98e2SPeter Wemm **	Returns:
174c2aa98e2SPeter Wemm **		none
175c2aa98e2SPeter Wemm **		Through TopFrame if QuickAbort is set.
176c2aa98e2SPeter Wemm **
177c2aa98e2SPeter Wemm **	Side Effects:
178c2aa98e2SPeter Wemm **		increments Errors.
179c2aa98e2SPeter Wemm */
180c2aa98e2SPeter Wemm 
181c2aa98e2SPeter Wemm /*VARARGS1*/
182c2aa98e2SPeter Wemm void
183c2aa98e2SPeter Wemm #ifdef __STDC__
184c2aa98e2SPeter Wemm usrerr(const char *fmt, ...)
185c2aa98e2SPeter Wemm #else
186c2aa98e2SPeter Wemm usrerr(fmt, va_alist)
187c2aa98e2SPeter Wemm 	const char *fmt;
188c2aa98e2SPeter Wemm 	va_dcl
189c2aa98e2SPeter Wemm #endif
190c2aa98e2SPeter Wemm {
191c2aa98e2SPeter Wemm 	VA_LOCAL_DECL
192c2aa98e2SPeter Wemm 
193c2aa98e2SPeter Wemm 	if (SuprErrs)
194c2aa98e2SPeter Wemm 		return;
195c2aa98e2SPeter Wemm 
196c2aa98e2SPeter Wemm 	VA_START(fmt);
197c2aa98e2SPeter Wemm 	fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
198c2aa98e2SPeter Wemm 	VA_END;
199c2aa98e2SPeter Wemm 
200c2aa98e2SPeter Wemm 	/* save this message for mailq printing */
201c2aa98e2SPeter Wemm 	switch (MsgBuf[0])
202c2aa98e2SPeter Wemm 	{
203c2aa98e2SPeter Wemm 	  case '4':
204c2aa98e2SPeter Wemm 	  case '8':
205c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
206c2aa98e2SPeter Wemm 			break;
207c2aa98e2SPeter Wemm 
208c2aa98e2SPeter Wemm 		/* fall through.... */
209c2aa98e2SPeter Wemm 
210c2aa98e2SPeter Wemm 	  case '5':
211c2aa98e2SPeter Wemm 	  case '6':
212c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
213c2aa98e2SPeter Wemm 			free(CurEnv->e_message);
214c2aa98e2SPeter Wemm 		if (MsgBuf[0] == '6')
215c2aa98e2SPeter Wemm 		{
216c2aa98e2SPeter Wemm 			char buf[MAXLINE];
217c2aa98e2SPeter Wemm 
218c2aa98e2SPeter Wemm 			snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
219c2aa98e2SPeter Wemm 				sizeof buf - 22, MsgBuf + 4);
220c2aa98e2SPeter Wemm 			CurEnv->e_message = newstr(buf);
221c2aa98e2SPeter Wemm 		}
222c2aa98e2SPeter Wemm 		else
223c2aa98e2SPeter Wemm 		{
224c2aa98e2SPeter Wemm 			CurEnv->e_message = newstr(MsgBuf + 4);
225c2aa98e2SPeter Wemm 		}
226c2aa98e2SPeter Wemm 		break;
227c2aa98e2SPeter Wemm 	}
228c2aa98e2SPeter Wemm 
229c2aa98e2SPeter Wemm 	puterrmsg(MsgBuf);
230c2aa98e2SPeter Wemm 
231c2aa98e2SPeter Wemm 	if (LogLevel > 3 && LogUsrErrs)
232c2aa98e2SPeter Wemm 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
233c2aa98e2SPeter Wemm 			"%.900s",
234c2aa98e2SPeter Wemm 			&MsgBuf[4]);
235c2aa98e2SPeter Wemm 
236c2aa98e2SPeter Wemm 	if (QuickAbort)
237c2aa98e2SPeter Wemm 		longjmp(TopFrame, 1);
238c2aa98e2SPeter Wemm }
239c2aa98e2SPeter Wemm /*
240c2aa98e2SPeter Wemm **  MESSAGE -- print message (not necessarily an error)
241c2aa98e2SPeter Wemm **
242c2aa98e2SPeter Wemm **	Parameters:
243c2aa98e2SPeter Wemm **		msg -- the message (printf fmt) -- it can begin with
244c2aa98e2SPeter Wemm **			an SMTP reply code.  If not, 050 is assumed.
245c2aa98e2SPeter Wemm **		(others) -- printf arguments
246c2aa98e2SPeter Wemm **
247c2aa98e2SPeter Wemm **	Returns:
248c2aa98e2SPeter Wemm **		none
249c2aa98e2SPeter Wemm **
250c2aa98e2SPeter Wemm **	Side Effects:
251c2aa98e2SPeter Wemm **		none.
252c2aa98e2SPeter Wemm */
253c2aa98e2SPeter Wemm 
254c2aa98e2SPeter Wemm /*VARARGS1*/
255c2aa98e2SPeter Wemm void
256c2aa98e2SPeter Wemm #ifdef __STDC__
257c2aa98e2SPeter Wemm message(const char *msg, ...)
258c2aa98e2SPeter Wemm #else
259c2aa98e2SPeter Wemm message(msg, va_alist)
260c2aa98e2SPeter Wemm 	const char *msg;
261c2aa98e2SPeter Wemm 	va_dcl
262c2aa98e2SPeter Wemm #endif
263c2aa98e2SPeter Wemm {
264c2aa98e2SPeter Wemm 	VA_LOCAL_DECL
265c2aa98e2SPeter Wemm 
266c2aa98e2SPeter Wemm 	errno = 0;
267c2aa98e2SPeter Wemm 	VA_START(msg);
268c2aa98e2SPeter Wemm 	fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
269c2aa98e2SPeter Wemm 	VA_END;
270c2aa98e2SPeter Wemm 	putoutmsg(MsgBuf, FALSE, FALSE);
271c2aa98e2SPeter Wemm 
272c2aa98e2SPeter Wemm 	/* save this message for mailq printing */
273c2aa98e2SPeter Wemm 	switch (MsgBuf[0])
274c2aa98e2SPeter Wemm 	{
275c2aa98e2SPeter Wemm 	  case '4':
276c2aa98e2SPeter Wemm 	  case '8':
277c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
278c2aa98e2SPeter Wemm 			break;
279c2aa98e2SPeter Wemm 		/* fall through.... */
280c2aa98e2SPeter Wemm 
281c2aa98e2SPeter Wemm 	  case '5':
282c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
283c2aa98e2SPeter Wemm 			free(CurEnv->e_message);
284c2aa98e2SPeter Wemm 		CurEnv->e_message = newstr(MsgBuf + 4);
285c2aa98e2SPeter Wemm 		break;
286c2aa98e2SPeter Wemm 	}
287c2aa98e2SPeter Wemm }
288c2aa98e2SPeter Wemm /*
289c2aa98e2SPeter Wemm **  NMESSAGE -- print message (not necessarily an error)
290c2aa98e2SPeter Wemm **
291c2aa98e2SPeter Wemm **	Just like "message" except it never puts the to... tag on.
292c2aa98e2SPeter Wemm **
293c2aa98e2SPeter Wemm **	Parameters:
294c2aa98e2SPeter Wemm **		msg -- the message (printf fmt) -- if it begins
295c2aa98e2SPeter Wemm **			with a three digit SMTP reply code, that is used,
296c2aa98e2SPeter Wemm **			otherwise 050 is assumed.
297c2aa98e2SPeter Wemm **		(others) -- printf arguments
298c2aa98e2SPeter Wemm **
299c2aa98e2SPeter Wemm **	Returns:
300c2aa98e2SPeter Wemm **		none
301c2aa98e2SPeter Wemm **
302c2aa98e2SPeter Wemm **	Side Effects:
303c2aa98e2SPeter Wemm **		none.
304c2aa98e2SPeter Wemm */
305c2aa98e2SPeter Wemm 
306c2aa98e2SPeter Wemm /*VARARGS1*/
307c2aa98e2SPeter Wemm void
308c2aa98e2SPeter Wemm #ifdef __STDC__
309c2aa98e2SPeter Wemm nmessage(const char *msg, ...)
310c2aa98e2SPeter Wemm #else
311c2aa98e2SPeter Wemm nmessage(msg, va_alist)
312c2aa98e2SPeter Wemm 	const char *msg;
313c2aa98e2SPeter Wemm 	va_dcl
314c2aa98e2SPeter Wemm #endif
315c2aa98e2SPeter Wemm {
316c2aa98e2SPeter Wemm 	VA_LOCAL_DECL
317c2aa98e2SPeter Wemm 
318c2aa98e2SPeter Wemm 	errno = 0;
319c2aa98e2SPeter Wemm 	VA_START(msg);
320c2aa98e2SPeter Wemm 	fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
321c2aa98e2SPeter Wemm 	VA_END;
322c2aa98e2SPeter Wemm 	putoutmsg(MsgBuf, FALSE, FALSE);
323c2aa98e2SPeter Wemm 
324c2aa98e2SPeter Wemm 	/* save this message for mailq printing */
325c2aa98e2SPeter Wemm 	switch (MsgBuf[0])
326c2aa98e2SPeter Wemm 	{
327c2aa98e2SPeter Wemm 	  case '4':
328c2aa98e2SPeter Wemm 	  case '8':
329c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
330c2aa98e2SPeter Wemm 			break;
331c2aa98e2SPeter Wemm 		/* fall through.... */
332c2aa98e2SPeter Wemm 
333c2aa98e2SPeter Wemm 	  case '5':
334c2aa98e2SPeter Wemm 		if (CurEnv->e_message != NULL)
335c2aa98e2SPeter Wemm 			free(CurEnv->e_message);
336c2aa98e2SPeter Wemm 		CurEnv->e_message = newstr(MsgBuf + 4);
337c2aa98e2SPeter Wemm 		break;
338c2aa98e2SPeter Wemm 	}
339c2aa98e2SPeter Wemm }
340c2aa98e2SPeter Wemm /*
341c2aa98e2SPeter Wemm **  PUTOUTMSG -- output error message to transcript and channel
342c2aa98e2SPeter Wemm **
343c2aa98e2SPeter Wemm **	Parameters:
344c2aa98e2SPeter Wemm **		msg -- message to output (in SMTP format).
345c2aa98e2SPeter Wemm **		holdmsg -- if TRUE, don't output a copy of the message to
346c2aa98e2SPeter Wemm **			our output channel.
347c2aa98e2SPeter Wemm **		heldmsg -- if TRUE, this is a previously held message;
348c2aa98e2SPeter Wemm **			don't log it to the transcript file.
349c2aa98e2SPeter Wemm **
350c2aa98e2SPeter Wemm **	Returns:
351c2aa98e2SPeter Wemm **		none.
352c2aa98e2SPeter Wemm **
353c2aa98e2SPeter Wemm **	Side Effects:
354c2aa98e2SPeter Wemm **		Outputs msg to the transcript.
355c2aa98e2SPeter Wemm **		If appropriate, outputs it to the channel.
356c2aa98e2SPeter Wemm **		Deletes SMTP reply code number as appropriate.
357c2aa98e2SPeter Wemm */
358c2aa98e2SPeter Wemm 
359c2aa98e2SPeter Wemm void
360c2aa98e2SPeter Wemm putoutmsg(msg, holdmsg, heldmsg)
361c2aa98e2SPeter Wemm 	char *msg;
362c2aa98e2SPeter Wemm 	bool holdmsg;
363c2aa98e2SPeter Wemm 	bool heldmsg;
364c2aa98e2SPeter Wemm {
365c2aa98e2SPeter Wemm 	char msgcode = msg[0];
366c2aa98e2SPeter Wemm 
367c2aa98e2SPeter Wemm 	/* display for debugging */
368c2aa98e2SPeter Wemm 	if (tTd(54, 8))
369c2aa98e2SPeter Wemm 		printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
370c2aa98e2SPeter Wemm 			heldmsg ? " (held)" : "");
371c2aa98e2SPeter Wemm 
372c2aa98e2SPeter Wemm 	/* map warnings to something SMTP can handle */
373c2aa98e2SPeter Wemm 	if (msgcode == '6')
374c2aa98e2SPeter Wemm 		msg[0] = '5';
375c2aa98e2SPeter Wemm 	else if (msgcode == '8')
376c2aa98e2SPeter Wemm 		msg[0] = '4';
377c2aa98e2SPeter Wemm 
378c2aa98e2SPeter Wemm 	/* output to transcript if serious */
379c2aa98e2SPeter Wemm 	if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&
380c2aa98e2SPeter Wemm 	    strchr("45", msg[0]) != NULL)
381c2aa98e2SPeter Wemm 		fprintf(CurEnv->e_xfp, "%s\n", msg);
382c2aa98e2SPeter Wemm 
383c2aa98e2SPeter Wemm 	if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
384c2aa98e2SPeter Wemm 		sm_syslog(LOG_INFO, CurEnv->e_id,
385c2aa98e2SPeter Wemm 			"--> %s%s",
386c2aa98e2SPeter Wemm 			msg, holdmsg ? " (held)" : "");
387c2aa98e2SPeter Wemm 
388c2aa98e2SPeter Wemm 	if (msgcode == '8')
389c2aa98e2SPeter Wemm 		msg[0] = '0';
390c2aa98e2SPeter Wemm 
391c2aa98e2SPeter Wemm 	/* output to channel if appropriate */
392c2aa98e2SPeter Wemm 	if (!Verbose && msg[0] == '0')
393c2aa98e2SPeter Wemm 		return;
394c2aa98e2SPeter Wemm 	if (holdmsg)
395c2aa98e2SPeter Wemm 	{
396c2aa98e2SPeter Wemm 		/* save for possible future display */
397c2aa98e2SPeter Wemm 		msg[0] = msgcode;
398c2aa98e2SPeter Wemm 		snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg);
399c2aa98e2SPeter Wemm 		return;
400c2aa98e2SPeter Wemm 	}
401c2aa98e2SPeter Wemm 
402c2aa98e2SPeter Wemm 	(void) fflush(stdout);
403c2aa98e2SPeter Wemm 
404c2aa98e2SPeter Wemm 	if (OutChannel == NULL)
405c2aa98e2SPeter Wemm 		return;
406c2aa98e2SPeter Wemm 
407c2aa98e2SPeter Wemm 	/* if DisConnected, OutChannel now points to the transcript */
408c2aa98e2SPeter Wemm 	if (!DisConnected &&
409c2aa98e2SPeter Wemm 	    (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
410c2aa98e2SPeter Wemm 		fprintf(OutChannel, "%s\r\n", msg);
411c2aa98e2SPeter Wemm 	else
412c2aa98e2SPeter Wemm 		fprintf(OutChannel, "%s\n", &msg[4]);
413c2aa98e2SPeter Wemm 	if (TrafficLogFile != NULL)
414c2aa98e2SPeter Wemm 		fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(),
415c2aa98e2SPeter Wemm 			(OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
416c2aa98e2SPeter Wemm 	if (msg[3] == ' ')
417c2aa98e2SPeter Wemm 		(void) fflush(OutChannel);
418c2aa98e2SPeter Wemm 	if (!ferror(OutChannel) || DisConnected)
419c2aa98e2SPeter Wemm 		return;
420c2aa98e2SPeter Wemm 
421c2aa98e2SPeter Wemm 	/*
422c2aa98e2SPeter Wemm 	**  Error on output -- if reporting lost channel, just ignore it.
423c2aa98e2SPeter Wemm 	**  Also, ignore errors from QUIT response (221 message) -- some
424c2aa98e2SPeter Wemm 	**	rude servers don't read result.
425c2aa98e2SPeter Wemm 	*/
426c2aa98e2SPeter Wemm 
427c2aa98e2SPeter Wemm 	if (InChannel == NULL || feof(InChannel) || ferror(InChannel) ||
428c2aa98e2SPeter Wemm 	    strncmp(msg, "221", 3) == 0)
429c2aa98e2SPeter Wemm 		return;
430c2aa98e2SPeter Wemm 
431c2aa98e2SPeter Wemm 	/* can't call syserr, 'cause we are using MsgBuf */
432c2aa98e2SPeter Wemm 	HoldErrs = TRUE;
433c2aa98e2SPeter Wemm 	if (LogLevel > 0)
434c2aa98e2SPeter Wemm 		sm_syslog(LOG_CRIT, CurEnv->e_id,
435c2aa98e2SPeter Wemm 			"SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
436c2aa98e2SPeter Wemm 			CurHostName == NULL ? "NO-HOST" : CurHostName,
437c2aa98e2SPeter Wemm 			shortenstring(msg, MAXSHORTSTR), errstring(errno));
438c2aa98e2SPeter Wemm }
439c2aa98e2SPeter Wemm /*
440c2aa98e2SPeter Wemm **  PUTERRMSG -- like putoutmsg, but does special processing for error messages
441c2aa98e2SPeter Wemm **
442c2aa98e2SPeter Wemm **	Parameters:
443c2aa98e2SPeter Wemm **		msg -- the message to output.
444c2aa98e2SPeter Wemm **
445c2aa98e2SPeter Wemm **	Returns:
446c2aa98e2SPeter Wemm **		none.
447c2aa98e2SPeter Wemm **
448c2aa98e2SPeter Wemm **	Side Effects:
449c2aa98e2SPeter Wemm **		Sets the fatal error bit in the envelope as appropriate.
450c2aa98e2SPeter Wemm */
451c2aa98e2SPeter Wemm 
452c2aa98e2SPeter Wemm void
453c2aa98e2SPeter Wemm puterrmsg(msg)
454c2aa98e2SPeter Wemm 	char *msg;
455c2aa98e2SPeter Wemm {
456c2aa98e2SPeter Wemm 	char msgcode = msg[0];
457c2aa98e2SPeter Wemm 
458c2aa98e2SPeter Wemm 	/* output the message as usual */
459c2aa98e2SPeter Wemm 	putoutmsg(msg, HoldErrs, FALSE);
460c2aa98e2SPeter Wemm 
461c2aa98e2SPeter Wemm 	/* be careful about multiple error messages */
462c2aa98e2SPeter Wemm 	if (OnlyOneError)
463c2aa98e2SPeter Wemm 		HoldErrs = TRUE;
464c2aa98e2SPeter Wemm 
465c2aa98e2SPeter Wemm 	/* signal the error */
466c2aa98e2SPeter Wemm 	Errors++;
467c2aa98e2SPeter Wemm 
468c2aa98e2SPeter Wemm 	if (CurEnv == NULL)
469c2aa98e2SPeter Wemm 		return;
470c2aa98e2SPeter Wemm 
471c2aa98e2SPeter Wemm 	if (msgcode == '6')
472c2aa98e2SPeter Wemm 	{
473c2aa98e2SPeter Wemm 		/* notify the postmaster */
474c2aa98e2SPeter Wemm 		CurEnv->e_flags |= EF_PM_NOTIFY;
475c2aa98e2SPeter Wemm 	}
476c2aa98e2SPeter Wemm 	else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
477c2aa98e2SPeter Wemm 	{
478c2aa98e2SPeter Wemm 		/* mark long-term fatal errors */
479c2aa98e2SPeter Wemm 		CurEnv->e_flags |= EF_FATALERRS;
480c2aa98e2SPeter Wemm 	}
481c2aa98e2SPeter Wemm }
482c2aa98e2SPeter Wemm /*
483c2aa98e2SPeter Wemm **  FMTMSG -- format a message into buffer.
484c2aa98e2SPeter Wemm **
485c2aa98e2SPeter Wemm **	Parameters:
486c2aa98e2SPeter Wemm **		eb -- error buffer to get result.
487c2aa98e2SPeter Wemm **		to -- the recipient tag for this message.
488c2aa98e2SPeter Wemm **		num -- arpanet error number.
489c2aa98e2SPeter Wemm **		en -- the error number to display.
490c2aa98e2SPeter Wemm **		fmt -- format of string.
491c2aa98e2SPeter Wemm **		a, b, c, d, e -- arguments.
492c2aa98e2SPeter Wemm **
493c2aa98e2SPeter Wemm **	Returns:
494c2aa98e2SPeter Wemm **		none.
495c2aa98e2SPeter Wemm **
496c2aa98e2SPeter Wemm **	Side Effects:
497c2aa98e2SPeter Wemm **		none.
498c2aa98e2SPeter Wemm */
499c2aa98e2SPeter Wemm 
500c2aa98e2SPeter Wemm static void
501c2aa98e2SPeter Wemm fmtmsg(eb, to, num, eno, fmt, ap)
502c2aa98e2SPeter Wemm 	register char *eb;
503c2aa98e2SPeter Wemm 	const char *to;
504c2aa98e2SPeter Wemm 	const char *num;
505c2aa98e2SPeter Wemm 	int eno;
506c2aa98e2SPeter Wemm 	const char *fmt;
507c2aa98e2SPeter Wemm 	va_list ap;
508c2aa98e2SPeter Wemm {
509c2aa98e2SPeter Wemm 	char del;
510c2aa98e2SPeter Wemm 	int l;
511c2aa98e2SPeter Wemm 	int spaceleft = sizeof MsgBuf;
512c2aa98e2SPeter Wemm 
513c2aa98e2SPeter Wemm 	/* output the reply code */
514c2aa98e2SPeter Wemm 	if (isascii(fmt[0]) && isdigit(fmt[0]) &&
515c2aa98e2SPeter Wemm 	    isascii(fmt[1]) && isdigit(fmt[1]) &&
516c2aa98e2SPeter Wemm 	    isascii(fmt[2]) && isdigit(fmt[2]))
517c2aa98e2SPeter Wemm 	{
518c2aa98e2SPeter Wemm 		num = fmt;
519c2aa98e2SPeter Wemm 		fmt += 4;
520c2aa98e2SPeter Wemm 	}
521c2aa98e2SPeter Wemm 	if (num[3] == '-')
522c2aa98e2SPeter Wemm 		del = '-';
523c2aa98e2SPeter Wemm 	else
524c2aa98e2SPeter Wemm 		del = ' ';
525c2aa98e2SPeter Wemm 	(void) snprintf(eb, spaceleft, "%3.3s%c", num, del);
526c2aa98e2SPeter Wemm 	eb += 4;
527c2aa98e2SPeter Wemm 	spaceleft -= 4;
528c2aa98e2SPeter Wemm 
529c2aa98e2SPeter Wemm 	/* output the file name and line number */
530c2aa98e2SPeter Wemm 	if (FileName != NULL)
531c2aa98e2SPeter Wemm 	{
532c2aa98e2SPeter Wemm 		(void) snprintf(eb, spaceleft, "%s: line %d: ",
533c2aa98e2SPeter Wemm 			shortenstring(FileName, 83), LineNumber);
534c2aa98e2SPeter Wemm 		eb += (l = strlen(eb));
535c2aa98e2SPeter Wemm 		spaceleft -= l;
536c2aa98e2SPeter Wemm 	}
537c2aa98e2SPeter Wemm 
538c2aa98e2SPeter Wemm 	/* output the "to" person */
539c2aa98e2SPeter Wemm 	if (to != NULL && to[0] != '\0' &&
540c2aa98e2SPeter Wemm 	    strncmp(num, "551", 3) != 0 &&
541c2aa98e2SPeter Wemm 	    strncmp(num, "251", 3) != 0)
542c2aa98e2SPeter Wemm 	{
543c2aa98e2SPeter Wemm 		(void) snprintf(eb, spaceleft, "%s... ",
544c2aa98e2SPeter Wemm 			shortenstring(to, MAXSHORTSTR));
545c2aa98e2SPeter Wemm 		spaceleft -= strlen(eb);
546c2aa98e2SPeter Wemm 		while (*eb != '\0')
547c2aa98e2SPeter Wemm 			*eb++ &= 0177;
548c2aa98e2SPeter Wemm 	}
549c2aa98e2SPeter Wemm 
550c2aa98e2SPeter Wemm 	/* output the message */
551c2aa98e2SPeter Wemm 	(void) vsnprintf(eb, spaceleft, fmt, ap);
552c2aa98e2SPeter Wemm 	spaceleft -= strlen(eb);
553c2aa98e2SPeter Wemm 	while (*eb != '\0')
554c2aa98e2SPeter Wemm 		*eb++ &= 0177;
555c2aa98e2SPeter Wemm 
556c2aa98e2SPeter Wemm 	/* output the error code, if any */
557c2aa98e2SPeter Wemm 	if (eno != 0)
558c2aa98e2SPeter Wemm 		(void) snprintf(eb, spaceleft, ": %s", errstring(eno));
559c2aa98e2SPeter Wemm }
560c2aa98e2SPeter Wemm /*
561c2aa98e2SPeter Wemm **  BUFFER_ERRORS -- arrange to buffer future error messages
562c2aa98e2SPeter Wemm **
563c2aa98e2SPeter Wemm **	Parameters:
564c2aa98e2SPeter Wemm **		none
565c2aa98e2SPeter Wemm **
566c2aa98e2SPeter Wemm **	Returns:
567c2aa98e2SPeter Wemm **		none.
568c2aa98e2SPeter Wemm */
569c2aa98e2SPeter Wemm 
570c2aa98e2SPeter Wemm void
571c2aa98e2SPeter Wemm buffer_errors()
572c2aa98e2SPeter Wemm {
573c2aa98e2SPeter Wemm 	HeldMessageBuf[0] = '\0';
574c2aa98e2SPeter Wemm 	HoldErrs = TRUE;
575c2aa98e2SPeter Wemm }
576c2aa98e2SPeter Wemm /*
577c2aa98e2SPeter Wemm **  FLUSH_ERRORS -- flush the held error message buffer
578c2aa98e2SPeter Wemm **
579c2aa98e2SPeter Wemm **	Parameters:
580c2aa98e2SPeter Wemm **		print -- if set, print the message, otherwise just
581c2aa98e2SPeter Wemm **			delete it.
582c2aa98e2SPeter Wemm **
583c2aa98e2SPeter Wemm **	Returns:
584c2aa98e2SPeter Wemm **		none.
585c2aa98e2SPeter Wemm */
586c2aa98e2SPeter Wemm 
587c2aa98e2SPeter Wemm void
588c2aa98e2SPeter Wemm flush_errors(print)
589c2aa98e2SPeter Wemm 	bool print;
590c2aa98e2SPeter Wemm {
591c2aa98e2SPeter Wemm 	if (print && HeldMessageBuf[0] != '\0')
592c2aa98e2SPeter Wemm 		putoutmsg(HeldMessageBuf, FALSE, TRUE);
593c2aa98e2SPeter Wemm 	HeldMessageBuf[0] = '\0';
594c2aa98e2SPeter Wemm 	HoldErrs = FALSE;
595c2aa98e2SPeter Wemm }
596c2aa98e2SPeter Wemm /*
597c2aa98e2SPeter Wemm **  ERRSTRING -- return string description of error code
598c2aa98e2SPeter Wemm **
599c2aa98e2SPeter Wemm **	Parameters:
600c2aa98e2SPeter Wemm **		errnum -- the error number to translate
601c2aa98e2SPeter Wemm **
602c2aa98e2SPeter Wemm **	Returns:
603c2aa98e2SPeter Wemm **		A string description of errnum.
604c2aa98e2SPeter Wemm **
605c2aa98e2SPeter Wemm **	Side Effects:
606c2aa98e2SPeter Wemm **		none.
607c2aa98e2SPeter Wemm */
608c2aa98e2SPeter Wemm 
609c2aa98e2SPeter Wemm const char *
610c2aa98e2SPeter Wemm errstring(errnum)
611c2aa98e2SPeter Wemm 	int errnum;
612c2aa98e2SPeter Wemm {
613c2aa98e2SPeter Wemm 	char *dnsmsg;
614c2aa98e2SPeter Wemm 	char *bp;
615c2aa98e2SPeter Wemm 	static char buf[MAXLINE];
616c2aa98e2SPeter Wemm # if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
617c2aa98e2SPeter Wemm 	extern char *sys_errlist[];
618c2aa98e2SPeter Wemm 	extern int sys_nerr;
619c2aa98e2SPeter Wemm # endif
620c2aa98e2SPeter Wemm # if SMTP
621c2aa98e2SPeter Wemm 	extern char *SmtpPhase;
622c2aa98e2SPeter Wemm # endif /* SMTP */
623c2aa98e2SPeter Wemm 
624c2aa98e2SPeter Wemm 	/*
625c2aa98e2SPeter Wemm 	**  Handle special network error codes.
626c2aa98e2SPeter Wemm 	**
627c2aa98e2SPeter Wemm 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
628c2aa98e2SPeter Wemm 	*/
629c2aa98e2SPeter Wemm 
630c2aa98e2SPeter Wemm 	dnsmsg = NULL;
631c2aa98e2SPeter Wemm 	switch (errnum)
632c2aa98e2SPeter Wemm 	{
633c2aa98e2SPeter Wemm # if defined(DAEMON) && defined(ETIMEDOUT)
634c2aa98e2SPeter Wemm 	  case ETIMEDOUT:
635c2aa98e2SPeter Wemm 	  case ECONNRESET:
636c2aa98e2SPeter Wemm 		bp = buf;
637c2aa98e2SPeter Wemm #if HASSTRERROR
638c2aa98e2SPeter Wemm 		snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum));
639c2aa98e2SPeter Wemm #else
640c2aa98e2SPeter Wemm 		if (errnum >= 0 && errnum < sys_nerr)
641c2aa98e2SPeter Wemm 			snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]);
642c2aa98e2SPeter Wemm 		else
643c2aa98e2SPeter Wemm 			snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum);
644c2aa98e2SPeter Wemm #endif
645c2aa98e2SPeter Wemm 		bp += strlen(bp);
646c2aa98e2SPeter Wemm 		if (CurHostName != NULL)
647c2aa98e2SPeter Wemm 		{
648c2aa98e2SPeter Wemm 			if (errnum == ETIMEDOUT)
649c2aa98e2SPeter Wemm 			{
650c2aa98e2SPeter Wemm 				snprintf(bp, SPACELEFT(buf, bp), " with ");
651c2aa98e2SPeter Wemm 				bp += strlen(bp);
652c2aa98e2SPeter Wemm 			}
653c2aa98e2SPeter Wemm 			else
654c2aa98e2SPeter Wemm 			{
655c2aa98e2SPeter Wemm 				bp = buf;
656c2aa98e2SPeter Wemm 				snprintf(bp, SPACELEFT(buf, bp),
657c2aa98e2SPeter Wemm 					"Connection reset by ");
658c2aa98e2SPeter Wemm 				bp += strlen(bp);
659c2aa98e2SPeter Wemm 			}
660c2aa98e2SPeter Wemm 			snprintf(bp, SPACELEFT(buf, bp), "%s",
661c2aa98e2SPeter Wemm 				shortenstring(CurHostName, MAXSHORTSTR));
662c2aa98e2SPeter Wemm 			bp += strlen(buf);
663c2aa98e2SPeter Wemm 		}
664c2aa98e2SPeter Wemm 		if (SmtpPhase != NULL)
665c2aa98e2SPeter Wemm 		{
666c2aa98e2SPeter Wemm 			snprintf(bp, SPACELEFT(buf, bp), " during %s",
667c2aa98e2SPeter Wemm 				SmtpPhase);
668c2aa98e2SPeter Wemm 		}
669c2aa98e2SPeter Wemm 		return (buf);
670c2aa98e2SPeter Wemm 
671c2aa98e2SPeter Wemm 	  case EHOSTDOWN:
672c2aa98e2SPeter Wemm 		if (CurHostName == NULL)
673c2aa98e2SPeter Wemm 			break;
674c2aa98e2SPeter Wemm 		(void) snprintf(buf, sizeof buf, "Host %s is down",
675c2aa98e2SPeter Wemm 			shortenstring(CurHostName, MAXSHORTSTR));
676c2aa98e2SPeter Wemm 		return (buf);
677c2aa98e2SPeter Wemm 
678c2aa98e2SPeter Wemm 	  case ECONNREFUSED:
679c2aa98e2SPeter Wemm 		if (CurHostName == NULL)
680c2aa98e2SPeter Wemm 			break;
681c2aa98e2SPeter Wemm 		(void) snprintf(buf, sizeof buf, "Connection refused by %s",
682c2aa98e2SPeter Wemm 			shortenstring(CurHostName, MAXSHORTSTR));
683c2aa98e2SPeter Wemm 		return (buf);
684c2aa98e2SPeter Wemm # endif
685c2aa98e2SPeter Wemm 
686c2aa98e2SPeter Wemm # if NAMED_BIND
687c2aa98e2SPeter Wemm 	  case HOST_NOT_FOUND + E_DNSBASE:
688c2aa98e2SPeter Wemm 		dnsmsg = "host not found";
689c2aa98e2SPeter Wemm 		break;
690c2aa98e2SPeter Wemm 
691c2aa98e2SPeter Wemm 	  case TRY_AGAIN + E_DNSBASE:
692c2aa98e2SPeter Wemm 		dnsmsg = "host name lookup failure";
693c2aa98e2SPeter Wemm 		break;
694c2aa98e2SPeter Wemm 
695c2aa98e2SPeter Wemm 	  case NO_RECOVERY + E_DNSBASE:
696c2aa98e2SPeter Wemm 		dnsmsg = "non-recoverable error";
697c2aa98e2SPeter Wemm 		break;
698c2aa98e2SPeter Wemm 
699c2aa98e2SPeter Wemm 	  case NO_DATA + E_DNSBASE:
700c2aa98e2SPeter Wemm 		dnsmsg = "no data known";
701c2aa98e2SPeter Wemm 		break;
702c2aa98e2SPeter Wemm # endif
703c2aa98e2SPeter Wemm 
704c2aa98e2SPeter Wemm 	  case EPERM:
705c2aa98e2SPeter Wemm 		/* SunOS gives "Not owner" -- this is the POSIX message */
706c2aa98e2SPeter Wemm 		return "Operation not permitted";
707c2aa98e2SPeter Wemm 
708c2aa98e2SPeter Wemm 	/*
709c2aa98e2SPeter Wemm 	**  Error messages used internally in sendmail.
710c2aa98e2SPeter Wemm 	*/
711c2aa98e2SPeter Wemm 
712c2aa98e2SPeter Wemm 	  case E_SM_OPENTIMEOUT:
713c2aa98e2SPeter Wemm 		return "Timeout on file open";
714c2aa98e2SPeter Wemm 
715c2aa98e2SPeter Wemm 	  case E_SM_NOSLINK:
716c2aa98e2SPeter Wemm 		return "Symbolic links not allowed";
717c2aa98e2SPeter Wemm 
718c2aa98e2SPeter Wemm 	  case E_SM_NOHLINK:
719c2aa98e2SPeter Wemm 		return "Hard links not allowed";
720c2aa98e2SPeter Wemm 
721c2aa98e2SPeter Wemm 	  case E_SM_REGONLY:
722c2aa98e2SPeter Wemm 		return "Regular files only";
723c2aa98e2SPeter Wemm 
724c2aa98e2SPeter Wemm 	  case E_SM_ISEXEC:
725c2aa98e2SPeter Wemm 		return "Executable files not allowed";
726c2aa98e2SPeter Wemm 
727c2aa98e2SPeter Wemm 	  case E_SM_WWDIR:
728c2aa98e2SPeter Wemm 		return "World writable directory";
729c2aa98e2SPeter Wemm 
730c2aa98e2SPeter Wemm 	  case E_SM_GWDIR:
731c2aa98e2SPeter Wemm 		return "Group writable directory";
732c2aa98e2SPeter Wemm 
733c2aa98e2SPeter Wemm 	  case E_SM_FILECHANGE:
734c2aa98e2SPeter Wemm 		return "File changed after open";
735c2aa98e2SPeter Wemm 
736c2aa98e2SPeter Wemm 	  case E_SM_WWFILE:
737c2aa98e2SPeter Wemm 		return "World writable file";
738c2aa98e2SPeter Wemm 
739c2aa98e2SPeter Wemm 	  case E_SM_GWFILE:
740c2aa98e2SPeter Wemm 		return "Group writable file";
741c2aa98e2SPeter Wemm 	}
742c2aa98e2SPeter Wemm 
743c2aa98e2SPeter Wemm 	if (dnsmsg != NULL)
744c2aa98e2SPeter Wemm 	{
745c2aa98e2SPeter Wemm 		bp = buf;
746c2aa98e2SPeter Wemm 		strcpy(bp, "Name server: ");
747c2aa98e2SPeter Wemm 		bp += strlen(bp);
748c2aa98e2SPeter Wemm 		if (CurHostName != NULL)
749c2aa98e2SPeter Wemm 		{
750c2aa98e2SPeter Wemm 			snprintf(bp, SPACELEFT(buf, bp), "%s: ",
751c2aa98e2SPeter Wemm 				shortenstring(CurHostName, MAXSHORTSTR));
752c2aa98e2SPeter Wemm 			bp += strlen(bp);
753c2aa98e2SPeter Wemm 		}
754c2aa98e2SPeter Wemm 		snprintf(bp, SPACELEFT(buf, bp), "%s", dnsmsg);
755c2aa98e2SPeter Wemm 		return buf;
756c2aa98e2SPeter Wemm 	}
757c2aa98e2SPeter Wemm 
758c2aa98e2SPeter Wemm #if HASSTRERROR
759c2aa98e2SPeter Wemm 	return strerror(errnum);
760c2aa98e2SPeter Wemm #else
761c2aa98e2SPeter Wemm 	if (errnum > 0 && errnum < sys_nerr)
762c2aa98e2SPeter Wemm 		return (sys_errlist[errnum]);
763c2aa98e2SPeter Wemm 
764c2aa98e2SPeter Wemm 	(void) snprintf(buf, sizeof buf, "Error %d", errnum);
765c2aa98e2SPeter Wemm 	return (buf);
766c2aa98e2SPeter Wemm #endif
767c2aa98e2SPeter Wemm }
768