Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
protected.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * protected.c - thread-safe versions of standard library functions
59  *
60  * Lars Wirzenius
61  */
62 
63 #include <locale.h>
64 #include <errno.h>
65 
66 #include "gwlib.h"
67 
68 
69 /*
70  * Undefine the accident protectors.
71  */
72 #undef localtime
73 #undef gmtime
74 #undef rand
75 #undef gethostbyname
76 #undef mktime
77 #undef strftime
78 
79 
80 enum {
85 };
86 
87 
89 
90 
91 static void lock(int which)
92 {
93  mutex_lock(&locks[which]);
94 }
95 
96 
97 static void unlock(int which)
98 {
99  mutex_unlock(&locks[which]);
100 }
101 
102 
104 {
105  int i;
106 
107  for (i = 0; i < NUM_LOCKS; ++i)
108  mutex_init_static(&locks[i]);
109 }
110 
111 
113 {
114  int i;
115 
116  for (i = 0; i < NUM_LOCKS; ++i)
117  mutex_destroy(&locks[i]);
118 }
119 
120 
121 struct tm gw_localtime(time_t t)
122 {
123  struct tm tm;
124 
125 #ifndef HAVE_LOCALTIME_R
126  lock(GWTIME);
127  tm = *localtime(&t);
128  unlock(GWTIME);
129 #else
130  localtime_r(&t, &tm);
131 #endif
132 
133  return tm;
134 }
135 
136 
137 struct tm gw_gmtime(time_t t)
138 {
139  struct tm tm;
140 
141 #ifndef HAVE_GMTIME_R
142  lock(GWTIME);
143  tm = *gmtime(&t);
144  unlock(GWTIME);
145 #else
146  gmtime_r(&t, &tm);
147 #endif
148 
149  return tm;
150 }
151 
152 
153 time_t gw_mktime(struct tm *tm)
154 {
155  time_t t;
156  lock(GWTIME);
157  t = mktime(tm);
158  unlock(GWTIME);
159 
160  return t;
161 }
162 
163 
164 size_t gw_strftime(char *s, size_t max, const char *format, const struct tm *tm)
165 {
166  size_t ret;
167  lock(GWTIME);
168  ret = strftime(s, max, format, tm);
169  unlock(GWTIME);
170  return ret;
171 }
172 
173 
174 int gw_rand(void)
175 {
176  int ret;
177 
178  lock(RAND);
179  ret = rand();
180  unlock(RAND);
181  return ret;
182 }
183 
184 #if HAVE_FUNC_GETHOSTBYNAME_R_6
185 /* linux version */
186 int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
187 {
188  struct hostent *tmphp, hp;
189  int herr, res;
190  size_t bufflen;
191 
192  tmphp = NULL; /* for compiler please */
193 
194  bufflen = 1024;
195  *buff = (char*) gw_malloc(bufflen);
196  while ((res=gethostbyname_r(name, &hp,*buff, bufflen, &tmphp, &herr)) == ERANGE) {
197  /* enlarge the buffer */
198  bufflen *= 2;
199  *buff = (char*) gw_realloc(*buff, bufflen);
200  }
201 
202  if (res != 0 || tmphp == NULL) {
203  error(herr, "Error while gw_gethostbyname occurs.");
204  gw_free(*buff);
205  *buff = NULL;
206  res = -1;
207  }
208  else {
209  *ent = hp;
210  }
211 
212  return res;
213 }
214 #elif HAVE_FUNC_GETHOSTBYNAME_R_5
215 /* solaris */
216 int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
217 {
218  int herr = 0;
219  size_t bufflen = 1024;
220  int res = 0;
221  struct hostent *tmphp = NULL;
222 
223  *buff = gw_malloc(bufflen);
224  while ((tmphp = gethostbyname_r(name, ent, *buff, bufflen, &herr)) == NULL && (errno == ERANGE)) {
225  /* Enlarge the buffer. */
226  bufflen *= 2;
227  *buff = (char *) gw_realloc(*buff, bufflen);
228  }
229 
230  if (tmphp == NULL) {
231  error(herr, "Error while gw_gethostbyname occurs.");
232  gw_free(*buff);
233  *buff = NULL;
234  res = -1;
235  }
236 
237  return res;
238 }
239 /* not yet implemented, no machine for testing (alex) */
240 /* #elif HAVE_FUNC_GETHOSTBYNAME_R_3 */
241 #else
242 /*
243  * Hmm, we don't have a gethostbyname_r(), this is bad...
244  * Here we must perform a "deep-copy" of a hostent struct returned
245  * from gethostbyname.
246  * Note: Bellow code is based on parts from cURL.
247  */
248 int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
249 {
250  int len, i;
251  struct hostent *p;
252  /* Allocate enough memory to hold the full name information structs and
253  * everything. OSF1 is known to require at least 8872 bytes. The buffer
254  * required for storing all possible aliases and IP numbers is according to
255  * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes!
256  */
257  size_t bufflen = 9000;
258  char *bufptr, *str;
259 
261 
262  p = gethostbyname(name);
263  if (p == NULL) {
265  *buff = NULL;
266  return -1;
267  }
268 
269  *ent = *p;
270  /* alloc mem */
271  bufptr = *buff = gw_malloc(bufflen);
272  ent->h_name = bufptr;
273  /* copy h_name into buff */
274  len = strlen(p->h_name) + 1;
275  strncpy(bufptr, p->h_name, len);
276  bufptr += len;
277 
278  /* we align on even 64bit boundaries for safety */
279 #define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))
280 
281  /* This must be aligned properly to work on many CPU architectures! */
282  bufptr = MEMALIGN(bufptr);
283 
284  ent->h_aliases = (char**)bufptr;
285 
286  /* Figure out how many aliases there are */
287  for (i = 0; p->h_aliases[i] != NULL; ++i)
288  ;
289 
290  /* Reserve room for the array */
291  bufptr += (i + 1) * sizeof(char*);
292 
293  /* Clone all known aliases */
294  for(i = 0; (str = p->h_aliases[i]); i++) {
295  len = strlen(str) + 1;
296  strncpy(bufptr, str, len);
297  ent->h_aliases[i] = bufptr;
298  bufptr += len;
299  }
300  /* Terminate the alias list with a NULL */
301  ent->h_aliases[i] = NULL;
302 
303  ent->h_addrtype = p->h_addrtype;
304  ent->h_length = p->h_length;
305 
306  /* align it for (at least) 32bit accesses */
307  bufptr = MEMALIGN(bufptr);
308 
309  ent->h_addr_list = (char**)bufptr;
310 
311  /* Figure out how many addresses there are */
312  for (i = 0; p->h_addr_list[i] != NULL; ++i)
313  ;
314 
315  /* Reserve room for the array */
316  bufptr += (i + 1) * sizeof(char*);
317 
318  i = 0;
319  len = p->h_length;
320  str = p->h_addr_list[i];
321  while (str != NULL) {
322  memcpy(bufptr, str, len);
323  ent->h_addr_list[i] = bufptr;
324  bufptr += len;
325  str = p->h_addr_list[++i];
326  }
327  ent->h_addr_list[i] = NULL;
328 
329 #undef MEMALIGN
330 
332 
333  return 0;
334 }
335 #endif
336 
void gwlib_protected_shutdown(void)
Definition: protected.c:112
void error(int err, const char *fmt,...)
Definition: log.c:612
#define MEMALIGN(x)
#define localtime(t)
Definition: protected.h:88
#define mutex_unlock(m)
Definition: thread.h:136
struct tm gw_gmtime(time_t t)
Definition: protected.c:137
#define gmtime(t)
Definition: protected.h:91
static void lock(int which)
Definition: protected.c:91
size_t gw_strftime(char *s, size_t max, const char *format, const struct tm *tm)
Definition: protected.c:164
static void unlock(int which)
Definition: protected.c:97
#define mktime(t)
Definition: protected.h:94
time_t gw_mktime(struct tm *tm)
Definition: protected.c:153
static Mutex locks[NUM_LOCKS]
Definition: protected.c:88
void gwlib_protected_init(void)
Definition: protected.c:103
char * name
Definition: smsc_cimd2.c:212
#define mutex_init_static(mutex)
Definition: thread.h:115
void mutex_destroy(Mutex *mutex)
Definition: thread.c:97
#define gethostbyname(a, b, c)
Definition: protected.h:103
int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
Definition: protected.c:248
struct tm gw_localtime(time_t t)
Definition: protected.c:121
#define rand()
Definition: protected.h:100
Definition: thread.h:76
#define mutex_lock(m)
Definition: thread.h:130
int gw_rand(void)
Definition: protected.c:174
Definition: protected.c:81
#define strftime(a, b, c, d)
Definition: protected.h:97
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.