/*
* Copyright (c) 2002-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.
*
* $Id: error.h,v 1.75 2007/01/11 05:13:48 ca Exp $
*/
#ifndef SM_ERROR_H
#define SM_ERROR_H 1
#include "sm/generic.h"
#include "sm/types.h"
#if HAVE_ERRNO_H
# include <errno.h>
#endif
/* need a 32bit signed integer */
typedef int32_t sm_error_T;
typedef int32_t sm_ret_T;
#define SM_RET_MAX INT32_MAX
/* not an error, but a useful return code for some functions */
#define SM_NOMATCH 1
#define SM_NOTDONE 2 /* operation not performed because it wasn't necessary */
/*
** layout:
** bit 31 1 (if error)
** bit 30-24 module (7bit: 0..127)
** bit 23-16 type (8bit: 0..255)
** bit 15- 0 number (similar to errno) (16bit)
**
** less bits for type, more for module?
**
** Note: Berkeley DB uses negative error numbers: -30800 -30999
** hence we cast the value to int16_t and then to int to preserve the sign.
*/
#define SM_ERR_HIGH_BIT 0x80000000
#define SM_ERR_MODULE_BITS 0x0000007f
#define SM_ERR_TYPE_BITS 0x000000ff
#define SM_ERR_VALUE_BITS 0x0000ffff
#define SM_ERR_MODULE_OFF 24
#define SM_ERR_TYPE_OFF 16
#define SM_ERR_VALUE_OFF 0 /* if changed: see below! */
#define sm_error_module(err) (((err) >> SM_ERR_MODULE_OFF) & SM_ERR_MODULE_BITS)
#define sm_error_type(err) (((err) >> SM_ERR_TYPE_OFF) & SM_ERR_TYPE_BITS)
#define sm_error_value(err) ((sm_ret_T)((int16_t)(err)))
#define sm_error_gen(mod, type, value) ((sm_ret_T)(SM_ERR_HIGH_BIT |\
((((mod) & SM_ERR_MODULE_BITS) << SM_ERR_MODULE_OFF) |\
(((type) & SM_ERR_TYPE_BITS) << SM_ERR_TYPE_OFF) |\
((value) & SM_ERR_VALUE_BITS))))
/* everything is fine... */
/* #define SM_SUCCESS 0 defined in generic.h */
/* error types, notice checks down below: require order */
#define SM_ERR_NONE 0
#define SM_ERR_INFO 1 /* make this "compliant" with EOF? */
#define SM_ERR_WARN 2
#define SM_ERR_TEMP 3
#define SM_ERR_PERM 4
/* more? */
/*
** For example:
** SM_ERR_SOFT_LIMIT
** SM_ERR_HARD_LIMIT
** SM_ERR_CONF_LIMIT
**
*/
/* No an error iff the high bit is not set */
#define sm_is_success(err) (((err) & SM_ERR_HIGH_BIT) == 0)
#define sm_is_err(err) (((err) & SM_ERR_HIGH_BIT) != 0)
/* Note: this can also be just a warning or info! */
/*
** XXX This doesn't really work if we want to "merge" error values
** and others, i.e,. if error values must have SM_ERR_HIGH_BIT set.
** Do we want that?
** XXX See above! Requires ordering! Maybe use bitmask?
*/
/* these checks are not ok unless you already know it's an error */
#define sm_is_temp_err(err) (sm_error_type(err) == SM_ERR_TEMP)
#define sm_is_perm_err(err) (sm_error_type(err) == SM_ERR_PERM)
#define sm_is_warn_err(err) (sm_error_type(err) == SM_ERR_WARN)
#define sm_is_error(err) (sm_error_type(err) > SM_ERR_WARN)
#define sm_is_ok(err) (sm_error_type(err) <= SM_ERR_WARN)
/* these checks are ok */
#define SM_IS_TEMP_ERR(err) (sm_is_err(err) && sm_error_type(err) == SM_ERR_TEMP)
#define SM_IS_PERM_ERR(err) (sm_is_err(err) && sm_error_type(err) == SM_ERR_PERM)
#define SM_IS_ERROR(err) (sm_is_err(err) && sm_error_type(err) > SM_ERR_WARN)
#define SM_IS_OK(err) (sm_is_success(err) || sm_error_type(err) <= SM_ERR_WARN)
#define sm_error_info(mod, value) sm_error_gen(mod, SM_ERR_INFO, (value))
#define sm_error_warn(mod, value) sm_error_gen(mod, SM_ERR_WARN, (value))
#define sm_error_temp(mod, value) sm_error_gen(mod, SM_ERR_TEMP, (value))
#define sm_error_perm(mod, value) sm_error_gen(mod, SM_ERR_PERM, (value))
#define sm_err_info(value) sm_error_gen(0, SM_ERR_INFO, (value))
#define sm_err_warn(value) sm_error_gen(0, SM_ERR_WARN, (value))
#define sm_err_temp(value) sm_error_gen(0, SM_ERR_TEMP, (value))
#define sm_err_perm(value) sm_error_gen(0, SM_ERR_PERM, (value))
/*
** Where to start? This is the same value as in sm8/include/errstring.h
** Make sure these offsets match the error codes used below!
**
** NOTE: if you make additions here, then change also libmta/smerr2txt.c
*/
#define SM_ERR_BASE 256
#define DNS_ERR_BASE (SM_ERR_BASE + 64)
#define R2821_BASE 512
/* sm specific error codes */
#define SM_E_NOMORE (SM_ERR_BASE + 1) /* no "next" entry */
#define SM_E_UNEXPECTED (SM_ERR_BASE + 2) /* unexpected error */
/*
** Input parameter out of range (too large or too small).
** This applies to scalar values that must be within a certain range
** which might be configured at runtime.
*/
#define SM_E_RANGE (SM_ERR_BASE + 3)
/*
** Too big: an input parameter is too large, e.g., a string is too long.
** This applies to non-scalar values (as opposed to SM_E_RANGE) which
** must be within a certain range that is known a-priori.
*/
#define SM_E_2BIG (SM_ERR_BASE + 4)
/*
** Object (e.g., cache, array, hash table) is "full": no entries can be added;
*/
#define SM_E_FULL (SM_ERR_BASE + 5)
/*
** Operation would cause overflow of some variable, e.g., integer overflow.
** This applies to scalar values (SC)
*/
#define SM_E_OVFLW_SC (SM_ERR_BASE + 6)
/*
** Operation would cause overflow of some buffer.
** This applies to non-scalar values (NS)
*/
#define SM_E_OVFLW_NS (SM_ERR_BASE + 7)
#define SM_E_NOTFOUND (SM_ERR_BASE + 8) /* object not found */
/* startup failed (need more detail!) */
#define SM_E_STARTFAIL (SM_ERR_BASE + 9)
#define SM_E_SYNTAX (SM_ERR_BASE + 10)
#define SM_E_USAGE (SM_ERR_BASE + 11)
/* do not start the system; e.g., option like -? has been used */
#define SM_E_DONTSTART (SM_ERR_BASE + 12)
/*
** Version (compile/run time) mismatch; this applies to
** libraries as well as data (e.g., persistent databases).
*/
#define SM_E_VER_MIX (SM_ERR_BASE + 13)
#define SM_E_NO_AR (SM_ERR_BASE + 14) /* no AR available */
#define SM_E_NO_DA (SM_ERR_BASE + 15) /* no DA available */
#define SM_E_NO_DA_FREE (SM_ERR_BASE + 16) /* no DA free */
/* protocol version mismatch */
#define SM_E_PR_V_MISM (SM_ERR_BASE + 17)
/* protocol error, e.g., unexpected RT or wrong length */
#define SM_E_PR_ERR (SM_ERR_BASE + 18)
/* RCB too long or length doesn't match data (protocol error) */
#define SM_E_RCB2LONG (SM_ERR_BASE + 19)
/* especially for map lookups */
#define SM_E_TEMPMAP (SM_ERR_BASE + 20) /* temporary map lookup failure */
#define SM_E_PERMMAP (SM_ERR_BASE + 21) /* permanent map lookup failure */
#define SM_E_CLOSEDMAP (SM_ERR_BASE + 22) /* map closed (why?) */
#define SM_E_NOMAP (SM_ERR_BASE + 23) /* map is NULL */
#define SM_E_NOTIMPL (SM_ERR_BASE + 24) /* required function is NULL */
/* others? */
/* MX list is empty after removal of local addresses */
#define SM_E_MXEMPTY (SM_ERR_BASE + 25)
/* talking to myself */
#define SM_E_TTMYSELF (SM_ERR_BASE + 26)
/* alias expansion in AR failed */
#define SM_E_ALIASEXP (SM_ERR_BASE + 27)
/* aliases nested too deep */
#define SM_E_ALIAS_REC (SM_ERR_BASE + 28)
/* DNS: answer came from different IP address */
#define SM_E_IP_MISM (SM_ERR_BASE + 29)
#define SM_E_NOSIG (SM_ERR_BASE + 30) /* BATV: no signature */
#define SM_E_EXPIRED (SM_ERR_BASE + 31) /* expired */
#define SM_E_RSR_PRB (SM_ERR_BASE + 32) /* resource problem */
#define SM_E_ILL_PIPE (SM_ERR_BASE + 33) /* invalid use of PIPELINING */
#define SM_E_RD (SM_ERR_BASE + 34) /* read error */
#define SM_E_EOF (SM_ERR_BASE + 35) /* read error: EOF */
#define SM_E_WR (SM_ERR_BASE + 36) /* write error */
#define SM_E_BARE_NL (SM_ERR_BASE + 37) /* bare NL '\n' in input */
/* connection to other module has been closed (EOF) */
#define SM_E_CONN_CLSD (SM_ERR_BASE + 38)
/* communication context id mismatch (see smtps/s2q.c) */
#define SM_E_WRONG_ID (SM_ERR_BASE + 39)
#define SM_SSL_ERROR_SYSCALL (SM_ERR_BASE + 40)
#define SM_SSL_ERROR_SSL (SM_ERR_BASE + 41)
#define SM_SSL_ERROR_GENERIC (SM_ERR_BASE + 42)
#define SM_E_UNAVAIL (SM_ERR_BASE + 43)
#define SM_E_LASTCODE SM_E_UNAVAIL
/* check for consistency! */
#if DNS_ERR_BASE <= SM_E_LASTCODE
ERROR: fix error numbers: _DNS_ERR_BASE <= _SM_E_LASTCODE
#endif
#define E_CONFBASE (SM_ERR_BASE + 45) /* base for sm-conf errors */
/* check for consistency! */
#if E_CONFBASE <= SM_E_LASTCODE
ERROR: fix error numbers: _E_CONFBASE <= _SM_E_LASTCODE
#endif
/* SM_CONF_ERR values */
#define SM_C_E_NEWLINE_IN_STRING (E_CONFBASE + 1)
#define SM_C_E_EOF_IN_STRING (E_CONFBASE + 2)
#define SM_C_E_BAD_CHAR (E_CONFBASE + 3)
#define SM_C_E_NO_MEMORY (E_CONFBASE + 4)
#define SM_C_E_HEX_EXPECTED (E_CONFBASE + 5)
#define SM_C_E_CHAR_OVERFLOW (E_CONFBASE + 6)
#define SM_C_E_INVALID (E_CONFBASE + 7)
#define SM_C_E_READ (E_CONFBASE + 8)
#define SM_C_E_READ_OPEN (E_CONFBASE + 9)
#define SM_C_E_READ_CLOSE (E_CONFBASE + 10)
#define SM_C_E_EOF (E_CONFBASE + 11)
#define SM_C_E_SYNTAX (E_CONFBASE + 12)
#define SM_C_E_NOT_FOUND (E_CONFBASE + 13)
#define SM_C_E_ALREADY (E_CONFBASE + 14)
#define SM_C_E_TYPE (E_CONFBASE + 15)
#define SM_C_E_NUL_IN_STRING (E_CONFBASE + 16)
#define SM_C_E_TOO_MANY (E_CONFBASE + 17)
/* check for consistency! use last SM_C_E_code here! */
#if DNS_ERR_BASE <= SM_C_E_TOO_MANY
ERROR: fix error numbers: _DNS_ERR_BASE <= _SM_C_E_TOO_MANY
#endif
#if 0
#define E_LDAPBASE (E_PSEUDOBASE + 70) /* base for LDAP errors */
#endif
/*
** Modules
** How fine grained should this be? Just on the library level?
** Down to function level? In that case the module field needs to be larger.
** Should the be somehow related to the logging context/modules?
** For example, the DNS library has its own error codes (see above, starting
** at DNS_ERR_BASE). Having also a DNS error module seems like overkill, but
** the DNS module can also return "generic" errors, e.g., ENOMEM.
** Note: any change here must be reflected in libmta/smerr2txt.c, e_modules
*/
#define SM_EM_NONE 0
#define SM_EM_AQ 1
#define SM_EM_IQDB 2
#define SM_EM_IBDB 3
#define SM_EM_EDB 4
#define SM_EM_CDB 5
#define SM_EM_DA 6
#define SM_EM_OCC 7
#define SM_EM_DNS 8
#define SM_EM_SMTPC 9
#define SM_EM_SMTPS 10
#define SM_EM_MAPS 11
#define SM_EM_MAP 12
#define SM_EM_BDB 13 /* Berkeley DB related */
/*
** state threads: sm I/O layer (not really returned to application because
** I/O errors are "hidden" and just indicated with a flag in sm I/O)
*/
#define SM_EM_STTHRIO 14
/* state threads (not yet used) */
#define SM_EM_STTHR 15
#define SM_EM_EVTHR 16
#define SM_EM_RECCOM 17
#define SM_EM_HT 18 /* hash table */
#define SM_EM_RSC 19 /* Restricted Size Cache */
#define SM_EM_STR 20 /* str */
#define SM_EM_RCB 21 /* RCB */
#define SM_EM_TLS 22 /* TLS library */
#define SM_EM_SASL 23 /* SASL library */
#define SM_EM_NET 24 /* network related */
#define SM_EM_IO 25 /* sm I/O related */
#define SM_EM_LOG 26 /* log related */
#define SM_EM_ADDR 27 /* RFC 2821 address parsing */
#define SM_EM_IP 28 /* IP address parsing */
/* inside QMGR */
#define SM_EM_Q_Q2AR 32 /* QMGR -> AR */
#define SM_EM_Q_AR2Q 33 /* AR -> QMGR */
#define SM_EM_Q_Q2SS 34 /* QMGR -> SMTPS */
#define SM_EM_Q_SS2Q 35 /* SMTPS -> QMGR */
#define SM_EM_Q_Q2SC 36 /* QMGR -> SMTPC */
#define SM_EM_Q_SC2Q 37 /* SMTPC -> QMGR */
#define SM_EM_Q_RDIBDB 38 /* read IBDB */
#define SM_EM_Q_IQDB 39 /* IQDB */
#define SM_EM_Q_IBDB 40 /* IBDB */
#define SM_EM_Q_EDBC 41 /* EDB cache */
#define SM_EM_Q_DSN 42 /* bounce handling */
#define SM_EM_Q_START 43 /* QMGR startup */
#define SM_EM_Q_CTL2Q 44 /* CONTROL -> QMGR */
#define SM_EM_Q_CONF 45 /* QMGR configuration */
#define SM_EM_Q_CLEAN 46 /* QMGR cleanup functions */
#define SM_EM_Q_SCHED 47 /* QMGR scheduler */
#define SM_EM_Q 48 /* other QMGR functions */
/* inside SMAR */
#define SM_EM_AR_Q2AR 60 /* QMGR -> AR */
#define SM_EM_AR_AR2Q 61 /* AR -> QMGR */
#define SM_EM_AR_DNSW 62 /* DNS Write */
#define SM_EM_AR_DNSR 63 /* DNS Read */
#define SM_EM_AR_DNSD 63 /* DNS Decode */
#define SM_EM_AR_WAIT 64 /* internal wait for async function */
#define SM_EM_AR 65 /* other AR functions */
#define SM_EM_CONF 66 /* sm-conf */
#define SM_EM_PMILTER 67 /* libpmilter */
#define SM_EM_THR 68 /* threads */
#define SM_EM_BATV 69 /* BATV */
#define SM_EM_UTIL 127 /* utility programs */
/* maximum: 127 */
#if 0
#define SM_EM_x 2
#endif
#define SM_CNF_E_NEWLINE_IN_STRING sm_error_perm(SM_EM_CONF, SM_C_E_NEWLINE_IN_STRING)
#define SM_CNF_E_EOF_IN_STRING sm_error_perm(SM_EM_CONF, SM_C_E_EOF_IN_STRING)
#define SM_CNF_E_BAD_CHAR sm_error_perm(SM_EM_CONF, SM_C_E_BAD_CHAR)
#define SM_CNF_E_NO_MEMORY sm_error_temp(SM_EM_CONF, SM_C_E_NO_MEMORY)
#define SM_CNF_E_HEX_EXPECTED sm_error_perm(SM_EM_CONF, SM_C_E_HEX_EXPECTED)
#define SM_CNF_E_CHAR_OVERFLOW sm_error_perm(SM_EM_CONF, SM_C_E_CHAR_OVERFLOW)
#define SM_CNF_E_INVALID sm_error_perm(SM_EM_CONF, SM_C_E_INVALID)
#define SM_CNF_E_READ sm_error_perm(SM_EM_CONF, SM_C_E_READ)
#define SM_CNF_E_READ_OPEN sm_error_perm(SM_EM_CONF, SM_C_E_READ_OPEN)
#define SM_CNF_E_READ_CLOSE sm_error_perm(SM_EM_CONF, SM_C_E_READ_CLOSE)
#define SM_CNF_E_EOF sm_error_perm(SM_EM_CONF, SM_C_E_EOF)
#define SM_CNF_E_SYNTAX sm_error_perm(SM_EM_CONF, SM_C_E_SYNTAX)
#define SM_CNF_E_NOT_FOUND sm_error_perm(SM_EM_CONF, SM_C_E_NOT_FOUND)
#define SM_CNF_E_ALREADY sm_error_perm(SM_EM_CONF, SM_C_E_ALREADY)
#define SM_CNF_E_TYPE sm_error_perm(SM_EM_CONF, SM_C_E_TYPE)
#define SM_CNF_E_NUL_IN_STRING sm_error_perm(SM_EM_CONF, SM_C_E_NUL_IN_STRING)
#define SM_CNF_E_TOO_MANY sm_error_perm(SM_EM_CONF, SM_C_E_TOO_MANY)
#define SM_ETXT_UNKNOWN "Unknown"
char *smerr2txt(sm_error_T _err);
char *smmod2txt(sm_error_T _err);
sm_ret_T errno2err(int _err, int _module);
int smerr2txt_r(sm_error_T _err, char *_strerrbuf, size_t _buflen);
#if defined(ELAST)
# define sm_sys_nerr (ELAST + 1)
#elif HAVE_SYS_NERR
# define sm_sys_nerr sys_nerr
#else
# define sm_sys_nerr SM_ERR_BASE
#endif
#endif /* SM_ERROR_H */
syntax highlighted by Code2HTML, v. 0.9.1