os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixCompat.c
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 +}