Tcl Source Code

Artifact [82fd7839b5]
Login

Artifact 82fd7839b5f1fa6e143f0740dadf8539e7107b30:

Attachment "tcl8.5.2-VxWorks-DKM.patch" to ticket [1955146fff] added by fpilhofer 2008-05-01 04:56:47.
diff -r -u -N tcl8.5.2.orig/generic/regguts.h tcl8.5.2/generic/regguts.h
--- tcl8.5.2.orig/generic/regguts.h	2007-12-18 05:53:16.000000000 -0500
+++ tcl8.5.2/generic/regguts.h	2008-03-31 15:01:27.914744600 -0400
@@ -108,6 +108,15 @@
 #define	_POSIX2_RE_DUP_MAX 255	/* normally from <limits.h> */
 #endif
 
+#if defined(_WRS_KERNEL)
+#if defined(EOS)
+#undef EOS
+#endif
+#if defined(LOCAL)
+#undef LOCAL
+#endif
+#endif
+
 /*
  * misc
  */
diff -r -u -N tcl8.5.2.orig/generic/tclBasic.c tcl8.5.2/generic/tclBasic.c
--- tcl8.5.2.orig/generic/tclBasic.c	2008-03-14 15:53:10.000000000 -0400
+++ tcl8.5.2/generic/tclBasic.c	2008-03-31 15:01:27.930369400 -0400
@@ -24,6 +24,14 @@
 #include <math.h>
 #include "tommath.h"
 
+#if defined (_WRS_KERNEL)
+double
+hypot (double x, double y)
+{
+    return sqrt (x*x + y*y);
+}
+#endif
+
 /*
  * Determine whether we're using IEEE floating point
  */
@@ -4339,7 +4347,7 @@
 	TclAdvanceLines(&line, parsePtr->commandStart, p);
 	Tcl_FreeParse(parsePtr);
 	gotParse = 0;
-    } while (bytesLeft > 0);
+    } while (bytesLeft > 0 && !(iPtr->flags & DELETED));
     iPtr->varFramePtr = savedVarFramePtr;
     code = TCL_OK;
     goto cleanup_return;
diff -r -u -N tcl8.5.2.orig/generic/tclCkalloc.c tcl8.5.2/generic/tclCkalloc.c
--- tcl8.5.2.orig/generic/tclCkalloc.c	2007-04-23 16:33:56.000000000 -0400
+++ tcl8.5.2/generic/tclCkalloc.c	2008-03-31 15:01:27.930369400 -0400
@@ -19,8 +19,10 @@
 
 #include "tclInt.h"
 
+#if !defined(_WRS_KERNEL)
 #define FALSE	0
 #define TRUE	1
+#endif
 
 #ifdef TCL_MEM_DEBUG
 
diff -r -u -N tcl8.5.2.orig/generic/tclClock.c tcl8.5.2/generic/tclClock.c
--- tcl8.5.2.orig/generic/tclClock.c	2008-02-26 21:08:27.000000000 -0500
+++ tcl8.5.2/generic/tclClock.c	2008-03-31 15:01:27.945994200 -0400
@@ -1977,6 +1977,7 @@
 static void
 TzsetIfNecessary(void)
 {
+#if !defined(_WRS_KERNEL)
     static char* tzWas = NULL;	/* Previous value of TZ, protected by
 				 * clockMutex. */
     const char* tzIsNow;	/* Current value of TZ */
@@ -1996,6 +1997,7 @@
 	tzWas = NULL;
     }
     Tcl_MutexUnlock(&clockMutex);
+#endif
 }
 
 /*
diff -r -u -N tcl8.5.2.orig/generic/tclCmdAH.c tcl8.5.2/generic/tclCmdAH.c
--- tcl8.5.2.orig/generic/tclCmdAH.c	2008-03-14 12:07:23.000000000 -0400
+++ tcl8.5.2/generic/tclCmdAH.c	2008-03-31 15:01:27.945994200 -0400
@@ -990,7 +990,7 @@
 	     * we always return 1.
 	     */
 
-#if defined(__WIN32__)
+#if defined(__WIN32__) || defined(_WRS_KERNEL)
 	    value = 1;
 #else
 	    value = (geteuid() == buf.st_uid);
diff -r -u -N tcl8.5.2.orig/generic/tclEnv.c tcl8.5.2/generic/tclEnv.c
--- tcl8.5.2.orig/generic/tclEnv.c	2007-12-13 10:23:16.000000000 -0500
+++ tcl8.5.2/generic/tclEnv.c	2008-03-31 15:01:27.945994200 -0400
@@ -17,6 +17,13 @@
 
 #include "tclInt.h"
 
+#if defined (_WRS_KERNEL)
+#include <envLib.h>
+#undef environ
+#define USE_PUTENV 1
+#define USE_PUTENV_FOR_UNSET 1
+#endif
+
 TCL_DECLARE_MUTEX(envMutex)	/* To serialize access to environ. */
 
 static struct {
@@ -76,6 +83,9 @@
     Tcl_Interp *interp)		/* Interpreter whose "env" array is to be
 				 * managed. */
 {
+#if defined (_WRS_KERNEL)
+    char ** environ = envGet (0);
+#endif
     Tcl_DString envString;
     char *p1, *p2;
     int i;
@@ -156,6 +166,9 @@
 				 * (UTF-8). */
     const char *value)		/* New value for variable (UTF-8). */
 {
+#if defined (_WRS_KERNEL)
+    char ** environ = envGet (0);
+#endif
     Tcl_DString envString;
     int index, length, nameLength;
     char *p, *oldValue;
@@ -353,6 +366,9 @@
 TclUnsetEnv(
     const char *name)		/* Name of variable to remove (UTF-8). */
 {
+#if defined (_WRS_KERNEL)
+    char ** environ = envGet (0);
+#endif
     char *oldValue;
     int length;
     int index;
@@ -469,6 +485,9 @@
 				 * value of the environment variable is
 				 * stored. */
 {
+#if defined (_WRS_KERNEL)
+    char ** environ = envGet (0);
+#endif
     int length, index;
     const char *result;
 
diff -r -u -N tcl8.5.2.orig/generic/tclEvent.c tcl8.5.2/generic/tclEvent.c
--- tcl8.5.2.orig/generic/tclEvent.c	2008-03-10 13:54:47.000000000 -0400
+++ tcl8.5.2/generic/tclEvent.c	2008-03-31 15:01:27.961619000 -0400
@@ -208,7 +208,7 @@
 
     Tcl_Preserve((ClientData) assocPtr);
     Tcl_Preserve((ClientData) interp);
-    while (assocPtr->firstBgPtr != NULL) {
+    while (assocPtr->firstBgPtr != NULL && !Tcl_InterpDeleted (interp)) {
 	int code, prefixObjc;
 	Tcl_Obj **prefixObjv, **tempObjv;
 
@@ -1244,7 +1244,7 @@
     };
     done = 0;
     foundEvent = 1;
-    while (!done && foundEvent) {
+    while (!done && foundEvent && !Tcl_InterpDeleted (interp)) {
 	foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS);
 	if (Tcl_LimitExceeded(interp)) {
 	    break;
@@ -1260,6 +1260,9 @@
      */
 
     Tcl_ResetResult(interp);
+    if (Tcl_InterpDeleted (interp)) {
+	return TCL_OK;
+    }
     if (!foundEvent) {
 	Tcl_AppendResult(interp, "can't wait for variable \"", nameString,
 		"\": would wait forever", NULL);
diff -r -u -N tcl8.5.2.orig/generic/tclExecute.c tcl8.5.2/generic/tclExecute.c
--- tcl8.5.2.orig/generic/tclExecute.c	2008-03-18 14:52:07.000000000 -0400
+++ tcl8.5.2/generic/tclExecute.c	2008-03-31 15:01:27.961619000 -0400
@@ -858,6 +858,10 @@
 #define WALLOCALIGN \
     (TCL_ALLOCALIGN/sizeof(Tcl_Obj *))
 
+#if defined (_WRS_KERNEL)
+#undef OFFSET
+#endif
+
 static inline int
 OFFSET(
     void *ptr)
@@ -1877,6 +1881,12 @@
 	}
     }
 
+    if (iPtr->flags & DELETED) {
+	Tcl_ResetResult (interp);
+	result = TCL_ERROR;
+	goto abnormalReturn;
+    }
+
      TCL_DTRACE_INST_NEXT();
 
     /*
diff -r -u -N tcl8.5.2.orig/generic/tclFileName.c tcl8.5.2/generic/tclFileName.c
--- tcl8.5.2.orig/generic/tclFileName.c	2007-12-13 10:23:17.000000000 -0500
+++ tcl8.5.2/generic/tclFileName.c	2008-03-31 15:01:27.977243800 -0400
@@ -415,6 +415,43 @@
 		}
 	    }
 #endif
+#if defined (_WRS_KERNEL)
+	    /*
+	     * Absolute names may start with a "<device>:" prefix.  If
+	     * the device is "host", and the host is running Windows,
+	     * then it might even look like "host:<drive>:<path>"
+	     */
+
+	    if (isalpha(UCHAR(*path))) {
+		++path;
+
+		while (isalnum(UCHAR(*path)) || *path == '_' ) {
+		    ++path;
+		}
+	    }
+
+	    if (path[0] == ':') {
+		if (path[1] != '\0' && path[2] == ':') {
+		    path += 2;
+		}
+		if (path[0] == '/') {
+		    path++;
+		}
+		if (driveNameLengthPtr != NULL) {
+		    *driveNameLengthPtr = 1 + path - origPath;
+		}
+		type = TCL_PATH_ABSOLUTE;
+	    }
+	    else if (path[0] == '/') {
+		type = TCL_PATH_ABSOLUTE;
+		if (driveNameLengthPtr != NULL) {
+		    *driveNameLengthPtr = 1;
+		}
+	    }
+	    else {
+		type = TCL_PATH_RELATIVE;
+	    }
+#else
 	    if (path[0] == '/') {
 		if (driveNameLengthPtr != NULL) {
 		    /*
@@ -426,6 +463,7 @@
 	    } else {
 		type = TCL_PATH_RELATIVE;
 	    }
+#endif
 	    break;
 	}
 	case TCL_PLATFORM_WINDOWS: {
diff -r -u -N tcl8.5.2.orig/generic/tclIOSock.c tcl8.5.2/generic/tclIOSock.c
--- tcl8.5.2.orig/generic/tclIOSock.c	2007-02-20 18:24:04.000000000 -0500
+++ tcl8.5.2/generic/tclIOSock.c	2008-03-31 15:01:27.977243800 -0400
@@ -12,6 +12,8 @@
  */
 
 #include "tclInt.h"
+#include <sockLib.h>
+
 
 /*
  *---------------------------------------------------------------------------
@@ -39,6 +41,7 @@
     const char *proto, /* "tcp" or "udp", typically */
     int *portPtr)		/* Return port number */
 {
+#if !defined (_WRS_KERNEL)
     struct servent *sp;		/* Protocol info for named services */
     Tcl_DString ds;
     const char *native;
@@ -56,6 +59,7 @@
 	    return TCL_OK;
 	}
     }
+#endif
     if (Tcl_GetInt(interp, string, portPtr) != TCL_OK) {
 	return TCL_ERROR;
     }
diff -r -u -N tcl8.5.2.orig/generic/tclInt.h tcl8.5.2/generic/tclInt.h
--- tcl8.5.2.orig/generic/tclInt.h	2008-01-23 16:32:36.000000000 -0500
+++ tcl8.5.2/generic/tclInt.h	2008-03-31 15:01:27.977243800 -0400
@@ -66,6 +66,15 @@
 typedef int ptrdiff_t;
 #endif
 
+#if defined (_WRS_KERNEL)
+extern int		strcasecmp _ANSI_ARGS_((CONST char *s1,
+			    CONST char *s2));
+#endif
+
+#if defined (_WRS_KERNEL) && defined (USE_THREAD_ALLOC)
+#undef USE_THREAD_ALLOC
+#endif
+
 /*
  * Ensure WORDS_BIGENDIAN is defined correcly:
  * Needs to happen here in addition to configure to work with fat compiles on
diff -r -u -N tcl8.5.2.orig/unix/Makefile.in tcl8.5.2/unix/Makefile.in
--- tcl8.5.2.orig/unix/Makefile.in	2008-03-28 14:41:53.000000000 -0400
+++ tcl8.5.2/unix/Makefile.in	2008-03-31 15:01:27.992868600 -0400
@@ -167,7 +167,7 @@
 
 STLIB_LD		= @STLIB_LD@
 SHLIB_LD		= @SHLIB_LD@
-SHLIB_CFLAGS		= @SHLIB_CFLAGS@
+SHLIB_CFLAGS		= # @SHLIB_CFLAGS@
 SHLIB_LD_LIBS		= @SHLIB_LD_LIBS@
 TCL_SHLIB_LD_EXTRAS	= @TCL_SHLIB_LD_EXTRAS@
 
@@ -318,7 +318,7 @@
 
 UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
 	tclUnixFile.o tclUnixPipe.o tclUnixSock.o \
-	tclUnixTime.o tclUnixInit.o tclUnixThrd.o \
+	tclUnixTime.o tclUnixInit.o tclVxWorksThrd.o \
 	tclUnixCompat.o
 
 NOTIFY_OBJS = tclUnixNotfy.o
@@ -328,7 +328,7 @@
 DTRACE_OBJ = tclDTrace.o
 
 TCL_OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} ${COMPAT_OBJS} \
-	@DL_OBJS@ @PLAT_OBJS@
+	tclLoadVxWorks.o @PLAT_OBJS@
 
 OBJS = ${TCL_OBJS} ${TOMMATH_OBJS} @DTRACE_OBJ@
 
@@ -505,7 +505,8 @@
 	$(UNIX_DIR)/tclUnixThrd.c \
 	$(UNIX_DIR)/tclUnixTime.c \
 	$(UNIX_DIR)/tclUnixInit.c \
-	$(UNIX_DIR)/tclUnixCompat.c
+	$(UNIX_DIR)/tclUnixCompat.c \
+	$(UNIX_DIR)/tclVxWorksThrd.c
 
 NOTIFY_SRCS = \
 	$(UNIX_DIR)/tclUnixNotfy.c
@@ -518,7 +519,8 @@
 	$(UNIX_DIR)/tclLoadDyld.c \
 	$(GENERIC_DIR)/tclLoadNone.c \
 	$(UNIX_DIR)/tclLoadOSF.c \
-	$(UNIX_DIR)/tclLoadShl.c
+	$(UNIX_DIR)/tclLoadShl.c \
+	$(UNIX_DIR)/tclLoadVxWorks.c
 
 MAC_OSX_SRCS = \
 	$(MAC_OSX_DIR)/tclMacOSXBundle.c \
@@ -538,7 +540,7 @@
 
 all: binaries libraries doc
 
-binaries: ${LIB_FILE} $(STUB_LIB_FILE) $(TCL_BUILD_EXP_FILE) tclsh
+binaries: ${LIB_FILE} $(STUB_LIB_FILE) $(TCL_BUILD_EXP_FILE) tclsh.out
 
 libraries:
 
@@ -569,6 +571,10 @@
 	${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} @TCL_BUILD_LIB_SPEC@ ${LIBS} @EXTRA_TCLSH_LIBS@ \
 		${CC_SEARCH_FLAGS} -o tclsh
 
+tclsh.out: tclVxWorksInit.o ${TCL_LIB_FILE}
+	${CC} ${CFLAGS} ${LDFLAGS} tclVxWorksInit.o @TCL_BUILD_LIB_SPEC@ @EXTRA_TCLSH_LIBS@ \
+		${CC_SEARCH_FLAGS} -o tclsh.out
+
 # Resetting the LIB_RUNTIME_DIR below is required so that the generated
 # tcltest executable gets the build directory burned into its ld search path.
 # This keeps tcltest from picking up an already installed version of the Tcl
@@ -883,12 +889,13 @@
 
 clean:
 	rm -f *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
-		errors tclsh tcltest lib.exp Tcl
+		errors tclsh tcltest lib.exp Tcl tclsh.out
 	cd dltest ; $(MAKE) clean
 
 distclean: clean
 	rm -rf Makefile config.status config.cache config.log tclConfig.sh \
 		$(PACKAGE).* prototype tclConfig.h *.plist Tcl.framework
+	rm -rf Makefile.?
 	cd dltest ; $(MAKE) distclean
 
 depend:
@@ -958,6 +965,9 @@
 tclAppInit.o: $(UNIX_DIR)/tclAppInit.c
 	$(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclAppInit.c
 
+tclVxWorksInit.o: $(UNIX_DIR)/tclVxWorksInit.c
+	$(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclVxWorksInit.c
+
 # On Unix we want to use the normal malloc/free implementation, so we
 # specifically set the USE_TCLALLOC flag.
 
@@ -1096,6 +1106,9 @@
 tclLoadShl.o: $(UNIX_DIR)/tclLoadShl.c
 	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadShl.c
 
+tclLoadVxWorks.o: $(UNIX_DIR)/tclLoadVxWorks.c
+	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadVxWorks.c
+
 tclMain.o: $(GENERIC_DIR)/tclMain.c
 	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclMain.c
 
@@ -1426,6 +1439,9 @@
 tclUnixThrd.o: $(UNIX_DIR)/tclUnixThrd.c
 	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixThrd.c
 
+tclVxWorksThrd.o: $(UNIX_DIR)/tclVxWorksThrd.c
+	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclVxWorksThrd.c
+
 tclUnixTime.o: $(UNIX_DIR)/tclUnixTime.c
 	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixTime.c
 
diff -r -u -N tcl8.5.2.orig/unix/configure tcl8.5.2/unix/configure
--- tcl8.5.2.orig/unix/configure	2008-03-28 14:41:53.000000000 -0400
+++ tcl8.5.2/unix/configure	2008-03-31 15:01:28.008493400 -0400
@@ -4561,7 +4561,7 @@
 
 	if test "$tcl_ok" = "yes"; then
 	    # The space is needed
-	    THREADS_LIBS=" -lpthread"
+	    THREADS_LIBS=""
 	else
 	    echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthreads" >&5
 echo $ECHO_N "checking for pthread_mutex_init in -lpthreads... $ECHO_C" >&6
diff -r -u -N tcl8.5.2.orig/unix/tclLoadVxWorks.c tcl8.5.2/unix/tclLoadVxWorks.c
--- tcl8.5.2.orig/unix/tclLoadVxWorks.c	1969-12-31 19:00:00.000000000 -0500
+++ tcl8.5.2/unix/tclLoadVxWorks.c	2008-03-31 15:01:28.008493400 -0400
@@ -0,0 +1,253 @@
+/*
+ * tclLoadVxWorks.c --
+ *
+ *	This procedure provides a version of the TclLoadFile that works with
+ *	the VxWorks kernel module loader for dynamic loading.
+ *
+ * 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 <string.h>
+#include <ioLib.h>
+#include <loadLib.h>
+#include <unldLib.h>
+#include <symLib.h>
+#include <moduleLib.h>
+#include <sysSymTbl.h>
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpDlopen --
+ *
+ *	Dynamically loads a binary code file into memory and returns a handle
+ *	to the new code.
+ *
+ * Results:
+ *	A standard Tcl completion code. If an error occurs, an error message
+ *	is left in the interp's result.
+ *
+ * Side effects:
+ *	New code suddenly appears in memory.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpDlopen(
+    Tcl_Interp *interp,		/* Used for error reporting. */
+    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
+				 * code (UTF-8). */
+    Tcl_LoadHandle *loadHandle,	/* Filled with token for dynamically loaded
+				 * file which will be passed back to
+				 * (*unloadProcPtr)() to unload the file. */
+    Tcl_FSUnloadFileProc **unloadProcPtr)
+				/* Filled with address of Tcl_FSUnloadFileProc
+				 * function which should be used for this
+				 * file. */
+{
+    MODULE_ID handle;
+    CONST char * native;
+    int fd, origErrno;
+
+    /*
+     * First try the full path the user gave us. This is particularly
+     * important if the cwd is inside a vfs, and we are trying to load using a
+     * relative path.
+     */
+
+    native = Tcl_FSGetNativePath(pathPtr);
+    fd = open (native, O_RDONLY, 0400);
+
+    if (fd == ERROR) {
+	Tcl_AppendResult (interp, "couldn't load file \"",
+			  Tcl_GetString (pathPtr), "\": ",
+			  Tcl_PosixError (interp),
+			  NULL);
+	return TCL_ERROR;
+    }
+
+    handle = loadModule (fd,
+			 LOAD_GLOBAL_SYMBOLS |
+			 LOAD_COMMON_MATCH_NONE |
+			 LOAD_CPLUS_XTOR_AUTO);
+    origErrno = errno;
+    close (fd);
+
+    if (!handle) {
+	/*
+	 * A null handle is also returned if there are unresolved symbols,
+	 * but the module remains loaded.  So we have to unload it.  For
+	 * that, we need the module id that loadModule() should have
+	 * returned.  What a lovely design.  So look up the module using
+	 * its module name, which is the file name.
+	 */
+
+	CONST char * baseName;
+	char * dirName;
+
+	baseName = strrchr (native, '/');
+
+	if (baseName) {
+	    int dirLen = baseName - native;
+	    dirName = malloc (dirLen + 1);
+	    memcpy (dirName, native, dirLen);
+	    dirName[dirLen] = '\0';
+	    baseName++;
+	}
+	else {
+	    baseName = native;
+	    dirName = malloc (1);
+	    dirName[0] = '\0';
+	}
+
+	if ((handle = moduleFindByNameAndPath ((char *) baseName, dirName))) {
+	    unldByModuleId (handle, 0);
+	}
+
+	errno = origErrno;
+	Tcl_AppendResult (interp, "couldn't load file \"",
+			  Tcl_GetString (pathPtr), "\": ",
+			  Tcl_PosixError (interp),
+			  NULL);
+	return TCL_ERROR;
+    }
+
+    *unloadProcPtr = &TclpUnloadFile;
+    *loadHandle = (Tcl_LoadHandle) handle;
+    return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFindSymbol --
+ *
+ *	Looks up a symbol, by name, through a handle associated with a
+ *	previously loaded piece of code (shared library).
+ *
+ * Results:
+ *	Returns a pointer to the function associated with 'symbol' if it is
+ *	found. Otherwise returns NULL and may leave an error message in the
+ *	interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+typedef struct FindSymbolHelperData_ {
+    const char * symbol;
+    int moduleGroupNumber;
+} FindSymbolHelperData;
+
+static
+BOOL
+findSymbolHelper (char * name,
+		  int val,
+		  SYM_TYPE type,
+		  int arg,
+		  UINT16 group)
+{
+    FindSymbolHelperData * hd = (FindSymbolHelperData *) arg;
+
+    if (group == hd->moduleGroupNumber &&
+	strcmp (hd->symbol, name) == 0) {
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+Tcl_PackageInitProc *
+TclpFindSymbol(
+    Tcl_Interp *interp,		/* Place to put error messages. */
+    Tcl_LoadHandle loadHandle,	/* Value from TcpDlopen(). */
+    CONST char *symbol)		/* Symbol to look up. */
+{
+    FindSymbolHelperData helperData;
+    MODULE_ID handle = (MODULE_ID) loadHandle;
+    MODULE_INFO moduleInfo;
+    Tcl_DString ds;
+    SYMBOL * sym;
+
+    if (moduleInfoGet (handle, &moduleInfo) != OK) {
+	return NULL;
+    }
+
+    helperData.symbol = Tcl_UtfToExternalDString (NULL, symbol, -1, &ds);
+    helperData.moduleGroupNumber = moduleInfo.group;
+
+    sym = symEach (sysSymTbl,
+		   (FUNCPTR) findSymbolHelper,
+		   (int) &helperData);
+
+    Tcl_DStringFree(&ds);
+    return (sym ? ((Tcl_PackageInitProc *) sym->value) : NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpUnloadFile --
+ *
+ *	Unloads a dynamically loaded binary code file from memory. Code
+ *	pointers in the formerly loaded file are no longer valid after calling
+ *	this function.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Code removed from memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpUnloadFile(
+    Tcl_LoadHandle loadHandle)	/* loadHandle returned by a previous call to
+				 * TclpDlopen(). The loadHandle is a token
+				 * that represents the loaded file. */
+{
+    MODULE_ID handle = (MODULE_ID) loadHandle;
+    unldByModuleId (handle, UNLD_CPLUS_XTOR_AUTO);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ *	If the "load" command is invoked without providing a package name,
+ *	this procedure is invoked to try to figure it out.
+ *
+ * Results:
+ *	Always returns 0 to indicate that we couldn't figure out a package
+ *	name; generic code will then try to guess the package from the file
+ *	name. A return value of 1 would have meant that we figured out the
+ *	package name and put it in bufPtr.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+    CONST char *fileName,	/* Name of file containing package (already
+				 * translated to local form if needed). */
+    Tcl_DString *bufPtr)	/* Initialized empty dstring. Append package
+				 * name to this if possible. */
+{
+    return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff -r -u -N tcl8.5.2.orig/unix/tclUnixChan.c tcl8.5.2/unix/tclUnixChan.c
--- tcl8.5.2.orig/unix/tclUnixChan.c	2008-03-03 09:54:43.000000000 -0500
+++ tcl8.5.2/unix/tclUnixChan.c	2008-03-31 15:45:43.490127800 -0400
@@ -16,6 +16,12 @@
 #include "tclInt.h"	/* Internal definitions for Tcl. */
 #include "tclIO.h"	/* To get Channel type declaration. */
 
+#if defined(_WRS_KERNEL)
+#include <sockLib.h>
+#include <hostLib.h>
+#include <selectLib.h>
+#endif
+
 #define SUPPORTS_TTY
 
 #undef DIRECT_BAUD
@@ -3173,6 +3179,7 @@
     FileState *fsPtr = (FileState *) instanceData;
     int result;
 
+#if !defined (_WRS_KERNEL)
 #ifdef HAVE_TYPE_OFF64_T
     /*
      * We assume this goes with the type for now...
@@ -3182,6 +3189,9 @@
 #else
     result = ftruncate(fsPtr->fd, (off_t) length);
 #endif
+#else
+    result = ioctl (fsPtr->fd, FIOTRUNC64, &length);
+#endif
     if (result) {
 	return errno;
     }
diff -r -u -N tcl8.5.2.orig/unix/tclUnixCompat.c tcl8.5.2/unix/tclUnixCompat.c
--- tcl8.5.2.orig/unix/tclUnixCompat.c	2008-02-28 15:14:12.000000000 -0500
+++ tcl8.5.2/unix/tclUnixCompat.c	2008-03-31 15:45:44.661987800 -0400
@@ -11,11 +11,18 @@
  */
 
 #include "tclInt.h"
+#if !defined (_WRS_KERNEL)
 #include <pwd.h>
 #include <grp.h>
+#endif
 #include <errno.h>
 #include <string.h>
 
+#if defined (_WRS_KERNEL)
+#include <ioLib.h>
+#include <hostLib.h>
+#endif
+
 /* See also: SC_BLOCKING_STYLE in unix/tcl.m4
  */
 #ifdef	USE_FIONBIO
@@ -84,11 +91,13 @@
 #ifdef TCL_THREADS
 
 typedef struct ThreadSpecificData {
+#if !defined (_WRS_KERNEL)
     struct passwd pwd;
     char pbuf[2048];
 
     struct group grp;
     char gbuf[2048];
+#endif
 
 #if !defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)
     struct hostent hent;
@@ -153,6 +162,7 @@
 TclpGetPwNam(
     const char *name)
 {
+#if !defined(_WRS_KERNEL)
 #if !defined(TCL_THREADS)
     return getpwnam(name);
 #else
@@ -186,6 +196,9 @@
 
     return NULL;		/* Not reached. */
 #endif /* TCL_THREADS */
+#else /* _WRS_KERNEL */
+    return NULL;
+#endif
 }
 
 /*
@@ -209,6 +222,7 @@
 TclpGetPwUid(
     uid_t uid)
 {
+#if !defined(_WRS_KERNEL)
 #if !defined(TCL_THREADS)
     return getpwuid(uid);
 #else
@@ -242,6 +256,9 @@
 
     return NULL;		/* Not reached. */
 #endif /* TCL_THREADS */
+#else /* _WRS_KERNEL */
+    return NULL;
+#endif
 }
 
 /*
@@ -265,6 +282,7 @@
 TclpGetGrNam(
     const char *name)
 {
+#if !defined(_WRS_KERNEL)
 #if !defined(TCL_THREADS)
     return getgrnam(name);
 #else
@@ -298,6 +316,9 @@
 
     return NULL;		/* Not reached. */
 #endif /* TCL_THREADS */
+#else /* _WRS_KERNEL */
+    return NULL;
+#endif
 }
 
 /*
@@ -321,6 +342,7 @@
 TclpGetGrGid(
     gid_t gid)
 {
+#if !defined(_WRS_KERNEL)
 #if !defined(TCL_THREADS)
     return getgrgid(gid);
 #else
@@ -354,6 +376,9 @@
 
     return NULL;		/* Not reached. */
 #endif /* TCL_THREADS */
+#else /* _WRS_KERNEL */
+    return NULL;
+#endif
 }
 
 /*
diff -r -u -N tcl8.5.2.orig/unix/tclUnixEvent.c tcl8.5.2/unix/tclUnixEvent.c
--- tcl8.5.2.orig/unix/tclUnixEvent.c	2005-11-02 19:26:50.000000000 -0400
+++ tcl8.5.2/unix/tclUnixEvent.c	2008-03-31 15:01:28.039743000 -0400
@@ -12,6 +12,12 @@
  */
 
 #include "tclInt.h"
+
+#if defined (_WRS_KERNEL)
+#include <sockLib.h>
+#include <selectLib.h>
+#endif
+
 
 /*
  *----------------------------------------------------------------------
diff -r -u -N tcl8.5.2.orig/unix/tclUnixFCmd.c tcl8.5.2/unix/tclUnixFCmd.c
--- tcl8.5.2.orig/unix/tclUnixFCmd.c	2007-12-13 10:28:42.000000000 -0500
+++ tcl8.5.2/unix/tclUnixFCmd.c	2008-03-31 15:01:28.039743000 -0400
@@ -48,7 +48,9 @@
 
 #include "tclInt.h"
 #include <utime.h>
+#if !defined(_WRS_KERNEL)
 #include <grp.h>
+#endif
 #ifndef HAVE_ST_BLKSIZE
 #ifndef NO_FSTATFS
 #include <sys/statfs.h>
@@ -58,6 +60,10 @@
 #include <fts.h>
 #endif
 
+#if defined(_WRS_KERNEL)
+#include <ioLib.h>
+#endif
+
 /*
  * The following constants specify the type of callback when
  * TraverseUnixTree() calls the traverseProc()
@@ -453,6 +459,7 @@
     }
 
     switch ((int) (statBufPtr->st_mode & S_IFMT)) {
+#if !defined(_WRS_KERNEL)
 #ifndef DJGPP
     case S_IFLNK: {
 	char link[MAXPATHLEN];
@@ -484,6 +491,7 @@
 	    return TCL_ERROR;
 	}
 	return CopyFileAtts(src, dst, statBufPtr);
+#endif
     default:
 	return TclUnixCopyFile(src, dst, statBufPtr, 0);
     }
@@ -676,6 +684,7 @@
 DoCreateDirectory(
     CONST char *path)		/* Pathname of directory to create (native). */
 {
+#if !defined(_WRS_KERNEL)
     mode_t mode;
 
     mode = umask(0);
@@ -691,6 +700,12 @@
 	return TCL_ERROR;
     }
     return TCL_OK;
+#else
+    if (mkdir(path) != 0) {				/* INTL: Native. */
+	return TCL_ERROR;
+    }
+    return TCL_OK;
+#endif
 }
 
 /*
@@ -1312,7 +1327,9 @@
     Tcl_Obj **attributePtrPtr)	/* A pointer to return the object with. */
 {
     Tcl_StatBuf statBuf;
+#if !defined(_WRS_KERNEL)
     struct group *groupPtr;
+#endif
     int result;
 
     result = TclpObjStat(fileName, &statBuf);
@@ -1326,6 +1343,7 @@
 	return TCL_ERROR;
     }
 
+#if !defined(_WRS_KERNEL)
     groupPtr = TclpGetGrGid(statBuf.st_gid);
 
     if (groupPtr == NULL) {
@@ -1339,6 +1357,9 @@
 	Tcl_DStringFree(&ds);
     }
     endgrent();
+#else
+    *attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_gid);
+#endif
     return TCL_OK;
 }
 
@@ -1367,7 +1388,9 @@
     Tcl_Obj **attributePtrPtr)	/* A pointer to return the object with. */
 {
     Tcl_StatBuf statBuf;
+#if !defined(_WRS_KERNEL)
     struct passwd *pwPtr;
+#endif
     int result;
 
     result = TclpObjStat(fileName, &statBuf);
@@ -1381,6 +1404,7 @@
 	return TCL_ERROR;
     }
 
+#if !defined(_WRS_KERNEL)
     pwPtr = TclpGetPwUid(statBuf.st_uid);
 
     if (pwPtr == NULL) {
@@ -1394,6 +1418,9 @@
 	Tcl_DStringFree(&ds);
     }
     endpwent();
+#else
+    *attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_uid);
+#endif
     return TCL_OK;
 }
 
@@ -1463,8 +1490,10 @@
     Tcl_Obj *fileName,		/* The name of the file (UTF-8). */
     Tcl_Obj *attributePtr)	/* New group for file. */
 {
-    long gid;
     int result;
+
+#if !defined(_WRS_KERNEL)
+    long gid;
     CONST char *native;
 
     if (Tcl_GetLongFromObj(NULL, attributePtr, &gid) != TCL_OK) {
@@ -1495,6 +1524,10 @@
     result = chown(native, (uid_t) -1, (gid_t) gid);	/* INTL: Native. */
 
     endgrent();
+#else
+    result = -1;
+    errno = ENOTSUP;
+#endif
     if (result != 0) {
 	if (interp != NULL) {
 	    Tcl_AppendResult(interp, "could not set group for file \"",
@@ -1529,8 +1562,10 @@
     Tcl_Obj *fileName,		/* The name of the file (UTF-8). */
     Tcl_Obj *attributePtr)	/* New owner for file. */
 {
-    long uid;
     int result;
+
+#if !defined(_WRS_KERNEL)
+    long uid;
     CONST char *native;
 
     if (Tcl_GetLongFromObj(NULL, attributePtr, &uid) != TCL_OK) {
@@ -1558,6 +1593,10 @@
 
     native = Tcl_FSGetNativePath(fileName);
     result = chown(native, (uid_t) uid, (gid_t) -1);	/* INTL: Native. */
+#else
+    result = -1;
+    errno = ENOTSUP;
+#endif
 
     if (result != 0) {
 	if (interp != NULL) {
diff -r -u -N tcl8.5.2.orig/unix/tclUnixFile.c tcl8.5.2/unix/tclUnixFile.c
--- tcl8.5.2.orig/unix/tclUnixFile.c	2007-12-13 10:28:42.000000000 -0500
+++ tcl8.5.2/unix/tclUnixFile.c	2008-03-31 15:01:28.039743000 -0400
@@ -442,7 +442,11 @@
 #endif
 			(buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
 		((types->perm & TCL_GLOB_PERM_R) &&
+#if !defined (_WRS_KERNEL)
 			(access(nativeEntry, R_OK) != 0)) ||
+#else
+			(access(nativeEntry, F_OK) != 0)) ||
+#endif
 		((types->perm & TCL_GLOB_PERM_W) &&
 			(access(nativeEntry, W_OK) != 0)) ||
 		((types->perm & TCL_GLOB_PERM_X) &&
@@ -562,6 +566,7 @@
     Tcl_DString *bufferPtr)	/* Uninitialized or free DString filled with
 				 * name of user's home directory. */
 {
+#if !defined(_WRS_KERNEL)
     struct passwd *pwPtr;
     Tcl_DString ds;
     CONST char *native;
@@ -577,6 +582,9 @@
     Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
     endpwent();
     return Tcl_DStringValue(bufferPtr);
+#else
+    return NULL;
+#endif
 }
 
 /*
@@ -601,6 +609,16 @@
     int mode)			/* Permission setting. */
 {
     CONST char *path = Tcl_FSGetNativePath(pathPtr);
+#if defined (_WRS_KERNEL)
+    /*
+     * access() refuses to check permissions beyond testing a file's
+     * existence for remote or host-based file systems.  At least
+     * pretend that files are readable.
+     */
+    if (mode == R_OK) {
+	mode = F_OK;
+    }
+#endif
     if (path == NULL) {
 	return -1;
     } else {
@@ -780,7 +798,7 @@
     Tcl_DString *linkPtr)	/* Uninitialized or free DString filled with
 				 * contents of link (UTF-8). */
 {
-#ifndef DJGPP
+#if !defined(DJGPP) && !defined(_WRS_KERNEL)
     char link[MAXPATHLEN];
     int length;
     CONST char *native;
@@ -838,6 +856,7 @@
     Tcl_Obj *toPtr,
     int linkAction)
 {
+#if !defined(_WRS_KERNEL)
     if (toPtr != NULL) {
 	CONST char *src = Tcl_FSGetNativePath(pathPtr);
 	CONST char *target = NULL;
@@ -972,6 +991,10 @@
 	}
 	return linkPtr;
     }
+#else
+    errno = ENOTSUP;
+    return NULL;
+#endif
 }
 #endif /* S_IFLNK */
 
diff -r -u -N tcl8.5.2.orig/unix/tclUnixInit.c tcl8.5.2/unix/tclUnixInit.c
--- tcl8.5.2.orig/unix/tclUnixInit.c	2007-12-13 10:28:42.000000000 -0500
+++ tcl8.5.2/unix/tclUnixInit.c	2008-03-31 15:01:28.055367800 -0400
@@ -37,6 +37,13 @@
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
+#if defined (_WRS_KERNEL)
+#include <envLib.h>
+#include <vmLib.h>
+#define getpagesize vmPageSizeGet
+#undef environ
+#endif
+
 /*
  * Define TCL_NO_STACK_CHECK in the compiler options if you want to revert to
  * the old behavior of never checking the stack.
@@ -68,6 +75,16 @@
 #define TCL_RESERVED_STACK_PAGES	8
 #endif
 
+#if defined (_WRS_KERNEL)
+/*
+ * The reported task stack size value can be trusted relatively well, and
+ * the default stack size on some platforms is a mere 20k.
+ */
+
+#undef TCL_RESERVED_STACK_PAGES
+#define TCL_RESERVED_STACK_PAGES 2
+#endif
+
 /*
  * Thread specific data for stack checking.
  */
@@ -382,13 +399,25 @@
      */
 
     if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
-	open("/dev/null", O_RDONLY);
+	open("/dev/null", O_RDONLY
+#if defined (_WRS_KERNEL)
+	     , 0
+#endif
+	     );
     }
     if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
-	open("/dev/null", O_WRONLY);
+	open("/dev/null", O_WRONLY
+#if defined (_WRS_KERNEL)
+	     , 0
+#endif
+	     );
     }
     if (TclOSseek(2, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
-	open("/dev/null", O_WRONLY);
+	open("/dev/null", O_WRONLY
+#if defined (_WRS_KERNEL)
+	     , 0
+#endif
+	     );
     }
 
     /*
@@ -400,9 +429,11 @@
      * different one of its own, if it wants.
      */
 
+#if !defined (_WRS_KERNEL)
 #ifdef SIGPIPE
     (void) signal(SIGPIPE, SIG_IGN);
 #endif /* SIGPIPE */
+#endif
 
 #if defined(__FreeBSD__) && defined(__GNUC__)
     /*
@@ -936,6 +967,7 @@
      */
 
     {
+#if !defined (_WRS_KERNEL)
 	struct passwd *pwEnt = TclpGetPwUid(getuid());
 	const char *user;
 
@@ -945,6 +977,10 @@
 	} else {
 	    user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &ds);
 	}
+#else
+	const char * user = "";
+	Tcl_DStringInit(&ds);	/* ensure cleanliness */
+#endif
 
 	Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
 	Tcl_DStringFree(&ds);
@@ -980,6 +1016,9 @@
 				 * entries in environ (for unsuccessful
 				 * searches). */
 {
+#if defined (_WRS_KERNEL)
+    char ** environ = envGet (0);
+#endif
     int i, result = -1;
     register CONST char *env, *p1, *p2;
     Tcl_DString envString;
@@ -1142,7 +1181,9 @@
     size_t *stackSizePtr)
 {
     size_t rawStackSize;
+#if !defined (_WRS_KERNEL)
     struct rlimit rLimit;	/* The result from getrlimit(). */
+#endif
 
 #ifdef TCL_THREADS
     rawStackSize = TclpThreadGetStackSize();
@@ -1164,6 +1205,7 @@
      */
 #endif /* TCL_THREADS */
 
+#if !defined (_WRS_KERNEL)
     if (getrlimit(RLIMIT_STACK, &rLimit) != 0) {
 	/*
 	 * getrlimit() failed, just fail the whole thing.
@@ -1179,6 +1221,9 @@
 	return TCL_CONTINUE;
     }
     rawStackSize = rLimit.rlim_cur;
+#else
+    rawStackSize = -1;
+#endif
 
     /*
      * Final sanity check on the determined stack size. If we fail this,
@@ -1198,6 +1243,13 @@
      * Calculate a stack size with a safety margin.
      */
 
+    if ((rawStackSize / TCL_MAGIC_STACK_DIVISOR) <
+	(getpagesize() * TCL_RESERVED_STACK_PAGES)) {
+	/* Don't want to return a negative value for the stack size. */
+	STACK_DEBUG(("skipping stack checks with success: stack looks smaller than safety margin\n"));
+	return TCL_CONTINUE;
+    }
+
     *stackSizePtr = (rawStackSize / TCL_MAGIC_STACK_DIVISOR)
 	    - (getpagesize() * TCL_RESERVED_STACK_PAGES);
 
diff -r -u -N tcl8.5.2.orig/unix/tclUnixNotfy.c tcl8.5.2/unix/tclUnixNotfy.c
--- tcl8.5.2.orig/unix/tclUnixNotfy.c	2008-03-11 18:23:50.000000000 -0400
+++ tcl8.5.2/unix/tclUnixNotfy.c	2008-03-31 15:38:03.464766200 -0400
@@ -18,6 +18,20 @@
 				 * in tclMacOSXNotify.c */
 #include <signal.h>
 
+#if defined (_WRS_KERNEL)
+#include <selectLib.h>
+#if defined (TCL_THREADS)
+/*
+ * We don't want the threaded notifier on VxWorks.  Not yet.  Our motivation
+ * for defining TCL_THREADS was just to enable proper locking between
+ * independent Tcl threads.  Each thread can use its own non-threaded
+ * notifier for now.  I'm not sure if this is intended to work, but it
+ * does so far.
+ */
+#undef TCL_THREADS
+#endif
+#endif
+
 /*
  * This code does deep stub magic to allow replacement of the notifier at
  * runtime.
diff -r -u -N tcl8.5.2.orig/unix/tclUnixPipe.c tcl8.5.2/unix/tclUnixPipe.c
--- tcl8.5.2.orig/unix/tclUnixPipe.c	2008-03-14 12:32:52.000000000 -0400
+++ tcl8.5.2/unix/tclUnixPipe.c	2008-03-31 15:38:02.996022200 -0400
@@ -60,8 +60,10 @@
 static int		PipeOutputProc(ClientData instanceData,
 			    const char *buf, int toWrite, int *errorCode);
 static void		PipeWatchProc(ClientData instanceData, int mask);
+#if !defined (_WRS_KERNEL)
 static void		RestoreSignals(void);
 static int		SetupStdFile(TclFile file, int type);
+#endif
 
 /*
  * This structure describes the channel type structure for command pipe based
@@ -191,6 +193,7 @@
 TclpCreateTempFile(
     const char *contents)	/* String to write into temp file, or NULL. */
 {
+#if !defined (_WRS_KERNEL)
     char fileName[L_tmpnam + 9];
     const char *native;
     Tcl_DString dstring;
@@ -223,6 +226,10 @@
 	TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET);
     }
     return MakeFile(fd);
+#else
+    errno = ENOTSUP;
+    return NULL;
+#endif
 }
 
 /*
@@ -244,6 +251,7 @@
 Tcl_Obj *
 TclpTempFileName(void)
 {
+#if !defined (_WRS_KERNEL)
     char fileName[L_tmpnam + 9];
     Tcl_Obj *result = NULL;
     int fd;
@@ -267,6 +275,10 @@
     result = TclpNativeToNormalized((ClientData) fileName);
     close(fd);
     return result;
+#else
+    errno = ENOTSUP;
+    return NULL;
+#endif
 }
 
 /*
@@ -292,6 +304,7 @@
     TclFile *writePipe)		/* Location to store file handle for write
 				 * side of pipe. */
 {
+#if !defined (_WRS_KERNEL)
     int pipeIds[2];
 
     if (pipe(pipeIds) != 0) {
@@ -304,6 +317,10 @@
     *readPipe = MakeFile(pipeIds[0]);
     *writePipe = MakeFile(pipeIds[1]);
     return 1;
+#else
+    errno = ENOTSUP;
+    return 0;
+#endif
 }
 
 /*
@@ -326,6 +343,7 @@
 TclpCloseFile(
     TclFile file)	/* The file to close. */
 {
+#if !defined (_WRS_KERNEL)
     int fd = GetFd(file);
 
     /*
@@ -338,6 +356,10 @@
 
     Tcl_DeleteFileHandler(fd);
     return close(fd);
+#else
+    errno = ENOTSUP;
+    return -1;
+#endif
 }
 
 /*
@@ -394,6 +416,7 @@
 				 * filled with the process id of the child
 				 * process. */
 {
+#if !defined (_WRS_KERNEL)
     TclFile errPipeIn, errPipeOut;
     int count, status, fd;
     char errSpace[200 + TCL_INTEGER_SPACE];
@@ -536,6 +559,10 @@
 	TclpCloseFile(errPipeOut);
     }
     return TCL_ERROR;
+#else
+    Tcl_AppendResult(interp, "spawning processes is not supported", NULL);
+    return TCL_ERROR;
+#endif
 }
 
 /*
@@ -556,6 +583,7 @@
  *----------------------------------------------------------------------
  */
 
+#if !defined (_WRS_KERNEL)
 static void
 RestoreSignals(void)
 {
@@ -611,6 +639,7 @@
     signal(SIGTTOU, SIG_DFL);
 #endif
 }
+#endif
 
 /*
  *----------------------------------------------------------------------
@@ -631,6 +660,7 @@
  *----------------------------------------------------------------------
  */
 
+#if !defined (_WRS_KERNEL)
 static int
 SetupStdFile(
     TclFile file,		/* File to dup, or NULL. */
@@ -690,6 +720,7 @@
     }
     return 1;
 }
+#endif
 
 /*
  *----------------------------------------------------------------------
@@ -841,6 +872,7 @@
 				 * TCL_MODE_BLOCKING or
 				 * TCL_MODE_NONBLOCKING. */
 {
+#if !defined (_WRS_KERNEL)
     PipeState *psPtr = instanceData;
 
     if (psPtr->inFile) {
@@ -857,6 +889,9 @@
     psPtr->isNonBlocking = (mode == TCL_MODE_NONBLOCKING);
 
     return 0;
+#else
+    return ENOTSUP;
+#endif
 }
 
 /*
@@ -883,6 +918,7 @@
     ClientData instanceData,	/* The pipe to close. */
     Tcl_Interp *interp)		/* For error reporting. */
 {
+#if !defined (_WRS_KERNEL)
     PipeState *pipePtr;
     Tcl_Channel errChan;
     int errorCode, result;
@@ -938,6 +974,9 @@
 	return result;
     }
     return errorCode;
+#else
+    return ENOTSUP;
+#endif
 }
 
 /*
@@ -966,6 +1005,7 @@
 				 * buffer? */
     int *errorCodePtr)		/* Where to store error code. */
 {
+#if !defined (_WRS_KERNEL)
     PipeState *psPtr = (PipeState *) instanceData;
     int bytesRead;		/* How many bytes were actually read from the
 				 * input device? */
@@ -990,6 +1030,10 @@
     } else {
 	return bytesRead;
     }
+#else
+    *errorCodePtr = ENOTSUP;
+    return -1;
+#endif
 }
 
 /*
@@ -1017,6 +1061,7 @@
     int toWrite,		/* How many bytes to write? */
     int *errorCodePtr)		/* Where to store error code. */
 {
+#if !defined (_WRS_KERNEL)
     PipeState *psPtr = (PipeState *) instanceData;
     int written;
 
@@ -1037,6 +1082,10 @@
     } else {
 	return written;
     }
+#else
+    *errorCodePtr = ENOTSUP;
+    return -1;
+#endif
 }
 
 /*
@@ -1147,6 +1196,7 @@
     int *statPtr,
     int options)
 {
+#if !defined (_WRS_KERNEL)
     int result;
     pid_t real_pid;
 
@@ -1157,6 +1207,10 @@
 	    return (Tcl_Pid) INT2PTR(result);
 	}
     }
+#else
+    errno = ENOTSUP;
+    return (Tcl_Pid) INT2PTR(-1);
+#endif
 }
 
 /*
diff -r -u -N tcl8.5.2.orig/unix/tclUnixPort.h tcl8.5.2/unix/tclUnixPort.h
--- tcl8.5.2.orig/unix/tclUnixPort.h	2008-03-11 18:26:27.000000000 -0400
+++ tcl8.5.2/unix/tclUnixPort.h	2008-03-31 15:38:02.480403800 -0400
@@ -41,7 +41,9 @@
 #ifdef HAVE_NET_ERRNO_H
 #   include <net/errno.h>
 #endif
+#if !defined(_WRS_KERNEL)
 #include <pwd.h>
+#endif
 #include <signal.h>
 #ifdef HAVE_SYS_PARAM_H
 #   include <sys/param.h>
@@ -83,7 +85,9 @@
 #   define TclOSlstat		lstat
 #endif
 
+#if !defined(_WRS_KERNEL)
 #include <sys/file.h>
+#endif
 #ifdef HAVE_SYS_SELECT_H
 #   include <sys/select.h>
 #endif
@@ -242,6 +246,7 @@
  * gettimeofday call, then must use times() instead.
  */
 
+#if !defined (_WRS_KERNEL)
 #ifdef NO_GETTOD
 #   include <sys/times.h>
 #else
@@ -249,11 +254,14 @@
 #	define gettimeofday BSDgettimeofday
 #   endif
 #endif
+#endif
 
+#if !defined(_WRS_KERNEL)
 #ifdef GETTOD_NOT_DECLARED
 EXTERN int		gettimeofday _ANSI_ARGS_((struct timeval *tp,
 			    struct timezone *tzp));
 #endif
+#endif
 
 /*
  * Define access mode constants if they aren't already defined.
@@ -286,7 +294,7 @@
  * define "lstat" to use "stat" instead.
  */
 
-#ifndef S_IFLNK
+#if !defined(S_IFLNK) || defined(_WRS_KERNEL)
 #   undef TclOSlstat
 #   define lstat	stat
 #   define lstat64	stat64
@@ -598,6 +606,7 @@
 EXTERN struct tm *     	TclpLocaltime(CONST time_t *);
 EXTERN struct tm *     	TclpGmtime(CONST time_t *);
 EXTERN char *          	TclpInetNtoa(struct in_addr);
+#if !defined (_WRS_KERNEL)
 /* #define localtime(x)	TclpLocaltime(x)
  * #define gmtime(x)	TclpGmtime(x)    */
 #   undef inet_ntoa
@@ -620,6 +629,7 @@
 #	    endif
 #	endif /* HAVE_PTHREAD_GETATTR_NP */
 #   endif /* HAVE_PTHREAD_ATTR_GET_NP */
+#endif /* _WRS_KERNEL */
 #endif /* TCL_THREADS */
 
 /*
@@ -630,8 +640,10 @@
  * to the TSD data. 
  */
 
+#if !defined (_WRS_KERNEL)
 #include <pwd.h>
 #include <grp.h>
+#endif
 
 MODULE_SCOPE struct passwd*  TclpGetPwNam(const char *name);
 MODULE_SCOPE struct group*   TclpGetGrNam(const char *name);
diff -r -u -N tcl8.5.2.orig/unix/tclUnixSock.c tcl8.5.2/unix/tclUnixSock.c
--- tcl8.5.2.orig/unix/tclUnixSock.c	2007-12-13 10:28:42.000000000 -0500
+++ tcl8.5.2/unix/tclUnixSock.c	2008-03-31 15:01:28.070992600 -0400
@@ -13,6 +13,10 @@
 
 #include "tclInt.h"
 
+#if defined (_WRS_KERNEL)
+#include <hostLib.h>
+#endif
+
 /*
  * The following variable holds the network name of this host.
  */
diff -r -u -N tcl8.5.2.orig/unix/tclUnixTime.c tcl8.5.2/unix/tclUnixTime.c
--- tcl8.5.2.orig/unix/tclUnixTime.c	2007-12-13 10:28:42.000000000 -0500
+++ tcl8.5.2/unix/tclUnixTime.c	2008-03-31 15:01:28.086617400 -0400
@@ -21,6 +21,10 @@
 #define TM_YEAR_BASE 1900
 #define IsLeapYear(x)	(((x)%4 == 0) && ((x)%100 != 0 || (x)%400 == 0))
 
+#if defined (_WRS_KERNEL)
+#include <tickLib.h>
+#endif
+
 /*
  * TclpGetDate is coded to return a pointer to a 'struct tm'. For thread
  * safety, this structure must be in thread-specific data. The 'tmKey'
@@ -38,11 +42,13 @@
  * this mutex to try to protect them.
  */
 
+#if !defined (_WRS_KERNEL)
 TCL_DECLARE_MUTEX(tmMutex)
 
 static char *lastTZ = NULL;	/* Holds the last setting of the TZ
 				 * environment variable, or an empty string if
 				 * the variable was not set. */
+#endif
 
 /*
  * Static functions declared in this file.
@@ -110,6 +116,7 @@
 {
     unsigned long now;
 
+#if !defined (_WRS_KERNEL)
 #ifdef NO_GETTOD
     if (tclGetTimeProcPtr != NativeGetTime) {
 	Tcl_Time time;
@@ -130,6 +137,9 @@
     (*tclGetTimeProcPtr) (&time, tclTimeClientData);
     now = time.sec*1000000 + time.usec;
 #endif
+#else
+    now = tickGet ();
+#endif
 
     return now;
 }
@@ -602,12 +612,19 @@
     Tcl_Time *timePtr,
     ClientData clientData)
 {
+#if !defined (_WRS_KERNEL)
     struct timeval tv;
     struct timezone tz;
 
     (void) gettimeofday(&tv, &tz);
     timePtr->sec = tv.tv_sec;
     timePtr->usec = tv.tv_usec;
+#else
+    struct timespec ts;
+    clock_gettime (CLOCK_REALTIME, &ts);
+    timePtr->sec = ts.tv_sec;
+    timePtr->usec = ts.tv_nsec / 1000;
+#endif
 }
 /*
  *----------------------------------------------------------------------
@@ -631,6 +648,7 @@
 static void
 SetTZIfNecessary(void)
 {
+#if !defined (_WRS_KERNEL)
     CONST char *newTZ = getenv("TZ");
 
     Tcl_MutexLock(&tmMutex);
@@ -648,6 +666,7 @@
 	strcpy(lastTZ, newTZ);
     }
     Tcl_MutexUnlock(&tmMutex);
+#endif
 }
 
 /*
@@ -667,12 +686,14 @@
  *----------------------------------------------------------------------
  */
 
+#if !defined (_WRS_KERNEL)
 static void
 CleanupMemory(
     ClientData ignored)
 {
     ckfree(lastTZ);
 }
+#endif
 
 /*
  * Local Variables:
diff -r -u -N tcl8.5.2.orig/unix/tclVxWorksInit.c tcl8.5.2/unix/tclVxWorksInit.c
--- tcl8.5.2.orig/unix/tclVxWorksInit.c	1969-12-31 19:00:00.000000000 -0500
+++ tcl8.5.2/unix/tclVxWorksInit.c	2008-03-31 15:01:28.086617400 -0400
@@ -0,0 +1,847 @@
+/*
+ * tclVxWorksInit.c --
+ *
+ *      Provides the "tcl" and "tclsh" entrypoints for VxWorks DKM.
+ *
+ *      "tcl" registers the Tcl interpreter with the kernel, and
+ *      switches to it.  The "C" command can be used to return to
+ *      the C kernel shell.
+ *
+ *      "tclsh" takes a single null-terminated string parameter,
+ *      which is parsed as a command line.  The first argument on
+ *      the command line is used as the name of a Tcl script that
+ *      is run in a new interpreter.  The remaining arguments are
+ *      used to initialize argv.
+ */
+
+#include "tcl.h"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Shell Interpreter
+ *
+ *----------------------------------------------------------------------
+ */
+
+#include <tclInt.h>
+#include <vxWorks.h>
+#include <ptyDrv.h>
+#include <sysLib.h>
+#include <taskLib.h>
+#include <shellLib.h>
+#include <shellConfigLib.h>
+#include <shellDataLib.h>
+#include <shellInterpLib.h>
+#include <shellPromptLib.h>
+#include <private/shellLibP.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+
+/*
+ * This symbol is exported.  Users should set it to the path that contains
+ * init.tcl before running tclsh or entering the Tcl shell.
+ */
+
+typedef enum {
+    PROMPT_NONE,		/* Print no prompt */
+    PROMPT_START,		/* Print prompt for command start */
+    PROMPT_CONTINUE		/* Print prompt for command continuation */
+} PromptType;
+
+typedef struct InteractiveState {
+    Tcl_Obj *commandPtr;	/* Used to assemble lines of input into Tcl
+				 * commands. */
+    PromptType lastPrompt;	/* Last prompt that was printed */
+    PromptType prompt;		/* Next prompt to print */
+    Tcl_Interp *interp;		/* Interpreter that evaluates interactive
+				 * commands. */
+} InteractiveState;
+
+static int vxTclShellConfigSet (ClientData, Tcl_Interp *, int objc, Tcl_Obj *CONST objv[]);
+static int vxTclShellEvaluate (ClientData, Tcl_Interp *, int objc, Tcl_Obj *CONST objv[]);
+static int vxTclShellExec (ClientData, Tcl_Interp *, int objc, Tcl_Obj *CONST objv[]);
+
+/*
+ * This is used to "exit" from the interactive Tcl session back to the
+ * "C" interpreter.
+ */
+
+static
+int
+vxTclExit (ClientData clientData,
+	   Tcl_Interp * interp,
+	   int objc,
+	   Tcl_Obj *CONST objv[])
+{
+    InteractiveState * isPtr =
+	(InteractiveState *) clientData;
+
+    /*
+     * Delete the current interpreter and return to the C shell.
+     */
+
+    Tcl_DeleteInterp (isPtr->interp);
+    isPtr->interp = NULL;
+    shellPromptFmtSet (CURRENT_SHELL_SESSION,
+		       "Tcl",
+		       "%% ");
+    shellConfigValueSet (CURRENT_SHELL_SESSION, SHELL_CFG_INTERP, "C");
+    return TCL_OK;
+}
+
+/*
+ * Initialize the state for the interactive Tcl session.
+ */
+
+static
+int
+vxTclInitState (InteractiveState * isPtr)
+{
+    isPtr->interp = Tcl_CreateInterp ();
+    Tcl_InitMemory (isPtr->interp);
+
+    if (Tcl_Init (isPtr->interp) == TCL_ERROR) {
+	Tcl_Channel errChannel = Tcl_GetStdChannel (TCL_STDERR);
+	if (errChannel != (Tcl_Channel) NULL) {
+	    Tcl_WriteObj (errChannel, Tcl_GetObjResult (isPtr->interp));
+	    Tcl_WriteChars (errChannel, "\n", 1);
+	}
+
+	return ERROR;
+    }
+
+    /*
+     * exit is evil and must be overruled.
+     */
+
+    Tcl_CreateObjCommand (isPtr->interp, "exit", vxTclExit,
+			  (ClientData) isPtr, NULL);
+
+    /*
+     * Useful extensions.
+     */
+
+    Tcl_CreateObjCommand (isPtr->interp, "shellConfigSet",
+			  vxTclShellConfigSet,
+			  NULL, NULL);
+    Tcl_CreateObjCommand (isPtr->interp, "shellEvaluate",
+			  vxTclShellEvaluate,
+			  NULL, NULL);
+    Tcl_CreateObjCommand (isPtr->interp, "shellExec",
+			  vxTclShellExec,
+			  NULL, NULL);
+
+    isPtr->lastPrompt = PROMPT_NONE;
+    isPtr->prompt = PROMPT_START;
+    isPtr->commandPtr = Tcl_NewObj ();
+    Tcl_IncrRefCount (isPtr->commandPtr);
+    return OK;
+}
+
+static
+STATUS
+vxTclInitialize (SHELL_INTERP_CTX * pInterpCtx)
+{
+    InteractiveState * isPtr =
+	(InteractiveState *) malloc (sizeof (InteractiveState));
+
+    if (vxTclInitState (isPtr) != OK) {
+	/* Otherwise, we're hosed. */
+	shellConfigValueSet (CURRENT_SHELL_SESSION, SHELL_CFG_INTERP, "C");
+	free (isPtr);
+	return ERROR;
+    }
+
+    pInterpCtx->pInterpParam = (void *) isPtr;
+    return OK;
+}
+
+static
+STATUS
+vxTclFinalize (SHELL_INTERP_CTX * pInterpCtx)
+{
+    InteractiveState * isPtr =
+	(InteractiveState *) pInterpCtx->pInterpParam;
+
+    if (isPtr) {
+	if (isPtr->commandPtr) {
+	    Tcl_DecrRefCount (isPtr->commandPtr);
+	}
+
+	if (isPtr->interp) {
+	    Tcl_DeleteInterp (isPtr->interp);
+	}
+    }
+
+    free (isPtr);
+    return OK;
+}
+
+static
+STATUS
+vxTclParse (SHELL_INTERP_CTX * pInterpCtx,
+	    const char * inputLine,
+	    BOOL isInteractive)
+{
+    InteractiveState *isPtr =
+	(InteractiveState *) pInterpCtx->pInterpParam;
+    Tcl_Obj *commandPtr;
+    Tcl_Interp *interp;
+    int code, length;
+
+    if (!isPtr->interp) {
+	if (vxTclInitState (isPtr) != OK) {
+	    printf ("error: failed to initialize Tcl interpreter.\n");
+	    shellConfigValueSet (CURRENT_SHELL_SESSION, SHELL_CFG_INTERP, "C");
+	    return ERROR;
+	}
+    }
+
+    interp = isPtr->interp;
+    commandPtr = isPtr->commandPtr;
+
+    Tcl_Preserve (interp);
+
+    if (Tcl_IsShared (commandPtr)) {
+	Tcl_DecrRefCount(commandPtr);
+	commandPtr = Tcl_DuplicateObj (commandPtr);
+	Tcl_IncrRefCount (commandPtr);
+    }
+
+    Tcl_AppendToObj (commandPtr, inputLine, strlen (inputLine));
+    Tcl_AppendToObj (commandPtr, "\n", 1);
+
+    if (!TclObjCommandComplete (commandPtr)) {
+	isPtr->prompt = PROMPT_CONTINUE;
+	goto prompt;
+    }
+
+    isPtr->prompt = PROMPT_START;
+    Tcl_GetStringFromObj (commandPtr, &length);
+    Tcl_SetObjLength (commandPtr, --length);
+
+    code = Tcl_RecordAndEvalObj (interp, commandPtr, TCL_EVAL_GLOBAL);
+    Tcl_DecrRefCount (commandPtr);
+    isPtr->commandPtr = commandPtr = Tcl_NewObj();
+    Tcl_IncrRefCount (commandPtr);
+
+    if (code != TCL_OK) {
+	Tcl_Channel errChannel = Tcl_GetStdChannel (TCL_STDERR);
+	if (errChannel != (Tcl_Channel) NULL) {
+	    Tcl_WriteObj (errChannel, Tcl_GetObjResult (interp));
+	    Tcl_WriteChars (errChannel, "\n", 1);
+	}
+    }
+    else {
+	Tcl_Obj *resultPtr = Tcl_GetObjResult (interp);
+	Tcl_Channel outChannel = Tcl_GetStdChannel (TCL_STDOUT);
+	Tcl_IncrRefCount (resultPtr);
+	Tcl_GetStringFromObj (resultPtr, &length);
+
+	if ((length >0) && (outChannel != (Tcl_Channel) NULL)) {
+	    Tcl_WriteObj (outChannel, resultPtr);
+	    Tcl_WriteChars (outChannel, "\n", 1);
+	}
+
+	Tcl_DecrRefCount(resultPtr);
+    }
+
+ prompt:
+    if (isPtr->prompt != isPtr->lastPrompt && !Tcl_InterpDeleted (interp)) {
+	char * newPrompt;
+	Tcl_Obj * promptCmdPtr;
+	char * promptString;
+	int promptLength;
+
+	if (isPtr->prompt == PROMPT_NONE) {
+	    promptString = "";
+	    promptLength = 0;
+	}
+	else {
+	    promptCmdPtr = Tcl_GetVar2Ex (interp,
+					  ((isPtr->prompt == PROMPT_CONTINUE) ?
+					   "tcl_prompt2" : "tcl_prompt1"),
+					  NULL, TCL_GLOBAL_ONLY);
+
+	    if (promptCmdPtr) {
+		promptString = Tcl_GetStringFromObj (promptCmdPtr, &promptLength);
+	    }
+	    else {
+		promptString = "%% ";
+		promptLength = 3;
+	    }
+	}
+
+	newPrompt = malloc (promptLength + 1);
+	memcpy (newPrompt, promptString, promptLength);
+	newPrompt[promptLength] = '\0';
+
+	shellPromptFmtSet (CURRENT_SHELL_SESSION,
+			   "Tcl",
+			   newPrompt);
+
+	isPtr->lastPrompt = isPtr->prompt;
+	free (newPrompt);
+    }
+
+    Tcl_Release (interp);
+    return OK;
+}
+
+static
+void
+vxTclRestart (SHELL_INTERP_CTX * pInterpCtx)
+{
+    vxTclFinalize (pInterpCtx);
+    if (vxTclInitialize (pInterpCtx) != OK) {
+	/* Otherwise, we're hosed. */
+	shellConfigValueSet (CURRENT_SHELL_SESSION, SHELL_CFG_INTERP, "C");
+    }
+}
+
+STATUS
+vxTclInit (SHELL_INTERP * pInterp)
+{
+    /* This must happen somewhere */
+    Tcl_FindExecutable (NULL);
+
+    /* Initialize the interpreter functions */
+    pInterp->ctxInit = vxTclInitialize;
+    pInterp->ctxFinalize = vxTclFinalize;
+    pInterp->parser = vxTclParse;
+    pInterp->ctxRestart = vxTclRestart;
+    pInterp->evaluate = NULL;		/* no evaluation */
+    pInterp->completion = NULL;		/* no completion */
+
+    /* Initialize name and default prompt */
+    pInterp->name = "Tcl";
+    pInterp->prompt = "%% ";
+
+    return OK;
+}
+
+int
+tcl ()
+{
+    shellInterpRegister (vxTclInit);
+    shellConfigValueSet (CURRENT_SHELL_SESSION,
+			 SHELL_CFG_INTERP,
+			 "Tcl");
+    return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Various useful extensions
+ *
+ *----------------------------------------------------------------------
+ */
+
+static
+int
+vxTclShellConfigSet (ClientData clientData,
+		     Tcl_Interp * interp,
+		     int objc,
+		     Tcl_Obj *CONST objv[])
+{
+    if (objc != 2) {
+	Tcl_WrongNumArgs (interp, 0, objv, "config");
+	return TCL_ERROR;
+    }
+
+    CONST char * config = Tcl_GetStringFromObj (objv[1], NULL);
+
+    shellConfigSet (CURRENT_SHELL_SESSION, config);
+    return TCL_OK;
+}
+
+static
+int
+vxTclShellEvaluate (ClientData clientData,
+		    Tcl_Interp * interp,
+		    int objc,
+		    Tcl_Obj *CONST objv[])
+{
+    CONST char *cmd, *interpreterName;
+    SHELL_EVAL_VALUE sev;
+
+    if (objc < 2 || objc > 3) {
+	Tcl_WrongNumArgs (interp, 0, objv, "cmd ?interpreter?");
+	return TCL_ERROR;
+    }
+
+    cmd = Tcl_GetStringFromObj (objv[1], NULL);
+
+    if (objc == 3) {
+	interpreterName = Tcl_GetStringFromObj (objv[2], NULL);
+    }
+    else {
+	/*
+	 * The documentation says that we can use NULL for the default
+	 * interpreter, but that didn't work for me.  Let's use the "C"
+	 * interpreter as the default.
+	 */
+
+	interpreterName = "C";
+    }
+
+    if (shellInterpEvaluate ((char *) cmd, interpreterName, &sev) != OK) {
+	Tcl_AppendResult (interp, "error evaluating \"", cmd,
+			  "\" in \"", interpreterName,
+			  "\" interpreter: ",
+			  Tcl_PosixError (interp),
+			  NULL);
+	return TCL_ERROR;
+    }
+
+    /*
+     * I did not find any documentation for SHELL_TYPE_VAL.  I've only
+     * ever seen the type set to SHELL_INT.
+     */
+
+    switch (sev.type) {
+    case SHELL_INT:
+	Tcl_SetObjResult (interp, Tcl_NewIntObj (sev.value.intVal));
+	break;
+
+    default:
+	Tcl_SetObjResult (interp, Tcl_ObjPrintf ("error: interpreter returned type %d", sev.type));
+	return TCL_ERROR;
+	break;
+    }
+
+    return TCL_OK;
+}
+
+TCL_DECLARE_MUTEX(vxTclShellExecSync);
+
+static
+int
+vxTclShellExec (ClientData clientData,
+		Tcl_Interp * interp,
+		int objc,
+		Tcl_Obj *CONST objv[])
+{
+    char currentDirectory[MAX_FILENAME_LENGTH+1];
+    CONST char *cmd, *interpreterName;
+    int fdInM, fdInS, fdOutM, fdOutS;
+    int tid, ttw, nUnread;
+    char *shellTaskName;
+    char shellConfig[32];
+    char buffer[2048];
+    int cmdLen, result;
+    Tcl_Obj * output;
+
+    if (objc < 2 || objc > 3) {
+	Tcl_WrongNumArgs (interp, 0, objv, "cmd ?interpreter?");
+	return TCL_ERROR;
+    }
+
+    cmd = Tcl_GetStringFromObj (objv[1], &cmdLen);
+
+    if (objc == 3) {
+	interpreterName = Tcl_GetStringFromObj (objv[2], NULL);
+
+	if (strlen (interpreterName) > 19) {
+	    Tcl_AppendResult (interp, "interpreter name \"",
+			      interpreterName, "\" too long",
+			      NULL);
+	    return TCL_ERROR;
+	}
+    }
+    else {
+	interpreterName = "C";
+    }
+
+    strcpy (shellConfig, "INTERPRETER=");
+    strcat (shellConfig, interpreterName);
+
+    /*
+     * Based on "10.2.15 Executing Shell Commands Programmatically"
+     * in the VxWorks Kernel Programmer's Guide.  Is this the best
+     * way to do this?  No idea, but documentation in this area is
+     * scarce, and it works well enough for me.
+     */
+
+    if (cmdLen > 2047) {
+	Tcl_AppendResult (interp, "command to long", NULL);
+	return TCL_ERROR;
+    }
+
+    /*
+     * For some reason, this procedure resets the current working
+     * directory.  So save it off and reset it afterwards.
+     */
+
+    ioDefPathGet (currentDirectory);
+
+    /*
+     * Using hard-coded pty dev names, this is a critical section.
+     */
+
+    Tcl_MutexLock (&vxTclShellExecSync);
+
+    if (ptyDevCreate ("tclExecIn", 2048, 2048) != OK) {
+	Tcl_AppendResult (interp, "failed to create \"in\" pty: ",
+			  Tcl_PosixError (interp), NULL);
+	Tcl_MutexUnlock (&vxTclShellExecSync);
+	return TCL_ERROR;
+    }
+
+    if (ptyDevCreate ("tclExecOut", 2048, 2048) != OK) {
+	Tcl_AppendResult (interp, "failed to create \"out\" pty: ",
+			  Tcl_PosixError (interp), NULL);
+	ptyDevRemove ("tclExecIn");
+	Tcl_MutexUnlock (&vxTclShellExecSync);
+	return TCL_ERROR;
+    }
+
+    result = TCL_OK;
+    output = Tcl_NewObj ();
+    Tcl_IncrRefCount (output);
+
+    fdInM  = open ("tclExecInM",  O_WRONLY, 0); /* us writing to the shell   */
+    fdInS  = open ("tclExecInS",  O_RDONLY, 0); /* shell reading from us     */
+    fdOutM = open ("tclExecOutM", O_RDONLY, 0); /* us reading from the shell */
+    fdOutS = open ("tclExecOutS", O_WRONLY, 0); /* shell writing to us       */
+
+    if (fdInM < 0 || fdInS < 0 || fdOutM < 0 || fdOutS < 0) {
+	Tcl_AppendResult (interp, "failed to open fds: ",
+			  Tcl_PosixError (interp), NULL);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Start the interpreter.
+     */
+
+    /*
+     * Is the shellTaskName allocated, and do we have to free it?  The
+     * documentation does not say.
+     */
+
+    if (shellGenericInit (shellConfig, 0,
+			  NULL, &shellTaskName,
+			  FALSE, FALSE,
+			  fdInS, fdOutS, fdOutS) != OK) {
+	Tcl_AppendResult (interp, "failed to start shell: ",
+			  Tcl_PosixError (interp), NULL);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Given the buffer size, we expect that we can write the entire
+     * command at once.
+     */
+
+    if (write (fdInM, (char *) cmd, cmdLen) != cmdLen ||
+	write (fdInM, "\n", 1) != 1) {
+	Tcl_AppendResult (interp, "failed to write to shell: ",
+			  Tcl_PosixError (interp), NULL);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Signal EOF to the shell, so that it may terminate.
+     */
+
+    close (fdInM);
+    fdInM = -1;
+
+    /*
+     * We never get an EOF on fdOutM, because fdOutS remains open even
+     * when the shell terminates.  The best we can do is to occasionally
+     * poll if there is data to read, and to see if the shell task is
+     * still alive.  Use a polling period of 100ms.
+     */
+
+    tid = taskNameToId (shellTaskName);
+    ttw = (sysClkRateGet() >= 10) ? (sysClkRateGet()/10) : 1;
+
+    while (tid != ERROR) {
+	if (taskIdVerify (tid) == ERROR) {
+	    break;
+	}
+
+	if (ioctl (fdOutM, FIONWRITE, (int) &nUnread) != OK) {
+	    nUnread = 0;
+	}
+
+	assert (nUnread <= 2048);
+
+	if (nUnread) {
+	    if (read (fdOutM, buffer, nUnread) != nUnread) {
+		Tcl_AppendResult (interp, "failed to read from shell: ",
+				  Tcl_PosixError (interp), NULL);
+		result = TCL_ERROR;
+		goto done;
+	    }
+
+	    Tcl_AppendToObj (output, buffer, nUnread);
+	    continue;
+	}
+
+	/*
+	 * Wait a while before polling again.
+	 */
+
+	taskDelay (ttw);
+    }
+
+    /*
+     * The shell task has terminated.  There may be leftover data.
+     */
+
+    if (ioctl (fdOutM, FIONWRITE, (int) &nUnread) != OK) {
+	nUnread = 0;
+    }
+
+    assert (nUnread <= 2048);
+
+    if (nUnread) {
+	if (read (fdOutM, buffer, nUnread) != nUnread) {
+	    Tcl_AppendResult (interp, "failed to read from shell: ",
+			      Tcl_PosixError (interp), NULL);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+
+	Tcl_AppendToObj (output, buffer, nUnread);
+    }
+
+    /*
+     * Looks good.
+     */
+
+    result = TCL_OK;
+    Tcl_SetObjResult (interp, output);
+
+    /*
+     * Clean up.
+     */
+
+ done:
+    Tcl_DecrRefCount (output);
+
+    if (fdInM  >= 0) close (fdInM);
+    if (fdInS  >= 0) close (fdInS);
+    if (fdOutM >= 0) close (fdOutM);
+    if (fdOutS >= 0) close (fdOutS);
+
+    ptyDevRemove ("tclExecOut");
+    ptyDevRemove ("tclExecIn");
+    ioDefPathSet (currentDirectory);
+
+    Tcl_MutexUnlock (&vxTclShellExecSync);
+
+    return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclsh
+ *
+ *	Entrypoint for VxWorks.  Executes a Tcl script in a new
+ *      interpreter.
+ *
+ * Results:
+ *	Returns OK or ERROR
+ *
+ *----------------------------------------------------------------------
+ */
+
+static
+int
+vxTclshExit (ClientData clientData,
+	     Tcl_Interp * interp,
+	     int objc,
+	     Tcl_Obj *CONST objv[])
+{
+    Tcl_DeleteInterp (interp);
+    return TCL_OK;
+}
+
+int
+tclsh (const char * cmd)
+{
+    const char *bptr, *pptr, *eptr;
+    int argc, argi, result, isquoted;
+    Tcl_DString appName;
+    Tcl_Interp * interp;
+    Tcl_Obj *argvPtr;
+    char *argv[32], *aptr;
+
+    if (!cmd) {
+	printf ("tclsh: error: command line is null\n");
+	return ERROR;
+    }
+
+    argc = 0;
+    pptr = cmd;
+	
+    while (*pptr) {
+	while (isspace ((unsigned char) *pptr)) {
+	    pptr++;
+	}
+
+	if (!*pptr) {
+	    break;
+	}
+		
+	/*
+	 * At the beginning of a parameter.
+	 */
+
+	if (*pptr == '"') {
+	    bptr = ++pptr;
+	    isquoted = 1;
+	}
+	else {
+	    bptr = pptr;
+	    isquoted = 0;
+	}
+		
+	eptr = 0;
+	while (*pptr) {
+	    /*
+	     * In the middle of a parameter.
+	     */
+			
+	    if (*pptr == '\\') {
+		if (*++pptr) {
+		    pptr++;
+		}
+	    }
+	    else if (isquoted && *pptr == '"') {
+		eptr = pptr;
+		pptr++;
+		break;
+	    }
+	    else if (!isquoted && isspace ((unsigned char) *pptr)) {
+		eptr = pptr;
+		pptr++;
+		break;
+	    }
+	    else {
+		pptr++;
+	    }
+	}
+		
+	/*
+	 * At the end of a parameter.
+	 */
+
+	if (!eptr) {
+	    /*
+	     * At the end of the command line.
+	     */
+			
+	    if (isquoted) {
+		printf ("tclsh: error parsing command line: unterminated quote\n");
+		return ERROR;
+	    }
+			
+	    eptr = pptr; 
+	}
+
+	if (argc >= 31) {
+	    printf ("tclsh: too many command-line parameters\n");
+	    return ERROR;
+	}
+
+	argv[argc] = malloc (eptr - bptr + 1);
+
+	for (aptr = argv[argc]; bptr < eptr; aptr++, bptr++) {
+	    if (*bptr == '\\') {
+		bptr++;
+	    }
+	    *aptr = *bptr;
+	}
+
+	*aptr = '\0';
+	argc++;
+    }
+
+    argv[argc] = NULL;
+
+    Tcl_FindExecutable (argv[0]);
+    interp = Tcl_CreateInterp ();
+    Tcl_InitMemory (interp);
+    result = Tcl_Init (interp);
+
+    if (result != TCL_OK) {
+	Tcl_Obj * resultPtr = Tcl_GetObjResult (interp);
+	printf ("error initializing Tcl interpreter: %s\n",
+		Tcl_GetStringFromObj (resultPtr, NULL));
+	Tcl_DeleteInterp (interp);
+	return ERROR;
+    }
+
+    Tcl_ExternalToUtfDString (NULL, argv[0], -1, &appName);
+    Tcl_SetVar (interp, "argv0", Tcl_DStringValue (&appName), TCL_GLOBAL_ONLY);
+    Tcl_DStringFree (&appName);
+
+    argvPtr = Tcl_NewListObj (0, NULL);
+
+    for (argi=1; argi<argc; argi++) {
+	Tcl_DString ds;
+	Tcl_ExternalToUtfDString (NULL, argv[argi], -1, &ds);
+	Tcl_ListObjAppendElement (NULL, argvPtr,
+				  Tcl_NewStringObj(Tcl_DStringValue (&ds),
+						   Tcl_DStringLength(&ds)));
+	Tcl_DStringFree (&ds);
+    }
+
+    Tcl_SetVar2Ex (interp, "argc", NULL, Tcl_NewIntObj (argc-1), TCL_GLOBAL_ONLY);
+    Tcl_SetVar2Ex (interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
+    Tcl_SetVar (interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
+
+    /*
+     * exit is evil and must be replaced.
+     */
+
+    Tcl_CreateObjCommand (interp, "exit", vxTclshExit, NULL, NULL);
+    Tcl_CreateObjCommand (interp, "shellConfigSet",
+			  vxTclShellConfigSet,
+			  NULL, NULL);
+    Tcl_CreateObjCommand (interp, "shellEvaluate",
+			  vxTclShellEvaluate,
+			  NULL, NULL);
+    Tcl_CreateObjCommand (interp, "shellExec",
+			  vxTclShellExec,
+			  NULL, NULL);
+
+    Tcl_Preserve (interp);
+    result = Tcl_EvalFile (interp, argv[0]);
+
+    if (result != TCL_OK) {
+	Tcl_Obj * resultPtr = Tcl_GetObjResult (interp);
+	printf ("error: %s\n", Tcl_GetStringFromObj (resultPtr, NULL));
+    }
+
+    Tcl_DeleteInterp (interp);
+    Tcl_Release (interp);
+
+    for (argi=0; argi<argc; argi++) {
+	free (argv[argi]);
+    }
+
+    return (result == TCL_OK) ? OK : ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff -r -u -N tcl8.5.2.orig/unix/tclVxWorksThrd.c tcl8.5.2/unix/tclVxWorksThrd.c
--- tcl8.5.2.orig/unix/tclVxWorksThrd.c	1969-12-31 19:00:00.000000000 -0500
+++ tcl8.5.2/unix/tclVxWorksThrd.c	2008-03-31 15:01:28.102242200 -0400
@@ -0,0 +1,650 @@
+/*
+ * tclVxWorksThrd.c --
+ *
+ *	This file implements the VxWorks-specific thread support.
+ */
+
+#include "tclInt.h"
+
+#ifdef TCL_THREADS
+
+#include <semLib.h>
+#include <objLib.h>
+#include <sysLib.h>
+#include <taskLib.h>
+
+typedef struct ThreadSpecificData {
+    char nabuf[16];
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * masterLock is used to serialize creation of mutexes, condition variables,
+ * and thread local storage. This is the only place that can count on the
+ * ability to statically initialize the mutex.
+ */
+
+static VX_MUTEX_SEMAPHORE(masterLockStorage);
+static SEM_ID masterLock;
+
+/*
+ * initLock is used to serialize initialization and finalization of Tcl. It
+ * cannot use any dyamically allocated storage.
+ */
+
+static int locksAreInitialized = 0;
+static VX_BINARY_SEMAPHORE(initLockStorage);
+static SEM_ID initLock;
+
+/*
+ * allocLock is used by Tcl's version of malloc for synchronization. For
+ * obvious reasons, cannot use any dyamically allocated storage.
+ */
+
+static VX_MUTEX_SEMAPHORE(allocLockStorage);
+static SEM_ID allocLock;
+
+/*
+ * These are for the critical sections inside this file.
+ */
+
+#define MASTER_LOCK	semTake(masterLock, WAIT_FOREVER)
+#define MASTER_UNLOCK	semGive(masterLock)
+
+#endif /* TCL_THREADS */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadCreate --
+ *
+ *	This procedure creates a new thread.
+ *
+ * Results:
+ *	TCL_OK if the thread could be created. The thread ID is returned in a
+ *	parameter.
+ *
+ * Side effects:
+ *	A new thread is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpThreadCreate(
+    Tcl_ThreadId *idPtr,	/* Return, the ID of the thread */
+    Tcl_ThreadCreateProc proc,	/* Main() function of the thread */
+    ClientData clientData,	/* The one argument to Main() */
+    int stackSize,		/* Size of stack for the new thread */
+    int flags)			/* Flags controlling behaviour of the new
+				 * thread. */
+{
+    errno = ENOTSUP;
+    return ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_JoinThread --
+ *
+ *	This procedure waits upon the exit of the specified thread.
+ *
+ * Results:
+ *	TCL_OK if the wait was successful, TCL_ERROR else.
+ *
+ * Side effects:
+ *	The result area is set to the exit code of the thread we waited upon.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_JoinThread(
+    Tcl_ThreadId threadId,	/* Id of the thread to wait upon. */
+    int *state)			/* Reference to the storage the result of the
+				 * thread we wait upon will be written into.
+				 * May be NULL. */
+{
+    errno = ENOTSUP;
+    return TCL_ERROR;
+}
+
+#ifdef TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadExit --
+ *
+ *	This procedure terminates the current thread.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	This procedure terminates the current thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpThreadExit(
+    int status)
+{
+}
+#endif /* TCL_THREADS */
+
+#ifdef TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadGetStackSize --
+ *
+ *	This procedure returns the size of the current thread's stack.
+ *
+ * Results:
+ *	Stack size (in bytes?) or -1 for error or 0 for undeterminable.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+size_t
+TclpThreadGetStackSize(void)
+{
+    TASK_DESC td;
+
+    if (taskInfoGet (0, &td) != OK) {
+	return 0;
+    }
+
+    return td.td_stackSize;
+}
+#endif /* TCL_THREADS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCurrentThread --
+ *
+ *	This procedure returns the ID of the currently running thread.
+ *
+ * Results:
+ *	A thread ID.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_ThreadId
+Tcl_GetCurrentThread(void)
+{
+#ifdef TCL_THREADS
+    return (Tcl_ThreadId) taskIdSelf ();
+#else
+    return (Tcl_ThreadId) 0;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpInitLock
+ *
+ *	This procedure is used to grab a lock that serializes initialization
+ *	and finalization of Tcl. On some platforms this may also initialize
+ *	the mutex used to serialize creation of more mutexes and thread local
+ *	storage keys.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Acquire the initialization mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpInitLock(void)
+{
+#ifdef TCL_THREADS
+    taskLock ();
+    if (!locksAreInitialized) {
+	initLock = semBInitialize (initLockStorage, 0, SEM_FULL);
+	masterLock = semMInitialize (masterLockStorage, 0);
+	allocLock = semMInitialize (allocLockStorage, 0);
+	locksAreInitialized = 1;
+    }
+    taskUnlock ();
+
+    semTake (initLock, WAIT_FOREVER);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeLock
+ *
+ *	This procedure is used to destroy all private resources used in this
+ *	file.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Destroys everything private. TclpInitLock must be held entering this
+ *	function.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeLock(void)
+{
+#ifdef TCL_THREADS
+    taskLock ();
+    locksAreInitialized = 0;
+    semDelete (allocLock);
+    semDelete (masterLock);
+    semDelete (initLock);
+    taskUnlock ();
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpInitUnlock
+ *
+ *	This procedure is used to release a lock that serializes
+ *	initialization and finalization of Tcl.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Release the initialization mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpInitUnlock(void)
+{
+#ifdef TCL_THREADS
+    semGive (initLock);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMasterLock
+ *
+ *	This procedure is used to grab a lock that serializes creation and
+ *	finalization of serialization objects. This interface is only needed
+ *	in finalization; it is hidden during creation of the objects.
+ *
+ *	This lock must be different than the initLock because the initLock is
+ *	held during creation of syncronization objects.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Acquire the master mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpMasterLock(void)
+{
+#ifdef TCL_THREADS
+    semTake (masterLock, WAIT_FOREVER);
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMasterUnlock
+ *
+ *	This procedure is used to release a lock that serializes creation and
+ *	finalization of synchronization objects.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Release the master mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpMasterUnlock(void)
+{
+#ifdef TCL_THREADS
+    semGive (masterLock);
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetAllocMutex
+ *
+ *	This procedure returns a pointer to a statically initialized mutex for
+ *	use by the memory allocator. The alloctor must use this lock, because
+ *	all other locks are allocated...
+ *
+ * Results:
+ *	A pointer to a mutex that is suitable for passing to Tcl_MutexLock and
+ *	Tcl_MutexUnlock.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Mutex *
+Tcl_GetAllocMutex(void)
+{
+#ifdef TCL_THREADS
+    return (Tcl_Mutex *) &allocLock;
+#else
+    return NULL;
+#endif
+}
+
+#ifdef TCL_THREADS
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MutexLock --
+ *
+ *	This procedure is invoked to lock a mutex. This procedure handles
+ *	initializing the mutex, if necessary. The caller can rely on the fact
+ *	that Tcl_Mutex is an opaque pointer. This routine will change that
+ *	pointer from NULL after first use.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	May block the current thread. The mutex is aquired when this returns.
+ *	Will allocate memory for a pthread_mutex_t and initialize this the
+ *	first time this Tcl_Mutex is used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_MutexLock(
+    Tcl_Mutex *mutexPtr)	/* Really (SEM_ID *) */
+{
+    SEM_ID mutex;
+
+    if (*mutexPtr == NULL) {
+	MASTER_LOCK;
+	if (*mutexPtr == NULL) {
+	    mutex = semMCreate (0);
+	    *mutexPtr = (Tcl_Mutex) mutex;
+	    TclRememberMutex (mutexPtr);
+	}
+	MASTER_UNLOCK;
+    }
+
+    mutex = *((SEM_ID *) mutexPtr);
+    semTake (mutex, WAIT_FOREVER);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MutexUnlock --
+ *
+ *	This procedure is invoked to unlock a mutex. The mutex must have been
+ *	locked by Tcl_MutexLock.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The mutex is released when this returns.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_MutexUnlock(
+    Tcl_Mutex *mutexPtr)	/* Really (SEM_ID *) */
+{
+    SEM_ID mutex = *((SEM_ID *) mutexPtr);
+    semGive (mutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeMutex --
+ *
+ *	This procedure is invoked to clean up one mutex. This is only safe to
+ *	call at the end of time.
+ *
+ *	This assumes the Master Lock is held.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The mutex list is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeMutex(
+    Tcl_Mutex *mutexPtr)
+{
+    if (*mutexPtr) {
+	SEM_ID mutex = *((SEM_ID *) mutexPtr);
+	semDelete (mutex);
+	*mutexPtr = NULL;
+    }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConditionWait --
+ *
+ *	This procedure is invoked to wait on a condition variable. The mutex
+ *	is automically released as part of the wait, and automatically grabbed
+ *	when the condition is signaled.
+ *
+ *	The mutex must be held when this procedure is called.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	May block the current thread. The mutex is aquired when this returns.
+ *	Will allocate memory for a pthread_mutex_t and initialize this the
+ *	first time this Tcl_Mutex is used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ConditionWait(
+    Tcl_Condition *condPtr,	/* Really (SEM_ID *) */
+    Tcl_Mutex *mutexPtr,	/* Really (SEM_ID *) */
+    Tcl_Time *timePtr)		/* Timeout on waiting period */
+{
+    unsigned int ticks;
+    SEM_ID mutex;
+    SEM_ID cond;
+
+    if (*condPtr == NULL) {
+	MASTER_LOCK;
+
+	/*
+	 * Double check inside mutex to avoid race, then initialize condition
+	 * variable if necessary.
+	 */
+
+	if (*condPtr == NULL) {
+	    cond = semBCreate (0, SEM_EMPTY);
+	    *condPtr = (Tcl_Condition) cond;
+	    TclRememberCondition (condPtr);
+	}
+
+	MASTER_UNLOCK;
+    }
+
+    mutex = *((SEM_ID *) mutexPtr);
+    cond = *((SEM_ID *) cond);
+
+
+    if (timePtr == NULL) {
+	ticks = WAIT_FOREVER;
+    }
+    else {
+	unsigned int msecs = ((timePtr->sec * 1000) +
+			      (timePtr->usec / 1000));
+	ticks = msecs * sysClkRateGet() / 1000;
+    }
+
+    semGive (mutex);
+    semTake (cond, ticks);
+    semTake (mutex, WAIT_FOREVER);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConditionNotify --
+ *
+ *	This procedure is invoked to signal a condition variable.
+ *
+ *	The mutex must be held during this call to avoid races, but this
+ *	interface does not enforce that.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	May unblock another thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ConditionNotify(
+    Tcl_Condition *condPtr)
+{
+    if (*condPtr != NULL) {
+	SEM_ID cond = *((SEM_ID *) cond);
+	semGive (cond);
+    } else {
+	/*
+	 * Noone has used the condition variable, so there are no waiters.
+	 */
+    }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeCondition --
+ *
+ *	This procedure is invoked to clean up a condition variable. This is
+ *	only safe to call at the end of time.
+ *
+ *	This assumes the Master Lock is held.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The condition variable is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeCondition(
+    Tcl_Condition *condPtr)
+{
+    if (*condPtr != NULL) {
+	SEM_ID cond = *((SEM_ID *) cond);
+	semDelete (cond);
+	*condPtr = NULL;
+    }
+}
+#endif /* TCL_THREADS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpReaddir, TclpLocaltime, TclpGmtime, TclpInetNtoa --
+ *
+ *	These procedures replace core C versions to be used in a threaded
+ *	environment.
+ *
+ * Results:
+ *	See documentation of C functions.
+ *
+ * Side effects:
+ *	See documentation of C functions.
+ *
+ * Notes:
+ *	TclpReaddir is no longer used by the core (see 1095909), but it
+ *	appears in the internal stubs table (see #589526).
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_DirEntry *
+TclpReaddir(
+    DIR * dir)
+{
+    return TclOSreaddir(dir);
+}
+
+char *
+TclpInetNtoa(
+    struct in_addr addr)
+{
+#ifdef TCL_THREADS
+    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+    unsigned char *b = (unsigned char*) &addr.s_addr;
+
+    sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
+    return tsdPtr->nabuf;
+#else
+    return inet_ntoa(addr);
+#endif
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */