diff options
Diffstat (limited to 'unix')
-rw-r--r-- | unix/Makefile.in | 10 | ||||
-rwxr-xr-x | unix/configure | 5 | ||||
-rw-r--r-- | unix/configure.ac | 1 | ||||
-rw-r--r-- | unix/dltest/pkga.c | 2 | ||||
-rw-r--r-- | unix/dltest/pkgc.c | 4 | ||||
-rw-r--r-- | unix/dltest/pkgd.c | 4 | ||||
-rw-r--r-- | unix/dltest/pkge.c | 2 | ||||
-rw-r--r-- | unix/dltest/pkgooa.c | 2 | ||||
-rw-r--r-- | unix/dltest/pkgua.c | 2 | ||||
-rw-r--r-- | unix/tcl.m4 | 4 | ||||
-rw-r--r-- | unix/tclConfig.h.in | 3 | ||||
-rw-r--r-- | unix/tclUnixCompat.c | 4 | ||||
-rw-r--r-- | unix/tclUnixFCmd.c | 28 | ||||
-rw-r--r-- | unix/tclUnixFile.c | 15 | ||||
-rw-r--r-- | unix/tclUnixInit.c | 11 | ||||
-rw-r--r-- | unix/tclUnixNotfy.c | 8 | ||||
-rw-r--r-- | unix/tclUnixSock.c | 402 | ||||
-rw-r--r-- | unix/tclUnixThrd.c | 14 | ||||
-rw-r--r-- | unix/tclUnixTime.c | 9 | ||||
-rw-r--r-- | unix/tclXtTest.c | 2 |
20 files changed, 336 insertions, 196 deletions
diff --git a/unix/Makefile.in b/unix/Makefile.in index eb083e0..c4f6136 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -320,7 +320,7 @@ TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \ bn_mp_cnt_lsb.o bn_mp_copy.o \ bn_mp_count_bits.o bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o \ bn_mp_div_2d.o bn_mp_div_3.o \ - bn_mp_exch.o bn_mp_expt_d.o bn_mp_grow.o bn_mp_init.o \ + bn_mp_exch.o bn_mp_expt_d.o bn_mp_expt_d_ex.o bn_mp_grow.o bn_mp_init.o \ bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \ bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_karatsuba_mul.o \ bn_mp_karatsuba_sqr.o \ @@ -503,6 +503,7 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_div_3.c \ $(TOMMATH_DIR)/bn_mp_exch.c \ $(TOMMATH_DIR)/bn_mp_expt_d.c \ + $(TOMMATH_DIR)/bn_mp_expt_d_ex.c \ $(TOMMATH_DIR)/bn_mp_grow.c \ $(TOMMATH_DIR)/bn_mp_init.c \ $(TOMMATH_DIR)/bn_mp_init_copy.c \ @@ -840,8 +841,8 @@ install-libraries: libraries do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \ done; - @echo "Installing package http 2.8.9 as a Tcl Module"; - @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.9.tm; + @echo "Installing package http 2.8.10 as a Tcl Module"; + @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.10.tm; @echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/"; @for i in $(TOP_DIR)/library/opt/*.tcl ; \ do \ @@ -1420,6 +1421,9 @@ bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c $(MATHHDRS) bn_mp_expt_d.o: $(TOMMATH_DIR)/bn_mp_expt_d.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_d.c +bn_mp_expt_d_ex.o: $(TOMMATH_DIR)/bn_mp_expt_d_ex.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_d_ex.c + bn_mp_grow.o: $(TOMMATH_DIR)/bn_mp_grow.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_grow.c diff --git a/unix/configure b/unix/configure index 068503c..8a1891c 100755 --- a/unix/configure +++ b/unix/configure @@ -5038,7 +5038,7 @@ fi if test "$GCC" = yes; then : CFLAGS_OPTIMIZE=-O2 - CFLAGS_WARNING="-Wall -Wsign-compare -Wdeclaration-after-statement" + CFLAGS_WARNING="-Wall -Wwrite-strings -Wsign-compare -Wdeclaration-after-statement" else @@ -6910,9 +6910,6 @@ $as_echo "enabled $tcl_ok debugging" >&6; } -$as_echo "#define TCL_TOMMATH 1" >>confdefs.h - - $as_echo "#define MP_PREC 4" >>confdefs.h diff --git a/unix/configure.ac b/unix/configure.ac index 41a1f62..bafb970 100644 --- a/unix/configure.ac +++ b/unix/configure.ac @@ -182,7 +182,6 @@ SC_CONFIG_CFLAGS SC_ENABLE_SYMBOLS(bccdebug) -AC_DEFINE(TCL_TOMMATH, 1, [Build libtommath?]) AC_DEFINE(MP_PREC, 4, [Default libtommath precision.]) #-------------------------------------------------------------------- diff --git a/unix/dltest/pkga.c b/unix/dltest/pkga.c index 2aee1b8..5bf3c1e 100644 --- a/unix/dltest/pkga.c +++ b/unix/dltest/pkga.c @@ -123,7 +123,7 @@ Pkga_Init( { int code; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvide(interp, "Pkga", "1.0"); diff --git a/unix/dltest/pkgc.c b/unix/dltest/pkgc.c index 48e4d2a..983fcf3 100644 --- a/unix/dltest/pkgc.c +++ b/unix/dltest/pkgc.c @@ -113,7 +113,7 @@ Pkgc_Init( { int code; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2"); @@ -150,7 +150,7 @@ Pkgc_SafeInit( { int code; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2"); diff --git a/unix/dltest/pkgd.c b/unix/dltest/pkgd.c index df7bbc9..c708df0 100644 --- a/unix/dltest/pkgd.c +++ b/unix/dltest/pkgd.c @@ -113,7 +113,7 @@ Pkgd_Init( { int code; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvide(interp, "Pkgd", "7.3"); @@ -150,7 +150,7 @@ Pkgd_SafeInit( { int code; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvide(interp, "Pkgd", "7.3"); diff --git a/unix/dltest/pkge.c b/unix/dltest/pkge.c index 7160d90..f46ca74 100644 --- a/unix/dltest/pkge.c +++ b/unix/dltest/pkge.c @@ -38,7 +38,7 @@ Pkge_Init( { static const char script[] = "if 44 {open non_existent}"; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } return Tcl_EvalEx(interp, script, -1, 0); diff --git a/unix/dltest/pkgooa.c b/unix/dltest/pkgooa.c index 78af376..5a0b0ef 100644 --- a/unix/dltest/pkgooa.c +++ b/unix/dltest/pkgooa.c @@ -96,7 +96,7 @@ Pkgooa_Init( * This worked in Tcl 8.6.0, and is expected * to keep working in all future Tcl 8.x releases. */ - if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } if (tclStubsPtr == NULL) { diff --git a/unix/dltest/pkgua.c b/unix/dltest/pkgua.c index 8634a5e..9d5a9d9 100644 --- a/unix/dltest/pkgua.c +++ b/unix/dltest/pkgua.c @@ -199,7 +199,7 @@ Pkgua_Init( int code, cmdIndex = 0; Tcl_Command *cmdTokens; - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } diff --git a/unix/tcl.m4 b/unix/tcl.m4 index f2827c6..47bfbf3 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1096,7 +1096,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ CFLAGS_DEBUG=-g AS_IF([test "$GCC" = yes], [ CFLAGS_OPTIMIZE=-O2 - CFLAGS_WARNING="-Wall -Wsign-compare -Wdeclaration-after-statement" + CFLAGS_WARNING="-Wall -Wwrite-strings -Wsign-compare -Wdeclaration-after-statement" ], [ CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" @@ -2709,7 +2709,7 @@ AC_DEFUN([SC_TCL_CFG_ENCODING], [ # advancedTest - the advanced test to run if the function is present # # Results: -# Might cause compatability versions of the function to be used. +# Might cause compatibility versions of the function to be used. # Might affect the following vars: # USE_COMPAT (implicit) # diff --git a/unix/tclConfig.h.in b/unix/tclConfig.h.in index 6c2f47d..88e03aa 100644 --- a/unix/tclConfig.h.in +++ b/unix/tclConfig.h.in @@ -400,9 +400,6 @@ /* Are we building with threads enabled? */ #undef TCL_THREADS -/* Build libtommath? */ -#undef TCL_TOMMATH - /* Do we allow unloading of shared libraries? */ #undef TCL_UNLOAD_DLLS diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c index 1247061..ea6067e 100644 --- a/unix/tclUnixCompat.c +++ b/unix/tclUnixCompat.c @@ -988,8 +988,8 @@ CopyString( int TclWinCPUID( - unsigned int index, /* Which CPUID value to retrieve. */ - unsigned int *regsPtr) /* Registers after the CPUID. */ + int index, /* Which CPUID value to retrieve. */ + int *regsPtr) /* Registers after the CPUID. */ { int status = TCL_ERROR; diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 4d38f8e..e156f77 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -1507,11 +1507,10 @@ SetGroupAttribute( Tcl_DString ds; struct group *groupPtr = NULL; const char *string; - int length; - string = TclGetStringFromObj(attributePtr, &length); + string = TclGetString(attributePtr); - native = Tcl_UtfToExternalDString(NULL, string, length, &ds); + native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds); groupPtr = TclpGetGrNam(native); /* INTL: Native. */ Tcl_DStringFree(&ds); @@ -1574,11 +1573,10 @@ SetOwnerAttribute( Tcl_DString ds; struct passwd *pwPtr = NULL; const char *string; - int length; - string = TclGetStringFromObj(attributePtr, &length); + string = TclGetString(attributePtr); - native = Tcl_UtfToExternalDString(NULL, string, length, &ds); + native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds); pwPtr = TclpGetPwNam(native); /* INTL: Native. */ Tcl_DStringFree(&ds); @@ -1946,9 +1944,9 @@ TclpObjNormalizePath( int nextCheckpoint) { const char *currentPathEndPosition; - int pathLen; char cur; - const char *path = TclGetStringFromObj(pathPtr, &pathLen); + const char *path = TclGetString(pathPtr); + size_t pathLen = pathPtr->length; Tcl_DString ds; const char *nativePath; #ifndef NO_REALPATH @@ -2177,15 +2175,15 @@ TclUnixOpenTemporaryFile( { Tcl_DString template, tmp; const char *string; - int len, fd; + int fd; /* * We should also check against making more then TMP_MAX of these. */ if (dirObj) { - string = TclGetStringFromObj(dirObj, &len); - Tcl_UtfToExternalDString(NULL, string, len, &template); + string = TclGetString(dirObj); + Tcl_UtfToExternalDString(NULL, string, dirObj->length, &template); } else { Tcl_DStringInit(&template); Tcl_DStringAppend(&template, DefaultTempDir(), -1); /* INTL: native */ @@ -2194,8 +2192,8 @@ TclUnixOpenTemporaryFile( TclDStringAppendLiteral(&template, "/"); if (basenameObj) { - string = TclGetStringFromObj(basenameObj, &len); - Tcl_UtfToExternalDString(NULL, string, len, &tmp); + string = TclGetString(basenameObj); + Tcl_UtfToExternalDString(NULL, string, basenameObj->length, &tmp); TclDStringAppendDString(&template, &tmp); Tcl_DStringFree(&tmp); } else { @@ -2206,8 +2204,8 @@ TclUnixOpenTemporaryFile( #ifdef HAVE_MKSTEMPS if (extensionObj) { - string = TclGetStringFromObj(extensionObj, &len); - Tcl_UtfToExternalDString(NULL, string, len, &tmp); + string = TclGetString(extensionObj); + Tcl_UtfToExternalDString(NULL, string, extensionObj->length, &tmp); TclDStringAppendDString(&template, &tmp); fd = mkstemps(Tcl_DStringValue(&template), Tcl_DStringLength(&tmp)); Tcl_DStringFree(&tmp); diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 886b5ad..5f5bfe0 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -262,14 +262,15 @@ TclpMatchInDirectory( DIR *d; Tcl_DirEntry *entryPtr; const char *dirName; - int dirLength, nativeDirLen; + size_t dirLength, nativeDirLen; int matchHidden, matchHiddenPat; Tcl_StatBuf statBuf; Tcl_DString ds; /* native encoding of dir */ Tcl_DString dsOrig; /* utf-8 encoding of dir */ Tcl_DStringInit(&dsOrig); - dirName = TclGetStringFromObj(fileNamePtr, &dirLength); + dirName = TclGetString(fileNamePtr); + dirLength = fileNamePtr->length; Tcl_DStringAppend(&dsOrig, dirName, dirLength); /* @@ -937,7 +938,6 @@ TclpObjLink( */ if (linkAction & TCL_CREATE_SYMBOLIC_LINK) { - int targetLen; Tcl_DString ds; Tcl_Obj *transPtr; @@ -951,8 +951,8 @@ TclpObjLink( if (transPtr == NULL) { return NULL; } - target = TclGetStringFromObj(transPtr, &targetLen); - target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds); + target = TclGetString(transPtr); + target = Tcl_UtfToExternalDString(NULL, target, transPtr->length, &ds); Tcl_DecrRefCount(transPtr); if (symlink(target, src) != 0) { @@ -1080,7 +1080,7 @@ TclNativeCreateNativeRep( const char *str; Tcl_DString ds; Tcl_Obj *validPathPtr; - int len; + size_t len; if (TclFSCwdIsNative()) { /* @@ -1105,7 +1105,8 @@ TclNativeCreateNativeRep( Tcl_IncrRefCount(validPathPtr); } - str = TclGetStringFromObj(validPathPtr, &len); + str = TclGetString(validPathPtr); + len = validPathPtr->length; Tcl_UtfToExternalDString(NULL, str, len, &ds); len = Tcl_DStringLength(&ds) + sizeof(char); if (strlen(Tcl_DStringValue(&ds)) < len - sizeof(char)) { diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index 91fb986..1e35b92 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -453,7 +453,7 @@ TclpInitPlatform(void) void TclpInitLibraryPath( char **valuePtr, - int *lengthPtr, + size_t *lengthPtr, Tcl_Encoding *encodingPtr) { #define LIBRARY_SIZE 32 @@ -542,9 +542,10 @@ TclpInitLibraryPath( Tcl_DStringFree(&buffer); *encodingPtr = Tcl_GetEncoding(NULL, NULL); - str = TclGetStringFromObj(pathPtr, lengthPtr); - *valuePtr = ckalloc((*lengthPtr) + 1); - memcpy(*valuePtr, str, (size_t)(*lengthPtr)+1); + str = TclGetString(pathPtr); + *lengthPtr = pathPtr->length; + *valuePtr = ckalloc(*lengthPtr + 1); + memcpy(*valuePtr, str, *lengthPtr + 1); Tcl_DecrRefCount(pathPtr); } @@ -761,7 +762,7 @@ TclpSetVariables( CFLocaleRef localeRef; - if (CFLocaleCopyCurrent != NULL && CFLocaleGetIdentifier != NULL && + if (&CFLocaleCopyCurrent != NULL && &CFLocaleGetIdentifier != NULL && (localeRef = CFLocaleCopyCurrent())) { CFStringRef locale = CFLocaleGetIdentifier(localeRef); diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index 6ed9443..495632c 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -153,8 +153,8 @@ static int triggerPipe = -1; * The notifierMutex locks access to all of the global notifier state. */ -pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER; /* * The following static indicates if the notifier thread is running. * @@ -196,7 +196,7 @@ static Tcl_ThreadId notifierThread; */ #ifdef TCL_THREADS -static void NotifierThreadProc(ClientData clientData); +static TCL_NORETURN void NotifierThreadProc(ClientData clientData); #if defined(HAVE_PTHREAD_ATFORK) static int atForkInit = 0; static void AtForkChild(void); @@ -1172,7 +1172,7 @@ Tcl_WaitForEvent( *---------------------------------------------------------------------- */ -static void +static TCL_NORETURN void NotifierThreadProc( ClientData clientData) /* Not used. */ { diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 8167077..b404080 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -19,6 +19,7 @@ #define SET_BITS(var, bits) ((var) |= (bits)) #define CLEAR_BITS(var, bits) ((var) &= ~(bits)) +#define GOT_BITS(var, bits) (((var) & (bits)) != 0) /* "sock" + a pointer in hex + \0 */ #define SOCK_CHAN_LENGTH (4 + sizeof(void *) * 2 + 1) @@ -52,6 +53,8 @@ typedef struct TcpFdList { struct TcpState { Tcl_Channel channel; /* Channel associated with this file. */ + int testFlags; /* bit field for tests. Is set by testsocket + * test procedure */ TcpFdList fds; /* The file descriptors of the sockets. */ int flags; /* ORed combination of the bitfields defined * below. */ @@ -93,6 +96,15 @@ struct TcpState { #define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */ /* + * These bits may be ORed together into the "testFlags" field of a TcpState + * structure. + */ + +#define TCP_ASYNC_TEST_MODE (1<<0) /* Async testing activated. Do not + * automatically continue connection + * process. */ + +/* * The following defines the maximum length of the listen queue. This is the * number of outstanding yet-to-be-serviced requests for a connection on a * server socket, more than this number of outstanding requests and the @@ -117,8 +129,7 @@ struct TcpState { * Static routines for this file: */ -static int TcpConnect(Tcl_Interp *interp, - TcpState *state); +static int TcpConnect(Tcl_Interp *interp, TcpState *state); static void TcpAccept(ClientData data, int mask); static int TcpBlockModeProc(ClientData data, int mode); static int TcpCloseProc(ClientData instanceData, @@ -173,21 +184,24 @@ static ProcessGlobalValue hostName = #if 0 /* printf debugging */ -void printaddrinfo(struct addrinfo *addrlist, char *prefix) +void +printaddrinfo( + struct addrinfo *addrlist, + char *prefix) { char host[NI_MAXHOST], port[NI_MAXSERV]; struct addrinfo *ai; + for (ai = addrlist; ai != NULL; ai = ai->ai_next) { getnameinfo(ai->ai_addr, ai->ai_addrlen, - host, sizeof(host), - port, sizeof(port), - NI_NUMERICHOST|NI_NUMERICSERV); + host, sizeof(host), port, sizeof(port), + NI_NUMERICHOST|NI_NUMERICSERV); fprintf(stderr,"%s: %s:%s\n", prefix, host, port); } } #endif /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * InitializeHostName -- * @@ -197,13 +211,13 @@ void printaddrinfo(struct addrinfo *addrlist, char *prefix) * Results: * None. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ static void InitializeHostName( char **valuePtr, - int *lengthPtr, + size_t *lengthPtr, Tcl_Encoding *encodingPtr) { const char *native = NULL; @@ -240,7 +254,7 @@ InitializeHostName( } } if (native == NULL) { - native = tclEmptyStringRep; + native = &tclEmptyString; } #else /* !NO_UNAME */ /* @@ -271,12 +285,12 @@ InitializeHostName( *encodingPtr = Tcl_GetEncoding(NULL, NULL); *lengthPtr = strlen(native); - *valuePtr = ckalloc((*lengthPtr) + 1); - memcpy(*valuePtr, native, (size_t)(*lengthPtr)+1); + *valuePtr = ckalloc(*lengthPtr + 1); + memcpy(*valuePtr, native, *lengthPtr + 1); } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * Tcl_GetHostName -- * @@ -290,7 +304,7 @@ InitializeHostName( * Side effects: * Caches the name to return for future calls. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ const char * @@ -300,7 +314,7 @@ Tcl_GetHostName(void) } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TclpHasSockets -- * @@ -312,7 +326,7 @@ Tcl_GetHostName(void) * Side effects: * None. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ int @@ -323,7 +337,7 @@ TclpHasSockets( } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TclpFinalizeSockets -- * @@ -335,7 +349,7 @@ TclpHasSockets( * Side effects: * None. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ void @@ -345,7 +359,7 @@ TclpFinalizeSockets(void) } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TcpBlockModeProc -- * @@ -358,7 +372,7 @@ TclpFinalizeSockets(void) * Side effects: * Sets the device into blocking or nonblocking mode. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ /* ARGSUSED */ @@ -376,7 +390,7 @@ TcpBlockModeProc( } else { SET_BITS(statePtr->flags, TCP_NONBLOCKING); } - if (statePtr->flags & TCP_ASYNC_CONNECT) { + if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) { statePtr->cachedBlocking = mode; return 0; } @@ -387,33 +401,32 @@ TcpBlockModeProc( } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * WaitForConnect -- * - * Check the state of an async connect process. If a connection - * attempt terminated, process it, which may finalize it or may - * start the next attempt. If a connect error occures, it is saved - * in statePtr->connectError to be reported by 'fconfigure -error'. + * Check the state of an async connect process. If a connection attempt + * terminated, process it, which may finalize it or may start the next + * attempt. If a connect error occures, it is saved in + * statePtr->connectError to be reported by 'fconfigure -error'. * * There are two modes of operation, defined by errorCodePtr: - * * non-NULL: Called by explicite read/write command. block if + * * non-NULL: Called by explicite read/write command. Blocks if the * socket is blocking. * May return two error codes: * * EWOULDBLOCK: if connect is still in progress - * * ENOTCONN: if connect failed. This would be the error - * message of a rect or sendto syscall so this is - * emulated here. - * * NULL: Called by a backround operation. Do not block and - * don't return any error code. + * * ENOTCONN: if connect failed. This would be the error message + * of a rect or sendto syscall so this is emulated here. + * * NULL: Called by a backround operation. Do not block and do not + * return any error code. * * Results: - * 0 if the connection has completed, -1 if still in progress - * or there is an error. + * 0 if the connection has completed, -1 if still in progress or there is + * an error. * * Side effects: - * Processes socket events off the system queue. - * May process asynchroneous connect. + * Processes socket events off the system queue. May process + * asynchroneous connects. * *---------------------------------------------------------------------- */ @@ -426,11 +439,11 @@ WaitForConnect( int timeout; /* - * Check if an async connect failed already and error reporting is demanded, - * return the error ENOTCONN + * Check if an async connect failed already and error reporting is + * demanded, return the error ENOTCONN */ - if (errorCodePtr != NULL && (statePtr->flags & TCP_ASYNC_FAILED)) { + if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) { *errorCodePtr = ENOTCONN; return -1; } @@ -439,26 +452,43 @@ WaitForConnect( * Check if an async connect is running. If not return ok */ - if (!(statePtr->flags & TCP_ASYNC_PENDING)) { + if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) { return 0; } - if (errorCodePtr == NULL || (statePtr->flags & TCP_NONBLOCKING)) { + /* + * In socket test mode do not continue with the connect. + * Exceptions are: + * - Call by recv/send and blocking socket + * (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING)) + */ + + if (GOT_BITS(statePtr->testFlags, TCP_ASYNC_TEST_MODE) + && !(errorCodePtr != NULL + && !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) { + *errorCodePtr = EWOULDBLOCK; + return -1; + } + + if (errorCodePtr == NULL || GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) { timeout = 0; } else { timeout = -1; } do { if (TclUnixWaitForFile(statePtr->fds.fd, - TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) { + TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) { TcpConnect(NULL, statePtr); } - /* Do this only once in the nonblocking case and repeat it until the - * socket is final when blocking */ - } while (timeout == -1 && statePtr->flags & TCP_ASYNC_CONNECT); + + /* + * Do this only once in the nonblocking case and repeat it until the + * socket is final when blocking. + */ + } while (timeout == -1 && GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)); if (errorCodePtr != NULL) { - if (statePtr->flags & TCP_ASYNC_PENDING) { + if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) { *errorCodePtr = EAGAIN; return -1; } else if (statePtr->connectError != 0) { @@ -615,6 +645,7 @@ TcpCloseProc( fds = statePtr->fds.next; while (fds != NULL) { TcpFdList *next = fds->next; + ckfree(fds); fds = next; } @@ -685,10 +716,9 @@ TcpClose2Proc( * * TcpHostPortList -- * - * This function is called by the -gethostname and -getpeername - * switches of TcpGetOptionProc() to add three list elements - * with the textual representation of the given address to the - * given DString. + * This function is called by the -gethostname and -getpeername switches + * of TcpGetOptionProc() to add three list elements with the textual + * representation of the given address to the given DString. * * Results: * None. @@ -709,22 +739,22 @@ TcpHostPortList( char host[NI_MAXHOST], nhost[NI_MAXHOST], nport[NI_MAXSERV]; int flags = 0; - getnameinfo(&addr.sa, salen, - nhost, sizeof(nhost), nport, sizeof(nport), - NI_NUMERICHOST | NI_NUMERICSERV); + getnameinfo(&addr.sa, salen, nhost, sizeof(nhost), nport, sizeof(nport), + NI_NUMERICHOST | NI_NUMERICSERV); Tcl_DStringAppendElement(dsPtr, nhost); + /* - * We don't want to resolve INADDR_ANY and sin6addr_any; they - * can sometimes cause problems (and never have a name). + * We don't want to resolve INADDR_ANY and sin6addr_any; they can + * sometimes cause problems (and never have a name). */ + if (addr.sa.sa_family == AF_INET) { if (addr.sa4.sin_addr.s_addr == INADDR_ANY) { flags |= NI_NUMERICHOST; } #ifndef NEED_FAKE_RFC2553 } else if (addr.sa.sa_family == AF_INET6) { - if ((IN6_ARE_ADDR_EQUAL(&addr.sa6.sin6_addr, - &in6addr_any)) + if ((IN6_ARE_ADDR_EQUAL(&addr.sa6.sin6_addr, &in6addr_any)) || (IN6_IS_ADDR_V4MAPPED(&addr.sa6.sin6_addr) && addr.sa6.sin6_addr.s6_addr[12] == 0 && addr.sa6.sin6_addr.s6_addr[13] == 0 && @@ -734,15 +764,27 @@ TcpHostPortList( } #endif /* NEED_FAKE_RFC2553 */ } - /* Check if reverse DNS has been switched off globally */ - if (interp != NULL && Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) { + + /* + * Check if reverse DNS has been switched off globally. + */ + + if (interp != NULL && + Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) { flags |= NI_NUMERICHOST; } - if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0, flags) == 0) { - /* Reverse mapping worked */ + if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0, + flags) == 0) { + /* + * Reverse mapping worked. + */ + Tcl_DStringAppendElement(dsPtr, host); } else { - /* Reverse mappong failed - use the numeric rep once more */ + /* + * Reverse mapping failed - use the numeric rep once more. + */ + Tcl_DStringAppendElement(dsPtr, nhost); } Tcl_DStringAppendElement(dsPtr, nport); @@ -792,16 +834,20 @@ TcpGetOptionProc( (strncmp(optionName, "-error", len) == 0)) { socklen_t optlen = sizeof(int); - if (statePtr->flags & TCP_ASYNC_CONNECT) { - /* Suppress errors as long as we are not done */ + if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) { + /* + * Suppress errors as long as we are not done. + */ + errno = 0; } else if (statePtr->connectError != 0) { errno = statePtr->connectError; statePtr->connectError = 0; } else { int err; - getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, - (char *) &err, &optlen); + + getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err, + &optlen); errno = err; } if (errno != 0) { @@ -812,9 +858,8 @@ TcpGetOptionProc( if ((len > 1) && (optionName[1] == 'c') && (strncmp(optionName, "-connecting", len) == 0)) { - Tcl_DStringAppend(dsPtr, - (statePtr->flags & TCP_ASYNC_CONNECT) ? "1" : "0", -1); + GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", -1); return TCL_OK; } @@ -823,10 +868,11 @@ TcpGetOptionProc( address peername; socklen_t size = sizeof(peername); - if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) { + if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) { /* * In async connect output an empty string */ + if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-peername"); Tcl_DStringAppendElement(dsPtr, ""); @@ -837,6 +883,7 @@ TcpGetOptionProc( /* * Peername fetch succeeded - output list */ + if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-peername"); Tcl_DStringStartSublist(dsPtr); @@ -876,11 +923,12 @@ TcpGetOptionProc( Tcl_DStringAppendElement(dsPtr, "-sockname"); Tcl_DStringStartSublist(dsPtr); } - if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) { + if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) { /* * In async connect output an empty string */ - found = 1; + + found = 1; } else { for (fds = &statePtr->fds; fds != NULL; fds = fds->next) { size = sizeof(sockname); @@ -905,14 +953,15 @@ TcpGetOptionProc( } if (len > 0) { - return Tcl_BadChannelOption(interp, optionName, "connecting peername sockname"); + return Tcl_BadChannelOption(interp, optionName, + "connecting peername sockname"); } return TCL_OK; } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TcpWatchProc -- * @@ -925,7 +974,7 @@ TcpGetOptionProc( * Sets up the notifier so that a future event on the channel will be * seen by Tcl. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ static void @@ -938,17 +987,17 @@ WrapNotify( if (newmask == 0) { /* - * There was no overlap between the states the channel is - * interested in notifications for, and the states that are - * reported present on the file descriptor by select(). The - * only way that can happen is when the channel is interested - * in a writable condition, and only a readable state is reported - * present (see TcpWatchProc() below). In that case, signal back - * to the caller the writable state, which is really an error - * condition. As an extra check on that assumption, check for - * a non-zero value of errno before reporting an artificial + * There was no overlap between the states the channel is interested + * in notifications for, and the states that are reported present on + * the file descriptor by select(). The only way that can happen is + * when the channel is interested in a writable condition, and only a + * readable state is reported present (see TcpWatchProc() below). In + * that case, signal back to the caller the writable state, which is + * really an error condition. As an extra check on that assumption, + * check for a non-zero value of errno before reporting an artificial * writable state. */ + if (errno == 0) { return; } @@ -972,33 +1021,36 @@ TcpWatchProc( * be readable or writable at the Tcl level. This keeps Tcl scripts * from interfering with the -accept behavior (bug #3394732). */ + return; } - if (statePtr->flags & TCP_ASYNC_PENDING) { - /* Async sockets use a FileHandler internally while connecting, so we - * need to cache this request until the connection has succeeded. */ + if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) { + /* + * Async sockets use a FileHandler internally while connecting, so we + * need to cache this request until the connection has succeeded. + */ + statePtr->filehandlers = mask; } else if (mask) { /* - * Whether it is a bug or feature or otherwise, it is a fact - * of life that on at least some Linux kernels select() fails - * to report that a socket file descriptor is writable when - * the other end of the socket is closed. This is in contrast - * to the guarantees Tcl makes that its channels become - * writable and fire writable events on an error conditon. - * This has caused a leak of file descriptors in a state of + * Whether it is a bug or feature or otherwise, it is a fact of life + * that on at least some Linux kernels select() fails to report that a + * socket file descriptor is writable when the other end of the socket + * is closed. This is in contrast to the guarantees Tcl makes that + * its channels become writable and fire writable events on an error + * conditon. This has caused a leak of file descriptors in a state of * background flushing. See Tcl ticket 1758a0b603. * - * As a workaround, when our caller indicates an interest in - * writable notifications, we must tell the notifier built - * around select() that we are interested in the readable state - * of the file descriptor as well, as that is the only reliable - * means to get notified of error conditions. Then it is the - * task of WrapNotify() above to untangle the meaning of these - * channel states and report the chan events as best it can. - * We save a copy of the mask passed in to assist with that. + * As a workaround, when our caller indicates an interest in writable + * notifications, we must tell the notifier built around select() that + * we are interested in the readable state of the file descriptor as + * well, as that is the only reliable means to get notified of error + * conditions. Then it is the task of WrapNotify() above to untangle + * the meaning of these channel states and report the chan events as + * best it can. We save a copy of the mask passed in to assist with + * that. */ statePtr->interest = mask; @@ -1010,7 +1062,7 @@ TcpWatchProc( } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TcpGetHandleProc -- * @@ -1024,7 +1076,7 @@ TcpWatchProc( * Side effects: * None. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ /* ARGSUSED */ @@ -1041,16 +1093,17 @@ TcpGetHandleProc( } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TcpAsyncCallback -- * - * Called by the event handler that TcpConnect sets up - * internally for [socket -async] to get notified when the - * asyncronous connection attempt has succeeded or failed. + * Called by the event handler that TcpConnect sets up internally for + * [socket -async] to get notified when the asyncronous connection + * attempt has succeeded or failed. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ + static void TcpAsyncCallback( ClientData clientData, /* The socket state. */ @@ -1062,7 +1115,7 @@ TcpAsyncCallback( } /* - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- * * TcpConnect -- * @@ -1088,7 +1141,7 @@ TcpAsyncCallback( * return and the loops resume as if they had never been interrupted. * For syncronously connecting sockets, the loops work the usual way. * - *---------------------------------------------------------------------- + * ---------------------------------------------------------------------- */ static int @@ -1097,9 +1150,9 @@ TcpConnect( TcpState *statePtr) { socklen_t optlen; - int async_callback = statePtr->flags & TCP_ASYNC_PENDING; - int ret = -1, error = errno; - int async = statePtr->flags & TCP_ASYNC_CONNECT; + int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING); + int ret = -1, error = EHOSTUNREACH; + int async = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT); if (async_callback) { goto reenter; @@ -1107,8 +1160,8 @@ TcpConnect( for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL; statePtr->addr = statePtr->addr->ai_next) { - - for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL; + for (statePtr->myaddr = statePtr->myaddrlist; + statePtr->myaddr != NULL; statePtr->myaddr = statePtr->myaddr->ai_next) { int reuseaddr = 1; @@ -1132,7 +1185,8 @@ TcpConnect( errno = 0; } - statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM, 0); + statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM, + 0); if (statePtr->fds.fd < 0) { continue; } @@ -1151,14 +1205,18 @@ TcpConnect( TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE); if (async) { - ret = TclUnixSetBlockingMode(statePtr->fds.fd,TCL_MODE_NONBLOCKING); + ret = TclUnixSetBlockingMode(statePtr->fds.fd, + TCL_MODE_NONBLOCKING); if (ret < 0) { continue; } } - /* Gotta reset the error variable here, before we use it for the - * first time in this iteration. */ + /* + * Must reset the error variable here, before we use it for the + * first time in this iteration. + */ + error = 0; (void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR, @@ -1179,10 +1237,13 @@ TcpConnect( ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr, statePtr->addr->ai_addrlen); - if (ret < 0) error = errno; + if (ret < 0) { + error = errno; + } if (ret < 0 && errno == EINPROGRESS) { Tcl_CreateFileHandler(statePtr->fds.fd, - TCL_WRITABLE|TCL_EXCEPTION, TcpAsyncCallback, statePtr); + TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback, + statePtr); errno = EWOULDBLOCK; SET_BITS(statePtr->flags, TCP_ASYNC_PENDING); return TCL_OK; @@ -1210,7 +1271,7 @@ TcpConnect( } } -out: + out: statePtr->connectError = error; CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT); if (async_callback) { @@ -1308,6 +1369,7 @@ Tcl_OpenTcpClient( /* * Allocate a new TcpState for this socket. */ + statePtr = ckalloc(sizeof(TcpState)); memset(statePtr, 0, sizeof(TcpState)); statePtr->flags = async ? TCP_ASYNC_CONNECT : 0; @@ -1319,6 +1381,7 @@ Tcl_OpenTcpClient( /* * Create a new client socket and wrap it in a channel. */ + if (TcpConnect(interp, statePtr) != TCL_OK) { TcpCloseProc(statePtr, NULL); return NULL; @@ -1326,8 +1389,8 @@ Tcl_OpenTcpClient( sprintf(channelName, SOCK_TEMPLATE, (long) statePtr); - statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, - (TCL_READABLE | TCL_WRITABLE)); + statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, + statePtr, TCL_READABLE | TCL_WRITABLE); if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation", "auto crlf") == TCL_ERROR) { Tcl_Close(NULL, statePtr->channel); @@ -1356,7 +1419,8 @@ Tcl_Channel Tcl_MakeTcpClientChannel( ClientData sock) /* The socket to wrap up into a channel. */ { - return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock, (TCL_READABLE | TCL_WRITABLE)); + return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock, + TCL_READABLE | TCL_WRITABLE); } /* @@ -1405,7 +1469,7 @@ TclpMakeTcpClientChannelMode( /* *---------------------------------------------------------------------- * - * Tcl_OpenTcpServer -- + * Tcl_OpenTcpServerEx -- * * Opens a TCP server socket and creates a channel around it. * @@ -1420,16 +1484,17 @@ TclpMakeTcpClientChannelMode( */ Tcl_Channel -Tcl_OpenTcpServer( +Tcl_OpenTcpServerEx( Tcl_Interp *interp, /* For error reporting - may be NULL. */ - int port, /* Port number to open. */ + const char *service, /* Port number to open. */ const char *myHost, /* Name of local host. */ + unsigned int flags, /* Flags. */ Tcl_TcpAcceptProc *acceptProc, /* Callback for accepting connections from new * clients. */ ClientData acceptProcData) /* Data for the callback. */ { - int status = 0, sock = -1, reuseaddr = 1, chosenport = 0; + int status = 0, sock = -1, optvalue, port, chosenport; struct addrinfo *addrlist = NULL, *addrPtr; /* socket address */ TcpState *statePtr = NULL; char channelName[SOCK_CHAN_LENGTH]; @@ -1444,7 +1509,45 @@ Tcl_OpenTcpServer( enum { LOOKUP, SOCKET, BIND, LISTEN } howfar = LOOKUP; int my_errno = 0; - if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) { + /* + * If we were called with port 0 to listen on a random port number, we + * copy the port number from the first member of the addrinfo list to all + * subsequent members, so that IPv4 and IPv6 listen on the same port. This + * might fail to bind() with EADDRINUSE if a port is free on the first + * address family in the list but already used on the other. In this case + * we revert everything we've done so far and start from scratch hoping + * that next time we'll find a port number that is usable on all address + * families. We try this at most MAXRETRY times to avoid an endless loop + * if all ports are taken. + */ + + int retry = 0; +#define MAXRETRY 10 + + repeat: + if (retry > 0) { + if (statePtr != NULL) { + TcpCloseProc(statePtr, NULL); + statePtr = NULL; + } + if (addrlist != NULL) { + freeaddrinfo(addrlist); + addrlist = NULL; + } + if (retry >= MAXRETRY) { + goto error; + } + } + retry++; + chosenport = 0; + + if (TclSockGetPort(interp, service, "tcp", &port) != TCL_OK) { + errorMsg = "invalid port number"; + goto error; + } + + if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, + &errorMsg)) { my_errno = errno; goto error; } @@ -1474,12 +1577,30 @@ Tcl_OpenTcpServer( TclSockMinimumBuffers(INT2PTR(sock), SOCKET_BUFSIZE); /* - * Set up to reuse server addresses automatically and bind to the - * specified port. + * Set up to reuse server addresses and/or ports if requested. */ - (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char *) &reuseaddr, sizeof(reuseaddr)); + if (GOT_BITS(flags, TCL_TCPSERVER_REUSEADDR)) { + optvalue = 1; + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (char *) &optvalue, sizeof(optvalue)); + } + + if (GOT_BITS(flags, TCL_TCPSERVER_REUSEPORT)) { +#ifndef SO_REUSEPORT + /* + * If the platform doesn't support the SO_REUSEPORT flag we can't + * do much beside erroring out. + */ + + errorMsg = "SO_REUSEPORT isn't supported by this platform"; + goto error; +#else + optvalue = 1; + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, + (char *) &optvalue, sizeof(optvalue)); +#endif + } /* * Make sure we use the same port number when opening two server @@ -1495,7 +1616,10 @@ Tcl_OpenTcpServer( } #ifdef IPV6_V6ONLY - /* Missing on: Solaris 2.8 */ + /* + * Missing on: Solaris 2.8 + */ + if (addrPtr->ai_family == AF_INET6) { int v6only = 1; @@ -1512,6 +1636,9 @@ Tcl_OpenTcpServer( } close(sock); sock = -1; + if (port == 0 && errno == EADDRINUSE) { + goto repeat; + } continue; } if (port == 0 && chosenport == 0) { @@ -1535,6 +1662,9 @@ Tcl_OpenTcpServer( } close(sock); sock = -1; + if (port == 0 && errno == EADDRINUSE) { + goto repeat; + } continue; } if (statePtr == NULL) { @@ -1641,7 +1771,7 @@ TcpAccept( sprintf(channelName, SOCK_TEMPLATE, (long) newSockState); newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName, - newSockState, (TCL_READABLE | TCL_WRITABLE)); + newSockState, TCL_READABLE | TCL_WRITABLE); Tcl_SetChannelOption(NULL, newSockState->channel, "-translation", "auto crlf"); diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 02f255f..33d88c2 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -673,6 +673,7 @@ TclpFinalizeCondition( *---------------------------------------------------------------------- */ +#ifndef TCL_NO_DEPRECATED Tcl_DirEntry * TclpReaddir( DIR * dir) @@ -695,6 +696,7 @@ TclpInetNtoa( return inet_ntoa(addr); #endif } +#endif /* TCL_NO_DEPRECATED */ #ifdef TCL_THREADS /* @@ -740,9 +742,7 @@ TclpFreeAllocMutex( void TclpInitAllocCache(void) { - pthread_mutex_lock(allocLockPtr); - pthread_key_create(&key, TclpFreeAllocCache); - pthread_mutex_unlock(allocLockPtr); + pthread_key_create(&key, NULL); } void @@ -751,13 +751,19 @@ TclpFreeAllocCache( { if (ptr != NULL) { /* - * Called by the pthread lib when a thread exits + * Called by TclFinalizeThreadAllocThread() during the thread + * finalization initiated from Tcl_FinalizeThread() */ TclFreeAllocCache(ptr); pthread_setspecific(key, NULL); } else { + /* + * Called by TclFinalizeThreadAlloc() during the process + * finalization initiated from Tcl_Finalize() + */ + pthread_key_delete(key); } } diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index ae758de..3c32070 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -22,6 +22,7 @@ * variable is the key to this buffer. */ +#ifndef TCL_NO_DEPRECATED static Tcl_ThreadDataKey tmKey; typedef struct { struct tm gmtime_buf; @@ -45,6 +46,8 @@ static char *lastTZ = NULL; /* Holds the last setting of the TZ static void SetTZIfNecessary(void); static void CleanupMemory(ClientData clientData); +#endif /* TCL_NO_DEPRECATED */ + static void NativeScaleTime(Tcl_Time *timebuf, ClientData clientData); static void NativeGetTime(Tcl_Time *timebuf, @@ -165,7 +168,7 @@ TclpGetWideClicks(void) Tcl_Time time; tclGetTimeProcPtr(&time, tclTimeClientData); - now = (Tcl_WideInt) (time.sec*1000000 + time.usec); + now = ((Tcl_WideInt)time.sec)*1000000 + time.usec; } else { #ifdef MAC_OSX_TCL now = (Tcl_WideInt) (mach_absolute_time() & INT64_MAX); @@ -270,6 +273,7 @@ Tcl_GetTime( *---------------------------------------------------------------------- */ +#ifndef TCL_NO_DEPRECATED struct tm * TclpGetDate( const time_t *time, @@ -359,6 +363,7 @@ TclpLocaltime( return &tsdPtr->localtime_buf; } +#endif /* TCL_NO_DEPRECATED */ /* *---------------------------------------------------------------------- @@ -495,6 +500,7 @@ NativeGetTime( *---------------------------------------------------------------------- */ +#ifndef TCL_NO_DEPRECATED static void SetTZIfNecessary(void) { @@ -540,6 +546,7 @@ CleanupMemory( { ckfree(lastTZ); } +#endif /* TCL_NO_DEPRECATED */ /* *---------------------------------------------------------------------- diff --git a/unix/tclXtTest.c b/unix/tclXtTest.c index f7c2652..cb70b58 100644 --- a/unix/tclXtTest.c +++ b/unix/tclXtTest.c @@ -48,7 +48,7 @@ int Tclxttest_Init( Tcl_Interp *interp) /* Interpreter for application. */ { - if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } XtToolkitInitialize(); |