os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixCompat.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
 * tclUnixCompat.c
sl@0
     3
 *
sl@0
     4
 * Written by: Zoran Vasiljevic (vasiljevic@users.sourceforge.net).
sl@0
     5
 *
sl@0
     6
 * See the file "license.terms" for information on usage and redistribution
sl@0
     7
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
     8
 *
sl@0
     9
 * RCS: @(#) $Id: tclUnixCompat.c,v 1.1.2.10 2006/09/12 22:05:03 andreas_kupries Exp $
sl@0
    10
 *
sl@0
    11
 */
sl@0
    12
sl@0
    13
#include "tclInt.h"
sl@0
    14
#include "tclPort.h"
sl@0
    15
#include <pwd.h>
sl@0
    16
#include <grp.h>
sl@0
    17
#include <errno.h>
sl@0
    18
#include <string.h>
sl@0
    19
sl@0
    20
/*
sl@0
    21
 * Used to pad structures at size'd boundaries
sl@0
    22
 *
sl@0
    23
 * This macro assumes that the pointer 'buffer' was created from an
sl@0
    24
 * aligned pointer by adding the 'length'. If this 'length' was not a
sl@0
    25
 * multiple of the 'size' the result is unaligned and PadBuffer
sl@0
    26
 * corrects both the pointer, _and_ the 'length'. The latter means
sl@0
    27
 * that future increments of 'buffer' by 'length' stay aligned.
sl@0
    28
 */
sl@0
    29
sl@0
    30
#define PadBuffer(buffer, length, size)             \
sl@0
    31
    if (((length) % (size))) {                      \
sl@0
    32
	(buffer) += ((size) - ((length) % (size))); \
sl@0
    33
	(length) += ((size) - ((length) % (size))); \
sl@0
    34
    }
sl@0
    35
sl@0
    36
/*
sl@0
    37
 * Per-thread private storage used to store values
sl@0
    38
 * returned from MT-unsafe library calls.
sl@0
    39
 */
sl@0
    40
sl@0
    41
#ifdef TCL_THREADS
sl@0
    42
sl@0
    43
typedef struct ThreadSpecificData {
sl@0
    44
sl@0
    45
    struct passwd pwd;
sl@0
    46
    char pbuf[2048];
sl@0
    47
sl@0
    48
    struct group grp;
sl@0
    49
    char gbuf[2048];
sl@0
    50
sl@0
    51
#if !defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)
sl@0
    52
    struct hostent hent;
sl@0
    53
    char hbuf[2048];
sl@0
    54
#endif
sl@0
    55
sl@0
    56
}  ThreadSpecificData;
sl@0
    57
sl@0
    58
static Tcl_ThreadDataKey dataKey;
sl@0
    59
sl@0
    60
#if ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
sl@0
    61
     (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
sl@0
    62
      !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
sl@0
    63
      !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
sl@0
    64
sl@0
    65
/*
sl@0
    66
 * Mutex to lock access to MT-unsafe calls. This is just to protect
sl@0
    67
 * our own usage. It does not protect us from others calling the
sl@0
    68
 * same functions without (or using some different) lock.
sl@0
    69
 */
sl@0
    70
sl@0
    71
static Tcl_Mutex compatLock;
sl@0
    72

sl@0
    73
/*
sl@0
    74
 *---------------------------------------------------------------------------
sl@0
    75
 *
sl@0
    76
 * CopyArray --
sl@0
    77
 *
sl@0
    78
 *      Copies array of NULL-terminated or fixed-length strings
sl@0
    79
 *      to the private buffer, honouring the size of the buffer.
sl@0
    80
 *
sl@0
    81
 * Results:
sl@0
    82
 *      Number of bytes copied on success or -1 on error (errno = ERANGE)
sl@0
    83
 *
sl@0
    84
 * Side effects:
sl@0
    85
 *      None.
sl@0
    86
 *
sl@0
    87
 *---------------------------------------------------------------------------
sl@0
    88
 */
sl@0
    89
sl@0
    90
static int
sl@0
    91
CopyArray(char **src, int elsize, char *buf, int buflen)
sl@0
    92
{
sl@0
    93
    int i, j, len = 0;
sl@0
    94
    char *p, **new;
sl@0
    95
sl@0
    96
    if (src == NULL) {
sl@0
    97
	return 0;
sl@0
    98
    }
sl@0
    99
    for (i = 0; src[i] != NULL; i++) {
sl@0
   100
	/* Empty loop to count howmany */
sl@0
   101
    }
sl@0
   102
    if ((sizeof(char *)*(i + 1)) >  buflen) {
sl@0
   103
	return -1;
sl@0
   104
    }
sl@0
   105
    len = (sizeof(char *)*(i + 1)); /* Leave place for the array */
sl@0
   106
    new = (char **)buf;
sl@0
   107
    p = buf + (sizeof(char *)*(i + 1));
sl@0
   108
    for (j = 0; j < i; j++) {
sl@0
   109
	if (elsize < 0) {
sl@0
   110
	    len += strlen(src[j]) + 1;
sl@0
   111
	} else {
sl@0
   112
	    len += elsize;
sl@0
   113
	}
sl@0
   114
	if (len > buflen) {
sl@0
   115
	    return -1;
sl@0
   116
	}
sl@0
   117
	if (elsize < 0) {
sl@0
   118
	    strcpy(p, src[j]);
sl@0
   119
	} else {
sl@0
   120
	    memcpy(p, src[j], elsize);
sl@0
   121
	}
sl@0
   122
	new[j] = p;
sl@0
   123
	p = buf + len;
sl@0
   124
    }
sl@0
   125
    new[j] = NULL;
sl@0
   126
sl@0
   127
    return len;
sl@0
   128
}
sl@0
   129
sl@0
   130

sl@0
   131
/*
sl@0
   132
 *---------------------------------------------------------------------------
sl@0
   133
 *
sl@0
   134
 * CopyString --
sl@0
   135
 *
sl@0
   136
 *      Copies a NULL-terminated string to the private buffer,
sl@0
   137
 *      honouring the size of the buffer
sl@0
   138
 *
sl@0
   139
 * Results:
sl@0
   140
 *      0 success or -1 on error (errno = ERANGE)
sl@0
   141
 *
sl@0
   142
 * Side effects:
sl@0
   143
 *      None
sl@0
   144
 *
sl@0
   145
 *---------------------------------------------------------------------------
sl@0
   146
 */
sl@0
   147
sl@0
   148
sl@0
   149
static int
sl@0
   150
CopyString(char *src, char *buf, int buflen)
sl@0
   151
{
sl@0
   152
    int len = 0;
sl@0
   153
sl@0
   154
    if (src != NULL) {
sl@0
   155
	len += strlen(src) + 1;
sl@0
   156
	if (len > buflen) {
sl@0
   157
	    return -1;
sl@0
   158
	}
sl@0
   159
	strcpy(buf, src);
sl@0
   160
    }
sl@0
   161
sl@0
   162
    return len;
sl@0
   163
}
sl@0
   164
#endif /* ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
sl@0
   165
	   (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
sl@0
   166
	    !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
sl@0
   167
	    !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
sl@0
   168
sl@0
   169
#if (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
sl@0
   170
    (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))
sl@0
   171

sl@0
   172
/*
sl@0
   173
 *---------------------------------------------------------------------------
sl@0
   174
 *
sl@0
   175
 * CopyHostnent --
sl@0
   176
 *
sl@0
   177
 *      Copies string fields of the hostnent structure to the
sl@0
   178
 *      private buffer, honouring the size of the buffer.
sl@0
   179
 *
sl@0
   180
 * Results:
sl@0
   181
 *      Number of bytes copied on success or -1 on error (errno = ERANGE)
sl@0
   182
 *
sl@0
   183
 * Side effects:
sl@0
   184
 *      None
sl@0
   185
 *
sl@0
   186
 *---------------------------------------------------------------------------
sl@0
   187
 */
sl@0
   188
sl@0
   189
static int
sl@0
   190
CopyHostent(struct hostent *tgtPtr, char *buf, int buflen)
sl@0
   191
{
sl@0
   192
    char *p = buf;
sl@0
   193
    int copied, len = 0;
sl@0
   194
sl@0
   195
    copied = CopyString(tgtPtr->h_name, p, buflen - len);
sl@0
   196
    if (copied == -1) {
sl@0
   197
    range:
sl@0
   198
	errno = ERANGE;
sl@0
   199
	return -1;
sl@0
   200
    }
sl@0
   201
    tgtPtr->h_name = (copied > 0) ? p : NULL;
sl@0
   202
    len += copied;
sl@0
   203
    p = buf + len;
sl@0
   204
sl@0
   205
    PadBuffer(p, len, sizeof(char *));
sl@0
   206
    copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
sl@0
   207
    if (copied == -1) {
sl@0
   208
	goto range;
sl@0
   209
    }
sl@0
   210
    tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
sl@0
   211
    len += copied;
sl@0
   212
    p += len;
sl@0
   213
sl@0
   214
    PadBuffer(p, len, sizeof(char *));
sl@0
   215
    copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen - len);
sl@0
   216
    if (copied == -1) {
sl@0
   217
	goto range;
sl@0
   218
    }
sl@0
   219
    tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
sl@0
   220
sl@0
   221
    return 0;
sl@0
   222
}
sl@0
   223
#endif /* (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
sl@0
   224
	  (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)) */
sl@0
   225
sl@0
   226
#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
sl@0
   227

sl@0
   228
/*
sl@0
   229
 *---------------------------------------------------------------------------
sl@0
   230
 *
sl@0
   231
 * CopyPwd --
sl@0
   232
 *
sl@0
   233
 *      Copies string fields of the passwd structure to the
sl@0
   234
 *      private buffer, honouring the size of the buffer.
sl@0
   235
 *
sl@0
   236
 * Results:
sl@0
   237
 *      0 on success or -1 on error (errno = ERANGE)
sl@0
   238
 *
sl@0
   239
 * Side effects:
sl@0
   240
 *      We are not copying the gecos field as it may not be supported
sl@0
   241
 *      on all platforms.
sl@0
   242
 *
sl@0
   243
 *---------------------------------------------------------------------------
sl@0
   244
 */
sl@0
   245
sl@0
   246
static int
sl@0
   247
CopyPwd(struct passwd *tgtPtr, char *buf, int buflen)
sl@0
   248
{
sl@0
   249
    char *p = buf;
sl@0
   250
    int copied, len = 0;
sl@0
   251
sl@0
   252
    copied = CopyString(tgtPtr->pw_name, p, buflen - len);
sl@0
   253
    if (copied == -1) {
sl@0
   254
    range:
sl@0
   255
	errno = ERANGE;
sl@0
   256
	return -1;
sl@0
   257
    }
sl@0
   258
    tgtPtr->pw_name = (copied > 0) ? p : NULL;
sl@0
   259
    len += copied;
sl@0
   260
    p = buf + len;
sl@0
   261
sl@0
   262
    copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
sl@0
   263
    if (copied == -1) {
sl@0
   264
	goto range;
sl@0
   265
    }
sl@0
   266
    tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
sl@0
   267
    len += copied;
sl@0
   268
    p = buf + len;
sl@0
   269
sl@0
   270
    copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
sl@0
   271
    if (copied == -1) {
sl@0
   272
	goto range;
sl@0
   273
    }
sl@0
   274
    tgtPtr->pw_dir = (copied > 0) ? p : NULL;
sl@0
   275
    len += copied;
sl@0
   276
    p = buf + len;
sl@0
   277
sl@0
   278
    copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
sl@0
   279
    if (copied == -1) {
sl@0
   280
	goto range;
sl@0
   281
    }
sl@0
   282
    tgtPtr->pw_shell = (copied > 0) ? p : NULL;
sl@0
   283
sl@0
   284
    return 0;
sl@0
   285
}
sl@0
   286
#endif /* !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) */
sl@0
   287
sl@0
   288
#if !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
sl@0
   289

sl@0
   290
/*
sl@0
   291
 *---------------------------------------------------------------------------
sl@0
   292
 *
sl@0
   293
 * CopyGrp --
sl@0
   294
 *
sl@0
   295
 *      Copies string fields of the group structure to the
sl@0
   296
 *      private buffer, honouring the size of the buffer.
sl@0
   297
 *
sl@0
   298
 * Results:
sl@0
   299
 *      0 on success or -1 on error (errno = ERANGE)
sl@0
   300
 *
sl@0
   301
 * Side effects:
sl@0
   302
 *      None.
sl@0
   303
 *
sl@0
   304
 *---------------------------------------------------------------------------
sl@0
   305
 */
sl@0
   306
sl@0
   307
static int
sl@0
   308
CopyGrp(struct group *tgtPtr, char *buf, int buflen)
sl@0
   309
{
sl@0
   310
    register char *p = buf;
sl@0
   311
    register int copied, len = 0;
sl@0
   312
sl@0
   313
    /* Copy username */
sl@0
   314
    copied = CopyString(tgtPtr->gr_name, p, buflen - len);
sl@0
   315
    if (copied == -1) {
sl@0
   316
    range:
sl@0
   317
	errno = ERANGE;
sl@0
   318
	return -1;
sl@0
   319
    }
sl@0
   320
    tgtPtr->gr_name = (copied > 0) ? p : NULL;
sl@0
   321
    len += copied;
sl@0
   322
    p = buf + len;
sl@0
   323
sl@0
   324
    /* Copy password */
sl@0
   325
    copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
sl@0
   326
    if (copied == -1) {
sl@0
   327
	goto range;
sl@0
   328
    }
sl@0
   329
    tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
sl@0
   330
    len += copied;
sl@0
   331
    p = buf + len;
sl@0
   332
sl@0
   333
    /* Copy group members */
sl@0
   334
    PadBuffer(p, len, sizeof(char *));
sl@0
   335
    copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
sl@0
   336
    if (copied == -1) {
sl@0
   337
	goto range;
sl@0
   338
    }
sl@0
   339
    tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
sl@0
   340
sl@0
   341
    return 0;
sl@0
   342
}
sl@0
   343
#endif /* !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
sl@0
   344
sl@0
   345
#endif /* TCL_THREADS */
sl@0
   346
sl@0
   347

sl@0
   348
/*
sl@0
   349
 *---------------------------------------------------------------------------
sl@0
   350
 *
sl@0
   351
 * TclpGetPwNam --
sl@0
   352
 *
sl@0
   353
 *      Thread-safe wrappers for getpwnam().
sl@0
   354
 *      See "man getpwnam" for more details.
sl@0
   355
 *
sl@0
   356
 * Results:
sl@0
   357
 *      Pointer to struct passwd on success or NULL on error.
sl@0
   358
 *
sl@0
   359
 * Side effects:
sl@0
   360
 *      None.
sl@0
   361
 *
sl@0
   362
 *---------------------------------------------------------------------------
sl@0
   363
 */
sl@0
   364
sl@0
   365
struct passwd *
sl@0
   366
TclpGetPwNam(const char *name)
sl@0
   367
{
sl@0
   368
#if !defined(TCL_THREADS)
sl@0
   369
    return getpwnam(name);
sl@0
   370
#else
sl@0
   371
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
sl@0
   372
sl@0
   373
#if defined(HAVE_GETPWNAM_R_5)
sl@0
   374
    struct passwd *pwPtr = NULL;
sl@0
   375
    return (getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
sl@0
   376
		       &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
sl@0
   377
sl@0
   378
#elif defined(HAVE_GETPWNAM_R_4)
sl@0
   379
    return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
sl@0
   380
sl@0
   381
#else
sl@0
   382
    struct passwd *pwPtr;
sl@0
   383
    Tcl_MutexLock(&compatLock);
sl@0
   384
    pwPtr = getpwnam(name);
sl@0
   385
    if (pwPtr != NULL) {
sl@0
   386
	tsdPtr->pwd = *pwPtr;
sl@0
   387
	pwPtr = &tsdPtr->pwd;
sl@0
   388
	if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) {
sl@0
   389
	    pwPtr = NULL;
sl@0
   390
	}
sl@0
   391
    }
sl@0
   392
    Tcl_MutexUnlock(&compatLock);
sl@0
   393
    return pwPtr;
sl@0
   394
#endif
sl@0
   395
    return NULL; /* Not reached */
sl@0
   396
#endif /* TCL_THREADS */
sl@0
   397
}
sl@0
   398
sl@0
   399

sl@0
   400
/*
sl@0
   401
 *---------------------------------------------------------------------------
sl@0
   402
 *
sl@0
   403
 * TclpGetPwUid --
sl@0
   404
 *
sl@0
   405
 *      Thread-safe wrappers for getpwuid().
sl@0
   406
 *      See "man getpwuid" for more details.
sl@0
   407
 *
sl@0
   408
 * Results:
sl@0
   409
 *      Pointer to struct passwd on success or NULL on error.
sl@0
   410
 *
sl@0
   411
 * Side effects:
sl@0
   412
 *      None.
sl@0
   413
 *
sl@0
   414
 *---------------------------------------------------------------------------
sl@0
   415
 */
sl@0
   416
sl@0
   417
struct passwd *
sl@0
   418
TclpGetPwUid(uid_t uid)
sl@0
   419
{
sl@0
   420
#if !defined(TCL_THREADS)
sl@0
   421
    return getpwuid(uid);
sl@0
   422
#else
sl@0
   423
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
sl@0
   424
sl@0
   425
#if defined(HAVE_GETPWUID_R_5)
sl@0
   426
    struct passwd *pwPtr = NULL;
sl@0
   427
    return (getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
sl@0
   428
		       &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
sl@0
   429
sl@0
   430
#elif defined(HAVE_GETPWUID_R_4)
sl@0
   431
    return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
sl@0
   432
sl@0
   433
#else
sl@0
   434
    struct passwd *pwPtr;
sl@0
   435
    Tcl_MutexLock(&compatLock);
sl@0
   436
    pwPtr = getpwuid(uid);
sl@0
   437
    if (pwPtr != NULL) {
sl@0
   438
	tsdPtr->pwd = *pwPtr;
sl@0
   439
	pwPtr = &tsdPtr->pwd;
sl@0
   440
	if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) {
sl@0
   441
	    pwPtr = NULL;
sl@0
   442
	}
sl@0
   443
    }
sl@0
   444
    Tcl_MutexUnlock(&compatLock);
sl@0
   445
    return pwPtr;
sl@0
   446
#endif
sl@0
   447
    return NULL; /* Not reached */
sl@0
   448
#endif /* TCL_THREADS */
sl@0
   449
}
sl@0
   450
sl@0
   451

sl@0
   452
/*
sl@0
   453
 *---------------------------------------------------------------------------
sl@0
   454
 *
sl@0
   455
 * TclpGetGrNam --
sl@0
   456
 *
sl@0
   457
 *      Thread-safe wrappers for getgrnam().
sl@0
   458
 *      See "man getgrnam" for more details.
sl@0
   459
 *
sl@0
   460
 * Results:
sl@0
   461
 *      Pointer to struct group on success or NULL on error.
sl@0
   462
 *
sl@0
   463
 * Side effects:
sl@0
   464
 *      None.
sl@0
   465
 *
sl@0
   466
 *---------------------------------------------------------------------------
sl@0
   467
 */
sl@0
   468
sl@0
   469
struct group *
sl@0
   470
TclpGetGrNam(const char *name)
sl@0
   471
{
sl@0
   472
#if !defined(TCL_THREADS)
sl@0
   473
    return getgrnam(name);
sl@0
   474
#else
sl@0
   475
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
sl@0
   476
sl@0
   477
#if defined(HAVE_GETGRNAM_R_5)
sl@0
   478
    struct group *grPtr = NULL;
sl@0
   479
    return (getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
sl@0
   480
		       &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
sl@0
   481
sl@0
   482
#elif defined(HAVE_GETGRNAM_R_4)
sl@0
   483
    return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
sl@0
   484
sl@0
   485
#else
sl@0
   486
    struct group *grPtr;
sl@0
   487
    Tcl_MutexLock(&compatLock);
sl@0
   488
    grPtr = getgrnam(name);
sl@0
   489
    if (grPtr != NULL) {
sl@0
   490
	tsdPtr->grp = *grPtr;
sl@0
   491
	grPtr = &tsdPtr->grp;
sl@0
   492
	if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) {
sl@0
   493
	    grPtr = NULL;
sl@0
   494
	}
sl@0
   495
    }
sl@0
   496
    Tcl_MutexUnlock(&compatLock);
sl@0
   497
    return grPtr;
sl@0
   498
#endif
sl@0
   499
    return NULL; /* Not reached */
sl@0
   500
#endif /* TCL_THREADS */
sl@0
   501
}
sl@0
   502
sl@0
   503

sl@0
   504
/*
sl@0
   505
 *---------------------------------------------------------------------------
sl@0
   506
 *
sl@0
   507
 * TclpGetGrGid --
sl@0
   508
 *
sl@0
   509
 *      Thread-safe wrappers for getgrgid().
sl@0
   510
 *      See "man getgrgid" for more details.
sl@0
   511
 *
sl@0
   512
 * Results:
sl@0
   513
 *      Pointer to struct group on success or NULL on error.
sl@0
   514
 *
sl@0
   515
 * Side effects:
sl@0
   516
 *      None.
sl@0
   517
 *
sl@0
   518
 *---------------------------------------------------------------------------
sl@0
   519
 */
sl@0
   520
sl@0
   521
struct group *
sl@0
   522
TclpGetGrGid(gid_t gid)
sl@0
   523
{
sl@0
   524
#if !defined(TCL_THREADS)
sl@0
   525
    return getgrgid(gid);
sl@0
   526
#else
sl@0
   527
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
sl@0
   528
sl@0
   529
#if defined(HAVE_GETGRGID_R_5)
sl@0
   530
    struct group *grPtr = NULL;
sl@0
   531
    return (getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
sl@0
   532
		       &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
sl@0
   533
sl@0
   534
#elif defined(HAVE_GETGRGID_R_4)
sl@0
   535
    return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
sl@0
   536
sl@0
   537
#else
sl@0
   538
    struct group *grPtr;
sl@0
   539
    Tcl_MutexLock(&compatLock);
sl@0
   540
    grPtr = getgrgid(gid);
sl@0
   541
    if (grPtr != NULL) {
sl@0
   542
	tsdPtr->grp = *grPtr;
sl@0
   543
	grPtr = &tsdPtr->grp;
sl@0
   544
	if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) {
sl@0
   545
	    grPtr = NULL;
sl@0
   546
	}
sl@0
   547
    }
sl@0
   548
    Tcl_MutexUnlock(&compatLock);
sl@0
   549
    return grPtr;
sl@0
   550
#endif
sl@0
   551
    return NULL; /* Not reached */
sl@0
   552
#endif /* TCL_THREADS */
sl@0
   553
}
sl@0
   554
sl@0
   555

sl@0
   556
/*
sl@0
   557
 *---------------------------------------------------------------------------
sl@0
   558
 *
sl@0
   559
 * TclpGetHostByName --
sl@0
   560
 *
sl@0
   561
 *      Thread-safe wrappers for gethostbyname().
sl@0
   562
 *      See "man gethostbyname" for more details.
sl@0
   563
 *
sl@0
   564
 * Results:
sl@0
   565
 *      Pointer to struct hostent on success or NULL on error.
sl@0
   566
 *
sl@0
   567
 * Side effects:
sl@0
   568
 *      None.
sl@0
   569
 *
sl@0
   570
 *---------------------------------------------------------------------------
sl@0
   571
 */
sl@0
   572
sl@0
   573
struct hostent *
sl@0
   574
TclpGetHostByName(const char *name)
sl@0
   575
{
sl@0
   576
#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME)
sl@0
   577
    return gethostbyname(name);
sl@0
   578
#else
sl@0
   579
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
sl@0
   580
sl@0
   581
#if defined(HAVE_GETHOSTBYNAME_R_5)
sl@0
   582
    int h_errno;
sl@0
   583
    return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
sl@0
   584
			   sizeof(tsdPtr->hbuf), &h_errno);
sl@0
   585
sl@0
   586
#elif defined(HAVE_GETHOSTBYNAME_R_6)
sl@0
   587
    struct hostent *hePtr;
sl@0
   588
    int h_errno;
sl@0
   589
    return (gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
sl@0
   590
			    sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
sl@0
   591
	&tsdPtr->hent : NULL;
sl@0
   592
sl@0
   593
#elif defined(HAVE_GETHOSTBYNAME_R_3)
sl@0
   594
    struct hostent_data data;
sl@0
   595
    return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0) ?
sl@0
   596
	&tsdPtr->hent : NULL;
sl@0
   597
#else
sl@0
   598
    struct hostent *hePtr;
sl@0
   599
    Tcl_MutexLock(&compatLock);
sl@0
   600
    hePtr = gethostbyname(name);
sl@0
   601
    if (hePtr != NULL) {
sl@0
   602
	tsdPtr->hent = *hePtr;
sl@0
   603
	hePtr = &tsdPtr->hent;
sl@0
   604
	if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
sl@0
   605
			sizeof(tsdPtr->hbuf)) == -1) {
sl@0
   606
	    hePtr = NULL;
sl@0
   607
	}
sl@0
   608
    }
sl@0
   609
    Tcl_MutexUnlock(&compatLock);
sl@0
   610
    return hePtr;
sl@0
   611
#endif
sl@0
   612
    return NULL; /* Not reached */
sl@0
   613
#endif /* TCL_THREADS */
sl@0
   614
}
sl@0
   615
sl@0
   616

sl@0
   617
/*
sl@0
   618
 *---------------------------------------------------------------------------
sl@0
   619
 *
sl@0
   620
 * TclpGetHostByAddr --
sl@0
   621
 *
sl@0
   622
 *      Thread-safe wrappers for gethostbyaddr().
sl@0
   623
 *      See "man gethostbyaddr" for more details.
sl@0
   624
 *
sl@0
   625
 * Results:
sl@0
   626
 *      Pointer to struct hostent on success or NULL on error.
sl@0
   627
 *
sl@0
   628
 * Side effects:
sl@0
   629
 *      None.
sl@0
   630
 *
sl@0
   631
 *---------------------------------------------------------------------------
sl@0
   632
 */
sl@0
   633
sl@0
   634
struct hostent *
sl@0
   635
TclpGetHostByAddr(const char *addr, int length, int type)
sl@0
   636
{
sl@0
   637
#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR)
sl@0
   638
    return gethostbyaddr(addr, length, type);
sl@0
   639
#else
sl@0
   640
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
sl@0
   641
sl@0
   642
#if defined(HAVE_GETHOSTBYADDR_R_7)
sl@0
   643
    int h_errno;
sl@0
   644
    return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
sl@0
   645
			   sizeof(tsdPtr->hbuf), &h_errno);
sl@0
   646
sl@0
   647
#elif defined(HAVE_GETHOSTBYADDR_R_8)
sl@0
   648
    struct hostent *hePtr;
sl@0
   649
    int h_errno;
sl@0
   650
    return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
sl@0
   651
			    sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
sl@0
   652
	&tsdPtr->hent : NULL;
sl@0
   653
#else
sl@0
   654
    struct hostent *hePtr;
sl@0
   655
    Tcl_MutexLock(&compatLock);
sl@0
   656
    hePtr = gethostbyaddr(addr, length, type);
sl@0
   657
    if (hePtr != NULL) {
sl@0
   658
	tsdPtr->hent = *hePtr;
sl@0
   659
	hePtr = &tsdPtr->hent;
sl@0
   660
	if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
sl@0
   661
			sizeof(tsdPtr->hbuf)) == -1) {
sl@0
   662
	    hePtr = NULL;
sl@0
   663
	}
sl@0
   664
    }
sl@0
   665
    Tcl_MutexUnlock(&compatLock);
sl@0
   666
    return hePtr;
sl@0
   667
#endif
sl@0
   668
    return NULL; /* Not reached */
sl@0
   669
#endif /* TCL_THREADS */
sl@0
   670
}