1 | /* |
---|
2 | * Copyright (c) 1998 Sendmail, Inc. All rights reserved. |
---|
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 | |
---|
13 | #ifndef lint |
---|
14 | static char sccsid[] = "@(#)err.c 8.74 (Berkeley) 6/4/1998"; |
---|
15 | #endif /* not lint */ |
---|
16 | |
---|
17 | # include "sendmail.h" |
---|
18 | # include <errno.h> |
---|
19 | |
---|
20 | /* |
---|
21 | ** SYSERR -- Print error message. |
---|
22 | ** |
---|
23 | ** Prints an error message via printf to the diagnostic output. |
---|
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 | ** |
---|
30 | ** Parameters: |
---|
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. |
---|
35 | ** (others) -- parameters |
---|
36 | ** |
---|
37 | ** Returns: |
---|
38 | ** none |
---|
39 | ** Through TopFrame if QuickAbort is set. |
---|
40 | ** |
---|
41 | ** Side Effects: |
---|
42 | ** increments Errors. |
---|
43 | ** sets ExitStat. |
---|
44 | */ |
---|
45 | |
---|
46 | char MsgBuf[BUFSIZ*2]; /* text of most recent message */ |
---|
47 | char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */ |
---|
48 | |
---|
49 | extern void putoutmsg __P((char *, bool, bool)); |
---|
50 | extern void puterrmsg __P((char *)); |
---|
51 | static void fmtmsg __P((char *, const char *, const char *, int, const char *, va_list)); |
---|
52 | |
---|
53 | #if NAMED_BIND && !defined(NO_DATA) |
---|
54 | # define NO_DATA NO_ADDRESS |
---|
55 | #endif |
---|
56 | |
---|
57 | void |
---|
58 | /*VARARGS1*/ |
---|
59 | #ifdef __STDC__ |
---|
60 | syserr(const char *fmt, ...) |
---|
61 | #else |
---|
62 | syserr(fmt, va_alist) |
---|
63 | const char *fmt; |
---|
64 | va_dcl |
---|
65 | #endif |
---|
66 | { |
---|
67 | register char *p; |
---|
68 | int olderrno = errno; |
---|
69 | bool panic; |
---|
70 | char *uname; |
---|
71 | struct passwd *pw; |
---|
72 | char ubuf[80]; |
---|
73 | VA_LOCAL_DECL |
---|
74 | |
---|
75 | panic = *fmt == '!'; |
---|
76 | if (panic) |
---|
77 | { |
---|
78 | fmt++; |
---|
79 | HoldErrs = FALSE; |
---|
80 | } |
---|
81 | |
---|
82 | /* format and output the error message */ |
---|
83 | if (olderrno == 0) |
---|
84 | p = "554"; |
---|
85 | else |
---|
86 | p = "451"; |
---|
87 | VA_START(fmt); |
---|
88 | fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap); |
---|
89 | VA_END; |
---|
90 | puterrmsg(MsgBuf); |
---|
91 | |
---|
92 | /* save this message for mailq printing */ |
---|
93 | if (!panic && CurEnv != NULL) |
---|
94 | { |
---|
95 | if (CurEnv->e_message != NULL) |
---|
96 | free(CurEnv->e_message); |
---|
97 | CurEnv->e_message = newstr(MsgBuf + 4); |
---|
98 | } |
---|
99 | |
---|
100 | /* determine exit status if not already set */ |
---|
101 | if (ExitStat == EX_OK) |
---|
102 | { |
---|
103 | if (olderrno == 0) |
---|
104 | ExitStat = EX_SOFTWARE; |
---|
105 | else |
---|
106 | ExitStat = EX_OSERR; |
---|
107 | if (tTd(54, 1)) |
---|
108 | printf("syserr: ExitStat = %d\n", ExitStat); |
---|
109 | } |
---|
110 | |
---|
111 | pw = sm_getpwuid(getuid()); |
---|
112 | if (pw != NULL) |
---|
113 | uname = pw->pw_name; |
---|
114 | else |
---|
115 | { |
---|
116 | uname = ubuf; |
---|
117 | snprintf(ubuf, sizeof ubuf, "UID%d", getuid()); |
---|
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", |
---|
124 | uname, &MsgBuf[4]); |
---|
125 | switch (olderrno) |
---|
126 | { |
---|
127 | case EBADF: |
---|
128 | case ENFILE: |
---|
129 | case EMFILE: |
---|
130 | case ENOTTY: |
---|
131 | #ifdef EFBIG |
---|
132 | case EFBIG: |
---|
133 | #endif |
---|
134 | #ifdef ESPIPE |
---|
135 | case ESPIPE: |
---|
136 | #endif |
---|
137 | #ifdef EPIPE |
---|
138 | case EPIPE: |
---|
139 | #endif |
---|
140 | #ifdef ENOBUFS |
---|
141 | case ENOBUFS: |
---|
142 | #endif |
---|
143 | #ifdef ESTALE |
---|
144 | case ESTALE: |
---|
145 | #endif |
---|
146 | printopenfds(TRUE); |
---|
147 | mci_dump_all(TRUE); |
---|
148 | break; |
---|
149 | } |
---|
150 | if (panic) |
---|
151 | { |
---|
152 | #ifdef XLA |
---|
153 | xla_all_end(); |
---|
154 | #endif |
---|
155 | if (tTd(0, 1)) |
---|
156 | abort(); |
---|
157 | exit(EX_OSERR); |
---|
158 | } |
---|
159 | errno = 0; |
---|
160 | if (QuickAbort) |
---|
161 | longjmp(TopFrame, 2); |
---|
162 | } |
---|
163 | /* |
---|
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 |
---|
170 | ** a three-digit SMTP reply code, 501 is assumed. |
---|
171 | ** (others) -- printf strings |
---|
172 | ** |
---|
173 | ** Returns: |
---|
174 | ** none |
---|
175 | ** Through TopFrame if QuickAbort is set. |
---|
176 | ** |
---|
177 | ** Side Effects: |
---|
178 | ** increments Errors. |
---|
179 | */ |
---|
180 | |
---|
181 | /*VARARGS1*/ |
---|
182 | void |
---|
183 | #ifdef __STDC__ |
---|
184 | usrerr(const char *fmt, ...) |
---|
185 | #else |
---|
186 | usrerr(fmt, va_alist) |
---|
187 | const char *fmt; |
---|
188 | va_dcl |
---|
189 | #endif |
---|
190 | { |
---|
191 | VA_LOCAL_DECL |
---|
192 | |
---|
193 | if (SuprErrs) |
---|
194 | return; |
---|
195 | |
---|
196 | VA_START(fmt); |
---|
197 | fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap); |
---|
198 | VA_END; |
---|
199 | |
---|
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 | |
---|
208 | /* fall through.... */ |
---|
209 | |
---|
210 | case '5': |
---|
211 | case '6': |
---|
212 | if (CurEnv->e_message != NULL) |
---|
213 | free(CurEnv->e_message); |
---|
214 | if (MsgBuf[0] == '6') |
---|
215 | { |
---|
216 | char buf[MAXLINE]; |
---|
217 | |
---|
218 | snprintf(buf, sizeof buf, "Postmaster warning: %.*s", |
---|
219 | sizeof buf - 22, MsgBuf + 4); |
---|
220 | CurEnv->e_message = newstr(buf); |
---|
221 | } |
---|
222 | else |
---|
223 | { |
---|
224 | CurEnv->e_message = newstr(MsgBuf + 4); |
---|
225 | } |
---|
226 | break; |
---|
227 | } |
---|
228 | |
---|
229 | puterrmsg(MsgBuf); |
---|
230 | |
---|
231 | if (LogLevel > 3 && LogUsrErrs) |
---|
232 | sm_syslog(LOG_NOTICE, CurEnv->e_id, |
---|
233 | "%.900s", |
---|
234 | &MsgBuf[4]); |
---|
235 | |
---|
236 | if (QuickAbort) |
---|
237 | longjmp(TopFrame, 1); |
---|
238 | } |
---|
239 | /* |
---|
240 | ** MESSAGE -- print message (not necessarily an error) |
---|
241 | ** |
---|
242 | ** Parameters: |
---|
243 | ** msg -- the message (printf fmt) -- it can begin with |
---|
244 | ** an SMTP reply code. If not, 050 is assumed. |
---|
245 | ** (others) -- printf arguments |
---|
246 | ** |
---|
247 | ** Returns: |
---|
248 | ** none |
---|
249 | ** |
---|
250 | ** Side Effects: |
---|
251 | ** none. |
---|
252 | */ |
---|
253 | |
---|
254 | /*VARARGS1*/ |
---|
255 | void |
---|
256 | #ifdef __STDC__ |
---|
257 | message(const char *msg, ...) |
---|
258 | #else |
---|
259 | message(msg, va_alist) |
---|
260 | const char *msg; |
---|
261 | va_dcl |
---|
262 | #endif |
---|
263 | { |
---|
264 | VA_LOCAL_DECL |
---|
265 | |
---|
266 | errno = 0; |
---|
267 | VA_START(msg); |
---|
268 | fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap); |
---|
269 | VA_END; |
---|
270 | putoutmsg(MsgBuf, FALSE, FALSE); |
---|
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; |
---|
279 | /* fall through.... */ |
---|
280 | |
---|
281 | case '5': |
---|
282 | if (CurEnv->e_message != NULL) |
---|
283 | free(CurEnv->e_message); |
---|
284 | CurEnv->e_message = newstr(MsgBuf + 4); |
---|
285 | break; |
---|
286 | } |
---|
287 | } |
---|
288 | /* |
---|
289 | ** NMESSAGE -- print message (not necessarily an error) |
---|
290 | ** |
---|
291 | ** Just like "message" except it never puts the to... tag on. |
---|
292 | ** |
---|
293 | ** Parameters: |
---|
294 | ** msg -- the message (printf fmt) -- if it begins |
---|
295 | ** with a three digit SMTP reply code, that is used, |
---|
296 | ** otherwise 050 is assumed. |
---|
297 | ** (others) -- printf arguments |
---|
298 | ** |
---|
299 | ** Returns: |
---|
300 | ** none |
---|
301 | ** |
---|
302 | ** Side Effects: |
---|
303 | ** none. |
---|
304 | */ |
---|
305 | |
---|
306 | /*VARARGS1*/ |
---|
307 | void |
---|
308 | #ifdef __STDC__ |
---|
309 | nmessage(const char *msg, ...) |
---|
310 | #else |
---|
311 | nmessage(msg, va_alist) |
---|
312 | const char *msg; |
---|
313 | va_dcl |
---|
314 | #endif |
---|
315 | { |
---|
316 | VA_LOCAL_DECL |
---|
317 | |
---|
318 | errno = 0; |
---|
319 | VA_START(msg); |
---|
320 | fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap); |
---|
321 | VA_END; |
---|
322 | putoutmsg(MsgBuf, FALSE, FALSE); |
---|
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; |
---|
331 | /* fall through.... */ |
---|
332 | |
---|
333 | case '5': |
---|
334 | if (CurEnv->e_message != NULL) |
---|
335 | free(CurEnv->e_message); |
---|
336 | CurEnv->e_message = newstr(MsgBuf + 4); |
---|
337 | break; |
---|
338 | } |
---|
339 | } |
---|
340 | /* |
---|
341 | ** PUTOUTMSG -- output error message to transcript and channel |
---|
342 | ** |
---|
343 | ** Parameters: |
---|
344 | ** msg -- message to output (in SMTP format). |
---|
345 | ** holdmsg -- if TRUE, don't output a copy of the message to |
---|
346 | ** our output channel. |
---|
347 | ** heldmsg -- if TRUE, this is a previously held message; |
---|
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 | |
---|
359 | void |
---|
360 | putoutmsg(msg, holdmsg, heldmsg) |
---|
361 | char *msg; |
---|
362 | bool holdmsg; |
---|
363 | bool heldmsg; |
---|
364 | { |
---|
365 | char msgcode = msg[0]; |
---|
366 | |
---|
367 | /* display for debugging */ |
---|
368 | if (tTd(54, 8)) |
---|
369 | printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "", |
---|
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'; |
---|
377 | |
---|
378 | /* output to transcript if serious */ |
---|
379 | if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL && |
---|
380 | strchr("45", msg[0]) != NULL) |
---|
381 | fprintf(CurEnv->e_xfp, "%s\n", msg); |
---|
382 | |
---|
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)" : ""); |
---|
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; |
---|
398 | snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg); |
---|
399 | return; |
---|
400 | } |
---|
401 | |
---|
402 | (void) fflush(stdout); |
---|
403 | |
---|
404 | if (OutChannel == NULL) |
---|
405 | return; |
---|
406 | |
---|
407 | /* if DisConnected, OutChannel now points to the transcript */ |
---|
408 | if (!DisConnected && |
---|
409 | (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP)) |
---|
410 | fprintf(OutChannel, "%s\r\n", msg); |
---|
411 | else |
---|
412 | fprintf(OutChannel, "%s\n", &msg[4]); |
---|
413 | if (TrafficLogFile != NULL) |
---|
414 | fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(), |
---|
415 | (OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]); |
---|
416 | if (msg[3] == ' ') |
---|
417 | (void) fflush(OutChannel); |
---|
418 | if (!ferror(OutChannel) || DisConnected) |
---|
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 | |
---|
427 | if (InChannel == NULL || feof(InChannel) || ferror(InChannel) || |
---|
428 | strncmp(msg, "221", 3) == 0) |
---|
429 | return; |
---|
430 | |
---|
431 | /* can't call syserr, 'cause we are using MsgBuf */ |
---|
432 | HoldErrs = TRUE; |
---|
433 | if (LogLevel > 0) |
---|
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)); |
---|
438 | } |
---|
439 | /* |
---|
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 | |
---|
452 | void |
---|
453 | puterrmsg(msg) |
---|
454 | char *msg; |
---|
455 | { |
---|
456 | char msgcode = msg[0]; |
---|
457 | |
---|
458 | /* output the message as usual */ |
---|
459 | putoutmsg(msg, HoldErrs, FALSE); |
---|
460 | |
---|
461 | /* be careful about multiple error messages */ |
---|
462 | if (OnlyOneError) |
---|
463 | HoldErrs = TRUE; |
---|
464 | |
---|
465 | /* signal the error */ |
---|
466 | Errors++; |
---|
467 | |
---|
468 | if (CurEnv == NULL) |
---|
469 | return; |
---|
470 | |
---|
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 | } |
---|
482 | /* |
---|
483 | ** FMTMSG -- format a message into buffer. |
---|
484 | ** |
---|
485 | ** Parameters: |
---|
486 | ** eb -- error buffer to get result. |
---|
487 | ** to -- the recipient tag for this message. |
---|
488 | ** num -- arpanet error number. |
---|
489 | ** en -- the error number to display. |
---|
490 | ** fmt -- format of string. |
---|
491 | ** a, b, c, d, e -- arguments. |
---|
492 | ** |
---|
493 | ** Returns: |
---|
494 | ** none. |
---|
495 | ** |
---|
496 | ** Side Effects: |
---|
497 | ** none. |
---|
498 | */ |
---|
499 | |
---|
500 | static void |
---|
501 | fmtmsg(eb, to, num, eno, fmt, ap) |
---|
502 | register char *eb; |
---|
503 | const char *to; |
---|
504 | const char *num; |
---|
505 | int eno; |
---|
506 | const char *fmt; |
---|
507 | va_list ap; |
---|
508 | { |
---|
509 | char del; |
---|
510 | int l; |
---|
511 | int spaceleft = sizeof MsgBuf; |
---|
512 | |
---|
513 | /* output the reply code */ |
---|
514 | if (isascii(fmt[0]) && isdigit(fmt[0]) && |
---|
515 | isascii(fmt[1]) && isdigit(fmt[1]) && |
---|
516 | isascii(fmt[2]) && isdigit(fmt[2])) |
---|
517 | { |
---|
518 | num = fmt; |
---|
519 | fmt += 4; |
---|
520 | } |
---|
521 | if (num[3] == '-') |
---|
522 | del = '-'; |
---|
523 | else |
---|
524 | del = ' '; |
---|
525 | (void) snprintf(eb, spaceleft, "%3.3s%c", num, del); |
---|
526 | eb += 4; |
---|
527 | spaceleft -= 4; |
---|
528 | |
---|
529 | /* output the file name and line number */ |
---|
530 | if (FileName != NULL) |
---|
531 | { |
---|
532 | (void) snprintf(eb, spaceleft, "%s: line %d: ", |
---|
533 | shortenstring(FileName, 83), LineNumber); |
---|
534 | eb += (l = strlen(eb)); |
---|
535 | spaceleft -= l; |
---|
536 | } |
---|
537 | |
---|
538 | /* output the "to" person */ |
---|
539 | if (to != NULL && to[0] != '\0' && |
---|
540 | strncmp(num, "551", 3) != 0 && |
---|
541 | strncmp(num, "251", 3) != 0) |
---|
542 | { |
---|
543 | (void) snprintf(eb, spaceleft, "%s... ", |
---|
544 | shortenstring(to, MAXSHORTSTR)); |
---|
545 | spaceleft -= strlen(eb); |
---|
546 | while (*eb != '\0') |
---|
547 | *eb++ &= 0177; |
---|
548 | } |
---|
549 | |
---|
550 | /* output the message */ |
---|
551 | (void) vsnprintf(eb, spaceleft, fmt, ap); |
---|
552 | spaceleft -= strlen(eb); |
---|
553 | while (*eb != '\0') |
---|
554 | *eb++ &= 0177; |
---|
555 | |
---|
556 | /* output the error code, if any */ |
---|
557 | if (eno != 0) |
---|
558 | (void) snprintf(eb, spaceleft, ": %s", errstring(eno)); |
---|
559 | } |
---|
560 | /* |
---|
561 | ** BUFFER_ERRORS -- arrange to buffer future error messages |
---|
562 | ** |
---|
563 | ** Parameters: |
---|
564 | ** none |
---|
565 | ** |
---|
566 | ** Returns: |
---|
567 | ** none. |
---|
568 | */ |
---|
569 | |
---|
570 | void |
---|
571 | buffer_errors() |
---|
572 | { |
---|
573 | HeldMessageBuf[0] = '\0'; |
---|
574 | HoldErrs = TRUE; |
---|
575 | } |
---|
576 | /* |
---|
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 | |
---|
587 | void |
---|
588 | flush_errors(print) |
---|
589 | bool print; |
---|
590 | { |
---|
591 | if (print && HeldMessageBuf[0] != '\0') |
---|
592 | putoutmsg(HeldMessageBuf, FALSE, TRUE); |
---|
593 | HeldMessageBuf[0] = '\0'; |
---|
594 | HoldErrs = FALSE; |
---|
595 | } |
---|
596 | /* |
---|
597 | ** ERRSTRING -- return string description of error code |
---|
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 | |
---|
609 | const char * |
---|
610 | errstring(errnum) |
---|
611 | int errnum; |
---|
612 | { |
---|
613 | char *dnsmsg; |
---|
614 | char *bp; |
---|
615 | static char buf[MAXLINE]; |
---|
616 | # if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) |
---|
617 | extern char *sys_errlist[]; |
---|
618 | extern int sys_nerr; |
---|
619 | # endif |
---|
620 | # if SMTP |
---|
621 | extern char *SmtpPhase; |
---|
622 | # endif /* SMTP */ |
---|
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) |
---|
634 | case ETIMEDOUT: |
---|
635 | case ECONNRESET: |
---|
636 | bp = buf; |
---|
637 | #if HASSTRERROR |
---|
638 | snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum)); |
---|
639 | #else |
---|
640 | if (errnum >= 0 && errnum < sys_nerr) |
---|
641 | snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]); |
---|
642 | else |
---|
643 | snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum); |
---|
644 | #endif |
---|
645 | bp += strlen(bp); |
---|
646 | if (CurHostName != NULL) |
---|
647 | { |
---|
648 | if (errnum == ETIMEDOUT) |
---|
649 | { |
---|
650 | snprintf(bp, SPACELEFT(buf, bp), " with "); |
---|
651 | bp += strlen(bp); |
---|
652 | } |
---|
653 | else |
---|
654 | { |
---|
655 | bp = buf; |
---|
656 | snprintf(bp, SPACELEFT(buf, bp), |
---|
657 | "Connection reset by "); |
---|
658 | bp += strlen(bp); |
---|
659 | } |
---|
660 | snprintf(bp, SPACELEFT(buf, bp), "%s", |
---|
661 | shortenstring(CurHostName, MAXSHORTSTR)); |
---|
662 | bp += strlen(buf); |
---|
663 | } |
---|
664 | if (SmtpPhase != NULL) |
---|
665 | { |
---|
666 | snprintf(bp, SPACELEFT(buf, bp), " during %s", |
---|
667 | SmtpPhase); |
---|
668 | } |
---|
669 | return (buf); |
---|
670 | |
---|
671 | case EHOSTDOWN: |
---|
672 | if (CurHostName == NULL) |
---|
673 | break; |
---|
674 | (void) snprintf(buf, sizeof buf, "Host %s is down", |
---|
675 | shortenstring(CurHostName, MAXSHORTSTR)); |
---|
676 | return (buf); |
---|
677 | |
---|
678 | case ECONNREFUSED: |
---|
679 | if (CurHostName == NULL) |
---|
680 | break; |
---|
681 | (void) snprintf(buf, sizeof buf, "Connection refused by %s", |
---|
682 | shortenstring(CurHostName, MAXSHORTSTR)); |
---|
683 | return (buf); |
---|
684 | # endif |
---|
685 | |
---|
686 | # if NAMED_BIND |
---|
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; |
---|
702 | # endif |
---|
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 | */ |
---|
711 | |
---|
712 | case E_SM_OPENTIMEOUT: |
---|
713 | return "Timeout on file open"; |
---|
714 | |
---|
715 | case E_SM_NOSLINK: |
---|
716 | return "Symbolic links not allowed"; |
---|
717 | |
---|
718 | case E_SM_NOHLINK: |
---|
719 | return "Hard links not allowed"; |
---|
720 | |
---|
721 | case E_SM_REGONLY: |
---|
722 | return "Regular files only"; |
---|
723 | |
---|
724 | case E_SM_ISEXEC: |
---|
725 | return "Executable files not allowed"; |
---|
726 | |
---|
727 | case E_SM_WWDIR: |
---|
728 | return "World writable directory"; |
---|
729 | |
---|
730 | case E_SM_GWDIR: |
---|
731 | return "Group writable directory"; |
---|
732 | |
---|
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"; |
---|
741 | } |
---|
742 | |
---|
743 | if (dnsmsg != NULL) |
---|
744 | { |
---|
745 | bp = buf; |
---|
746 | strcpy(bp, "Name server: "); |
---|
747 | bp += strlen(bp); |
---|
748 | if (CurHostName != NULL) |
---|
749 | { |
---|
750 | snprintf(bp, SPACELEFT(buf, bp), "%s: ", |
---|
751 | shortenstring(CurHostName, MAXSHORTSTR)); |
---|
752 | bp += strlen(bp); |
---|
753 | } |
---|
754 | snprintf(bp, SPACELEFT(buf, bp), "%s", dnsmsg); |
---|
755 | return buf; |
---|
756 | } |
---|
757 | |
---|
758 | #if HASSTRERROR |
---|
759 | return strerror(errnum); |
---|
760 | #else |
---|
761 | if (errnum > 0 && errnum < sys_nerr) |
---|
762 | return (sys_errlist[errnum]); |
---|
763 | |
---|
764 | (void) snprintf(buf, sizeof buf, "Error %d", errnum); |
---|
765 | return (buf); |
---|
766 | #endif |
---|
767 | } |
---|