xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 58524)
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*58524Seric static char sccsid[] = "@(#)err.c	6.7 (Berkeley) 03/06/93";
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*/
4557642Seric #ifdef __STDC__
4657642Seric syserr(char *fmt, ...)
4757642Seric #else
4857642Seric syserr(fmt, va_alist)
49295Seric 	char *fmt;
5057642Seric 	va_dcl
5157642Seric #endif
52295Seric {
5316901Seric 	register char *p;
5416901Seric 	int olderrno = errno;
5556852Seric 	VA_LOCAL_DECL
56295Seric 
577525Seric 	/* format and output the error message */
5816901Seric 	if (olderrno == 0)
5958151Seric 		p = "554";
607957Seric 	else
6158151Seric 		p = "451";
6256852Seric 	VA_START(fmt);
6356852Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
6456852Seric 	VA_END;
659389Seric 	puterrmsg(MsgBuf);
664063Seric 
67295Seric 	/* determine exit status if not already set */
68295Seric 	if (ExitStat == EX_OK)
69295Seric 	{
7016901Seric 		if (olderrno == 0)
71295Seric 			ExitStat = EX_SOFTWARE;
72295Seric 		else
731598Seric 			ExitStat = EX_OSERR;
74295Seric 	}
75295Seric 
76295Seric # ifdef LOG
777674Seric 	if (LogLevel > 0)
7825277Seric 		syslog(LOG_CRIT, "%s: SYSERR: %s",
7925277Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
8025277Seric 			&MsgBuf[4]);
8156795Seric # endif /* LOG */
82295Seric 	errno = 0;
837762Seric 	if (QuickAbort)
847762Seric 		longjmp(TopFrame, 2);
85295Seric }
86295Seric /*
87295Seric **  USRERR -- Signal user error.
88295Seric **
89295Seric **	This is much like syserr except it is for user errors.
90295Seric **
91295Seric **	Parameters:
92295Seric **		fmt, a, b, c, d -- printf strings
93295Seric **
94295Seric **	Returns:
954084Seric **		none
967762Seric **		Through TopFrame if QuickAbort is set.
97295Seric **
98295Seric **	Side Effects:
991514Seric **		increments Errors.
100295Seric */
101295Seric 
102295Seric /*VARARGS1*/
10357642Seric #ifdef __STDC__
10457642Seric usrerr(char *fmt, ...)
10557642Seric #else
10657642Seric usrerr(fmt, va_alist)
107295Seric 	char *fmt;
10857642Seric 	va_dcl
10957642Seric #endif
110295Seric {
11156852Seric 	VA_LOCAL_DECL
112295Seric 	extern char SuprErrs;
11316901Seric 	extern int errno;
114295Seric 
115295Seric 	if (SuprErrs)
1164084Seric 		return;
117295Seric 
11856852Seric 	VA_START(fmt);
119*58524Seric 	fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
12056852Seric 	VA_END;
1219389Seric 	puterrmsg(MsgBuf);
1228239Seric 
12351951Seric # ifdef LOG
12458020Seric 	if (LogLevel > 3 && LogUsrErrs)
12551951Seric 		syslog(LOG_NOTICE, "%s: %s",
12651951Seric 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
12751951Seric 			&MsgBuf[4]);
12856795Seric # endif /* LOG */
12951951Seric 
1307762Seric 	if (QuickAbort)
1317762Seric 		longjmp(TopFrame, 1);
1324063Seric }
1334063Seric /*
1344063Seric **  MESSAGE -- print message (not necessarily an error)
1354063Seric **
1364063Seric **	Parameters:
1374063Seric **		num -- the default ARPANET error number (in ascii)
1384063Seric **		msg -- the message (printf fmt) -- if it begins
1394063Seric **			with a digit, this number overrides num.
1404063Seric **		a, b, c, d, e -- printf arguments
1414063Seric **
1424063Seric **	Returns:
1434063Seric **		none
1444063Seric **
1454063Seric **	Side Effects:
1464063Seric **		none.
1474063Seric */
1484063Seric 
1494084Seric /*VARARGS2*/
15057642Seric #ifdef __STDC__
15158151Seric message(char *msg, ...)
15257642Seric #else
15358151Seric message(msg, va_alist)
15456852Seric 	char *msg;
15557642Seric 	va_dcl
15657642Seric #endif
1574063Seric {
15856852Seric 	VA_LOCAL_DECL
15956852Seric 
1604711Seric 	errno = 0;
16156852Seric 	VA_START(msg);
16258151Seric 	fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
16356852Seric 	VA_END;
1649108Seric 	putmsg(MsgBuf, FALSE);
1657613Seric }
1667613Seric /*
1678239Seric **  NMESSAGE -- print message (not necessarily an error)
1688239Seric **
1698239Seric **	Just like "message" except it never puts the to... tag on.
1708239Seric **
1718239Seric **	Parameters:
1728239Seric **		num -- the default ARPANET error number (in ascii)
1738239Seric **		msg -- the message (printf fmt) -- if it begins
17424943Seric **			with three digits, this number overrides num.
1758239Seric **		a, b, c, d, e -- printf arguments
1768239Seric **
1778239Seric **	Returns:
1788239Seric **		none
1798239Seric **
1808239Seric **	Side Effects:
1818239Seric **		none.
1828239Seric */
1838239Seric 
1848239Seric /*VARARGS2*/
18557642Seric #ifdef __STDC__
18658151Seric nmessage(char *msg, ...)
18757642Seric #else
18858151Seric nmessage(msg, va_alist)
18956852Seric 	char *msg;
19057642Seric 	va_dcl
19157642Seric #endif
1928239Seric {
19356852Seric 	VA_LOCAL_DECL
19456852Seric 
1958239Seric 	errno = 0;
19656852Seric 	VA_START(msg);
19758151Seric 	fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
19856852Seric 	VA_END;
1999108Seric 	putmsg(MsgBuf, FALSE);
2008239Seric }
2018239Seric /*
2027613Seric **  PUTMSG -- output error message to transcript and channel
2037613Seric **
2047613Seric **	Parameters:
2057613Seric **		msg -- message to output (in SMTP format).
2069108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
2079108Seric **			our output channel.
2087613Seric **
2097613Seric **	Returns:
2107613Seric **		none.
2117613Seric **
2127613Seric **	Side Effects:
2137613Seric **		Outputs msg to the transcript.
2147613Seric **		If appropriate, outputs it to the channel.
2157613Seric **		Deletes SMTP reply code number as appropriate.
2167613Seric */
2174711Seric 
2189108Seric putmsg(msg, holdmsg)
2197613Seric 	char *msg;
2209108Seric 	bool holdmsg;
2217613Seric {
22214900Seric 	/* output to transcript if serious */
22314900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
22414900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
2254711Seric 
2264711Seric 	/* output to channel if appropriate */
2279108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
2284063Seric 	{
2297275Seric 		(void) fflush(stdout);
23052220Seric 		if (OpMode == MD_SMTP)
2317613Seric 			fprintf(OutChannel, "%s\r\n", msg);
2324711Seric 		else
2337613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
2344711Seric 		(void) fflush(OutChannel);
2354063Seric 	}
2369389Seric }
2379389Seric /*
2389389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2399389Seric **
2409389Seric **	Parameters:
2419389Seric **		msg -- the message to output.
2429389Seric **
2439389Seric **	Returns:
2449389Seric **		none.
2459389Seric **
2469389Seric **	Side Effects:
2479389Seric **		Sets the fatal error bit in the envelope as appropriate.
2489389Seric */
2498239Seric 
2509389Seric puterrmsg(msg)
2519389Seric 	char *msg;
2529389Seric {
2539389Seric 	/* output the message as usual */
2549389Seric 	putmsg(msg, HoldErrs);
2559389Seric 
2569389Seric 	/* signal the error */
2579389Seric 	Errors++;
2589389Seric 	if (msg[0] == '5')
2599336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2604711Seric }
2614711Seric /*
2624711Seric **  FMTMSG -- format a message into buffer.
2634711Seric **
2644711Seric **	Parameters:
2654711Seric **		eb -- error buffer to get result.
2664711Seric **		to -- the recipient tag for this message.
2674711Seric **		num -- arpanet error number.
26816901Seric **		en -- the error number to display.
2694711Seric **		fmt -- format of string.
2704711Seric **		a, b, c, d, e -- arguments.
2714711Seric **
2724711Seric **	Returns:
2734711Seric **		none.
2744711Seric **
2754711Seric **	Side Effects:
2764711Seric **		none.
2774711Seric */
2784063Seric 
27946928Sbostic static void
28056852Seric fmtmsg(eb, to, num, eno, fmt, ap)
2814711Seric 	register char *eb;
2824711Seric 	char *to;
2834711Seric 	char *num;
28416904Seric 	int eno;
2854711Seric 	char *fmt;
28656852Seric 	va_list ap;
2874711Seric {
2884711Seric 	char del;
2894711Seric 
2904711Seric 	/* output the reply code */
29124943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2924577Seric 	{
2934711Seric 		num = fmt;
2944711Seric 		fmt += 4;
2954711Seric 	}
2964711Seric 	if (num[3] == '-')
2974711Seric 		del = '-';
2984711Seric 	else
2994711Seric 		del = ' ';
3004711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
3014711Seric 	eb += 4;
3024063Seric 
3039372Seric 	/* output the file name and line number */
3049372Seric 	if (FileName != NULL)
3059372Seric 	{
3069372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
3079372Seric 		eb += strlen(eb);
3089372Seric 	}
3099372Seric 
3104711Seric 	/* output the "to" person */
3114711Seric 	if (to != NULL && to[0] != '\0')
3124711Seric 	{
3134711Seric 		(void) sprintf(eb, "%s... ", to);
3145201Seric 		while (*eb != '\0')
3155201Seric 			*eb++ &= 0177;
3164711Seric 	}
3174711Seric 
3184711Seric 	/* output the message */
31956852Seric 	(void) vsprintf(eb, fmt, ap);
3205201Seric 	while (*eb != '\0')
3215201Seric 		*eb++ &= 0177;
3224711Seric 
3234711Seric 	/* output the error code, if any */
32416904Seric 	if (eno != 0)
3254711Seric 	{
32615136Seric 		extern char *errstring();
32715136Seric 
32816904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
3294711Seric 		eb += strlen(eb);
3304577Seric 	}
331295Seric }
33215136Seric /*
33315136Seric **  ERRSTRING -- return string description of error code
33415136Seric **
33515136Seric **	Parameters:
33615136Seric **		errno -- the error number to translate
33715136Seric **
33815136Seric **	Returns:
33915136Seric **		A string description of errno.
34015136Seric **
34115136Seric **	Side Effects:
34215136Seric **		none.
34315136Seric */
34415136Seric 
34515136Seric char *
34615136Seric errstring(errno)
34715136Seric 	int errno;
34815136Seric {
34915136Seric 	extern char *sys_errlist[];
35015136Seric 	extern int sys_nerr;
35157232Seric 	static char buf[MAXLINE];
35224943Seric # ifdef SMTP
35324943Seric 	extern char *SmtpPhase;
35456795Seric # endif /* SMTP */
35515136Seric 
35624943Seric # ifdef DAEMON
35752107Seric # ifdef ETIMEDOUT
35824943Seric 	/*
35924943Seric 	**  Handle special network error codes.
36024943Seric 	**
36124943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
36224943Seric 	*/
36324943Seric 
36424943Seric 	switch (errno)
36524943Seric 	{
36624943Seric 	  case ETIMEDOUT:
36724943Seric 	  case ECONNRESET:
36824943Seric 		(void) strcpy(buf, sys_errlist[errno]);
36924943Seric 		if (SmtpPhase != NULL)
37024943Seric 		{
37124943Seric 			(void) strcat(buf, " during ");
37224943Seric 			(void) strcat(buf, SmtpPhase);
37324943Seric 		}
37425050Seric 		if (CurHostName != NULL)
37524943Seric 		{
37624943Seric 			(void) strcat(buf, " with ");
37725050Seric 			(void) strcat(buf, CurHostName);
37824943Seric 		}
37924943Seric 		return (buf);
38024943Seric 
38124943Seric 	  case EHOSTDOWN:
38225050Seric 		if (CurHostName == NULL)
38324943Seric 			break;
38425050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
38524943Seric 		return (buf);
38624943Seric 
38724943Seric 	  case ECONNREFUSED:
38825050Seric 		if (CurHostName == NULL)
38924943Seric 			break;
39025050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
39124943Seric 		return (buf);
39225526Smiriam 
39357736Seric # ifdef NAMED_BIND
39458010Seric 	  case HOST_NOT_FOUND + MAX_ERRNO:
39558010Seric 		return ("Name server: host not found");
39658010Seric 
39758010Seric 	  case TRY_AGAIN + MAX_ERRNO:
39858010Seric 		return ("Name server: host name lookup failure");
39958010Seric 
40058010Seric 	  case NO_RECOVERY + MAX_ERRNO:
40158010Seric 		return ("Name server: non-recoverable error");
40258010Seric 
40358010Seric 	  case NO_DATA + MAX_ERRNO:
40458010Seric 		return ("Name server: no data known for name");
40557736Seric # endif
40624943Seric 	}
40752107Seric # endif
40852107Seric # endif
40924943Seric 
41015136Seric 	if (errno > 0 && errno < sys_nerr)
41115136Seric 		return (sys_errlist[errno]);
41215136Seric 
41315136Seric 	(void) sprintf(buf, "Error %d", errno);
41415136Seric 	return (buf);
41515136Seric }
416