diff options
Diffstat (limited to 'unix/tclUnixCompat.c')
-rw-r--r-- | unix/tclUnixCompat.c | 940 |
1 files changed, 321 insertions, 619 deletions
diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c index 1424ab3..6e2666b 100644 --- a/unix/tclUnixCompat.c +++ b/unix/tclUnixCompat.c @@ -3,163 +3,352 @@ * * 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. */ #include "tclInt.h" +#include "tclPort.h" #include <pwd.h> #include <grp.h> #include <errno.h> #include <string.h> /* - * See also: SC_BLOCKING_STYLE in unix/tcl.m4 - */ - -#ifdef USE_FIONBIO -# ifdef HAVE_SYS_FILIO_H -# include <sys/filio.h> /* For FIONBIO. */ -# endif -# ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -# endif -#endif /* USE_FIONBIO */ - -/* * 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) \ - if (((length) % (size))) { \ - (buffer) += ((size) - ((length) % (size))); \ - (length) += ((size) - ((length) % (size))); \ +#define PadBuffer(buffer, length, size) \ + if (((length) % (size))) { \ + (buffer) += ((size) - ((length) % (size))); \ + (length) += ((size) - ((length) % (size))); \ } /* - * 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; -#if defined(HAVE_GETPWNAM_R_5) || defined(HAVE_GETPWUID_R_5) -#define NEED_PW_CLEANER 1 - char *pbuf; - int pbuflen; -#else char pbuf[2048]; -#endif struct group grp; -#if defined(HAVE_GETGRNAM_R_5) || defined(HAVE_GETGRGID_R_5) -#define NEED_GR_CLEANER 1 - char *gbuf; - int gbuflen; -#else char gbuf[2048]; -#endif #if !defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR) 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; +} + + /* - * Helper function declarations. Note that these are only used if needed and - * only defined if used (via the NEED_* macros). + *--------------------------------------------------------------------------- + * + * 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 + * + *--------------------------------------------------------------------------- */ -#undef NEED_COPYARRAY -#undef NEED_COPYGRP -#undef NEED_COPYHOSTENT -#undef NEED_COPYPWD -#undef NEED_COPYSTRING -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(const char *src, char *buf, int buflen); +static int +CopyString(CONST char *src, char *buf, int buflen) +{ + int len = 0; -#endif + if (src != NULL) { + len += strlen(src) + 1; + if (len > buflen) { + return -1; + } + strcpy(buf, src); + } -#ifdef NEED_PW_CLEANER -static void FreePwBuf(ClientData ignored); -#endif -#ifdef NEED_GR_CLEANER -static void FreeGrBuf(ClientData ignored); -#endif -#endif /* TCL_THREADS */ + 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)) /* *--------------------------------------------------------------------------- * - * TclUnixSetBlockingMode -- + * CopyHostnent -- * - * Set the blocking mode of a file descriptor. + * 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) * - * 0 on success, -1 (with errno set) on error. + * Side effects: + * None * *--------------------------------------------------------------------------- */ -int -TclUnixSetBlockingMode( - int fd, /* File descriptor */ - int mode) /* Either TCL_MODE_BLOCKING or - * TCL_MODE_NONBLOCKING. */ +static int +CopyHostent(struct hostent *tgtPtr, char *buf, int buflen) { -#ifndef USE_FIONBIO - int flags = fcntl(fd, F_GETFL); + char *p = buf; + int copied, len = 0; - if (mode == TCL_MODE_BLOCKING) { - flags &= ~O_NONBLOCK; - } else { - flags |= O_NONBLOCK; + copied = CopyString(tgtPtr->h_name, p, buflen - len); + if (copied == -1) { + range: + errno = ERANGE; + return -1; } - return fcntl(fd, F_SETFL, flags); -#else /* USE_FIONBIO */ - int state = (mode == TCL_MODE_NONBLOCKING); + tgtPtr->h_name = (copied > 0) ? p : NULL; + len += copied; + p = buf + len; - return ioctl(fd, FIONBIO, &state); -#endif /* !USE_FIONBIO */ + 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. + * + *--------------------------------------------------------------------------- + */ + +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 /* !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) */ + +#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. @@ -171,8 +360,7 @@ TclUnixSetBlockingMode( */ struct passwd * -TclpGetPwNam( - const char *name) +TclpGetPwNam(const char *name) { #if !defined(TCL_THREADS) return getpwnam(name); @@ -181,42 +369,14 @@ TclpGetPwNam( #if defined(HAVE_GETPWNAM_R_5) struct passwd *pwPtr = NULL; - - /* - * How to allocate a buffer of the right initial size. If you want the - * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt - * and weep. - */ - - if (tsdPtr->pbuf == NULL) { - tsdPtr->pbuflen = (int) sysconf(_SC_GETPW_R_SIZE_MAX); - if (tsdPtr->pbuflen < 1) { - tsdPtr->pbuflen = 1024; - } - tsdPtr->pbuf = ckalloc(tsdPtr->pbuflen); - Tcl_CreateThreadExitHandler(FreePwBuf, NULL); - } - while (1) { - int e = getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, tsdPtr->pbuflen, - &pwPtr); - - if (e == 0) { - break; - } else if (e != ERANGE) { - return NULL; - } - tsdPtr->pbuflen *= 2; - tsdPtr->pbuf = ckrealloc(tsdPtr->pbuf, tsdPtr->pbuflen); - } - return (pwPtr != NULL ? &tsdPtr->pwd : NULL); + return (getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf), + &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL; #elif defined(HAVE_GETPWNAM_R_4) 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) { @@ -229,18 +389,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. @@ -252,8 +412,7 @@ TclpGetPwNam( */ struct passwd * -TclpGetPwUid( - uid_t uid) +TclpGetPwUid(uid_t uid) { #if !defined(TCL_THREADS) return getpwuid(uid); @@ -262,42 +421,14 @@ TclpGetPwUid( #if defined(HAVE_GETPWUID_R_5) struct passwd *pwPtr = NULL; - - /* - * How to allocate a buffer of the right initial size. If you want the - * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt - * and weep. - */ - - if (tsdPtr->pbuf == NULL) { - tsdPtr->pbuflen = (int) sysconf(_SC_GETPW_R_SIZE_MAX); - if (tsdPtr->pbuflen < 1) { - tsdPtr->pbuflen = 1024; - } - tsdPtr->pbuf = ckalloc(tsdPtr->pbuflen); - Tcl_CreateThreadExitHandler(FreePwBuf, NULL); - } - while (1) { - int e = getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, tsdPtr->pbuflen, - &pwPtr); - - if (e == 0) { - break; - } else if (e != ERANGE) { - return NULL; - } - tsdPtr->pbuflen *= 2; - tsdPtr->pbuf = ckrealloc(tsdPtr->pbuf, tsdPtr->pbuflen); - } - return (pwPtr != NULL ? &tsdPtr->pwd : NULL); + return (getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf), + &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL; #elif defined(HAVE_GETPWUID_R_4) 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) { @@ -310,41 +441,18 @@ TclpGetPwUid( Tcl_MutexUnlock(&compatLock); return pwPtr; #endif - - return NULL; /* Not reached. */ + return NULL; /* Not reached */ #endif /* TCL_THREADS */ } - -/* - *--------------------------------------------------------------------------- - * - * FreePwBuf -- - * - * Helper that is used to dispose of space allocated and referenced from - * the ThreadSpecificData for user entries. (Darn that baroque POSIX - * reentrant interface.) - * - *--------------------------------------------------------------------------- - */ - -#ifdef NEED_PW_CLEANER -static void -FreePwBuf( - ClientData ignored) -{ - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - ckfree(tsdPtr->pbuf); -} -#endif /* NEED_PW_CLEANER */ /* *--------------------------------------------------------------------------- * * 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. @@ -356,52 +464,23 @@ FreePwBuf( */ struct group * -TclpGetGrNam( - const char *name) +TclpGetGrNam(const char *name) { #if !defined(TCL_THREADS) return getgrnam(name); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -#ifdef HAVE_GETGRNAM_R_5 +#if defined(HAVE_GETGRNAM_R_5) struct group *grPtr = NULL; - - /* - * How to allocate a buffer of the right initial size. If you want the - * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt - * and weep. - */ - - if (tsdPtr->gbuf == NULL) { - tsdPtr->gbuflen = (int) sysconf(_SC_GETGR_R_SIZE_MAX); - if (tsdPtr->gbuflen < 1) { - tsdPtr->gbuflen = 1024; - } - tsdPtr->gbuf = ckalloc(tsdPtr->gbuflen); - Tcl_CreateThreadExitHandler(FreeGrBuf, NULL); - } - while (1) { - int e = getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, tsdPtr->gbuflen, - &grPtr); - - if (e == 0) { - break; - } else if (e != ERANGE) { - return NULL; - } - tsdPtr->gbuflen *= 2; - tsdPtr->gbuf = ckrealloc(tsdPtr->gbuf, tsdPtr->gbuflen); - } - return (grPtr != NULL ? &tsdPtr->grp : NULL); + return (getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf), + &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL; #elif defined(HAVE_GETGRNAM_R_4) 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) { @@ -414,18 +493,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. @@ -437,8 +516,7 @@ TclpGetGrNam( */ struct group * -TclpGetGrGid( - gid_t gid) +TclpGetGrGid(gid_t gid) { #if !defined(TCL_THREADS) return getgrgid(gid); @@ -447,42 +525,14 @@ TclpGetGrGid( #if defined(HAVE_GETGRGID_R_5) struct group *grPtr = NULL; - - /* - * How to allocate a buffer of the right initial size. If you want the - * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt - * and weep. - */ - - if (tsdPtr->gbuf == NULL) { - tsdPtr->gbuflen = (int) sysconf(_SC_GETGR_R_SIZE_MAX); - if (tsdPtr->gbuflen < 1) { - tsdPtr->gbuflen = 1024; - } - tsdPtr->gbuf = ckalloc(tsdPtr->gbuflen); - Tcl_CreateThreadExitHandler(FreeGrBuf, NULL); - } - while (1) { - int e = getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, tsdPtr->gbuflen, - &grPtr); - - if (e == 0) { - break; - } else if (e != ERANGE) { - return NULL; - } - tsdPtr->gbuflen *= 2; - tsdPtr->gbuf = ckrealloc(tsdPtr->gbuf, tsdPtr->gbuflen); - } - return (grPtr != NULL ? &tsdPtr->grp : NULL); + return (getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf), + &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL; #elif defined(HAVE_GETGRGID_R_4) 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) { @@ -495,41 +545,18 @@ TclpGetGrGid( Tcl_MutexUnlock(&compatLock); return grPtr; #endif - - return NULL; /* Not reached. */ + return NULL; /* Not reached */ #endif /* TCL_THREADS */ } - -/* - *--------------------------------------------------------------------------- - * - * FreeGrBuf -- - * - * Helper that is used to dispose of space allocated and referenced from - * the ThreadSpecificData for group entries. (Darn that baroque POSIX - * reentrant interface.) - * - *--------------------------------------------------------------------------- - */ - -#ifdef NEED_GR_CLEANER -static void -FreeGrBuf( - ClientData ignored) -{ - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - ckfree(tsdPtr->gbuf); -} -#endif /* NEED_GR_CLEANER */ /* *--------------------------------------------------------------------------- * * 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. @@ -541,8 +568,7 @@ FreeGrBuf( */ struct hostent * -TclpGetHostByName( - const char *name) +TclpGetHostByName(const char *name) { #if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME) return gethostbyname(name); @@ -551,53 +577,48 @@ 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 = NULL; - int h_errno, result; + struct hostent *hePtr; + int result, h_errno; result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf, - sizeof(tsdPtr->hbuf), &hePtr, &h_errno); + sizeof(tsdPtr->hbuf), &hePtr, &h_errno); return (result == 0) ? hePtr : 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. @@ -609,10 +630,7 @@ TclpGetHostByName( */ struct hostent * -TclpGetHostByAddr( - const char *addr, - int length, - int type) +TclpGetHostByAddr(const char *addr, int length, int type) { #if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR) return gethostbyaddr(addr, length, type); @@ -621,349 +639,33 @@ 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 ? (int) 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( - const 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: - */ /* *------------------------------------------------------------------------ @@ -973,8 +675,7 @@ CopyString( * Get CPU ID information on an Intel box under UNIX (either Linux or Cygwin) * * Results: - * Returns TCL_OK if successful, TCL_ERROR if CPUID is not supported or - * fails. + * Returns TCL_OK if successful, TCL_ERROR if CPUID is not supported. * * Side effects: * If successful, stores EAX, EBX, ECX and EDX registers after the CPUID @@ -990,6 +691,7 @@ TclWinCPUID( { int status = TCL_ERROR; + /* See: <http://en.wikipedia.org/wiki/CPUID> */ #if defined(HAVE_CPUID) __asm__ __volatile__("mov %%ebx, %%edi \n\t" /* save %ebx */ "cpuid \n\t" |