xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 25526)
122705Sdist /*
222705Sdist **  Sendmail
322705Sdist **  Copyright (c) 1983  Eric P. Allman
422705Sdist **  Berkeley, California
522705Sdist **
622705Sdist **  Copyright (c) 1983 Regents of the University of California.
722705Sdist **  All rights reserved.  The Berkeley software License Agreement
822705Sdist **  specifies the terms and conditions for redistribution.
922705Sdist */
1022705Sdist 
1122705Sdist #ifndef lint
12*25526Smiriam static char	SccsId[] = "@(#)err.c	5.7 (Berkeley) 11/22/85";
1322705Sdist #endif not lint
1422705Sdist 
153311Seric # include "sendmail.h"
1624943Seric # include <errno.h>
17*25526Smiriam # include <netdb.h>
18295Seric 
19295Seric /*
201514Seric **  SYSERR -- Print error message.
21295Seric **
22295Seric **	Prints an error message via printf to the diagnostic
23295Seric **	output.  If LOG is defined, it logs it also.
24295Seric **
25295Seric **	Parameters:
26295Seric **		f -- the format string
27295Seric **		a, b, c, d, e -- parameters
28295Seric **
29295Seric **	Returns:
304084Seric **		none
317762Seric **		Through TopFrame if QuickAbort is set.
32295Seric **
33295Seric **	Side Effects:
341514Seric **		increments Errors.
351514Seric **		sets ExitStat.
36295Seric */
37295Seric 
384084Seric # ifdef lint
394084Seric int	sys_nerr;
404084Seric char	*sys_errlist[];
414084Seric # endif lint
4210147Seric char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
434084Seric 
44295Seric /*VARARGS1*/
45295Seric syserr(fmt, a, b, c, d, e)
46295Seric 	char *fmt;
47295Seric {
4816901Seric 	register char *p;
4916901Seric 	int olderrno = errno;
507957Seric 	extern char Arpa_PSyserr[];
517957Seric 	extern char Arpa_TSyserr[];
52295Seric 
537525Seric 	/* format and output the error message */
5416901Seric 	if (olderrno == 0)
557957Seric 		p = Arpa_PSyserr;
567957Seric 	else
577957Seric 		p = Arpa_TSyserr;
5816901Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
599389Seric 	puterrmsg(MsgBuf);
604063Seric 
61295Seric 	/* determine exit status if not already set */
62295Seric 	if (ExitStat == EX_OK)
63295Seric 	{
6416901Seric 		if (olderrno == 0)
65295Seric 			ExitStat = EX_SOFTWARE;
66295Seric 		else
671598Seric 			ExitStat = EX_OSERR;
68295Seric 	}
69295Seric 
70295Seric # ifdef LOG
717674Seric 	if (LogLevel > 0)
7225277Seric 		syslog(LOG_CRIT, "%s: SYSERR: %s",
7325277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
7425277Seric 			&MsgBuf[4]);
75295Seric # endif LOG
76295Seric 	errno = 0;
777762Seric 	if (QuickAbort)
787762Seric 		longjmp(TopFrame, 2);
79295Seric }
80295Seric /*
81295Seric **  USRERR -- Signal user error.
82295Seric **
83295Seric **	This is much like syserr except it is for user errors.
84295Seric **
85295Seric **	Parameters:
86295Seric **		fmt, a, b, c, d -- printf strings
87295Seric **
88295Seric **	Returns:
894084Seric **		none
907762Seric **		Through TopFrame if QuickAbort is set.
91295Seric **
92295Seric **	Side Effects:
931514Seric **		increments Errors.
94295Seric */
95295Seric 
96295Seric /*VARARGS1*/
97295Seric usrerr(fmt, a, b, c, d, e)
98295Seric 	char *fmt;
99295Seric {
100295Seric 	extern char SuprErrs;
1014167Seric 	extern char Arpa_Usrerr[];
10216901Seric 	extern int errno;
103295Seric 
104295Seric 	if (SuprErrs)
1054084Seric 		return;
106295Seric 
10716901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
1089389Seric 	puterrmsg(MsgBuf);
1098239Seric 
1107762Seric 	if (QuickAbort)
1117762Seric 		longjmp(TopFrame, 1);
1124063Seric }
1134063Seric /*
1144063Seric **  MESSAGE -- print message (not necessarily an error)
1154063Seric **
1164063Seric **	Parameters:
1174063Seric **		num -- the default ARPANET error number (in ascii)
1184063Seric **		msg -- the message (printf fmt) -- if it begins
1194063Seric **			with a digit, this number overrides num.
1204063Seric **		a, b, c, d, e -- printf arguments
1214063Seric **
1224063Seric **	Returns:
1234063Seric **		none
1244063Seric **
1254063Seric **	Side Effects:
1264063Seric **		none.
1274063Seric */
1284063Seric 
1294084Seric /*VARARGS2*/
1304063Seric message(num, msg, a, b, c, d, e)
1314063Seric 	register char *num;
1324063Seric 	register char *msg;
1334063Seric {
1344711Seric 	errno = 0;
13516901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
1369108Seric 	putmsg(MsgBuf, FALSE);
1377613Seric }
1387613Seric /*
1398239Seric **  NMESSAGE -- print message (not necessarily an error)
1408239Seric **
1418239Seric **	Just like "message" except it never puts the to... tag on.
1428239Seric **
1438239Seric **	Parameters:
1448239Seric **		num -- the default ARPANET error number (in ascii)
1458239Seric **		msg -- the message (printf fmt) -- if it begins
14624943Seric **			with three digits, this number overrides num.
1478239Seric **		a, b, c, d, e -- printf arguments
1488239Seric **
1498239Seric **	Returns:
1508239Seric **		none
1518239Seric **
1528239Seric **	Side Effects:
1538239Seric **		none.
1548239Seric */
1558239Seric 
1568239Seric /*VARARGS2*/
1578239Seric nmessage(num, msg, a, b, c, d, e)
1588239Seric 	register char *num;
1598239Seric 	register char *msg;
1608239Seric {
1618239Seric 	errno = 0;
16216901Seric 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
1639108Seric 	putmsg(MsgBuf, FALSE);
1648239Seric }
1658239Seric /*
1667613Seric **  PUTMSG -- output error message to transcript and channel
1677613Seric **
1687613Seric **	Parameters:
1697613Seric **		msg -- message to output (in SMTP format).
1709108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
1719108Seric **			our output channel.
1727613Seric **
1737613Seric **	Returns:
1747613Seric **		none.
1757613Seric **
1767613Seric **	Side Effects:
1777613Seric **		Outputs msg to the transcript.
1787613Seric **		If appropriate, outputs it to the channel.
1797613Seric **		Deletes SMTP reply code number as appropriate.
1807613Seric */
1814711Seric 
1829108Seric putmsg(msg, holdmsg)
1837613Seric 	char *msg;
1849108Seric 	bool holdmsg;
1857613Seric {
18614900Seric 	/* output to transcript if serious */
18714900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
18814900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
1894711Seric 
1904711Seric 	/* output to channel if appropriate */
1919108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
1924063Seric 	{
1937275Seric 		(void) fflush(stdout);
1949277Seric 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
1957613Seric 			fprintf(OutChannel, "%s\r\n", msg);
1964711Seric 		else
1977613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
1984711Seric 		(void) fflush(OutChannel);
1994063Seric 	}
2009389Seric }
2019389Seric /*
2029389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2039389Seric **
2049389Seric **	Parameters:
2059389Seric **		msg -- the message to output.
2069389Seric **
2079389Seric **	Returns:
2089389Seric **		none.
2099389Seric **
2109389Seric **	Side Effects:
2119389Seric **		Sets the fatal error bit in the envelope as appropriate.
2129389Seric */
2138239Seric 
2149389Seric puterrmsg(msg)
2159389Seric 	char *msg;
2169389Seric {
2179389Seric 	/* output the message as usual */
2189389Seric 	putmsg(msg, HoldErrs);
2199389Seric 
2209389Seric 	/* signal the error */
2219389Seric 	Errors++;
2229389Seric 	if (msg[0] == '5')
2239336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2244711Seric }
2254711Seric /*
2264711Seric **  FMTMSG -- format a message into buffer.
2274711Seric **
2284711Seric **	Parameters:
2294711Seric **		eb -- error buffer to get result.
2304711Seric **		to -- the recipient tag for this message.
2314711Seric **		num -- arpanet error number.
23216901Seric **		en -- the error number to display.
2334711Seric **		fmt -- format of string.
2344711Seric **		a, b, c, d, e -- arguments.
2354711Seric **
2364711Seric **	Returns:
2374711Seric **		none.
2384711Seric **
2394711Seric **	Side Effects:
2404711Seric **		none.
2414711Seric */
2424063Seric 
24316901Seric /*VARARGS5*/
2444711Seric static
24516901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
2464711Seric 	register char *eb;
2474711Seric 	char *to;
2484711Seric 	char *num;
24916904Seric 	int eno;
2504711Seric 	char *fmt;
2514711Seric {
2524711Seric 	char del;
2534711Seric 
2544711Seric 	/* output the reply code */
25524943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2564577Seric 	{
2574711Seric 		num = fmt;
2584711Seric 		fmt += 4;
2594711Seric 	}
2604711Seric 	if (num[3] == '-')
2614711Seric 		del = '-';
2624711Seric 	else
2634711Seric 		del = ' ';
2644711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
2654711Seric 	eb += 4;
2664063Seric 
2679372Seric 	/* output the file name and line number */
2689372Seric 	if (FileName != NULL)
2699372Seric 	{
2709372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
2719372Seric 		eb += strlen(eb);
2729372Seric 	}
2739372Seric 
2744711Seric 	/* output the "to" person */
2754711Seric 	if (to != NULL && to[0] != '\0')
2764711Seric 	{
2774711Seric 		(void) sprintf(eb, "%s... ", to);
2785201Seric 		while (*eb != '\0')
2795201Seric 			*eb++ &= 0177;
2804711Seric 	}
2814711Seric 
2824711Seric 	/* output the message */
2834711Seric 	(void) sprintf(eb, fmt, a, b, c, d, e);
2845201Seric 	while (*eb != '\0')
2855201Seric 		*eb++ &= 0177;
2864711Seric 
2874711Seric 	/* output the error code, if any */
28816904Seric 	if (eno != 0)
2894711Seric 	{
29015136Seric 		extern char *errstring();
29115136Seric 
29216904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
2934711Seric 		eb += strlen(eb);
2944577Seric 	}
295295Seric }
29615136Seric /*
29715136Seric **  ERRSTRING -- return string description of error code
29815136Seric **
29915136Seric **	Parameters:
30015136Seric **		errno -- the error number to translate
30115136Seric **
30215136Seric **	Returns:
30315136Seric **		A string description of errno.
30415136Seric **
30515136Seric **	Side Effects:
30615136Seric **		none.
30715136Seric */
30815136Seric 
30915136Seric char *
31015136Seric errstring(errno)
31115136Seric 	int errno;
31215136Seric {
31315136Seric 	extern char *sys_errlist[];
31415136Seric 	extern int sys_nerr;
31524943Seric 	static char buf[100];
31624943Seric # ifdef SMTP
31724943Seric 	extern char *SmtpPhase;
31824943Seric # endif SMTP
31915136Seric 
32024943Seric # ifdef DAEMON
32124943Seric # ifdef VMUNIX
32224943Seric 	/*
32324943Seric 	**  Handle special network error codes.
32424943Seric 	**
32524943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
32624943Seric 	*/
32724943Seric 
32824943Seric 	switch (errno)
32924943Seric 	{
33024943Seric 	  case ETIMEDOUT:
33124943Seric 	  case ECONNRESET:
33224943Seric 		(void) strcpy(buf, sys_errlist[errno]);
33324943Seric 		if (SmtpPhase != NULL)
33424943Seric 		{
33524943Seric 			(void) strcat(buf, " during ");
33624943Seric 			(void) strcat(buf, SmtpPhase);
33724943Seric 		}
33825050Seric 		if (CurHostName != NULL)
33924943Seric 		{
34024943Seric 			(void) strcat(buf, " with ");
34125050Seric 			(void) strcat(buf, CurHostName);
34224943Seric 		}
34324943Seric 		return (buf);
34424943Seric 
34524943Seric 	  case EHOSTDOWN:
34625050Seric 		if (CurHostName == NULL)
34724943Seric 			break;
34825050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
34924943Seric 		return (buf);
35024943Seric 
35124943Seric 	  case ECONNREFUSED:
35225050Seric 		if (CurHostName == NULL)
35324943Seric 			break;
35425050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
35524943Seric 		return (buf);
356*25526Smiriam 
357*25526Smiriam 	  case (TRY_AGAIN+MAX_ERRNO):
358*25526Smiriam 		(void) sprintf(buf, "Host Name Lookup Failure");
359*25526Smiriam 		return (buf);
36024943Seric 	}
36124943Seric # endif VMUNIX
36224943Seric # endif DAEMON
36324943Seric 
36415136Seric 	if (errno > 0 && errno < sys_nerr)
36515136Seric 		return (sys_errlist[errno]);
36615136Seric 
36715136Seric 	(void) sprintf(buf, "Error %d", errno);
36815136Seric 	return (buf);
36915136Seric }
370