2 * Copyright (c) 1998-2003, 2010, 2015 Proofpoint, Inc. and its suppliers.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
16 SM_RCSID("@(#)$Id: err.c,v 8.206 2013-11-22 20:51:55 ca Exp $")
20 # include <ldap.h> /* for LDAP error codes */
23 # include <sm/sendmail.h>
26 static void putoutmsg __P((char *, bool, bool));
27 static void puterrmsg __P((char *));
28 static char *fmtmsg __P((char *, const char *, const char *, const char *,
29 int, const char *, va_list));
32 ** FATAL_ERROR -- handle a fatal exception
34 ** This function is installed as the default exception handler
35 ** in the main sendmail process, and in all child processes
36 ** that we create. Its job is to handle exceptions that are not
37 ** handled at a lower level.
39 ** The theory is that unhandled exceptions will be 'fatal' class
40 ** exceptions (with an "F:" prefix), such as the out-of-memory
41 ** exception "F:sm.heap". As such, they are handled by exiting
42 ** the process in exactly the same way that xalloc() in Sendmail 8.10
43 ** exits the process when it fails due to lack of memory:
44 ** we call syserr with a message beginning with "!".
47 ** exc -- exception which is terminating this process
61 ** This function may be called when the heap is exhausted.
62 ** The following code writes the message for 'exc' into our
63 ** static buffer without allocating memory or raising exceptions.
66 sm_strio_init(&f, buf, sizeof(buf));
67 sm_exc_write(exc, &f);
68 (void) sm_io_flush(&f, SM_TIME_DEFAULT);
71 ** Terminate the process after logging an error and cleaning up.
73 ** - syserr decides what class of error this is by looking at errno.
74 ** That's no good; we should look at the exc structure.
75 ** - The cleanup code should be moved out of syserr
76 ** and into individual exception handlers
77 ** that are part of the module they clean up after.
85 ** SYSERR -- Print error message.
87 ** Prints an error message via sm_io_printf to the diagnostic output.
89 ** If the first character of the syserr message is `!' it will
90 ** log this as an ALERT message and exit immediately. This can
91 ** leave queue files in an indeterminate state, so it should not
94 ** If the first character of the syserr message is '!' or '@'
95 ** then syserr knows that the process is about to be terminated,
96 ** so the SMTP reply code defaults to 421. Otherwise, the
97 ** reply code defaults to 451 or 554, depending on errno.
100 ** fmt -- the format string. An optional '!', '@', or '+',
101 ** followed by an optional three-digit SMTP
102 ** reply code, followed by message text.
103 ** (others) -- parameters
107 ** Raises E:mta.quickabort if QuickAbort is set.
110 ** increments Errors.
114 char MsgBuf[BUFSIZ*2]; /* text of most recent message */
115 static char HeldMessageBuf[sizeof(MsgBuf)]; /* for held messages */
120 syserr(const char *fmt, ...)
122 syserr(fmt, va_alist)
125 #endif /* __STDC__ */
128 int save_errno = errno;
129 bool panic, exiting, keep;
137 panic = exiting = keep = false;
142 panic = exiting = true;
156 /* format and output the error message */
160 ** Since we are terminating the process,
161 ** we are aborting the entire SMTP session,
162 ** rather than just the current transaction.
168 else if (save_errno == 0)
178 SM_VA_START(ap, fmt);
179 errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap);
183 /* save this message for mailq printing */
184 if (!panic && CurEnv != NULL && (!keep || CurEnv->e_message == NULL))
186 char *nmsg = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
188 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
189 sm_free(CurEnv->e_message);
190 CurEnv->e_message = nmsg;
193 /* determine exit status if not already set */
194 if (ExitStat == EX_OK)
197 ExitStat = EX_SOFTWARE;
201 sm_dprintf("syserr: ExitStat = %d\n", ExitStat);
204 pw = sm_getpwuid(RealUid);
210 (void) sm_snprintf(ubuf, sizeof(ubuf), "UID%d", (int) RealUid);
214 sm_syslog(panic ? LOG_ALERT : LOG_CRIT,
215 CurEnv == NULL ? NOQID : CurEnv->e_id,
216 "SYSERR(%s): %.900s",
240 mci_dump_all(smioout, true);
255 sm_exc_raisenew_x(&EtypeQuickAbort, 2);
259 ** USRERR -- Signal user error.
261 ** This is much like syserr except it is for user errors.
264 ** fmt -- the format string. If it does not begin with
265 ** a three-digit SMTP reply code, 550 is assumed.
266 ** (others) -- sm_io_printf strings
270 ** Raises E:mta.quickabort if QuickAbort is set.
273 ** increments Errors.
279 usrerr(const char *fmt, ...)
281 usrerr(fmt, va_alist)
284 #endif /* __STDC__ */
290 if (fmt[0] == '5' || fmt[0] == '6')
292 else if (fmt[0] == '4' || fmt[0] == '8')
294 else if (fmt[0] == '2')
298 SM_VA_START(ap, fmt);
299 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap);
305 /* save this message for mailq printing */
310 if (CurEnv->e_message != NULL)
317 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
318 sm_free(CurEnv->e_message);
319 if (MsgBuf[0] == '6')
323 (void) sm_snprintf(buf, sizeof(buf),
324 "Postmaster warning: %.*s",
325 (int) sizeof(buf) - 22, errtxt);
327 sm_rpool_strdup_x(CurEnv->e_rpool, buf);
332 sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
338 if (LogLevel > 3 && LogUsrErrs)
339 sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
341 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
345 ** USRERRENH -- Signal user error.
347 ** Same as usrerr but with enhanced status code.
350 ** enhsc -- the enhanced status code.
351 ** fmt -- the format string. If it does not begin with
352 ** a three-digit SMTP reply code, 550 is assumed.
353 ** (others) -- sm_io_printf strings
357 ** Raises E:mta.quickabort if QuickAbort is set.
360 ** increments Errors.
366 usrerrenh(char *enhsc, const char *fmt, ...)
368 usrerrenh(enhsc, fmt, va_alist)
372 #endif /* __STDC__ */
377 if (SM_IS_EMPTY(enhsc))
379 if (fmt[0] == '5' || fmt[0] == '6')
381 else if (fmt[0] == '4' || fmt[0] == '8')
383 else if (fmt[0] == '2')
386 SM_VA_START(ap, fmt);
387 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap);
393 /* save this message for mailq printing */
398 if (CurEnv->e_message != NULL)
405 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
406 sm_free(CurEnv->e_message);
407 if (MsgBuf[0] == '6')
411 (void) sm_snprintf(buf, sizeof(buf),
412 "Postmaster warning: %.*s",
413 (int) sizeof(buf) - 22, errtxt);
415 sm_rpool_strdup_x(CurEnv->e_rpool, buf);
420 sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
426 if (LogLevel > 3 && LogUsrErrs)
427 sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
429 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
433 ** MESSAGE -- print message (not necessarily an error)
436 ** msg -- the message (sm_io_printf fmt) -- it can begin with
437 ** an SMTP reply code. If not, 050 is assumed.
438 ** (others) -- sm_io_printf arguments
447 message(const char *msg, ...)
449 message(msg, va_alist)
452 #endif /* __STDC__ */
458 SM_VA_START(ap, msg);
459 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap);
461 putoutmsg(MsgBuf, false, false);
463 /* save this message for mailq printing */
468 if (CurEnv->e_message != NULL)
473 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
474 sm_free(CurEnv->e_message);
475 CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
482 ** EMESSAGE -- print message (not necessarily an error)
483 ** (same as message() but requires reply code and enhanced status code)
486 ** replycode -- SMTP reply code.
487 ** enhsc -- enhanced status code.
488 ** msg -- the message (sm_io_printf fmt) -- it can begin with
489 ** an SMTP reply code. If not, 050 is assumed.
490 ** (others) -- sm_io_printf arguments
499 emessage(const char *replycode, const char *enhsc, const char *msg, ...)
500 # else /* __STDC__ */
501 emessage(replycode, enhsc, msg, va_alist)
502 const char *replycode;
506 # endif /* __STDC__ */
512 SM_VA_START(ap, msg);
513 errtxt = fmtmsg(MsgBuf, CurEnv->e_to, replycode, enhsc, 0, msg, ap);
515 putoutmsg(MsgBuf, false, false);
517 /* save this message for mailq printing */
522 if (CurEnv->e_message != NULL)
527 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
528 sm_free(CurEnv->e_message);
529 CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
535 ** EXTSC -- check and extract a status codes
538 ** msg -- string with possible enhanced status code.
539 ** delim -- delim for enhanced status code.
540 ** replycode -- pointer to storage for SMTP reply code;
541 ** must be != NULL and have space for at least
543 ** enhsc -- pointer to storage for enhanced status code;
544 ** must be != NULL and have space for at least
545 ** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3})
548 ** -1 -- no SMTP reply code.
549 ** >=3 -- offset of error text in msg.
550 ** (<=4 -- no enhanced status code)
554 extsc(msg, delim, replycode, enhsc)
562 SM_REQUIRE(replycode != NULL);
563 SM_REQUIRE(enhsc != NULL);
568 if (!ISSMTPREPLY(msg))
570 sm_strlcpy(replycode, msg, 4);
574 if (isenhsc(msg + 4, delim))
575 offset = extenhsc(msg + 4, delim, enhsc) + 4;
578 #endif /* _FFR_PROXY */
581 ** NMESSAGE -- print message (not necessarily an error)
583 ** Just like "message" except it never puts the to... tag on.
586 ** msg -- the message (sm_io_printf fmt) -- if it begins
587 ** with a three digit SMTP reply code, that is used,
588 ** otherwise 050 is assumed.
589 ** (others) -- sm_io_printf arguments
598 nmessage(const char *msg, ...)
600 nmessage(msg, va_alist)
603 #endif /* __STDC__ */
609 SM_VA_START(ap, msg);
610 errtxt = fmtmsg(MsgBuf, (char *) NULL, "050",
611 (char *) NULL, 0, msg, ap);
613 putoutmsg(MsgBuf, false, false);
615 /* save this message for mailq printing */
620 if (CurEnv->e_message != NULL)
625 if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL)
626 sm_free(CurEnv->e_message);
627 CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt);
633 ** PUTOUTMSG -- output error message to transcript and channel
636 ** msg -- message to output (in SMTP format).
637 ** holdmsg -- if true, don't output a copy of the message to
638 ** our output channel.
639 ** heldmsg -- if true, this is a previously held message;
640 ** don't log it to the transcript file.
646 ** Outputs msg to the transcript.
647 ** If appropriate, outputs it to the channel.
648 ** Deletes SMTP reply code number as appropriate.
652 putoutmsg(msg, holdmsg, heldmsg)
657 char msgcode = msg[0];
661 /* display for debugging */
663 sm_dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
664 heldmsg ? " (held)" : "");
666 /* map warnings to something SMTP can handle */
669 else if (msgcode == '8')
671 id = (CurEnv != NULL) ? CurEnv->e_id : NULL;
673 /* output to transcript if serious */
674 if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&
675 strchr("45", msg[0]) != NULL)
676 (void) sm_io_fprintf(CurEnv->e_xfp, SM_TIME_DEFAULT, "%s\n",
679 if (LogLevel > 14 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
680 sm_syslog(LOG_INFO, id,
681 "--- %s%s%s", msg, holdmsg ? " (hold)" : "",
682 heldmsg ? " (held)" : "");
687 /* output to channel if appropriate */
688 if (!Verbose && msg[0] == '0')
692 /* save for possible future display */
694 if (HeldMessageBuf[0] == '5' && msgcode == '4')
696 (void) sm_strlcpy(HeldMessageBuf, msg, sizeof(HeldMessageBuf));
700 (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
702 if (OutChannel == NULL)
705 /* find actual text of error (after SMTP status codes) */
706 if (ISSMTPREPLY(errtxt))
711 l = isenhsc(errtxt, ' ');
713 l = isenhsc(errtxt, '\0');
718 /* if DisConnected, OutChannel now points to the transcript */
720 (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
721 (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\r\n",
724 (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\n",
726 if (TrafficLogFile != NULL)
727 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT,
728 "%05d >>> %s\n", (int) CurrentPid,
729 (OpMode == MD_SMTP || OpMode == MD_DAEMON)
733 ** Note: in case of an SMTP reply this should check
734 ** that the last line of msg is not a continuation line
735 ** but that's probably not worth the effort.
738 if (ISSMTPREPLY(msg))
739 (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
740 if (!sm_io_error(OutChannel) || DisConnected)
744 ** Error on output -- if reporting lost channel, just ignore it.
745 ** Also, ignore errors from QUIT response (221 message) -- some
746 ** rude servers don't read result.
749 if (InChannel == NULL || sm_io_eof(InChannel) ||
750 sm_io_error(InChannel) || strncmp(msg, "221", 3) == 0)
753 /* can't call syserr, 'cause we are using MsgBuf */
756 sm_syslog(LOG_CRIT, id,
757 "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
759 shortenstring(msg, MAXSHORTSTR), sm_errstring(errno));
760 #endif /* !PIPELINING */
764 ** PUTERRMSG -- like putoutmsg, but does special processing for error messages
767 ** msg -- the message to output.
773 ** Sets the fatal error bit in the envelope as appropriate.
780 char msgcode = msg[0];
782 /* output the message as usual */
783 putoutmsg(msg, HoldErrs, false);
785 /* be careful about multiple error messages */
789 /* signal the error */
797 /* notify the postmaster */
798 CurEnv->e_flags |= EF_PM_NOTIFY;
800 else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
802 /* mark long-term fatal errors */
803 CurEnv->e_flags |= EF_FATALERRS;
808 ** ISENHSC -- check whether a string contains an enhanced status code
811 ** s -- string with possible enhanced status code.
812 ** delim -- delim for enhanced status code.
815 ** 0 -- no enhanced status code.
816 ** >4 -- length of enhanced status code.
828 if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
832 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
834 if (h == 0 || s[l + h] != '.')
838 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
840 if (h == 0 || s[l + h] != delim)
846 ** EXTENHSC -- check and extract an enhanced status code
849 ** s -- string with possible enhanced status code.
850 ** delim -- delim for enhanced status code.
851 ** e -- pointer to storage for enhanced status code.
852 ** must be != NULL and have space for at least
853 ** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3})
856 ** 0 -- no enhanced status code.
857 ** >4 -- length of enhanced status code.
860 ** fills e with enhanced status code.
864 extenhsc(s, delim, e)
873 if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
879 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
884 if (h == 0 || s[l + h] != '.')
889 while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
894 if (h == 0 || s[l + h] != delim)
902 ** SKIPADDRHOST -- skip address and host in a message
905 ** s -- string with possible address and host
906 ** skiphost -- skip also host?
909 ** 0 -- no address and host
910 ** >0 -- position after address (and host)
914 skipaddrhost(s, skiphost)
921 #define SM_ADDR_DELIM "... "
924 str = strstr(s, SM_ADDR_DELIM);
927 str += sizeof(SM_ADDR_DELIM) + 1;
934 str = strchr(str, ' ');
942 ** FMTMSG -- format a message into buffer.
945 ** eb -- error buffer to get result -- MUST BE MsgBuf.
946 ** to -- the recipient tag for this message.
947 ** num -- default three digit SMTP reply code.
948 ** enhsc -- enhanced status code.
949 ** en -- the error number to display.
950 ** fmt -- format of string: See NOTE below.
951 ** ap -- arguments for fmt.
954 ** pointer to error text beyond status codes.
957 ** Do NOT use "%s" as fmt if the argument starts with an SMTP
962 fmtmsg(eb, to, num, enhsc, eno, fmt, ap)
973 int spaceleft = sizeof(MsgBuf);
976 /* output the reply code */
986 if (SoftBounce && num[0] == '5')
989 (void) sm_snprintf(eb, spaceleft, "4%2.2s%c", num + 1, del);
992 (void) sm_snprintf(eb, spaceleft, "%3.3s%c", num, del);
996 if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4)
998 /* copy enh.status code including trailing blank */
1000 (void) sm_strlcpy(eb, fmt, l + 1);
1005 else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4)
1007 /* copy enh.status code */
1008 (void) sm_strlcpy(eb, enhsc, l + 1);
1014 if (SoftBounce && eb[-l] == '5')
1016 /* replace 5 by 4 */
1021 /* output the file name and line number */
1022 if (FileName != NULL)
1024 (void) sm_snprintf(eb, spaceleft, "%s: line %d: ",
1025 shortenstring(FileName, 83), LineNumber);
1026 eb += (l = strlen(eb));
1031 ** output the "to" address only if it is defined and one of the
1032 ** following codes is used:
1033 ** 050 internal notices, e.g., alias expansion
1035 ** 252 Cannot VRFY user, but will accept message and attempt delivery
1036 ** 450 Requested mail action not taken: mailbox unavailable
1037 ** 550 Requested action not taken: mailbox unavailable
1038 ** 553 Requested action not taken: mailbox name not allowed
1040 ** Notice: this still isn't "the right thing", this code shouldn't
1041 ** (indirectly) depend on CurEnv->e_to.
1044 if (to != NULL && to[0] != '\0' &&
1045 (strncmp(num, "050", 3) == 0 ||
1046 strncmp(num, "250", 3) == 0 ||
1047 strncmp(num, "252", 3) == 0 ||
1048 strncmp(num, "450", 3) == 0 ||
1049 strncmp(num, "550", 3) == 0 ||
1050 strncmp(num, "553", 3) == 0))
1052 #if _FFR_8BITENVADDR
1053 char xbuf[MAXNAME + 1]; /* EAI:ok */
1057 (void) sm_strlcpy(xbuf, to, len);
1058 (void) dequote_internal_chars(xbuf, xbuf, len);
1059 (void) sm_strlcpyn(eb, spaceleft, 2,
1060 shortenstring(xbuf, MAXSHORTSTR), "... ");
1062 #else /* _FFR_8BITENVADDR */
1063 (void) sm_strlcpyn(eb, spaceleft, 2,
1064 shortenstring(to, MAXSHORTSTR), "... ");
1067 #endif /* _FFR_8BITENVADDR */
1068 spaceleft -= strlen(eb);
1071 /* output the message */
1072 (void) sm_vsnprintf(eb, spaceleft, fmt, ap);
1073 spaceleft -= strlen(eb);
1081 /* output the error code, if any */
1083 (void) sm_strlcpyn(eb, spaceleft, 2, ": ", sm_errstring(eno));
1089 ** BUFFER_ERRORS -- arrange to buffer future error messages
1101 HeldMessageBuf[0] = '\0';
1106 ** FLUSH_ERRORS -- flush the held error message buffer
1109 ** print -- if set, print the message, otherwise just
1120 if (print && HeldMessageBuf[0] != '\0')
1121 putoutmsg(HeldMessageBuf, false, true);
1122 HeldMessageBuf[0] = '\0';
1126 ** SM_ERRSTRING -- return string description of error code
1129 ** errnum -- the error number to translate
1132 ** A string description of errnum.
1136 sm_errstring(errnum)
1141 static char buf[MAXLINE];
1146 #if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
1147 extern char *sys_errlist[];
1148 extern int sys_nerr;
1152 ** Handle special network error codes.
1154 ** These are 4.2/4.3bsd specific; they should be in daemon.c.
1164 err = strerror(errnum);
1167 (void) sm_snprintf(errbuf, sizeof(errbuf),
1168 "Error %d", errnum);
1171 (void) sm_strlcpy(bp, err, SPACELEFT(buf, bp));
1172 #else /* HASSTRERROR */
1173 if (errnum >= 0 && errnum < sys_nerr)
1174 (void) sm_strlcpy(bp, sys_errlist[errnum],
1175 SPACELEFT(buf, bp));
1177 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1178 "Error %d", errnum);
1179 #endif /* HASSTRERROR */
1181 if (CurHostName != NULL)
1183 if (errnum == ETIMEDOUT)
1185 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1192 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1193 "Connection reset by ");
1196 (void) sm_strlcpy(bp,
1197 shortenstring(CurHostName, MAXSHORTSTR),
1198 SPACELEFT(buf, bp));
1201 if (SmtpPhase != NULL)
1203 (void) sm_snprintf(bp, SPACELEFT(buf, bp),
1204 " during %s", SmtpPhase);
1209 if (CurHostName == NULL)
1211 (void) sm_snprintf(buf, sizeof(buf), "Host %s is down",
1212 shortenstring(CurHostName, MAXSHORTSTR));
1216 if (CurHostName == NULL)
1218 (void) sm_strlcpyn(buf, sizeof(buf), 2, "Connection refused by ",
1219 shortenstring(CurHostName, MAXSHORTSTR));
1223 case HOST_NOT_FOUND + E_DNSBASE:
1224 dnsmsg = "host not found";
1227 case TRY_AGAIN + E_DNSBASE:
1228 dnsmsg = "host name lookup failure";
1231 case NO_RECOVERY + E_DNSBASE:
1232 dnsmsg = "non-recoverable error";
1235 case NO_DATA + E_DNSBASE:
1236 dnsmsg = "no data known";
1238 #endif /* NAMED_BIND */
1241 /* SunOS gives "Not owner" -- this is the POSIX message */
1242 return "Operation not permitted";
1245 ** Error messages used internally in sendmail.
1248 case E_SM_OPENTIMEOUT:
1249 return "Timeout on file open";
1252 return "Symbolic links not allowed";
1255 return "Hard links not allowed";
1258 return "Regular files only";
1261 return "Executable files not allowed";
1264 return "World writable directory";
1267 return "Group writable directory";
1269 case E_SM_FILECHANGE:
1270 return "File changed after open";
1273 return "World writable file";
1276 return "Group writable file";
1279 return "Group readable file";
1282 return "World readable file";
1288 bp += sm_strlcpy(bp, "Name server: ", sizeof(buf));
1289 if (CurHostName != NULL)
1291 (void) sm_strlcpyn(bp, SPACELEFT(buf, bp), 2,
1292 shortenstring(CurHostName, MAXSHORTSTR), ": ");
1295 (void) sm_strlcpy(bp, dnsmsg, SPACELEFT(buf, bp));
1300 if (errnum >= E_LDAPBASE - E_LDAP_SHIM)
1301 return ldap_err2string(errnum - E_LDAPBASE);
1305 err = strerror(errnum);
1308 (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum);
1312 #else /* HASSTRERROR */
1313 if (errnum > 0 && errnum < sys_nerr)
1314 return sys_errlist[errnum];
1316 (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum);
1318 #endif /* HASSTRERROR */