os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixCompat.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixCompat.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,670 @@
     1.4 +/*
     1.5 + * tclUnixCompat.c
     1.6 + *
     1.7 + * Written by: Zoran Vasiljevic (vasiljevic@users.sourceforge.net).
     1.8 + *
     1.9 + * See the file "license.terms" for information on usage and redistribution
    1.10 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1.11 + *
    1.12 + * RCS: @(#) $Id: tclUnixCompat.c,v 1.1.2.10 2006/09/12 22:05:03 andreas_kupries Exp $
    1.13 + *
    1.14 + */
    1.15 +
    1.16 +#include "tclInt.h"
    1.17 +#include "tclPort.h"
    1.18 +#include <pwd.h>
    1.19 +#include <grp.h>
    1.20 +#include <errno.h>
    1.21 +#include <string.h>
    1.22 +
    1.23 +/*
    1.24 + * Used to pad structures at size'd boundaries
    1.25 + *
    1.26 + * This macro assumes that the pointer 'buffer' was created from an
    1.27 + * aligned pointer by adding the 'length'. If this 'length' was not a
    1.28 + * multiple of the 'size' the result is unaligned and PadBuffer
    1.29 + * corrects both the pointer, _and_ the 'length'. The latter means
    1.30 + * that future increments of 'buffer' by 'length' stay aligned.
    1.31 + */
    1.32 +
    1.33 +#define PadBuffer(buffer, length, size)             \
    1.34 +    if (((length) % (size))) {                      \
    1.35 +	(buffer) += ((size) - ((length) % (size))); \
    1.36 +	(length) += ((size) - ((length) % (size))); \
    1.37 +    }
    1.38 +
    1.39 +/*
    1.40 + * Per-thread private storage used to store values
    1.41 + * returned from MT-unsafe library calls.
    1.42 + */
    1.43 +
    1.44 +#ifdef TCL_THREADS
    1.45 +
    1.46 +typedef struct ThreadSpecificData {
    1.47 +
    1.48 +    struct passwd pwd;
    1.49 +    char pbuf[2048];
    1.50 +
    1.51 +    struct group grp;
    1.52 +    char gbuf[2048];
    1.53 +
    1.54 +#if !defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)
    1.55 +    struct hostent hent;
    1.56 +    char hbuf[2048];
    1.57 +#endif
    1.58 +
    1.59 +}  ThreadSpecificData;
    1.60 +
    1.61 +static Tcl_ThreadDataKey dataKey;
    1.62 +
    1.63 +#if ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
    1.64 +     (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
    1.65 +      !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
    1.66 +      !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
    1.67 +
    1.68 +/*
    1.69 + * Mutex to lock access to MT-unsafe calls. This is just to protect
    1.70 + * our own usage. It does not protect us from others calling the
    1.71 + * same functions without (or using some different) lock.
    1.72 + */
    1.73 +
    1.74 +static Tcl_Mutex compatLock;
    1.75 +
    1.76 +/*
    1.77 + *---------------------------------------------------------------------------
    1.78 + *
    1.79 + * CopyArray --
    1.80 + *
    1.81 + *      Copies array of NULL-terminated or fixed-length strings
    1.82 + *      to the private buffer, honouring the size of the buffer.
    1.83 + *
    1.84 + * Results:
    1.85 + *      Number of bytes copied on success or -1 on error (errno = ERANGE)
    1.86 + *
    1.87 + * Side effects:
    1.88 + *      None.
    1.89 + *
    1.90 + *---------------------------------------------------------------------------
    1.91 + */
    1.92 +
    1.93 +static int
    1.94 +CopyArray(char **src, int elsize, char *buf, int buflen)
    1.95 +{
    1.96 +    int i, j, len = 0;
    1.97 +    char *p, **new;
    1.98 +
    1.99 +    if (src == NULL) {
   1.100 +	return 0;
   1.101 +    }
   1.102 +    for (i = 0; src[i] != NULL; i++) {
   1.103 +	/* Empty loop to count howmany */
   1.104 +    }
   1.105 +    if ((sizeof(char *)*(i + 1)) >  buflen) {
   1.106 +	return -1;
   1.107 +    }
   1.108 +    len = (sizeof(char *)*(i + 1)); /* Leave place for the array */
   1.109 +    new = (char **)buf;
   1.110 +    p = buf + (sizeof(char *)*(i + 1));
   1.111 +    for (j = 0; j < i; j++) {
   1.112 +	if (elsize < 0) {
   1.113 +	    len += strlen(src[j]) + 1;
   1.114 +	} else {
   1.115 +	    len += elsize;
   1.116 +	}
   1.117 +	if (len > buflen) {
   1.118 +	    return -1;
   1.119 +	}
   1.120 +	if (elsize < 0) {
   1.121 +	    strcpy(p, src[j]);
   1.122 +	} else {
   1.123 +	    memcpy(p, src[j], elsize);
   1.124 +	}
   1.125 +	new[j] = p;
   1.126 +	p = buf + len;
   1.127 +    }
   1.128 +    new[j] = NULL;
   1.129 +
   1.130 +    return len;
   1.131 +}
   1.132 +
   1.133 +
   1.134 +/*
   1.135 + *---------------------------------------------------------------------------
   1.136 + *
   1.137 + * CopyString --
   1.138 + *
   1.139 + *      Copies a NULL-terminated string to the private buffer,
   1.140 + *      honouring the size of the buffer
   1.141 + *
   1.142 + * Results:
   1.143 + *      0 success or -1 on error (errno = ERANGE)
   1.144 + *
   1.145 + * Side effects:
   1.146 + *      None
   1.147 + *
   1.148 + *---------------------------------------------------------------------------
   1.149 + */
   1.150 +
   1.151 +
   1.152 +static int
   1.153 +CopyString(char *src, char *buf, int buflen)
   1.154 +{
   1.155 +    int len = 0;
   1.156 +
   1.157 +    if (src != NULL) {
   1.158 +	len += strlen(src) + 1;
   1.159 +	if (len > buflen) {
   1.160 +	    return -1;
   1.161 +	}
   1.162 +	strcpy(buf, src);
   1.163 +    }
   1.164 +
   1.165 +    return len;
   1.166 +}
   1.167 +#endif /* ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
   1.168 +	   (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
   1.169 +	    !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
   1.170 +	    !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
   1.171 +
   1.172 +#if (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
   1.173 +    (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))
   1.174 +
   1.175 +/*
   1.176 + *---------------------------------------------------------------------------
   1.177 + *
   1.178 + * CopyHostnent --
   1.179 + *
   1.180 + *      Copies string fields of the hostnent structure to the
   1.181 + *      private buffer, honouring the size of the buffer.
   1.182 + *
   1.183 + * Results:
   1.184 + *      Number of bytes copied on success or -1 on error (errno = ERANGE)
   1.185 + *
   1.186 + * Side effects:
   1.187 + *      None
   1.188 + *
   1.189 + *---------------------------------------------------------------------------
   1.190 + */
   1.191 +
   1.192 +static int
   1.193 +CopyHostent(struct hostent *tgtPtr, char *buf, int buflen)
   1.194 +{
   1.195 +    char *p = buf;
   1.196 +    int copied, len = 0;
   1.197 +
   1.198 +    copied = CopyString(tgtPtr->h_name, p, buflen - len);
   1.199 +    if (copied == -1) {
   1.200 +    range:
   1.201 +	errno = ERANGE;
   1.202 +	return -1;
   1.203 +    }
   1.204 +    tgtPtr->h_name = (copied > 0) ? p : NULL;
   1.205 +    len += copied;
   1.206 +    p = buf + len;
   1.207 +
   1.208 +    PadBuffer(p, len, sizeof(char *));
   1.209 +    copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
   1.210 +    if (copied == -1) {
   1.211 +	goto range;
   1.212 +    }
   1.213 +    tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
   1.214 +    len += copied;
   1.215 +    p += len;
   1.216 +
   1.217 +    PadBuffer(p, len, sizeof(char *));
   1.218 +    copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen - len);
   1.219 +    if (copied == -1) {
   1.220 +	goto range;
   1.221 +    }
   1.222 +    tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
   1.223 +
   1.224 +    return 0;
   1.225 +}
   1.226 +#endif /* (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
   1.227 +	  (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)) */
   1.228 +
   1.229 +#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
   1.230 +
   1.231 +/*
   1.232 + *---------------------------------------------------------------------------
   1.233 + *
   1.234 + * CopyPwd --
   1.235 + *
   1.236 + *      Copies string fields of the passwd structure to the
   1.237 + *      private buffer, honouring the size of the buffer.
   1.238 + *
   1.239 + * Results:
   1.240 + *      0 on success or -1 on error (errno = ERANGE)
   1.241 + *
   1.242 + * Side effects:
   1.243 + *      We are not copying the gecos field as it may not be supported
   1.244 + *      on all platforms.
   1.245 + *
   1.246 + *---------------------------------------------------------------------------
   1.247 + */
   1.248 +
   1.249 +static int
   1.250 +CopyPwd(struct passwd *tgtPtr, char *buf, int buflen)
   1.251 +{
   1.252 +    char *p = buf;
   1.253 +    int copied, len = 0;
   1.254 +
   1.255 +    copied = CopyString(tgtPtr->pw_name, p, buflen - len);
   1.256 +    if (copied == -1) {
   1.257 +    range:
   1.258 +	errno = ERANGE;
   1.259 +	return -1;
   1.260 +    }
   1.261 +    tgtPtr->pw_name = (copied > 0) ? p : NULL;
   1.262 +    len += copied;
   1.263 +    p = buf + len;
   1.264 +
   1.265 +    copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
   1.266 +    if (copied == -1) {
   1.267 +	goto range;
   1.268 +    }
   1.269 +    tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
   1.270 +    len += copied;
   1.271 +    p = buf + len;
   1.272 +
   1.273 +    copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
   1.274 +    if (copied == -1) {
   1.275 +	goto range;
   1.276 +    }
   1.277 +    tgtPtr->pw_dir = (copied > 0) ? p : NULL;
   1.278 +    len += copied;
   1.279 +    p = buf + len;
   1.280 +
   1.281 +    copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
   1.282 +    if (copied == -1) {
   1.283 +	goto range;
   1.284 +    }
   1.285 +    tgtPtr->pw_shell = (copied > 0) ? p : NULL;
   1.286 +
   1.287 +    return 0;
   1.288 +}
   1.289 +#endif /* !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) */
   1.290 +
   1.291 +#if !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
   1.292 +
   1.293 +/*
   1.294 + *---------------------------------------------------------------------------
   1.295 + *
   1.296 + * CopyGrp --
   1.297 + *
   1.298 + *      Copies string fields of the group structure to the
   1.299 + *      private buffer, honouring the size of the buffer.
   1.300 + *
   1.301 + * Results:
   1.302 + *      0 on success or -1 on error (errno = ERANGE)
   1.303 + *
   1.304 + * Side effects:
   1.305 + *      None.
   1.306 + *
   1.307 + *---------------------------------------------------------------------------
   1.308 + */
   1.309 +
   1.310 +static int
   1.311 +CopyGrp(struct group *tgtPtr, char *buf, int buflen)
   1.312 +{
   1.313 +    register char *p = buf;
   1.314 +    register int copied, len = 0;
   1.315 +
   1.316 +    /* Copy username */
   1.317 +    copied = CopyString(tgtPtr->gr_name, p, buflen - len);
   1.318 +    if (copied == -1) {
   1.319 +    range:
   1.320 +	errno = ERANGE;
   1.321 +	return -1;
   1.322 +    }
   1.323 +    tgtPtr->gr_name = (copied > 0) ? p : NULL;
   1.324 +    len += copied;
   1.325 +    p = buf + len;
   1.326 +
   1.327 +    /* Copy password */
   1.328 +    copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
   1.329 +    if (copied == -1) {
   1.330 +	goto range;
   1.331 +    }
   1.332 +    tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
   1.333 +    len += copied;
   1.334 +    p = buf + len;
   1.335 +
   1.336 +    /* Copy group members */
   1.337 +    PadBuffer(p, len, sizeof(char *));
   1.338 +    copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
   1.339 +    if (copied == -1) {
   1.340 +	goto range;
   1.341 +    }
   1.342 +    tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
   1.343 +
   1.344 +    return 0;
   1.345 +}
   1.346 +#endif /* !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
   1.347 +
   1.348 +#endif /* TCL_THREADS */
   1.349 +
   1.350 +
   1.351 +/*
   1.352 + *---------------------------------------------------------------------------
   1.353 + *
   1.354 + * TclpGetPwNam --
   1.355 + *
   1.356 + *      Thread-safe wrappers for getpwnam().
   1.357 + *      See "man getpwnam" for more details.
   1.358 + *
   1.359 + * Results:
   1.360 + *      Pointer to struct passwd on success or NULL on error.
   1.361 + *
   1.362 + * Side effects:
   1.363 + *      None.
   1.364 + *
   1.365 + *---------------------------------------------------------------------------
   1.366 + */
   1.367 +
   1.368 +struct passwd *
   1.369 +TclpGetPwNam(const char *name)
   1.370 +{
   1.371 +#if !defined(TCL_THREADS)
   1.372 +    return getpwnam(name);
   1.373 +#else
   1.374 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
   1.375 +
   1.376 +#if defined(HAVE_GETPWNAM_R_5)
   1.377 +    struct passwd *pwPtr = NULL;
   1.378 +    return (getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
   1.379 +		       &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
   1.380 +
   1.381 +#elif defined(HAVE_GETPWNAM_R_4)
   1.382 +    return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
   1.383 +
   1.384 +#else
   1.385 +    struct passwd *pwPtr;
   1.386 +    Tcl_MutexLock(&compatLock);
   1.387 +    pwPtr = getpwnam(name);
   1.388 +    if (pwPtr != NULL) {
   1.389 +	tsdPtr->pwd = *pwPtr;
   1.390 +	pwPtr = &tsdPtr->pwd;
   1.391 +	if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) {
   1.392 +	    pwPtr = NULL;
   1.393 +	}
   1.394 +    }
   1.395 +    Tcl_MutexUnlock(&compatLock);
   1.396 +    return pwPtr;
   1.397 +#endif
   1.398 +    return NULL; /* Not reached */
   1.399 +#endif /* TCL_THREADS */
   1.400 +}
   1.401 +
   1.402 +
   1.403 +/*
   1.404 + *---------------------------------------------------------------------------
   1.405 + *
   1.406 + * TclpGetPwUid --
   1.407 + *
   1.408 + *      Thread-safe wrappers for getpwuid().
   1.409 + *      See "man getpwuid" for more details.
   1.410 + *
   1.411 + * Results:
   1.412 + *      Pointer to struct passwd on success or NULL on error.
   1.413 + *
   1.414 + * Side effects:
   1.415 + *      None.
   1.416 + *
   1.417 + *---------------------------------------------------------------------------
   1.418 + */
   1.419 +
   1.420 +struct passwd *
   1.421 +TclpGetPwUid(uid_t uid)
   1.422 +{
   1.423 +#if !defined(TCL_THREADS)
   1.424 +    return getpwuid(uid);
   1.425 +#else
   1.426 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
   1.427 +
   1.428 +#if defined(HAVE_GETPWUID_R_5)
   1.429 +    struct passwd *pwPtr = NULL;
   1.430 +    return (getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
   1.431 +		       &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
   1.432 +
   1.433 +#elif defined(HAVE_GETPWUID_R_4)
   1.434 +    return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
   1.435 +
   1.436 +#else
   1.437 +    struct passwd *pwPtr;
   1.438 +    Tcl_MutexLock(&compatLock);
   1.439 +    pwPtr = getpwuid(uid);
   1.440 +    if (pwPtr != NULL) {
   1.441 +	tsdPtr->pwd = *pwPtr;
   1.442 +	pwPtr = &tsdPtr->pwd;
   1.443 +	if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) {
   1.444 +	    pwPtr = NULL;
   1.445 +	}
   1.446 +    }
   1.447 +    Tcl_MutexUnlock(&compatLock);
   1.448 +    return pwPtr;
   1.449 +#endif
   1.450 +    return NULL; /* Not reached */
   1.451 +#endif /* TCL_THREADS */
   1.452 +}
   1.453 +
   1.454 +
   1.455 +/*
   1.456 + *---------------------------------------------------------------------------
   1.457 + *
   1.458 + * TclpGetGrNam --
   1.459 + *
   1.460 + *      Thread-safe wrappers for getgrnam().
   1.461 + *      See "man getgrnam" for more details.
   1.462 + *
   1.463 + * Results:
   1.464 + *      Pointer to struct group on success or NULL on error.
   1.465 + *
   1.466 + * Side effects:
   1.467 + *      None.
   1.468 + *
   1.469 + *---------------------------------------------------------------------------
   1.470 + */
   1.471 +
   1.472 +struct group *
   1.473 +TclpGetGrNam(const char *name)
   1.474 +{
   1.475 +#if !defined(TCL_THREADS)
   1.476 +    return getgrnam(name);
   1.477 +#else
   1.478 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
   1.479 +
   1.480 +#if defined(HAVE_GETGRNAM_R_5)
   1.481 +    struct group *grPtr = NULL;
   1.482 +    return (getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
   1.483 +		       &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
   1.484 +
   1.485 +#elif defined(HAVE_GETGRNAM_R_4)
   1.486 +    return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
   1.487 +
   1.488 +#else
   1.489 +    struct group *grPtr;
   1.490 +    Tcl_MutexLock(&compatLock);
   1.491 +    grPtr = getgrnam(name);
   1.492 +    if (grPtr != NULL) {
   1.493 +	tsdPtr->grp = *grPtr;
   1.494 +	grPtr = &tsdPtr->grp;
   1.495 +	if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) {
   1.496 +	    grPtr = NULL;
   1.497 +	}
   1.498 +    }
   1.499 +    Tcl_MutexUnlock(&compatLock);
   1.500 +    return grPtr;
   1.501 +#endif
   1.502 +    return NULL; /* Not reached */
   1.503 +#endif /* TCL_THREADS */
   1.504 +}
   1.505 +
   1.506 +
   1.507 +/*
   1.508 + *---------------------------------------------------------------------------
   1.509 + *
   1.510 + * TclpGetGrGid --
   1.511 + *
   1.512 + *      Thread-safe wrappers for getgrgid().
   1.513 + *      See "man getgrgid" for more details.
   1.514 + *
   1.515 + * Results:
   1.516 + *      Pointer to struct group on success or NULL on error.
   1.517 + *
   1.518 + * Side effects:
   1.519 + *      None.
   1.520 + *
   1.521 + *---------------------------------------------------------------------------
   1.522 + */
   1.523 +
   1.524 +struct group *
   1.525 +TclpGetGrGid(gid_t gid)
   1.526 +{
   1.527 +#if !defined(TCL_THREADS)
   1.528 +    return getgrgid(gid);
   1.529 +#else
   1.530 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
   1.531 +
   1.532 +#if defined(HAVE_GETGRGID_R_5)
   1.533 +    struct group *grPtr = NULL;
   1.534 +    return (getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
   1.535 +		       &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
   1.536 +
   1.537 +#elif defined(HAVE_GETGRGID_R_4)
   1.538 +    return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
   1.539 +
   1.540 +#else
   1.541 +    struct group *grPtr;
   1.542 +    Tcl_MutexLock(&compatLock);
   1.543 +    grPtr = getgrgid(gid);
   1.544 +    if (grPtr != NULL) {
   1.545 +	tsdPtr->grp = *grPtr;
   1.546 +	grPtr = &tsdPtr->grp;
   1.547 +	if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) {
   1.548 +	    grPtr = NULL;
   1.549 +	}
   1.550 +    }
   1.551 +    Tcl_MutexUnlock(&compatLock);
   1.552 +    return grPtr;
   1.553 +#endif
   1.554 +    return NULL; /* Not reached */
   1.555 +#endif /* TCL_THREADS */
   1.556 +}
   1.557 +
   1.558 +
   1.559 +/*
   1.560 + *---------------------------------------------------------------------------
   1.561 + *
   1.562 + * TclpGetHostByName --
   1.563 + *
   1.564 + *      Thread-safe wrappers for gethostbyname().
   1.565 + *      See "man gethostbyname" for more details.
   1.566 + *
   1.567 + * Results:
   1.568 + *      Pointer to struct hostent on success or NULL on error.
   1.569 + *
   1.570 + * Side effects:
   1.571 + *      None.
   1.572 + *
   1.573 + *---------------------------------------------------------------------------
   1.574 + */
   1.575 +
   1.576 +struct hostent *
   1.577 +TclpGetHostByName(const char *name)
   1.578 +{
   1.579 +#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME)
   1.580 +    return gethostbyname(name);
   1.581 +#else
   1.582 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
   1.583 +
   1.584 +#if defined(HAVE_GETHOSTBYNAME_R_5)
   1.585 +    int h_errno;
   1.586 +    return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
   1.587 +			   sizeof(tsdPtr->hbuf), &h_errno);
   1.588 +
   1.589 +#elif defined(HAVE_GETHOSTBYNAME_R_6)
   1.590 +    struct hostent *hePtr;
   1.591 +    int h_errno;
   1.592 +    return (gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
   1.593 +			    sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
   1.594 +	&tsdPtr->hent : NULL;
   1.595 +
   1.596 +#elif defined(HAVE_GETHOSTBYNAME_R_3)
   1.597 +    struct hostent_data data;
   1.598 +    return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0) ?
   1.599 +	&tsdPtr->hent : NULL;
   1.600 +#else
   1.601 +    struct hostent *hePtr;
   1.602 +    Tcl_MutexLock(&compatLock);
   1.603 +    hePtr = gethostbyname(name);
   1.604 +    if (hePtr != NULL) {
   1.605 +	tsdPtr->hent = *hePtr;
   1.606 +	hePtr = &tsdPtr->hent;
   1.607 +	if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
   1.608 +			sizeof(tsdPtr->hbuf)) == -1) {
   1.609 +	    hePtr = NULL;
   1.610 +	}
   1.611 +    }
   1.612 +    Tcl_MutexUnlock(&compatLock);
   1.613 +    return hePtr;
   1.614 +#endif
   1.615 +    return NULL; /* Not reached */
   1.616 +#endif /* TCL_THREADS */
   1.617 +}
   1.618 +
   1.619 +
   1.620 +/*
   1.621 + *---------------------------------------------------------------------------
   1.622 + *
   1.623 + * TclpGetHostByAddr --
   1.624 + *
   1.625 + *      Thread-safe wrappers for gethostbyaddr().
   1.626 + *      See "man gethostbyaddr" for more details.
   1.627 + *
   1.628 + * Results:
   1.629 + *      Pointer to struct hostent on success or NULL on error.
   1.630 + *
   1.631 + * Side effects:
   1.632 + *      None.
   1.633 + *
   1.634 + *---------------------------------------------------------------------------
   1.635 + */
   1.636 +
   1.637 +struct hostent *
   1.638 +TclpGetHostByAddr(const char *addr, int length, int type)
   1.639 +{
   1.640 +#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR)
   1.641 +    return gethostbyaddr(addr, length, type);
   1.642 +#else
   1.643 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
   1.644 +
   1.645 +#if defined(HAVE_GETHOSTBYADDR_R_7)
   1.646 +    int h_errno;
   1.647 +    return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
   1.648 +			   sizeof(tsdPtr->hbuf), &h_errno);
   1.649 +
   1.650 +#elif defined(HAVE_GETHOSTBYADDR_R_8)
   1.651 +    struct hostent *hePtr;
   1.652 +    int h_errno;
   1.653 +    return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
   1.654 +			    sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
   1.655 +	&tsdPtr->hent : NULL;
   1.656 +#else
   1.657 +    struct hostent *hePtr;
   1.658 +    Tcl_MutexLock(&compatLock);
   1.659 +    hePtr = gethostbyaddr(addr, length, type);
   1.660 +    if (hePtr != NULL) {
   1.661 +	tsdPtr->hent = *hePtr;
   1.662 +	hePtr = &tsdPtr->hent;
   1.663 +	if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
   1.664 +			sizeof(tsdPtr->hbuf)) == -1) {
   1.665 +	    hePtr = NULL;
   1.666 +	}
   1.667 +    }
   1.668 +    Tcl_MutexUnlock(&compatLock);
   1.669 +    return hePtr;
   1.670 +#endif
   1.671 +    return NULL; /* Not reached */
   1.672 +#endif /* TCL_THREADS */
   1.673 +}