diff options
Diffstat (limited to 'unix/tclUnixCompat.c')
-rw-r--r-- | unix/tclUnixCompat.c | 730 |
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: + */ |