xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 33729)
122705Sdist /*
2*33729Sbostic  * Copyright (c) 1988 Regents of the University of California.
3*33729Sbostic  * All rights reserved.
4*33729Sbostic  *
5*33729Sbostic  * Redistribution and use in source and binary forms are permitted
6*33729Sbostic  * provided that this notice is preserved and that due credit is given
7*33729Sbostic  * to the University of California at Berkeley. The name of the University
8*33729Sbostic  * may not be used to endorse or promote products derived from this
9*33729Sbostic  * software without specific prior written permission. This software
10*33729Sbostic  * is provided ``as is'' without express or implied warranty.
11*33729Sbostic  *
12*33729Sbostic  *  Sendmail
13*33729Sbostic  *  Copyright (c) 1983  Eric P. Allman
14*33729Sbostic  *  Berkeley, California
15*33729Sbostic  */
1622705Sdist 
1722705Sdist #ifndef lint
18*33729Sbostic static char sccsid[] = "@(#)err.c	5.8 (Berkeley) 03/13/88";
19*33729Sbostic #endif /* not lint */
2022705Sdist 
213311Seric # include "sendmail.h"
2224943Seric # include <errno.h>
2325526Smiriam # include <netdb.h>
24295Seric 
25295Seric /*
261514Seric **  SYSERR -- Print error message.
27295Seric **
28295Seric **	Prints an error message via printf to the diagnostic
29295Seric **	output.  If LOG is defined, it logs it also.
30295Seric **
31295Seric **	Parameters:
32295Seric **		f -- the format string
33295Seric **		a, b, c, d, e -- parameters
34295Seric **
35295Seric **	Returns:
364084Seric **		none
377762Seric **		Through TopFrame if QuickAbort is set.
38295Seric **
39295Seric **	Side Effects:
401514Seric **		increments Errors.
411514Seric **		sets ExitStat.
42295Seric */
43295Seric 
444084Seric # ifdef lint
454084Seric int	sys_nerr;
464084Seric char	*sys_errlist[];
474084Seric # endif lint
4810147Seric char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
494084Seric 
50295Seric /*VARARGS1*/
51295Seric syserr(fmt, a, b, c, d, e)
52295Seric 	char *fmt;
53295Seric {
5416901Seric 	register char *p;
5516901Seric 	int olderrno = errno;
567957Seric 	extern char Arpa_PSyserr[];
577957Seric 	extern char Arpa_TSyserr[];
58295Seric 
597525Seric 	/* format and output the error message */
6016901Seric 	if (olderrno == 0)
617957Seric 		p = Arpa_PSyserr;
627957Seric 	else
637957Seric 		p = Arpa_TSyserr;
6416901Seric 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
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]);
81295Seric # 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*/
103295Seric usrerr(fmt, a, b, c, d, e)
104295Seric 	char *fmt;
105295Seric {
106295Seric 	extern char SuprErrs;
1074167Seric 	extern char Arpa_Usrerr[];
10816901Seric 	extern int errno;
109295Seric 
110295Seric 	if (SuprErrs)
1114084Seric 		return;
112295Seric 
11316901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
1149389Seric 	puterrmsg(MsgBuf);
1158239Seric 
1167762Seric 	if (QuickAbort)
1177762Seric 		longjmp(TopFrame, 1);
1184063Seric }
1194063Seric /*
1204063Seric **  MESSAGE -- print message (not necessarily an error)
1214063Seric **
1224063Seric **	Parameters:
1234063Seric **		num -- the default ARPANET error number (in ascii)
1244063Seric **		msg -- the message (printf fmt) -- if it begins
1254063Seric **			with a digit, this number overrides num.
1264063Seric **		a, b, c, d, e -- printf arguments
1274063Seric **
1284063Seric **	Returns:
1294063Seric **		none
1304063Seric **
1314063Seric **	Side Effects:
1324063Seric **		none.
1334063Seric */
1344063Seric 
1354084Seric /*VARARGS2*/
1364063Seric message(num, msg, a, b, c, d, e)
1374063Seric 	register char *num;
1384063Seric 	register char *msg;
1394063Seric {
1404711Seric 	errno = 0;
14116901Seric 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
1429108Seric 	putmsg(MsgBuf, FALSE);
1437613Seric }
1447613Seric /*
1458239Seric **  NMESSAGE -- print message (not necessarily an error)
1468239Seric **
1478239Seric **	Just like "message" except it never puts the to... tag on.
1488239Seric **
1498239Seric **	Parameters:
1508239Seric **		num -- the default ARPANET error number (in ascii)
1518239Seric **		msg -- the message (printf fmt) -- if it begins
15224943Seric **			with three digits, this number overrides num.
1538239Seric **		a, b, c, d, e -- printf arguments
1548239Seric **
1558239Seric **	Returns:
1568239Seric **		none
1578239Seric **
1588239Seric **	Side Effects:
1598239Seric **		none.
1608239Seric */
1618239Seric 
1628239Seric /*VARARGS2*/
1638239Seric nmessage(num, msg, a, b, c, d, e)
1648239Seric 	register char *num;
1658239Seric 	register char *msg;
1668239Seric {
1678239Seric 	errno = 0;
16816901Seric 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
1699108Seric 	putmsg(MsgBuf, FALSE);
1708239Seric }
1718239Seric /*
1727613Seric **  PUTMSG -- output error message to transcript and channel
1737613Seric **
1747613Seric **	Parameters:
1757613Seric **		msg -- message to output (in SMTP format).
1769108Seric **		holdmsg -- if TRUE, don't output a copy of the message to
1779108Seric **			our output channel.
1787613Seric **
1797613Seric **	Returns:
1807613Seric **		none.
1817613Seric **
1827613Seric **	Side Effects:
1837613Seric **		Outputs msg to the transcript.
1847613Seric **		If appropriate, outputs it to the channel.
1857613Seric **		Deletes SMTP reply code number as appropriate.
1867613Seric */
1874711Seric 
1889108Seric putmsg(msg, holdmsg)
1897613Seric 	char *msg;
1909108Seric 	bool holdmsg;
1917613Seric {
19214900Seric 	/* output to transcript if serious */
19314900Seric 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
19414900Seric 		fprintf(CurEnv->e_xfp, "%s\n", msg);
1954711Seric 
1964711Seric 	/* output to channel if appropriate */
1979108Seric 	if (!holdmsg && (Verbose || msg[0] != '0'))
1984063Seric 	{
1997275Seric 		(void) fflush(stdout);
2009277Seric 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
2017613Seric 			fprintf(OutChannel, "%s\r\n", msg);
2024711Seric 		else
2037613Seric 			fprintf(OutChannel, "%s\n", &msg[4]);
2044711Seric 		(void) fflush(OutChannel);
2054063Seric 	}
2069389Seric }
2079389Seric /*
2089389Seric **  PUTERRMSG -- like putmsg, but does special processing for error messages
2099389Seric **
2109389Seric **	Parameters:
2119389Seric **		msg -- the message to output.
2129389Seric **
2139389Seric **	Returns:
2149389Seric **		none.
2159389Seric **
2169389Seric **	Side Effects:
2179389Seric **		Sets the fatal error bit in the envelope as appropriate.
2189389Seric */
2198239Seric 
2209389Seric puterrmsg(msg)
2219389Seric 	char *msg;
2229389Seric {
2239389Seric 	/* output the message as usual */
2249389Seric 	putmsg(msg, HoldErrs);
2259389Seric 
2269389Seric 	/* signal the error */
2279389Seric 	Errors++;
2289389Seric 	if (msg[0] == '5')
2299336Seric 		CurEnv->e_flags |= EF_FATALERRS;
2304711Seric }
2314711Seric /*
2324711Seric **  FMTMSG -- format a message into buffer.
2334711Seric **
2344711Seric **	Parameters:
2354711Seric **		eb -- error buffer to get result.
2364711Seric **		to -- the recipient tag for this message.
2374711Seric **		num -- arpanet error number.
23816901Seric **		en -- the error number to display.
2394711Seric **		fmt -- format of string.
2404711Seric **		a, b, c, d, e -- arguments.
2414711Seric **
2424711Seric **	Returns:
2434711Seric **		none.
2444711Seric **
2454711Seric **	Side Effects:
2464711Seric **		none.
2474711Seric */
2484063Seric 
24916901Seric /*VARARGS5*/
2504711Seric static
25116901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
2524711Seric 	register char *eb;
2534711Seric 	char *to;
2544711Seric 	char *num;
25516904Seric 	int eno;
2564711Seric 	char *fmt;
2574711Seric {
2584711Seric 	char del;
2594711Seric 
2604711Seric 	/* output the reply code */
26124943Seric 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
2624577Seric 	{
2634711Seric 		num = fmt;
2644711Seric 		fmt += 4;
2654711Seric 	}
2664711Seric 	if (num[3] == '-')
2674711Seric 		del = '-';
2684711Seric 	else
2694711Seric 		del = ' ';
2704711Seric 	(void) sprintf(eb, "%3.3s%c", num, del);
2714711Seric 	eb += 4;
2724063Seric 
2739372Seric 	/* output the file name and line number */
2749372Seric 	if (FileName != NULL)
2759372Seric 	{
2769372Seric 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
2779372Seric 		eb += strlen(eb);
2789372Seric 	}
2799372Seric 
2804711Seric 	/* output the "to" person */
2814711Seric 	if (to != NULL && to[0] != '\0')
2824711Seric 	{
2834711Seric 		(void) sprintf(eb, "%s... ", to);
2845201Seric 		while (*eb != '\0')
2855201Seric 			*eb++ &= 0177;
2864711Seric 	}
2874711Seric 
2884711Seric 	/* output the message */
2894711Seric 	(void) sprintf(eb, fmt, a, b, c, d, e);
2905201Seric 	while (*eb != '\0')
2915201Seric 		*eb++ &= 0177;
2924711Seric 
2934711Seric 	/* output the error code, if any */
29416904Seric 	if (eno != 0)
2954711Seric 	{
29615136Seric 		extern char *errstring();
29715136Seric 
29816904Seric 		(void) sprintf(eb, ": %s", errstring(eno));
2994711Seric 		eb += strlen(eb);
3004577Seric 	}
301295Seric }
30215136Seric /*
30315136Seric **  ERRSTRING -- return string description of error code
30415136Seric **
30515136Seric **	Parameters:
30615136Seric **		errno -- the error number to translate
30715136Seric **
30815136Seric **	Returns:
30915136Seric **		A string description of errno.
31015136Seric **
31115136Seric **	Side Effects:
31215136Seric **		none.
31315136Seric */
31415136Seric 
31515136Seric char *
31615136Seric errstring(errno)
31715136Seric 	int errno;
31815136Seric {
31915136Seric 	extern char *sys_errlist[];
32015136Seric 	extern int sys_nerr;
32124943Seric 	static char buf[100];
32224943Seric # ifdef SMTP
32324943Seric 	extern char *SmtpPhase;
32424943Seric # endif SMTP
32515136Seric 
32624943Seric # ifdef DAEMON
32724943Seric # ifdef VMUNIX
32824943Seric 	/*
32924943Seric 	**  Handle special network error codes.
33024943Seric 	**
33124943Seric 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
33224943Seric 	*/
33324943Seric 
33424943Seric 	switch (errno)
33524943Seric 	{
33624943Seric 	  case ETIMEDOUT:
33724943Seric 	  case ECONNRESET:
33824943Seric 		(void) strcpy(buf, sys_errlist[errno]);
33924943Seric 		if (SmtpPhase != NULL)
34024943Seric 		{
34124943Seric 			(void) strcat(buf, " during ");
34224943Seric 			(void) strcat(buf, SmtpPhase);
34324943Seric 		}
34425050Seric 		if (CurHostName != NULL)
34524943Seric 		{
34624943Seric 			(void) strcat(buf, " with ");
34725050Seric 			(void) strcat(buf, CurHostName);
34824943Seric 		}
34924943Seric 		return (buf);
35024943Seric 
35124943Seric 	  case EHOSTDOWN:
35225050Seric 		if (CurHostName == NULL)
35324943Seric 			break;
35425050Seric 		(void) sprintf(buf, "Host %s is down", CurHostName);
35524943Seric 		return (buf);
35624943Seric 
35724943Seric 	  case ECONNREFUSED:
35825050Seric 		if (CurHostName == NULL)
35924943Seric 			break;
36025050Seric 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
36124943Seric 		return (buf);
36225526Smiriam 
36325526Smiriam 	  case (TRY_AGAIN+MAX_ERRNO):
36425526Smiriam 		(void) sprintf(buf, "Host Name Lookup Failure");
36525526Smiriam 		return (buf);
36624943Seric 	}
36724943Seric # endif VMUNIX
36824943Seric # endif DAEMON
36924943Seric 
37015136Seric 	if (errno > 0 && errno < sys_nerr)
37115136Seric 		return (sys_errlist[errno]);
37215136Seric 
37315136Seric 	(void) sprintf(buf, "Error %d", errno);
37415136Seric 	return (buf);
37515136Seric }
376