1c2aa98e2SPeter Wemm /* 25dd76dd0SGregory Neil Shapiro * Copyright (c) 1998-2003, 2010 Proofpoint, Inc. and its suppliers. 33299c2f1SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 1412ed1c7cSGregory Neil Shapiro #include <sendmail.h> 1512ed1c7cSGregory Neil Shapiro 16*4313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: err.c,v 8.206 2013-11-22 20:51:55 ca Exp $") 17c2aa98e2SPeter Wemm 1812ed1c7cSGregory Neil Shapiro #if LDAPMAP 193299c2f1SGregory Neil Shapiro # include <lber.h> 203299c2f1SGregory Neil Shapiro # include <ldap.h> /* for LDAP error codes */ 213299c2f1SGregory Neil Shapiro #endif /* LDAPMAP */ 223299c2f1SGregory Neil Shapiro 233299c2f1SGregory Neil Shapiro static void putoutmsg __P((char *, bool, bool)); 243299c2f1SGregory Neil Shapiro static void puterrmsg __P((char *)); 253299c2f1SGregory Neil Shapiro static char *fmtmsg __P((char *, const char *, const char *, const char *, 263299c2f1SGregory Neil Shapiro int, const char *, va_list)); 27c2aa98e2SPeter Wemm 28c2aa98e2SPeter Wemm /* 2912ed1c7cSGregory Neil Shapiro ** FATAL_ERROR -- handle a fatal exception 3012ed1c7cSGregory Neil Shapiro ** 3112ed1c7cSGregory Neil Shapiro ** This function is installed as the default exception handler 3212ed1c7cSGregory Neil Shapiro ** in the main sendmail process, and in all child processes 3312ed1c7cSGregory Neil Shapiro ** that we create. Its job is to handle exceptions that are not 3412ed1c7cSGregory Neil Shapiro ** handled at a lower level. 3512ed1c7cSGregory Neil Shapiro ** 3612ed1c7cSGregory Neil Shapiro ** The theory is that unhandled exceptions will be 'fatal' class 3712ed1c7cSGregory Neil Shapiro ** exceptions (with an "F:" prefix), such as the out-of-memory 3812ed1c7cSGregory Neil Shapiro ** exception "F:sm.heap". As such, they are handled by exiting 3912ed1c7cSGregory Neil Shapiro ** the process in exactly the same way that xalloc() in Sendmail 8.10 4012ed1c7cSGregory Neil Shapiro ** exits the process when it fails due to lack of memory: 4112ed1c7cSGregory Neil Shapiro ** we call syserr with a message beginning with "!". 4212ed1c7cSGregory Neil Shapiro ** 4312ed1c7cSGregory Neil Shapiro ** Parameters: 4412ed1c7cSGregory Neil Shapiro ** exc -- exception which is terminating this process 4512ed1c7cSGregory Neil Shapiro ** 4612ed1c7cSGregory Neil Shapiro ** Returns: 4712ed1c7cSGregory Neil Shapiro ** none 4812ed1c7cSGregory Neil Shapiro */ 4912ed1c7cSGregory Neil Shapiro 5012ed1c7cSGregory Neil Shapiro void 5112ed1c7cSGregory Neil Shapiro fatal_error(exc) 5212ed1c7cSGregory Neil Shapiro SM_EXC_T *exc; 5312ed1c7cSGregory Neil Shapiro { 5412ed1c7cSGregory Neil Shapiro static char buf[256]; 5512ed1c7cSGregory Neil Shapiro SM_FILE_T f; 5612ed1c7cSGregory Neil Shapiro 5712ed1c7cSGregory Neil Shapiro /* 5812ed1c7cSGregory Neil Shapiro ** This function may be called when the heap is exhausted. 5912ed1c7cSGregory Neil Shapiro ** The following code writes the message for 'exc' into our 6012ed1c7cSGregory Neil Shapiro ** static buffer without allocating memory or raising exceptions. 6112ed1c7cSGregory Neil Shapiro */ 6212ed1c7cSGregory Neil Shapiro 6312ed1c7cSGregory Neil Shapiro sm_strio_init(&f, buf, sizeof(buf)); 6412ed1c7cSGregory Neil Shapiro sm_exc_write(exc, &f); 6512ed1c7cSGregory Neil Shapiro (void) sm_io_flush(&f, SM_TIME_DEFAULT); 6612ed1c7cSGregory Neil Shapiro 6712ed1c7cSGregory Neil Shapiro /* 6812ed1c7cSGregory Neil Shapiro ** Terminate the process after logging an error and cleaning up. 6912ed1c7cSGregory Neil Shapiro ** Problems: 7012ed1c7cSGregory Neil Shapiro ** - syserr decides what class of error this is by looking at errno. 7112ed1c7cSGregory Neil Shapiro ** That's no good; we should look at the exc structure. 7212ed1c7cSGregory Neil Shapiro ** - The cleanup code should be moved out of syserr 7312ed1c7cSGregory Neil Shapiro ** and into individual exception handlers 7412ed1c7cSGregory Neil Shapiro ** that are part of the module they clean up after. 7512ed1c7cSGregory Neil Shapiro */ 7612ed1c7cSGregory Neil Shapiro 7712ed1c7cSGregory Neil Shapiro errno = ENOMEM; 7812ed1c7cSGregory Neil Shapiro syserr("!%s", buf); 7912ed1c7cSGregory Neil Shapiro } 8012ed1c7cSGregory Neil Shapiro 8112ed1c7cSGregory Neil Shapiro /* 82c2aa98e2SPeter Wemm ** SYSERR -- Print error message. 83c2aa98e2SPeter Wemm ** 8412ed1c7cSGregory Neil Shapiro ** Prints an error message via sm_io_printf to the diagnostic output. 85c2aa98e2SPeter Wemm ** 86c2aa98e2SPeter Wemm ** If the first character of the syserr message is `!' it will 87c2aa98e2SPeter Wemm ** log this as an ALERT message and exit immediately. This can 88c2aa98e2SPeter Wemm ** leave queue files in an indeterminate state, so it should not 89c2aa98e2SPeter Wemm ** be used lightly. 90c2aa98e2SPeter Wemm ** 9112ed1c7cSGregory Neil Shapiro ** If the first character of the syserr message is '!' or '@' 9212ed1c7cSGregory Neil Shapiro ** then syserr knows that the process is about to be terminated, 9312ed1c7cSGregory Neil Shapiro ** so the SMTP reply code defaults to 421. Otherwise, the 9412ed1c7cSGregory Neil Shapiro ** reply code defaults to 451 or 554, depending on errno. 9512ed1c7cSGregory Neil Shapiro ** 96c2aa98e2SPeter Wemm ** Parameters: 9712ed1c7cSGregory Neil Shapiro ** fmt -- the format string. An optional '!' or '@', 9812ed1c7cSGregory Neil Shapiro ** followed by an optional three-digit SMTP 9912ed1c7cSGregory Neil Shapiro ** reply code, followed by message text. 100c2aa98e2SPeter Wemm ** (others) -- parameters 101c2aa98e2SPeter Wemm ** 102c2aa98e2SPeter Wemm ** Returns: 103c2aa98e2SPeter Wemm ** none 10412ed1c7cSGregory Neil Shapiro ** Raises E:mta.quickabort if QuickAbort is set. 105c2aa98e2SPeter Wemm ** 106c2aa98e2SPeter Wemm ** Side Effects: 107c2aa98e2SPeter Wemm ** increments Errors. 108c2aa98e2SPeter Wemm ** sets ExitStat. 109c2aa98e2SPeter Wemm */ 110c2aa98e2SPeter Wemm 111c2aa98e2SPeter Wemm char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 112951742c4SGregory Neil Shapiro static char HeldMessageBuf[sizeof(MsgBuf)]; /* for held messages */ 113c2aa98e2SPeter Wemm 114c2aa98e2SPeter Wemm #if NAMED_BIND && !defined(NO_DATA) 115c2aa98e2SPeter Wemm # define NO_DATA NO_ADDRESS 1163299c2f1SGregory Neil Shapiro #endif /* NAMED_BIND && !defined(NO_DATA) */ 117c2aa98e2SPeter Wemm 118c2aa98e2SPeter Wemm void 119c2aa98e2SPeter Wemm /*VARARGS1*/ 120c2aa98e2SPeter Wemm #ifdef __STDC__ 121c2aa98e2SPeter Wemm syserr(const char *fmt, ...) 1223299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 123c2aa98e2SPeter Wemm syserr(fmt, va_alist) 124c2aa98e2SPeter Wemm const char *fmt; 125c2aa98e2SPeter Wemm va_dcl 1263299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 127c2aa98e2SPeter Wemm { 128c2aa98e2SPeter Wemm register char *p; 1293299c2f1SGregory Neil Shapiro int save_errno = errno; 130c2aa98e2SPeter Wemm bool panic; 13112ed1c7cSGregory Neil Shapiro bool exiting; 1323299c2f1SGregory Neil Shapiro char *user; 1333299c2f1SGregory Neil Shapiro char *enhsc; 1343299c2f1SGregory Neil Shapiro char *errtxt; 135c2aa98e2SPeter Wemm struct passwd *pw; 136c2aa98e2SPeter Wemm char ubuf[80]; 13712ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 138c2aa98e2SPeter Wemm 13912ed1c7cSGregory Neil Shapiro switch (*fmt) 140c2aa98e2SPeter Wemm { 14112ed1c7cSGregory Neil Shapiro case '!': 14212ed1c7cSGregory Neil Shapiro ++fmt; 14312ed1c7cSGregory Neil Shapiro panic = true; 14412ed1c7cSGregory Neil Shapiro exiting = true; 14512ed1c7cSGregory Neil Shapiro break; 14612ed1c7cSGregory Neil Shapiro case '@': 14712ed1c7cSGregory Neil Shapiro ++fmt; 14812ed1c7cSGregory Neil Shapiro panic = false; 14912ed1c7cSGregory Neil Shapiro exiting = true; 15012ed1c7cSGregory Neil Shapiro break; 15112ed1c7cSGregory Neil Shapiro default: 15212ed1c7cSGregory Neil Shapiro panic = false; 15312ed1c7cSGregory Neil Shapiro exiting = false; 15412ed1c7cSGregory Neil Shapiro break; 155c2aa98e2SPeter Wemm } 156c2aa98e2SPeter Wemm 157c2aa98e2SPeter Wemm /* format and output the error message */ 15812ed1c7cSGregory Neil Shapiro if (exiting) 15912ed1c7cSGregory Neil Shapiro { 16012ed1c7cSGregory Neil Shapiro /* 16112ed1c7cSGregory Neil Shapiro ** Since we are terminating the process, 16212ed1c7cSGregory Neil Shapiro ** we are aborting the entire SMTP session, 16312ed1c7cSGregory Neil Shapiro ** rather than just the current transaction. 16412ed1c7cSGregory Neil Shapiro */ 16512ed1c7cSGregory Neil Shapiro 16612ed1c7cSGregory Neil Shapiro p = "421"; 16712ed1c7cSGregory Neil Shapiro enhsc = "4.0.0"; 16812ed1c7cSGregory Neil Shapiro } 16912ed1c7cSGregory Neil Shapiro else if (save_errno == 0) 1703299c2f1SGregory Neil Shapiro { 171c2aa98e2SPeter Wemm p = "554"; 1723299c2f1SGregory Neil Shapiro enhsc = "5.0.0"; 1733299c2f1SGregory Neil Shapiro } 174c2aa98e2SPeter Wemm else 1753299c2f1SGregory Neil Shapiro { 176c2aa98e2SPeter Wemm p = "451"; 1773299c2f1SGregory Neil Shapiro enhsc = "4.0.0"; 1783299c2f1SGregory Neil Shapiro } 17912ed1c7cSGregory Neil Shapiro SM_VA_START(ap, fmt); 1803299c2f1SGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap); 18112ed1c7cSGregory Neil Shapiro SM_VA_END(ap); 182c2aa98e2SPeter Wemm puterrmsg(MsgBuf); 183c2aa98e2SPeter Wemm 184c2aa98e2SPeter Wemm /* save this message for mailq printing */ 185c2aa98e2SPeter Wemm if (!panic && CurEnv != NULL) 186c2aa98e2SPeter Wemm { 18712ed1c7cSGregory Neil Shapiro char *nmsg = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 18812ed1c7cSGregory Neil Shapiro 18912ed1c7cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 190c0c4794dSGregory Neil Shapiro sm_free(CurEnv->e_message); 19112ed1c7cSGregory Neil Shapiro CurEnv->e_message = nmsg; 192c2aa98e2SPeter Wemm } 193c2aa98e2SPeter Wemm 194c2aa98e2SPeter Wemm /* determine exit status if not already set */ 195c2aa98e2SPeter Wemm if (ExitStat == EX_OK) 196c2aa98e2SPeter Wemm { 1973299c2f1SGregory Neil Shapiro if (save_errno == 0) 198c2aa98e2SPeter Wemm ExitStat = EX_SOFTWARE; 199c2aa98e2SPeter Wemm else 200c2aa98e2SPeter Wemm ExitStat = EX_OSERR; 201c2aa98e2SPeter Wemm if (tTd(54, 1)) 20212ed1c7cSGregory Neil Shapiro sm_dprintf("syserr: ExitStat = %d\n", ExitStat); 203c2aa98e2SPeter Wemm } 204c2aa98e2SPeter Wemm 205c0c4794dSGregory Neil Shapiro pw = sm_getpwuid(RealUid); 206c2aa98e2SPeter Wemm if (pw != NULL) 2073299c2f1SGregory Neil Shapiro user = pw->pw_name; 208c2aa98e2SPeter Wemm else 209c2aa98e2SPeter Wemm { 2103299c2f1SGregory Neil Shapiro user = ubuf; 211951742c4SGregory Neil Shapiro (void) sm_snprintf(ubuf, sizeof(ubuf), "UID%d", (int) RealUid); 212c2aa98e2SPeter Wemm } 213c2aa98e2SPeter Wemm 214c2aa98e2SPeter Wemm if (LogLevel > 0) 215c2aa98e2SPeter Wemm sm_syslog(panic ? LOG_ALERT : LOG_CRIT, 216c2aa98e2SPeter Wemm CurEnv == NULL ? NOQID : CurEnv->e_id, 217c2aa98e2SPeter Wemm "SYSERR(%s): %.900s", 2183299c2f1SGregory Neil Shapiro user, errtxt); 2193299c2f1SGregory Neil Shapiro switch (save_errno) 220c2aa98e2SPeter Wemm { 221c2aa98e2SPeter Wemm case EBADF: 222c2aa98e2SPeter Wemm case ENFILE: 223c2aa98e2SPeter Wemm case EMFILE: 224c2aa98e2SPeter Wemm case ENOTTY: 225c2aa98e2SPeter Wemm #ifdef EFBIG 226c2aa98e2SPeter Wemm case EFBIG: 2273299c2f1SGregory Neil Shapiro #endif /* EFBIG */ 228c2aa98e2SPeter Wemm #ifdef ESPIPE 229c2aa98e2SPeter Wemm case ESPIPE: 2303299c2f1SGregory Neil Shapiro #endif /* ESPIPE */ 231c2aa98e2SPeter Wemm #ifdef EPIPE 232c2aa98e2SPeter Wemm case EPIPE: 2333299c2f1SGregory Neil Shapiro #endif /* EPIPE */ 234c2aa98e2SPeter Wemm #ifdef ENOBUFS 235c2aa98e2SPeter Wemm case ENOBUFS: 2363299c2f1SGregory Neil Shapiro #endif /* ENOBUFS */ 237c2aa98e2SPeter Wemm #ifdef ESTALE 238c2aa98e2SPeter Wemm case ESTALE: 2393299c2f1SGregory Neil Shapiro #endif /* ESTALE */ 24012ed1c7cSGregory Neil Shapiro printopenfds(true); 241bfb62e91SGregory Neil Shapiro mci_dump_all(smioout, true); 242c2aa98e2SPeter Wemm break; 243c2aa98e2SPeter Wemm } 244c2aa98e2SPeter Wemm if (panic) 245c2aa98e2SPeter Wemm { 24612ed1c7cSGregory Neil Shapiro #if XLA 247c2aa98e2SPeter Wemm xla_all_end(); 2483299c2f1SGregory Neil Shapiro #endif /* XLA */ 2493299c2f1SGregory Neil Shapiro sync_queue_time(); 250c2aa98e2SPeter Wemm if (tTd(0, 1)) 251c2aa98e2SPeter Wemm abort(); 252c2aa98e2SPeter Wemm exit(EX_OSERR); 253c2aa98e2SPeter Wemm } 254c2aa98e2SPeter Wemm errno = 0; 255c2aa98e2SPeter Wemm if (QuickAbort) 25612ed1c7cSGregory Neil Shapiro sm_exc_raisenew_x(&EtypeQuickAbort, 2); 257c2aa98e2SPeter Wemm } 25812ed1c7cSGregory Neil Shapiro /* 259c2aa98e2SPeter Wemm ** USRERR -- Signal user error. 260c2aa98e2SPeter Wemm ** 261c2aa98e2SPeter Wemm ** This is much like syserr except it is for user errors. 262c2aa98e2SPeter Wemm ** 263c2aa98e2SPeter Wemm ** Parameters: 264c2aa98e2SPeter Wemm ** fmt -- the format string. If it does not begin with 26512ed1c7cSGregory Neil Shapiro ** a three-digit SMTP reply code, 550 is assumed. 26612ed1c7cSGregory Neil Shapiro ** (others) -- sm_io_printf strings 267c2aa98e2SPeter Wemm ** 268c2aa98e2SPeter Wemm ** Returns: 269c2aa98e2SPeter Wemm ** none 27012ed1c7cSGregory Neil Shapiro ** Raises E:mta.quickabort if QuickAbort is set. 271c2aa98e2SPeter Wemm ** 272c2aa98e2SPeter Wemm ** Side Effects: 273c2aa98e2SPeter Wemm ** increments Errors. 274c2aa98e2SPeter Wemm */ 275c2aa98e2SPeter Wemm 276c2aa98e2SPeter Wemm /*VARARGS1*/ 277c2aa98e2SPeter Wemm void 278c2aa98e2SPeter Wemm #ifdef __STDC__ 279c2aa98e2SPeter Wemm usrerr(const char *fmt, ...) 2803299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 281c2aa98e2SPeter Wemm usrerr(fmt, va_alist) 282c2aa98e2SPeter Wemm const char *fmt; 283c2aa98e2SPeter Wemm va_dcl 2843299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 285c2aa98e2SPeter Wemm { 2863299c2f1SGregory Neil Shapiro char *enhsc; 2873299c2f1SGregory Neil Shapiro char *errtxt; 28812ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 289c2aa98e2SPeter Wemm 2903299c2f1SGregory Neil Shapiro if (fmt[0] == '5' || fmt[0] == '6') 2913299c2f1SGregory Neil Shapiro enhsc = "5.0.0"; 2923299c2f1SGregory Neil Shapiro else if (fmt[0] == '4' || fmt[0] == '8') 2933299c2f1SGregory Neil Shapiro enhsc = "4.0.0"; 2943299c2f1SGregory Neil Shapiro else if (fmt[0] == '2') 2953299c2f1SGregory Neil Shapiro enhsc = "2.0.0"; 2963299c2f1SGregory Neil Shapiro else 2973299c2f1SGregory Neil Shapiro enhsc = NULL; 29812ed1c7cSGregory Neil Shapiro SM_VA_START(ap, fmt); 29912ed1c7cSGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap); 30012ed1c7cSGregory Neil Shapiro SM_VA_END(ap); 3013299c2f1SGregory Neil Shapiro 302c2aa98e2SPeter Wemm if (SuprErrs) 303c2aa98e2SPeter Wemm return; 304c2aa98e2SPeter Wemm 305c2aa98e2SPeter Wemm /* save this message for mailq printing */ 306c2aa98e2SPeter Wemm switch (MsgBuf[0]) 307c2aa98e2SPeter Wemm { 308c2aa98e2SPeter Wemm case '4': 309c2aa98e2SPeter Wemm case '8': 310c2aa98e2SPeter Wemm if (CurEnv->e_message != NULL) 311c2aa98e2SPeter Wemm break; 312c2aa98e2SPeter Wemm 3133299c2f1SGregory Neil Shapiro /* FALLTHROUGH */ 314c2aa98e2SPeter Wemm 315c2aa98e2SPeter Wemm case '5': 316c2aa98e2SPeter Wemm case '6': 31712ed1c7cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 318c0c4794dSGregory Neil Shapiro sm_free(CurEnv->e_message); 319c2aa98e2SPeter Wemm if (MsgBuf[0] == '6') 320c2aa98e2SPeter Wemm { 321c2aa98e2SPeter Wemm char buf[MAXLINE]; 322c2aa98e2SPeter Wemm 323951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), 32412ed1c7cSGregory Neil Shapiro "Postmaster warning: %.*s", 325951742c4SGregory Neil Shapiro (int) sizeof(buf) - 22, errtxt); 32612ed1c7cSGregory Neil Shapiro CurEnv->e_message = 32712ed1c7cSGregory Neil Shapiro sm_rpool_strdup_x(CurEnv->e_rpool, buf); 328c2aa98e2SPeter Wemm } 329c2aa98e2SPeter Wemm else 330c2aa98e2SPeter Wemm { 33112ed1c7cSGregory Neil Shapiro CurEnv->e_message = 33212ed1c7cSGregory Neil Shapiro sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 333c2aa98e2SPeter Wemm } 334c2aa98e2SPeter Wemm break; 335c2aa98e2SPeter Wemm } 336c2aa98e2SPeter Wemm 337c2aa98e2SPeter Wemm puterrmsg(MsgBuf); 338c2aa98e2SPeter Wemm if (LogLevel > 3 && LogUsrErrs) 3393299c2f1SGregory Neil Shapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); 3403299c2f1SGregory Neil Shapiro if (QuickAbort) 34112ed1c7cSGregory Neil Shapiro sm_exc_raisenew_x(&EtypeQuickAbort, 1); 3423299c2f1SGregory Neil Shapiro } 34312ed1c7cSGregory Neil Shapiro /* 3443299c2f1SGregory Neil Shapiro ** USRERRENH -- Signal user error. 3453299c2f1SGregory Neil Shapiro ** 3463299c2f1SGregory Neil Shapiro ** Same as usrerr but with enhanced status code. 3473299c2f1SGregory Neil Shapiro ** 3483299c2f1SGregory Neil Shapiro ** Parameters: 3493299c2f1SGregory Neil Shapiro ** enhsc -- the enhanced status code. 3503299c2f1SGregory Neil Shapiro ** fmt -- the format string. If it does not begin with 35112ed1c7cSGregory Neil Shapiro ** a three-digit SMTP reply code, 550 is assumed. 35212ed1c7cSGregory Neil Shapiro ** (others) -- sm_io_printf strings 3533299c2f1SGregory Neil Shapiro ** 3543299c2f1SGregory Neil Shapiro ** Returns: 3553299c2f1SGregory Neil Shapiro ** none 35612ed1c7cSGregory Neil Shapiro ** Raises E:mta.quickabort if QuickAbort is set. 3573299c2f1SGregory Neil Shapiro ** 3583299c2f1SGregory Neil Shapiro ** Side Effects: 3593299c2f1SGregory Neil Shapiro ** increments Errors. 3603299c2f1SGregory Neil Shapiro */ 3613299c2f1SGregory Neil Shapiro 3626f9c8e5bSGregory Neil Shapiro /*VARARGS2*/ 3633299c2f1SGregory Neil Shapiro void 3643299c2f1SGregory Neil Shapiro #ifdef __STDC__ 3653299c2f1SGregory Neil Shapiro usrerrenh(char *enhsc, const char *fmt, ...) 3663299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 3673299c2f1SGregory Neil Shapiro usrerrenh(enhsc, fmt, va_alist) 3683299c2f1SGregory Neil Shapiro char *enhsc; 3693299c2f1SGregory Neil Shapiro const char *fmt; 3703299c2f1SGregory Neil Shapiro va_dcl 3713299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 3723299c2f1SGregory Neil Shapiro { 3733299c2f1SGregory Neil Shapiro char *errtxt; 37412ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 3753299c2f1SGregory Neil Shapiro 3763299c2f1SGregory Neil Shapiro if (enhsc == NULL || *enhsc == '\0') 3773299c2f1SGregory Neil Shapiro { 3783299c2f1SGregory Neil Shapiro if (fmt[0] == '5' || fmt[0] == '6') 3793299c2f1SGregory Neil Shapiro enhsc = "5.0.0"; 3803299c2f1SGregory Neil Shapiro else if (fmt[0] == '4' || fmt[0] == '8') 3813299c2f1SGregory Neil Shapiro enhsc = "4.0.0"; 3823299c2f1SGregory Neil Shapiro else if (fmt[0] == '2') 3833299c2f1SGregory Neil Shapiro enhsc = "2.0.0"; 3843299c2f1SGregory Neil Shapiro } 38512ed1c7cSGregory Neil Shapiro SM_VA_START(ap, fmt); 38612ed1c7cSGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap); 38712ed1c7cSGregory Neil Shapiro SM_VA_END(ap); 3883299c2f1SGregory Neil Shapiro 3893299c2f1SGregory Neil Shapiro if (SuprErrs) 3903299c2f1SGregory Neil Shapiro return; 3913299c2f1SGregory Neil Shapiro 3923299c2f1SGregory Neil Shapiro /* save this message for mailq printing */ 3933299c2f1SGregory Neil Shapiro switch (MsgBuf[0]) 3943299c2f1SGregory Neil Shapiro { 3953299c2f1SGregory Neil Shapiro case '4': 3963299c2f1SGregory Neil Shapiro case '8': 3973299c2f1SGregory Neil Shapiro if (CurEnv->e_message != NULL) 3983299c2f1SGregory Neil Shapiro break; 3993299c2f1SGregory Neil Shapiro 4003299c2f1SGregory Neil Shapiro /* FALLTHROUGH */ 4013299c2f1SGregory Neil Shapiro 4023299c2f1SGregory Neil Shapiro case '5': 4033299c2f1SGregory Neil Shapiro case '6': 40412ed1c7cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 405c0c4794dSGregory Neil Shapiro sm_free(CurEnv->e_message); 4063299c2f1SGregory Neil Shapiro if (MsgBuf[0] == '6') 4073299c2f1SGregory Neil Shapiro { 4083299c2f1SGregory Neil Shapiro char buf[MAXLINE]; 4093299c2f1SGregory Neil Shapiro 410951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), 41112ed1c7cSGregory Neil Shapiro "Postmaster warning: %.*s", 412951742c4SGregory Neil Shapiro (int) sizeof(buf) - 22, errtxt); 41312ed1c7cSGregory Neil Shapiro CurEnv->e_message = 41412ed1c7cSGregory Neil Shapiro sm_rpool_strdup_x(CurEnv->e_rpool, buf); 4153299c2f1SGregory Neil Shapiro } 4163299c2f1SGregory Neil Shapiro else 4173299c2f1SGregory Neil Shapiro { 41812ed1c7cSGregory Neil Shapiro CurEnv->e_message = 41912ed1c7cSGregory Neil Shapiro sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 4203299c2f1SGregory Neil Shapiro } 4213299c2f1SGregory Neil Shapiro break; 4223299c2f1SGregory Neil Shapiro } 4233299c2f1SGregory Neil Shapiro 4243299c2f1SGregory Neil Shapiro puterrmsg(MsgBuf); 4253299c2f1SGregory Neil Shapiro if (LogLevel > 3 && LogUsrErrs) 4263299c2f1SGregory Neil Shapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); 427c2aa98e2SPeter Wemm if (QuickAbort) 42812ed1c7cSGregory Neil Shapiro sm_exc_raisenew_x(&EtypeQuickAbort, 1); 429c2aa98e2SPeter Wemm } 4306f9c8e5bSGregory Neil Shapiro 43112ed1c7cSGregory Neil Shapiro /* 432c2aa98e2SPeter Wemm ** MESSAGE -- print message (not necessarily an error) 433c2aa98e2SPeter Wemm ** 434c2aa98e2SPeter Wemm ** Parameters: 43512ed1c7cSGregory Neil Shapiro ** msg -- the message (sm_io_printf fmt) -- it can begin with 436c2aa98e2SPeter Wemm ** an SMTP reply code. If not, 050 is assumed. 43712ed1c7cSGregory Neil Shapiro ** (others) -- sm_io_printf arguments 438c2aa98e2SPeter Wemm ** 439c2aa98e2SPeter Wemm ** Returns: 440c2aa98e2SPeter Wemm ** none 441c2aa98e2SPeter Wemm ** 442c2aa98e2SPeter Wemm ** Side Effects: 443c2aa98e2SPeter Wemm ** none. 444c2aa98e2SPeter Wemm */ 445c2aa98e2SPeter Wemm 446c2aa98e2SPeter Wemm /*VARARGS1*/ 447c2aa98e2SPeter Wemm void 448c2aa98e2SPeter Wemm #ifdef __STDC__ 449c2aa98e2SPeter Wemm message(const char *msg, ...) 4503299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 451c2aa98e2SPeter Wemm message(msg, va_alist) 452c2aa98e2SPeter Wemm const char *msg; 453c2aa98e2SPeter Wemm va_dcl 4543299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 455c2aa98e2SPeter Wemm { 4563299c2f1SGregory Neil Shapiro char *errtxt; 45712ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 458c2aa98e2SPeter Wemm 459c2aa98e2SPeter Wemm errno = 0; 46012ed1c7cSGregory Neil Shapiro SM_VA_START(ap, msg); 4613299c2f1SGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap); 46212ed1c7cSGregory Neil Shapiro SM_VA_END(ap); 46312ed1c7cSGregory Neil Shapiro putoutmsg(MsgBuf, false, false); 464c2aa98e2SPeter Wemm 465c2aa98e2SPeter Wemm /* save this message for mailq printing */ 466c2aa98e2SPeter Wemm switch (MsgBuf[0]) 467c2aa98e2SPeter Wemm { 468c2aa98e2SPeter Wemm case '4': 469c2aa98e2SPeter Wemm case '8': 470c2aa98e2SPeter Wemm if (CurEnv->e_message != NULL) 471c2aa98e2SPeter Wemm break; 4723299c2f1SGregory Neil Shapiro /* FALLTHROUGH */ 473c2aa98e2SPeter Wemm 474c2aa98e2SPeter Wemm case '5': 47512ed1c7cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 476c0c4794dSGregory Neil Shapiro sm_free(CurEnv->e_message); 4776f9c8e5bSGregory Neil Shapiro CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 478c2aa98e2SPeter Wemm break; 479c2aa98e2SPeter Wemm } 480c2aa98e2SPeter Wemm } 4816f9c8e5bSGregory Neil Shapiro 4826f9c8e5bSGregory Neil Shapiro 48312ed1c7cSGregory Neil Shapiro /* 484c2aa98e2SPeter Wemm ** NMESSAGE -- print message (not necessarily an error) 485c2aa98e2SPeter Wemm ** 486c2aa98e2SPeter Wemm ** Just like "message" except it never puts the to... tag on. 487c2aa98e2SPeter Wemm ** 488c2aa98e2SPeter Wemm ** Parameters: 48912ed1c7cSGregory Neil Shapiro ** msg -- the message (sm_io_printf fmt) -- if it begins 490c2aa98e2SPeter Wemm ** with a three digit SMTP reply code, that is used, 491c2aa98e2SPeter Wemm ** otherwise 050 is assumed. 49212ed1c7cSGregory Neil Shapiro ** (others) -- sm_io_printf arguments 493c2aa98e2SPeter Wemm ** 494c2aa98e2SPeter Wemm ** Returns: 495c2aa98e2SPeter Wemm ** none 496c2aa98e2SPeter Wemm ** 497c2aa98e2SPeter Wemm ** Side Effects: 498c2aa98e2SPeter Wemm ** none. 499c2aa98e2SPeter Wemm */ 500c2aa98e2SPeter Wemm 501c2aa98e2SPeter Wemm /*VARARGS1*/ 502c2aa98e2SPeter Wemm void 503c2aa98e2SPeter Wemm #ifdef __STDC__ 504c2aa98e2SPeter Wemm nmessage(const char *msg, ...) 5053299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 506c2aa98e2SPeter Wemm nmessage(msg, va_alist) 507c2aa98e2SPeter Wemm const char *msg; 508c2aa98e2SPeter Wemm va_dcl 5093299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 510c2aa98e2SPeter Wemm { 5113299c2f1SGregory Neil Shapiro char *errtxt; 51212ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 513c2aa98e2SPeter Wemm 514c2aa98e2SPeter Wemm errno = 0; 51512ed1c7cSGregory Neil Shapiro SM_VA_START(ap, msg); 5163299c2f1SGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, (char *) NULL, "050", 5173299c2f1SGregory Neil Shapiro (char *) NULL, 0, msg, ap); 51812ed1c7cSGregory Neil Shapiro SM_VA_END(ap); 51912ed1c7cSGregory Neil Shapiro putoutmsg(MsgBuf, false, false); 520c2aa98e2SPeter Wemm 521c2aa98e2SPeter Wemm /* save this message for mailq printing */ 522c2aa98e2SPeter Wemm switch (MsgBuf[0]) 523c2aa98e2SPeter Wemm { 524c2aa98e2SPeter Wemm case '4': 525c2aa98e2SPeter Wemm case '8': 526c2aa98e2SPeter Wemm if (CurEnv->e_message != NULL) 527c2aa98e2SPeter Wemm break; 5283299c2f1SGregory Neil Shapiro /* FALLTHROUGH */ 529c2aa98e2SPeter Wemm 530c2aa98e2SPeter Wemm case '5': 53112ed1c7cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 532c0c4794dSGregory Neil Shapiro sm_free(CurEnv->e_message); 533951742c4SGregory Neil Shapiro CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 534c2aa98e2SPeter Wemm break; 535c2aa98e2SPeter Wemm } 536c2aa98e2SPeter Wemm } 53712ed1c7cSGregory Neil Shapiro /* 538c2aa98e2SPeter Wemm ** PUTOUTMSG -- output error message to transcript and channel 539c2aa98e2SPeter Wemm ** 540c2aa98e2SPeter Wemm ** Parameters: 541c2aa98e2SPeter Wemm ** msg -- message to output (in SMTP format). 54212ed1c7cSGregory Neil Shapiro ** holdmsg -- if true, don't output a copy of the message to 543c2aa98e2SPeter Wemm ** our output channel. 54412ed1c7cSGregory Neil Shapiro ** heldmsg -- if true, this is a previously held message; 545c2aa98e2SPeter Wemm ** don't log it to the transcript file. 546c2aa98e2SPeter Wemm ** 547c2aa98e2SPeter Wemm ** Returns: 548c2aa98e2SPeter Wemm ** none. 549c2aa98e2SPeter Wemm ** 550c2aa98e2SPeter Wemm ** Side Effects: 551c2aa98e2SPeter Wemm ** Outputs msg to the transcript. 552c2aa98e2SPeter Wemm ** If appropriate, outputs it to the channel. 553c2aa98e2SPeter Wemm ** Deletes SMTP reply code number as appropriate. 554c2aa98e2SPeter Wemm */ 555c2aa98e2SPeter Wemm 5563299c2f1SGregory Neil Shapiro static void 557c2aa98e2SPeter Wemm putoutmsg(msg, holdmsg, heldmsg) 558c2aa98e2SPeter Wemm char *msg; 559c2aa98e2SPeter Wemm bool holdmsg; 560c2aa98e2SPeter Wemm bool heldmsg; 561c2aa98e2SPeter Wemm { 562c2aa98e2SPeter Wemm char msgcode = msg[0]; 563951742c4SGregory Neil Shapiro char *errtxt = msg; 564951742c4SGregory Neil Shapiro char *id; 565c2aa98e2SPeter Wemm 566c2aa98e2SPeter Wemm /* display for debugging */ 567c2aa98e2SPeter Wemm if (tTd(54, 8)) 56812ed1c7cSGregory Neil Shapiro sm_dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "", 569c2aa98e2SPeter Wemm heldmsg ? " (held)" : ""); 570c2aa98e2SPeter Wemm 571c2aa98e2SPeter Wemm /* map warnings to something SMTP can handle */ 572c2aa98e2SPeter Wemm if (msgcode == '6') 573c2aa98e2SPeter Wemm msg[0] = '5'; 574c2aa98e2SPeter Wemm else if (msgcode == '8') 575c2aa98e2SPeter Wemm msg[0] = '4'; 576951742c4SGregory Neil Shapiro id = (CurEnv != NULL) ? CurEnv->e_id : NULL; 577c2aa98e2SPeter Wemm 578c2aa98e2SPeter Wemm /* output to transcript if serious */ 579c2aa98e2SPeter Wemm if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL && 580c2aa98e2SPeter Wemm strchr("45", msg[0]) != NULL) 58112ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(CurEnv->e_xfp, SM_TIME_DEFAULT, "%s\n", 58212ed1c7cSGregory Neil Shapiro msg); 583c2aa98e2SPeter Wemm 58412ed1c7cSGregory Neil Shapiro if (LogLevel > 14 && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 585951742c4SGregory Neil Shapiro sm_syslog(LOG_INFO, id, 58612ed1c7cSGregory Neil Shapiro "--- %s%s%s", msg, holdmsg ? " (hold)" : "", 58712ed1c7cSGregory Neil Shapiro heldmsg ? " (held)" : ""); 588c2aa98e2SPeter Wemm 589c2aa98e2SPeter Wemm if (msgcode == '8') 590c2aa98e2SPeter Wemm msg[0] = '0'; 591c2aa98e2SPeter Wemm 592c2aa98e2SPeter Wemm /* output to channel if appropriate */ 593c2aa98e2SPeter Wemm if (!Verbose && msg[0] == '0') 594c2aa98e2SPeter Wemm return; 595c2aa98e2SPeter Wemm if (holdmsg) 596c2aa98e2SPeter Wemm { 597c2aa98e2SPeter Wemm /* save for possible future display */ 598c2aa98e2SPeter Wemm msg[0] = msgcode; 5993299c2f1SGregory Neil Shapiro if (HeldMessageBuf[0] == '5' && msgcode == '4') 6003299c2f1SGregory Neil Shapiro return; 601951742c4SGregory Neil Shapiro (void) sm_strlcpy(HeldMessageBuf, msg, sizeof(HeldMessageBuf)); 602c2aa98e2SPeter Wemm return; 603c2aa98e2SPeter Wemm } 604c2aa98e2SPeter Wemm 60512ed1c7cSGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 606c2aa98e2SPeter Wemm 607c2aa98e2SPeter Wemm if (OutChannel == NULL) 608c2aa98e2SPeter Wemm return; 609c2aa98e2SPeter Wemm 6103299c2f1SGregory Neil Shapiro /* find actual text of error (after SMTP status codes) */ 6113299c2f1SGregory Neil Shapiro if (ISSMTPREPLY(errtxt)) 6123299c2f1SGregory Neil Shapiro { 6133299c2f1SGregory Neil Shapiro int l; 6143299c2f1SGregory Neil Shapiro 6153299c2f1SGregory Neil Shapiro errtxt += 4; 6163299c2f1SGregory Neil Shapiro l = isenhsc(errtxt, ' '); 6173299c2f1SGregory Neil Shapiro if (l <= 0) 6183299c2f1SGregory Neil Shapiro l = isenhsc(errtxt, '\0'); 6193299c2f1SGregory Neil Shapiro if (l > 0) 6203299c2f1SGregory Neil Shapiro errtxt += l + 1; 6213299c2f1SGregory Neil Shapiro } 6223299c2f1SGregory Neil Shapiro 623c2aa98e2SPeter Wemm /* if DisConnected, OutChannel now points to the transcript */ 624c2aa98e2SPeter Wemm if (!DisConnected && 625c2aa98e2SPeter Wemm (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP)) 62612ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\r\n", 62712ed1c7cSGregory Neil Shapiro msg); 628c2aa98e2SPeter Wemm else 62912ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\n", 63012ed1c7cSGregory Neil Shapiro errtxt); 631c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 63212ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 63312ed1c7cSGregory Neil Shapiro "%05d >>> %s\n", (int) CurrentPid, 63412ed1c7cSGregory Neil Shapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON) 63512ed1c7cSGregory Neil Shapiro ? msg : errtxt); 63612ed1c7cSGregory Neil Shapiro #if !PIPELINING 63712ed1c7cSGregory Neil Shapiro /* XXX can't flush here for SMTP pipelining */ 638c2aa98e2SPeter Wemm if (msg[3] == ' ') 63912ed1c7cSGregory Neil Shapiro (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT); 64012ed1c7cSGregory Neil Shapiro if (!sm_io_error(OutChannel) || DisConnected) 641c2aa98e2SPeter Wemm return; 642c2aa98e2SPeter Wemm 643c2aa98e2SPeter Wemm /* 644c2aa98e2SPeter Wemm ** Error on output -- if reporting lost channel, just ignore it. 645c2aa98e2SPeter Wemm ** Also, ignore errors from QUIT response (221 message) -- some 646c2aa98e2SPeter Wemm ** rude servers don't read result. 647c2aa98e2SPeter Wemm */ 648c2aa98e2SPeter Wemm 64912ed1c7cSGregory Neil Shapiro if (InChannel == NULL || sm_io_eof(InChannel) || 65012ed1c7cSGregory Neil Shapiro sm_io_error(InChannel) || strncmp(msg, "221", 3) == 0) 651c2aa98e2SPeter Wemm return; 652c2aa98e2SPeter Wemm 653c2aa98e2SPeter Wemm /* can't call syserr, 'cause we are using MsgBuf */ 65412ed1c7cSGregory Neil Shapiro HoldErrs = true; 655c2aa98e2SPeter Wemm if (LogLevel > 0) 656951742c4SGregory Neil Shapiro sm_syslog(LOG_CRIT, id, 657c2aa98e2SPeter Wemm "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", 65812ed1c7cSGregory Neil Shapiro CURHOSTNAME, 65912ed1c7cSGregory Neil Shapiro shortenstring(msg, MAXSHORTSTR), sm_errstring(errno)); 66012ed1c7cSGregory Neil Shapiro #endif /* !PIPELINING */ 661c2aa98e2SPeter Wemm } 66212ed1c7cSGregory Neil Shapiro /* 663c2aa98e2SPeter Wemm ** PUTERRMSG -- like putoutmsg, but does special processing for error messages 664c2aa98e2SPeter Wemm ** 665c2aa98e2SPeter Wemm ** Parameters: 666c2aa98e2SPeter Wemm ** msg -- the message to output. 667c2aa98e2SPeter Wemm ** 668c2aa98e2SPeter Wemm ** Returns: 669c2aa98e2SPeter Wemm ** none. 670c2aa98e2SPeter Wemm ** 671c2aa98e2SPeter Wemm ** Side Effects: 672c2aa98e2SPeter Wemm ** Sets the fatal error bit in the envelope as appropriate. 673c2aa98e2SPeter Wemm */ 674c2aa98e2SPeter Wemm 6753299c2f1SGregory Neil Shapiro static void 676c2aa98e2SPeter Wemm puterrmsg(msg) 677c2aa98e2SPeter Wemm char *msg; 678c2aa98e2SPeter Wemm { 679c2aa98e2SPeter Wemm char msgcode = msg[0]; 680c2aa98e2SPeter Wemm 681c2aa98e2SPeter Wemm /* output the message as usual */ 68212ed1c7cSGregory Neil Shapiro putoutmsg(msg, HoldErrs, false); 683c2aa98e2SPeter Wemm 684c2aa98e2SPeter Wemm /* be careful about multiple error messages */ 685c2aa98e2SPeter Wemm if (OnlyOneError) 68612ed1c7cSGregory Neil Shapiro HoldErrs = true; 687c2aa98e2SPeter Wemm 688c2aa98e2SPeter Wemm /* signal the error */ 689c2aa98e2SPeter Wemm Errors++; 690c2aa98e2SPeter Wemm 691c2aa98e2SPeter Wemm if (CurEnv == NULL) 692c2aa98e2SPeter Wemm return; 693c2aa98e2SPeter Wemm 694c2aa98e2SPeter Wemm if (msgcode == '6') 695c2aa98e2SPeter Wemm { 696c2aa98e2SPeter Wemm /* notify the postmaster */ 697c2aa98e2SPeter Wemm CurEnv->e_flags |= EF_PM_NOTIFY; 698c2aa98e2SPeter Wemm } 699c2aa98e2SPeter Wemm else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags)) 700c2aa98e2SPeter Wemm { 701c2aa98e2SPeter Wemm /* mark long-term fatal errors */ 702c2aa98e2SPeter Wemm CurEnv->e_flags |= EF_FATALERRS; 703c2aa98e2SPeter Wemm } 704c2aa98e2SPeter Wemm } 70512ed1c7cSGregory Neil Shapiro /* 7063299c2f1SGregory Neil Shapiro ** ISENHSC -- check whether a string contains an enhanced status code 7073299c2f1SGregory Neil Shapiro ** 7083299c2f1SGregory Neil Shapiro ** Parameters: 7093299c2f1SGregory Neil Shapiro ** s -- string with possible enhanced status code. 7103299c2f1SGregory Neil Shapiro ** delim -- delim for enhanced status code. 7113299c2f1SGregory Neil Shapiro ** 7123299c2f1SGregory Neil Shapiro ** Returns: 7133299c2f1SGregory Neil Shapiro ** 0 -- no enhanced status code. 7143299c2f1SGregory Neil Shapiro ** >4 -- length of enhanced status code. 7153299c2f1SGregory Neil Shapiro ** 7163299c2f1SGregory Neil Shapiro ** Side Effects: 7173299c2f1SGregory Neil Shapiro ** none. 7183299c2f1SGregory Neil Shapiro */ 7193299c2f1SGregory Neil Shapiro int 7203299c2f1SGregory Neil Shapiro isenhsc(s, delim) 7213299c2f1SGregory Neil Shapiro const char *s; 7223299c2f1SGregory Neil Shapiro int delim; 7233299c2f1SGregory Neil Shapiro { 7243299c2f1SGregory Neil Shapiro int l, h; 7253299c2f1SGregory Neil Shapiro 7263299c2f1SGregory Neil Shapiro if (s == NULL) 7273299c2f1SGregory Neil Shapiro return 0; 7283299c2f1SGregory Neil Shapiro if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) 7293299c2f1SGregory Neil Shapiro return 0; 7303299c2f1SGregory Neil Shapiro h = 0; 7313299c2f1SGregory Neil Shapiro l = 2; 7323299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 7333299c2f1SGregory Neil Shapiro ++h; 7343299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != '.') 7353299c2f1SGregory Neil Shapiro return 0; 7363299c2f1SGregory Neil Shapiro l += h + 1; 7373299c2f1SGregory Neil Shapiro h = 0; 7383299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 7393299c2f1SGregory Neil Shapiro ++h; 7403299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != delim) 7413299c2f1SGregory Neil Shapiro return 0; 7423299c2f1SGregory Neil Shapiro return l + h; 7433299c2f1SGregory Neil Shapiro } 74412ed1c7cSGregory Neil Shapiro /* 7453299c2f1SGregory Neil Shapiro ** EXTENHSC -- check and extract an enhanced status code 7463299c2f1SGregory Neil Shapiro ** 7473299c2f1SGregory Neil Shapiro ** Parameters: 7483299c2f1SGregory Neil Shapiro ** s -- string with possible enhanced status code. 7493299c2f1SGregory Neil Shapiro ** delim -- delim for enhanced status code. 7503299c2f1SGregory Neil Shapiro ** e -- pointer to storage for enhanced status code. 7513299c2f1SGregory Neil Shapiro ** must be != NULL and have space for at least 7523299c2f1SGregory Neil Shapiro ** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3}) 7533299c2f1SGregory Neil Shapiro ** 7543299c2f1SGregory Neil Shapiro ** Returns: 7553299c2f1SGregory Neil Shapiro ** 0 -- no enhanced status code. 7563299c2f1SGregory Neil Shapiro ** >4 -- length of enhanced status code. 7573299c2f1SGregory Neil Shapiro ** 7583299c2f1SGregory Neil Shapiro ** Side Effects: 7593299c2f1SGregory Neil Shapiro ** fills e with enhanced status code. 7603299c2f1SGregory Neil Shapiro */ 76112ed1c7cSGregory Neil Shapiro 7623299c2f1SGregory Neil Shapiro int 7633299c2f1SGregory Neil Shapiro extenhsc(s, delim, e) 7643299c2f1SGregory Neil Shapiro const char *s; 7653299c2f1SGregory Neil Shapiro int delim; 7663299c2f1SGregory Neil Shapiro char *e; 7673299c2f1SGregory Neil Shapiro { 7683299c2f1SGregory Neil Shapiro int l, h; 7693299c2f1SGregory Neil Shapiro 7703299c2f1SGregory Neil Shapiro if (s == NULL) 7713299c2f1SGregory Neil Shapiro return 0; 7723299c2f1SGregory Neil Shapiro if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) 7733299c2f1SGregory Neil Shapiro return 0; 7743299c2f1SGregory Neil Shapiro h = 0; 7753299c2f1SGregory Neil Shapiro l = 2; 7763299c2f1SGregory Neil Shapiro e[0] = s[0]; 7773299c2f1SGregory Neil Shapiro e[1] = '.'; 7783299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 7793299c2f1SGregory Neil Shapiro { 7803299c2f1SGregory Neil Shapiro e[l + h] = s[l + h]; 7813299c2f1SGregory Neil Shapiro ++h; 7823299c2f1SGregory Neil Shapiro } 7833299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != '.') 7843299c2f1SGregory Neil Shapiro return 0; 7853299c2f1SGregory Neil Shapiro e[l + h] = '.'; 7863299c2f1SGregory Neil Shapiro l += h + 1; 7873299c2f1SGregory Neil Shapiro h = 0; 7883299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 7893299c2f1SGregory Neil Shapiro { 7903299c2f1SGregory Neil Shapiro e[l + h] = s[l + h]; 7913299c2f1SGregory Neil Shapiro ++h; 7923299c2f1SGregory Neil Shapiro } 7933299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != delim) 7943299c2f1SGregory Neil Shapiro return 0; 7953299c2f1SGregory Neil Shapiro e[l + h] = '\0'; 7963299c2f1SGregory Neil Shapiro return l + h; 7973299c2f1SGregory Neil Shapiro } 79812ed1c7cSGregory Neil Shapiro /* 799c2aa98e2SPeter Wemm ** FMTMSG -- format a message into buffer. 800c2aa98e2SPeter Wemm ** 801c2aa98e2SPeter Wemm ** Parameters: 8023299c2f1SGregory Neil Shapiro ** eb -- error buffer to get result -- MUST BE MsgBuf. 803c2aa98e2SPeter Wemm ** to -- the recipient tag for this message. 8043299c2f1SGregory Neil Shapiro ** num -- default three digit SMTP reply code. 8053299c2f1SGregory Neil Shapiro ** enhsc -- enhanced status code. 806c2aa98e2SPeter Wemm ** en -- the error number to display. 807c2aa98e2SPeter Wemm ** fmt -- format of string. 8083299c2f1SGregory Neil Shapiro ** ap -- arguments for fmt. 809c2aa98e2SPeter Wemm ** 810c2aa98e2SPeter Wemm ** Returns: 8113299c2f1SGregory Neil Shapiro ** pointer to error text beyond status codes. 812c2aa98e2SPeter Wemm ** 813c2aa98e2SPeter Wemm ** Side Effects: 814c2aa98e2SPeter Wemm ** none. 815c2aa98e2SPeter Wemm */ 816c2aa98e2SPeter Wemm 8173299c2f1SGregory Neil Shapiro static char * 8183299c2f1SGregory Neil Shapiro fmtmsg(eb, to, num, enhsc, eno, fmt, ap) 819c2aa98e2SPeter Wemm register char *eb; 820c2aa98e2SPeter Wemm const char *to; 821c2aa98e2SPeter Wemm const char *num; 8223299c2f1SGregory Neil Shapiro const char *enhsc; 823c2aa98e2SPeter Wemm int eno; 824c2aa98e2SPeter Wemm const char *fmt; 82512ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 826c2aa98e2SPeter Wemm { 827c2aa98e2SPeter Wemm char del; 828c2aa98e2SPeter Wemm int l; 829951742c4SGregory Neil Shapiro int spaceleft = sizeof(MsgBuf); 8303299c2f1SGregory Neil Shapiro char *errtxt; 831c2aa98e2SPeter Wemm 832c2aa98e2SPeter Wemm /* output the reply code */ 8333299c2f1SGregory Neil Shapiro if (ISSMTPCODE(fmt)) 834c2aa98e2SPeter Wemm { 835c2aa98e2SPeter Wemm num = fmt; 836c2aa98e2SPeter Wemm fmt += 4; 837c2aa98e2SPeter Wemm } 838c2aa98e2SPeter Wemm if (num[3] == '-') 839c2aa98e2SPeter Wemm del = '-'; 840c2aa98e2SPeter Wemm else 841c2aa98e2SPeter Wemm del = ' '; 84212ed1c7cSGregory Neil Shapiro if (SoftBounce && num[0] == '5') 84312ed1c7cSGregory Neil Shapiro { 84412ed1c7cSGregory Neil Shapiro /* replace 5 by 4 */ 84512ed1c7cSGregory Neil Shapiro (void) sm_snprintf(eb, spaceleft, "4%2.2s%c", num + 1, del); 84612ed1c7cSGregory Neil Shapiro } 84712ed1c7cSGregory Neil Shapiro else 84812ed1c7cSGregory Neil Shapiro (void) sm_snprintf(eb, spaceleft, "%3.3s%c", num, del); 849c2aa98e2SPeter Wemm eb += 4; 850c2aa98e2SPeter Wemm spaceleft -= 4; 851c2aa98e2SPeter Wemm 8523299c2f1SGregory Neil Shapiro if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4) 8533299c2f1SGregory Neil Shapiro { 8543299c2f1SGregory Neil Shapiro /* copy enh.status code including trailing blank */ 8553299c2f1SGregory Neil Shapiro l++; 85612ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(eb, fmt, l + 1); 8573299c2f1SGregory Neil Shapiro eb += l; 8583299c2f1SGregory Neil Shapiro spaceleft -= l; 8593299c2f1SGregory Neil Shapiro fmt += l; 8603299c2f1SGregory Neil Shapiro } 8613299c2f1SGregory Neil Shapiro else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4) 8623299c2f1SGregory Neil Shapiro { 8633299c2f1SGregory Neil Shapiro /* copy enh.status code */ 86412ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(eb, enhsc, l + 1); 8653299c2f1SGregory Neil Shapiro eb[l] = ' '; 8663299c2f1SGregory Neil Shapiro eb[++l] = '\0'; 8673299c2f1SGregory Neil Shapiro eb += l; 8683299c2f1SGregory Neil Shapiro spaceleft -= l; 8693299c2f1SGregory Neil Shapiro } 87012ed1c7cSGregory Neil Shapiro if (SoftBounce && eb[-l] == '5') 87112ed1c7cSGregory Neil Shapiro { 87212ed1c7cSGregory Neil Shapiro /* replace 5 by 4 */ 87312ed1c7cSGregory Neil Shapiro eb[-l] = '4'; 87412ed1c7cSGregory Neil Shapiro } 8753299c2f1SGregory Neil Shapiro errtxt = eb; 8763299c2f1SGregory Neil Shapiro 877c2aa98e2SPeter Wemm /* output the file name and line number */ 878c2aa98e2SPeter Wemm if (FileName != NULL) 879c2aa98e2SPeter Wemm { 88012ed1c7cSGregory Neil Shapiro (void) sm_snprintf(eb, spaceleft, "%s: line %d: ", 881c2aa98e2SPeter Wemm shortenstring(FileName, 83), LineNumber); 882c2aa98e2SPeter Wemm eb += (l = strlen(eb)); 883c2aa98e2SPeter Wemm spaceleft -= l; 884c2aa98e2SPeter Wemm } 885c2aa98e2SPeter Wemm 88656477e1eSGregory Neil Shapiro /* 88756477e1eSGregory Neil Shapiro ** output the "to" address only if it is defined and one of the 88856477e1eSGregory Neil Shapiro ** following codes is used: 88956477e1eSGregory Neil Shapiro ** 050 internal notices, e.g., alias expansion 89056477e1eSGregory Neil Shapiro ** 250 Ok 89156477e1eSGregory Neil Shapiro ** 252 Cannot VRFY user, but will accept message and attempt delivery 89256477e1eSGregory Neil Shapiro ** 450 Requested mail action not taken: mailbox unavailable 89356477e1eSGregory Neil Shapiro ** 550 Requested action not taken: mailbox unavailable 89456477e1eSGregory Neil Shapiro ** 553 Requested action not taken: mailbox name not allowed 89556477e1eSGregory Neil Shapiro ** 89656477e1eSGregory Neil Shapiro ** Notice: this still isn't "the right thing", this code shouldn't 89756477e1eSGregory Neil Shapiro ** (indirectly) depend on CurEnv->e_to. 89856477e1eSGregory Neil Shapiro */ 89956477e1eSGregory Neil Shapiro 900c2aa98e2SPeter Wemm if (to != NULL && to[0] != '\0' && 90156477e1eSGregory Neil Shapiro (strncmp(num, "050", 3) == 0 || 90256477e1eSGregory Neil Shapiro strncmp(num, "250", 3) == 0 || 90356477e1eSGregory Neil Shapiro strncmp(num, "252", 3) == 0 || 90456477e1eSGregory Neil Shapiro strncmp(num, "450", 3) == 0 || 90556477e1eSGregory Neil Shapiro strncmp(num, "550", 3) == 0 || 90656477e1eSGregory Neil Shapiro strncmp(num, "553", 3) == 0)) 907c2aa98e2SPeter Wemm { 90812ed1c7cSGregory Neil Shapiro (void) sm_strlcpyn(eb, spaceleft, 2, 90912ed1c7cSGregory Neil Shapiro shortenstring(to, MAXSHORTSTR), "... "); 910c2aa98e2SPeter Wemm spaceleft -= strlen(eb); 911c2aa98e2SPeter Wemm while (*eb != '\0') 912c2aa98e2SPeter Wemm *eb++ &= 0177; 913c2aa98e2SPeter Wemm } 914c2aa98e2SPeter Wemm 915c2aa98e2SPeter Wemm /* output the message */ 91612ed1c7cSGregory Neil Shapiro (void) sm_vsnprintf(eb, spaceleft, fmt, ap); 917c2aa98e2SPeter Wemm spaceleft -= strlen(eb); 918c2aa98e2SPeter Wemm while (*eb != '\0') 919c2aa98e2SPeter Wemm *eb++ &= 0177; 920c2aa98e2SPeter Wemm 921c2aa98e2SPeter Wemm /* output the error code, if any */ 922c2aa98e2SPeter Wemm if (eno != 0) 92312ed1c7cSGregory Neil Shapiro (void) sm_strlcpyn(eb, spaceleft, 2, ": ", sm_errstring(eno)); 9243299c2f1SGregory Neil Shapiro 9253299c2f1SGregory Neil Shapiro return errtxt; 926c2aa98e2SPeter Wemm } 92712ed1c7cSGregory Neil Shapiro /* 928c2aa98e2SPeter Wemm ** BUFFER_ERRORS -- arrange to buffer future error messages 929c2aa98e2SPeter Wemm ** 930c2aa98e2SPeter Wemm ** Parameters: 931c2aa98e2SPeter Wemm ** none 932c2aa98e2SPeter Wemm ** 933c2aa98e2SPeter Wemm ** Returns: 934c2aa98e2SPeter Wemm ** none. 935c2aa98e2SPeter Wemm */ 936c2aa98e2SPeter Wemm 937c2aa98e2SPeter Wemm void 938c2aa98e2SPeter Wemm buffer_errors() 939c2aa98e2SPeter Wemm { 940c2aa98e2SPeter Wemm HeldMessageBuf[0] = '\0'; 94112ed1c7cSGregory Neil Shapiro HoldErrs = true; 942c2aa98e2SPeter Wemm } 94312ed1c7cSGregory Neil Shapiro /* 944c2aa98e2SPeter Wemm ** FLUSH_ERRORS -- flush the held error message buffer 945c2aa98e2SPeter Wemm ** 946c2aa98e2SPeter Wemm ** Parameters: 947c2aa98e2SPeter Wemm ** print -- if set, print the message, otherwise just 948c2aa98e2SPeter Wemm ** delete it. 949c2aa98e2SPeter Wemm ** 950c2aa98e2SPeter Wemm ** Returns: 951c2aa98e2SPeter Wemm ** none. 952c2aa98e2SPeter Wemm */ 953c2aa98e2SPeter Wemm 954c2aa98e2SPeter Wemm void 955c2aa98e2SPeter Wemm flush_errors(print) 956c2aa98e2SPeter Wemm bool print; 957c2aa98e2SPeter Wemm { 958c2aa98e2SPeter Wemm if (print && HeldMessageBuf[0] != '\0') 95912ed1c7cSGregory Neil Shapiro putoutmsg(HeldMessageBuf, false, true); 960c2aa98e2SPeter Wemm HeldMessageBuf[0] = '\0'; 96112ed1c7cSGregory Neil Shapiro HoldErrs = false; 962c2aa98e2SPeter Wemm } 96312ed1c7cSGregory Neil Shapiro /* 96412ed1c7cSGregory Neil Shapiro ** SM_ERRSTRING -- return string description of error code 965c2aa98e2SPeter Wemm ** 966c2aa98e2SPeter Wemm ** Parameters: 967c2aa98e2SPeter Wemm ** errnum -- the error number to translate 968c2aa98e2SPeter Wemm ** 969c2aa98e2SPeter Wemm ** Returns: 970c2aa98e2SPeter Wemm ** A string description of errnum. 971c2aa98e2SPeter Wemm ** 972c2aa98e2SPeter Wemm ** Side Effects: 973c2aa98e2SPeter Wemm ** none. 974c2aa98e2SPeter Wemm */ 975c2aa98e2SPeter Wemm 976c2aa98e2SPeter Wemm const char * 97712ed1c7cSGregory Neil Shapiro sm_errstring(errnum) 978c2aa98e2SPeter Wemm int errnum; 979c2aa98e2SPeter Wemm { 980c2aa98e2SPeter Wemm char *dnsmsg; 981c2aa98e2SPeter Wemm char *bp; 982c2aa98e2SPeter Wemm static char buf[MAXLINE]; 98312ed1c7cSGregory Neil Shapiro #if HASSTRERROR 98412ed1c7cSGregory Neil Shapiro char *err; 98512ed1c7cSGregory Neil Shapiro char errbuf[30]; 98612ed1c7cSGregory Neil Shapiro #endif /* HASSTRERROR */ 987c2aa98e2SPeter Wemm #if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) 988c2aa98e2SPeter Wemm extern char *sys_errlist[]; 989c2aa98e2SPeter Wemm extern int sys_nerr; 9903299c2f1SGregory Neil Shapiro #endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */ 991c2aa98e2SPeter Wemm 992c2aa98e2SPeter Wemm /* 993c2aa98e2SPeter Wemm ** Handle special network error codes. 994c2aa98e2SPeter Wemm ** 995c2aa98e2SPeter Wemm ** These are 4.2/4.3bsd specific; they should be in daemon.c. 996c2aa98e2SPeter Wemm */ 997c2aa98e2SPeter Wemm 998c2aa98e2SPeter Wemm dnsmsg = NULL; 999c2aa98e2SPeter Wemm switch (errnum) 1000c2aa98e2SPeter Wemm { 1001c2aa98e2SPeter Wemm case ETIMEDOUT: 1002c2aa98e2SPeter Wemm case ECONNRESET: 1003c2aa98e2SPeter Wemm bp = buf; 1004c2aa98e2SPeter Wemm #if HASSTRERROR 100512ed1c7cSGregory Neil Shapiro err = strerror(errnum); 100612ed1c7cSGregory Neil Shapiro if (err == NULL) 100712ed1c7cSGregory Neil Shapiro { 1008951742c4SGregory Neil Shapiro (void) sm_snprintf(errbuf, sizeof(errbuf), 100912ed1c7cSGregory Neil Shapiro "Error %d", errnum); 101012ed1c7cSGregory Neil Shapiro err = errbuf; 101112ed1c7cSGregory Neil Shapiro } 101212ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, err, SPACELEFT(buf, bp)); 10133299c2f1SGregory Neil Shapiro #else /* HASSTRERROR */ 1014c2aa98e2SPeter Wemm if (errnum >= 0 && errnum < sys_nerr) 101512ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, sys_errlist[errnum], 101612ed1c7cSGregory Neil Shapiro SPACELEFT(buf, bp)); 1017c2aa98e2SPeter Wemm else 101812ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 101912ed1c7cSGregory Neil Shapiro "Error %d", errnum); 10203299c2f1SGregory Neil Shapiro #endif /* HASSTRERROR */ 1021c2aa98e2SPeter Wemm bp += strlen(bp); 1022c2aa98e2SPeter Wemm if (CurHostName != NULL) 1023c2aa98e2SPeter Wemm { 1024c2aa98e2SPeter Wemm if (errnum == ETIMEDOUT) 1025c2aa98e2SPeter Wemm { 102612ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 102712ed1c7cSGregory Neil Shapiro " with "); 1028c2aa98e2SPeter Wemm bp += strlen(bp); 1029c2aa98e2SPeter Wemm } 1030c2aa98e2SPeter Wemm else 1031c2aa98e2SPeter Wemm { 1032c2aa98e2SPeter Wemm bp = buf; 103312ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 1034c2aa98e2SPeter Wemm "Connection reset by "); 1035c2aa98e2SPeter Wemm bp += strlen(bp); 1036c2aa98e2SPeter Wemm } 103712ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, 103812ed1c7cSGregory Neil Shapiro shortenstring(CurHostName, MAXSHORTSTR), 103912ed1c7cSGregory Neil Shapiro SPACELEFT(buf, bp)); 1040c2aa98e2SPeter Wemm bp += strlen(buf); 1041c2aa98e2SPeter Wemm } 1042c2aa98e2SPeter Wemm if (SmtpPhase != NULL) 1043c2aa98e2SPeter Wemm { 104412ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 104512ed1c7cSGregory Neil Shapiro " during %s", SmtpPhase); 1046c2aa98e2SPeter Wemm } 10473299c2f1SGregory Neil Shapiro return buf; 1048c2aa98e2SPeter Wemm 1049c2aa98e2SPeter Wemm case EHOSTDOWN: 1050c2aa98e2SPeter Wemm if (CurHostName == NULL) 1051c2aa98e2SPeter Wemm break; 1052951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "Host %s is down", 1053c2aa98e2SPeter Wemm shortenstring(CurHostName, MAXSHORTSTR)); 10543299c2f1SGregory Neil Shapiro return buf; 1055c2aa98e2SPeter Wemm 1056c2aa98e2SPeter Wemm case ECONNREFUSED: 1057c2aa98e2SPeter Wemm if (CurHostName == NULL) 1058c2aa98e2SPeter Wemm break; 1059951742c4SGregory Neil Shapiro (void) sm_strlcpyn(buf, sizeof(buf), 2, "Connection refused by ", 1060c2aa98e2SPeter Wemm shortenstring(CurHostName, MAXSHORTSTR)); 10613299c2f1SGregory Neil Shapiro return buf; 1062c2aa98e2SPeter Wemm 1063c2aa98e2SPeter Wemm #if NAMED_BIND 1064c2aa98e2SPeter Wemm case HOST_NOT_FOUND + E_DNSBASE: 1065c2aa98e2SPeter Wemm dnsmsg = "host not found"; 1066c2aa98e2SPeter Wemm break; 1067c2aa98e2SPeter Wemm 1068c2aa98e2SPeter Wemm case TRY_AGAIN + E_DNSBASE: 1069c2aa98e2SPeter Wemm dnsmsg = "host name lookup failure"; 1070c2aa98e2SPeter Wemm break; 1071c2aa98e2SPeter Wemm 1072c2aa98e2SPeter Wemm case NO_RECOVERY + E_DNSBASE: 1073c2aa98e2SPeter Wemm dnsmsg = "non-recoverable error"; 1074c2aa98e2SPeter Wemm break; 1075c2aa98e2SPeter Wemm 1076c2aa98e2SPeter Wemm case NO_DATA + E_DNSBASE: 1077c2aa98e2SPeter Wemm dnsmsg = "no data known"; 1078c2aa98e2SPeter Wemm break; 10793299c2f1SGregory Neil Shapiro #endif /* NAMED_BIND */ 1080c2aa98e2SPeter Wemm 1081c2aa98e2SPeter Wemm case EPERM: 1082c2aa98e2SPeter Wemm /* SunOS gives "Not owner" -- this is the POSIX message */ 1083c2aa98e2SPeter Wemm return "Operation not permitted"; 1084c2aa98e2SPeter Wemm 1085c2aa98e2SPeter Wemm /* 1086c2aa98e2SPeter Wemm ** Error messages used internally in sendmail. 1087c2aa98e2SPeter Wemm */ 1088c2aa98e2SPeter Wemm 1089c2aa98e2SPeter Wemm case E_SM_OPENTIMEOUT: 1090c2aa98e2SPeter Wemm return "Timeout on file open"; 1091c2aa98e2SPeter Wemm 1092c2aa98e2SPeter Wemm case E_SM_NOSLINK: 1093c2aa98e2SPeter Wemm return "Symbolic links not allowed"; 1094c2aa98e2SPeter Wemm 1095c2aa98e2SPeter Wemm case E_SM_NOHLINK: 1096c2aa98e2SPeter Wemm return "Hard links not allowed"; 1097c2aa98e2SPeter Wemm 1098c2aa98e2SPeter Wemm case E_SM_REGONLY: 1099c2aa98e2SPeter Wemm return "Regular files only"; 1100c2aa98e2SPeter Wemm 1101c2aa98e2SPeter Wemm case E_SM_ISEXEC: 1102c2aa98e2SPeter Wemm return "Executable files not allowed"; 1103c2aa98e2SPeter Wemm 1104c2aa98e2SPeter Wemm case E_SM_WWDIR: 1105c2aa98e2SPeter Wemm return "World writable directory"; 1106c2aa98e2SPeter Wemm 1107c2aa98e2SPeter Wemm case E_SM_GWDIR: 1108c2aa98e2SPeter Wemm return "Group writable directory"; 1109c2aa98e2SPeter Wemm 1110c2aa98e2SPeter Wemm case E_SM_FILECHANGE: 1111c2aa98e2SPeter Wemm return "File changed after open"; 1112c2aa98e2SPeter Wemm 1113c2aa98e2SPeter Wemm case E_SM_WWFILE: 1114c2aa98e2SPeter Wemm return "World writable file"; 1115c2aa98e2SPeter Wemm 1116c2aa98e2SPeter Wemm case E_SM_GWFILE: 1117c2aa98e2SPeter Wemm return "Group writable file"; 11183299c2f1SGregory Neil Shapiro 11193299c2f1SGregory Neil Shapiro case E_SM_GRFILE: 11203299c2f1SGregory Neil Shapiro return "Group readable file"; 11213299c2f1SGregory Neil Shapiro 11223299c2f1SGregory Neil Shapiro case E_SM_WRFILE: 11233299c2f1SGregory Neil Shapiro return "World readable file"; 1124c2aa98e2SPeter Wemm } 1125c2aa98e2SPeter Wemm 1126c2aa98e2SPeter Wemm if (dnsmsg != NULL) 1127c2aa98e2SPeter Wemm { 1128c2aa98e2SPeter Wemm bp = buf; 1129951742c4SGregory Neil Shapiro bp += sm_strlcpy(bp, "Name server: ", sizeof(buf)); 1130c2aa98e2SPeter Wemm if (CurHostName != NULL) 1131c2aa98e2SPeter Wemm { 113212ed1c7cSGregory Neil Shapiro (void) sm_strlcpyn(bp, SPACELEFT(buf, bp), 2, 113312ed1c7cSGregory Neil Shapiro shortenstring(CurHostName, MAXSHORTSTR), ": "); 1134c2aa98e2SPeter Wemm bp += strlen(bp); 1135c2aa98e2SPeter Wemm } 113612ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, dnsmsg, SPACELEFT(buf, bp)); 1137c2aa98e2SPeter Wemm return buf; 1138c2aa98e2SPeter Wemm } 1139c2aa98e2SPeter Wemm 114012ed1c7cSGregory Neil Shapiro #if LDAPMAP 11413299c2f1SGregory Neil Shapiro if (errnum >= E_LDAPBASE) 11423299c2f1SGregory Neil Shapiro return ldap_err2string(errnum - E_LDAPBASE); 11433299c2f1SGregory Neil Shapiro #endif /* LDAPMAP */ 11443299c2f1SGregory Neil Shapiro 1145c2aa98e2SPeter Wemm #if HASSTRERROR 114612ed1c7cSGregory Neil Shapiro err = strerror(errnum); 114712ed1c7cSGregory Neil Shapiro if (err == NULL) 114812ed1c7cSGregory Neil Shapiro { 1149951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum); 115012ed1c7cSGregory Neil Shapiro return buf; 115112ed1c7cSGregory Neil Shapiro } 115212ed1c7cSGregory Neil Shapiro return err; 11533299c2f1SGregory Neil Shapiro #else /* HASSTRERROR */ 1154c2aa98e2SPeter Wemm if (errnum > 0 && errnum < sys_nerr) 11553299c2f1SGregory Neil Shapiro return sys_errlist[errnum]; 1156c2aa98e2SPeter Wemm 1157951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum); 11583299c2f1SGregory Neil Shapiro return buf; 11593299c2f1SGregory Neil Shapiro #endif /* HASSTRERROR */ 1160c2aa98e2SPeter Wemm } 1161