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 164313cc83SGregory 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: 97*da7d7b9cSGregory 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; 130*da7d7b9cSGregory Neil Shapiro bool panic, exiting, keep; 1313299c2f1SGregory Neil Shapiro char *user; 1323299c2f1SGregory Neil Shapiro char *enhsc; 1333299c2f1SGregory Neil Shapiro char *errtxt; 134c2aa98e2SPeter Wemm struct passwd *pw; 135c2aa98e2SPeter Wemm char ubuf[80]; 13612ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 137c2aa98e2SPeter Wemm 138*da7d7b9cSGregory Neil Shapiro panic = exiting = keep = false; 13912ed1c7cSGregory Neil Shapiro switch (*fmt) 140c2aa98e2SPeter Wemm { 14112ed1c7cSGregory Neil Shapiro case '!': 14212ed1c7cSGregory Neil Shapiro ++fmt; 143*da7d7b9cSGregory Neil Shapiro panic = exiting = true; 14412ed1c7cSGregory Neil Shapiro break; 14512ed1c7cSGregory Neil Shapiro case '@': 14612ed1c7cSGregory Neil Shapiro ++fmt; 14712ed1c7cSGregory Neil Shapiro exiting = true; 14812ed1c7cSGregory Neil Shapiro break; 149*da7d7b9cSGregory Neil Shapiro case '+': 150*da7d7b9cSGregory Neil Shapiro ++fmt; 151*da7d7b9cSGregory Neil Shapiro keep = true; 152*da7d7b9cSGregory Neil Shapiro break; 15312ed1c7cSGregory Neil Shapiro default: 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 */ 185*da7d7b9cSGregory Neil Shapiro if (!panic && CurEnv != NULL && (!keep || CurEnv->e_message == 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 482*da7d7b9cSGregory Neil Shapiro #if _FFR_PROXY 483*da7d7b9cSGregory Neil Shapiro /* 484*da7d7b9cSGregory Neil Shapiro ** EMESSAGE -- print message (not necessarily an error) 485*da7d7b9cSGregory Neil Shapiro ** (same as message() but requires reply code and enhanced status code) 486*da7d7b9cSGregory Neil Shapiro ** 487*da7d7b9cSGregory Neil Shapiro ** Parameters: 488*da7d7b9cSGregory Neil Shapiro ** replycode -- SMTP reply code. 489*da7d7b9cSGregory Neil Shapiro ** enhsc -- enhanced status code. 490*da7d7b9cSGregory Neil Shapiro ** msg -- the message (sm_io_printf fmt) -- it can begin with 491*da7d7b9cSGregory Neil Shapiro ** an SMTP reply code. If not, 050 is assumed. 492*da7d7b9cSGregory Neil Shapiro ** (others) -- sm_io_printf arguments 493*da7d7b9cSGregory Neil Shapiro ** 494*da7d7b9cSGregory Neil Shapiro ** Returns: 495*da7d7b9cSGregory Neil Shapiro ** none 496*da7d7b9cSGregory Neil Shapiro ** 497*da7d7b9cSGregory Neil Shapiro ** Side Effects: 498*da7d7b9cSGregory Neil Shapiro ** none. 499*da7d7b9cSGregory Neil Shapiro */ 500*da7d7b9cSGregory Neil Shapiro 501*da7d7b9cSGregory Neil Shapiro /*VARARGS3*/ 502*da7d7b9cSGregory Neil Shapiro void 503*da7d7b9cSGregory Neil Shapiro # ifdef __STDC__ 504*da7d7b9cSGregory Neil Shapiro emessage(const char *replycode, const char *enhsc, const char *msg, ...) 505*da7d7b9cSGregory Neil Shapiro # else /* __STDC__ */ 506*da7d7b9cSGregory Neil Shapiro emessage(replycode, enhsc, msg, va_alist) 507*da7d7b9cSGregory Neil Shapiro const char *replycode; 508*da7d7b9cSGregory Neil Shapiro const char *enhsc; 509*da7d7b9cSGregory Neil Shapiro const char *msg; 510*da7d7b9cSGregory Neil Shapiro va_dcl 511*da7d7b9cSGregory Neil Shapiro # endif /* __STDC__ */ 512*da7d7b9cSGregory Neil Shapiro { 513*da7d7b9cSGregory Neil Shapiro char *errtxt; 514*da7d7b9cSGregory Neil Shapiro SM_VA_LOCAL_DECL 515*da7d7b9cSGregory Neil Shapiro 516*da7d7b9cSGregory Neil Shapiro errno = 0; 517*da7d7b9cSGregory Neil Shapiro SM_VA_START(ap, msg); 518*da7d7b9cSGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, CurEnv->e_to, replycode, enhsc, 0, msg, ap); 519*da7d7b9cSGregory Neil Shapiro SM_VA_END(ap); 520*da7d7b9cSGregory Neil Shapiro putoutmsg(MsgBuf, false, false); 521*da7d7b9cSGregory Neil Shapiro 522*da7d7b9cSGregory Neil Shapiro /* save this message for mailq printing */ 523*da7d7b9cSGregory Neil Shapiro switch (MsgBuf[0]) 524*da7d7b9cSGregory Neil Shapiro { 525*da7d7b9cSGregory Neil Shapiro case '4': 526*da7d7b9cSGregory Neil Shapiro case '8': 527*da7d7b9cSGregory Neil Shapiro if (CurEnv->e_message != NULL) 528*da7d7b9cSGregory Neil Shapiro break; 529*da7d7b9cSGregory Neil Shapiro /* FALLTHROUGH */ 530*da7d7b9cSGregory Neil Shapiro 531*da7d7b9cSGregory Neil Shapiro case '5': 532*da7d7b9cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 533*da7d7b9cSGregory Neil Shapiro sm_free(CurEnv->e_message); 534*da7d7b9cSGregory Neil Shapiro CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 535*da7d7b9cSGregory Neil Shapiro break; 536*da7d7b9cSGregory Neil Shapiro } 537*da7d7b9cSGregory Neil Shapiro } 538*da7d7b9cSGregory Neil Shapiro 539*da7d7b9cSGregory Neil Shapiro /* 540*da7d7b9cSGregory Neil Shapiro ** EXTSC -- check and extract a status codes 541*da7d7b9cSGregory Neil Shapiro ** 542*da7d7b9cSGregory Neil Shapiro ** Parameters: 543*da7d7b9cSGregory Neil Shapiro ** msg -- string with possible enhanced status code. 544*da7d7b9cSGregory Neil Shapiro ** delim -- delim for enhanced status code. 545*da7d7b9cSGregory Neil Shapiro ** replycode -- pointer to storage for SMTP reply code; 546*da7d7b9cSGregory Neil Shapiro ** must be != NULL and have space for at least 547*da7d7b9cSGregory Neil Shapiro ** 4 characters. 548*da7d7b9cSGregory Neil Shapiro ** enhsc -- pointer to storage for enhanced status code; 549*da7d7b9cSGregory Neil Shapiro ** must be != NULL and have space for at least 550*da7d7b9cSGregory Neil Shapiro ** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3}) 551*da7d7b9cSGregory Neil Shapiro ** 552*da7d7b9cSGregory Neil Shapiro ** Returns: 553*da7d7b9cSGregory Neil Shapiro ** -1 -- no SMTP reply code. 554*da7d7b9cSGregory Neil Shapiro ** >=3 -- offset of error text in msg. 555*da7d7b9cSGregory Neil Shapiro ** (<=4 -- no enhanced status code) 556*da7d7b9cSGregory Neil Shapiro */ 557*da7d7b9cSGregory Neil Shapiro 558*da7d7b9cSGregory Neil Shapiro int 559*da7d7b9cSGregory Neil Shapiro extsc(msg, delim, replycode, enhsc) 560*da7d7b9cSGregory Neil Shapiro const char *msg; 561*da7d7b9cSGregory Neil Shapiro int delim; 562*da7d7b9cSGregory Neil Shapiro char *replycode; 563*da7d7b9cSGregory Neil Shapiro char *enhsc; 564*da7d7b9cSGregory Neil Shapiro { 565*da7d7b9cSGregory Neil Shapiro int offset; 566*da7d7b9cSGregory Neil Shapiro 567*da7d7b9cSGregory Neil Shapiro SM_REQUIRE(replycode != NULL); 568*da7d7b9cSGregory Neil Shapiro SM_REQUIRE(enhsc != NULL); 569*da7d7b9cSGregory Neil Shapiro replycode[0] = '\0'; 570*da7d7b9cSGregory Neil Shapiro enhsc[0] = '\0'; 571*da7d7b9cSGregory Neil Shapiro if (msg == NULL) 572*da7d7b9cSGregory Neil Shapiro return -1; 573*da7d7b9cSGregory Neil Shapiro if (!ISSMTPREPLY(msg)) 574*da7d7b9cSGregory Neil Shapiro return -1; 575*da7d7b9cSGregory Neil Shapiro sm_strlcpy(replycode, msg, 4); 576*da7d7b9cSGregory Neil Shapiro if (msg[3] == '\0') 577*da7d7b9cSGregory Neil Shapiro return 3; 578*da7d7b9cSGregory Neil Shapiro offset = 4; 579*da7d7b9cSGregory Neil Shapiro if (isenhsc(msg + 4, delim)) 580*da7d7b9cSGregory Neil Shapiro offset = extenhsc(msg + 4, delim, enhsc) + 4; 581*da7d7b9cSGregory Neil Shapiro return offset; 582*da7d7b9cSGregory Neil Shapiro } 583*da7d7b9cSGregory Neil Shapiro #endif /* _FFR_PROXY */ 5846f9c8e5bSGregory Neil Shapiro 58512ed1c7cSGregory Neil Shapiro /* 586c2aa98e2SPeter Wemm ** NMESSAGE -- print message (not necessarily an error) 587c2aa98e2SPeter Wemm ** 588c2aa98e2SPeter Wemm ** Just like "message" except it never puts the to... tag on. 589c2aa98e2SPeter Wemm ** 590c2aa98e2SPeter Wemm ** Parameters: 59112ed1c7cSGregory Neil Shapiro ** msg -- the message (sm_io_printf fmt) -- if it begins 592c2aa98e2SPeter Wemm ** with a three digit SMTP reply code, that is used, 593c2aa98e2SPeter Wemm ** otherwise 050 is assumed. 59412ed1c7cSGregory Neil Shapiro ** (others) -- sm_io_printf arguments 595c2aa98e2SPeter Wemm ** 596c2aa98e2SPeter Wemm ** Returns: 597c2aa98e2SPeter Wemm ** none 598c2aa98e2SPeter Wemm ** 599c2aa98e2SPeter Wemm ** Side Effects: 600c2aa98e2SPeter Wemm ** none. 601c2aa98e2SPeter Wemm */ 602c2aa98e2SPeter Wemm 603c2aa98e2SPeter Wemm /*VARARGS1*/ 604c2aa98e2SPeter Wemm void 605c2aa98e2SPeter Wemm #ifdef __STDC__ 606c2aa98e2SPeter Wemm nmessage(const char *msg, ...) 6073299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 608c2aa98e2SPeter Wemm nmessage(msg, va_alist) 609c2aa98e2SPeter Wemm const char *msg; 610c2aa98e2SPeter Wemm va_dcl 6113299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 612c2aa98e2SPeter Wemm { 6133299c2f1SGregory Neil Shapiro char *errtxt; 61412ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 615c2aa98e2SPeter Wemm 616c2aa98e2SPeter Wemm errno = 0; 61712ed1c7cSGregory Neil Shapiro SM_VA_START(ap, msg); 6183299c2f1SGregory Neil Shapiro errtxt = fmtmsg(MsgBuf, (char *) NULL, "050", 6193299c2f1SGregory Neil Shapiro (char *) NULL, 0, msg, ap); 62012ed1c7cSGregory Neil Shapiro SM_VA_END(ap); 62112ed1c7cSGregory Neil Shapiro putoutmsg(MsgBuf, false, false); 622c2aa98e2SPeter Wemm 623c2aa98e2SPeter Wemm /* save this message for mailq printing */ 624c2aa98e2SPeter Wemm switch (MsgBuf[0]) 625c2aa98e2SPeter Wemm { 626c2aa98e2SPeter Wemm case '4': 627c2aa98e2SPeter Wemm case '8': 628c2aa98e2SPeter Wemm if (CurEnv->e_message != NULL) 629c2aa98e2SPeter Wemm break; 6303299c2f1SGregory Neil Shapiro /* FALLTHROUGH */ 631c2aa98e2SPeter Wemm 632c2aa98e2SPeter Wemm case '5': 63312ed1c7cSGregory Neil Shapiro if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) 634c0c4794dSGregory Neil Shapiro sm_free(CurEnv->e_message); 635951742c4SGregory Neil Shapiro CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); 636c2aa98e2SPeter Wemm break; 637c2aa98e2SPeter Wemm } 638c2aa98e2SPeter Wemm } 63912ed1c7cSGregory Neil Shapiro /* 640c2aa98e2SPeter Wemm ** PUTOUTMSG -- output error message to transcript and channel 641c2aa98e2SPeter Wemm ** 642c2aa98e2SPeter Wemm ** Parameters: 643c2aa98e2SPeter Wemm ** msg -- message to output (in SMTP format). 64412ed1c7cSGregory Neil Shapiro ** holdmsg -- if true, don't output a copy of the message to 645c2aa98e2SPeter Wemm ** our output channel. 64612ed1c7cSGregory Neil Shapiro ** heldmsg -- if true, this is a previously held message; 647c2aa98e2SPeter Wemm ** don't log it to the transcript file. 648c2aa98e2SPeter Wemm ** 649c2aa98e2SPeter Wemm ** Returns: 650c2aa98e2SPeter Wemm ** none. 651c2aa98e2SPeter Wemm ** 652c2aa98e2SPeter Wemm ** Side Effects: 653c2aa98e2SPeter Wemm ** Outputs msg to the transcript. 654c2aa98e2SPeter Wemm ** If appropriate, outputs it to the channel. 655c2aa98e2SPeter Wemm ** Deletes SMTP reply code number as appropriate. 656c2aa98e2SPeter Wemm */ 657c2aa98e2SPeter Wemm 6583299c2f1SGregory Neil Shapiro static void 659c2aa98e2SPeter Wemm putoutmsg(msg, holdmsg, heldmsg) 660c2aa98e2SPeter Wemm char *msg; 661c2aa98e2SPeter Wemm bool holdmsg; 662c2aa98e2SPeter Wemm bool heldmsg; 663c2aa98e2SPeter Wemm { 664c2aa98e2SPeter Wemm char msgcode = msg[0]; 665951742c4SGregory Neil Shapiro char *errtxt = msg; 666951742c4SGregory Neil Shapiro char *id; 667c2aa98e2SPeter Wemm 668c2aa98e2SPeter Wemm /* display for debugging */ 669c2aa98e2SPeter Wemm if (tTd(54, 8)) 67012ed1c7cSGregory Neil Shapiro sm_dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "", 671c2aa98e2SPeter Wemm heldmsg ? " (held)" : ""); 672c2aa98e2SPeter Wemm 673c2aa98e2SPeter Wemm /* map warnings to something SMTP can handle */ 674c2aa98e2SPeter Wemm if (msgcode == '6') 675c2aa98e2SPeter Wemm msg[0] = '5'; 676c2aa98e2SPeter Wemm else if (msgcode == '8') 677c2aa98e2SPeter Wemm msg[0] = '4'; 678951742c4SGregory Neil Shapiro id = (CurEnv != NULL) ? CurEnv->e_id : NULL; 679c2aa98e2SPeter Wemm 680c2aa98e2SPeter Wemm /* output to transcript if serious */ 681c2aa98e2SPeter Wemm if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL && 682c2aa98e2SPeter Wemm strchr("45", msg[0]) != NULL) 68312ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(CurEnv->e_xfp, SM_TIME_DEFAULT, "%s\n", 68412ed1c7cSGregory Neil Shapiro msg); 685c2aa98e2SPeter Wemm 68612ed1c7cSGregory Neil Shapiro if (LogLevel > 14 && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 687951742c4SGregory Neil Shapiro sm_syslog(LOG_INFO, id, 68812ed1c7cSGregory Neil Shapiro "--- %s%s%s", msg, holdmsg ? " (hold)" : "", 68912ed1c7cSGregory Neil Shapiro heldmsg ? " (held)" : ""); 690c2aa98e2SPeter Wemm 691c2aa98e2SPeter Wemm if (msgcode == '8') 692c2aa98e2SPeter Wemm msg[0] = '0'; 693c2aa98e2SPeter Wemm 694c2aa98e2SPeter Wemm /* output to channel if appropriate */ 695c2aa98e2SPeter Wemm if (!Verbose && msg[0] == '0') 696c2aa98e2SPeter Wemm return; 697c2aa98e2SPeter Wemm if (holdmsg) 698c2aa98e2SPeter Wemm { 699c2aa98e2SPeter Wemm /* save for possible future display */ 700c2aa98e2SPeter Wemm msg[0] = msgcode; 7013299c2f1SGregory Neil Shapiro if (HeldMessageBuf[0] == '5' && msgcode == '4') 7023299c2f1SGregory Neil Shapiro return; 703951742c4SGregory Neil Shapiro (void) sm_strlcpy(HeldMessageBuf, msg, sizeof(HeldMessageBuf)); 704c2aa98e2SPeter Wemm return; 705c2aa98e2SPeter Wemm } 706c2aa98e2SPeter Wemm 70712ed1c7cSGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 708c2aa98e2SPeter Wemm 709c2aa98e2SPeter Wemm if (OutChannel == NULL) 710c2aa98e2SPeter Wemm return; 711c2aa98e2SPeter Wemm 7123299c2f1SGregory Neil Shapiro /* find actual text of error (after SMTP status codes) */ 7133299c2f1SGregory Neil Shapiro if (ISSMTPREPLY(errtxt)) 7143299c2f1SGregory Neil Shapiro { 7153299c2f1SGregory Neil Shapiro int l; 7163299c2f1SGregory Neil Shapiro 7173299c2f1SGregory Neil Shapiro errtxt += 4; 7183299c2f1SGregory Neil Shapiro l = isenhsc(errtxt, ' '); 7193299c2f1SGregory Neil Shapiro if (l <= 0) 7203299c2f1SGregory Neil Shapiro l = isenhsc(errtxt, '\0'); 7213299c2f1SGregory Neil Shapiro if (l > 0) 7223299c2f1SGregory Neil Shapiro errtxt += l + 1; 7233299c2f1SGregory Neil Shapiro } 7243299c2f1SGregory Neil Shapiro 725c2aa98e2SPeter Wemm /* if DisConnected, OutChannel now points to the transcript */ 726c2aa98e2SPeter Wemm if (!DisConnected && 727c2aa98e2SPeter Wemm (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP)) 72812ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\r\n", 72912ed1c7cSGregory Neil Shapiro msg); 730c2aa98e2SPeter Wemm else 73112ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\n", 73212ed1c7cSGregory Neil Shapiro errtxt); 733c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 73412ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 73512ed1c7cSGregory Neil Shapiro "%05d >>> %s\n", (int) CurrentPid, 73612ed1c7cSGregory Neil Shapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON) 73712ed1c7cSGregory Neil Shapiro ? msg : errtxt); 73812ed1c7cSGregory Neil Shapiro #if !PIPELINING 73912ed1c7cSGregory Neil Shapiro /* XXX can't flush here for SMTP pipelining */ 740c2aa98e2SPeter Wemm if (msg[3] == ' ') 74112ed1c7cSGregory Neil Shapiro (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT); 74212ed1c7cSGregory Neil Shapiro if (!sm_io_error(OutChannel) || DisConnected) 743c2aa98e2SPeter Wemm return; 744c2aa98e2SPeter Wemm 745c2aa98e2SPeter Wemm /* 746c2aa98e2SPeter Wemm ** Error on output -- if reporting lost channel, just ignore it. 747c2aa98e2SPeter Wemm ** Also, ignore errors from QUIT response (221 message) -- some 748c2aa98e2SPeter Wemm ** rude servers don't read result. 749c2aa98e2SPeter Wemm */ 750c2aa98e2SPeter Wemm 75112ed1c7cSGregory Neil Shapiro if (InChannel == NULL || sm_io_eof(InChannel) || 75212ed1c7cSGregory Neil Shapiro sm_io_error(InChannel) || strncmp(msg, "221", 3) == 0) 753c2aa98e2SPeter Wemm return; 754c2aa98e2SPeter Wemm 755c2aa98e2SPeter Wemm /* can't call syserr, 'cause we are using MsgBuf */ 75612ed1c7cSGregory Neil Shapiro HoldErrs = true; 757c2aa98e2SPeter Wemm if (LogLevel > 0) 758951742c4SGregory Neil Shapiro sm_syslog(LOG_CRIT, id, 759c2aa98e2SPeter Wemm "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", 76012ed1c7cSGregory Neil Shapiro CURHOSTNAME, 76112ed1c7cSGregory Neil Shapiro shortenstring(msg, MAXSHORTSTR), sm_errstring(errno)); 76212ed1c7cSGregory Neil Shapiro #endif /* !PIPELINING */ 763c2aa98e2SPeter Wemm } 76412ed1c7cSGregory Neil Shapiro /* 765c2aa98e2SPeter Wemm ** PUTERRMSG -- like putoutmsg, but does special processing for error messages 766c2aa98e2SPeter Wemm ** 767c2aa98e2SPeter Wemm ** Parameters: 768c2aa98e2SPeter Wemm ** msg -- the message to output. 769c2aa98e2SPeter Wemm ** 770c2aa98e2SPeter Wemm ** Returns: 771c2aa98e2SPeter Wemm ** none. 772c2aa98e2SPeter Wemm ** 773c2aa98e2SPeter Wemm ** Side Effects: 774c2aa98e2SPeter Wemm ** Sets the fatal error bit in the envelope as appropriate. 775c2aa98e2SPeter Wemm */ 776c2aa98e2SPeter Wemm 7773299c2f1SGregory Neil Shapiro static void 778c2aa98e2SPeter Wemm puterrmsg(msg) 779c2aa98e2SPeter Wemm char *msg; 780c2aa98e2SPeter Wemm { 781c2aa98e2SPeter Wemm char msgcode = msg[0]; 782c2aa98e2SPeter Wemm 783c2aa98e2SPeter Wemm /* output the message as usual */ 78412ed1c7cSGregory Neil Shapiro putoutmsg(msg, HoldErrs, false); 785c2aa98e2SPeter Wemm 786c2aa98e2SPeter Wemm /* be careful about multiple error messages */ 787c2aa98e2SPeter Wemm if (OnlyOneError) 78812ed1c7cSGregory Neil Shapiro HoldErrs = true; 789c2aa98e2SPeter Wemm 790c2aa98e2SPeter Wemm /* signal the error */ 791c2aa98e2SPeter Wemm Errors++; 792c2aa98e2SPeter Wemm 793c2aa98e2SPeter Wemm if (CurEnv == NULL) 794c2aa98e2SPeter Wemm return; 795c2aa98e2SPeter Wemm 796c2aa98e2SPeter Wemm if (msgcode == '6') 797c2aa98e2SPeter Wemm { 798c2aa98e2SPeter Wemm /* notify the postmaster */ 799c2aa98e2SPeter Wemm CurEnv->e_flags |= EF_PM_NOTIFY; 800c2aa98e2SPeter Wemm } 801c2aa98e2SPeter Wemm else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags)) 802c2aa98e2SPeter Wemm { 803c2aa98e2SPeter Wemm /* mark long-term fatal errors */ 804c2aa98e2SPeter Wemm CurEnv->e_flags |= EF_FATALERRS; 805c2aa98e2SPeter Wemm } 806c2aa98e2SPeter Wemm } 80712ed1c7cSGregory Neil Shapiro /* 8083299c2f1SGregory Neil Shapiro ** ISENHSC -- check whether a string contains an enhanced status code 8093299c2f1SGregory Neil Shapiro ** 8103299c2f1SGregory Neil Shapiro ** Parameters: 8113299c2f1SGregory Neil Shapiro ** s -- string with possible enhanced status code. 8123299c2f1SGregory Neil Shapiro ** delim -- delim for enhanced status code. 8133299c2f1SGregory Neil Shapiro ** 8143299c2f1SGregory Neil Shapiro ** Returns: 8153299c2f1SGregory Neil Shapiro ** 0 -- no enhanced status code. 8163299c2f1SGregory Neil Shapiro ** >4 -- length of enhanced status code. 8173299c2f1SGregory Neil Shapiro ** 8183299c2f1SGregory Neil Shapiro ** Side Effects: 8193299c2f1SGregory Neil Shapiro ** none. 8203299c2f1SGregory Neil Shapiro */ 8213299c2f1SGregory Neil Shapiro int 8223299c2f1SGregory Neil Shapiro isenhsc(s, delim) 8233299c2f1SGregory Neil Shapiro const char *s; 8243299c2f1SGregory Neil Shapiro int delim; 8253299c2f1SGregory Neil Shapiro { 8263299c2f1SGregory Neil Shapiro int l, h; 8273299c2f1SGregory Neil Shapiro 8283299c2f1SGregory Neil Shapiro if (s == NULL) 8293299c2f1SGregory Neil Shapiro return 0; 8303299c2f1SGregory Neil Shapiro if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) 8313299c2f1SGregory Neil Shapiro return 0; 8323299c2f1SGregory Neil Shapiro h = 0; 8333299c2f1SGregory Neil Shapiro l = 2; 8343299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 8353299c2f1SGregory Neil Shapiro ++h; 8363299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != '.') 8373299c2f1SGregory Neil Shapiro return 0; 8383299c2f1SGregory Neil Shapiro l += h + 1; 8393299c2f1SGregory Neil Shapiro h = 0; 8403299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 8413299c2f1SGregory Neil Shapiro ++h; 8423299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != delim) 8433299c2f1SGregory Neil Shapiro return 0; 8443299c2f1SGregory Neil Shapiro return l + h; 8453299c2f1SGregory Neil Shapiro } 84612ed1c7cSGregory Neil Shapiro /* 8473299c2f1SGregory Neil Shapiro ** EXTENHSC -- check and extract an enhanced status code 8483299c2f1SGregory Neil Shapiro ** 8493299c2f1SGregory Neil Shapiro ** Parameters: 8503299c2f1SGregory Neil Shapiro ** s -- string with possible enhanced status code. 8513299c2f1SGregory Neil Shapiro ** delim -- delim for enhanced status code. 8523299c2f1SGregory Neil Shapiro ** e -- pointer to storage for enhanced status code. 8533299c2f1SGregory Neil Shapiro ** must be != NULL and have space for at least 8543299c2f1SGregory Neil Shapiro ** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3}) 8553299c2f1SGregory Neil Shapiro ** 8563299c2f1SGregory Neil Shapiro ** Returns: 8573299c2f1SGregory Neil Shapiro ** 0 -- no enhanced status code. 8583299c2f1SGregory Neil Shapiro ** >4 -- length of enhanced status code. 8593299c2f1SGregory Neil Shapiro ** 8603299c2f1SGregory Neil Shapiro ** Side Effects: 8613299c2f1SGregory Neil Shapiro ** fills e with enhanced status code. 8623299c2f1SGregory Neil Shapiro */ 86312ed1c7cSGregory Neil Shapiro 8643299c2f1SGregory Neil Shapiro int 8653299c2f1SGregory Neil Shapiro extenhsc(s, delim, e) 8663299c2f1SGregory Neil Shapiro const char *s; 8673299c2f1SGregory Neil Shapiro int delim; 8683299c2f1SGregory Neil Shapiro char *e; 8693299c2f1SGregory Neil Shapiro { 8703299c2f1SGregory Neil Shapiro int l, h; 8713299c2f1SGregory Neil Shapiro 8723299c2f1SGregory Neil Shapiro if (s == NULL) 8733299c2f1SGregory Neil Shapiro return 0; 8743299c2f1SGregory Neil Shapiro if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) 8753299c2f1SGregory Neil Shapiro return 0; 8763299c2f1SGregory Neil Shapiro h = 0; 8773299c2f1SGregory Neil Shapiro l = 2; 8783299c2f1SGregory Neil Shapiro e[0] = s[0]; 8793299c2f1SGregory Neil Shapiro e[1] = '.'; 8803299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 8813299c2f1SGregory Neil Shapiro { 8823299c2f1SGregory Neil Shapiro e[l + h] = s[l + h]; 8833299c2f1SGregory Neil Shapiro ++h; 8843299c2f1SGregory Neil Shapiro } 8853299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != '.') 8863299c2f1SGregory Neil Shapiro return 0; 8873299c2f1SGregory Neil Shapiro e[l + h] = '.'; 8883299c2f1SGregory Neil Shapiro l += h + 1; 8893299c2f1SGregory Neil Shapiro h = 0; 8903299c2f1SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) 8913299c2f1SGregory Neil Shapiro { 8923299c2f1SGregory Neil Shapiro e[l + h] = s[l + h]; 8933299c2f1SGregory Neil Shapiro ++h; 8943299c2f1SGregory Neil Shapiro } 8953299c2f1SGregory Neil Shapiro if (h == 0 || s[l + h] != delim) 8963299c2f1SGregory Neil Shapiro return 0; 8973299c2f1SGregory Neil Shapiro e[l + h] = '\0'; 8983299c2f1SGregory Neil Shapiro return l + h; 8993299c2f1SGregory Neil Shapiro } 90012ed1c7cSGregory Neil Shapiro /* 901c2aa98e2SPeter Wemm ** FMTMSG -- format a message into buffer. 902c2aa98e2SPeter Wemm ** 903c2aa98e2SPeter Wemm ** Parameters: 9043299c2f1SGregory Neil Shapiro ** eb -- error buffer to get result -- MUST BE MsgBuf. 905c2aa98e2SPeter Wemm ** to -- the recipient tag for this message. 9063299c2f1SGregory Neil Shapiro ** num -- default three digit SMTP reply code. 9073299c2f1SGregory Neil Shapiro ** enhsc -- enhanced status code. 908c2aa98e2SPeter Wemm ** en -- the error number to display. 909c2aa98e2SPeter Wemm ** fmt -- format of string. 9103299c2f1SGregory Neil Shapiro ** ap -- arguments for fmt. 911c2aa98e2SPeter Wemm ** 912c2aa98e2SPeter Wemm ** Returns: 9133299c2f1SGregory Neil Shapiro ** pointer to error text beyond status codes. 914c2aa98e2SPeter Wemm ** 915c2aa98e2SPeter Wemm ** Side Effects: 916c2aa98e2SPeter Wemm ** none. 917c2aa98e2SPeter Wemm */ 918c2aa98e2SPeter Wemm 9193299c2f1SGregory Neil Shapiro static char * 9203299c2f1SGregory Neil Shapiro fmtmsg(eb, to, num, enhsc, eno, fmt, ap) 921c2aa98e2SPeter Wemm register char *eb; 922c2aa98e2SPeter Wemm const char *to; 923c2aa98e2SPeter Wemm const char *num; 9243299c2f1SGregory Neil Shapiro const char *enhsc; 925c2aa98e2SPeter Wemm int eno; 926c2aa98e2SPeter Wemm const char *fmt; 92712ed1c7cSGregory Neil Shapiro SM_VA_LOCAL_DECL 928c2aa98e2SPeter Wemm { 929c2aa98e2SPeter Wemm char del; 930c2aa98e2SPeter Wemm int l; 931951742c4SGregory Neil Shapiro int spaceleft = sizeof(MsgBuf); 9323299c2f1SGregory Neil Shapiro char *errtxt; 933c2aa98e2SPeter Wemm 934c2aa98e2SPeter Wemm /* output the reply code */ 9353299c2f1SGregory Neil Shapiro if (ISSMTPCODE(fmt)) 936c2aa98e2SPeter Wemm { 937c2aa98e2SPeter Wemm num = fmt; 938c2aa98e2SPeter Wemm fmt += 4; 939c2aa98e2SPeter Wemm } 940c2aa98e2SPeter Wemm if (num[3] == '-') 941c2aa98e2SPeter Wemm del = '-'; 942c2aa98e2SPeter Wemm else 943c2aa98e2SPeter Wemm del = ' '; 94412ed1c7cSGregory Neil Shapiro if (SoftBounce && num[0] == '5') 94512ed1c7cSGregory Neil Shapiro { 94612ed1c7cSGregory Neil Shapiro /* replace 5 by 4 */ 94712ed1c7cSGregory Neil Shapiro (void) sm_snprintf(eb, spaceleft, "4%2.2s%c", num + 1, del); 94812ed1c7cSGregory Neil Shapiro } 94912ed1c7cSGregory Neil Shapiro else 95012ed1c7cSGregory Neil Shapiro (void) sm_snprintf(eb, spaceleft, "%3.3s%c", num, del); 951c2aa98e2SPeter Wemm eb += 4; 952c2aa98e2SPeter Wemm spaceleft -= 4; 953c2aa98e2SPeter Wemm 9543299c2f1SGregory Neil Shapiro if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4) 9553299c2f1SGregory Neil Shapiro { 9563299c2f1SGregory Neil Shapiro /* copy enh.status code including trailing blank */ 9573299c2f1SGregory Neil Shapiro l++; 95812ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(eb, fmt, l + 1); 9593299c2f1SGregory Neil Shapiro eb += l; 9603299c2f1SGregory Neil Shapiro spaceleft -= l; 9613299c2f1SGregory Neil Shapiro fmt += l; 9623299c2f1SGregory Neil Shapiro } 9633299c2f1SGregory Neil Shapiro else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4) 9643299c2f1SGregory Neil Shapiro { 9653299c2f1SGregory Neil Shapiro /* copy enh.status code */ 96612ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(eb, enhsc, l + 1); 9673299c2f1SGregory Neil Shapiro eb[l] = ' '; 9683299c2f1SGregory Neil Shapiro eb[++l] = '\0'; 9693299c2f1SGregory Neil Shapiro eb += l; 9703299c2f1SGregory Neil Shapiro spaceleft -= l; 9713299c2f1SGregory Neil Shapiro } 97212ed1c7cSGregory Neil Shapiro if (SoftBounce && eb[-l] == '5') 97312ed1c7cSGregory Neil Shapiro { 97412ed1c7cSGregory Neil Shapiro /* replace 5 by 4 */ 97512ed1c7cSGregory Neil Shapiro eb[-l] = '4'; 97612ed1c7cSGregory Neil Shapiro } 9773299c2f1SGregory Neil Shapiro errtxt = eb; 9783299c2f1SGregory Neil Shapiro 979c2aa98e2SPeter Wemm /* output the file name and line number */ 980c2aa98e2SPeter Wemm if (FileName != NULL) 981c2aa98e2SPeter Wemm { 98212ed1c7cSGregory Neil Shapiro (void) sm_snprintf(eb, spaceleft, "%s: line %d: ", 983c2aa98e2SPeter Wemm shortenstring(FileName, 83), LineNumber); 984c2aa98e2SPeter Wemm eb += (l = strlen(eb)); 985c2aa98e2SPeter Wemm spaceleft -= l; 986c2aa98e2SPeter Wemm } 987c2aa98e2SPeter Wemm 98856477e1eSGregory Neil Shapiro /* 98956477e1eSGregory Neil Shapiro ** output the "to" address only if it is defined and one of the 99056477e1eSGregory Neil Shapiro ** following codes is used: 99156477e1eSGregory Neil Shapiro ** 050 internal notices, e.g., alias expansion 99256477e1eSGregory Neil Shapiro ** 250 Ok 99356477e1eSGregory Neil Shapiro ** 252 Cannot VRFY user, but will accept message and attempt delivery 99456477e1eSGregory Neil Shapiro ** 450 Requested mail action not taken: mailbox unavailable 99556477e1eSGregory Neil Shapiro ** 550 Requested action not taken: mailbox unavailable 99656477e1eSGregory Neil Shapiro ** 553 Requested action not taken: mailbox name not allowed 99756477e1eSGregory Neil Shapiro ** 99856477e1eSGregory Neil Shapiro ** Notice: this still isn't "the right thing", this code shouldn't 99956477e1eSGregory Neil Shapiro ** (indirectly) depend on CurEnv->e_to. 100056477e1eSGregory Neil Shapiro */ 100156477e1eSGregory Neil Shapiro 1002c2aa98e2SPeter Wemm if (to != NULL && to[0] != '\0' && 100356477e1eSGregory Neil Shapiro (strncmp(num, "050", 3) == 0 || 100456477e1eSGregory Neil Shapiro strncmp(num, "250", 3) == 0 || 100556477e1eSGregory Neil Shapiro strncmp(num, "252", 3) == 0 || 100656477e1eSGregory Neil Shapiro strncmp(num, "450", 3) == 0 || 100756477e1eSGregory Neil Shapiro strncmp(num, "550", 3) == 0 || 100856477e1eSGregory Neil Shapiro strncmp(num, "553", 3) == 0)) 1009c2aa98e2SPeter Wemm { 101012ed1c7cSGregory Neil Shapiro (void) sm_strlcpyn(eb, spaceleft, 2, 101112ed1c7cSGregory Neil Shapiro shortenstring(to, MAXSHORTSTR), "... "); 1012c2aa98e2SPeter Wemm spaceleft -= strlen(eb); 1013c2aa98e2SPeter Wemm while (*eb != '\0') 1014c2aa98e2SPeter Wemm *eb++ &= 0177; 1015c2aa98e2SPeter Wemm } 1016c2aa98e2SPeter Wemm 1017c2aa98e2SPeter Wemm /* output the message */ 101812ed1c7cSGregory Neil Shapiro (void) sm_vsnprintf(eb, spaceleft, fmt, ap); 1019c2aa98e2SPeter Wemm spaceleft -= strlen(eb); 1020c2aa98e2SPeter Wemm while (*eb != '\0') 1021c2aa98e2SPeter Wemm *eb++ &= 0177; 1022c2aa98e2SPeter Wemm 1023c2aa98e2SPeter Wemm /* output the error code, if any */ 1024c2aa98e2SPeter Wemm if (eno != 0) 102512ed1c7cSGregory Neil Shapiro (void) sm_strlcpyn(eb, spaceleft, 2, ": ", sm_errstring(eno)); 10263299c2f1SGregory Neil Shapiro 10273299c2f1SGregory Neil Shapiro return errtxt; 1028c2aa98e2SPeter Wemm } 102912ed1c7cSGregory Neil Shapiro /* 1030c2aa98e2SPeter Wemm ** BUFFER_ERRORS -- arrange to buffer future error messages 1031c2aa98e2SPeter Wemm ** 1032c2aa98e2SPeter Wemm ** Parameters: 1033c2aa98e2SPeter Wemm ** none 1034c2aa98e2SPeter Wemm ** 1035c2aa98e2SPeter Wemm ** Returns: 1036c2aa98e2SPeter Wemm ** none. 1037c2aa98e2SPeter Wemm */ 1038c2aa98e2SPeter Wemm 1039c2aa98e2SPeter Wemm void 1040c2aa98e2SPeter Wemm buffer_errors() 1041c2aa98e2SPeter Wemm { 1042c2aa98e2SPeter Wemm HeldMessageBuf[0] = '\0'; 104312ed1c7cSGregory Neil Shapiro HoldErrs = true; 1044c2aa98e2SPeter Wemm } 104512ed1c7cSGregory Neil Shapiro /* 1046c2aa98e2SPeter Wemm ** FLUSH_ERRORS -- flush the held error message buffer 1047c2aa98e2SPeter Wemm ** 1048c2aa98e2SPeter Wemm ** Parameters: 1049c2aa98e2SPeter Wemm ** print -- if set, print the message, otherwise just 1050c2aa98e2SPeter Wemm ** delete it. 1051c2aa98e2SPeter Wemm ** 1052c2aa98e2SPeter Wemm ** Returns: 1053c2aa98e2SPeter Wemm ** none. 1054c2aa98e2SPeter Wemm */ 1055c2aa98e2SPeter Wemm 1056c2aa98e2SPeter Wemm void 1057c2aa98e2SPeter Wemm flush_errors(print) 1058c2aa98e2SPeter Wemm bool print; 1059c2aa98e2SPeter Wemm { 1060c2aa98e2SPeter Wemm if (print && HeldMessageBuf[0] != '\0') 106112ed1c7cSGregory Neil Shapiro putoutmsg(HeldMessageBuf, false, true); 1062c2aa98e2SPeter Wemm HeldMessageBuf[0] = '\0'; 106312ed1c7cSGregory Neil Shapiro HoldErrs = false; 1064c2aa98e2SPeter Wemm } 106512ed1c7cSGregory Neil Shapiro /* 106612ed1c7cSGregory Neil Shapiro ** SM_ERRSTRING -- return string description of error code 1067c2aa98e2SPeter Wemm ** 1068c2aa98e2SPeter Wemm ** Parameters: 1069c2aa98e2SPeter Wemm ** errnum -- the error number to translate 1070c2aa98e2SPeter Wemm ** 1071c2aa98e2SPeter Wemm ** Returns: 1072c2aa98e2SPeter Wemm ** A string description of errnum. 1073c2aa98e2SPeter Wemm ** 1074c2aa98e2SPeter Wemm ** Side Effects: 1075c2aa98e2SPeter Wemm ** none. 1076c2aa98e2SPeter Wemm */ 1077c2aa98e2SPeter Wemm 1078c2aa98e2SPeter Wemm const char * 107912ed1c7cSGregory Neil Shapiro sm_errstring(errnum) 1080c2aa98e2SPeter Wemm int errnum; 1081c2aa98e2SPeter Wemm { 1082c2aa98e2SPeter Wemm char *dnsmsg; 1083c2aa98e2SPeter Wemm char *bp; 1084c2aa98e2SPeter Wemm static char buf[MAXLINE]; 108512ed1c7cSGregory Neil Shapiro #if HASSTRERROR 108612ed1c7cSGregory Neil Shapiro char *err; 108712ed1c7cSGregory Neil Shapiro char errbuf[30]; 108812ed1c7cSGregory Neil Shapiro #endif /* HASSTRERROR */ 1089c2aa98e2SPeter Wemm #if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) 1090c2aa98e2SPeter Wemm extern char *sys_errlist[]; 1091c2aa98e2SPeter Wemm extern int sys_nerr; 10923299c2f1SGregory Neil Shapiro #endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */ 1093c2aa98e2SPeter Wemm 1094c2aa98e2SPeter Wemm /* 1095c2aa98e2SPeter Wemm ** Handle special network error codes. 1096c2aa98e2SPeter Wemm ** 1097c2aa98e2SPeter Wemm ** These are 4.2/4.3bsd specific; they should be in daemon.c. 1098c2aa98e2SPeter Wemm */ 1099c2aa98e2SPeter Wemm 1100c2aa98e2SPeter Wemm dnsmsg = NULL; 1101c2aa98e2SPeter Wemm switch (errnum) 1102c2aa98e2SPeter Wemm { 1103c2aa98e2SPeter Wemm case ETIMEDOUT: 1104c2aa98e2SPeter Wemm case ECONNRESET: 1105c2aa98e2SPeter Wemm bp = buf; 1106c2aa98e2SPeter Wemm #if HASSTRERROR 110712ed1c7cSGregory Neil Shapiro err = strerror(errnum); 110812ed1c7cSGregory Neil Shapiro if (err == NULL) 110912ed1c7cSGregory Neil Shapiro { 1110951742c4SGregory Neil Shapiro (void) sm_snprintf(errbuf, sizeof(errbuf), 111112ed1c7cSGregory Neil Shapiro "Error %d", errnum); 111212ed1c7cSGregory Neil Shapiro err = errbuf; 111312ed1c7cSGregory Neil Shapiro } 111412ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, err, SPACELEFT(buf, bp)); 11153299c2f1SGregory Neil Shapiro #else /* HASSTRERROR */ 1116c2aa98e2SPeter Wemm if (errnum >= 0 && errnum < sys_nerr) 111712ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, sys_errlist[errnum], 111812ed1c7cSGregory Neil Shapiro SPACELEFT(buf, bp)); 1119c2aa98e2SPeter Wemm else 112012ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 112112ed1c7cSGregory Neil Shapiro "Error %d", errnum); 11223299c2f1SGregory Neil Shapiro #endif /* HASSTRERROR */ 1123c2aa98e2SPeter Wemm bp += strlen(bp); 1124c2aa98e2SPeter Wemm if (CurHostName != NULL) 1125c2aa98e2SPeter Wemm { 1126c2aa98e2SPeter Wemm if (errnum == ETIMEDOUT) 1127c2aa98e2SPeter Wemm { 112812ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 112912ed1c7cSGregory Neil Shapiro " with "); 1130c2aa98e2SPeter Wemm bp += strlen(bp); 1131c2aa98e2SPeter Wemm } 1132c2aa98e2SPeter Wemm else 1133c2aa98e2SPeter Wemm { 1134c2aa98e2SPeter Wemm bp = buf; 113512ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 1136c2aa98e2SPeter Wemm "Connection reset by "); 1137c2aa98e2SPeter Wemm bp += strlen(bp); 1138c2aa98e2SPeter Wemm } 113912ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, 114012ed1c7cSGregory Neil Shapiro shortenstring(CurHostName, MAXSHORTSTR), 114112ed1c7cSGregory Neil Shapiro SPACELEFT(buf, bp)); 1142c2aa98e2SPeter Wemm bp += strlen(buf); 1143c2aa98e2SPeter Wemm } 1144c2aa98e2SPeter Wemm if (SmtpPhase != NULL) 1145c2aa98e2SPeter Wemm { 114612ed1c7cSGregory Neil Shapiro (void) sm_snprintf(bp, SPACELEFT(buf, bp), 114712ed1c7cSGregory Neil Shapiro " during %s", SmtpPhase); 1148c2aa98e2SPeter Wemm } 11493299c2f1SGregory Neil Shapiro return buf; 1150c2aa98e2SPeter Wemm 1151c2aa98e2SPeter Wemm case EHOSTDOWN: 1152c2aa98e2SPeter Wemm if (CurHostName == NULL) 1153c2aa98e2SPeter Wemm break; 1154951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "Host %s is down", 1155c2aa98e2SPeter Wemm shortenstring(CurHostName, MAXSHORTSTR)); 11563299c2f1SGregory Neil Shapiro return buf; 1157c2aa98e2SPeter Wemm 1158c2aa98e2SPeter Wemm case ECONNREFUSED: 1159c2aa98e2SPeter Wemm if (CurHostName == NULL) 1160c2aa98e2SPeter Wemm break; 1161951742c4SGregory Neil Shapiro (void) sm_strlcpyn(buf, sizeof(buf), 2, "Connection refused by ", 1162c2aa98e2SPeter Wemm shortenstring(CurHostName, MAXSHORTSTR)); 11633299c2f1SGregory Neil Shapiro return buf; 1164c2aa98e2SPeter Wemm 1165c2aa98e2SPeter Wemm #if NAMED_BIND 1166c2aa98e2SPeter Wemm case HOST_NOT_FOUND + E_DNSBASE: 1167c2aa98e2SPeter Wemm dnsmsg = "host not found"; 1168c2aa98e2SPeter Wemm break; 1169c2aa98e2SPeter Wemm 1170c2aa98e2SPeter Wemm case TRY_AGAIN + E_DNSBASE: 1171c2aa98e2SPeter Wemm dnsmsg = "host name lookup failure"; 1172c2aa98e2SPeter Wemm break; 1173c2aa98e2SPeter Wemm 1174c2aa98e2SPeter Wemm case NO_RECOVERY + E_DNSBASE: 1175c2aa98e2SPeter Wemm dnsmsg = "non-recoverable error"; 1176c2aa98e2SPeter Wemm break; 1177c2aa98e2SPeter Wemm 1178c2aa98e2SPeter Wemm case NO_DATA + E_DNSBASE: 1179c2aa98e2SPeter Wemm dnsmsg = "no data known"; 1180c2aa98e2SPeter Wemm break; 11813299c2f1SGregory Neil Shapiro #endif /* NAMED_BIND */ 1182c2aa98e2SPeter Wemm 1183c2aa98e2SPeter Wemm case EPERM: 1184c2aa98e2SPeter Wemm /* SunOS gives "Not owner" -- this is the POSIX message */ 1185c2aa98e2SPeter Wemm return "Operation not permitted"; 1186c2aa98e2SPeter Wemm 1187c2aa98e2SPeter Wemm /* 1188c2aa98e2SPeter Wemm ** Error messages used internally in sendmail. 1189c2aa98e2SPeter Wemm */ 1190c2aa98e2SPeter Wemm 1191c2aa98e2SPeter Wemm case E_SM_OPENTIMEOUT: 1192c2aa98e2SPeter Wemm return "Timeout on file open"; 1193c2aa98e2SPeter Wemm 1194c2aa98e2SPeter Wemm case E_SM_NOSLINK: 1195c2aa98e2SPeter Wemm return "Symbolic links not allowed"; 1196c2aa98e2SPeter Wemm 1197c2aa98e2SPeter Wemm case E_SM_NOHLINK: 1198c2aa98e2SPeter Wemm return "Hard links not allowed"; 1199c2aa98e2SPeter Wemm 1200c2aa98e2SPeter Wemm case E_SM_REGONLY: 1201c2aa98e2SPeter Wemm return "Regular files only"; 1202c2aa98e2SPeter Wemm 1203c2aa98e2SPeter Wemm case E_SM_ISEXEC: 1204c2aa98e2SPeter Wemm return "Executable files not allowed"; 1205c2aa98e2SPeter Wemm 1206c2aa98e2SPeter Wemm case E_SM_WWDIR: 1207c2aa98e2SPeter Wemm return "World writable directory"; 1208c2aa98e2SPeter Wemm 1209c2aa98e2SPeter Wemm case E_SM_GWDIR: 1210c2aa98e2SPeter Wemm return "Group writable directory"; 1211c2aa98e2SPeter Wemm 1212c2aa98e2SPeter Wemm case E_SM_FILECHANGE: 1213c2aa98e2SPeter Wemm return "File changed after open"; 1214c2aa98e2SPeter Wemm 1215c2aa98e2SPeter Wemm case E_SM_WWFILE: 1216c2aa98e2SPeter Wemm return "World writable file"; 1217c2aa98e2SPeter Wemm 1218c2aa98e2SPeter Wemm case E_SM_GWFILE: 1219c2aa98e2SPeter Wemm return "Group writable file"; 12203299c2f1SGregory Neil Shapiro 12213299c2f1SGregory Neil Shapiro case E_SM_GRFILE: 12223299c2f1SGregory Neil Shapiro return "Group readable file"; 12233299c2f1SGregory Neil Shapiro 12243299c2f1SGregory Neil Shapiro case E_SM_WRFILE: 12253299c2f1SGregory Neil Shapiro return "World readable file"; 1226c2aa98e2SPeter Wemm } 1227c2aa98e2SPeter Wemm 1228c2aa98e2SPeter Wemm if (dnsmsg != NULL) 1229c2aa98e2SPeter Wemm { 1230c2aa98e2SPeter Wemm bp = buf; 1231951742c4SGregory Neil Shapiro bp += sm_strlcpy(bp, "Name server: ", sizeof(buf)); 1232c2aa98e2SPeter Wemm if (CurHostName != NULL) 1233c2aa98e2SPeter Wemm { 123412ed1c7cSGregory Neil Shapiro (void) sm_strlcpyn(bp, SPACELEFT(buf, bp), 2, 123512ed1c7cSGregory Neil Shapiro shortenstring(CurHostName, MAXSHORTSTR), ": "); 1236c2aa98e2SPeter Wemm bp += strlen(bp); 1237c2aa98e2SPeter Wemm } 123812ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(bp, dnsmsg, SPACELEFT(buf, bp)); 1239c2aa98e2SPeter Wemm return buf; 1240c2aa98e2SPeter Wemm } 1241c2aa98e2SPeter Wemm 124212ed1c7cSGregory Neil Shapiro #if LDAPMAP 1243*da7d7b9cSGregory Neil Shapiro if (errnum >= E_LDAPBASE - E_LDAP_SHIM) 12443299c2f1SGregory Neil Shapiro return ldap_err2string(errnum - E_LDAPBASE); 12453299c2f1SGregory Neil Shapiro #endif /* LDAPMAP */ 12463299c2f1SGregory Neil Shapiro 1247c2aa98e2SPeter Wemm #if HASSTRERROR 124812ed1c7cSGregory Neil Shapiro err = strerror(errnum); 124912ed1c7cSGregory Neil Shapiro if (err == NULL) 125012ed1c7cSGregory Neil Shapiro { 1251951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum); 125212ed1c7cSGregory Neil Shapiro return buf; 125312ed1c7cSGregory Neil Shapiro } 125412ed1c7cSGregory Neil Shapiro return err; 12553299c2f1SGregory Neil Shapiro #else /* HASSTRERROR */ 1256c2aa98e2SPeter Wemm if (errnum > 0 && errnum < sys_nerr) 12573299c2f1SGregory Neil Shapiro return sys_errlist[errnum]; 1258c2aa98e2SPeter Wemm 1259951742c4SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum); 12603299c2f1SGregory Neil Shapiro return buf; 12613299c2f1SGregory Neil Shapiro #endif /* HASSTRERROR */ 1262c2aa98e2SPeter Wemm } 1263