xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 25277)
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*25277Seric static char	SccsId[] = "@(#)err.c	5.6 (Berkeley) 10/24/85";
1322705Sdist #endif not lint
1422705Sdist 
153311Seric # include "sendmail.h"
1624943Seric # include <errno.h>
17295Seric 
18295Seric /*
191514Seric **  SYSERR -- Print error message.
20295Seric **
21295Seric **	Prints an error message via printf to the diagnostic
22295Seric **	output.  If LOG is defined, it logs it also.
23295Seric **
24295Seric **	Parameters:
25295Seric **		f -- the format string
26295Seric **		a, b, c, d, e -- parameters
27295Seric **
28295Seric **	Returns:
294084Seric **		none
307762Seric **		Through TopFrame if QuickAbort is set.
31295Seric **
32295Seric **	Side Effects:
331514Seric **		increments Errors.
341514Seric **		sets ExitStat.
35295Seric */
36295Seric 
374084Seric # ifdef lint
384084Seric int	sys_nerr;
394084Seric char	*sys_errlist[];
404084Seric # endif lint
4110147Seric char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
424084Seric 
43295Seric /*VARARGS1*/
44295Seric syserr(fmt, a, b, c, d, e)
45295Seric 	char *fmt;
46295Seric {
4716901Seric 	register char *p;
4816901Seric 	int olderrno = errno;
497957Seric 	extern char Arpa_PSyserr[];
507957Seric 	extern char Arpa_TSyserr[];
51295Seric 
527525Seric 	/* format and output the error message */
5316901Seric 	if (olderrno == 0)
547957Seric 		p = Arpa_PSyserr;
557957Seric 	else
567957Seric 		p = Arpa_TSyserr;
5716901Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
589389Seric 	puterrmsg(MsgBuf);
594063Seric 
60295Seric 	/* determine exit status if not already set */
61295Seric 	if (ExitStat == EX_OK)
62295Seric 	{
6316901Seric 		if (olderrno == 0)
64295Seric 			ExitStat = EX_SOFTWARE;
65295Seric 		else
661598Seric 			ExitStat = EX_OSERR;
67295Seric 	}
68295Seric 
69295Seric # ifdef LOG
707674Seric 	if (LogLevel > 0)
71*25277Seric 		syslog(LOG_CRIT, "%s: SYSERR: %s",
72*25277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
73*25277Seric 			&MsgBuf[4]);
74295Seric # endif LOG
75295Seric 	errno = 0;
767762Seric 	if (QuickAbort)
777762Seric 		longjmp(TopFrame, 2);
78295Seric }
79295Seric /*
80295Seric **  USRERR -- Signal user error.
81295Seric **
82295Seric **	This is much like syserr except it is for user errors.
83295Seric **
84295Seric **	Parameters:
85295Seric **		fmt, a, b, c, d -- printf strings
86295Seric **
87295Seric **	Returns:
884084Seric **		none
897762Seric **		Through TopFrame if QuickAbort is set.
90295Seric **
91295Seric **	Side Effects:
921514Seric **		increments Errors.
93295Seric */
94295Seric 
95295Seric /*VARARGS1*/
96295Seric usrerr(fmt, a, b, c, d, e)
97295Seric 	char *fmt;
98295Seric {
99295Seric 	extern char SuprErrs;
1004167Seric 	extern char Arpa_Usrerr[];
10116901Seric 	extern int errno;
102295Seric 
103295Seric 	if (SuprErrs)
1044084Seric 		return;
105295Seric 
10616901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
1079389Seric 	puterrmsg(MsgBuf);
1088239Seric 
1097762Seric 	if (QuickAbort)
1107762Seric 		longjmp(TopFrame, 1);
1114063Seric }
1124063Seric /*
1134063Seric **  MESSAGE -- print message (not necessarily an error)
1144063Seric **
1154063Seric **	Parameters:
1164063Seric **		num -- the default ARPANET error number (in ascii)
1174063Seric **		msg -- the message (printf fmt) -- if it begins
1184063Seric **			with a digit, this number overrides num.
1194063Seric **		a, b, c, d, e -- printf arguments
1204063Seric **
1214063Seric **	Returns:
1224063Seric **		none
1234063Seric **
1244063Seric **	Side Effects:
1254063Seric **		none.
1264063Seric */
1274063Seric 
1284084Seric /*VARARGS2*/
1294063Seric message(num, msg, a, b, c, d, e)
1304063Seric 	register char *num;
1314063Seric 	register char *msg;
1324063Seric {
1334711Seric 	errno = 0;
13416901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
1359108Seric 	putmsg(MsgBuf, FALSE);
1367613Seric }
1377613Seric /*
1388239Seric **  NMESSAGE -- print message (not necessarily an error)
1398239Seric **
1408239Seric **	Just like "message" except it never puts the to... tag on.
1418239Seric **
1428239Seric **	Parameters:
1438239Seric **		num -- the default ARPANET error number (in ascii)
1448239Seric **		msg -- the message (printf fmt) -- if it begins
14524943Seric **			with three digits, this number overrides num.
1468239Seric **		a, b, c, d, e -- printf arguments
1478239Seric **
1488239Seric **	Returns:
1498239Seric **		none
1508239Seric **
1518239Seric **	Side Effects:
1528239Seric **		none.
1538239Seric */
1548239Seric 
1558239Seric /*VARARGS2*/
1568239Seric nmessage(num, msg, a, b, c, d, e)
1578239Seric 	register char *num;
1588239Seric 	register char *msg;
1598239Seric {
1608239Seric 	errno = 0;
16116901Seric 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
1629108Seric 	putmsg(MsgBuf, FALSE);
1638239Seric }
1648239Seric /*
1657613Seric **  PUTMSG -- output error message to transcript and channel
1667613Seric **
1677613Seric **	Parameters:
1687613Seric **		msg -- message to output (in SMTP format).
1699108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
1709108Seric **			our output channel.
1717613Seric **
1727613Seric **	Returns:
1737613Seric **		none.
1747613Seric **
1757613Seric **	Side Effects:
1767613Seric **		Outputs msg to the transcript.
1777613Seric **		If appropriate, outputs it to the channel.
1787613Seric **		Deletes SMTP reply code number as appropriate.
1797613Seric */
1804711Seric 
1819108Seric putmsg(msg, holdmsg)
1827613Seric 	char *msg;
1839108Seric 	bool holdmsg;
1847613Seric {
18514900Seric 	/* output to transcript if serious */
18614900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
18714900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
1884711Seric 
1894711Seric 	/* output to channel if appropriate */
1909108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
1914063Seric 	{
1927275Seric 		(void) fflush(stdout);
1939277Seric 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
1947613Seric 			fprintf(OutChannel, "%s\r\n", msg);
1954711Seric 		else
1967613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
1974711Seric 		(void) fflush(OutChannel);
1984063Seric 	}
1999389Seric }
2009389Seric /*
2019389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2029389Seric **
2039389Seric **	Parameters:
2049389Seric **		msg -- the message to output.
2059389Seric **
2069389Seric **	Returns:
2079389Seric **		none.
2089389Seric **
2099389Seric **	Side Effects:
2109389Seric **		Sets the fatal error bit in the envelope as appropriate.
2119389Seric */
2128239Seric 
2139389Seric puterrmsg(msg)
2149389Seric 	char *msg;
2159389Seric {
2169389Seric 	/* output the message as usual */
2179389Seric 	putmsg(msg, HoldErrs);
2189389Seric 
2199389Seric 	/* signal the error */
2209389Seric 	Errors++;
2219389Seric 	if (msg[0] == '5')
2229336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2234711Seric }
2244711Seric /*
2254711Seric **  FMTMSG -- format a message into buffer.
2264711Seric **
2274711Seric **	Parameters:
2284711Seric **		eb -- error buffer to get result.
2294711Seric **		to -- the recipient tag for this message.
2304711Seric **		num -- arpanet error number.
23116901Seric **		en -- the error number to display.
2324711Seric **		fmt -- format of string.
2334711Seric **		a, b, c, d, e -- arguments.
2344711Seric **
2354711Seric **	Returns:
2364711Seric **		none.
2374711Seric **
2384711Seric **	Side Effects:
2394711Seric **		none.
2404711Seric */
2414063Seric 
24216901Seric /*VARARGS5*/
2434711Seric static
24416901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
2454711Seric 	register char *eb;
2464711Seric 	char *to;
2474711Seric 	char *num;
24816904Seric 	int eno;
2494711Seric 	char *fmt;
2504711Seric {
2514711Seric 	char del;
2524711Seric 
2534711Seric 	/* output the reply code */
25424943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2554577Seric 	{
2564711Seric 		num = fmt;
2574711Seric 		fmt += 4;
2584711Seric 	}
2594711Seric 	if (num[3] == '-')
2604711Seric 		del = '-';
2614711Seric 	else
2624711Seric 		del = ' ';
2634711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
2644711Seric 	eb += 4;
2654063Seric 
2669372Seric 	/* output the file name and line number */
2679372Seric 	if (FileName != NULL)
2689372Seric 	{
2699372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
2709372Seric 		eb += strlen(eb);
2719372Seric 	}
2729372Seric 
2734711Seric 	/* output the "to" person */
2744711Seric 	if (to != NULL && to[0] != '\0')
2754711Seric 	{
2764711Seric 		(void) sprintf(eb, "%s... ", to);
2775201Seric 		while (*eb != '\0')
2785201Seric 			*eb++ &= 0177;
2794711Seric 	}
2804711Seric 
2814711Seric 	/* output the message */
2824711Seric 	(void) sprintf(eb, fmt, a, b, c, d, e);
2835201Seric 	while (*eb != '\0')
2845201Seric 		*eb++ &= 0177;
2854711Seric 
2864711Seric 	/* output the error code, if any */
28716904Seric 	if (eno != 0)
2884711Seric 	{
28915136Seric 		extern char *errstring();
29015136Seric 
29116904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
2924711Seric 		eb += strlen(eb);
2934577Seric 	}
294295Seric }
29515136Seric /*
29615136Seric **  ERRSTRING -- return string description of error code
29715136Seric **
29815136Seric **	Parameters:
29915136Seric **		errno -- the error number to translate
30015136Seric **
30115136Seric **	Returns:
30215136Seric **		A string description of errno.
30315136Seric **
30415136Seric **	Side Effects:
30515136Seric **		none.
30615136Seric */
30715136Seric 
30815136Seric char *
30915136Seric errstring(errno)
31015136Seric 	int errno;
31115136Seric {
31215136Seric 	extern char *sys_errlist[];
31315136Seric 	extern int sys_nerr;
31424943Seric 	static char buf[100];
31524943Seric # ifdef SMTP
31624943Seric 	extern char *SmtpPhase;
31724943Seric # endif SMTP
31815136Seric 
31924943Seric # ifdef DAEMON
32024943Seric # ifdef VMUNIX
32124943Seric 	/*
32224943Seric 	**  Handle special network error codes.
32324943Seric 	**
32424943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
32524943Seric 	*/
32624943Seric 
32724943Seric 	switch (errno)
32824943Seric 	{
32924943Seric 	  case ETIMEDOUT:
33024943Seric 	  case ECONNRESET:
33124943Seric 		(void) strcpy(buf, sys_errlist[errno]);
33224943Seric 		if (SmtpPhase != NULL)
33324943Seric 		{
33424943Seric 			(void) strcat(buf, " during ");
33524943Seric 			(void) strcat(buf, SmtpPhase);
33624943Seric 		}
33725050Seric 		if (CurHostName != NULL)
33824943Seric 		{
33924943Seric 			(void) strcat(buf, " with ");
34025050Seric 			(void) strcat(buf, CurHostName);
34124943Seric 		}
34224943Seric 		return (buf);
34324943Seric 
34424943Seric 	  case EHOSTDOWN:
34525050Seric 		if (CurHostName == NULL)
34624943Seric 			break;
34725050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
34824943Seric 		return (buf);
34924943Seric 
35024943Seric 	  case ECONNREFUSED:
35125050Seric 		if (CurHostName == NULL)
35224943Seric 			break;
35325050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
35424943Seric 		return (buf);
35524943Seric 	}
35624943Seric # endif VMUNIX
35724943Seric # endif DAEMON
35824943Seric 
35915136Seric 	if (errno > 0 && errno < sys_nerr)
36015136Seric 		return (sys_errlist[errno]);
36115136Seric 
36215136Seric 	(void) sprintf(buf, "Error %d", errno);
36315136Seric 	return (buf);
36415136Seric }
365