diff options
Diffstat (limited to 'unix/tclUnixCompat.c')
| -rw-r--r-- | unix/tclUnixCompat.c | 268 | 
1 files changed, 219 insertions, 49 deletions
diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c index 4d959d6..456a552 100644 --- a/unix/tclUnixCompat.c +++ b/unix/tclUnixCompat.c @@ -13,8 +13,10 @@  #include <errno.h>  #include <string.h> -/* See also: SC_BLOCKING_STYLE in unix/tcl.m4 +/* + * See also: SC_BLOCKING_STYLE in unix/tcl.m4   */ +  #ifdef	USE_FIONBIO  #   ifdef HAVE_SYS_FILIO_H  #	include	<sys/filio.h>	/* For FIONBIO. */ @@ -23,39 +25,6 @@  #	include	<sys/ioctl.h>  #   endif  #endif	/* USE_FIONBIO */ - -/* - *--------------------------------------------------------------------------- - * - * TclUnixSetBlockingMode -- - * - *	Set the blocking mode of a file descriptor. - * - * Results: - * - *	0 on success, -1 (with errno set) on error. - * - *--------------------------------------------------------------------------- - */ -int -TclUnixSetBlockingMode( -    int fd,		/* File descriptor */ -    int mode)		/* TCL_MODE_BLOCKING or TCL_MODE_NONBLOCKING */ -{ -#ifndef USE_FIONBIO -    int flags = fcntl(fd, F_GETFL); - -    if (mode == TCL_MODE_BLOCKING) { -	flags &= ~O_NONBLOCK; -    } else { -	flags |= O_NONBLOCK; -    } -    return fcntl(fd, F_SETFL, flags); -#else /* USE_FIONBIO */ -    int state = (mode == TCL_MODE_NONBLOCKING); -    return ioctl(fd, FIONBIO, &state); -#endif /* !USE_FIONBIO */ -}  /*   * Used to pad structures at size'd boundaries @@ -67,10 +36,10 @@ TclUnixSetBlockingMode(   * '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)));	\      }  /* @@ -82,10 +51,22 @@ TclUnixSetBlockingMode(  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; @@ -124,14 +105,57 @@ 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); + +#endif +#ifdef NEED_PW_CLEANER +static void		FreePwBuf(ClientData ignored); +#endif +#ifdef NEED_GR_CLEANER +static void		FreeGrBuf(ClientData ignored);  #endif  #endif /* TCL_THREADS */  /*   *---------------------------------------------------------------------------   * + * TclUnixSetBlockingMode -- + * + *	Set the blocking mode of a file descriptor. + * + * Results: + * + *	0 on success, -1 (with errno set) on error. + * + *--------------------------------------------------------------------------- + */ + +int +TclUnixSetBlockingMode( +    int fd,			/* File descriptor */ +    int mode)			/* Either TCL_MODE_BLOCKING or +				 * TCL_MODE_NONBLOCKING. */ +{ +#ifndef USE_FIONBIO +    int flags = fcntl(fd, F_GETFL); + +    if (mode == TCL_MODE_BLOCKING) { +	flags &= ~O_NONBLOCK; +    } else { +	flags |= O_NONBLOCK; +    } +    return fcntl(fd, F_SETFL, flags); +#else /* USE_FIONBIO */ +    int state = (mode == TCL_MODE_NONBLOCKING); + +    return ioctl(fd, FIONBIO, &state); +#endif /* !USE_FIONBIO */ +} + +/* + *--------------------------------------------------------------------------- + *   * TclpGetPwNam --   *   *      Thread-safe wrappers for getpwnam(). See "man getpwnam" for more @@ -158,8 +182,33 @@ 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; +    /* +     * 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);  #elif defined(HAVE_GETPWNAM_R_4)      return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)); @@ -214,8 +263,33 @@ 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; +    /* +     * 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);  #elif defined(HAVE_GETPWUID_R_4)      return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)); @@ -244,6 +318,29 @@ TclpGetPwUid(  /*   *---------------------------------------------------------------------------   * + * 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 @@ -267,11 +364,36 @@ TclpGetGrNam(  #else      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -#if defined(HAVE_GETGRNAM_R_5) +#ifdef 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; +    /* +     * 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);  #elif defined(HAVE_GETGRNAM_R_4)      return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)); @@ -326,8 +448,33 @@ 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; +    /* +     * 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);  #elif defined(HAVE_GETGRGID_R_4)      return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)); @@ -356,6 +503,29 @@ TclpGetGrGid(  /*   *---------------------------------------------------------------------------   * + * 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 @@ -769,7 +939,7 @@ CopyArray(  #ifdef NEED_COPYSTRING  static int  CopyString( -    CONST char *src,	/* String to copy. */ +    const char *src,		/* String to copy. */      char *buf,			/* Buffer to copy into. */      int buflen)			/* Size of buffer. */  {  | 
