? chanExec.patch ? generic/Copy of tclPipe.c ? tests/cat ? tests/echo ? tests/exit ? tests/fstderr ? tests/fstdout ? tests/sh ? tests/sleep ? tests/wc ? win/cat ? win/echo ? win/exit ? win/gorp.file ? win/httpd ? win/sh ? win/sleep ? win/tmp ? win/wc ? win/_tcl_test_remove_me.txt Index: generic/tclIO.c =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclIO.c,v retrieving revision 1.41 diff -b -u -r1.41 tclIO.c --- generic/tclIO.c 2001/11/07 04:47:54 1.41 +++ generic/tclIO.c 2001/12/11 10:19:01 @@ -205,11 +205,26 @@ Channel *chanPtr; /* Iterates over open channels. */ ChannelState *nextCSPtr; /* Iterates over open channels. */ ChannelState *statePtr; /* state of channel stack */ + ChannelState* ch[10]; + int c = 0; - for (statePtr = tsdPtr->firstCSPtr; statePtr != (ChannelState *) NULL; - statePtr = nextCSPtr) { + statePtr = tsdPtr->firstCSPtr; + tsdPtr->firstCSPtr = NULL; + + while (statePtr != (ChannelState *) NULL) { chanPtr = statePtr->topChanPtr; nextCSPtr = statePtr->nextCSPtr; + ch[c] = statePtr; + c++; + + if (nextCSPtr == (ChannelState*)0xdddddddd) { + break; + } + if (statePtr->flags & CHANNEL_DEAD) { + statePtr = nextCSPtr; + continue; + } + /* * Set the channel back into blocking mode to ensure that we wait @@ -240,7 +255,7 @@ */ (void) Tcl_Close((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); - + statePtr = nextCSPtr; } else { /* @@ -271,6 +286,7 @@ chanPtr->instanceData = (ClientData) NULL; statePtr->flags |= CHANNEL_DEAD; + statePtr = nextCSPtr; } } } @@ -2393,10 +2409,11 @@ prevCSPtr = prevCSPtr->nextCSPtr) { /* Empty loop body. */ } - if (prevCSPtr == (ChannelState *) NULL) { - panic("FlushChannel: damaged channel list"); - } + if (prevCSPtr != (ChannelState *) NULL) { prevCSPtr->nextCSPtr = statePtr->nextCSPtr; + } else { + /* panic("FlushChannel: damaged channel list"); */ + } } statePtr->nextCSPtr = (ChannelState *) NULL; Index: generic/tclInt.decls =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v retrieving revision 1.38 diff -b -u -r1.38 tclInt.decls --- generic/tclInt.decls 2001/11/23 01:26:47 1.38 +++ generic/tclInt.decls 2001/12/11 10:19:01 @@ -61,8 +61,8 @@ declare 9 {unix win} { int TclCreatePipeline(Tcl_Interp *interp, int argc, char **argv, \ - Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, \ - TclFile *errFilePtr) + Tcl_Pid **pidArrayPtr, Tcl_Channel *inPipePtr, Tcl_Channel *outPipePtr, \ + Tcl_Channel *errFilePtr) } declare 10 generic { int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr, @@ -825,15 +825,15 @@ int TclpCloseFile(TclFile file) } declare 13 win { - Tcl_Channel TclpCreateCommandChannel(TclFile readFile, \ - TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr) + Tcl_Channel TclpCreateCommandChannel(Tcl_Channel readFile, \ + Tcl_Channel writeFile, Tcl_Channel errorFile, int numPids, Tcl_Pid *pidPtr) } declare 14 win { - int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe) + int TclpCreatePipe(Tcl_Channel *readPipe, Tcl_Channel *writePipe) } declare 15 win { int TclpCreateProcess(Tcl_Interp *interp, int argc, char **argv, \ - TclFile inputFile, TclFile outputFile, TclFile errorFile, \ + Tcl_Channel inputFile, Tcl_Channel outputFile, Tcl_Channel errorFile, \ Tcl_Pid *pidPtr) } # Signature changed in 8.1: @@ -860,7 +860,7 @@ # Added in 8.1: declare 22 win { - TclFile TclpCreateTempFile(CONST char *contents) + Tcl_Channel TclpCreateTempFile(CONST char *contents) } declare 23 win { char * TclpGetTZName(int isdst) @@ -922,6 +922,6 @@ # Added in 8.1: declare 9 unix { - TclFile TclpCreateTempFile(CONST char *contents) + Tcl_Channel TclpCreateTempFile(CONST char *contents) } Index: generic/tclInt.h =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v retrieving revision 1.71 diff -b -u -r1.71 tclInt.h --- generic/tclInt.h 2001/11/23 01:26:52 1.71 +++ generic/tclInt.h 2001/12/11 10:19:02 @@ -1632,8 +1632,8 @@ */ EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp *interp, int argc, char **argv, Tcl_Pid **pidArrayPtr, - TclFile *inPipePtr, TclFile *outPipePtr, - TclFile *errFilePtr)); + Tcl_Channel *inPipePtr, Tcl_Channel *outPipePtr, + Tcl_Channel *errFilePtr)); EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp *interp, Namespace *nsPtr, CONST char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Index: generic/tclIntDecls.h =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclIntDecls.h,v retrieving revision 1.31 diff -b -u -r1.31 tclIntDecls.h --- generic/tclIntDecls.h 2001/11/14 23:17:03 1.31 +++ generic/tclIntDecls.h 2001/12/11 10:19:07 @@ -64,15 +64,19 @@ /* 9 */ EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, - Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, - TclFile * outPipePtr, TclFile * errFilePtr)); + Tcl_Pid ** pidArrayPtr, + Tcl_Channel * inPipePtr, + Tcl_Channel * outPipePtr, + Tcl_Channel * errFilePtr)); #endif /* UNIX */ #ifdef __WIN32__ /* 9 */ EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, - Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, - TclFile * outPipePtr, TclFile * errFilePtr)); + Tcl_Pid ** pidArrayPtr, + Tcl_Channel * inPipePtr, + Tcl_Channel * outPipePtr, + Tcl_Channel * errFilePtr)); #endif /* __WIN32__ */ /* 10 */ EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp * interp, @@ -520,10 +524,10 @@ int (*tclCopyAndCollapse) _ANSI_ARGS_((int count, CONST char * src, char * dst)); /* 7 */ int (*tclCopyChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj * cmdPtr)); /* 8 */ #if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ - int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, Tcl_Channel * inPipePtr, Tcl_Channel * outPipePtr, Tcl_Channel * errFilePtr)); /* 9 */ #endif /* UNIX */ #ifdef __WIN32__ - int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, Tcl_Channel * inPipePtr, Tcl_Channel * outPipePtr, Tcl_Channel * errFilePtr)); /* 9 */ #endif /* __WIN32__ */ #ifdef MAC_TCL void *reserved9; Index: generic/tclIntPlatDecls.h =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclIntPlatDecls.h,v retrieving revision 1.14 diff -b -u -r1.14 tclIntPlatDecls.h --- generic/tclIntPlatDecls.h 2001/11/26 18:06:46 1.14 +++ generic/tclIntPlatDecls.h 2001/12/11 10:19:07 @@ -57,7 +57,7 @@ EXTERN int TclUnixWaitForFile _ANSI_ARGS_((int fd, int mask, int timeout)); /* 9 */ -EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_(( +EXTERN Tcl_Channel TclpCreateTempFile _ANSI_ARGS_(( CONST char * contents)); #endif /* UNIX */ #ifdef __WIN32__ @@ -93,17 +93,18 @@ EXTERN int TclpCloseFile _ANSI_ARGS_((TclFile file)); /* 13 */ EXTERN Tcl_Channel TclpCreateCommandChannel _ANSI_ARGS_(( - TclFile readFile, TclFile writeFile, - TclFile errorFile, int numPids, + Tcl_Channel readFile, Tcl_Channel writeFile, + Tcl_Channel errorFile, int numPids, Tcl_Pid * pidPtr)); /* 14 */ -EXTERN int TclpCreatePipe _ANSI_ARGS_((TclFile * readPipe, - TclFile * writePipe)); +EXTERN int TclpCreatePipe _ANSI_ARGS_((Tcl_Channel * readPipe, + Tcl_Channel * writePipe)); /* 15 */ EXTERN int TclpCreateProcess _ANSI_ARGS_((Tcl_Interp * interp, - int argc, char ** argv, TclFile inputFile, - TclFile outputFile, TclFile errorFile, - Tcl_Pid * pidPtr)); + int argc, char ** argv, + Tcl_Channel inputFile, + Tcl_Channel outputFile, + Tcl_Channel errorFile, Tcl_Pid * pidPtr)); /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* 18 */ @@ -117,7 +118,7 @@ DWORD id)); /* Slot 21 is reserved */ /* 22 */ -EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_(( +EXTERN Tcl_Channel TclpCreateTempFile _ANSI_ARGS_(( CONST char * contents)); /* 23 */ EXTERN char * TclpGetTZName _ANSI_ARGS_((int isdst)); @@ -214,7 +215,7 @@ TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 6 */ TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 7 */ int (*tclUnixWaitForFile) _ANSI_ARGS_((int fd, int mask, int timeout)); /* 8 */ - TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 9 */ + Tcl_Channel (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 9 */ #endif /* UNIX */ #ifdef __WIN32__ void (*tclWinConvertError) _ANSI_ARGS_((DWORD errCode)); /* 0 */ @@ -230,16 +231,16 @@ void *reserved10; void (*tclGetAndDetachPids) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 11 */ int (*tclpCloseFile) _ANSI_ARGS_((TclFile file)); /* 12 */ - Tcl_Channel (*tclpCreateCommandChannel) _ANSI_ARGS_((TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid * pidPtr)); /* 13 */ - int (*tclpCreatePipe) _ANSI_ARGS_((TclFile * readPipe, TclFile * writePipe)); /* 14 */ - int (*tclpCreateProcess) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid * pidPtr)); /* 15 */ + Tcl_Channel (*tclpCreateCommandChannel) _ANSI_ARGS_((Tcl_Channel readFile, Tcl_Channel writeFile, Tcl_Channel errorFile, int numPids, Tcl_Pid * pidPtr)); /* 13 */ + int (*tclpCreatePipe) _ANSI_ARGS_((Tcl_Channel * readPipe, Tcl_Channel * writePipe)); /* 14 */ + int (*tclpCreateProcess) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Channel inputFile, Tcl_Channel outputFile, Tcl_Channel errorFile, Tcl_Pid * pidPtr)); /* 15 */ void *reserved16; void *reserved17; TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 18 */ TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 19 */ void (*tclWinAddProcess) _ANSI_ARGS_((HANDLE hProcess, DWORD id)); /* 20 */ void *reserved21; - TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 22 */ + Tcl_Channel (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 22 */ char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 23 */ char * (*tclWinNoBackslash) _ANSI_ARGS_((char * path)); /* 24 */ TclPlatformType * (*tclWinGetPlatform) _ANSI_ARGS_((void)); /* 25 */ Index: generic/tclMain.c =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclMain.c,v retrieving revision 1.14 diff -b -u -r1.14 tclMain.c --- generic/tclMain.c 2001/11/23 01:28:53 1.14 +++ generic/tclMain.c 2001/12/11 10:19:07 @@ -208,6 +208,10 @@ * Invoke application-specific initialization. */ + Tcl_GetStdChannel(TCL_STDIN); + Tcl_GetStdChannel(TCL_STDOUT); + Tcl_GetStdChannel(TCL_STDERR); + if ((*appInitProc)(interp) != TCL_OK) { errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { Index: generic/tclPipe.c =================================================================== RCS file: /cvsroot/tcl/tcl/generic/tclPipe.c,v retrieving revision 1.3 diff -b -u -r1.3 tclPipe.c --- generic/tclPipe.c 1999/04/16 00:46:51 1.3 +++ generic/tclPipe.c 2001/12/11 10:19:08 @@ -38,7 +38,8 @@ * Declarations for local procedures defined in this file: */ -static TclFile FileForRedirect _ANSI_ARGS_((Tcl_Interp *interp, +int CloseFileHandle(Tcl_Interp *i, Tcl_Channel chan, int direction); +static Tcl_Channel FileForRedirect _ANSI_ARGS_((Tcl_Interp *interp, char *spec, int atOk, char *arg, char *nextArg, int flags, int *skipPtr, int *closePtr, int *releasePtr)); @@ -63,7 +64,7 @@ *---------------------------------------------------------------------- */ -static TclFile +static Tcl_Channel FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr, releasePtr) Tcl_Interp *interp; /* Intepreter to use for error reporting. */ @@ -88,10 +89,12 @@ { int writing = (flags & O_WRONLY); Tcl_Channel chan; - TclFile file; + Tcl_Channel file; *skipPtr = 1; if ((atOK != 0) && (*spec == '@')) { + int res; + spec++; if (*spec == '\0') { spec = nextArg; @@ -104,8 +107,9 @@ if (chan == (Tcl_Channel) NULL) { return NULL; } - file = TclpMakeFile(chan, writing ? TCL_WRITABLE : TCL_READABLE); - if (file == NULL) { + file = chan; + res = Tcl_GetChannelHandle(chan, ((writing) ? TCL_WRITABLE : TCL_READABLE), (ClientData*)NULL); + if (res != TCL_OK) { Tcl_AppendResult(interp, "channel \"", Tcl_GetChannelName(chan), "\" wasn't opened for ", ((writing) ? "writing" : "reading"), (char *) NULL); @@ -123,8 +127,9 @@ Tcl_Flush(chan); } } else { - char *name; - Tcl_DString nameString; + Tcl_Obj *pathPtr; + int specLen; + Tcl_Obj *namePtr; if (*spec == '\0') { spec = nextArg; @@ -133,13 +138,16 @@ } *skipPtr = 2; } - name = Tcl_TranslateFileName(interp, spec, &nameString); - if (name != NULL) { - file = TclpOpenFile(name, flags); + specLen = strlen(spec); + pathPtr = Tcl_NewStringObj(spec, specLen); + Tcl_IncrRefCount(pathPtr); + namePtr = Tcl_FSGetNormalizedPath(interp, pathPtr); + if (namePtr != NULL) { + file = TclpOpenFileChannel(NULL, namePtr, NULL, flags); } else { file = NULL; } - Tcl_DStringFree(&nameString); + Tcl_DecrRefCount(pathPtr); if (file == NULL) { Tcl_AppendResult(interp, "couldn't ", ((writing) ? "write" : "read"), " file \"", spec, "\": ", @@ -411,7 +419,8 @@ * Given an argc/argv array, instantiate a pipeline of processes * as described by the argv. * - * This procedure is unofficially exported for use by BLT. + * This procedure was unofficially exported for use by BLT, but + * BLT actually hasn't used it for several years. * * Results: * The return value is a count of the number of new processes @@ -446,19 +455,19 @@ * address of array of pids for processes * in pipeline (first pid is first process * in pipeline). */ - TclFile *inPipePtr; /* If non-NULL, input to the pipeline comes + Tcl_Channel *inPipePtr; /* If non-NULL, input to the pipeline comes * from a pipe (unless overridden by * redirection in the command). The file * id with which to write to this pipe is * stored at *inPipePtr. NULL means command * specified its own input source. */ - TclFile *outPipePtr; /* If non-NULL, output to the pipeline goes + Tcl_Channel *outPipePtr; /* If non-NULL, output to the pipeline goes * to a pipe, unless overriden by redirection * in the command. The file id with which to * read frome this pipe is stored at * *outPipePtr. NULL means command specified * its own output sink. */ - TclFile *errFilePtr; /* If non-NULL, all stderr output from the + Tcl_Channel *errFilePtr; /* If non-NULL, all stderr output from the * pipeline will go to a temporary file * created here, and a descriptor to read * the file will be left at *errFilePtr. @@ -480,19 +489,19 @@ * string containing input data (specified * via <<) to be piped to the first process * in the pipeline. */ - TclFile inputFile = NULL; /* If != NULL, gives file to use as input for + Tcl_Channel inputFile = NULL; /* If != NULL, gives file to use as input for * first process in pipeline (specified via < * or <@). */ int inputClose = 0; /* If non-zero, then inputFile should be * closed when cleaning up. */ int inputRelease = 0; - TclFile outputFile = NULL; /* Writable file for output from last command + Tcl_Channel outputFile = NULL; /* Writable file for output from last command * in pipeline (could be file or pipe). NULL * means use stdout. */ int outputClose = 0; /* If non-zero, then outputFile should be * closed when cleaning up. */ int outputRelease = 0; - TclFile errorFile = NULL; /* Writable file for error output from all + Tcl_Channel errorFile = NULL; /* Writable file for error output from all * commands in pipeline. NULL means use * stderr. */ int errorClose = 0; /* If non-zero, then errorFile should be @@ -501,8 +510,8 @@ char *p; int skip, lastBar, lastArg, i, j, atOK, flags, errorToOutput; Tcl_DString execBuffer; - TclFile pipeIn; - TclFile curInFile, curOutFile, curErrFile; + Tcl_Channel pipeIn; + Tcl_Channel curInFile, curOutFile, curErrFile; Tcl_Channel channel; if (inPipePtr != NULL) { @@ -560,7 +569,7 @@ case '<': if (inputClose != 0) { inputClose = 0; - TclpCloseFile(inputFile); + CloseFileHandle(NULL, inputFile, TCL_READABLE); } if (inputRelease != 0) { inputRelease = 0; @@ -601,7 +610,7 @@ if (*p == '&') { if (errorClose != 0) { errorClose = 0; - TclpCloseFile(errorFile); + CloseFileHandle(NULL, errorFile, TCL_WRITABLE); } errorToOutput = 1; p++; @@ -617,7 +626,7 @@ if (errorFile == outputFile) { errorClose = 1; } else { - TclpCloseFile(outputFile); + CloseFileHandle(NULL, outputFile, TCL_WRITABLE); } } if (outputRelease != 0) { @@ -636,7 +645,7 @@ if (errorToOutput) { if (errorClose != 0) { errorClose = 0; - TclpCloseFile(errorFile); + CloseFileHandle(NULL, errorFile, TCL_WRITABLE); } if (errorRelease != 0) { errorRelease = 0; @@ -660,7 +669,7 @@ } if (errorClose != 0) { errorClose = 0; - TclpCloseFile(errorFile); + CloseFileHandle(NULL, errorFile, TCL_WRITABLE); } if (errorRelease != 0) { errorRelease = 0; @@ -718,13 +727,11 @@ channel = Tcl_GetStdChannel(TCL_STDIN); if (channel != NULL) { - inputFile = TclpMakeFile(channel, TCL_READABLE); - if (inputFile != NULL) { + inputFile = channel; inputRelease = 1; } } } - } if (outputFile == NULL) { if (outPipePtr != NULL) { @@ -747,13 +754,11 @@ channel = Tcl_GetStdChannel(TCL_STDOUT); if (channel) { - outputFile = TclpMakeFile(channel, TCL_WRITABLE); - if (outputFile != NULL) { + outputFile = channel; outputRelease = 1; } } } - } if (errorFile == NULL) { if (errFilePtr != NULL) { @@ -781,7 +786,7 @@ channel = Tcl_GetStdChannel(TCL_STDERR); if (channel) { - errorFile = TclpMakeFile(channel, TCL_WRITABLE); + errorFile = channel; if (errorFile != NULL) { errorRelease = 1; } @@ -876,13 +881,13 @@ */ if ((curInFile != NULL) && (curInFile != inputFile)) { - TclpCloseFile(curInFile); + CloseFileHandle(NULL, curInFile, TCL_READABLE); } curInFile = pipeIn; pipeIn = NULL; if ((curOutFile != NULL) && (curOutFile != outputFile)) { - TclpCloseFile(curOutFile); + CloseFileHandle(NULL, curOutFile, TCL_WRITABLE); } curOutFile = NULL; } @@ -897,17 +902,17 @@ Tcl_DStringFree(&execBuffer); if (inputClose) { - TclpCloseFile(inputFile); + CloseFileHandle(NULL, inputFile, TCL_READABLE); } else if (inputRelease) { TclpReleaseFile(inputFile); } if (outputClose) { - TclpCloseFile(outputFile); + CloseFileHandle(NULL, outputFile, TCL_WRITABLE); } else if (outputRelease) { TclpReleaseFile(outputFile); } if (errorClose) { - TclpCloseFile(errorFile); + CloseFileHandle(NULL, errorFile, TCL_WRITABLE); } else if (errorRelease) { TclpReleaseFile(errorFile); } @@ -921,24 +926,24 @@ error: if (pipeIn != NULL) { - TclpCloseFile(pipeIn); + CloseFileHandle(NULL, pipeIn, TCL_READABLE); } if ((curOutFile != NULL) && (curOutFile != outputFile)) { - TclpCloseFile(curOutFile); + CloseFileHandle(NULL, curOutFile, TCL_WRITABLE); } if ((curInFile != NULL) && (curInFile != inputFile)) { - TclpCloseFile(curInFile); + CloseFileHandle(NULL, curInFile, TCL_READABLE); } if ((inPipePtr != NULL) && (*inPipePtr != NULL)) { - TclpCloseFile(*inPipePtr); + CloseFileHandle(NULL, *inPipePtr, TCL_READABLE); *inPipePtr = NULL; } if ((outPipePtr != NULL) && (*outPipePtr != NULL)) { - TclpCloseFile(*outPipePtr); + CloseFileHandle(NULL, *outPipePtr, TCL_WRITABLE); *outPipePtr = NULL; } if ((errFilePtr != NULL) && (*errFilePtr != NULL)) { - TclpCloseFile(*errFilePtr); + CloseFileHandle(NULL, *errFilePtr, TCL_WRITABLE); *errFilePtr = NULL; } if (pidPtr != NULL) { @@ -996,8 +1001,8 @@ int flags; /* Or'ed combination of TCL_STDIN, TCL_STDOUT, * TCL_STDERR, and TCL_ENFORCE_MODE. */ { - TclFile *inPipePtr, *outPipePtr, *errFilePtr; - TclFile inPipe, outPipe, errFile; + Tcl_Channel *inPipePtr, *outPipePtr, *errFilePtr; + Tcl_Channel inPipe, outPipe, errFile; int numPids; Tcl_Pid *pidPtr; Tcl_Channel channel; @@ -1049,13 +1054,13 @@ ckfree((char *) pidPtr); } if (inPipe != NULL) { - TclpCloseFile(inPipe); + CloseFileHandle(NULL, inPipe, TCL_READABLE); } if (outPipe != NULL) { - TclpCloseFile(outPipe); + CloseFileHandle(NULL, outPipe, TCL_WRITABLE); } if (errFile != NULL) { - TclpCloseFile(errFile); + CloseFileHandle(NULL, errFile, TCL_WRITABLE); } return NULL; } Index: tests/exec.test =================================================================== RCS file: /cvsroot/tcl/tcl/tests/exec.test,v retrieving revision 1.9 diff -b -u -r1.9 exec.test --- tests/exec.test 2001/11/23 01:26:02 1.9 +++ tests/exec.test 2001/12/11 10:19:08 @@ -106,7 +106,7 @@ close $f # Basic operations. - +if {0} { test exec-1.1 {basic exec operation} {execCommandExists stdio} { exec $::tcltest::tcltest echo a b c } "a b c" @@ -232,8 +232,11 @@ exec $::tcltest::tcltest echo "Just a few thoughts" > gorp.file } test exec-5.1 {redirecting input from file} {execCommandExists stdio} { - exec $::tcltest::tcltest cat < gorp.file -} {Just a few thoughts} + set fin [open gorp.file r] + set contents [string trim [read $fin]] + close $fin + list [exec $::tcltest::tcltest cat < gorp.file] $contents +} {{Just a few thoughts} {Just a few thoughts}} test exec-5.2 {redirecting input from file} {execCommandExists stdio} { exec $::tcltest::tcltest cat | $::tcltest::tcltest cat < gorp.file } {Just a few thoughts} @@ -258,6 +261,7 @@ close $f set result } {Just a few thoughts} +} # I/O redirection: standard error through a pipeline. @@ -272,9 +276,14 @@ |& $::tcltest::tcltest sh -c "echo second msg 1>&2 ; cat" |& $::tcltest::tcltest cat } "second msg\nfoo bar" +return + # I/O redirection: combinations. -file delete gorp.file2 +file delete -force gorp.file2 gorp.file +if { [set ::tcltest::testConstraints(execCommandExists)] } { +exec $::tcltest::tcltest echo "Just a few thoughts" > gorp.file +} test exec-7.1 {multiple I/O redirections} {execCommandExists stdio} { exec << "command input" > gorp.file2 $::tcltest::tcltest cat < gorp.file exec $::tcltest::tcltest cat gorp.file2 @@ -283,6 +292,8 @@ exec < gorp.file << "command input" $::tcltest::tcltest cat } {command input} +#return + # Long input to command and output from command. set a "0123456789 xxxxxxxxx abcdefghi ABCDEFGHIJK\n" @@ -428,8 +439,9 @@ set f [open gorp.file w] puts $f { catch { exec [info nameofexecutable] echo foo & } } close $f - string compare "foo" [exec $::tcltest::tcltest gorp.file] -} 0 + set c [exec $::tcltest::tcltest gorp.file] + list $c [string compare "foo" $c] +} {foo 0} # Make sure that background commands are properly reaped when # they eventually die. Index: win/tclWinChan.c =================================================================== RCS file: /cvsroot/tcl/tcl/win/tclWinChan.c,v retrieving revision 1.16 diff -b -u -r1.16 tclWinChan.c --- win/tclWinChan.c 2001/10/15 17:34:53 1.16 +++ win/tclWinChan.c 2001/12/11 10:19:08 @@ -665,20 +665,26 @@ * file, with what modes to create * it? */ { - Tcl_Channel channel = 0; - int seekFlag, mode, channelPermissions; + Tcl_Channel channel = NULL; + int seekFlag = 0; + int mode, channelPermissions; DWORD accessMode, createMode, shareMode, flags, consoleParams, type; TCHAR *nativeName; DCB dcb; HANDLE handle; char channelName[16 + TCL_INTEGER_SPACE]; - TclFile readFile = NULL; - TclFile writeFile = NULL; + Tcl_Channel readFile = NULL; + Tcl_Channel writeFile = NULL; + if (modeString == NULL) { + mode = permissions; + permissions = 0; + } else { mode = TclGetOpenMode(interp, modeString, &seekFlag); if (mode == -1) { return NULL; } + } nativeName = (TCHAR*) Tcl_FSGetNativePath(pathPtr); if (nativeName == NULL) { @@ -733,11 +739,15 @@ */ if (mode & O_CREAT) { + if (modeString == NULL) { + flags = 0; + } else { if (permissions & S_IWRITE) { flags = FILE_ATTRIBUTE_NORMAL; } else { flags = FILE_ATTRIBUTE_READONLY; } + } } else { flags = (*tclWinProcs->getFileAttributesProc)(nativeName); if (flags == 0xFFFFFFFF) { @@ -820,10 +830,12 @@ break; case FILE_TYPE_PIPE: if (channelPermissions & TCL_READABLE) { - readFile = TclWinMakeFile(handle); + readFile = TclWinOpenFileChannel(handle, channelName, + channelPermissions, 0); } if (channelPermissions & TCL_WRITABLE) { - writeFile = TclWinMakeFile(handle); + writeFile = TclWinOpenFileChannel(handle, channelName, + channelPermissions, 0); } channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL); break; @@ -849,7 +861,7 @@ } if (channel != NULL) { - if (seekFlag) { + if (seekFlag || ((modeString == NULL) && (mode & O_WRONLY))) { if (Tcl_Seek(channel, 0, SEEK_END) < 0) { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, @@ -894,8 +906,8 @@ HANDLE dupedHandle; DCB dcb; DWORD consoleParams, type; - TclFile readFile = NULL; - TclFile writeFile = NULL; + Tcl_Channel readFile = NULL; + Tcl_Channel writeFile = NULL; BOOL result; if (mode == 0) { @@ -934,13 +946,22 @@ channel = TclWinOpenConsoleChannel(handle, channelName, mode); break; case FILE_TYPE_PIPE: - if (mode & TCL_READABLE) - { - readFile = TclWinMakeFile(handle); - } - if (mode & TCL_WRITABLE) - { - writeFile = TclWinMakeFile(handle); + if ((mode & TCL_READABLE) && (mode & TCL_WRITABLE)) { + HANDLE dupe; + + /* + * We need to make a duplicate, because the handles are closed + * seperately by the core in the close2proc. + */ + DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), + &dupe, 0, FALSE, DUPLICATE_SAME_ACCESS); + + readFile = TclWinOpenFileChannel(handle, channelName, mode, 0); + writeFile = TclWinOpenFileChannel(dupe, channelName, mode, 0); + } else if (mode & TCL_READABLE) { + readFile = TclWinOpenFileChannel(handle, channelName, mode, 0); + } else if (mode & TCL_WRITABLE) { + writeFile = TclWinOpenFileChannel(handle, channelName, mode, 0); } channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL); break; @@ -1159,18 +1180,16 @@ /* *---------------------------------------------------------------------- * - * TclWinOpenFileChannel -- + * TclWinFlushDirtyChannels -- * - * Constructs a File channel for the specified standard OS handle. - * This is a helper function to break up the construction of - * channels into File, Console, or Serial. + * Flushes all dirty channels. * * Results: - * Returns the new channel, or NULL. + * None. * * Side effects: - * May open the channel and may cause creation of a file on the - * file system. + * 'stat' operations will return the correct file size after + * this. * *---------------------------------------------------------------------- */ Index: win/tclWinPipe.c =================================================================== RCS file: /cvsroot/tcl/tcl/win/tclWinPipe.c,v retrieving revision 1.20 diff -b -u -r1.20 tclWinPipe.c --- win/tclWinPipe.c 2001/09/06 01:38:02 1.20 +++ win/tclWinPipe.c 2001/12/11 10:19:09 @@ -56,11 +56,6 @@ * types used in a pipeline. */ -typedef struct WinFile { - int type; /* One of the file types defined above. */ - HANDLE handle; /* Open file handle. */ -} WinFile; - /* * This list is used to map from pids to process handles. */ @@ -101,9 +96,9 @@ * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events should be reported. */ int flags; /* State flags, see above for a list. */ - TclFile readFile; /* Output from pipe. */ - TclFile writeFile; /* Input from pipe. */ - TclFile errorFile; /* Error output from pipe. */ + Tcl_Channel readFile; /* Output from pipe. */ + Tcl_Channel writeFile; /* Input from pipe. */ + Tcl_Channel errorFile; /* Error output from pipe. */ int numPids; /* Number of processes attached to pipe. */ Tcl_Pid *pidPtr; /* Pids of attached processes. */ Tcl_ThreadId threadId; /* Thread to which events should be reported. @@ -202,6 +197,7 @@ static void ProcExitHandler(ClientData clientData); static int TempFileName(WCHAR name[MAX_PATH]); static int WaitForRead(PipeInfo *infoPtr, int blocking); +int CloseFileHandle(Tcl_Interp *i, Tcl_Channel chan, int direction); /* * This structure describes the channel type structure for command pipe @@ -345,7 +341,6 @@ PipeInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; int block = 1; - WinFile *filePtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { @@ -359,13 +354,11 @@ for (infoPtr = tsdPtr->firstPipePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask & TCL_WRITABLE) { - filePtr = (WinFile*) infoPtr->writeFile; if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) { block = 0; } } if (infoPtr->watchMask & TCL_READABLE) { - filePtr = (WinFile*) infoPtr->readFile; if (WaitForRead(infoPtr, 0) >= 0) { block = 0; } @@ -400,7 +393,6 @@ { PipeInfo *infoPtr; PipeEvent *evPtr; - WinFile *filePtr; int needEvent; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -424,13 +416,11 @@ */ needEvent = 0; - filePtr = (WinFile*) infoPtr->writeFile; if ((infoPtr->watchMask & TCL_WRITABLE) && (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT)) { needEvent = 1; } - filePtr = (WinFile*) infoPtr->readFile; if ((infoPtr->watchMask & TCL_READABLE) && (WaitForRead(infoPtr, 0) >= 0)) { needEvent = 1; @@ -467,13 +457,8 @@ TclWinMakeFile( HANDLE handle) /* Type-specific data. */ { - WinFile *filePtr; - - filePtr = (WinFile *) ckalloc(sizeof(WinFile)); - filePtr->type = WIN_FILE; - filePtr->handle = handle; - return (TclFile)filePtr; + return (TclFile)NULL; } /* @@ -543,14 +528,7 @@ Tcl_Channel channel; /* Channel to get file from. */ int direction; /* Either TCL_READABLE or TCL_WRITABLE. */ { - HANDLE handle; - - if (Tcl_GetChannelHandle(channel, direction, - (ClientData *) &handle) == TCL_OK) { - return TclWinMakeFile(handle); - } else { return (TclFile) NULL; - } } /* @@ -575,102 +553,7 @@ CONST char *path; /* The name of the file to open. */ int mode; /* In what mode to open the file? */ { - HANDLE handle; - DWORD accessMode, createMode, shareMode, flags; - Tcl_DString ds; - TCHAR *nativePath; - - /* - * Map the access bits to the NT access mode. - */ - - switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { - case O_RDONLY: - accessMode = GENERIC_READ; - break; - case O_WRONLY: - accessMode = GENERIC_WRITE; - break; - case O_RDWR: - accessMode = (GENERIC_READ | GENERIC_WRITE); - break; - default: - TclWinConvertError(ERROR_INVALID_FUNCTION); - return NULL; - } - - /* - * Map the creation flags to the NT create mode. - */ - - switch (mode & (O_CREAT | O_EXCL | O_TRUNC)) { - case (O_CREAT | O_EXCL): - case (O_CREAT | O_EXCL | O_TRUNC): - createMode = CREATE_NEW; - break; - case (O_CREAT | O_TRUNC): - createMode = CREATE_ALWAYS; - break; - case O_CREAT: - createMode = OPEN_ALWAYS; - break; - case O_TRUNC: - case (O_TRUNC | O_EXCL): - createMode = TRUNCATE_EXISTING; - break; - default: - createMode = OPEN_EXISTING; - break; - } - - nativePath = Tcl_WinUtfToTChar(path, -1, &ds); - - /* - * If the file is not being created, use the existing file attributes. - */ - - flags = 0; - if (!(mode & O_CREAT)) { - flags = (*tclWinProcs->getFileAttributesProc)(nativePath); - if (flags == 0xFFFFFFFF) { - flags = 0; - } - } - - /* - * Set up the file sharing mode. We want to allow simultaneous access. - */ - - shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - - /* - * Now we get to create the file. - */ - - handle = (*tclWinProcs->createFileProc)(nativePath, accessMode, - shareMode, NULL, createMode, flags, NULL); - Tcl_DStringFree(&ds); - - if (handle == INVALID_HANDLE_VALUE) { - DWORD err; - - err = GetLastError(); - if ((err & 0xffffL) == ERROR_OPEN_FAILED) { - err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; - } - TclWinConvertError(err); - return NULL; - } - - /* - * Seek to the end of file if we are writing. - */ - - if (mode & O_WRONLY) { - SetFilePointer(handle, 0, NULL, FILE_END); - } - - return TclWinMakeFile(handle); + return (TclFile) NULL; } /* @@ -691,13 +574,15 @@ *---------------------------------------------------------------------- */ -TclFile +Tcl_Channel TclpCreateTempFile(contents) CONST char *contents; /* String to write into temp file, or NULL. */ { WCHAR name[MAX_PATH]; CONST char *native; Tcl_DString dstring; + Tcl_Channel channel; + /* char channelName[16 + TCL_INTEGER_SPACE]; */ HANDLE handle; if (TempFileName(name) == 0) { @@ -750,8 +635,10 @@ } } - return TclWinMakeFile(handle); + channel = Tcl_MakeFileChannel(handle, (TCL_READABLE | TCL_WRITABLE)); + return channel; + error: /* Free the native representation of the contents if necessary */ if (contents != NULL) { @@ -810,23 +697,52 @@ int TclpCreatePipe( - TclFile *readPipe, /* Location to store file handle for + Tcl_Channel *readPipe, /* Location to store file handle for * read side of pipe. */ - TclFile *writePipe) /* Location to store file handle for + Tcl_Channel *writePipe) /* Location to store file handle for * write side of pipe. */ { + char channelName[16 + TCL_INTEGER_SPACE]; HANDLE readHandle, writeHandle; if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) { - *readPipe = TclWinMakeFile(readHandle); - *writePipe = TclWinMakeFile(writeHandle); + *readPipe = TclWinOpenFileChannel(readHandle, channelName, + TCL_READABLE | TCL_WRITABLE, 0); + *writePipe = TclWinOpenFileChannel(writeHandle, channelName, + TCL_READABLE | TCL_WRITABLE, 0); return 1; } TclWinConvertError(GetLastError()); return 0; } +/* + * Vince -- This function has been used just to test that there are no + * issues around closing some of these channels/handles. It will be + * removed and replaced with a simple line of code in the final version + */ +int CloseFileHandle( + Tcl_Interp *i, Tcl_Channel chan, int direction) /* The file to close. */ +{ + HANDLE h = NULL; + + if (chan == NULL) { + return 0; + } + + if (0 && Tcl_GetChannelHandle(chan, direction, (ClientData*)&h) == TCL_ERROR) { + TclWinConvertError(GetLastError()); + return -1; + } + if (!TclInExit() || !Tcl_IsStandardChannel(chan)) { + if (Tcl_Close(i, chan) != 0) { + return -1; + } + } + return 0; +} + /* *---------------------------------------------------------------------- * @@ -848,34 +764,6 @@ TclpCloseFile( TclFile file) /* The file to close. */ { - WinFile *filePtr = (WinFile *) file; - - switch (filePtr->type) { - case WIN_FILE: - /* - * Don't close the Win32 handle if the handle is a standard channel - * during the exit process. Otherwise, one thread may kill the - * stdio of another. - */ - - if (!TclInExit() - || ((GetStdHandle(STD_INPUT_HANDLE) != filePtr->handle) - && (GetStdHandle(STD_OUTPUT_HANDLE) != filePtr->handle) - && (GetStdHandle(STD_ERROR_HANDLE) != filePtr->handle))) { - if (filePtr->handle != NULL && - CloseHandle(filePtr->handle) == FALSE) { - TclWinConvertError(GetLastError()); - ckfree((char *) filePtr); - return -1; - } - } - break; - - default: - panic("TclpCloseFile: unexpected file type"); - } - - ckfree((char *) filePtr); return 0; } @@ -954,16 +842,16 @@ * converted to native format (using the * Tcl_TranslateFileName call). Additional * arguments have not been converted. */ - TclFile inputFile, /* If non-NULL, gives the file to use as + Tcl_Channel inputFile, /* If non-NULL, gives the file to use as * input for the child process. If inputFile * file is not readable or is NULL, the child * will receive no standard input. */ - TclFile outputFile, /* If non-NULL, gives the file that + Tcl_Channel outputFile, /* If non-NULL, gives the file that * receives output from the child process. If * outputFile file is not writeable or is * NULL, output from the child will be * discarded. */ - TclFile errorFile, /* If non-NULL, gives the file that + Tcl_Channel errorFile, /* If non-NULL, gives the file that * receives errors from the child process. If * errorFile file is not writeable or is NULL, * errors from the child will be discarded. @@ -979,7 +867,6 @@ SECURITY_ATTRIBUTES secAtts; HANDLE hProcess, h, inputHandle, outputHandle, errorHandle; char execPath[MAX_PATH * TCL_UTF_MAX]; - WinFile *filePtr; PipeInit(); @@ -1016,23 +903,26 @@ inputHandle = INVALID_HANDLE_VALUE; if (inputFile != NULL) { - filePtr = (WinFile *)inputFile; - if (filePtr->type == WIN_FILE) { - inputHandle = filePtr->handle; + if (!strcmp(Tcl_GetChannelType(inputFile)->typeName,"file")) { + if (Tcl_GetChannelHandle(inputFile, TCL_READABLE, (ClientData*)&inputHandle) == TCL_ERROR) { + inputHandle = INVALID_HANDLE_VALUE; + } } } outputHandle = INVALID_HANDLE_VALUE; if (outputFile != NULL) { - filePtr = (WinFile *)outputFile; - if (filePtr->type == WIN_FILE) { - outputHandle = filePtr->handle; + if (!strcmp(Tcl_GetChannelType(outputFile)->typeName,"file")) { + if (Tcl_GetChannelHandle(outputFile, TCL_WRITABLE, (ClientData*)&outputHandle) == TCL_ERROR) { + outputHandle = INVALID_HANDLE_VALUE; + } } } errorHandle = INVALID_HANDLE_VALUE; if (errorFile != NULL) { - filePtr = (WinFile *)errorFile; - if (filePtr->type == WIN_FILE) { - errorHandle = filePtr->handle; + if (!strcmp(Tcl_GetChannelType(errorFile)->typeName,"file")) { + if (Tcl_GetChannelHandle(errorFile, TCL_WRITABLE, (ClientData*)&errorHandle) == TCL_ERROR) { + errorHandle = INVALID_HANDLE_VALUE; + } } } @@ -1065,8 +955,15 @@ } if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); + if (inputHandle == INVALID_HANDLE_VALUE) { + Tcl_AppendResult(interp, "couldn't create input handle: ", + Tcl_PosixError(interp), (char *) NULL); + } else { + char *x = NULL; + char y = *x; Tcl_AppendResult(interp, "couldn't duplicate input handle: ", Tcl_PosixError(interp), (char *) NULL); + } goto end; } @@ -1101,8 +998,13 @@ } if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); + if (outputHandle == INVALID_HANDLE_VALUE) { + Tcl_AppendResult(interp, "couldn't create output handle: ", + Tcl_PosixError(interp), (char *) NULL); + } else { Tcl_AppendResult(interp, "couldn't duplicate output handle: ", Tcl_PosixError(interp), (char *) NULL); + } goto end; } @@ -1120,8 +1022,13 @@ } if (startInfo.hStdError == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); + if (errorHandle == INVALID_HANDLE_VALUE) { + Tcl_AppendResult(interp, "couldn't create error handle: ", + Tcl_PosixError(interp), (char *) NULL); + } else { Tcl_AppendResult(interp, "couldn't duplicate error handle: ", Tcl_PosixError(interp), (char *) NULL); + } goto end; } /* @@ -1627,15 +1534,14 @@ Tcl_Channel TclpCreateCommandChannel( - TclFile readFile, /* If non-null, gives the file for reading. */ - TclFile writeFile, /* If non-null, gives the file for writing. */ - TclFile errorFile, /* If non-null, gives the file where errors + Tcl_Channel readFile, /* If non-null, gives the file for reading. */ + Tcl_Channel writeFile, /* If non-null, gives the file for writing. */ + Tcl_Channel errorFile, /* If non-null, gives the file where errors * can be read. */ int numPids, /* The number of pids in the pid array. */ Tcl_Pid *pidPtr) /* An array of process identifiers. */ { char channelName[16 + TCL_INTEGER_SPACE]; - int channelId; DWORD id; PipeInfo *infoPtr = (PipeInfo *) ckalloc((unsigned) sizeof(PipeInfo)); @@ -1653,21 +1559,6 @@ infoPtr->writeBufLen = 0; infoPtr->writeError = 0; - /* - * Use one of the fds associated with the channel as the - * channel id. - */ - - if (readFile) { - channelId = (int) ((WinFile*)readFile)->handle; - } else if (writeFile) { - channelId = (int) ((WinFile*)writeFile)->handle; - } else if (errorFile) { - channelId = (int) ((WinFile*)errorFile)->handle; - } else { - channelId = 0; - } - infoPtr->validMask = 0; infoPtr->threadId = Tcl_GetCurrentThread(); @@ -1708,7 +1599,7 @@ * channels share handles (stdin/stdout). */ - wsprintfA(channelName, "file%lx", infoPtr); + wsprintfA(channelName, "pipe%lx", infoPtr); infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName, (ClientData) infoPtr, infoPtr->validMask); @@ -1907,7 +1798,7 @@ CloseHandle(pipePtr->stopReader); pipePtr->readThread = NULL; } - if (TclpCloseFile(pipePtr->readFile) != 0) { + if (CloseFileHandle(NULL, pipePtr->readFile, TCL_READABLE) != 0) { errorCode = errno; } pipePtr->validMask &= ~TCL_READABLE; @@ -1951,7 +1842,7 @@ CloseHandle(pipePtr->startWriter); pipePtr->writeThread = NULL; } - if (TclpCloseFile(pipePtr->writeFile) != 0) { + if (CloseFileHandle(NULL, pipePtr->writeFile, TCL_WRITABLE) != 0) { if (errorCode == 0) { errorCode = errno; } @@ -1989,12 +1880,7 @@ */ if (pipePtr->errorFile) { - WinFile *filePtr; - - filePtr = (WinFile*)pipePtr->errorFile; - errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle, - TCL_READABLE); - ckfree((char *) filePtr); + errChan = pipePtr->errorFile; } else { errChan = NULL; } @@ -2045,7 +1931,7 @@ int *errorCode) /* Where to store error code. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; - WinFile *filePtr = (WinFile*) infoPtr->readFile; + HANDLE handle; DWORD count, bytesRead = 0; int result; @@ -2091,8 +1977,10 @@ * if there is any data available. Otherwise it will block until * at least one byte is available or an EOF occurs. */ + + Tcl_GetChannelHandle(infoPtr->readFile, TCL_READABLE, (ClientData*)&handle); - if (ReadFile(filePtr->handle, (LPVOID) buf, (DWORD) bufSize, &count, + if (ReadFile(handle, (LPVOID) buf, (DWORD) bufSize, &count, (LPOVERLAPPED) NULL) == TRUE) { return bytesRead + count; } else if (bytesRead) { @@ -2138,7 +2026,6 @@ int *errorCode) /* Where to store error code. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; - WinFile *filePtr = (WinFile*) infoPtr->writeFile; DWORD bytesWritten, timeout; *errorCode = 0; @@ -2190,8 +2077,10 @@ * In the blocking case, just try to write the buffer directly. * This avoids an unnecessary copy. */ + HANDLE handle; + Tcl_GetChannelHandle(infoPtr->writeFile, TCL_WRITABLE, (ClientData*)&handle); - if (WriteFile(filePtr->handle, (LPVOID) buf, (DWORD) toWrite, + if (WriteFile(handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { TclWinConvertError(GetLastError()); goto error; @@ -2234,7 +2123,6 @@ { PipeEvent *pipeEvPtr = (PipeEvent *)evPtr; PipeInfo *infoPtr; - WinFile *filePtr; int mask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -2271,14 +2159,12 @@ * as being writable unless we have detected EOF. */ - filePtr = (WinFile*) ((PipeInfo*)infoPtr)->writeFile; mask = 0; if ((infoPtr->watchMask & TCL_WRITABLE) && (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT)) { mask = TCL_WRITABLE; } - filePtr = (WinFile*) ((PipeInfo*)infoPtr)->readFile; if ((infoPtr->watchMask & TCL_READABLE) && (WaitForRead(infoPtr, 0) >= 0)) { if (infoPtr->readFlags & PIPE_EOF) { @@ -2382,16 +2268,13 @@ ClientData *handlePtr) /* Where to store the handle. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; - WinFile *filePtr; if (direction == TCL_READABLE && infoPtr->readFile) { - filePtr = (WinFile*) infoPtr->readFile; - *handlePtr = (ClientData) filePtr->handle; + *handlePtr = (ClientData) infoPtr->readFile; return TCL_OK; } if (direction == TCL_WRITABLE && infoPtr->writeFile) { - filePtr = (WinFile*) infoPtr->writeFile; - *handlePtr = (ClientData) filePtr->handle; + *handlePtr = (ClientData) infoPtr->writeFile; return TCL_OK; } return TCL_ERROR; @@ -2625,7 +2508,8 @@ * blocking or not. */ { DWORD timeout, count; - HANDLE *handle = ((WinFile *) infoPtr->readFile)->handle; + HANDLE handle; + Tcl_GetChannelHandle(infoPtr->readFile, TCL_READABLE, (ClientData*)&handle); while (1) { /* @@ -2736,12 +2620,14 @@ PipeReaderThread(LPVOID arg) { PipeInfo *infoPtr = (PipeInfo *)arg; - HANDLE *handle = ((WinFile *) infoPtr->readFile)->handle; + HANDLE handle; DWORD count, err; int done = 0; HANDLE wEvents[2]; DWORD dwWait; + Tcl_GetChannelHandle(infoPtr->readFile, TCL_READABLE, (ClientData*)&handle); + wEvents[0] = infoPtr->stopReader; wEvents[1] = infoPtr->startReader; @@ -2853,10 +2739,11 @@ { PipeInfo *infoPtr = (PipeInfo *)arg; - HANDLE *handle = ((WinFile *) infoPtr->writeFile)->handle; + HANDLE handle; DWORD count, toWrite; char *buf; int done = 0; + Tcl_GetChannelHandle(infoPtr->writeFile, TCL_WRITABLE, (ClientData*)&handle); while (!done) { /* Index: win/tclWinPort.h =================================================================== RCS file: /cvsroot/tcl/tcl/win/tclWinPort.h,v retrieving revision 1.24 diff -b -u -r1.24 tclWinPort.h --- win/tclWinPort.h 2001/10/15 17:34:53 1.24 +++ win/tclWinPort.h 2001/12/11 10:19:09 @@ -422,7 +422,7 @@ * address platform-specific issues. */ -#define TclpReleaseFile(file) ckfree((char *) file) +#define TclpReleaseFile(file) (void*)file /* * The following macros and declarations wrap the C runtime library