xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 57232)
122705Sdist /*
234921Sbostic  * Copyright (c) 1983 Eric P. Allman
333729Sbostic  * Copyright (c) 1988 Regents of the University of California.
433729Sbostic  * All rights reserved.
533729Sbostic  *
642826Sbostic  * %sccs.include.redist.c%
733729Sbostic  */
822705Sdist 
922705Sdist #ifndef lint
10*57232Seric static char sccsid[] = "@(#)err.c	5.17 (Berkeley) 12/20/92";
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 
4246928Sbostic static void fmtmsg();
4346928Sbostic 
44295Seric /*VARARGS1*/
4556852Seric syserr(fmt VA_ARG_FORMAL)
46295Seric 	char *fmt;
4756852Seric 	VA_ARG_DECL
48295Seric {
4916901Seric 	register char *p;
5016901Seric 	int olderrno = errno;
5156852Seric 	VA_LOCAL_DECL
527957Seric 	extern char Arpa_PSyserr[];
537957Seric 	extern char Arpa_TSyserr[];
54295Seric 
557525Seric 	/* format and output the error message */
5616901Seric 	if (olderrno == 0)
577957Seric 		p = Arpa_PSyserr;
587957Seric 	else
597957Seric 		p = Arpa_TSyserr;
6056852Seric 	VA_START(fmt);
6156852Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
6256852Seric 	VA_END;
639389Seric 	puterrmsg(MsgBuf);
644063Seric 
65295Seric 	/* determine exit status if not already set */
66295Seric 	if (ExitStat == EX_OK)
67295Seric 	{
6816901Seric 		if (olderrno == 0)
69295Seric 			ExitStat = EX_SOFTWARE;
70295Seric 		else
711598Seric 			ExitStat = EX_OSERR;
72295Seric 	}
73295Seric 
74295Seric # ifdef LOG
757674Seric 	if (LogLevel > 0)
7625277Seric 		syslog(LOG_CRIT, "%s: SYSERR: %s",
7725277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
7825277Seric 			&MsgBuf[4]);
7956795Seric # endif /* LOG */
80295Seric 	errno = 0;
817762Seric 	if (QuickAbort)
827762Seric 		longjmp(TopFrame, 2);
83295Seric }
84295Seric /*
85295Seric **  USRERR -- Signal user error.
86295Seric **
87295Seric **	This is much like syserr except it is for user errors.
88295Seric **
89295Seric **	Parameters:
90295Seric **		fmt, a, b, c, d -- printf strings
91295Seric **
92295Seric **	Returns:
934084Seric **		none
947762Seric **		Through TopFrame if QuickAbort is set.
95295Seric **
96295Seric **	Side Effects:
971514Seric **		increments Errors.
98295Seric */
99295Seric 
100295Seric /*VARARGS1*/
10156852Seric usrerr(fmt VA_ARG_FORMAL)
102295Seric 	char *fmt;
10356852Seric 	VA_ARG_DECL
104295Seric {
10556852Seric 	VA_LOCAL_DECL
106295Seric 	extern char SuprErrs;
1074167Seric 	extern char Arpa_Usrerr[];
10816901Seric 	extern int errno;
109295Seric 
110295Seric 	if (SuprErrs)
1114084Seric 		return;
112295Seric 
11356852Seric 	VA_START(fmt);
11456852Seric 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, ap);
11556852Seric 	VA_END;
1169389Seric 	puterrmsg(MsgBuf);
1178239Seric 
11851951Seric # ifdef LOG
11951951Seric 	if (LogLevel > 1 && LogUsrErrs)
12051951Seric 		syslog(LOG_NOTICE, "%s: %s",
12151951Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
12251951Seric 			&MsgBuf[4]);
12356795Seric # endif /* LOG */
12451951Seric 
1257762Seric 	if (QuickAbort)
1267762Seric 		longjmp(TopFrame, 1);
1274063Seric }
1284063Seric /*
1294063Seric **  MESSAGE -- print message (not necessarily an error)
1304063Seric **
1314063Seric **	Parameters:
1324063Seric **		num -- the default ARPANET error number (in ascii)
1334063Seric **		msg -- the message (printf fmt) -- if it begins
1344063Seric **			with a digit, this number overrides num.
1354063Seric **		a, b, c, d, e -- printf arguments
1364063Seric **
1374063Seric **	Returns:
1384063Seric **		none
1394063Seric **
1404063Seric **	Side Effects:
1414063Seric **		none.
1424063Seric */
1434063Seric 
1444084Seric /*VARARGS2*/
14556852Seric message(num, msg VA_ARG_FORMAL)
14656852Seric 	char *num;
14756852Seric 	char *msg;
14856852Seric 	VA_ARG_DECL
1494063Seric {
15056852Seric 	VA_LOCAL_DECL
15156852Seric 
1524711Seric 	errno = 0;
15356852Seric 	VA_START(msg);
15456852Seric 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, ap);
15556852Seric 	VA_END;
1569108Seric 	putmsg(MsgBuf, FALSE);
1577613Seric }
1587613Seric /*
1598239Seric **  NMESSAGE -- print message (not necessarily an error)
1608239Seric **
1618239Seric **	Just like "message" except it never puts the to... tag on.
1628239Seric **
1638239Seric **	Parameters:
1648239Seric **		num -- the default ARPANET error number (in ascii)
1658239Seric **		msg -- the message (printf fmt) -- if it begins
16624943Seric **			with three digits, this number overrides num.
1678239Seric **		a, b, c, d, e -- printf arguments
1688239Seric **
1698239Seric **	Returns:
1708239Seric **		none
1718239Seric **
1728239Seric **	Side Effects:
1738239Seric **		none.
1748239Seric */
1758239Seric 
1768239Seric /*VARARGS2*/
17756852Seric nmessage(num, msg VA_ARG_FORMAL)
17856852Seric 	char *num;
17956852Seric 	char *msg;
18056852Seric 	VA_ARG_DECL
1818239Seric {
18256852Seric 	VA_LOCAL_DECL
18356852Seric 
1848239Seric 	errno = 0;
18556852Seric 	VA_START(msg);
18656852Seric 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, ap);
18756852Seric 	VA_END;
1889108Seric 	putmsg(MsgBuf, FALSE);
1898239Seric }
1908239Seric /*
1917613Seric **  PUTMSG -- output error message to transcript and channel
1927613Seric **
1937613Seric **	Parameters:
1947613Seric **		msg -- message to output (in SMTP format).
1959108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
1969108Seric **			our output channel.
1977613Seric **
1987613Seric **	Returns:
1997613Seric **		none.
2007613Seric **
2017613Seric **	Side Effects:
2027613Seric **		Outputs msg to the transcript.
2037613Seric **		If appropriate, outputs it to the channel.
2047613Seric **		Deletes SMTP reply code number as appropriate.
2057613Seric */
2064711Seric 
2079108Seric putmsg(msg, holdmsg)
2087613Seric 	char *msg;
2099108Seric 	bool holdmsg;
2107613Seric {
21114900Seric 	/* output to transcript if serious */
21214900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
21314900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
2144711Seric 
2154711Seric 	/* output to channel if appropriate */
2169108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
2174063Seric 	{
2187275Seric 		(void) fflush(stdout);
21952220Seric 		if (OpMode == MD_SMTP)
2207613Seric 			fprintf(OutChannel, "%s\r\n", msg);
2214711Seric 		else
2227613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
2234711Seric 		(void) fflush(OutChannel);
2244063Seric 	}
2259389Seric }
2269389Seric /*
2279389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2289389Seric **
2299389Seric **	Parameters:
2309389Seric **		msg -- the message to output.
2319389Seric **
2329389Seric **	Returns:
2339389Seric **		none.
2349389Seric **
2359389Seric **	Side Effects:
2369389Seric **		Sets the fatal error bit in the envelope as appropriate.
2379389Seric */
2388239Seric 
2399389Seric puterrmsg(msg)
2409389Seric 	char *msg;
2419389Seric {
2429389Seric 	/* output the message as usual */
2439389Seric 	putmsg(msg, HoldErrs);
2449389Seric 
2459389Seric 	/* signal the error */
2469389Seric 	Errors++;
2479389Seric 	if (msg[0] == '5')
2489336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2494711Seric }
2504711Seric /*
2514711Seric **  FMTMSG -- format a message into buffer.
2524711Seric **
2534711Seric **	Parameters:
2544711Seric **		eb -- error buffer to get result.
2554711Seric **		to -- the recipient tag for this message.
2564711Seric **		num -- arpanet error number.
25716901Seric **		en -- the error number to display.
2584711Seric **		fmt -- format of string.
2594711Seric **		a, b, c, d, e -- arguments.
2604711Seric **
2614711Seric **	Returns:
2624711Seric **		none.
2634711Seric **
2644711Seric **	Side Effects:
2654711Seric **		none.
2664711Seric */
2674063Seric 
26846928Sbostic static void
26956852Seric fmtmsg(eb, to, num, eno, fmt, ap)
2704711Seric 	register char *eb;
2714711Seric 	char *to;
2724711Seric 	char *num;
27316904Seric 	int eno;
2744711Seric 	char *fmt;
27556852Seric 	va_list ap;
2764711Seric {
2774711Seric 	char del;
2784711Seric 
2794711Seric 	/* output the reply code */
28024943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2814577Seric 	{
2824711Seric 		num = fmt;
2834711Seric 		fmt += 4;
2844711Seric 	}
2854711Seric 	if (num[3] == '-')
2864711Seric 		del = '-';
2874711Seric 	else
2884711Seric 		del = ' ';
2894711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
2904711Seric 	eb += 4;
2914063Seric 
2929372Seric 	/* output the file name and line number */
2939372Seric 	if (FileName != NULL)
2949372Seric 	{
2959372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
2969372Seric 		eb += strlen(eb);
2979372Seric 	}
2989372Seric 
2994711Seric 	/* output the "to" person */
3004711Seric 	if (to != NULL && to[0] != '\0')
3014711Seric 	{
3024711Seric 		(void) sprintf(eb, "%s... ", to);
3035201Seric 		while (*eb != '\0')
3045201Seric 			*eb++ &= 0177;
3054711Seric 	}
3064711Seric 
3074711Seric 	/* output the message */
30856852Seric 	(void) vsprintf(eb, fmt, ap);
3095201Seric 	while (*eb != '\0')
3105201Seric 		*eb++ &= 0177;
3114711Seric 
3124711Seric 	/* output the error code, if any */
31316904Seric 	if (eno != 0)
3144711Seric 	{
31515136Seric 		extern char *errstring();
31615136Seric 
31716904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
3184711Seric 		eb += strlen(eb);
3194577Seric 	}
320295Seric }
32115136Seric /*
32215136Seric **  ERRSTRING -- return string description of error code
32315136Seric **
32415136Seric **	Parameters:
32515136Seric **		errno -- the error number to translate
32615136Seric **
32715136Seric **	Returns:
32815136Seric **		A string description of errno.
32915136Seric **
33015136Seric **	Side Effects:
33115136Seric **		none.
33215136Seric */
33315136Seric 
33415136Seric char *
33515136Seric errstring(errno)
33615136Seric 	int errno;
33715136Seric {
33815136Seric 	extern char *sys_errlist[];
33915136Seric 	extern int sys_nerr;
340*57232Seric 	static char buf[MAXLINE];
34124943Seric # ifdef SMTP
34224943Seric 	extern char *SmtpPhase;
34356795Seric # endif /* SMTP */
34415136Seric 
34524943Seric # ifdef DAEMON
34652107Seric # ifdef ETIMEDOUT
34724943Seric 	/*
34824943Seric 	**  Handle special network error codes.
34924943Seric 	**
35024943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
35124943Seric 	*/
35224943Seric 
35324943Seric 	switch (errno)
35424943Seric 	{
35524943Seric 	  case ETIMEDOUT:
35624943Seric 	  case ECONNRESET:
35724943Seric 		(void) strcpy(buf, sys_errlist[errno]);
35824943Seric 		if (SmtpPhase != NULL)
35924943Seric 		{
36024943Seric 			(void) strcat(buf, " during ");
36124943Seric 			(void) strcat(buf, SmtpPhase);
36224943Seric 		}
36325050Seric 		if (CurHostName != NULL)
36424943Seric 		{
36524943Seric 			(void) strcat(buf, " with ");
36625050Seric 			(void) strcat(buf, CurHostName);
36724943Seric 		}
36824943Seric 		return (buf);
36924943Seric 
37024943Seric 	  case EHOSTDOWN:
37125050Seric 		if (CurHostName == NULL)
37224943Seric 			break;
37325050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
37424943Seric 		return (buf);
37524943Seric 
37624943Seric 	  case ECONNREFUSED:
37725050Seric 		if (CurHostName == NULL)
37824943Seric 			break;
37925050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
38024943Seric 		return (buf);
38125526Smiriam 
38225526Smiriam 	  case (TRY_AGAIN+MAX_ERRNO):
38325526Smiriam 		(void) sprintf(buf, "Host Name Lookup Failure");
38425526Smiriam 		return (buf);
38524943Seric 	}
38652107Seric # endif
38752107Seric # endif
38824943Seric 
38915136Seric 	if (errno > 0 && errno < sys_nerr)
39015136Seric 		return (sys_errlist[errno]);
39115136Seric 
39215136Seric 	(void) sprintf(buf, "Error %d", errno);
39315136Seric 	return (buf);
39415136Seric }
395