Deleted Added
full compact
err.c (302408) err.c (38032)
1/*
1/*
2 * Copyright (c) 1998-2003, 2010 Proofpoint, Inc. and its suppliers.
3 * All rights reserved.
2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
14#include <sendmail.h>
13#ifndef lint
14static char sccsid[] = "@(#)err.c 8.74 (Berkeley) 6/4/98";
15#endif /* not lint */
15
16
16SM_RCSID("@(#)$Id: err.c,v 8.206 2013-11-22 20:51:55 ca Exp $")
17# include "sendmail.h"
18# include <errno.h>
17
19
18#if LDAPMAP
19# include <lber.h>
20# include <ldap.h> /* for LDAP error codes */
21#endif /* LDAPMAP */
22
23static void putoutmsg __P((char *, bool, bool));
24static void puterrmsg __P((char *));
25static char *fmtmsg __P((char *, const char *, const char *, const char *,
26 int, const char *, va_list));
27
28/*
20/*
29** FATAL_ERROR -- handle a fatal exception
30**
31** This function is installed as the default exception handler
32** in the main sendmail process, and in all child processes
33** that we create. Its job is to handle exceptions that are not
34** handled at a lower level.
35**
36** The theory is that unhandled exceptions will be 'fatal' class
37** exceptions (with an "F:" prefix), such as the out-of-memory
38** exception "F:sm.heap". As such, they are handled by exiting
39** the process in exactly the same way that xalloc() in Sendmail 8.10
40** exits the process when it fails due to lack of memory:
41** we call syserr with a message beginning with "!".
42**
43** Parameters:
44** exc -- exception which is terminating this process
45**
46** Returns:
47** none
48*/
49
50void
51fatal_error(exc)
52 SM_EXC_T *exc;
53{
54 static char buf[256];
55 SM_FILE_T f;
56
57 /*
58 ** This function may be called when the heap is exhausted.
59 ** The following code writes the message for 'exc' into our
60 ** static buffer without allocating memory or raising exceptions.
61 */
62
63 sm_strio_init(&f, buf, sizeof(buf));
64 sm_exc_write(exc, &f);
65 (void) sm_io_flush(&f, SM_TIME_DEFAULT);
66
67 /*
68 ** Terminate the process after logging an error and cleaning up.
69 ** Problems:
70 ** - syserr decides what class of error this is by looking at errno.
71 ** That's no good; we should look at the exc structure.
72 ** - The cleanup code should be moved out of syserr
73 ** and into individual exception handlers
74 ** that are part of the module they clean up after.
75 */
76
77 errno = ENOMEM;
78 syserr("!%s", buf);
79}
80
81/*
82** SYSERR -- Print error message.
83**
21** SYSERR -- Print error message.
22**
84** Prints an error message via sm_io_printf to the diagnostic output.
23** Prints an error message via printf to the diagnostic output.
85**
86** If the first character of the syserr message is `!' it will
87** log this as an ALERT message and exit immediately. This can
88** leave queue files in an indeterminate state, so it should not
89** be used lightly.
90**
24**
25** If the first character of the syserr message is `!' it will
26** log this as an ALERT message and exit immediately. This can
27** leave queue files in an indeterminate state, so it should not
28** be used lightly.
29**
91** If the first character of the syserr message is '!' or '@'
92** then syserr knows that the process is about to be terminated,
93** so the SMTP reply code defaults to 421. Otherwise, the
94** reply code defaults to 451 or 554, depending on errno.
95**
96** Parameters:
30** Parameters:
97** fmt -- the format string. An optional '!', '@', or '+',
98** followed by an optional three-digit SMTP
99** reply code, followed by message text.
31** fmt -- the format string. If it does not begin with
32** a three-digit SMTP reply code, either 554 or
33** 451 is assumed depending on whether errno
34** is set.
100** (others) -- parameters
101**
102** Returns:
103** none
35** (others) -- parameters
36**
37** Returns:
38** none
104** Raises E:mta.quickabort if QuickAbort is set.
39** Through TopFrame if QuickAbort is set.
105**
106** Side Effects:
107** increments Errors.
108** sets ExitStat.
109*/
110
40**
41** Side Effects:
42** increments Errors.
43** sets ExitStat.
44*/
45
111char MsgBuf[BUFSIZ*2]; /* text of most recent message */
112static char HeldMessageBuf[sizeof(MsgBuf)]; /* for held messages */
46char MsgBuf[BUFSIZ*2]; /* text of most recent message */
47char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */
113
48
49extern void putoutmsg __P((char *, bool, bool));
50extern void puterrmsg __P((char *));
51static void fmtmsg __P((char *, const char *, const char *, int, const char *, va_list));
52
114#if NAMED_BIND && !defined(NO_DATA)
115# define NO_DATA NO_ADDRESS
53#if NAMED_BIND && !defined(NO_DATA)
54# define NO_DATA NO_ADDRESS
116#endif /* NAMED_BIND && !defined(NO_DATA) */
55#endif
117
118void
119/*VARARGS1*/
120#ifdef __STDC__
121syserr(const char *fmt, ...)
56
57void
58/*VARARGS1*/
59#ifdef __STDC__
60syserr(const char *fmt, ...)
122#else /* __STDC__ */
61#else
123syserr(fmt, va_alist)
124 const char *fmt;
125 va_dcl
62syserr(fmt, va_alist)
63 const char *fmt;
64 va_dcl
126#endif /* __STDC__ */
65#endif
127{
128 register char *p;
66{
67 register char *p;
129 int save_errno = errno;
130 bool panic, exiting, keep;
131 char *user;
132 char *enhsc;
133 char *errtxt;
68 int olderrno = errno;
69 bool panic;
70 char *uname;
134 struct passwd *pw;
135 char ubuf[80];
71 struct passwd *pw;
72 char ubuf[80];
136 SM_VA_LOCAL_DECL
73 VA_LOCAL_DECL
137
74
138 panic = exiting = keep = false;
139 switch (*fmt)
75 panic = *fmt == '!';
76 if (panic)
140 {
77 {
141 case '!':
142 ++fmt;
143 panic = exiting = true;
144 break;
145 case '@':
146 ++fmt;
147 exiting = true;
148 break;
149 case '+':
150 ++fmt;
151 keep = true;
152 break;
153 default:
154 break;
78 fmt++;
79 HoldErrs = FALSE;
155 }
156
157 /* format and output the error message */
80 }
81
82 /* format and output the error message */
158 if (exiting)
159 {
160 /*
161 ** Since we are terminating the process,
162 ** we are aborting the entire SMTP session,
163 ** rather than just the current transaction.
164 */
165
166 p = "421";
167 enhsc = "4.0.0";
168 }
169 else if (save_errno == 0)
170 {
83 if (olderrno == 0)
171 p = "554";
84 p = "554";
172 enhsc = "5.0.0";
173 }
174 else
85 else
175 {
176 p = "451";
86 p = "451";
177 enhsc = "4.0.0";
178 }
179 SM_VA_START(ap, fmt);
180 errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap);
181 SM_VA_END(ap);
87 VA_START(fmt);
88 fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
89 VA_END;
182 puterrmsg(MsgBuf);
183
184 /* save this message for mailq printing */
90 puterrmsg(MsgBuf);
91
92 /* save this message for mailq printing */
185 if (!panic && CurEnv != NULL && (!keep || CurEnv->e_message == NULL))
93 if (!panic && CurEnv != NULL)
186 {
94 {
187 char *nmsg = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
188
189 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
190 sm_free(CurEnv->e_message);
191 CurEnv->e_message = nmsg;
95 if (CurEnv->e_message != NULL)
96 free(CurEnv->e_message);
97 CurEnv->e_message = newstr(MsgBuf + 4);
192 }
193
194 /* determine exit status if not already set */
195 if (ExitStat == EX_OK)
196 {
98 }
99
100 /* determine exit status if not already set */
101 if (ExitStat == EX_OK)
102 {
197 if (save_errno == 0)
103 if (olderrno == 0)
198 ExitStat = EX_SOFTWARE;
199 else
200 ExitStat = EX_OSERR;
201 if (tTd(54, 1))
104 ExitStat = EX_SOFTWARE;
105 else
106 ExitStat = EX_OSERR;
107 if (tTd(54, 1))
202 sm_dprintf("syserr: ExitStat = %d\n", ExitStat);
108 printf("syserr: ExitStat = %d\n", ExitStat);
203 }
204
109 }
110
205 pw = sm_getpwuid(RealUid);
111 pw = sm_getpwuid(getuid());
206 if (pw != NULL)
112 if (pw != NULL)
207 user = pw->pw_name;
113 uname = pw->pw_name;
208 else
209 {
114 else
115 {
210 user = ubuf;
211 (void) sm_snprintf(ubuf, sizeof(ubuf), "UID%d", (int) RealUid);
116 uname = ubuf;
117 snprintf(ubuf, sizeof ubuf, "UID%d", getuid());
212 }
213
214 if (LogLevel > 0)
215 sm_syslog(panic ? LOG_ALERT : LOG_CRIT,
216 CurEnv == NULL ? NOQID : CurEnv->e_id,
217 "SYSERR(%s): %.900s",
118 }
119
120 if (LogLevel > 0)
121 sm_syslog(panic ? LOG_ALERT : LOG_CRIT,
122 CurEnv == NULL ? NOQID : CurEnv->e_id,
123 "SYSERR(%s): %.900s",
218 user, errtxt);
219 switch (save_errno)
124 uname, &MsgBuf[4]);
125 switch (olderrno)
220 {
221 case EBADF:
222 case ENFILE:
223 case EMFILE:
224 case ENOTTY:
225#ifdef EFBIG
226 case EFBIG:
126 {
127 case EBADF:
128 case ENFILE:
129 case EMFILE:
130 case ENOTTY:
131#ifdef EFBIG
132 case EFBIG:
227#endif /* EFBIG */
133#endif
228#ifdef ESPIPE
229 case ESPIPE:
134#ifdef ESPIPE
135 case ESPIPE:
230#endif /* ESPIPE */
136#endif
231#ifdef EPIPE
232 case EPIPE:
137#ifdef EPIPE
138 case EPIPE:
233#endif /* EPIPE */
139#endif
234#ifdef ENOBUFS
235 case ENOBUFS:
140#ifdef ENOBUFS
141 case ENOBUFS:
236#endif /* ENOBUFS */
142#endif
237#ifdef ESTALE
238 case ESTALE:
143#ifdef ESTALE
144 case ESTALE:
239#endif /* ESTALE */
240 printopenfds(true);
241 mci_dump_all(smioout, true);
145#endif
146 printopenfds(TRUE);
147 mci_dump_all(TRUE);
242 break;
243 }
244 if (panic)
245 {
148 break;
149 }
150 if (panic)
151 {
246#if XLA
152#ifdef XLA
247 xla_all_end();
153 xla_all_end();
248#endif /* XLA */
249 sync_queue_time();
154#endif
250 if (tTd(0, 1))
251 abort();
252 exit(EX_OSERR);
253 }
254 errno = 0;
255 if (QuickAbort)
155 if (tTd(0, 1))
156 abort();
157 exit(EX_OSERR);
158 }
159 errno = 0;
160 if (QuickAbort)
256 sm_exc_raisenew_x(&EtypeQuickAbort, 2);
161 longjmp(TopFrame, 2);
257}
162}
258/*
163 /*
259** USRERR -- Signal user error.
260**
261** This is much like syserr except it is for user errors.
262**
263** Parameters:
264** fmt -- the format string. If it does not begin with
164** USRERR -- Signal user error.
165**
166** This is much like syserr except it is for user errors.
167**
168** Parameters:
169** fmt -- the format string. If it does not begin with
265** a three-digit SMTP reply code, 550 is assumed.
266** (others) -- sm_io_printf strings
170** a three-digit SMTP reply code, 501 is assumed.
171** (others) -- printf strings
267**
268** Returns:
269** none
172**
173** Returns:
174** none
270** Raises E:mta.quickabort if QuickAbort is set.
175** Through TopFrame if QuickAbort is set.
271**
272** Side Effects:
273** increments Errors.
274*/
275
276/*VARARGS1*/
277void
278#ifdef __STDC__
279usrerr(const char *fmt, ...)
176**
177** Side Effects:
178** increments Errors.
179*/
180
181/*VARARGS1*/
182void
183#ifdef __STDC__
184usrerr(const char *fmt, ...)
280#else /* __STDC__ */
185#else
281usrerr(fmt, va_alist)
282 const char *fmt;
283 va_dcl
186usrerr(fmt, va_alist)
187 const char *fmt;
188 va_dcl
284#endif /* __STDC__ */
189#endif
285{
190{
286 char *enhsc;
287 char *errtxt;
288 SM_VA_LOCAL_DECL
191 VA_LOCAL_DECL
289
192
290 if (fmt[0] == '5' || fmt[0] == '6')
291 enhsc = "5.0.0";
292 else if (fmt[0] == '4' || fmt[0] == '8')
293 enhsc = "4.0.0";
294 else if (fmt[0] == '2')
295 enhsc = "2.0.0";
296 else
297 enhsc = NULL;
298 SM_VA_START(ap, fmt);
299 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap);
300 SM_VA_END(ap);
301
302 if (SuprErrs)
303 return;
304
193 if (SuprErrs)
194 return;
195
305 /* save this message for mailq printing */
306 switch (MsgBuf[0])
307 {
308 case '4':
309 case '8':
310 if (CurEnv->e_message != NULL)
311 break;
196 VA_START(fmt);
197 fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
198 VA_END;
312
199
313 /* FALLTHROUGH */
314
315 case '5':
316 case '6':
317 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
318 sm_free(CurEnv->e_message);
319 if (MsgBuf[0] == '6')
320 {
321 char buf[MAXLINE];
322
323 (void) sm_snprintf(buf, sizeof(buf),
324 "Postmaster warning: %.*s",
325 (int) sizeof(buf) - 22, errtxt);
326 CurEnv->e_message =
327 sm_rpool_strdup_x(CurEnv->e_rpool, buf);
328 }
329 else
330 {
331 CurEnv->e_message =
332 sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
333 }
334 break;
335 }
336
337 puterrmsg(MsgBuf);
338 if (LogLevel > 3 && LogUsrErrs)
339 sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
340 if (QuickAbort)
341 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
342}
343/*
344** USRERRENH -- Signal user error.
345**
346** Same as usrerr but with enhanced status code.
347**
348** Parameters:
349** enhsc -- the enhanced status code.
350** fmt -- the format string. If it does not begin with
351** a three-digit SMTP reply code, 550 is assumed.
352** (others) -- sm_io_printf strings
353**
354** Returns:
355** none
356** Raises E:mta.quickabort if QuickAbort is set.
357**
358** Side Effects:
359** increments Errors.
360*/
361
362/*VARARGS2*/
363void
364#ifdef __STDC__
365usrerrenh(char *enhsc, const char *fmt, ...)
366#else /* __STDC__ */
367usrerrenh(enhsc, fmt, va_alist)
368 char *enhsc;
369 const char *fmt;
370 va_dcl
371#endif /* __STDC__ */
372{
373 char *errtxt;
374 SM_VA_LOCAL_DECL
375
376 if (enhsc == NULL || *enhsc == '\0')
377 {
378 if (fmt[0] == '5' || fmt[0] == '6')
379 enhsc = "5.0.0";
380 else if (fmt[0] == '4' || fmt[0] == '8')
381 enhsc = "4.0.0";
382 else if (fmt[0] == '2')
383 enhsc = "2.0.0";
384 }
385 SM_VA_START(ap, fmt);
386 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap);
387 SM_VA_END(ap);
388
389 if (SuprErrs)
390 return;
391
392 /* save this message for mailq printing */
393 switch (MsgBuf[0])
394 {
395 case '4':
396 case '8':
397 if (CurEnv->e_message != NULL)
398 break;
399
200 /* save this message for mailq printing */
201 switch (MsgBuf[0])
202 {
203 case '4':
204 case '8':
205 if (CurEnv->e_message != NULL)
206 break;
207
400 /* FALLTHROUGH */
208 /* fall through.... */
401
402 case '5':
403 case '6':
209
210 case '5':
211 case '6':
404 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
405 sm_free(CurEnv->e_message);
212 if (CurEnv->e_message != NULL)
213 free(CurEnv->e_message);
406 if (MsgBuf[0] == '6')
407 {
408 char buf[MAXLINE];
409
214 if (MsgBuf[0] == '6')
215 {
216 char buf[MAXLINE];
217
410 (void) sm_snprintf(buf, sizeof(buf),
411 "Postmaster warning: %.*s",
412 (int) sizeof(buf) - 22, errtxt);
413 CurEnv->e_message =
414 sm_rpool_strdup_x(CurEnv->e_rpool, buf);
218 snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
219 sizeof buf - 22, MsgBuf + 4);
220 CurEnv->e_message = newstr(buf);
415 }
416 else
417 {
221 }
222 else
223 {
418 CurEnv->e_message =
419 sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
224 CurEnv->e_message = newstr(MsgBuf + 4);
420 }
421 break;
422 }
423
424 puterrmsg(MsgBuf);
225 }
226 break;
227 }
228
229 puterrmsg(MsgBuf);
230
425 if (LogLevel > 3 && LogUsrErrs)
231 if (LogLevel > 3 && LogUsrErrs)
426 sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
232 sm_syslog(LOG_NOTICE, CurEnv->e_id,
233 "%.900s",
234 &MsgBuf[4]);
235
427 if (QuickAbort)
236 if (QuickAbort)
428 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
237 longjmp(TopFrame, 1);
429}
238}
430
431/*
239 /*
432** MESSAGE -- print message (not necessarily an error)
433**
434** Parameters:
240** MESSAGE -- print message (not necessarily an error)
241**
242** Parameters:
435** msg -- the message (sm_io_printf fmt) -- it can begin with
243** msg -- the message (printf fmt) -- it can begin with
436** an SMTP reply code. If not, 050 is assumed.
244** an SMTP reply code. If not, 050 is assumed.
437** (others) -- sm_io_printf arguments
245** (others) -- printf arguments
438**
439** Returns:
440** none
441**
442** Side Effects:
443** none.
444*/
445
446/*VARARGS1*/
447void
448#ifdef __STDC__
449message(const char *msg, ...)
246**
247** Returns:
248** none
249**
250** Side Effects:
251** none.
252*/
253
254/*VARARGS1*/
255void
256#ifdef __STDC__
257message(const char *msg, ...)
450#else /* __STDC__ */
258#else
451message(msg, va_alist)
452 const char *msg;
453 va_dcl
259message(msg, va_alist)
260 const char *msg;
261 va_dcl
454#endif /* __STDC__ */
262#endif
455{
263{
456 char *errtxt;
457 SM_VA_LOCAL_DECL
264 VA_LOCAL_DECL
458
459 errno = 0;
265
266 errno = 0;
460 SM_VA_START(ap, msg);
461 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap);
462 SM_VA_END(ap);
463 putoutmsg(MsgBuf, false, false);
267 VA_START(msg);
268 fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
269 VA_END;
270 putoutmsg(MsgBuf, FALSE, FALSE);
464
465 /* save this message for mailq printing */
466 switch (MsgBuf[0])
467 {
468 case '4':
469 case '8':
470 if (CurEnv->e_message != NULL)
471 break;
271
272 /* save this message for mailq printing */
273 switch (MsgBuf[0])
274 {
275 case '4':
276 case '8':
277 if (CurEnv->e_message != NULL)
278 break;
472 /* FALLTHROUGH */
279 /* fall through.... */
473
474 case '5':
280
281 case '5':
475 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
476 sm_free(CurEnv->e_message);
477 CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
478 break;
479 }
480}
481
482#if _FFR_PROXY
483/*
484** EMESSAGE -- print message (not necessarily an error)
485** (same as message() but requires reply code and enhanced status code)
486**
487** Parameters:
488** replycode -- SMTP reply code.
489** enhsc -- enhanced status code.
490** msg -- the message (sm_io_printf fmt) -- it can begin with
491** an SMTP reply code. If not, 050 is assumed.
492** (others) -- sm_io_printf arguments
493**
494** Returns:
495** none
496**
497** Side Effects:
498** none.
499*/
500
501/*VARARGS3*/
502void
503# ifdef __STDC__
504emessage(const char *replycode, const char *enhsc, const char *msg, ...)
505# else /* __STDC__ */
506emessage(replycode, enhsc, msg, va_alist)
507 const char *replycode;
508 const char *enhsc;
509 const char *msg;
510 va_dcl
511# endif /* __STDC__ */
512{
513 char *errtxt;
514 SM_VA_LOCAL_DECL
515
516 errno = 0;
517 SM_VA_START(ap, msg);
518 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, replycode, enhsc, 0, msg, ap);
519 SM_VA_END(ap);
520 putoutmsg(MsgBuf, false, false);
521
522 /* save this message for mailq printing */
523 switch (MsgBuf[0])
524 {
525 case '4':
526 case '8':
527 if (CurEnv->e_message != NULL)
282 if (CurEnv->e_message != NULL)
528 break;
529 /* FALLTHROUGH */
530
531 case '5':
532 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
533 sm_free(CurEnv->e_message);
534 CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
283 free(CurEnv->e_message);
284 CurEnv->e_message = newstr(MsgBuf + 4);
535 break;
536 }
537}
285 break;
286 }
287}
538
539/*
540** EXTSC -- check and extract a status codes
541**
542** Parameters:
543** msg -- string with possible enhanced status code.
544** delim -- delim for enhanced status code.
545** replycode -- pointer to storage for SMTP reply code;
546** must be != NULL and have space for at least
547** 4 characters.
548** enhsc -- pointer to storage for enhanced status code;
549** must be != NULL and have space for at least
550** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3})
551**
552** Returns:
553** -1 -- no SMTP reply code.
554** >=3 -- offset of error text in msg.
555** (<=4 -- no enhanced status code)
556*/
557
558int
559extsc(msg, delim, replycode, enhsc)
560 const char *msg;
561 int delim;
562 char *replycode;
563 char *enhsc;
564{
565 int offset;
566
567 SM_REQUIRE(replycode != NULL);
568 SM_REQUIRE(enhsc != NULL);
569 replycode[0] = '\0';
570 enhsc[0] = '\0';
571 if (msg == NULL)
572 return -1;
573 if (!ISSMTPREPLY(msg))
574 return -1;
575 sm_strlcpy(replycode, msg, 4);
576 if (msg[3] == '\0')
577 return 3;
578 offset = 4;
579 if (isenhsc(msg + 4, delim))
580 offset = extenhsc(msg + 4, delim, enhsc) + 4;
581 return offset;
582}
583#endif /* _FFR_PROXY */
584
585/*
288 /*
586** NMESSAGE -- print message (not necessarily an error)
587**
588** Just like "message" except it never puts the to... tag on.
589**
590** Parameters:
289** NMESSAGE -- print message (not necessarily an error)
290**
291** Just like "message" except it never puts the to... tag on.
292**
293** Parameters:
591** msg -- the message (sm_io_printf fmt) -- if it begins
294** msg -- the message (printf fmt) -- if it begins
592** with a three digit SMTP reply code, that is used,
593** otherwise 050 is assumed.
295** with a three digit SMTP reply code, that is used,
296** otherwise 050 is assumed.
594** (others) -- sm_io_printf arguments
297** (others) -- printf arguments
595**
596** Returns:
597** none
598**
599** Side Effects:
600** none.
601*/
602
603/*VARARGS1*/
604void
605#ifdef __STDC__
606nmessage(const char *msg, ...)
298**
299** Returns:
300** none
301**
302** Side Effects:
303** none.
304*/
305
306/*VARARGS1*/
307void
308#ifdef __STDC__
309nmessage(const char *msg, ...)
607#else /* __STDC__ */
310#else
608nmessage(msg, va_alist)
609 const char *msg;
610 va_dcl
311nmessage(msg, va_alist)
312 const char *msg;
313 va_dcl
611#endif /* __STDC__ */
314#endif
612{
315{
613 char *errtxt;
614 SM_VA_LOCAL_DECL
316 VA_LOCAL_DECL
615
616 errno = 0;
317
318 errno = 0;
617 SM_VA_START(ap, msg);
618 errtxt = fmtmsg(MsgBuf, (char *) NULL, "050",
619 (char *) NULL, 0, msg, ap);
620 SM_VA_END(ap);
621 putoutmsg(MsgBuf, false, false);
319 VA_START(msg);
320 fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
321 VA_END;
322 putoutmsg(MsgBuf, FALSE, FALSE);
622
623 /* save this message for mailq printing */
624 switch (MsgBuf[0])
625 {
626 case '4':
627 case '8':
628 if (CurEnv->e_message != NULL)
629 break;
323
324 /* save this message for mailq printing */
325 switch (MsgBuf[0])
326 {
327 case '4':
328 case '8':
329 if (CurEnv->e_message != NULL)
330 break;
630 /* FALLTHROUGH */
331 /* fall through.... */
631
632 case '5':
332
333 case '5':
633 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
634 sm_free(CurEnv->e_message);
635 CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
334 if (CurEnv->e_message != NULL)
335 free(CurEnv->e_message);
336 CurEnv->e_message = newstr(MsgBuf + 4);
636 break;
637 }
638}
337 break;
338 }
339}
639/*
340 /*
640** PUTOUTMSG -- output error message to transcript and channel
641**
642** Parameters:
643** msg -- message to output (in SMTP format).
341** PUTOUTMSG -- output error message to transcript and channel
342**
343** Parameters:
344** msg -- message to output (in SMTP format).
644** holdmsg -- if true, don't output a copy of the message to
345** holdmsg -- if TRUE, don't output a copy of the message to
645** our output channel.
346** our output channel.
646** heldmsg -- if true, this is a previously held message;
347** heldmsg -- if TRUE, this is a previously held message;
647** don't log it to the transcript file.
648**
649** Returns:
650** none.
651**
652** Side Effects:
653** Outputs msg to the transcript.
654** If appropriate, outputs it to the channel.
655** Deletes SMTP reply code number as appropriate.
656*/
657
348** don't log it to the transcript file.
349**
350** Returns:
351** none.
352**
353** Side Effects:
354** Outputs msg to the transcript.
355** If appropriate, outputs it to the channel.
356** Deletes SMTP reply code number as appropriate.
357*/
358
658static void
359void
659putoutmsg(msg, holdmsg, heldmsg)
660 char *msg;
661 bool holdmsg;
662 bool heldmsg;
663{
664 char msgcode = msg[0];
360putoutmsg(msg, holdmsg, heldmsg)
361 char *msg;
362 bool holdmsg;
363 bool heldmsg;
364{
365 char msgcode = msg[0];
665 char *errtxt = msg;
666 char *id;
667
668 /* display for debugging */
669 if (tTd(54, 8))
366
367 /* display for debugging */
368 if (tTd(54, 8))
670 sm_dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
369 printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
671 heldmsg ? " (held)" : "");
672
673 /* map warnings to something SMTP can handle */
674 if (msgcode == '6')
675 msg[0] = '5';
676 else if (msgcode == '8')
677 msg[0] = '4';
370 heldmsg ? " (held)" : "");
371
372 /* map warnings to something SMTP can handle */
373 if (msgcode == '6')
374 msg[0] = '5';
375 else if (msgcode == '8')
376 msg[0] = '4';
678 id = (CurEnv != NULL) ? CurEnv->e_id : NULL;
679
680 /* output to transcript if serious */
681 if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&
682 strchr("45", msg[0]) != NULL)
377
378 /* output to transcript if serious */
379 if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&
380 strchr("45", msg[0]) != NULL)
683 (void) sm_io_fprintf(CurEnv->e_xfp, SM_TIME_DEFAULT, "%s\n",
684 msg);
381 fprintf(CurEnv->e_xfp, "%s\n", msg);
685
382
686 if (LogLevel > 14 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
687 sm_syslog(LOG_INFO, id,
688 "--- %s%s%s", msg, holdmsg ? " (hold)" : "",
689 heldmsg ? " (held)" : "");
383 if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
384 sm_syslog(LOG_INFO, CurEnv->e_id,
385 "--> %s%s",
386 msg, holdmsg ? " (held)" : "");
690
691 if (msgcode == '8')
692 msg[0] = '0';
693
694 /* output to channel if appropriate */
695 if (!Verbose && msg[0] == '0')
696 return;
697 if (holdmsg)
698 {
699 /* save for possible future display */
700 msg[0] = msgcode;
387
388 if (msgcode == '8')
389 msg[0] = '0';
390
391 /* output to channel if appropriate */
392 if (!Verbose && msg[0] == '0')
393 return;
394 if (holdmsg)
395 {
396 /* save for possible future display */
397 msg[0] = msgcode;
701 if (HeldMessageBuf[0] == '5' && msgcode == '4')
702 return;
703 (void) sm_strlcpy(HeldMessageBuf, msg, sizeof(HeldMessageBuf));
398 snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg);
704 return;
705 }
706
399 return;
400 }
401
707 (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
402 (void) fflush(stdout);
708
709 if (OutChannel == NULL)
710 return;
403
404 if (OutChannel == NULL)
405 return;
711
712 /* find actual text of error (after SMTP status codes) */
713 if (ISSMTPREPLY(errtxt))
714 {
715 int l;
716
717 errtxt += 4;
718 l = isenhsc(errtxt, ' ');
719 if (l <= 0)
720 l = isenhsc(errtxt, '\0');
721 if (l > 0)
722 errtxt += l + 1;
723 }
724
406
725 /* if DisConnected, OutChannel now points to the transcript */
726 if (!DisConnected &&
727 (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
407 /* if DisConnected, OutChannel now points to the transcript */
408 if (!DisConnected &&
409 (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
728 (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\r\n",
729 msg);
410 fprintf(OutChannel, "%s\r\n", msg);
730 else
411 else
731 (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\n",
732 errtxt);
412 fprintf(OutChannel, "%s\n", &msg[4]);
733 if (TrafficLogFile != NULL)
413 if (TrafficLogFile != NULL)
734 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT,
735 "%05d >>> %s\n", (int) CurrentPid,
736 (OpMode == MD_SMTP || OpMode == MD_DAEMON)
737 ? msg : errtxt);
738#if !PIPELINING
739 /* XXX can't flush here for SMTP pipelining */
414 fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(),
415 (OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
740 if (msg[3] == ' ')
416 if (msg[3] == ' ')
741 (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
742 if (!sm_io_error(OutChannel) || DisConnected)
417 (void) fflush(OutChannel);
418 if (!ferror(OutChannel) || DisConnected)
743 return;
744
745 /*
746 ** Error on output -- if reporting lost channel, just ignore it.
747 ** Also, ignore errors from QUIT response (221 message) -- some
748 ** rude servers don't read result.
749 */
750
419 return;
420
421 /*
422 ** Error on output -- if reporting lost channel, just ignore it.
423 ** Also, ignore errors from QUIT response (221 message) -- some
424 ** rude servers don't read result.
425 */
426
751 if (InChannel == NULL || sm_io_eof(InChannel) ||
752 sm_io_error(InChannel) || strncmp(msg, "221", 3) == 0)
427 if (InChannel == NULL || feof(InChannel) || ferror(InChannel) ||
428 strncmp(msg, "221", 3) == 0)
753 return;
754
755 /* can't call syserr, 'cause we are using MsgBuf */
429 return;
430
431 /* can't call syserr, 'cause we are using MsgBuf */
756 HoldErrs = true;
432 HoldErrs = TRUE;
757 if (LogLevel > 0)
433 if (LogLevel > 0)
758 sm_syslog(LOG_CRIT, id,
759 "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
760 CURHOSTNAME,
761 shortenstring(msg, MAXSHORTSTR), sm_errstring(errno));
762#endif /* !PIPELINING */
434 sm_syslog(LOG_CRIT, CurEnv->e_id,
435 "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
436 CurHostName == NULL ? "NO-HOST" : CurHostName,
437 shortenstring(msg, MAXSHORTSTR), errstring(errno));
763}
438}
764/*
439 /*
765** PUTERRMSG -- like putoutmsg, but does special processing for error messages
766**
767** Parameters:
768** msg -- the message to output.
769**
770** Returns:
771** none.
772**
773** Side Effects:
774** Sets the fatal error bit in the envelope as appropriate.
775*/
776
440** PUTERRMSG -- like putoutmsg, but does special processing for error messages
441**
442** Parameters:
443** msg -- the message to output.
444**
445** Returns:
446** none.
447**
448** Side Effects:
449** Sets the fatal error bit in the envelope as appropriate.
450*/
451
777static void
452void
778puterrmsg(msg)
779 char *msg;
780{
781 char msgcode = msg[0];
782
783 /* output the message as usual */
453puterrmsg(msg)
454 char *msg;
455{
456 char msgcode = msg[0];
457
458 /* output the message as usual */
784 putoutmsg(msg, HoldErrs, false);
459 putoutmsg(msg, HoldErrs, FALSE);
785
786 /* be careful about multiple error messages */
787 if (OnlyOneError)
460
461 /* be careful about multiple error messages */
462 if (OnlyOneError)
788 HoldErrs = true;
463 HoldErrs = TRUE;
789
790 /* signal the error */
791 Errors++;
792
793 if (CurEnv == NULL)
794 return;
464
465 /* signal the error */
466 Errors++;
467
468 if (CurEnv == NULL)
469 return;
795
470
796 if (msgcode == '6')
797 {
798 /* notify the postmaster */
799 CurEnv->e_flags |= EF_PM_NOTIFY;
800 }
801 else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
802 {
803 /* mark long-term fatal errors */
804 CurEnv->e_flags |= EF_FATALERRS;
805 }
806}
471 if (msgcode == '6')
472 {
473 /* notify the postmaster */
474 CurEnv->e_flags |= EF_PM_NOTIFY;
475 }
476 else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
477 {
478 /* mark long-term fatal errors */
479 CurEnv->e_flags |= EF_FATALERRS;
480 }
481}
807/*
808** ISENHSC -- check whether a string contains an enhanced status code
809**
810** Parameters:
811** s -- string with possible enhanced status code.
812** delim -- delim for enhanced status code.
813**
814** Returns:
815** 0 -- no enhanced status code.
816** >4 -- length of enhanced status code.
817**
818** Side Effects:
819** none.
820*/
821int
822isenhsc(s, delim)
823 const char *s;
824 int delim;
825{
826 int l, h;
827
828 if (s == NULL)
829 return 0;
830 if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
831 return 0;
832 h = 0;
833 l = 2;
834 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
835 ++h;
836 if (h == 0 || s[l + h] != '.')
837 return 0;
838 l += h + 1;
839 h = 0;
840 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
841 ++h;
842 if (h == 0 || s[l + h] != delim)
843 return 0;
844 return l + h;
845}
846/*
847** EXTENHSC -- check and extract an enhanced status code
848**
849** Parameters:
850** s -- string with possible enhanced status code.
851** delim -- delim for enhanced status code.
852** e -- pointer to storage for enhanced status code.
853** must be != NULL and have space for at least
854** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3})
855**
856** Returns:
857** 0 -- no enhanced status code.
858** >4 -- length of enhanced status code.
859**
860** Side Effects:
861** fills e with enhanced status code.
862*/
863
864int
865extenhsc(s, delim, e)
866 const char *s;
867 int delim;
868 char *e;
869{
870 int l, h;
871
872 if (s == NULL)
873 return 0;
874 if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
875 return 0;
876 h = 0;
877 l = 2;
878 e[0] = s[0];
879 e[1] = '.';
880 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
881 {
882 e[l + h] = s[l + h];
883 ++h;
884 }
885 if (h == 0 || s[l + h] != '.')
886 return 0;
887 e[l + h] = '.';
888 l += h + 1;
889 h = 0;
890 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
891 {
892 e[l + h] = s[l + h];
893 ++h;
894 }
895 if (h == 0 || s[l + h] != delim)
896 return 0;
897 e[l + h] = '\0';
898 return l + h;
899}
900/*
482 /*
901** FMTMSG -- format a message into buffer.
902**
903** Parameters:
483** FMTMSG -- format a message into buffer.
484**
485** Parameters:
904** eb -- error buffer to get result -- MUST BE MsgBuf.
486** eb -- error buffer to get result.
905** to -- the recipient tag for this message.
487** to -- the recipient tag for this message.
906** num -- default three digit SMTP reply code.
907** enhsc -- enhanced status code.
488** num -- arpanet error number.
908** en -- the error number to display.
909** fmt -- format of string.
489** en -- the error number to display.
490** fmt -- format of string.
910** ap -- arguments for fmt.
491** a, b, c, d, e -- arguments.
911**
912** Returns:
492**
493** Returns:
913** pointer to error text beyond status codes.
494** none.
914**
915** Side Effects:
916** none.
917*/
918
495**
496** Side Effects:
497** none.
498*/
499
919static char *
920fmtmsg(eb, to, num, enhsc, eno, fmt, ap)
500static void
501fmtmsg(eb, to, num, eno, fmt, ap)
921 register char *eb;
922 const char *to;
923 const char *num;
502 register char *eb;
503 const char *to;
504 const char *num;
924 const char *enhsc;
925 int eno;
926 const char *fmt;
505 int eno;
506 const char *fmt;
927 SM_VA_LOCAL_DECL
507 va_list ap;
928{
929 char del;
930 int l;
508{
509 char del;
510 int l;
931 int spaceleft = sizeof(MsgBuf);
932 char *errtxt;
511 int spaceleft = sizeof MsgBuf;
933
934 /* output the reply code */
512
513 /* output the reply code */
935 if (ISSMTPCODE(fmt))
514 if (isascii(fmt[0]) && isdigit(fmt[0]) &&
515 isascii(fmt[1]) && isdigit(fmt[1]) &&
516 isascii(fmt[2]) && isdigit(fmt[2]))
936 {
937 num = fmt;
938 fmt += 4;
939 }
940 if (num[3] == '-')
941 del = '-';
942 else
943 del = ' ';
517 {
518 num = fmt;
519 fmt += 4;
520 }
521 if (num[3] == '-')
522 del = '-';
523 else
524 del = ' ';
944 if (SoftBounce && num[0] == '5')
945 {
946 /* replace 5 by 4 */
947 (void) sm_snprintf(eb, spaceleft, "4%2.2s%c", num + 1, del);
948 }
949 else
950 (void) sm_snprintf(eb, spaceleft, "%3.3s%c", num, del);
525 (void) snprintf(eb, spaceleft, "%3.3s%c", num, del);
951 eb += 4;
952 spaceleft -= 4;
953
526 eb += 4;
527 spaceleft -= 4;
528
954 if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4)
955 {
956 /* copy enh.status code including trailing blank */
957 l++;
958 (void) sm_strlcpy(eb, fmt, l + 1);
959 eb += l;
960 spaceleft -= l;
961 fmt += l;
962 }
963 else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4)
964 {
965 /* copy enh.status code */
966 (void) sm_strlcpy(eb, enhsc, l + 1);
967 eb[l] = ' ';
968 eb[++l] = '\0';
969 eb += l;
970 spaceleft -= l;
971 }
972 if (SoftBounce && eb[-l] == '5')
973 {
974 /* replace 5 by 4 */
975 eb[-l] = '4';
976 }
977 errtxt = eb;
978
979 /* output the file name and line number */
980 if (FileName != NULL)
981 {
529 /* output the file name and line number */
530 if (FileName != NULL)
531 {
982 (void) sm_snprintf(eb, spaceleft, "%s: line %d: ",
983 shortenstring(FileName, 83), LineNumber);
532 (void) snprintf(eb, spaceleft, "%s: line %d: ",
533 shortenstring(FileName, 83), LineNumber);
984 eb += (l = strlen(eb));
985 spaceleft -= l;
986 }
987
534 eb += (l = strlen(eb));
535 spaceleft -= l;
536 }
537
988 /*
989 ** output the "to" address only if it is defined and one of the
990 ** following codes is used:
991 ** 050 internal notices, e.g., alias expansion
992 ** 250 Ok
993 ** 252 Cannot VRFY user, but will accept message and attempt delivery
994 ** 450 Requested mail action not taken: mailbox unavailable
995 ** 550 Requested action not taken: mailbox unavailable
996 ** 553 Requested action not taken: mailbox name not allowed
997 **
998 ** Notice: this still isn't "the right thing", this code shouldn't
999 ** (indirectly) depend on CurEnv->e_to.
1000 */
1001
538 /* output the "to" person */
1002 if (to != NULL && to[0] != '\0' &&
539 if (to != NULL && to[0] != '\0' &&
1003 (strncmp(num, "050", 3) == 0 ||
1004 strncmp(num, "250", 3) == 0 ||
1005 strncmp(num, "252", 3) == 0 ||
1006 strncmp(num, "450", 3) == 0 ||
1007 strncmp(num, "550", 3) == 0 ||
1008 strncmp(num, "553", 3) == 0))
540 strncmp(num, "551", 3) != 0 &&
541 strncmp(num, "251", 3) != 0)
1009 {
542 {
1010 (void) sm_strlcpyn(eb, spaceleft, 2,
1011 shortenstring(to, MAXSHORTSTR), "... ");
543 (void) snprintf(eb, spaceleft, "%s... ",
544 shortenstring(to, MAXSHORTSTR));
1012 spaceleft -= strlen(eb);
1013 while (*eb != '\0')
1014 *eb++ &= 0177;
1015 }
1016
1017 /* output the message */
545 spaceleft -= strlen(eb);
546 while (*eb != '\0')
547 *eb++ &= 0177;
548 }
549
550 /* output the message */
1018 (void) sm_vsnprintf(eb, spaceleft, fmt, ap);
551 (void) vsnprintf(eb, spaceleft, fmt, ap);
1019 spaceleft -= strlen(eb);
1020 while (*eb != '\0')
1021 *eb++ &= 0177;
1022
1023 /* output the error code, if any */
1024 if (eno != 0)
552 spaceleft -= strlen(eb);
553 while (*eb != '\0')
554 *eb++ &= 0177;
555
556 /* output the error code, if any */
557 if (eno != 0)
1025 (void) sm_strlcpyn(eb, spaceleft, 2, ": ", sm_errstring(eno));
1026
1027 return errtxt;
558 (void) snprintf(eb, spaceleft, ": %s", errstring(eno));
1028}
559}
1029/*
560 /*
1030** BUFFER_ERRORS -- arrange to buffer future error messages
1031**
1032** Parameters:
1033** none
1034**
1035** Returns:
1036** none.
1037*/
1038
1039void
1040buffer_errors()
1041{
1042 HeldMessageBuf[0] = '\0';
561** BUFFER_ERRORS -- arrange to buffer future error messages
562**
563** Parameters:
564** none
565**
566** Returns:
567** none.
568*/
569
570void
571buffer_errors()
572{
573 HeldMessageBuf[0] = '\0';
1043 HoldErrs = true;
574 HoldErrs = TRUE;
1044}
575}
1045/*
576 /*
1046** FLUSH_ERRORS -- flush the held error message buffer
1047**
1048** Parameters:
1049** print -- if set, print the message, otherwise just
1050** delete it.
1051**
1052** Returns:
1053** none.
1054*/
1055
1056void
1057flush_errors(print)
1058 bool print;
1059{
1060 if (print && HeldMessageBuf[0] != '\0')
577** FLUSH_ERRORS -- flush the held error message buffer
578**
579** Parameters:
580** print -- if set, print the message, otherwise just
581** delete it.
582**
583** Returns:
584** none.
585*/
586
587void
588flush_errors(print)
589 bool print;
590{
591 if (print && HeldMessageBuf[0] != '\0')
1061 putoutmsg(HeldMessageBuf, false, true);
592 putoutmsg(HeldMessageBuf, FALSE, TRUE);
1062 HeldMessageBuf[0] = '\0';
593 HeldMessageBuf[0] = '\0';
1063 HoldErrs = false;
594 HoldErrs = FALSE;
1064}
595}
1065/*
1066** SM_ERRSTRING -- return string description of error code
596 /*
597** ERRSTRING -- return string description of error code
1067**
1068** Parameters:
1069** errnum -- the error number to translate
1070**
1071** Returns:
1072** A string description of errnum.
1073**
1074** Side Effects:
1075** none.
1076*/
1077
1078const char *
598**
599** Parameters:
600** errnum -- the error number to translate
601**
602** Returns:
603** A string description of errnum.
604**
605** Side Effects:
606** none.
607*/
608
609const char *
1079sm_errstring(errnum)
610errstring(errnum)
1080 int errnum;
1081{
1082 char *dnsmsg;
1083 char *bp;
1084 static char buf[MAXLINE];
611 int errnum;
612{
613 char *dnsmsg;
614 char *bp;
615 static char buf[MAXLINE];
1085#if HASSTRERROR
1086 char *err;
1087 char errbuf[30];
1088#endif /* HASSTRERROR */
1089#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
616# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
1090 extern char *sys_errlist[];
1091 extern int sys_nerr;
617 extern char *sys_errlist[];
618 extern int sys_nerr;
1092#endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */
619# endif
620# if SMTP
621 extern char *SmtpPhase;
622# endif /* SMTP */
1093
1094 /*
1095 ** Handle special network error codes.
1096 **
1097 ** These are 4.2/4.3bsd specific; they should be in daemon.c.
1098 */
1099
1100 dnsmsg = NULL;
1101 switch (errnum)
1102 {
623
624 /*
625 ** Handle special network error codes.
626 **
627 ** These are 4.2/4.3bsd specific; they should be in daemon.c.
628 */
629
630 dnsmsg = NULL;
631 switch (errnum)
632 {
633# if defined(DAEMON) && defined(ETIMEDOUT)
1103 case ETIMEDOUT:
1104 case ECONNRESET:
1105 bp = buf;
1106#if HASSTRERROR
634 case ETIMEDOUT:
635 case ECONNRESET:
636 bp = buf;
637#if HASSTRERROR
1107 err = strerror(errnum);
1108 if (err == NULL)
1109 {
1110 (void) sm_snprintf(errbuf, sizeof(errbuf),
1111 "Error %d", errnum);
1112 err = errbuf;
1113 }
1114 (void) sm_strlcpy(bp, err, SPACELEFT(buf, bp));
1115#else /* HASSTRERROR */
638 snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum));
639#else
1116 if (errnum >= 0 && errnum < sys_nerr)
640 if (errnum >= 0 && errnum < sys_nerr)
1117 (void) sm_strlcpy(bp, sys_errlist[errnum],
1118 SPACELEFT(buf, bp));
641 snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]);
1119 else
642 else
1120 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1121 "Error %d", errnum);
1122#endif /* HASSTRERROR */
643 snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum);
644#endif
1123 bp += strlen(bp);
1124 if (CurHostName != NULL)
1125 {
1126 if (errnum == ETIMEDOUT)
1127 {
645 bp += strlen(bp);
646 if (CurHostName != NULL)
647 {
648 if (errnum == ETIMEDOUT)
649 {
1128 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1129 " with ");
650 snprintf(bp, SPACELEFT(buf, bp), " with ");
1130 bp += strlen(bp);
1131 }
1132 else
1133 {
1134 bp = buf;
651 bp += strlen(bp);
652 }
653 else
654 {
655 bp = buf;
1135 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
656 snprintf(bp, SPACELEFT(buf, bp),
1136 "Connection reset by ");
1137 bp += strlen(bp);
1138 }
657 "Connection reset by ");
658 bp += strlen(bp);
659 }
1139 (void) sm_strlcpy(bp,
1140 shortenstring(CurHostName, MAXSHORTSTR),
1141 SPACELEFT(buf, bp));
660 snprintf(bp, SPACELEFT(buf, bp), "%s",
661 shortenstring(CurHostName, MAXSHORTSTR));
1142 bp += strlen(buf);
1143 }
1144 if (SmtpPhase != NULL)
1145 {
662 bp += strlen(buf);
663 }
664 if (SmtpPhase != NULL)
665 {
1146 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1147 " during %s", SmtpPhase);
666 snprintf(bp, SPACELEFT(buf, bp), " during %s",
667 SmtpPhase);
1148 }
668 }
1149 return buf;
669 return (buf);
1150
1151 case EHOSTDOWN:
1152 if (CurHostName == NULL)
1153 break;
670
671 case EHOSTDOWN:
672 if (CurHostName == NULL)
673 break;
1154 (void) sm_snprintf(buf, sizeof(buf), "Host %s is down",
674 (void) snprintf(buf, sizeof buf, "Host %s is down",
1155 shortenstring(CurHostName, MAXSHORTSTR));
675 shortenstring(CurHostName, MAXSHORTSTR));
1156 return buf;
676 return (buf);
1157
1158 case ECONNREFUSED:
1159 if (CurHostName == NULL)
1160 break;
677
678 case ECONNREFUSED:
679 if (CurHostName == NULL)
680 break;
1161 (void) sm_strlcpyn(buf, sizeof(buf), 2, "Connection refused by ",
681 (void) snprintf(buf, sizeof buf, "Connection refused by %s",
1162 shortenstring(CurHostName, MAXSHORTSTR));
682 shortenstring(CurHostName, MAXSHORTSTR));
1163 return buf;
683 return (buf);
684# endif
1164
685
1165#if NAMED_BIND
686# if NAMED_BIND
1166 case HOST_NOT_FOUND + E_DNSBASE:
1167 dnsmsg = "host not found";
1168 break;
1169
1170 case TRY_AGAIN + E_DNSBASE:
1171 dnsmsg = "host name lookup failure";
1172 break;
1173
1174 case NO_RECOVERY + E_DNSBASE:
1175 dnsmsg = "non-recoverable error";
1176 break;
1177
1178 case NO_DATA + E_DNSBASE:
1179 dnsmsg = "no data known";
1180 break;
687 case HOST_NOT_FOUND + E_DNSBASE:
688 dnsmsg = "host not found";
689 break;
690
691 case TRY_AGAIN + E_DNSBASE:
692 dnsmsg = "host name lookup failure";
693 break;
694
695 case NO_RECOVERY + E_DNSBASE:
696 dnsmsg = "non-recoverable error";
697 break;
698
699 case NO_DATA + E_DNSBASE:
700 dnsmsg = "no data known";
701 break;
1181#endif /* NAMED_BIND */
702# endif
1182
1183 case EPERM:
1184 /* SunOS gives "Not owner" -- this is the POSIX message */
1185 return "Operation not permitted";
1186
1187 /*
1188 ** Error messages used internally in sendmail.
1189 */

--- 22 unchanged lines hidden (view full) ---

1212 case E_SM_FILECHANGE:
1213 return "File changed after open";
1214
1215 case E_SM_WWFILE:
1216 return "World writable file";
1217
1218 case E_SM_GWFILE:
1219 return "Group writable file";
703
704 case EPERM:
705 /* SunOS gives "Not owner" -- this is the POSIX message */
706 return "Operation not permitted";
707
708 /*
709 ** Error messages used internally in sendmail.
710 */

--- 22 unchanged lines hidden (view full) ---

733 case E_SM_FILECHANGE:
734 return "File changed after open";
735
736 case E_SM_WWFILE:
737 return "World writable file";
738
739 case E_SM_GWFILE:
740 return "Group writable file";
1220
1221 case E_SM_GRFILE:
1222 return "Group readable file";
1223
1224 case E_SM_WRFILE:
1225 return "World readable file";
1226 }
1227
1228 if (dnsmsg != NULL)
1229 {
1230 bp = buf;
741 }
742
743 if (dnsmsg != NULL)
744 {
745 bp = buf;
1231 bp += sm_strlcpy(bp, "Name server: ", sizeof(buf));
746 strcpy(bp, "Name server: ");
747 bp += strlen(bp);
1232 if (CurHostName != NULL)
1233 {
748 if (CurHostName != NULL)
749 {
1234 (void) sm_strlcpyn(bp, SPACELEFT(buf, bp), 2,
1235 shortenstring(CurHostName, MAXSHORTSTR), ": ");
750 snprintf(bp, SPACELEFT(buf, bp), "%s: ",
751 shortenstring(CurHostName, MAXSHORTSTR));
1236 bp += strlen(bp);
1237 }
752 bp += strlen(bp);
753 }
1238 (void) sm_strlcpy(bp, dnsmsg, SPACELEFT(buf, bp));
754 snprintf(bp, SPACELEFT(buf, bp), "%s", dnsmsg);
1239 return buf;
1240 }
1241
755 return buf;
756 }
757
1242#if LDAPMAP
1243 if (errnum >= E_LDAPBASE - E_LDAP_SHIM)
1244 return ldap_err2string(errnum - E_LDAPBASE);
1245#endif /* LDAPMAP */
1246
1247#if HASSTRERROR
758#if HASSTRERROR
1248 err = strerror(errnum);
1249 if (err == NULL)
1250 {
1251 (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum);
1252 return buf;
1253 }
1254 return err;
1255#else /* HASSTRERROR */
759 return strerror(errnum);
760#else
1256 if (errnum > 0 && errnum < sys_nerr)
761 if (errnum > 0 && errnum < sys_nerr)
1257 return sys_errlist[errnum];
762 return (sys_errlist[errnum]);
1258
763
1259 (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum);
1260 return buf;
1261#endif /* HASSTRERROR */
764 (void) snprintf(buf, sizeof buf, "Error %d", errnum);
765 return (buf);
766#endif
1262}
767}