Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

protected.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * protected.c - thread-safe versions of standard library functions
00059  *
00060  * Lars Wirzenius
00061  */
00062 
00063 #include <locale.h>
00064 #include <errno.h>
00065 
00066 #include "gwlib.h"
00067 
00068 
00069 /*
00070  * Undefine the accident protectors.
00071  */
00072 #undef localtime
00073 #undef gmtime
00074 #undef rand
00075 #undef gethostbyname
00076 #undef mktime
00077 #undef strftime
00078 
00079 
00080 enum {
00081     RAND,
00082     GETHOSTBYNAME,
00083     GWTIME,
00084     NUM_LOCKS
00085 };
00086 
00087 
00088 static Mutex locks[NUM_LOCKS];
00089 
00090 
00091 static void lock(int which)
00092 {
00093     mutex_lock(&locks[which]);
00094 }
00095 
00096 
00097 static void unlock(int which)
00098 {
00099     mutex_unlock(&locks[which]);
00100 }
00101 
00102 
00103 void gwlib_protected_init(void)
00104 {
00105     int i;
00106 
00107     for (i = 0; i < NUM_LOCKS; ++i)
00108         mutex_init_static(&locks[i]);
00109 }
00110 
00111 
00112 void gwlib_protected_shutdown(void)
00113 {
00114     int i;
00115 
00116     for (i = 0; i < NUM_LOCKS; ++i)
00117         mutex_destroy(&locks[i]);
00118 }
00119 
00120 
00121 struct tm gw_localtime(time_t t)
00122 {
00123     struct tm tm;
00124 
00125 #ifndef HAVE_LOCALTIME_R
00126     lock(GWTIME);
00127     tm = *localtime(&t);
00128     unlock(GWTIME);
00129 #else
00130     localtime_r(&t, &tm);
00131 #endif
00132 
00133     return tm;
00134 }
00135 
00136 
00137 struct tm gw_gmtime(time_t t)
00138 {
00139     struct tm tm;
00140 
00141 #ifndef HAVE_GMTIME_R
00142     lock(GWTIME);
00143     tm = *gmtime(&t);
00144     unlock(GWTIME);
00145 #else
00146     gmtime_r(&t, &tm);
00147 #endif
00148 
00149     return tm;
00150 }
00151 
00152 
00153 time_t gw_mktime(struct tm *tm)
00154 {
00155     time_t t;
00156     lock(GWTIME);
00157     t = mktime(tm);
00158     unlock(GWTIME);
00159 
00160     return t;
00161 }
00162 
00163 
00164 size_t gw_strftime(char *s, size_t max, const char *format, const struct tm *tm)
00165 {
00166     size_t ret;
00167     lock(GWTIME);
00168     ret = strftime(s, max, format, tm);
00169     unlock(GWTIME);
00170     return ret;
00171 }
00172 
00173 
00174 int gw_rand(void)
00175 {
00176     int ret;
00177 
00178     lock(RAND);
00179     ret = rand();
00180     unlock(RAND);
00181     return ret;
00182 }
00183 
00184 #if HAVE_FUNC_GETHOSTBYNAME_R_6
00185 /* linux version */
00186 int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
00187 {
00188     struct hostent *tmphp, hp;
00189     int herr, res;
00190     size_t bufflen;
00191 
00192     tmphp = NULL; /* for compiler please */
00193 
00194     bufflen = 1024;
00195     *buff = (char*) gw_malloc(bufflen);
00196     while ((res=gethostbyname_r(name, &hp,*buff, bufflen, &tmphp, &herr)) == ERANGE) {
00197         /* enlarge the buffer */
00198     bufflen *= 2;
00199     *buff = (char*) gw_realloc(*buff, bufflen);
00200     }
00201 
00202     if (res != 0 || tmphp == NULL) {
00203         error(herr, "Error while gw_gethostbyname occurs.");
00204         gw_free(*buff);
00205         *buff = NULL;
00206         res = -1;
00207     }
00208     else {
00209         *ent = hp;
00210     }
00211 
00212     return res;
00213 }
00214 #elif HAVE_FUNC_GETHOSTBYNAME_R_5
00215 /* solaris */
00216 int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
00217 {
00218     int herr = 0;
00219     size_t bufflen = 1024;
00220     int res = 0;
00221     struct hostent *tmphp = NULL;
00222 
00223     *buff = gw_malloc(bufflen);
00224     while ((tmphp = gethostbyname_r(name, ent, *buff, bufflen, &herr)) == NULL && (errno == ERANGE)) {
00225         /* Enlarge the buffer. */
00226         bufflen *= 2;
00227         *buff = (char *) gw_realloc(*buff, bufflen);
00228     }
00229 
00230     if (tmphp == NULL) {
00231         error(herr, "Error while gw_gethostbyname occurs.");
00232         gw_free(*buff);
00233         *buff = NULL;
00234         res = -1;
00235     }
00236 
00237     return res;
00238 }
00239 /* not yet implemented, no machine for testing (alex) */
00240 /* #elif HAVE_FUNC_GETHOSTBYNAME_R_3 */
00241 #else
00242 /*
00243  * Hmm, we don't have a gethostbyname_r(), this is bad...
00244  * Here we must perform a "deep-copy" of a hostent struct returned
00245  * from gethostbyname.
00246  * Note: Bellow code is based on parts from cURL.
00247  */
00248 int gw_gethostbyname(struct hostent *ent, const char *name, char **buff)
00249 {
00250     int len, i;
00251     struct hostent *p;
00252     /* Allocate enough memory to hold the full name information structs and
00253      * everything. OSF1 is known to require at least 8872 bytes. The buffer
00254      * required for storing all possible aliases and IP numbers is according to
00255      * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes!
00256      */
00257     size_t bufflen = 9000;
00258     char *bufptr, *str;
00259 
00260     lock(GETHOSTBYNAME);
00261 
00262     p = gethostbyname(name);
00263     if (p == NULL) {
00264         unlock(GETHOSTBYNAME);
00265         *buff = NULL;
00266         return -1;
00267     }
00268 
00269     *ent = *p;
00270     /* alloc mem */
00271     bufptr = *buff = gw_malloc(bufflen);
00272     ent->h_name = bufptr;
00273     /* copy h_name into buff */
00274     len = strlen(p->h_name) + 1;
00275     strncpy(bufptr, p->h_name, len);
00276     bufptr += len;
00277 
00278   /* we align on even 64bit boundaries for safety */
00279 #define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))
00280 
00281     /* This must be aligned properly to work on many CPU architectures! */
00282     bufptr = MEMALIGN(bufptr);
00283 
00284     ent->h_aliases = (char**)bufptr;
00285 
00286     /* Figure out how many aliases there are */
00287     for (i = 0; p->h_aliases[i] != NULL; ++i)
00288         ;
00289 
00290     /* Reserve room for the array */
00291     bufptr += (i + 1) * sizeof(char*);
00292 
00293     /* Clone all known aliases */
00294     for(i = 0; (str = p->h_aliases[i]); i++) {
00295         len = strlen(str) + 1;
00296         strncpy(bufptr, str, len);
00297         ent->h_aliases[i] = bufptr;
00298         bufptr += len;
00299     }
00300     /* Terminate the alias list with a NULL */
00301     ent->h_aliases[i] = NULL;
00302 
00303     ent->h_addrtype = p->h_addrtype;
00304     ent->h_length = p->h_length;
00305 
00306     /* align it for (at least) 32bit accesses */
00307     bufptr = MEMALIGN(bufptr);
00308 
00309     ent->h_addr_list = (char**)bufptr;
00310 
00311     /* Figure out how many addresses there are */
00312     for (i = 0; p->h_addr_list[i] != NULL; ++i)
00313         ;
00314 
00315     /* Reserve room for the array */
00316     bufptr += (i + 1) * sizeof(char*);
00317 
00318     i = 0;
00319     len = p->h_length;
00320     str = p->h_addr_list[i];
00321     while (str != NULL) {
00322         memcpy(bufptr, str, len);
00323         ent->h_addr_list[i] = bufptr;
00324         bufptr += len;
00325         str = p->h_addr_list[++i];
00326     }
00327     ent->h_addr_list[i] = NULL;
00328 
00329 #undef MEMALIGN
00330 
00331     unlock(GETHOSTBYNAME);
00332 
00333     return 0;
00334 }
00335 #endif
00336 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.