xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 34921)
122705Sdist /*
2*34921Sbostic  * Copyright (c) 1983 Eric P. Allman
333729Sbostic  * Copyright (c) 1988 Regents of the University of California.
433729Sbostic  * All rights reserved.
533729Sbostic  *
633729Sbostic  * Redistribution and use in source and binary forms are permitted
7*34921Sbostic  * provided that the above copyright notice and this paragraph are
8*34921Sbostic  * duplicated in all such forms and that any documentation,
9*34921Sbostic  * advertising materials, and other materials related to such
10*34921Sbostic  * distribution and use acknowledge that the software was developed
11*34921Sbostic  * by the University of California, Berkeley.  The name of the
12*34921Sbostic  * University may not be used to endorse or promote products derived
13*34921Sbostic  * from this software without specific prior written permission.
14*34921Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15*34921Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16*34921Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1733729Sbostic  */
1822705Sdist 
1922705Sdist #ifndef lint
20*34921Sbostic static char sccsid[] = "@(#)err.c	5.9 (Berkeley) 06/30/88";
2133729Sbostic #endif /* not lint */
2222705Sdist 
233311Seric # include "sendmail.h"
2424943Seric # include <errno.h>
2525526Smiriam # include <netdb.h>
26295Seric 
27295Seric /*
281514Seric **  SYSERR -- Print error message.
29295Seric **
30295Seric **	Prints an error message via printf to the diagnostic
31295Seric **	output.  If LOG is defined, it logs it also.
32295Seric **
33295Seric **	Parameters:
34295Seric **		f -- the format string
35295Seric **		a, b, c, d, e -- parameters
36295Seric **
37295Seric **	Returns:
384084Seric **		none
397762Seric **		Through TopFrame if QuickAbort is set.
40295Seric **
41295Seric **	Side Effects:
421514Seric **		increments Errors.
431514Seric **		sets ExitStat.
44295Seric */
45295Seric 
464084Seric # ifdef lint
474084Seric int	sys_nerr;
484084Seric char	*sys_errlist[];
494084Seric # endif lint
5010147Seric char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
514084Seric 
52295Seric /*VARARGS1*/
53295Seric syserr(fmt, a, b, c, d, e)
54295Seric 	char *fmt;
55295Seric {
5616901Seric 	register char *p;
5716901Seric 	int olderrno = errno;
587957Seric 	extern char Arpa_PSyserr[];
597957Seric 	extern char Arpa_TSyserr[];
60295Seric 
617525Seric 	/* format and output the error message */
6216901Seric 	if (olderrno == 0)
637957Seric 		p = Arpa_PSyserr;
647957Seric 	else
657957Seric 		p = Arpa_TSyserr;
6616901Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
679389Seric 	puterrmsg(MsgBuf);
684063Seric 
69295Seric 	/* determine exit status if not already set */
70295Seric 	if (ExitStat == EX_OK)
71295Seric 	{
7216901Seric 		if (olderrno == 0)
73295Seric 			ExitStat = EX_SOFTWARE;
74295Seric 		else
751598Seric 			ExitStat = EX_OSERR;
76295Seric 	}
77295Seric 
78295Seric # ifdef LOG
797674Seric 	if (LogLevel > 0)
8025277Seric 		syslog(LOG_CRIT, "%s: SYSERR: %s",
8125277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
8225277Seric 			&MsgBuf[4]);
83295Seric # endif LOG
84295Seric 	errno = 0;
857762Seric 	if (QuickAbort)
867762Seric 		longjmp(TopFrame, 2);
87295Seric }
88295Seric /*
89295Seric **  USRERR -- Signal user error.
90295Seric **
91295Seric **	This is much like syserr except it is for user errors.
92295Seric **
93295Seric **	Parameters:
94295Seric **		fmt, a, b, c, d -- printf strings
95295Seric **
96295Seric **	Returns:
974084Seric **		none
987762Seric **		Through TopFrame if QuickAbort is set.
99295Seric **
100295Seric **	Side Effects:
1011514Seric **		increments Errors.
102295Seric */
103295Seric 
104295Seric /*VARARGS1*/
105295Seric usrerr(fmt, a, b, c, d, e)
106295Seric 	char *fmt;
107295Seric {
108295Seric 	extern char SuprErrs;
1094167Seric 	extern char Arpa_Usrerr[];
11016901Seric 	extern int errno;
111295Seric 
112295Seric 	if (SuprErrs)
1134084Seric 		return;
114295Seric 
11516901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
1169389Seric 	puterrmsg(MsgBuf);
1178239Seric 
1187762Seric 	if (QuickAbort)
1197762Seric 		longjmp(TopFrame, 1);
1204063Seric }
1214063Seric /*
1224063Seric **  MESSAGE -- print message (not necessarily an error)
1234063Seric **
1244063Seric **	Parameters:
1254063Seric **		num -- the default ARPANET error number (in ascii)
1264063Seric **		msg -- the message (printf fmt) -- if it begins
1274063Seric **			with a digit, this number overrides num.
1284063Seric **		a, b, c, d, e -- printf arguments
1294063Seric **
1304063Seric **	Returns:
1314063Seric **		none
1324063Seric **
1334063Seric **	Side Effects:
1344063Seric **		none.
1354063Seric */
1364063Seric 
1374084Seric /*VARARGS2*/
1384063Seric message(num, msg, a, b, c, d, e)
1394063Seric 	register char *num;
1404063Seric 	register char *msg;
1414063Seric {
1424711Seric 	errno = 0;
14316901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
1449108Seric 	putmsg(MsgBuf, FALSE);
1457613Seric }
1467613Seric /*
1478239Seric **  NMESSAGE -- print message (not necessarily an error)
1488239Seric **
1498239Seric **	Just like "message" except it never puts the to... tag on.
1508239Seric **
1518239Seric **	Parameters:
1528239Seric **		num -- the default ARPANET error number (in ascii)
1538239Seric **		msg -- the message (printf fmt) -- if it begins
15424943Seric **			with three digits, this number overrides num.
1558239Seric **		a, b, c, d, e -- printf arguments
1568239Seric **
1578239Seric **	Returns:
1588239Seric **		none
1598239Seric **
1608239Seric **	Side Effects:
1618239Seric **		none.
1628239Seric */
1638239Seric 
1648239Seric /*VARARGS2*/
1658239Seric nmessage(num, msg, a, b, c, d, e)
1668239Seric 	register char *num;
1678239Seric 	register char *msg;
1688239Seric {
1698239Seric 	errno = 0;
17016901Seric 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
1719108Seric 	putmsg(MsgBuf, FALSE);
1728239Seric }
1738239Seric /*
1747613Seric **  PUTMSG -- output error message to transcript and channel
1757613Seric **
1767613Seric **	Parameters:
1777613Seric **		msg -- message to output (in SMTP format).
1789108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
1799108Seric **			our output channel.
1807613Seric **
1817613Seric **	Returns:
1827613Seric **		none.
1837613Seric **
1847613Seric **	Side Effects:
1857613Seric **		Outputs msg to the transcript.
1867613Seric **		If appropriate, outputs it to the channel.
1877613Seric **		Deletes SMTP reply code number as appropriate.
1887613Seric */
1894711Seric 
1909108Seric putmsg(msg, holdmsg)
1917613Seric 	char *msg;
1929108Seric 	bool holdmsg;
1937613Seric {
19414900Seric 	/* output to transcript if serious */
19514900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
19614900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
1974711Seric 
1984711Seric 	/* output to channel if appropriate */
1999108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
2004063Seric 	{
2017275Seric 		(void) fflush(stdout);
2029277Seric 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
2037613Seric 			fprintf(OutChannel, "%s\r\n", msg);
2044711Seric 		else
2057613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
2064711Seric 		(void) fflush(OutChannel);
2074063Seric 	}
2089389Seric }
2099389Seric /*
2109389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2119389Seric **
2129389Seric **	Parameters:
2139389Seric **		msg -- the message to output.
2149389Seric **
2159389Seric **	Returns:
2169389Seric **		none.
2179389Seric **
2189389Seric **	Side Effects:
2199389Seric **		Sets the fatal error bit in the envelope as appropriate.
2209389Seric */
2218239Seric 
2229389Seric puterrmsg(msg)
2239389Seric 	char *msg;
2249389Seric {
2259389Seric 	/* output the message as usual */
2269389Seric 	putmsg(msg, HoldErrs);
2279389Seric 
2289389Seric 	/* signal the error */
2299389Seric 	Errors++;
2309389Seric 	if (msg[0] == '5')
2319336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2324711Seric }
2334711Seric /*
2344711Seric **  FMTMSG -- format a message into buffer.
2354711Seric **
2364711Seric **	Parameters:
2374711Seric **		eb -- error buffer to get result.
2384711Seric **		to -- the recipient tag for this message.
2394711Seric **		num -- arpanet error number.
24016901Seric **		en -- the error number to display.
2414711Seric **		fmt -- format of string.
2424711Seric **		a, b, c, d, e -- arguments.
2434711Seric **
2444711Seric **	Returns:
2454711Seric **		none.
2464711Seric **
2474711Seric **	Side Effects:
2484711Seric **		none.
2494711Seric */
2504063Seric 
25116901Seric /*VARARGS5*/
2524711Seric static
25316901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
2544711Seric 	register char *eb;
2554711Seric 	char *to;
2564711Seric 	char *num;
25716904Seric 	int eno;
2584711Seric 	char *fmt;
2594711Seric {
2604711Seric 	char del;
2614711Seric 
2624711Seric 	/* output the reply code */
26324943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2644577Seric 	{
2654711Seric 		num = fmt;
2664711Seric 		fmt += 4;
2674711Seric 	}
2684711Seric 	if (num[3] == '-')
2694711Seric 		del = '-';
2704711Seric 	else
2714711Seric 		del = ' ';
2724711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
2734711Seric 	eb += 4;
2744063Seric 
2759372Seric 	/* output the file name and line number */
2769372Seric 	if (FileName != NULL)
2779372Seric 	{
2789372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
2799372Seric 		eb += strlen(eb);
2809372Seric 	}
2819372Seric 
2824711Seric 	/* output the "to" person */
2834711Seric 	if (to != NULL && to[0] != '\0')
2844711Seric 	{
2854711Seric 		(void) sprintf(eb, "%s... ", to);
2865201Seric 		while (*eb != '\0')
2875201Seric 			*eb++ &= 0177;
2884711Seric 	}
2894711Seric 
2904711Seric 	/* output the message */
2914711Seric 	(void) sprintf(eb, fmt, a, b, c, d, e);
2925201Seric 	while (*eb != '\0')
2935201Seric 		*eb++ &= 0177;
2944711Seric 
2954711Seric 	/* output the error code, if any */
29616904Seric 	if (eno != 0)
2974711Seric 	{
29815136Seric 		extern char *errstring();
29915136Seric 
30016904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
3014711Seric 		eb += strlen(eb);
3024577Seric 	}
303295Seric }
30415136Seric /*
30515136Seric **  ERRSTRING -- return string description of error code
30615136Seric **
30715136Seric **	Parameters:
30815136Seric **		errno -- the error number to translate
30915136Seric **
31015136Seric **	Returns:
31115136Seric **		A string description of errno.
31215136Seric **
31315136Seric **	Side Effects:
31415136Seric **		none.
31515136Seric */
31615136Seric 
31715136Seric char *
31815136Seric errstring(errno)
31915136Seric 	int errno;
32015136Seric {
32115136Seric 	extern char *sys_errlist[];
32215136Seric 	extern int sys_nerr;
32324943Seric 	static char buf[100];
32424943Seric # ifdef SMTP
32524943Seric 	extern char *SmtpPhase;
32624943Seric # endif SMTP
32715136Seric 
32824943Seric # ifdef DAEMON
32924943Seric # ifdef VMUNIX
33024943Seric 	/*
33124943Seric 	**  Handle special network error codes.
33224943Seric 	**
33324943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
33424943Seric 	*/
33524943Seric 
33624943Seric 	switch (errno)
33724943Seric 	{
33824943Seric 	  case ETIMEDOUT:
33924943Seric 	  case ECONNRESET:
34024943Seric 		(void) strcpy(buf, sys_errlist[errno]);
34124943Seric 		if (SmtpPhase != NULL)
34224943Seric 		{
34324943Seric 			(void) strcat(buf, " during ");
34424943Seric 			(void) strcat(buf, SmtpPhase);
34524943Seric 		}
34625050Seric 		if (CurHostName != NULL)
34724943Seric 		{
34824943Seric 			(void) strcat(buf, " with ");
34925050Seric 			(void) strcat(buf, CurHostName);
35024943Seric 		}
35124943Seric 		return (buf);
35224943Seric 
35324943Seric 	  case EHOSTDOWN:
35425050Seric 		if (CurHostName == NULL)
35524943Seric 			break;
35625050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
35724943Seric 		return (buf);
35824943Seric 
35924943Seric 	  case ECONNREFUSED:
36025050Seric 		if (CurHostName == NULL)
36124943Seric 			break;
36225050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
36324943Seric 		return (buf);
36425526Smiriam 
36525526Smiriam 	  case (TRY_AGAIN+MAX_ERRNO):
36625526Smiriam 		(void) sprintf(buf, "Host Name Lookup Failure");
36725526Smiriam 		return (buf);
36824943Seric 	}
36924943Seric # endif VMUNIX
37024943Seric # endif DAEMON
37124943Seric 
37215136Seric 	if (errno > 0 && errno < sys_nerr)
37315136Seric 		return (sys_errlist[errno]);
37415136Seric 
37515136Seric 	(void) sprintf(buf, "Error %d", errno);
37615136Seric 	return (buf);
37715136Seric }
378