xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 42826)
122705Sdist /*
234921Sbostic  * Copyright (c) 1983 Eric P. Allman
333729Sbostic  * Copyright (c) 1988 Regents of the University of California.
433729Sbostic  * All rights reserved.
533729Sbostic  *
6*42826Sbostic  * %sccs.include.redist.c%
733729Sbostic  */
822705Sdist 
922705Sdist #ifndef lint
10*42826Sbostic static char sccsid[] = "@(#)err.c	5.10 (Berkeley) 06/01/90";
1133729Sbostic #endif /* not lint */
1222705Sdist 
133311Seric # include "sendmail.h"
1424943Seric # include <errno.h>
1525526Smiriam # include <netdb.h>
16295Seric 
17295Seric /*
181514Seric **  SYSERR -- Print error message.
19295Seric **
20295Seric **	Prints an error message via printf to the diagnostic
21295Seric **	output.  If LOG is defined, it logs it also.
22295Seric **
23295Seric **	Parameters:
24295Seric **		f -- the format string
25295Seric **		a, b, c, d, e -- parameters
26295Seric **
27295Seric **	Returns:
284084Seric **		none
297762Seric **		Through TopFrame if QuickAbort is set.
30295Seric **
31295Seric **	Side Effects:
321514Seric **		increments Errors.
331514Seric **		sets ExitStat.
34295Seric */
35295Seric 
364084Seric # ifdef lint
374084Seric int	sys_nerr;
384084Seric char	*sys_errlist[];
394084Seric # endif lint
4010147Seric char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
414084Seric 
42295Seric /*VARARGS1*/
43295Seric syserr(fmt, a, b, c, d, e)
44295Seric 	char *fmt;
45295Seric {
4616901Seric 	register char *p;
4716901Seric 	int olderrno = errno;
487957Seric 	extern char Arpa_PSyserr[];
497957Seric 	extern char Arpa_TSyserr[];
50295Seric 
517525Seric 	/* format and output the error message */
5216901Seric 	if (olderrno == 0)
537957Seric 		p = Arpa_PSyserr;
547957Seric 	else
557957Seric 		p = Arpa_TSyserr;
5616901Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
579389Seric 	puterrmsg(MsgBuf);
584063Seric 
59295Seric 	/* determine exit status if not already set */
60295Seric 	if (ExitStat == EX_OK)
61295Seric 	{
6216901Seric 		if (olderrno == 0)
63295Seric 			ExitStat = EX_SOFTWARE;
64295Seric 		else
651598Seric 			ExitStat = EX_OSERR;
66295Seric 	}
67295Seric 
68295Seric # ifdef LOG
697674Seric 	if (LogLevel > 0)
7025277Seric 		syslog(LOG_CRIT, "%s: SYSERR: %s",
7125277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
7225277Seric 			&MsgBuf[4]);
73295Seric # endif LOG
74295Seric 	errno = 0;
757762Seric 	if (QuickAbort)
767762Seric 		longjmp(TopFrame, 2);
77295Seric }
78295Seric /*
79295Seric **  USRERR -- Signal user error.
80295Seric **
81295Seric **	This is much like syserr except it is for user errors.
82295Seric **
83295Seric **	Parameters:
84295Seric **		fmt, a, b, c, d -- printf strings
85295Seric **
86295Seric **	Returns:
874084Seric **		none
887762Seric **		Through TopFrame if QuickAbort is set.
89295Seric **
90295Seric **	Side Effects:
911514Seric **		increments Errors.
92295Seric */
93295Seric 
94295Seric /*VARARGS1*/
95295Seric usrerr(fmt, a, b, c, d, e)
96295Seric 	char *fmt;
97295Seric {
98295Seric 	extern char SuprErrs;
994167Seric 	extern char Arpa_Usrerr[];
10016901Seric 	extern int errno;
101295Seric 
102295Seric 	if (SuprErrs)
1034084Seric 		return;
104295Seric 
10516901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
1069389Seric 	puterrmsg(MsgBuf);
1078239Seric 
1087762Seric 	if (QuickAbort)
1097762Seric 		longjmp(TopFrame, 1);
1104063Seric }
1114063Seric /*
1124063Seric **  MESSAGE -- print message (not necessarily an error)
1134063Seric **
1144063Seric **	Parameters:
1154063Seric **		num -- the default ARPANET error number (in ascii)
1164063Seric **		msg -- the message (printf fmt) -- if it begins
1174063Seric **			with a digit, this number overrides num.
1184063Seric **		a, b, c, d, e -- printf arguments
1194063Seric **
1204063Seric **	Returns:
1214063Seric **		none
1224063Seric **
1234063Seric **	Side Effects:
1244063Seric **		none.
1254063Seric */
1264063Seric 
1274084Seric /*VARARGS2*/
1284063Seric message(num, msg, a, b, c, d, e)
1294063Seric 	register char *num;
1304063Seric 	register char *msg;
1314063Seric {
1324711Seric 	errno = 0;
13316901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
1349108Seric 	putmsg(MsgBuf, FALSE);
1357613Seric }
1367613Seric /*
1378239Seric **  NMESSAGE -- print message (not necessarily an error)
1388239Seric **
1398239Seric **	Just like "message" except it never puts the to... tag on.
1408239Seric **
1418239Seric **	Parameters:
1428239Seric **		num -- the default ARPANET error number (in ascii)
1438239Seric **		msg -- the message (printf fmt) -- if it begins
14424943Seric **			with three digits, this number overrides num.
1458239Seric **		a, b, c, d, e -- printf arguments
1468239Seric **
1478239Seric **	Returns:
1488239Seric **		none
1498239Seric **
1508239Seric **	Side Effects:
1518239Seric **		none.
1528239Seric */
1538239Seric 
1548239Seric /*VARARGS2*/
1558239Seric nmessage(num, msg, a, b, c, d, e)
1568239Seric 	register char *num;
1578239Seric 	register char *msg;
1588239Seric {
1598239Seric 	errno = 0;
16016901Seric 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
1619108Seric 	putmsg(MsgBuf, FALSE);
1628239Seric }
1638239Seric /*
1647613Seric **  PUTMSG -- output error message to transcript and channel
1657613Seric **
1667613Seric **	Parameters:
1677613Seric **		msg -- message to output (in SMTP format).
1689108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
1699108Seric **			our output channel.
1707613Seric **
1717613Seric **	Returns:
1727613Seric **		none.
1737613Seric **
1747613Seric **	Side Effects:
1757613Seric **		Outputs msg to the transcript.
1767613Seric **		If appropriate, outputs it to the channel.
1777613Seric **		Deletes SMTP reply code number as appropriate.
1787613Seric */
1794711Seric 
1809108Seric putmsg(msg, holdmsg)
1817613Seric 	char *msg;
1829108Seric 	bool holdmsg;
1837613Seric {
18414900Seric 	/* output to transcript if serious */
18514900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
18614900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
1874711Seric 
1884711Seric 	/* output to channel if appropriate */
1899108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
1904063Seric 	{
1917275Seric 		(void) fflush(stdout);
1929277Seric 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
1937613Seric 			fprintf(OutChannel, "%s\r\n", msg);
1944711Seric 		else
1957613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
1964711Seric 		(void) fflush(OutChannel);
1974063Seric 	}
1989389Seric }
1999389Seric /*
2009389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2019389Seric **
2029389Seric **	Parameters:
2039389Seric **		msg -- the message to output.
2049389Seric **
2059389Seric **	Returns:
2069389Seric **		none.
2079389Seric **
2089389Seric **	Side Effects:
2099389Seric **		Sets the fatal error bit in the envelope as appropriate.
2109389Seric */
2118239Seric 
2129389Seric puterrmsg(msg)
2139389Seric 	char *msg;
2149389Seric {
2159389Seric 	/* output the message as usual */
2169389Seric 	putmsg(msg, HoldErrs);
2179389Seric 
2189389Seric 	/* signal the error */
2199389Seric 	Errors++;
2209389Seric 	if (msg[0] == '5')
2219336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2224711Seric }
2234711Seric /*
2244711Seric **  FMTMSG -- format a message into buffer.
2254711Seric **
2264711Seric **	Parameters:
2274711Seric **		eb -- error buffer to get result.
2284711Seric **		to -- the recipient tag for this message.
2294711Seric **		num -- arpanet error number.
23016901Seric **		en -- the error number to display.
2314711Seric **		fmt -- format of string.
2324711Seric **		a, b, c, d, e -- arguments.
2334711Seric **
2344711Seric **	Returns:
2354711Seric **		none.
2364711Seric **
2374711Seric **	Side Effects:
2384711Seric **		none.
2394711Seric */
2404063Seric 
24116901Seric /*VARARGS5*/
2424711Seric static
24316901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
2444711Seric 	register char *eb;
2454711Seric 	char *to;
2464711Seric 	char *num;
24716904Seric 	int eno;
2484711Seric 	char *fmt;
2494711Seric {
2504711Seric 	char del;
2514711Seric 
2524711Seric 	/* output the reply code */
25324943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2544577Seric 	{
2554711Seric 		num = fmt;
2564711Seric 		fmt += 4;
2574711Seric 	}
2584711Seric 	if (num[3] == '-')
2594711Seric 		del = '-';
2604711Seric 	else
2614711Seric 		del = ' ';
2624711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
2634711Seric 	eb += 4;
2644063Seric 
2659372Seric 	/* output the file name and line number */
2669372Seric 	if (FileName != NULL)
2679372Seric 	{
2689372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
2699372Seric 		eb += strlen(eb);
2709372Seric 	}
2719372Seric 
2724711Seric 	/* output the "to" person */
2734711Seric 	if (to != NULL && to[0] != '\0')
2744711Seric 	{
2754711Seric 		(void) sprintf(eb, "%s... ", to);
2765201Seric 		while (*eb != '\0')
2775201Seric 			*eb++ &= 0177;
2784711Seric 	}
2794711Seric 
2804711Seric 	/* output the message */
2814711Seric 	(void) sprintf(eb, fmt, a, b, c, d, e);
2825201Seric 	while (*eb != '\0')
2835201Seric 		*eb++ &= 0177;
2844711Seric 
2854711Seric 	/* output the error code, if any */
28616904Seric 	if (eno != 0)
2874711Seric 	{
28815136Seric 		extern char *errstring();
28915136Seric 
29016904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
2914711Seric 		eb += strlen(eb);
2924577Seric 	}
293295Seric }
29415136Seric /*
29515136Seric **  ERRSTRING -- return string description of error code
29615136Seric **
29715136Seric **	Parameters:
29815136Seric **		errno -- the error number to translate
29915136Seric **
30015136Seric **	Returns:
30115136Seric **		A string description of errno.
30215136Seric **
30315136Seric **	Side Effects:
30415136Seric **		none.
30515136Seric */
30615136Seric 
30715136Seric char *
30815136Seric errstring(errno)
30915136Seric 	int errno;
31015136Seric {
31115136Seric 	extern char *sys_errlist[];
31215136Seric 	extern int sys_nerr;
31324943Seric 	static char buf[100];
31424943Seric # ifdef SMTP
31524943Seric 	extern char *SmtpPhase;
31624943Seric # endif SMTP
31715136Seric 
31824943Seric # ifdef DAEMON
31924943Seric # ifdef VMUNIX
32024943Seric 	/*
32124943Seric 	**  Handle special network error codes.
32224943Seric 	**
32324943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
32424943Seric 	*/
32524943Seric 
32624943Seric 	switch (errno)
32724943Seric 	{
32824943Seric 	  case ETIMEDOUT:
32924943Seric 	  case ECONNRESET:
33024943Seric 		(void) strcpy(buf, sys_errlist[errno]);
33124943Seric 		if (SmtpPhase != NULL)
33224943Seric 		{
33324943Seric 			(void) strcat(buf, " during ");
33424943Seric 			(void) strcat(buf, SmtpPhase);
33524943Seric 		}
33625050Seric 		if (CurHostName != NULL)
33724943Seric 		{
33824943Seric 			(void) strcat(buf, " with ");
33925050Seric 			(void) strcat(buf, CurHostName);
34024943Seric 		}
34124943Seric 		return (buf);
34224943Seric 
34324943Seric 	  case EHOSTDOWN:
34425050Seric 		if (CurHostName == NULL)
34524943Seric 			break;
34625050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
34724943Seric 		return (buf);
34824943Seric 
34924943Seric 	  case ECONNREFUSED:
35025050Seric 		if (CurHostName == NULL)
35124943Seric 			break;
35225050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
35324943Seric 		return (buf);
35425526Smiriam 
35525526Smiriam 	  case (TRY_AGAIN+MAX_ERRNO):
35625526Smiriam 		(void) sprintf(buf, "Host Name Lookup Failure");
35725526Smiriam 		return (buf);
35824943Seric 	}
35924943Seric # endif VMUNIX
36024943Seric # endif DAEMON
36124943Seric 
36215136Seric 	if (errno > 0 && errno < sys_nerr)
36315136Seric 		return (sys_errlist[errno]);
36415136Seric 
36515136Seric 	(void) sprintf(buf, "Error %d", errno);
36615136Seric 	return (buf);
36715136Seric }
368