xref: /original-bsd/usr.sbin/sendmail/src/err.c (revision 30e23803)
1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)err.c	5.10 (Berkeley) 06/01/90";
11 #endif /* not lint */
12 
13 # include "sendmail.h"
14 # include <errno.h>
15 # include <netdb.h>
16 
17 /*
18 **  SYSERR -- Print error message.
19 **
20 **	Prints an error message via printf to the diagnostic
21 **	output.  If LOG is defined, it logs it also.
22 **
23 **	Parameters:
24 **		f -- the format string
25 **		a, b, c, d, e -- parameters
26 **
27 **	Returns:
28 **		none
29 **		Through TopFrame if QuickAbort is set.
30 **
31 **	Side Effects:
32 **		increments Errors.
33 **		sets ExitStat.
34 */
35 
36 # ifdef lint
37 int	sys_nerr;
38 char	*sys_errlist[];
39 # endif lint
40 char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
41 
42 /*VARARGS1*/
43 syserr(fmt, a, b, c, d, e)
44 	char *fmt;
45 {
46 	register char *p;
47 	int olderrno = errno;
48 	extern char Arpa_PSyserr[];
49 	extern char Arpa_TSyserr[];
50 
51 	/* format and output the error message */
52 	if (olderrno == 0)
53 		p = Arpa_PSyserr;
54 	else
55 		p = Arpa_TSyserr;
56 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
57 	puterrmsg(MsgBuf);
58 
59 	/* determine exit status if not already set */
60 	if (ExitStat == EX_OK)
61 	{
62 		if (olderrno == 0)
63 			ExitStat = EX_SOFTWARE;
64 		else
65 			ExitStat = EX_OSERR;
66 	}
67 
68 # ifdef LOG
69 	if (LogLevel > 0)
70 		syslog(LOG_CRIT, "%s: SYSERR: %s",
71 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
72 			&MsgBuf[4]);
73 # endif LOG
74 	errno = 0;
75 	if (QuickAbort)
76 		longjmp(TopFrame, 2);
77 }
78 /*
79 **  USRERR -- Signal user error.
80 **
81 **	This is much like syserr except it is for user errors.
82 **
83 **	Parameters:
84 **		fmt, a, b, c, d -- printf strings
85 **
86 **	Returns:
87 **		none
88 **		Through TopFrame if QuickAbort is set.
89 **
90 **	Side Effects:
91 **		increments Errors.
92 */
93 
94 /*VARARGS1*/
95 usrerr(fmt, a, b, c, d, e)
96 	char *fmt;
97 {
98 	extern char SuprErrs;
99 	extern char Arpa_Usrerr[];
100 	extern int errno;
101 
102 	if (SuprErrs)
103 		return;
104 
105 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
106 	puterrmsg(MsgBuf);
107 
108 	if (QuickAbort)
109 		longjmp(TopFrame, 1);
110 }
111 /*
112 **  MESSAGE -- print message (not necessarily an error)
113 **
114 **	Parameters:
115 **		num -- the default ARPANET error number (in ascii)
116 **		msg -- the message (printf fmt) -- if it begins
117 **			with a digit, this number overrides num.
118 **		a, b, c, d, e -- printf arguments
119 **
120 **	Returns:
121 **		none
122 **
123 **	Side Effects:
124 **		none.
125 */
126 
127 /*VARARGS2*/
128 message(num, msg, a, b, c, d, e)
129 	register char *num;
130 	register char *msg;
131 {
132 	errno = 0;
133 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
134 	putmsg(MsgBuf, FALSE);
135 }
136 /*
137 **  NMESSAGE -- print message (not necessarily an error)
138 **
139 **	Just like "message" except it never puts the to... tag on.
140 **
141 **	Parameters:
142 **		num -- the default ARPANET error number (in ascii)
143 **		msg -- the message (printf fmt) -- if it begins
144 **			with three digits, this number overrides num.
145 **		a, b, c, d, e -- printf arguments
146 **
147 **	Returns:
148 **		none
149 **
150 **	Side Effects:
151 **		none.
152 */
153 
154 /*VARARGS2*/
155 nmessage(num, msg, a, b, c, d, e)
156 	register char *num;
157 	register char *msg;
158 {
159 	errno = 0;
160 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
161 	putmsg(MsgBuf, FALSE);
162 }
163 /*
164 **  PUTMSG -- output error message to transcript and channel
165 **
166 **	Parameters:
167 **		msg -- message to output (in SMTP format).
168 **		holdmsg -- if TRUE, don't output a copy of the message to
169 **			our output channel.
170 **
171 **	Returns:
172 **		none.
173 **
174 **	Side Effects:
175 **		Outputs msg to the transcript.
176 **		If appropriate, outputs it to the channel.
177 **		Deletes SMTP reply code number as appropriate.
178 */
179 
180 putmsg(msg, holdmsg)
181 	char *msg;
182 	bool holdmsg;
183 {
184 	/* output to transcript if serious */
185 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
186 		fprintf(CurEnv->e_xfp, "%s\n", msg);
187 
188 	/* output to channel if appropriate */
189 	if (!holdmsg && (Verbose || msg[0] != '0'))
190 	{
191 		(void) fflush(stdout);
192 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
193 			fprintf(OutChannel, "%s\r\n", msg);
194 		else
195 			fprintf(OutChannel, "%s\n", &msg[4]);
196 		(void) fflush(OutChannel);
197 	}
198 }
199 /*
200 **  PUTERRMSG -- like putmsg, but does special processing for error messages
201 **
202 **	Parameters:
203 **		msg -- the message to output.
204 **
205 **	Returns:
206 **		none.
207 **
208 **	Side Effects:
209 **		Sets the fatal error bit in the envelope as appropriate.
210 */
211 
212 puterrmsg(msg)
213 	char *msg;
214 {
215 	/* output the message as usual */
216 	putmsg(msg, HoldErrs);
217 
218 	/* signal the error */
219 	Errors++;
220 	if (msg[0] == '5')
221 		CurEnv->e_flags |= EF_FATALERRS;
222 }
223 /*
224 **  FMTMSG -- format a message into buffer.
225 **
226 **	Parameters:
227 **		eb -- error buffer to get result.
228 **		to -- the recipient tag for this message.
229 **		num -- arpanet error number.
230 **		en -- the error number to display.
231 **		fmt -- format of string.
232 **		a, b, c, d, e -- arguments.
233 **
234 **	Returns:
235 **		none.
236 **
237 **	Side Effects:
238 **		none.
239 */
240 
241 /*VARARGS5*/
242 static
243 fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
244 	register char *eb;
245 	char *to;
246 	char *num;
247 	int eno;
248 	char *fmt;
249 {
250 	char del;
251 
252 	/* output the reply code */
253 	if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
254 	{
255 		num = fmt;
256 		fmt += 4;
257 	}
258 	if (num[3] == '-')
259 		del = '-';
260 	else
261 		del = ' ';
262 	(void) sprintf(eb, "%3.3s%c", num, del);
263 	eb += 4;
264 
265 	/* output the file name and line number */
266 	if (FileName != NULL)
267 	{
268 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
269 		eb += strlen(eb);
270 	}
271 
272 	/* output the "to" person */
273 	if (to != NULL && to[0] != '\0')
274 	{
275 		(void) sprintf(eb, "%s... ", to);
276 		while (*eb != '\0')
277 			*eb++ &= 0177;
278 	}
279 
280 	/* output the message */
281 	(void) sprintf(eb, fmt, a, b, c, d, e);
282 	while (*eb != '\0')
283 		*eb++ &= 0177;
284 
285 	/* output the error code, if any */
286 	if (eno != 0)
287 	{
288 		extern char *errstring();
289 
290 		(void) sprintf(eb, ": %s", errstring(eno));
291 		eb += strlen(eb);
292 	}
293 }
294 /*
295 **  ERRSTRING -- return string description of error code
296 **
297 **	Parameters:
298 **		errno -- the error number to translate
299 **
300 **	Returns:
301 **		A string description of errno.
302 **
303 **	Side Effects:
304 **		none.
305 */
306 
307 char *
308 errstring(errno)
309 	int errno;
310 {
311 	extern char *sys_errlist[];
312 	extern int sys_nerr;
313 	static char buf[100];
314 # ifdef SMTP
315 	extern char *SmtpPhase;
316 # endif SMTP
317 
318 # ifdef DAEMON
319 # ifdef VMUNIX
320 	/*
321 	**  Handle special network error codes.
322 	**
323 	**	These are 4.2/4.3bsd specific; they should be in daemon.c.
324 	*/
325 
326 	switch (errno)
327 	{
328 	  case ETIMEDOUT:
329 	  case ECONNRESET:
330 		(void) strcpy(buf, sys_errlist[errno]);
331 		if (SmtpPhase != NULL)
332 		{
333 			(void) strcat(buf, " during ");
334 			(void) strcat(buf, SmtpPhase);
335 		}
336 		if (CurHostName != NULL)
337 		{
338 			(void) strcat(buf, " with ");
339 			(void) strcat(buf, CurHostName);
340 		}
341 		return (buf);
342 
343 	  case EHOSTDOWN:
344 		if (CurHostName == NULL)
345 			break;
346 		(void) sprintf(buf, "Host %s is down", CurHostName);
347 		return (buf);
348 
349 	  case ECONNREFUSED:
350 		if (CurHostName == NULL)
351 			break;
352 		(void) sprintf(buf, "Connection refused by %s", CurHostName);
353 		return (buf);
354 
355 	  case (TRY_AGAIN+MAX_ERRNO):
356 		(void) sprintf(buf, "Host Name Lookup Failure");
357 		return (buf);
358 	}
359 # endif VMUNIX
360 # endif DAEMON
361 
362 	if (errno > 0 && errno < sys_nerr)
363 		return (sys_errlist[errno]);
364 
365 	(void) sprintf(buf, "Error %d", errno);
366 	return (buf);
367 }
368