xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 69748)
122705Sdist /*
268839Seric  * Copyright (c) 1983, 1995 Eric P. Allman
362525Sbostic  * Copyright (c) 1988, 1993
462525Sbostic  *	The Regents of the University of California.  All rights reserved.
533729Sbostic  *
642826Sbostic  * %sccs.include.redist.c%
733729Sbostic  */
822705Sdist 
922705Sdist #ifndef lint
10*69748Seric static char sccsid[] = "@(#)err.c	8.34 (Berkeley) 05/28/95";
1133729Sbostic #endif /* not lint */
1222705Sdist 
133311Seric # include "sendmail.h"
1424943Seric # include <errno.h>
15295Seric 
16295Seric /*
171514Seric **  SYSERR -- Print error message.
18295Seric **
19295Seric **	Prints an error message via printf to the diagnostic
20295Seric **	output.  If LOG is defined, it logs it also.
21295Seric **
2258690Seric **	If the first character of the syserr message is `!' it will
2358690Seric **	log this as an ALERT message and exit immediately.  This can
2458690Seric **	leave queue files in an indeterminate state, so it should not
2558690Seric **	be used lightly.
2658690Seric **
27295Seric **	Parameters:
2867818Seric **		fmt -- the format string.  If it does not begin with
2967818Seric **			a three-digit SMTP reply code, either 554 or
3067818Seric **			451 is assumed depending on whether errno
3167818Seric **			is set.
3267818Seric **		(others) -- parameters
33295Seric **
34295Seric **	Returns:
354084Seric **		none
367762Seric **		Through TopFrame if QuickAbort is set.
37295Seric **
38295Seric **	Side Effects:
391514Seric **		increments Errors.
401514Seric **		sets ExitStat.
41295Seric */
42295Seric 
4368692Seric char	MsgBuf[BUFSIZ*2];		/* text of most recent message */
4468692Seric char	HeldMessageBuf[sizeof MsgBuf];	/* for held messages */
454084Seric 
46*69748Seric extern void	putoutmsg __P((char *, bool, bool));
47*69748Seric extern void	puterrmsg __P((char *));
48*69748Seric static void	fmtmsg __P((char *, const char *, const char *, int, const char *, va_list));
4946928Sbostic 
5066334Seric #if NAMED_BIND && !defined(NO_DATA)
5163969Seric # define NO_DATA	NO_ADDRESS
5263969Seric #endif
5363969Seric 
5458824Seric void
55295Seric /*VARARGS1*/
5657642Seric #ifdef __STDC__
5760094Seric syserr(const char *fmt, ...)
5857642Seric #else
5957642Seric syserr(fmt, va_alist)
6060094Seric 	const char *fmt;
6157642Seric 	va_dcl
6257642Seric #endif
63295Seric {
6416901Seric 	register char *p;
6516901Seric 	int olderrno = errno;
6658690Seric 	bool panic;
6766006Seric #ifdef LOG
6866006Seric 	char *uname;
6966006Seric 	struct passwd *pw;
7066006Seric 	char ubuf[80];
7166006Seric #endif
7256852Seric 	VA_LOCAL_DECL
73295Seric 
7458690Seric 	panic = *fmt == '!';
7558690Seric 	if (panic)
7658690Seric 		fmt++;
7758690Seric 
787525Seric 	/* format and output the error message */
7916901Seric 	if (olderrno == 0)
8058151Seric 		p = "554";
817957Seric 	else
8258151Seric 		p = "451";
8356852Seric 	VA_START(fmt);
8456852Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
8556852Seric 	VA_END;
869389Seric 	puterrmsg(MsgBuf);
874063Seric 
8867818Seric 	/* save this message for mailq printing */
8967818Seric 	if (!panic)
9067818Seric 	{
9167818Seric 		if (CurEnv->e_message != NULL)
9267818Seric 			free(CurEnv->e_message);
9367818Seric 		CurEnv->e_message = newstr(MsgBuf + 4);
9467818Seric 	}
9567818Seric 
96295Seric 	/* determine exit status if not already set */
97295Seric 	if (ExitStat == EX_OK)
98295Seric 	{
9916901Seric 		if (olderrno == 0)
100295Seric 			ExitStat = EX_SOFTWARE;
101295Seric 		else
1021598Seric 			ExitStat = EX_OSERR;
10366323Seric 		if (tTd(54, 1))
10466323Seric 			printf("syserr: ExitStat = %d\n", ExitStat);
105295Seric 	}
106295Seric 
107295Seric # ifdef LOG
10868693Seric 	pw = sm_getpwuid(getuid());
10966006Seric 	if (pw != NULL)
11066006Seric 		uname = pw->pw_name;
11166006Seric 	else
11266006Seric 	{
11366006Seric 		uname = ubuf;
11466006Seric 		sprintf(ubuf, "UID%d", getuid());
11566006Seric 	}
11666006Seric 
1177674Seric 	if (LogLevel > 0)
11866006Seric 		syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR(%s): %s",
11925277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
12066006Seric 			uname, &MsgBuf[4]);
12156795Seric # endif /* LOG */
12264725Seric 	if (olderrno == EMFILE)
12364731Seric 	{
12464725Seric 		printopenfds(TRUE);
12564731Seric 		mci_dump_all(TRUE);
12664731Seric 	}
12758690Seric 	if (panic)
12859156Seric 	{
12959156Seric #ifdef XLA
13059156Seric 		xla_all_end();
13159156Seric #endif
13258690Seric 		exit(EX_OSERR);
13359156Seric 	}
134295Seric 	errno = 0;
1357762Seric 	if (QuickAbort)
1367762Seric 		longjmp(TopFrame, 2);
137295Seric }
138295Seric /*
139295Seric **  USRERR -- Signal user error.
140295Seric **
141295Seric **	This is much like syserr except it is for user errors.
142295Seric **
143295Seric **	Parameters:
14467818Seric **		fmt -- the format string.  If it does not begin with
14567818Seric **			a three-digit SMTP reply code, 501 is assumed.
14667818Seric **		(others) -- printf strings
147295Seric **
148295Seric **	Returns:
1494084Seric **		none
1507762Seric **		Through TopFrame if QuickAbort is set.
151295Seric **
152295Seric **	Side Effects:
1531514Seric **		increments Errors.
154295Seric */
155295Seric 
156295Seric /*VARARGS1*/
15758824Seric void
15857642Seric #ifdef __STDC__
15960094Seric usrerr(const char *fmt, ...)
16057642Seric #else
16157642Seric usrerr(fmt, va_alist)
16260094Seric 	const char *fmt;
16357642Seric 	va_dcl
16457642Seric #endif
165295Seric {
16656852Seric 	VA_LOCAL_DECL
167295Seric 
168295Seric 	if (SuprErrs)
1694084Seric 		return;
170295Seric 
17156852Seric 	VA_START(fmt);
17258524Seric 	fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
17356852Seric 	VA_END;
1749389Seric 	puterrmsg(MsgBuf);
1758239Seric 
17667818Seric 	/* save this message for mailq printing */
17767818Seric 	if (MsgBuf[0] == '5' || (CurEnv->e_message == NULL && MsgBuf[0] == '4'))
17867818Seric 	{
17967818Seric 		if (CurEnv->e_message != NULL)
18067818Seric 			free(CurEnv->e_message);
18167818Seric 		CurEnv->e_message = newstr(MsgBuf + 4);
18267818Seric 	}
18367818Seric 
18451951Seric # ifdef LOG
18558020Seric 	if (LogLevel > 3 && LogUsrErrs)
18651951Seric 		syslog(LOG_NOTICE, "%s: %s",
18751951Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
18851951Seric 			&MsgBuf[4]);
18956795Seric # endif /* LOG */
19051951Seric 
1917762Seric 	if (QuickAbort)
1927762Seric 		longjmp(TopFrame, 1);
1934063Seric }
1944063Seric /*
1954063Seric **  MESSAGE -- print message (not necessarily an error)
1964063Seric **
1974063Seric **	Parameters:
19859581Seric **		msg -- the message (printf fmt) -- it can begin with
19959581Seric **			an SMTP reply code.  If not, 050 is assumed.
20067818Seric **		(others) -- printf arguments
2014063Seric **
2024063Seric **	Returns:
2034063Seric **		none
2044063Seric **
2054063Seric **	Side Effects:
2064063Seric **		none.
2074063Seric */
2084063Seric 
2094084Seric /*VARARGS2*/
21058826Seric void
21157642Seric #ifdef __STDC__
21260094Seric message(const char *msg, ...)
21357642Seric #else
21458151Seric message(msg, va_alist)
21560094Seric 	const char *msg;
21657642Seric 	va_dcl
21757642Seric #endif
2184063Seric {
21956852Seric 	VA_LOCAL_DECL
22056852Seric 
2214711Seric 	errno = 0;
22256852Seric 	VA_START(msg);
22358151Seric 	fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
22456852Seric 	VA_END;
22568692Seric 	putoutmsg(MsgBuf, FALSE, FALSE);
22667818Seric 
22767818Seric 	/* save this message for mailq printing */
22867818Seric 	if (MsgBuf[0] == '5' || (CurEnv->e_message == NULL && MsgBuf[0] == '4'))
22967818Seric 	{
23067818Seric 		if (CurEnv->e_message != NULL)
23167818Seric 			free(CurEnv->e_message);
23267818Seric 		CurEnv->e_message = newstr(MsgBuf + 4);
23367818Seric 	}
2347613Seric }
2357613Seric /*
2368239Seric **  NMESSAGE -- print message (not necessarily an error)
2378239Seric **
2388239Seric **	Just like "message" except it never puts the to... tag on.
2398239Seric **
2408239Seric **	Parameters:
2418239Seric **		msg -- the message (printf fmt) -- if it begins
24267818Seric **			with a three digit SMTP reply code, that is used,
24367818Seric **			otherwise 050 is assumed.
24467818Seric **		(others) -- printf arguments
2458239Seric **
2468239Seric **	Returns:
2478239Seric **		none
2488239Seric **
2498239Seric **	Side Effects:
2508239Seric **		none.
2518239Seric */
2528239Seric 
2538239Seric /*VARARGS2*/
25458826Seric void
25557642Seric #ifdef __STDC__
25660094Seric nmessage(const char *msg, ...)
25757642Seric #else
25858151Seric nmessage(msg, va_alist)
25960094Seric 	const char *msg;
26057642Seric 	va_dcl
26157642Seric #endif
2628239Seric {
26356852Seric 	VA_LOCAL_DECL
26456852Seric 
2658239Seric 	errno = 0;
26656852Seric 	VA_START(msg);
26758151Seric 	fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
26856852Seric 	VA_END;
26968692Seric 	putoutmsg(MsgBuf, FALSE, FALSE);
2708239Seric }
2718239Seric /*
27263753Seric **  PUTOUTMSG -- output error message to transcript and channel
2737613Seric **
2747613Seric **	Parameters:
2757613Seric **		msg -- message to output (in SMTP format).
2769108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
2779108Seric **			our output channel.
27868692Seric **		heldmsg -- if TRUE, this is a previously held message;
27968692Seric **			don't log it to the transcript file.
2807613Seric **
2817613Seric **	Returns:
2827613Seric **		none.
2837613Seric **
2847613Seric **	Side Effects:
2857613Seric **		Outputs msg to the transcript.
2867613Seric **		If appropriate, outputs it to the channel.
2877613Seric **		Deletes SMTP reply code number as appropriate.
2887613Seric */
2894711Seric 
290*69748Seric void
29168692Seric putoutmsg(msg, holdmsg, heldmsg)
2927613Seric 	char *msg;
2939108Seric 	bool holdmsg;
29468692Seric 	bool heldmsg;
2957613Seric {
29664249Seric 	/* display for debugging */
29764249Seric 	if (tTd(54, 8))
29868692Seric 		printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
29968692Seric 			heldmsg ? " (held)" : "");
30064249Seric 
30114900Seric 	/* output to transcript if serious */
30268692Seric 	if (!heldmsg && CurEnv->e_xfp != NULL && strchr("456", msg[0]) != NULL)
30314900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
3044711Seric 
3054711Seric 	/* output to channel if appropriate */
30668692Seric 	if (!Verbose && msg[0] == '0')
30760421Seric 		return;
30868692Seric 	if (holdmsg)
30968692Seric 	{
31068692Seric 		/* save for possible future display */
31168692Seric 		strcpy(HeldMessageBuf, msg);
31268692Seric 		return;
31368692Seric 	}
31460421Seric 
31563848Seric 	/* map warnings to something SMTP can handle */
31663848Seric 	if (msg[0] == '6')
31763848Seric 		msg[0] = '5';
31863848Seric 
31960421Seric 	(void) fflush(stdout);
32066017Seric 
32166017Seric 	/* if DisConnected, OutChannel now points to the transcript */
32266017Seric 	if (!DisConnected &&
32366017Seric 	    (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
32460421Seric 		fprintf(OutChannel, "%s\r\n", msg);
32560421Seric 	else
32660421Seric 		fprintf(OutChannel, "%s\n", &msg[4]);
32763753Seric 	if (TrafficLogFile != NULL)
32863753Seric 		fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(),
32965580Seric 			(OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
33060421Seric 	if (msg[3] == ' ')
33160421Seric 		(void) fflush(OutChannel);
33266017Seric 	if (!ferror(OutChannel) || DisConnected)
33360421Seric 		return;
33460421Seric 
33564499Seric 	/*
33664499Seric 	**  Error on output -- if reporting lost channel, just ignore it.
33764499Seric 	**  Also, ignore errors from QUIT response (221 message) -- some
33864499Seric 	**	rude servers don't read result.
33964499Seric 	*/
34064499Seric 
34164499Seric 	if (feof(InChannel) || ferror(InChannel) || strncmp(msg, "221", 3) == 0)
34260421Seric 		return;
34360421Seric 
34460421Seric 	/* can't call syserr, 'cause we are using MsgBuf */
34560421Seric 	HoldErrs = TRUE;
34660283Seric #ifdef LOG
34760421Seric 	if (LogLevel > 0)
34860421Seric 		syslog(LOG_CRIT,
34966864Seric 			"%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
35060421Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
35164123Seric 			CurHostName == NULL ? "NO-HOST" : CurHostName,
35266864Seric 			msg, errstring(errno));
35360283Seric #endif
3549389Seric }
3559389Seric /*
35663753Seric **  PUTERRMSG -- like putoutmsg, but does special processing for error messages
3579389Seric **
3589389Seric **	Parameters:
3599389Seric **		msg -- the message to output.
3609389Seric **
3619389Seric **	Returns:
3629389Seric **		none.
3639389Seric **
3649389Seric **	Side Effects:
3659389Seric **		Sets the fatal error bit in the envelope as appropriate.
3669389Seric */
3678239Seric 
368*69748Seric void
3699389Seric puterrmsg(msg)
3709389Seric 	char *msg;
3719389Seric {
37263848Seric 	char msgcode = msg[0];
37363848Seric 
3749389Seric 	/* output the message as usual */
37568692Seric 	putoutmsg(msg, HoldErrs, FALSE);
3769389Seric 
3779389Seric 	/* signal the error */
37864773Seric 	Errors++;
37963848Seric 	if (msgcode == '6')
38063848Seric 	{
38163848Seric 		/* notify the postmaster */
38263848Seric 		CurEnv->e_flags |= EF_PM_NOTIFY;
38363848Seric 	}
38467786Seric 	else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
38564773Seric 	{
38664773Seric 		/* mark long-term fatal errors */
38764773Seric 		CurEnv->e_flags |= EF_FATALERRS;
38864773Seric 	}
3894711Seric }
3904711Seric /*
3914711Seric **  FMTMSG -- format a message into buffer.
3924711Seric **
3934711Seric **	Parameters:
3944711Seric **		eb -- error buffer to get result.
3954711Seric **		to -- the recipient tag for this message.
3964711Seric **		num -- arpanet error number.
39716901Seric **		en -- the error number to display.
3984711Seric **		fmt -- format of string.
3994711Seric **		a, b, c, d, e -- arguments.
4004711Seric **
4014711Seric **	Returns:
4024711Seric **		none.
4034711Seric **
4044711Seric **	Side Effects:
4054711Seric **		none.
4064711Seric */
4074063Seric 
40846928Sbostic static void
40956852Seric fmtmsg(eb, to, num, eno, fmt, ap)
4104711Seric 	register char *eb;
411*69748Seric 	const char *to;
412*69748Seric 	const char *num;
41316904Seric 	int eno;
414*69748Seric 	const char *fmt;
41556852Seric 	va_list ap;
4164711Seric {
4174711Seric 	char del;
41859596Seric 	char *meb;
4194711Seric 
4204711Seric 	/* output the reply code */
42124943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
4224577Seric 	{
4234711Seric 		num = fmt;
4244711Seric 		fmt += 4;
4254711Seric 	}
4264711Seric 	if (num[3] == '-')
4274711Seric 		del = '-';
4284711Seric 	else
4294711Seric 		del = ' ';
4304711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
4314711Seric 	eb += 4;
4324063Seric 
4339372Seric 	/* output the file name and line number */
4349372Seric 	if (FileName != NULL)
4359372Seric 	{
4369372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
4379372Seric 		eb += strlen(eb);
4389372Seric 	}
4399372Seric 
4404711Seric 	/* output the "to" person */
4414711Seric 	if (to != NULL && to[0] != '\0')
4424711Seric 	{
44366297Seric 		(void) sprintf(eb, "%s... ", shortenstring(to, 203));
4445201Seric 		while (*eb != '\0')
4455201Seric 			*eb++ &= 0177;
4464711Seric 	}
4474711Seric 
44859596Seric 	meb = eb;
44959596Seric 
4504711Seric 	/* output the message */
45156852Seric 	(void) vsprintf(eb, fmt, ap);
4525201Seric 	while (*eb != '\0')
4535201Seric 		*eb++ &= 0177;
4544711Seric 
4554711Seric 	/* output the error code, if any */
45616904Seric 	if (eno != 0)
4574711Seric 	{
45816904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
4594711Seric 		eb += strlen(eb);
4604577Seric 	}
461295Seric }
46215136Seric /*
46368692Seric **  BUFFER_ERRORS -- arrange to buffer future error messages
46468692Seric **
46568692Seric **	Parameters:
46668692Seric **		none
46768692Seric **
46868692Seric **	Returns:
46968692Seric **		none.
47068692Seric */
47168692Seric 
47268692Seric void
47368692Seric buffer_errors()
47468692Seric {
47568692Seric 	HeldMessageBuf[0] = '\0';
47668692Seric 	HoldErrs = TRUE;
47768692Seric }
47868692Seric /*
47968692Seric **  FLUSH_ERRORS -- flush the held error message buffer
48068692Seric **
48168692Seric **	Parameters:
48268692Seric **		print -- if set, print the message, otherwise just
48368692Seric **			delete it.
48468692Seric **
48568692Seric **	Returns:
48668692Seric **		none.
48768692Seric */
48868692Seric 
48968692Seric void
49068692Seric flush_errors(print)
49168692Seric 	bool print;
49268692Seric {
49368692Seric 	if (print && HeldMessageBuf[0] != '\0')
49468692Seric 		putoutmsg(HeldMessageBuf, FALSE, TRUE);
49568692Seric 	HeldMessageBuf[0] = '\0';
49668692Seric 	HoldErrs = FALSE;
49768692Seric }
49868692Seric /*
49915136Seric **  ERRSTRING -- return string description of error code
50015136Seric **
50115136Seric **	Parameters:
50265751Seric **		errnum -- the error number to translate
50315136Seric **
50415136Seric **	Returns:
50565751Seric **		A string description of errnum.
50615136Seric **
50715136Seric **	Side Effects:
50815136Seric **		none.
50915136Seric */
51015136Seric 
51160089Seric const char *
51265751Seric errstring(errnum)
51365751Seric 	int errnum;
51415136Seric {
51565168Seric 	char *dnsmsg;
51663839Seric 	static char buf[MAXLINE];
51763839Seric # ifndef ERRLIST_PREDEFINED
51863839Seric 	extern char *sys_errlist[];
51915136Seric 	extern int sys_nerr;
52063839Seric # endif
52124943Seric # ifdef SMTP
52224943Seric 	extern char *SmtpPhase;
52356795Seric # endif /* SMTP */
52415136Seric 
52524943Seric 	/*
52624943Seric 	**  Handle special network error codes.
52724943Seric 	**
52824943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
52924943Seric 	*/
53024943Seric 
53165168Seric 	dnsmsg = NULL;
53265751Seric 	switch (errnum)
53324943Seric 	{
53465067Seric # if defined(DAEMON) && defined(ETIMEDOUT)
53524943Seric 	  case ETIMEDOUT:
53624943Seric 	  case ECONNRESET:
53765751Seric 		(void) strcpy(buf, sys_errlist[errnum]);
53824943Seric 		if (SmtpPhase != NULL)
53924943Seric 		{
54024943Seric 			(void) strcat(buf, " during ");
54124943Seric 			(void) strcat(buf, SmtpPhase);
54224943Seric 		}
54325050Seric 		if (CurHostName != NULL)
54424943Seric 		{
54524943Seric 			(void) strcat(buf, " with ");
54625050Seric 			(void) strcat(buf, CurHostName);
54724943Seric 		}
54824943Seric 		return (buf);
54924943Seric 
55024943Seric 	  case EHOSTDOWN:
55125050Seric 		if (CurHostName == NULL)
55224943Seric 			break;
55325050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
55424943Seric 		return (buf);
55524943Seric 
55624943Seric 	  case ECONNREFUSED:
55725050Seric 		if (CurHostName == NULL)
55824943Seric 			break;
55925050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
56024943Seric 		return (buf);
56165067Seric # endif
56225526Smiriam 
56363993Seric 	  case EOPENTIMEOUT:
56463993Seric 		return "Timeout on file open";
56563993Seric 
56666334Seric # if NAMED_BIND
56763993Seric 	  case HOST_NOT_FOUND + E_DNSBASE:
56865168Seric 		dnsmsg = "host not found";
56965168Seric 		break;
57058010Seric 
57163993Seric 	  case TRY_AGAIN + E_DNSBASE:
57265168Seric 		dnsmsg = "host name lookup failure";
57365168Seric 		break;
57458010Seric 
57563993Seric 	  case NO_RECOVERY + E_DNSBASE:
57665168Seric 		dnsmsg = "non-recoverable error";
57765168Seric 		break;
57858010Seric 
57963993Seric 	  case NO_DATA + E_DNSBASE:
58065168Seric 		dnsmsg = "no data known";
58165168Seric 		break;
58257736Seric # endif
58365067Seric 
58465067Seric 	  case EPERM:
58565067Seric 		/* SunOS gives "Not owner" -- this is the POSIX message */
58665067Seric 		return "Operation not permitted";
58724943Seric 	}
58824943Seric 
58965168Seric 	if (dnsmsg != NULL)
59065168Seric 	{
59165168Seric 		(void) strcpy(buf, "Name server: ");
59265168Seric 		if (CurHostName != NULL)
59365168Seric 		{
59465168Seric 			(void) strcat(buf, CurHostName);
59565168Seric 			(void) strcat(buf, ": ");
59665168Seric 		}
59765168Seric 		(void) strcat(buf, dnsmsg);
59865168Seric 		return buf;
59965168Seric 	}
60065168Seric 
60165751Seric 	if (errnum > 0 && errnum < sys_nerr)
60265751Seric 		return (sys_errlist[errnum]);
60315136Seric 
60465751Seric 	(void) sprintf(buf, "Error %d", errnum);
60515136Seric 	return (buf);
60615136Seric }
607