~ubuntu-branches/ubuntu/utopic/libesmtp/utopic

« back to all changes in this revision

Viewing changes to errors.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy T. Bouse
  • Date: 2002-03-06 08:37:48 UTC
  • Revision ID: james.westby@ubuntu.com-20020306083748-ihmt32mddsslvg5i
Tags: upstream-0.8.11
ImportĀ upstreamĀ versionĀ 0.8.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  This file is part of libESMTP, a library for submission of RFC 2822
 
3
 *  formatted electronic mail messages using the SMTP protocol described
 
4
 *  in RFC 2821.
 
5
 *
 
6
 *  Copyright (C) 2001,2002  Brian Stafford  <brian@stafford.uklinux.net>
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include <config.h>
 
25
#endif
 
26
 
 
27
#define _SVID_SOURCE    1       /* Need this to get strerror_r() */
 
28
 
 
29
#include <missing.h> /* declarations for missing library functions */
 
30
 
 
31
#include <stdio.h>
 
32
#include <errno.h>
 
33
#include <string.h>
 
34
#include <stdlib.h>
 
35
#if HAVE_LWRES_NETDB_H
 
36
# include <lwres/netdb.h>
 
37
#elif !HAVE_GETADDRINFO
 
38
# include "getaddrinfo.h"
 
39
#else
 
40
# include <netdb.h>
 
41
#endif
 
42
#include "libesmtp-private.h"
 
43
#include "api.h"
 
44
 
 
45
struct errno_vars
 
46
  {
 
47
    int error;
 
48
    int herror;
 
49
  };
 
50
 
 
51
static inline void
 
52
set_error_internal (struct errno_vars *err, int code)
 
53
{
 
54
  err->error = code;
 
55
  err->herror = 0;
 
56
}
 
57
 
 
58
static inline void
 
59
set_herror_internal (struct errno_vars *err, int code)
 
60
{
 
61
  err->herror = code;
 
62
  if (err->herror == EAI_SYSTEM)
 
63
    err->error = errno;
 
64
}
 
65
 
 
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. */
 
70
 
 
71
static int
 
72
eai_to_libesmtp (int code)
 
73
{
 
74
#define MAP(code)       case code: return SMTP_ERR_##code;
 
75
  switch (code)
 
76
    {
 
77
    MAP(EAI_AGAIN)
 
78
    MAP(EAI_FAIL)
 
79
    MAP(EAI_MEMORY)
 
80
    MAP(EAI_ADDRFAMILY)
 
81
    MAP(EAI_NODATA)
 
82
    MAP(EAI_FAMILY)
 
83
    MAP(EAI_BADFLAGS)
 
84
    MAP(EAI_NONAME)
 
85
    MAP(EAI_SERVICE)
 
86
    MAP(EAI_SOCKTYPE)
 
87
    default: return SMTP_ERR_INVAL;
 
88
    }
 
89
#undef MAP
 
90
}
 
91
 
 
92
static int
 
93
libesmtp_to_eai (int code)
 
94
{
 
95
#define MAP(code)       case SMTP_ERR_##code: return code;
 
96
  switch (code)
 
97
    {
 
98
    MAP(EAI_AGAIN)
 
99
    MAP(EAI_FAIL)
 
100
    MAP(EAI_MEMORY)
 
101
    MAP(EAI_ADDRFAMILY)
 
102
    MAP(EAI_NODATA)
 
103
    MAP(EAI_FAMILY)
 
104
    MAP(EAI_BADFLAGS)
 
105
    MAP(EAI_NONAME)
 
106
    MAP(EAI_SERVICE)
 
107
    MAP(EAI_SOCKTYPE)
 
108
    default: return 0;
 
109
    }
 
110
#undef MAP
 
111
}
 
112
 
 
113
static inline int
 
114
get_error_internal (struct errno_vars *err)
 
115
{
 
116
  if (err->herror == 0 || err->herror == EAI_SYSTEM)
 
117
    return err->error;
 
118
  return eai_to_libesmtp (err->herror);
 
119
}
 
120
 
 
121
#ifndef USE_PTHREADS
 
122
 
 
123
static struct errno_vars libesmtp_errno;
 
124
 
 
125
void
 
126
set_error (int code)
 
127
{
 
128
  set_error_internal (&libesmtp_errno, code);
 
129
}
 
130
 
 
131
void
 
132
set_herror (int code)
 
133
{
 
134
  set_herror_internal (&libesmtp_errno, code);
 
135
}
 
136
 
 
137
int
 
138
smtp_errno (void)
 
139
{
 
140
  return get_error_internal (&libesmtp_errno);
 
141
}
 
142
 
 
143
#else
 
144
 
 
145
#include <pthread.h>
 
146
 
 
147
static pthread_key_t libesmtp_errno;
 
148
static pthread_once_t libesmtp_errno_once = PTHREAD_ONCE_INIT;
 
149
 
 
150
static void
 
151
errno_destroy (void *value)
 
152
{
 
153
  if (value != NULL)
 
154
    free (value);
 
155
}
 
156
 
 
157
static void
 
158
errno_alloc (void)
 
159
{
 
160
  pthread_key_create (&libesmtp_errno, errno_destroy);
 
161
}
 
162
 
 
163
static struct errno_vars *
 
164
errno_ptr (void)
 
165
{
 
166
  struct errno_vars *value;
 
167
 
 
168
  pthread_once (&libesmtp_errno_once, errno_alloc);
 
169
  value = pthread_getspecific (libesmtp_errno);
 
170
  if (value == NULL)
 
171
    {
 
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);
 
176
    }
 
177
  return value;
 
178
}
 
179
 
 
180
void
 
181
set_error (int code)
 
182
{
 
183
  struct errno_vars *value = errno_ptr ();
 
184
 
 
185
  if (value != NULL)
 
186
    set_error_internal (value, code);
 
187
}
 
188
 
 
189
void
 
190
set_herror (int code)
 
191
{
 
192
  struct errno_vars *value = errno_ptr ();
 
193
 
 
194
  if (value != NULL)
 
195
    set_herror_internal (value, code);
 
196
}
 
197
 
 
198
int
 
199
smtp_errno (void)
 
200
{
 
201
  struct errno_vars *value = errno_ptr ();
 
202
 
 
203
  return (value != NULL) ? get_error_internal (value) : ENOMEM;
 
204
}
 
205
 
 
206
#endif
 
207
 
 
208
/* store the value of errno in libESMTP's error variable. */
 
209
void
 
210
set_errno (int code)
 
211
{
 
212
  set_error (-code);
 
213
}
 
214
 
 
215
static const char *libesmtp_errors[] =
 
216
  {
 
217
    "No Error",
 
218
    "",
 
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 */
 
229
    NULL,                                               /* EAI_FAIL */
 
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 */
 
238
  };
 
239
 
 
240
char *
 
241
smtp_strerror (int error, char buf[], size_t buflen)
 
242
{
 
243
  const char *text;
 
244
  int len;
 
245
  int map;
 
246
 
 
247
  SMTPAPI_CHECK_ARGS (buf != NULL && buflen > 0, NULL);
 
248
 
 
249
  if (error < 0)
 
250
#if HAVE_WORKING_STRERROR_R
 
251
    return strerror_r (-error, buf, buflen);
 
252
#elif HAVE_STRERROR_R
 
253
    {
 
254
      /* Assume the broken OSF1 strerror_r which returns an int. */
 
255
      int n = strerror_r (-error, buf, buflen);
 
256
 
 
257
      return n >= 0 ? buf : NULL;
 
258
    }
 
259
#else
 
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);
 
267
#endif
 
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];
 
272
  else
 
273
    text = (const char *) 0;
 
274
 
 
275
  if (text == (const char *) 0)
 
276
    len = snprintf (buf, buflen, "Error %d", error);
 
277
  else
 
278
    {
 
279
      len = strlen (text);
 
280
      if (len > (int) buflen - 1)
 
281
        len = buflen - 1;
 
282
      memcpy (buf, text, len);
 
283
      buf[len] = '\0';
 
284
    }
 
285
  return len >= 0 ? buf : NULL;
 
286
}