summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
Diffstat (limited to 'unix')
-rw-r--r--unix/tclUnixCompat.c730
1 files changed, 396 insertions, 334 deletions
diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c
index 23905a4..90630a3 100644
--- a/unix/tclUnixCompat.c
+++ b/unix/tclUnixCompat.c
@@ -3,10 +3,10 @@
*
* Written by: Zoran Vasiljevic (vasiljevic@users.sourceforge.net).
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUnixCompat.c,v 1.9 2007/04/16 13:36:36 dkf Exp $
+ * RCS: @(#) $Id: tclUnixCompat.c,v 1.10 2007/07/31 09:30:48 dkf Exp $
*
*/
@@ -20,11 +20,11 @@
/*
* Used to pad structures at size'd boundaries
*
- * This macro assumes that the pointer 'buffer' was created from an
- * aligned pointer by adding the 'length'. If this 'length' was not a
- * multiple of the 'size' the result is unaligned and PadBuffer
- * corrects both the pointer, _and_ the 'length'. The latter means
- * that future increments of 'buffer' by 'length' stay aligned.
+ * This macro assumes that the pointer 'buffer' was created from an aligned
+ * pointer by adding the 'length'. If this 'length' was not a multiple of the
+ * 'size' the result is unaligned and PadBuffer corrects both the pointer,
+ * _and_ the 'length'. The latter means that future increments of 'buffer' by
+ * 'length' stay aligned.
*/
#define PadBuffer(buffer, length, size) \
@@ -34,14 +34,13 @@
}
/*
- * Per-thread private storage used to store values
- * returned from MT-unsafe library calls.
+ * Per-thread private storage used to store values returned from MT-unsafe
+ * library calls.
*/
#ifdef TCL_THREADS
typedef struct ThreadSpecificData {
-
struct passwd pwd;
char pbuf[2048];
@@ -52,322 +51,51 @@ typedef struct ThreadSpecificData {
struct hostent hent;
char hbuf[2048];
#endif
-
} ThreadSpecificData;
-
static Tcl_ThreadDataKey dataKey;
#if ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
+ (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || \
+ !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
!defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
!defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
-
/*
- * Mutex to lock access to MT-unsafe calls. This is just to protect
- * our own usage. It does not protect us from others calling the
- * same functions without (or using some different) lock.
+ * Mutex to lock access to MT-unsafe calls. This is just to protect our own
+ * usage. It does not protect us from others calling the same functions
+ * without (or using some different) lock.
*/
static Tcl_Mutex compatLock;
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyArray --
- *
- * Copies array of NULL-terminated or fixed-length strings
- * to the private buffer, honouring the size of the buffer.
- *
- * Results:
- * Number of bytes copied on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-CopyArray(
- char **src,
- int elsize,
- char *buf,
- int buflen)
-{
- int i, j, len = 0;
- char *p, **new;
-
- if (src == NULL) {
- return 0;
- }
- for (i = 0; src[i] != NULL; i++) {
- /* Empty loop to count howmany */
- }
- if ((sizeof(char *)*(i + 1)) > buflen) {
- return -1;
- }
- len = (sizeof(char *)*(i + 1)); /* Leave place for the array */
- new = (char **)buf;
- p = buf + (sizeof(char *)*(i + 1));
- for (j = 0; j < i; j++) {
- if (elsize < 0) {
- len += strlen(src[j]) + 1;
- } else {
- len += elsize;
- }
- if (len > buflen) {
- return -1;
- }
- if (elsize < 0) {
- strcpy(p, src[j]);
- } else {
- memcpy(p, src[j], elsize);
- }
- new[j] = p;
- p = buf + len;
- }
- new[j] = NULL;
-
- return len;
-}
-
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyString --
- *
- * Copies a NULL-terminated string to the private buffer,
- * honouring the size of the buffer
- *
- * Results:
- * 0 success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None
- *
- *---------------------------------------------------------------------------
- */
-
-
-static int
-CopyString(
- char *src,
- char *buf,
- int buflen)
-{
- int len = 0;
-
- if (src != NULL) {
- len += strlen(src) + 1;
- if (len > buflen) {
- return -1;
- }
- strcpy(buf, src);
- }
-
- return len;
-}
-#endif /* ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
- !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
- !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
-
-#if (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyHostnent --
- *
- * Copies string fields of the hostnent structure to the
- * private buffer, honouring the size of the buffer.
- *
- * Results:
- * Number of bytes copied on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-CopyHostent(
- struct hostent *tgtPtr,
- char *buf,
- int buflen)
-{
- char *p = buf;
- int copied, len = 0;
-
- copied = CopyString(tgtPtr->h_name, p, buflen - len);
- if (copied == -1) {
- range:
- errno = ERANGE;
- return -1;
- }
- tgtPtr->h_name = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- PadBuffer(p, len, sizeof(char *));
- copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
- len += copied;
- p += len;
-
- PadBuffer(p, len, sizeof(char *));
- copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
-
- return 0;
-}
-#endif /* (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)) */
-#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
-
/*
- *---------------------------------------------------------------------------
- *
- * CopyPwd --
- *
- * Copies string fields of the passwd structure to the
- * private buffer, honouring the size of the buffer.
- *
- * Results:
- * 0 on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * We are not copying the gecos field as it may not be supported
- * on all platforms.
- *
- *---------------------------------------------------------------------------
+ * Helper function declarations. Note that these are only used if needed and
+ * only defined if used (via the NEED_* macros).
*/
-static int
-CopyPwd(
- struct passwd *tgtPtr,
- char *buf,
- int buflen)
-{
- char *p = buf;
- int copied, len = 0;
-
- copied = CopyString(tgtPtr->pw_name, p, buflen - len);
- if (copied == -1) {
- range:
- errno = ERANGE;
- return -1;
- }
- tgtPtr->pw_name = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->pw_dir = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->pw_shell = (copied > 0) ? p : NULL;
+#undef NEED_COPYARRAY
+#undef NEED_COPYGRP
+#undef NEED_COPYHOSTENT
+#undef NEED_COPYPWD
+#undef NEED_COPYSTRING
- return 0;
-}
-#endif /* !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) */
-
-#if !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyGrp --
- *
- * Copies string fields of the group structure to the
- * private buffer, honouring the size of the buffer.
- *
- * Results:
- * 0 on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-CopyGrp(
- struct group *tgtPtr,
- char *buf,
- int buflen)
-{
- register char *p = buf;
- register int copied, len = 0;
-
- /* Copy username */
- copied = CopyString(tgtPtr->gr_name, p, buflen - len);
- if (copied == -1) {
- range:
- errno = ERANGE;
- return -1;
- }
- tgtPtr->gr_name = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- /* Copy password */
- copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- /* Copy group members */
- PadBuffer(p, len, sizeof(char *));
- copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
-
- return 0;
-}
-#endif /* !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
+static int CopyArray(char **src, int elsize, char *buf,
+ int buflen);
+static int CopyGrp(struct group *tgtPtr, char *buf, int buflen);
+static int CopyHostent(struct hostent *tgtPtr, char *buf,
+ int buflen);
+static int CopyPwd(struct passwd *tgtPtr, char *buf, int buflen);
+static int CopyString(char *src, char *buf, int buflen);
+#endif
#endif /* TCL_THREADS */
-
/*
*---------------------------------------------------------------------------
*
* TclpGetPwNam --
*
- * Thread-safe wrappers for getpwnam().
- * See "man getpwnam" for more details.
+ * Thread-safe wrappers for getpwnam(). See "man getpwnam" for more
+ * details.
*
* Results:
* Pointer to struct passwd on success or NULL on error.
@@ -389,6 +117,7 @@ TclpGetPwNam(
#if defined(HAVE_GETPWNAM_R_5)
struct passwd *pwPtr = NULL;
+
return (getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
&pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
@@ -396,7 +125,9 @@ TclpGetPwNam(
return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
#else
+#define NEED_COPYPWD 1
struct passwd *pwPtr;
+
Tcl_MutexLock(&compatLock);
pwPtr = getpwnam(name);
if (pwPtr != NULL) {
@@ -409,18 +140,18 @@ TclpGetPwNam(
Tcl_MutexUnlock(&compatLock);
return pwPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetPwUid --
*
- * Thread-safe wrappers for getpwuid().
- * See "man getpwuid" for more details.
+ * Thread-safe wrappers for getpwuid(). See "man getpwuid" for more
+ * details.
*
* Results:
* Pointer to struct passwd on success or NULL on error.
@@ -442,6 +173,7 @@ TclpGetPwUid(
#if defined(HAVE_GETPWUID_R_5)
struct passwd *pwPtr = NULL;
+
return (getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
&pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
@@ -449,7 +181,9 @@ TclpGetPwUid(
return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
#else
+#define NEED_COPYPWD 1
struct passwd *pwPtr;
+
Tcl_MutexLock(&compatLock);
pwPtr = getpwuid(uid);
if (pwPtr != NULL) {
@@ -462,18 +196,18 @@ TclpGetPwUid(
Tcl_MutexUnlock(&compatLock);
return pwPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetGrNam --
*
- * Thread-safe wrappers for getgrnam().
- * See "man getgrnam" for more details.
+ * Thread-safe wrappers for getgrnam(). See "man getgrnam" for more
+ * details.
*
* Results:
* Pointer to struct group on success or NULL on error.
@@ -495,6 +229,7 @@ TclpGetGrNam(
#if defined(HAVE_GETGRNAM_R_5)
struct group *grPtr = NULL;
+
return (getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
&grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
@@ -502,7 +237,9 @@ TclpGetGrNam(
return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
#else
+#define NEED_COPYGRP 1
struct group *grPtr;
+
Tcl_MutexLock(&compatLock);
grPtr = getgrnam(name);
if (grPtr != NULL) {
@@ -515,18 +252,18 @@ TclpGetGrNam(
Tcl_MutexUnlock(&compatLock);
return grPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetGrGid --
*
- * Thread-safe wrappers for getgrgid().
- * See "man getgrgid" for more details.
+ * Thread-safe wrappers for getgrgid(). See "man getgrgid" for more
+ * details.
*
* Results:
* Pointer to struct group on success or NULL on error.
@@ -548,6 +285,7 @@ TclpGetGrGid(
#if defined(HAVE_GETGRGID_R_5)
struct group *grPtr = NULL;
+
return (getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
&grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
@@ -555,7 +293,9 @@ TclpGetGrGid(
return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
#else
+#define NEED_COPYGRP 1
struct group *grPtr;
+
Tcl_MutexLock(&compatLock);
grPtr = getgrgid(gid);
if (grPtr != NULL) {
@@ -568,18 +308,18 @@ TclpGetGrGid(
Tcl_MutexUnlock(&compatLock);
return grPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetHostByName --
*
- * Thread-safe wrappers for gethostbyname().
- * See "man gethostbyname" for more details.
+ * Thread-safe wrappers for gethostbyname(). See "man gethostbyname" for
+ * more details.
*
* Results:
* Pointer to struct hostent on success or NULL on error.
@@ -601,47 +341,53 @@ TclpGetHostByName(
#if defined(HAVE_GETHOSTBYNAME_R_5)
int h_errno;
+
return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
sizeof(tsdPtr->hbuf), &h_errno);
#elif defined(HAVE_GETHOSTBYNAME_R_6)
struct hostent *hePtr;
int h_errno;
+
return (gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
- &tsdPtr->hent : NULL;
+ sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0)
+ ? &tsdPtr->hent : NULL;
#elif defined(HAVE_GETHOSTBYNAME_R_3)
struct hostent_data data;
- return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0) ?
- &tsdPtr->hent : NULL;
+
+ return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0)
+ ? &tsdPtr->hent : NULL;
+
#else
+#define NEED_COPYHOSTENT 1
struct hostent *hePtr;
+
Tcl_MutexLock(&compatLock);
hePtr = gethostbyname(name);
if (hePtr != NULL) {
tsdPtr->hent = *hePtr;
hePtr = &tsdPtr->hent;
if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf)) == -1) {
+ sizeof(tsdPtr->hbuf)) == -1) {
hePtr = NULL;
}
}
Tcl_MutexUnlock(&compatLock);
return hePtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetHostByAddr --
*
- * Thread-safe wrappers for gethostbyaddr().
- * See "man gethostbyaddr" for more details.
+ * Thread-safe wrappers for gethostbyaddr(). See "man gethostbyaddr" for
+ * more details.
*
* Results:
* Pointer to struct hostent on success or NULL on error.
@@ -665,30 +411,346 @@ TclpGetHostByAddr(
#if defined(HAVE_GETHOSTBYADDR_R_7)
int h_errno;
+
return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf), &h_errno);
+ sizeof(tsdPtr->hbuf), &h_errno);
#elif defined(HAVE_GETHOSTBYADDR_R_8)
struct hostent *hePtr;
int h_errno;
+
return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
- &tsdPtr->hent : NULL;
+ sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0)
+ ? &tsdPtr->hent : NULL;
#else
+#define NEED_COPYHOSTENT 1
struct hostent *hePtr;
+
Tcl_MutexLock(&compatLock);
hePtr = gethostbyaddr(addr, length, type);
if (hePtr != NULL) {
tsdPtr->hent = *hePtr;
hePtr = &tsdPtr->hent;
if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf)) == -1) {
+ sizeof(tsdPtr->hbuf)) == -1) {
hePtr = NULL;
}
}
Tcl_MutexUnlock(&compatLock);
return hePtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyGrp --
+ *
+ * Copies string fields of the group structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * 0 on success or -1 on error (errno = ERANGE).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYGRP
+#define NEED_COPYARRAY 1
+#define NEED_COPYSTRING 1
+
+static int
+CopyGrp(
+ struct group *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ register char *p = buf;
+ register int copied, len = 0;
+
+ /*
+ * Copy username.
+ */
+
+ copied = CopyString(tgtPtr->gr_name, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ /*
+ * Copy password.
+ */
+
+ copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ /*
+ * Copy group members.
+ */
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
+
+ return 0;
+
+ range:
+ errno = ERANGE;
+ return -1;
+}
+#endif /* NEED_COPYGRP */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyHostent --
+ *
+ * Copies string fields of the hostnent structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * Number of bytes copied on success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYHOSTENT
+#define NEED_COPYSTRING 1
+#define NEED_COPYARRAY 1
+
+static int
+CopyHostent(
+ struct hostent *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ char *p = buf;
+ int copied, len = 0;
+
+ copied = CopyString(tgtPtr->h_name, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
+ len += copied;
+ p += len;
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen-len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
+
+ return 0;
+
+ range:
+ errno = ERANGE;
+ return -1;
+}
+#endif /* NEED_COPYHOSTENT */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyPwd --
+ *
+ * Copies string fields of the passwd structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * 0 on success or -1 on error (errno = ERANGE).
+ *
+ * Side effects:
+ * We are not copying the gecos field as it may not be supported on all
+ * platforms.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYPWD
+#define NEED_COPYSTRING 1
+
+static int
+CopyPwd(
+ struct passwd *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ char *p = buf;
+ int copied, len = 0;
+
+ copied = CopyString(tgtPtr->pw_name, p, buflen - len);
+ if (copied == -1) {
+ range:
+ errno = ERANGE;
+ return -1;
+ }
+ tgtPtr->pw_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_dir = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_shell = (copied > 0) ? p : NULL;
+
+ return 0;
+}
+#endif /* NEED_COPYPWD */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyArray --
+ *
+ * Copies array of NULL-terminated or fixed-length strings to the private
+ * buffer, honouring the size of the buffer.
+ *
+ * Results:
+ * Number of bytes copied on success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYARRAY
+static int
+CopyArray(
+ char **src, /* Array of elements to copy. */
+ int elsize, /* Size of each element, or -1 to indicate
+ * that they are C strings of dynamic
+ * length. */
+ char *buf, /* Buffer to copy into. */
+ int buflen) /* Size of buffer. */
+{
+ int i, j, len = 0;
+ char *p, **new;
+
+ if (src == NULL) {
+ return 0;
+ }
+
+ for (i = 0; src[i] != NULL; i++) {
+ /*
+ * Empty loop to count how many.
+ */
+ }
+ len = sizeof(char *) * (i + 1); /* Leave place for the array. */
+ if (len > buflen) {
+ return -1;
+ }
+
+ new = (char **) buf;
+ p = buf + len;
+
+ for (j = 0; j < i; j++) {
+ int sz = (elsize<0 ? strlen(src[j])+1 : elsize);
+
+ len += sz;
+ if (len > buflen) {
+ return -1;
+ }
+ memcpy(p, src[j], sz);
+ new[j] = p;
+ p = buf + len;
+ }
+ new[j] = NULL;
+
+ return len;
+}
+#endif /* NEED_COPYARRAY */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyString --
+ *
+ * Copies a NULL-terminated string to the private buffer, honouring the
+ * size of the buffer
+ *
+ * Results:
+ * 0 success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYSTRING
+static int
+CopyString(
+ char *src, /* String to copy. */
+ char *buf, /* Buffer to copy into. */
+ int buflen) /* Size of buffer. */
+{
+ int len = 0;
+
+ if (src != NULL) {
+ len = strlen(src) + 1;
+ if (len > buflen) {
+ return -1;
+ }
+ memcpy(buf, src, len);
+ }
+
+ return len;
+}
+#endif /* NEED_COPYSTRING */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */