/*
* Copyright (c) 2004-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: smerr2txt.c,v 1.26 2007/11/05 05:47:50 ca Exp $")
#include "sm/error.h"
#include "sm/dns.h"
#include "sm/bdb.h"
#include "sm/rfc2821.h"
#define SMERR2TXT 1
#include "smerr2txt.h"
#if 0
/*
convert define line to struct entry:
:'a,.s/^#define \(SM[^ ]*\).*/ { \1, "\1" },/
*/
#endif /* 0 */
static e2s_T
e_modules[] =
{
{ SM_EM_NONE, "none" },
{ SM_EM_AQ, "AQ" },
{ SM_EM_IQDB, "IQDB" },
{ SM_EM_IBDB, "IBDB" },
{ SM_EM_EDB, "EDB" },
{ SM_EM_CDB, "CDB" },
{ SM_EM_DA, "delivery agent" },
{ SM_EM_OCC, "open connection cache" },
{ SM_EM_DNS, "DNS" },
{ SM_EM_SMTPC, "SMTPC" },
{ SM_EM_SMTPS, "SMTPS" },
{ SM_EM_MAPS, "MAPS" },
{ SM_EM_MAP, "MAP" },
{ SM_EM_BDB, "BDB" },
{ SM_EM_STTHRIO, "STTHRIO" },
{ SM_EM_STTHR, "STTHR" },
{ SM_EM_EVTHR, "EVTHR" },
{ SM_EM_RECCOM, "RECCOM" },
{ SM_EM_HT, "hash table" },
{ SM_EM_RSC, "restricted size cache" },
{ SM_EM_STR, "str" },
{ SM_EM_RCB, "RCB" },
{ SM_EM_TLS, "TLS" },
{ SM_EM_SASL, "SASL" },
{ SM_EM_NET, "NET" },
{ SM_EM_IO, "IO" },
{ SM_EM_LOG, "logging" },
{ SM_EM_ADDR, "RFC 2821 address parsing" },
{ SM_EM_IP, "IP address parsing" },
{ SM_EM_Q_Q2AR, "QMGR: QMGR to SMAR" },
{ SM_EM_Q_AR2Q, "QMGR: SMAR to QMGR" },
{ SM_EM_Q_Q2SS, "QMGR: QMGR to SMTPS" },
{ SM_EM_Q_SS2Q, "QMGR: SMTPS to QMGR" },
{ SM_EM_Q_Q2SC, "QMGR: QMGR to SMTPC" },
{ SM_EM_Q_SC2Q, "QMGR: SMTPC to QMGR" },
{ SM_EM_Q_RDIBDB, "QMGR: read IBDB" },
{ SM_EM_Q_IQDB, "QMGR: IQDB" },
{ SM_EM_Q_IBDB, "QMGR: IBDB" },
{ SM_EM_Q_EDBC, "QMGR: EDBC" },
{ SM_EM_Q_DSN, "QMGR: DSN" },
{ SM_EM_Q_START, "QMGR: startup" },
{ SM_EM_Q_CTL2Q, "QMGR: control" },
{ SM_EM_Q_CONF, "QMGR: configuration" },
{ SM_EM_Q_CLEAN, "QMGR: cleanup" },
{ SM_EM_Q_SCHED, "QMGR: scheduler" },
{ SM_EM_Q, "QMGR: misc" },
{ SM_EM_AR_Q2AR, "SMAR: QMGR to SMAR" },
{ SM_EM_AR_AR2Q, "SMAR: SMAR to QMGR" },
{ SM_EM_AR_DNSW, "SMAR: DNS write" },
{ SM_EM_AR_DNSR, "SMAR: DNS read" },
{ SM_EM_AR_DNSD, "SMAR: DNS read" },
{ SM_EM_AR_WAIT, "SMAR: wait for async function" },
{ SM_EM_AR, "SMAR: misc" },
{ SM_EM_CONF, "configuration" },
{ SM_EM_PMILTER, "pmilter" },
{ SM_EM_THR, "thread" },
{ SM_EM_BATV, "BATV" },
{ SM_EM_UTIL, "utility functions" },
{ 0, NULL }
};
e2s_T
e_error[] =
{
{ SM_E_NOMORE, "no next entry" },
{ SM_E_UNEXPECTED, "unexpected" },
{ SM_E_RANGE, "input parameter out of range" },
{ SM_E_2BIG, "input parameter too big" },
{ SM_E_FULL, "object full" },
{ SM_E_OVFLW_SC, "scalar overflow" },
{ SM_E_OVFLW_NS, "nonscalar overflow" },
{ SM_E_NOTFOUND, "not found" },
{ SM_E_STARTFAIL, "start failure" },
{ SM_E_SYNTAX, "syntax" },
{ SM_E_USAGE, "usage" },
{ SM_E_DONTSTART, "donotstart" },
{ SM_E_VER_MIX, "version mismatch" },
{ SM_E_NO_AR, "smar not available" },
{ SM_E_NO_DA, "no delivery agent available" },
{ SM_E_NO_DA_FREE, "no free delivery agent" },
{ SM_E_PR_V_MISM, "protocol version mismatch" },
{ SM_E_PR_ERR, "protocol error" },
{ SM_E_RCB2LONG, "RCB too large" },
{ SM_E_TEMPMAP, "temporary map error" },
{ SM_E_PERMMAP, "permanent map error" },
{ SM_E_CLOSEDMAP, "closedmap" },
{ SM_E_NOMAP, "map is not available" },
{ SM_E_NOTIMPL, "not implemented" },
{ SM_E_MXEMPTY, "MX list is empty after removal of local addresses" },
{ SM_E_TTMYSELF, "talking to myself" },
{ SM_E_ALIASEXP, "alias expansion failed" },
{ SM_E_ALIAS_REC, "aliases nested too deep" },
{ SM_E_IP_MISM, "DNS answer from different server" },
{ SM_E_NOSIG, "no signature" },
{ SM_E_EXPIRED, "expired" },
{ SM_E_RSR_PRB, "resource problem" },
{ SM_E_ILL_PIPE, "illegal pipelining" },
{ SM_E_RD, "read error" },
{ SM_E_EOF, "EOF" },
{ SM_E_WR, "write error" },
{ SM_E_BARE_NL, "bare NL detected" },
{ SM_E_CONN_CLSD, "internal connection to other module closed" },
{ SM_E_WRONG_ID, "internal error: communication context id mismatch" },
{ SM_SSL_ERROR_SYSCALL, "TLS syscall error" },
{ SM_SSL_ERROR_SSL, "TLS protocol error" },
{ SM_SSL_ERROR_GENERIC, "TLS unknown error" },
{ SM_E_UNAVAIL, "unavailable" },
{ DNSR_NOTFOUND, "DNS record not found (authorative)" },
{ DNSR_NO_DATA, "valid name but no data record of requested type" },
{ DNSR_TEMP, "query failed: try again" },
{ DNSR_PERM, "query failed: do not retry" },
{ DNSR_TIMEOUT, "query timed out" },
{ DNSR_REFUSED, "query refused by nameserver" },
{ DNSR_MXINVALID, "MX record invalid" },
{ DNSR_PTRINVALID, "PTR record invalid" },
{ DNSR_CNINVALID, "CNAME record invalid" },
{ R2821_ERR_LEFT, "missing '<'" },
{ R2821_ERR_RIGHT, "missing '>'" },
{ R2821_ERR_ROUTE, "route address not allowed" },
{ R2821_ERR_HOST, "domain part does not start with an atom" },
{ R2821_ERR_FQDN, "domain part is not a FQDN" },
{ R2821_ERR_LOCAL, "missing local part" },
{ R2821_ERR_AT, "missing '@'" },
{ R2821_ERR_EMPTY, "<> not allowed here" },
{ R2821_ERR_MBOX, "completely empty address" },
{ R2821_ERR_COLON, "missing ':' (unused)" },
{ R2821_ERR_DOTSTR, "\"dotstr\" syntax is wrong: expected atom after '.'" },
{ R2821_ERR_DOMAIN, "domain part is empty" },
{ R2821_ERR_DOT, "expecting ':'" },
{ R2821_ERR_TRAILDOT, "domain has trailing '.'" },
{ R2821_ERR_ATDOMAIN, "'@' in route address missing" },
{ R2821_ERR_COMMA, "comma in route address missing" },
{ R2821_ERR_DOMSYNTAX, "domain part has wrong syntax" },
{ R2821_ERR_MORE, "tokens after end" },
{ R2821_ERR_DEL_MISS, "domain does not end in delimiter" },
{ R2821_ERR_TOOLONG, "address too long" },
{ R2821_ERR_TRAILBACKSL, "trailing backslash" },
{ R2821_ERR_CLS_BRACKET, "too many closing brackets" },
{ R2821_ERR_CLS_PARENTH, "too many closing parentheses" },
{ R2821_ERR_PARENTHESIS, "parenthesis in address not allowed" },
{ R2821_ERR_MUSTQUOTE, "character must be quoted but isn't" },
{ SM_CNF_E_NEWLINE_IN_STRING, "newline in string" },
{ SM_CNF_E_EOF_IN_STRING, "EOF in string" },
{ SM_CNF_E_BAD_CHAR, "unexpected character" },
{ SM_CNF_E_NO_MEMORY, "out of memory" },
{ SM_CNF_E_HEX_EXPECTED, "hexadecimal digit expected after \\x \\u or \\U" },
{ SM_CNF_E_CHAR_OVERFLOW, "character constant too large" },
{ SM_CNF_E_INVALID, "invalid argument to configuration function" },
{ SM_CNF_E_READ, "error while reading configuration file" },
{ SM_CNF_E_READ_OPEN, "cannot open configuration file for reading" },
{ SM_CNF_E_READ_CLOSE, "error closing configuration file after reading" },
{ SM_CNF_E_SYNTAX, "syntax error" },
{ SM_CNF_E_NOT_FOUND, "not found" },
{ SM_CNF_E_ALREADY, "already exists" },
{ SM_CNF_E_TYPE, "invalid value" },
{ SM_CNF_E_NUL_IN_STRING, "ascii NUL character in string" },
{ SM_CNF_E_TOO_MANY, "too many elements in array" },
{ 0, NULL }
};
/* XXX HACK XXX is there a DB function to do this? */
e2s_T
e_bdb4_2[] =
{
{ DB_DONOTINDEX, "DB_DONOTINDEX" },
#ifdef DB_FILEOPEN
{ DB_FILEOPEN, "DB_FILEOPEN" },
#endif
{ DB_KEYEMPTY, "DB_KEYEMPTY" },
{ DB_KEYEXIST, "DB_KEYEXIST" },
{ DB_LOCK_DEADLOCK, "DB_LOCK_DEADLOCK" },
{ DB_LOCK_NOTGRANTED, "DB_LOCK_NOTGRANTED" },
{ DB_NOSERVER, "DB_NOSERVER" },
{ DB_NOSERVER_HOME, "DB_NOSERVER_HOME" },
{ DB_NOSERVER_ID, "DB_NOSERVER_ID" },
{ DB_NOTFOUND, "DB_NOTFOUND" },
{ DB_OLD_VERSION, "DB_OLD_VERSION" },
{ DB_PAGE_NOTFOUND, "DB_PAGE_NOTFOUND" },
{ DB_REP_DUPMASTER, "DB_REP_DUPMASTER" },
#ifdef DB_REP_HANDLE_DEAD
{ DB_REP_HANDLE_DEAD, "DB_REP_HANDLE_DEAD" },
#endif
{ DB_REP_HOLDELECTION, "DB_REP_HOLDELECTION" },
#ifdef DB_REP_ISPERM
{ DB_REP_ISPERM, "DB_REP_ISPERM" },
#endif
{ DB_REP_NEWMASTER, "DB_REP_NEWMASTER" },
{ DB_REP_NEWSITE, "DB_REP_NEWSITE" },
#ifdef DB_REP_NOTPERM
{ DB_REP_NOTPERM, "DB_REP_NOTPERM" },
#endif
#ifdef DB_REP_OUTDATED
{ DB_REP_OUTDATED, "DB_REP_OUTDATED" },
#endif
{ DB_REP_UNAVAIL, "DB_REP_UNAVAIL" },
{ DB_RUNRECOVERY, "DB_RUNRECOVERY" },
{ DB_SECONDARY_BAD, "DB_SECONDARY_BAD" },
#ifdef DB_VERIFY_BAD
{ DB_VERIFY_BAD, "DB_VERIFY_BAD" },
#endif
#if defined(DB_BUFFER_SMALL) && ENOMEM != DB_BUFFER_SMALL
{ DB_BUFFER_SMALL, "DB_BUFFER_SMALL" },
#endif
{ 0, NULL }
};
#if 0
static e2s_T
e_dns[] =
{
{ DNSR_NOTFOUND, "DNSR Not Found" },
{ DNSR_NO_DATA, "Valid name but no data record of requested type" },
{ DNSR_TEMP, "query failed: try again" },
{ DNSR_PERM, "query failed: don't retry" },
{ DNSR_TIMEOUT, "query timed out" },
{ DNSR_REFUSED, "query refused by nameserver" },
{ DNSR_MXINVALID, "MX record invalid" },
{ DNSR_PTRINVALID, "PTR record invalid" },
{ DNSR_CNINVALID, "CNAME record invalid" },
{ 0, NULL }
};
#endif /* 0 */
char *
finde(int ecode, e2s_P table)
{
int i;
i = 0;
while (table[i].e2s_code != 0 || table[i].e2s_str != NULL)
{
if (table[i].e2s_code == ecode)
return table[i].e2s_str;
if (sm_error_value(table[i].e2s_code) == sm_error_value(ecode))
return table[i].e2s_str;
++i;
}
return NULL;
}
char *
smmod2txt(sm_error_T err)
{
char *errtxt;
errtxt = finde(sm_error_module(err), e_modules);
return (errtxt != NULL) ? errtxt : SM_ETXT_UNKNOWN;
}
char *
smerr2txt(sm_error_T err)
{
int errornumber, eno;
char *errtxt;
eno = errornumber = sm_error_value(err);
errtxt = NULL;
if (err == SM_IO_EOF)
errtxt = "EOF";
else if (errornumber > 0 && errornumber < sm_sys_nerr)
errtxt = strerror(errornumber);
else if (SM_IS_BDB_ERR(err))
#if 0
/*
** If this is used then every application needs to link
** against libdb.
*/
errtxt = db_strerror(eno);
#else
errtxt = finde(eno, e_bdb4_2);
#endif
#if 0
else if (errornumber >= DNS_ERR_BASE && errornumber < R2821_BASE)
errtxt = finde(err, e_dns);
#endif /* 0 */
else
errtxt = finde(errornumber, e_error);
return (errtxt != NULL) ? errtxt : SM_ETXT_UNKNOWN;
}
syntax highlighted by Code2HTML, v. 0.9.1