diff options
Diffstat (limited to 'win/tclWinPipe.c')
| -rw-r--r-- | win/tclWinPipe.c | 475 |
1 files changed, 199 insertions, 276 deletions
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c index 117ed71..ee088a5 100644 --- a/win/tclWinPipe.c +++ b/win/tclWinPipe.c @@ -12,8 +12,6 @@ #include "tclWinInt.h" -#include <sys/stat.h> - /* * The following variable is used to tell whether this module has been * initialized. @@ -131,9 +129,9 @@ typedef struct PipeInfo { */ char *writeBuf; /* Current background output buffer. Access is * synchronized with the writable object. */ - size_t writeBufLen; /* Size of write buffer. Access is + int writeBufLen; /* Size of write buffer. Access is * synchronized with the writable object. */ - size_t toWrite; /* Current amount to be written. Access is + int toWrite; /* Current amount to be written. Access is * synchronized with the writable object. */ int readFlags; /* Flags that are shared with the reader * thread. Access is synchronized with the @@ -173,35 +171,38 @@ typedef struct PipeEvent { * Declarations for functions used only in this file. */ -static Tcl_DriverBlockModeProc PipeBlockModeProc; -static Tcl_DriverClose2Proc PipeClose2Proc; -static Tcl_DriverGetHandleProc PipeGetHandleProc; -static Tcl_DriverInputProc PipeInputProc; -static Tcl_DriverOutputProc PipeOutputProc; -static Tcl_DriverThreadActionProc PipeThreadActionProc; -static Tcl_DriverWatchProc PipeWatchProc; - -static Tcl_EventCheckProc PipeCheckProc; -static Tcl_EventProc PipeEventProc; -static Tcl_EventSetupProc PipeSetupProc; - static int ApplicationType(Tcl_Interp *interp, const char *fileName, char *fullName); -static void BuildCommandLine(const char *executable, size_t argc, +static void BuildCommandLine(const char *executable, int argc, const char **argv, Tcl_DString *linePtr); static BOOL HasConsole(void); +static int PipeBlockModeProc(ClientData instanceData, int mode); +static void PipeCheckProc(ClientData clientData, int flags); +static int PipeClose2Proc(ClientData instanceData, + Tcl_Interp *interp, int flags); +static int PipeEventProc(Tcl_Event *evPtr, int flags); +static int PipeGetHandleProc(ClientData instanceData, + int direction, ClientData *handlePtr); static void PipeInit(void); +static int PipeInputProc(ClientData instanceData, char *buf, + int toRead, int *errorCode); +static int PipeOutputProc(ClientData instanceData, + const char *buf, int toWrite, int *errorCode); static DWORD WINAPI PipeReaderThread(LPVOID arg); +static void PipeSetupProc(ClientData clientData, int flags); +static void PipeWatchProc(ClientData instanceData, int mask); static DWORD WINAPI PipeWriterThread(LPVOID arg); -static int TempFileName(TCHAR name[MAX_PATH]); +static int TempFileName(WCHAR name[MAX_PATH]); static int WaitForRead(PipeInfo *infoPtr, int blocking); +static void PipeThreadActionProc(ClientData instanceData, + int action); /* * This structure describes the channel type structure for command pipe based * I/O. */ -static const Tcl_ChannelType pipeChannelType = { +static Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ TCL_CLOSE2PROC, /* Close proc. */ @@ -218,7 +219,7 @@ static const Tcl_ChannelType pipeChannelType = { NULL, /* handler proc. */ NULL, /* wide seek proc */ PipeThreadActionProc, /* thread action proc */ - NULL /* truncate */ + NULL, /* truncate */ }; /* @@ -403,7 +404,7 @@ PipeCheckProc( if (needEvent) { infoPtr->flags |= PIPE_PENDING; - evPtr = ckalloc(sizeof(PipeEvent)); + evPtr = (PipeEvent *) ckalloc(sizeof(PipeEvent)); evPtr->header.proc = PipeEventProc; evPtr->infoPtr = infoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); @@ -434,7 +435,7 @@ TclWinMakeFile( { WinFile *filePtr; - filePtr = ckalloc(sizeof(WinFile)); + filePtr = (WinFile *) ckalloc(sizeof(WinFile)); filePtr->type = WIN_FILE; filePtr->handle = handle; @@ -463,18 +464,27 @@ TclWinMakeFile( static int TempFileName( - TCHAR name[MAX_PATH]) /* Buffer in which name for temporary file + WCHAR name[MAX_PATH]) /* Buffer in which name for temporary file * gets stored. */ { - const TCHAR *prefix = TEXT("TCL"); - if (GetTempPath(MAX_PATH, name) != 0) { - if (GetTempFileName(name, prefix, 0, name) != 0) { + TCHAR *prefix; + + prefix = (tclWinProcs->useWide) ? (TCHAR *) L"TCL" : (TCHAR *) "TCL"; + if ((*tclWinProcs->getTempPathProc)(MAX_PATH, name) != 0) { + if ((*tclWinProcs->getTempFileNameProc)((TCHAR *) name, prefix, 0, + name) != 0) { return 1; } } - name[0] = '.'; - name[1] = '\0'; - return GetTempFileName(name, prefix, 0, name); + if (tclWinProcs->useWide) { + ((WCHAR *) name)[0] = '.'; + ((WCHAR *) name)[1] = '\0'; + } else { + ((char *) name)[0] = '.'; + ((char *) name)[1] = '\0'; + } + return (*tclWinProcs->getTempFileNameProc)((TCHAR *) name, prefix, 0, + name); } /* @@ -578,7 +588,7 @@ TclpOpenFile( break; } - nativePath = Tcl_WinUtfToTChar(path, TCL_STRLEN, &ds); + nativePath = Tcl_WinUtfToTChar(path, -1, &ds); /* * If the file is not being created, use the existing file attributes. @@ -586,7 +596,7 @@ TclpOpenFile( flags = 0; if (!(mode & O_CREAT)) { - flags = GetFileAttributes(nativePath); + flags = (*tclWinProcs->getFileAttributesProc)(nativePath); if (flags == 0xFFFFFFFF) { flags = 0; } @@ -602,8 +612,8 @@ TclpOpenFile( * Now we get to create the file. */ - handle = CreateFile(nativePath, accessMode, shareMode, - NULL, createMode, flags, NULL); + handle = (*tclWinProcs->createFileProc)(nativePath, accessMode, + shareMode, NULL, createMode, flags, NULL); Tcl_DStringFree(&ds); if (handle == INVALID_HANDLE_VALUE) { @@ -650,7 +660,7 @@ TclFile TclpCreateTempFile( const char *contents) /* String to write into temp file, or NULL. */ { - TCHAR name[MAX_PATH]; + WCHAR name[MAX_PATH]; const char *native; Tcl_DString dstring; HANDLE handle; @@ -659,7 +669,7 @@ TclpCreateTempFile( return NULL; } - handle = CreateFile(name, + handle = (*tclWinProcs->createFileProc)((TCHAR *) name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, NULL); if (handle == INVALID_HANDLE_VALUE) { @@ -673,13 +683,13 @@ TclpCreateTempFile( if (contents != NULL) { DWORD result, length; const char *p; - size_t toCopy; + int toCopy; /* * Convert the contents from UTF to native encoding */ - native = Tcl_UtfToExternalDString(NULL,contents,TCL_STRLEN, &dstring); + native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); toCopy = Tcl_DStringLength(&dstring); for (p = native; toCopy > 0; p++, toCopy--) { @@ -721,7 +731,7 @@ TclpCreateTempFile( TclWinConvertError(GetLastError()); CloseHandle(handle); - DeleteFile(name); + (*tclWinProcs->deleteFileProc)((TCHAR *) name); return NULL; } @@ -744,13 +754,13 @@ TclpCreateTempFile( Tcl_Obj * TclpTempFileName(void) { - TCHAR fileName[MAX_PATH]; + WCHAR fileName[MAX_PATH]; if (TempFileName(fileName) == 0) { return NULL; } - return TclpNativeToNormalized(fileName); + return TclpNativeToNormalized((ClientData) fileName); } /* @@ -826,7 +836,7 @@ TclpCloseFile( if (filePtr->handle != NULL && CloseHandle(filePtr->handle) == FALSE) { TclWinConvertError(GetLastError()); - ckfree(filePtr); + ckfree((char *) filePtr); return -1; } } @@ -836,7 +846,7 @@ TclpCloseFile( Tcl_Panic("TclpCloseFile: unexpected file type"); } - ckfree(filePtr); + ckfree((char *) filePtr); return 0; } @@ -911,7 +921,7 @@ TclpCreateProcess( * occurred when creating the child process. * Error messages from the child process * itself are sent to errorFile. */ - size_t argc, /* Number of arguments in following array. */ + int argc, /* Number of arguments in following array. */ const char **argv, /* Array of argument strings. argv[0] contains * the name of the executable converted to * native format (using the @@ -937,7 +947,7 @@ TclpCreateProcess( { int result, applType, createFlags; Tcl_DString cmdLine; /* Complete command line (TCHAR). */ - STARTUPINFO startInfo; + STARTUPINFOA startInfo; PROCESS_INFORMATION procInfo; SECURITY_ATTRIBUTES secAtts; HANDLE hProcess, h, inputHandle, outputHandle, errorHandle; @@ -1027,9 +1037,8 @@ TclpCreateProcess( } if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't duplicate input handle: %s", - Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't duplicate input handle: ", + Tcl_PosixError(interp), (char *) NULL); goto end; } @@ -1063,9 +1072,8 @@ TclpCreateProcess( } if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't duplicate output handle: %s", - Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't duplicate output handle: ", + Tcl_PosixError(interp), (char *) NULL); goto end; } @@ -1083,9 +1091,8 @@ TclpCreateProcess( } if (startInfo.hStdError == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't duplicate error handle: %s", - Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't duplicate error handle: ", + Tcl_PosixError(interp), (char *) NULL); goto end; } @@ -1117,7 +1124,7 @@ TclpCreateProcess( startInfo.wShowWindow = SW_HIDE; startInfo.dwFlags |= STARTF_USESHOWWINDOW; createFlags = CREATE_NEW_CONSOLE; - TclDStringAppendLiteral(&cmdLine, "cmd.exe /c"); + Tcl_DStringAppend(&cmdLine, "cmd.exe /c", -1); } else { createFlags = DETACHED_PROCESS; } @@ -1129,12 +1136,82 @@ TclpCreateProcess( } if (applType == APPL_DOS) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "DOS application process not supported on this platform", - TCL_STRLEN)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "DOS_APP", - NULL); - goto end; + /* + * Under Windows 95, 16-bit DOS applications do not work well with + * pipes: + * + * 1. EOF on a pipe between a detached 16-bit DOS application and + * another application is not seen at the other end of the pipe, + * so the listening process blocks forever on reads. This inablity + * to detect EOF happens when either a 16-bit app or the 32-bit + * app is the listener. + * + * 2. If a 16-bit DOS application (detached or not) blocks when + * writing to a pipe, it will never wake up again, and it + * eventually brings the whole system down around it. + * + * The 16-bit application is run as a normal process inside of a + * hidden helper console app, and this helper may be run as a + * detached process. If any of the stdio handles is a pipe, the + * helper application accumulates information into temp files and + * forwards it to or from the DOS application as appropriate. + * This means that DOS apps must receive EOF from a stdin pipe + * before they will actually begin, and must finish generating + * stdout or stderr before the data will be sent to the next stage + * of the pipe. + * + * The helper app should be located in the same directory as the + * tcl dll. + */ + Tcl_Obj *tclExePtr, *pipeDllPtr; + char *start, *end; + int i, fileExists; + Tcl_DString pipeDll; + + if (createFlags != 0) { + startInfo.wShowWindow = SW_HIDE; + startInfo.dwFlags |= STARTF_USESHOWWINDOW; + createFlags = CREATE_NEW_CONSOLE; + } + + Tcl_DStringInit(&pipeDll); + Tcl_DStringAppend(&pipeDll, TCL_PIPE_DLL, -1); + tclExePtr = TclGetObjNameOfExecutable(); + Tcl_IncrRefCount(tclExePtr); + start = Tcl_GetStringFromObj(tclExePtr, &i); + for (end = start + (i-1); end > start; end--) { + if (*end == '/') { + break; + } + } + if (*end != '/') { + Tcl_AppendResult(interp, "no / in executable path name \"", + start, "\"", (char *) NULL); + Tcl_DecrRefCount(tclExePtr); + Tcl_DStringFree(&pipeDll); + goto end; + } + i = (end - start) + 1; + pipeDllPtr = Tcl_NewStringObj(start, i); + Tcl_AppendToObj(pipeDllPtr, Tcl_DStringValue(&pipeDll), -1); + Tcl_IncrRefCount(pipeDllPtr); + if (Tcl_FSConvertToPathType(interp, pipeDllPtr) != TCL_OK) { + Tcl_Panic("Tcl_FSConvertToPathType failed"); + } + fileExists = (Tcl_FSAccess(pipeDllPtr, F_OK) == 0); + if (!fileExists) { + Tcl_AppendResult(interp, "Tcl pipe dll \"", + Tcl_DStringValue(&pipeDll), "\" not found", + (char *) NULL); + Tcl_DecrRefCount(tclExePtr); + Tcl_DecrRefCount(pipeDllPtr); + Tcl_DStringFree(&pipeDll); + goto end; + } + Tcl_DStringAppend(&cmdLine, Tcl_DStringValue(&pipeDll), -1); + Tcl_DecrRefCount(tclExePtr); + Tcl_DecrRefCount(pipeDllPtr); + Tcl_DStringFree(&pipeDll); } } @@ -1158,12 +1235,12 @@ TclpCreateProcess( BuildCommandLine(execPath, argc, argv, &cmdLine); - if (CreateProcess(NULL, (TCHAR *) Tcl_DStringValue(&cmdLine), - NULL, NULL, TRUE, (DWORD) createFlags, NULL, NULL, &startInfo, - &procInfo) == 0) { + if ((*tclWinProcs->createProcessProc)(NULL, + (TCHAR *) Tcl_DStringValue(&cmdLine), NULL, NULL, TRUE, + (DWORD) createFlags, NULL, NULL, &startInfo, &procInfo) == 0) { TclWinConvertError(GetLastError()); - Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s", - argv[0], Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't execute \"", argv[0], + "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } @@ -1291,7 +1368,7 @@ ApplicationType( IMAGE_DOS_HEADER header; Tcl_DString nameBuf, ds; const TCHAR *nativeName; - TCHAR nativeFullPath[MAX_PATH]; + WCHAR nativeFullPath[MAX_PATH]; static const char extensions[][5] = {"", ".com", ".exe", ".bat"}; /* @@ -1309,16 +1386,16 @@ ApplicationType( applType = APPL_NONE; Tcl_DStringInit(&nameBuf); - Tcl_DStringAppend(&nameBuf, originalName, TCL_STRLEN); + Tcl_DStringAppend(&nameBuf, originalName, -1); nameLen = Tcl_DStringLength(&nameBuf); for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) { Tcl_DStringSetLength(&nameBuf, nameLen); - Tcl_DStringAppend(&nameBuf, extensions[i], TCL_STRLEN); + Tcl_DStringAppend(&nameBuf, extensions[i], -1); nativeName = Tcl_WinUtfToTChar(Tcl_DStringValue(&nameBuf), Tcl_DStringLength(&nameBuf), &ds); - found = SearchPath(NULL, nativeName, NULL, MAX_PATH, - nativeFullPath, &rest); + found = (*tclWinProcs->searchPathProc)(NULL, nativeName, NULL, + MAX_PATH, nativeFullPath, &rest); Tcl_DStringFree(&ds); if (found == 0) { continue; @@ -1329,11 +1406,11 @@ ApplicationType( * known type. */ - attr = GetFileAttributes(nativeFullPath); + attr = (*tclWinProcs->getFileAttributesProc)((TCHAR *) nativeFullPath); if ((attr == 0xffffffff) || (attr & FILE_ATTRIBUTE_DIRECTORY)) { continue; } - strcpy(fullName, Tcl_WinTCharToUtf(nativeFullPath, TCL_STRLEN, &ds)); + strcpy(fullName, Tcl_WinTCharToUtf((TCHAR *) nativeFullPath, -1, &ds)); Tcl_DStringFree(&ds); ext = strrchr(fullName, '.'); @@ -1342,7 +1419,7 @@ ApplicationType( break; } - hFile = CreateFile(nativeFullPath, + hFile = (*tclWinProcs->createFileProc)((TCHAR *) nativeFullPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { @@ -1409,8 +1486,8 @@ ApplicationType( if (applType == APPL_NONE) { TclWinConvertError(GetLastError()); - Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s", - originalName, Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't execute \"", originalName, + "\": ", Tcl_PosixError(interp), (char *) NULL); return APPL_NONE; } @@ -1422,8 +1499,9 @@ ApplicationType( * application name from the arguments. */ - GetShortPathName(nativeFullPath, nativeFullPath, MAX_PATH); - strcpy(fullName, Tcl_WinTCharToUtf(nativeFullPath, TCL_STRLEN, &ds)); + (*tclWinProcs->getShortPathNameProc)((TCHAR *) nativeFullPath, + nativeFullPath, MAX_PATH); + strcpy(fullName, Tcl_WinTCharToUtf((TCHAR *) nativeFullPath, -1, &ds)); Tcl_DStringFree(&ds); } return applType; @@ -1452,7 +1530,7 @@ static void BuildCommandLine( const char *executable, /* Full path of executable (including * extension). Replacement for argv[0]. */ - size_t argc, /* Number of arguments. */ + int argc, /* Number of arguments. */ const char **argv, /* Argument strings in UTF. */ Tcl_DString *linePtr) /* Initialized Tcl_DString that receives the * command line (TCHAR). */ @@ -1467,9 +1545,9 @@ BuildCommandLine( * Prime the path. Add a space separator if we were primed with something. */ - TclDStringAppendDString(&ds, linePtr); + Tcl_DStringAppend(&ds, Tcl_DStringValue(linePtr), -1); if (Tcl_DStringLength(linePtr) > 0) { - TclDStringAppendLiteral(&ds, " "); + Tcl_DStringAppend(&ds, " ", 1); } for (i = 0; i < argc; i++) { @@ -1477,7 +1555,7 @@ BuildCommandLine( arg = executable; } else { arg = argv[i]; - TclDStringAppendLiteral(&ds, " "); + Tcl_DStringAppend(&ds, " ", 1); } quote = 0; @@ -1486,7 +1564,6 @@ BuildCommandLine( } else { int count; Tcl_UniChar ch; - for (start = arg; *start != '\0'; start += count) { count = Tcl_UtfToUniChar(start, &ch); if (Tcl_UniCharIsSpace(ch)) { /* INTL: ISO space. */ @@ -1496,7 +1573,7 @@ BuildCommandLine( } } if (quote) { - TclDStringAppendLiteral(&ds, "\""); + Tcl_DStringAppend(&ds, "\"", 1); } start = arg; for (special = arg; ; ) { @@ -1525,7 +1602,7 @@ BuildCommandLine( } if (*special == '"') { Tcl_DStringAppend(&ds, start, (int) (special - start)); - TclDStringAppendLiteral(&ds, "\\\""); + Tcl_DStringAppend(&ds, "\\\"", 2); start = special + 1; } if (*special == '\0') { @@ -1535,7 +1612,7 @@ BuildCommandLine( } Tcl_DStringAppend(&ds, start, (int) (special - start)); if (quote) { - TclDStringAppendLiteral(&ds, "\""); + Tcl_DStringAppend(&ds, "\"", 1); } } Tcl_DStringFree(linePtr); @@ -1571,7 +1648,7 @@ TclpCreateCommandChannel( { char channelName[16 + TCL_INTEGER_SPACE]; DWORD id; - PipeInfo *infoPtr = ckalloc(sizeof(PipeInfo)); + PipeInfo *infoPtr = (PipeInfo *) ckalloc((unsigned) sizeof(PipeInfo)); PipeInit(); @@ -1586,7 +1663,7 @@ TclpCreateCommandChannel( infoPtr->writeBuf = 0; infoPtr->writeBufLen = 0; infoPtr->writeError = 0; - infoPtr->channel = NULL; + infoPtr->channel = (Tcl_Channel) NULL; infoPtr->validMask = 0; @@ -1628,9 +1705,9 @@ TclpCreateCommandChannel( * unique, in case channels share handles (stdin/stdout). */ - sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t) infoPtr); + sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t)infoPtr); infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName, - infoPtr, infoPtr->validMask); + (ClientData) infoPtr, infoPtr->validMask); /* * Pipes have AUTO translation mode on Windows and ^Z eof char, which @@ -1638,58 +1715,16 @@ TclpCreateCommandChannel( * Windows programs that expect a ^Z at EOF. */ - Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); - Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); + Tcl_SetChannelOption((Tcl_Interp *) NULL, infoPtr->channel, + "-translation", "auto"); + Tcl_SetChannelOption((Tcl_Interp *) NULL, infoPtr->channel, + "-eofchar", "\032 {}"); return infoPtr->channel; } /* *---------------------------------------------------------------------- * - * Tcl_CreatePipe -- - * - * System dependent interface to create a pipe for the [chan pipe] - * command. Stolen from TclX. - * - * Results: - * TCL_OK or TCL_ERROR. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_CreatePipe( - Tcl_Interp *interp, /* Errors returned in result.*/ - Tcl_Channel *rchan, /* Where to return the read side. */ - Tcl_Channel *wchan, /* Where to return the write side. */ - int flags) /* Reserved for future use. */ -{ - HANDLE readHandle, writeHandle; - SECURITY_ATTRIBUTES sec; - - sec.nLength = sizeof(SECURITY_ATTRIBUTES); - sec.lpSecurityDescriptor = NULL; - sec.bInheritHandle = FALSE; - - if (!CreatePipe(&readHandle, &writeHandle, &sec, 0)) { - TclWinConvertError(GetLastError()); - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "pipe creation failed: %s", Tcl_PosixError(interp))); - return TCL_ERROR; - } - - *rchan = Tcl_MakeFileChannel((ClientData) readHandle, TCL_READABLE); - Tcl_RegisterChannel(interp, *rchan); - - *wchan = Tcl_MakeFileChannel((ClientData) writeHandle, TCL_WRITABLE); - Tcl_RegisterChannel(interp, *wchan); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * * TclGetAndDetachPids -- * * Stores a list of the command PIDs for a command channel in the @@ -1711,8 +1746,8 @@ TclGetAndDetachPids( { PipeInfo *pipePtr; const Tcl_ChannelType *chanTypePtr; - Tcl_Obj *pidsObj; int i; + char buf[TCL_INTEGER_SPACE]; /* * Punt if the channel is not a command channel. @@ -1723,17 +1758,14 @@ TclGetAndDetachPids( return; } - pipePtr = Tcl_GetChannelInstanceData(chan); - TclNewObj(pidsObj); + pipePtr = (PipeInfo *) Tcl_GetChannelInstanceData(chan); for (i = 0; i < pipePtr->numPids; i++) { - Tcl_ListObjAppendElement(NULL, pidsObj, - Tcl_NewWideIntObj((unsigned) - TclpGetPid(pipePtr->pidPtr[i]))); - Tcl_DetachPids(1, &pipePtr->pidPtr[i]); + wsprintfA(buf, "%lu", TclpGetPid(pipePtr->pidPtr[i])); + Tcl_AppendElement(interp, buf); + Tcl_DetachPids(1, &(pipePtr->pidPtr[i])); } - Tcl_SetObjResult(interp, pidsObj); if (pipePtr->numPids > 0) { - ckfree(pipePtr->pidPtr); + ckfree((char *) pipePtr->pidPtr); pipePtr->numPids = 0; } } @@ -1878,26 +1910,12 @@ PipeClose2Proc( && (pipePtr->writeFile != NULL)) { if (pipePtr->writeThread) { /* - * Wait for the writer thread to finish the current buffer, then - * terminate the thread and close the handles. If the channel is - * nonblocking but blocked during exit, bail out since the worker - * thread is not interruptible and we want TIP#398-fast-exit. + * Wait for the writer thread to finish the current buffer, then + * terminate the thread and close the handles. If the channel is + * nonblocking, there should be no pending write operations. */ - if (TclInExit() - && (pipePtr->flags & PIPE_ASYNC)) { - - /* give it a chance to leave honorably */ - SetEvent(pipePtr->stopWriter); - if (WaitForSingleObject(pipePtr->writable, 0) == WAIT_TIMEOUT) { - return EAGAIN; - } - - } else { - - WaitForSingleObject(pipePtr->writable, INFINITE); - - } + WaitForSingleObject(pipePtr->writable, INFINITE); /* * The thread may already have closed on it's own. Check its exit @@ -2007,11 +2025,12 @@ PipeClose2Proc( */ if (pipePtr->errorFile) { - WinFile *filePtr = (WinFile *) pipePtr->errorFile; + WinFile *filePtr; + filePtr = (WinFile*)pipePtr->errorFile; errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle, TCL_READABLE); - ckfree(filePtr); + ckfree((char *) filePtr); } else { errChan = NULL; } @@ -2021,14 +2040,14 @@ PipeClose2Proc( } if (pipePtr->numPids > 0) { - ckfree(pipePtr->pidPtr); + ckfree((char *) pipePtr->pidPtr); } if (pipePtr->writeBuf != NULL) { ckfree(pipePtr->writeBuf); } - ckfree(pipePtr); + ckfree((char*) pipePtr); if (errorCode == 0) { return result; @@ -2054,11 +2073,11 @@ PipeClose2Proc( *---------------------------------------------------------------------- */ -static ssize_t +static int PipeInputProc( ClientData instanceData, /* Pipe state. */ char *buf, /* Where to store data read. */ - size_t bufSize, /* How much space is available in the + int bufSize, /* How much space is available in the * buffer? */ int *errorCode) /* Where to store error code. */ { @@ -2148,11 +2167,11 @@ PipeInputProc( *---------------------------------------------------------------------- */ -static ssize_t +static int PipeOutputProc( ClientData instanceData, /* Pipe state. */ const char *buf, /* The data buffer. */ - size_t toWrite, /* How many bytes to write? */ + int toWrite, /* How many bytes to write? */ int *errorCode) /* Where to store error code. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; @@ -2196,7 +2215,7 @@ PipeOutputProc( ckfree(infoPtr->writeBuf); } infoPtr->writeBufLen = toWrite; - infoPtr->writeBuf = ckalloc(toWrite); + infoPtr->writeBuf = ckalloc((unsigned int) toWrite); } memcpy(infoPtr->writeBuf, buf, (size_t) toWrite); infoPtr->toWrite = toWrite; @@ -2575,7 +2594,7 @@ Tcl_WaitPid( */ CloseHandle(infoPtr->hProcess); - ckfree(infoPtr); + ckfree((char*)infoPtr); return result; } @@ -2601,9 +2620,9 @@ Tcl_WaitPid( void TclWinAddProcess( void *hProcess, /* Handle to process */ - unsigned long id) /* Global process identifier */ + unsigned long id) /* Global process identifier */ { - ProcInfo *procPtr = ckalloc(sizeof(ProcInfo)); + ProcInfo *procPtr = (ProcInfo *) ckalloc(sizeof(ProcInfo)); PipeInit(); @@ -2637,7 +2656,7 @@ int Tcl_PidObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ - size_t objc, /* Number of arguments. */ + int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Argument strings. */ { Tcl_Channel chan; @@ -2645,13 +2664,15 @@ Tcl_PidObjCmd( PipeInfo *pipePtr; int i; Tcl_Obj *resultPtr; + char buf[TCL_INTEGER_SPACE]; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?channelId?"); return TCL_ERROR; } if (objc == 1) { - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((unsigned) getpid())); + wsprintfA(buf, "%lu", (unsigned long) getpid()); + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); } else { chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); @@ -2666,9 +2687,9 @@ Tcl_PidObjCmd( pipePtr = (PipeInfo *) Tcl_GetChannelInstanceData(chan); resultPtr = Tcl_NewObj(); for (i = 0; i < pipePtr->numPids; i++) { + wsprintfA(buf, "%lu", TclpGetPid(pipePtr->pidPtr[i])); Tcl_ListObjAppendElement(/*interp*/ NULL, resultPtr, - Tcl_NewWideIntObj((unsigned) - TclpGetPid(pipePtr->pidPtr[i]))); + Tcl_NewStringObj(buf, -1)); } Tcl_SetObjResult(interp, resultPtr); } @@ -2960,10 +2981,6 @@ PipeWriterThread( * an error, so exit. */ - if (waitResult == WAIT_OBJECT_0) { - SetEvent(infoPtr->writable); - } - break; } @@ -3064,100 +3081,6 @@ PipeThreadActionProc( } /* - *---------------------------------------------------------------------- - * - * TclpOpenTemporaryFile -- - * - * Creates a temporary file, possibly based on the supplied bits and - * pieces of template supplied in the first three arguments. If the - * fourth argument is non-NULL, it contains a Tcl_Obj to store the name - * of the temporary file in (and it is caller's responsibility to clean - * up). If the fourth argument is NULL, try to arrange for the temporary - * file to go away once it is no longer needed. - * - * Results: - * A read-write Tcl Channel open on the file. - * - *---------------------------------------------------------------------- - */ - -Tcl_Channel -TclpOpenTemporaryFile( - Tcl_Obj *dirObj, - Tcl_Obj *basenameObj, - Tcl_Obj *extensionObj, - Tcl_Obj *resultingNameObj) -{ - TCHAR name[MAX_PATH]; - char *namePtr; - HANDLE handle; - DWORD flags = FILE_ATTRIBUTE_TEMPORARY; - int length, counter, counter2; - Tcl_DString buf; - - if (!resultingNameObj) { - flags |= FILE_FLAG_DELETE_ON_CLOSE; - } - - namePtr = (char *) name; - length = GetTempPath(MAX_PATH, name); - if (length == 0) { - goto gotError; - } - namePtr += length * sizeof(TCHAR); - if (basenameObj) { - const char *string = Tcl_GetStringFromObj(basenameObj, &length); - - Tcl_WinUtfToTChar(string, length, &buf); - memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)); - namePtr += Tcl_DStringLength(&buf); - Tcl_DStringFree(&buf); - } else { - const TCHAR *baseStr = TEXT("TCL"); - int length = 3 * sizeof(TCHAR); - - memcpy(namePtr, baseStr, length); - namePtr += length; - } - counter = TclpGetClicks() % 65533; - counter2 = 1024; /* Only try this many times! Prevents - * an infinite loop. */ - - do { - char number[TCL_INTEGER_SPACE + 4]; - - sprintf(number, "%d.TMP", counter); - counter = (unsigned short) (counter + 1); - Tcl_WinUtfToTChar(number, strlen(number), &buf); - Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf) + 1); - memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf) + 1); - Tcl_DStringFree(&buf); - - handle = CreateFile(name, - GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, flags, NULL); - } while (handle == INVALID_HANDLE_VALUE - && --counter2 > 0 - && GetLastError() == ERROR_FILE_EXISTS); - if (handle == INVALID_HANDLE_VALUE) { - goto gotError; - } - - if (resultingNameObj) { - Tcl_Obj *tmpObj = TclpNativeToNormalized(name); - - Tcl_AppendObjToObj(resultingNameObj, tmpObj); - TclDecrRefCount(tmpObj); - } - - return Tcl_MakeFileChannel((ClientData) handle, - TCL_READABLE|TCL_WRITABLE); - - gotError: - TclWinConvertError(GetLastError()); - return NULL; -} - -/* * Local Variables: * mode: c * c-basic-offset: 4 |
