summaryrefslogtreecommitdiffstats
path: root/win/tclWinPipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tclWinPipe.c')
-rw-r--r--win/tclWinPipe.c475
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