2
* This file is part of libESMTP, a library for submission of RFC 2822
3
* formatted electronic mail messages using the SMTP protocol described
6
* Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#define _SVID_SOURCE 1 /* Need this to get strerror_r() */
29
#include <missing.h> /* declarations for missing library functions */
35
#if HAVE_LWRES_NETDB_H
36
# include <lwres/netdb.h>
37
#elif !HAVE_GETADDRINFO
38
# include "getaddrinfo.h"
42
#include "libesmtp-private.h"
52
set_error_internal (struct errno_vars *err, int code)
59
set_herror_internal (struct errno_vars *err, int code)
62
if (err->herror == EAI_SYSTEM)
66
/* Map error codes from getaddrinfo to/from those used by libESMTP. RFC
67
2553 is silent on whether these values are +ve, -ve, how they sort or
68
even whether they are contiguous so the mapping is done with a
69
switch. NB EAI_SYSTEM is *not* mapped. */
72
eai_to_libesmtp (int code)
74
#define MAP(code) case code: return SMTP_ERR_##code;
87
default: return SMTP_ERR_INVAL;
93
libesmtp_to_eai (int code)
95
#define MAP(code) case SMTP_ERR_##code: return code;
114
get_error_internal (struct errno_vars *err)
116
if (err->herror == 0 || err->herror == EAI_SYSTEM)
118
return eai_to_libesmtp (err->herror);
123
static struct errno_vars libesmtp_errno;
128
set_error_internal (&libesmtp_errno, code);
132
set_herror (int code)
134
set_herror_internal (&libesmtp_errno, code);
140
return get_error_internal (&libesmtp_errno);
147
static pthread_key_t libesmtp_errno;
148
static pthread_once_t libesmtp_errno_once = PTHREAD_ONCE_INIT;
151
errno_destroy (void *value)
160
pthread_key_create (&libesmtp_errno, errno_destroy);
163
static struct errno_vars *
166
struct errno_vars *value;
168
pthread_once (&libesmtp_errno_once, errno_alloc);
169
value = pthread_getspecific (libesmtp_errno);
172
value = malloc (sizeof (struct errno_vars));
173
/* FIXME: check for NULL malloc */
174
memset (value, 0, sizeof (struct errno_vars));
175
pthread_setspecific (libesmtp_errno, value);
183
struct errno_vars *value = errno_ptr ();
186
set_error_internal (value, code);
190
set_herror (int code)
192
struct errno_vars *value = errno_ptr ();
195
set_herror_internal (value, code);
201
struct errno_vars *value = errno_ptr ();
203
return (value != NULL) ? get_error_internal (value) : ENOMEM;
208
/* store the value of errno in libESMTP's error variable. */
215
static const char *libesmtp_errors[] =
219
"Nothing to do", /* NOTHING_TO_DO */
220
"SMTP server dropped connection", /* DROPPED_CONNECTION */
221
"Invalid SMTP syntax in server response", /* INVALID_RESPONSE_SYNTAX */
222
"SMTP Status code mismatch on continuation line", /* STATUS_MISMATCH */
223
"Invalid SMTP status code in server response", /* INVALID_RESPONSE_STATUS */
224
"Invalid API function argument", /* INVAL */
225
"Requested SMTP extension not available", /* EXTENSION_NOT_AVAILABLE */
226
/* Next 10 codes handled by gai_strerror() */
227
NULL, /* EAI_ADDRFAMILY */
228
NULL, /* EAI_NODATA */
230
NULL, /* EAI_AGAIN */
231
NULL, /* EAI_MEMORY */
232
NULL, /* EAI_FAMILY */
233
NULL, /* EAI_BADFLAGS */
234
NULL, /* EAI_NONAME */
235
NULL, /* EAI_SERVICE */
236
NULL, /* EAI_SOCKTYPE */
237
"Unterminated server response", /* UNTERMINATED_RESPONSE */
241
smtp_strerror (int error, char buf[], size_t buflen)
247
SMTPAPI_CHECK_ARGS (buf != NULL && buflen > 0, NULL);
250
#if HAVE_WORKING_STRERROR_R
251
return strerror_r (-error, buf, buflen);
252
#elif HAVE_STRERROR_R
254
/* Assume the broken OSF1 strerror_r which returns an int. */
255
int n = strerror_r (-error, buf, buflen);
257
return n >= 0 ? buf : NULL;
260
/* Could end up here when threading is enabled but a working
261
strerror_r() is not found. There will be a critical section
262
of code until the returned string is copied to the supplied
263
buffer. This could be solved using a mutex but its hardly
264
worth it since even if libESMTP is protected against itself
265
the application could still call strerror anyway. */
266
text = strerror (-error);
268
else if ((map = libesmtp_to_eai (error)) != 0)
269
text = gai_strerror (map);
270
else if (error < (int) (sizeof libesmtp_errors / sizeof libesmtp_errors[0]))
271
text = libesmtp_errors[error];
273
text = (const char *) 0;
275
if (text == (const char *) 0)
276
len = snprintf (buf, buflen, "Error %d", error);
280
if (len > (int) buflen - 1)
282
memcpy (buf, text, len);
285
return len >= 0 ? buf : NULL;