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} |