1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*
* tclWinPipe.c --
*
* This file implements the Windows-specific exec pipeline functions,
* the "pipe" channel driver, and the "pid" Tcl command.
*
* Copyright (c) 1996-1997 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclWinPipe.c,v 1.1.2.5 1998/12/12 01:37:05 lfb Exp $
*/
#include "tclWinInt.h"
#include <dos.h>
#include <fcntl.h>
#include <io.h>
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*
* tclWinPipe.c --
*
* This file implements the Windows-specific exec pipeline functions,
* the "pipe" channel driver, and the "pid" Tcl command.
*
* Copyright (c) 1996-1997 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclWinPipe.c,v 1.1.2.6 1999/02/26 02:19:24 redman Exp $
*/
#include "tclWinInt.h"
#include <dos.h>
#include <fcntl.h>
#include <io.h>
|
| ︙ | | | ︙ | |
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
static int ApplicationType(Tcl_Interp *interp,
const char *fileName, char *fullName);
static void BuildCommandLine(const char *executable, int argc,
char **argv, Tcl_DString *linePtr);
static void CopyChannel(HANDLE dst, HANDLE src);
static BOOL HasConsole(void);
static TclFile MakeFile(HANDLE handle);
static char * MakeTempFile(Tcl_DString *namePtr);
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 void PipeExitHandler(ClientData clientData);
|
<
|
202
203
204
205
206
207
208
209
210
211
212
213
214
215
|
static int ApplicationType(Tcl_Interp *interp,
const char *fileName, char *fullName);
static void BuildCommandLine(const char *executable, int argc,
char **argv, Tcl_DString *linePtr);
static void CopyChannel(HANDLE dst, HANDLE src);
static BOOL HasConsole(void);
static char * MakeTempFile(Tcl_DString *namePtr);
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 void PipeExitHandler(ClientData clientData);
|
| ︙ | | | ︙ | |
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
|
*----------------------------------------------------------------------
*/
static void
PipeInit()
{
ThreadSpecificData *tsdPtr;
Tcl_MutexLock(&procMutex);
if (!initialized) {
initialized = 1;
procList = NULL;
Tcl_CreateExitHandler(ProcExitHandler, NULL);
}
Tcl_MutexUnlock(&procMutex);
tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
if (tsdPtr == NULL) {
tsdPtr = TCL_TSD_INIT(&dataKey);
tsdPtr->firstPipePtr = NULL;
Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL);
Tcl_CreateThreadExitHandler(PipeExitHandler, NULL);
|
>
>
>
>
>
>
>
|
|
|
|
|
|
|
>
|
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
|
*----------------------------------------------------------------------
*/
static void
PipeInit()
{
ThreadSpecificData *tsdPtr;
/*
* Check the initialized flag first, then check again in the mutex.
* This is a speed enhancement.
*/
if (!initialized) {
Tcl_MutexLock(&procMutex);
if (!initialized) {
initialized = 1;
procList = NULL;
Tcl_CreateExitHandler(ProcExitHandler, NULL);
}
Tcl_MutexUnlock(&procMutex);
}
tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
if (tsdPtr == NULL) {
tsdPtr = TCL_TSD_INIT(&dataKey);
tsdPtr->firstPipePtr = NULL;
Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL);
Tcl_CreateThreadExitHandler(PipeExitHandler, NULL);
|
| ︙ | | | ︙ | |
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
*/
static void
PipeExitHandler(
ClientData clientData) /* Old window proc */
{
Tcl_DeleteEventSource(PipeSetupProc, PipeCheckProc, NULL);
initialized = 0;
}
/*
*----------------------------------------------------------------------
*
* ProcExitHandler --
*
|
<
|
310
311
312
313
314
315
316
317
318
319
320
321
322
323
|
*/
static void
PipeExitHandler(
ClientData clientData) /* Old window proc */
{
Tcl_DeleteEventSource(PipeSetupProc, PipeCheckProc, NULL);
}
/*
*----------------------------------------------------------------------
*
* ProcExitHandler --
*
|
| ︙ | | | ︙ | |
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
|
}
}
}
/*
*----------------------------------------------------------------------
*
* MakeFile --
*
* This function constructs a new TclFile from a given data and
* type value.
*
* Results:
* Returns a newly allocated WinFile as a TclFile.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static TclFile
MakeFile(
HANDLE handle) /* Type-specific data. */
{
WinFile *filePtr;
filePtr = (WinFile *) ckalloc(sizeof(WinFile));
filePtr->type = WIN_FILE;
filePtr->handle = handle;
|
|
|
|
|
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
|
}
}
}
/*
*----------------------------------------------------------------------
*
* TclWinMakeFile --
*
* This function constructs a new TclFile from a given data and
* type value.
*
* Results:
* Returns a newly allocated WinFile as a TclFile.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
TclFile
TclWinMakeFile(
HANDLE handle) /* Type-specific data. */
{
WinFile *filePtr;
filePtr = (WinFile *) ckalloc(sizeof(WinFile));
filePtr->type = WIN_FILE;
filePtr->handle = handle;
|
| ︙ | | | ︙ | |
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
|
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 MakeFile(handle);
} else {
return (TclFile) NULL;
}
}
/*
*----------------------------------------------------------------------
|
|
|
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
|
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;
}
}
/*
*----------------------------------------------------------------------
|
| ︙ | | | ︙ | |
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
|
* Seek to the end of file if we are writing.
*/
if (mode & O_WRONLY) {
SetFilePointer(handle, 0, NULL, FILE_END);
}
return MakeFile(handle);
}
/*
*----------------------------------------------------------------------
*
* TclpCreateTempFile --
*
|
|
|
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
|
* Seek to the end of file if we are writing.
*/
if (mode & O_WRONLY) {
SetFilePointer(handle, 0, NULL, FILE_END);
}
return TclWinMakeFile(handle);
}
/*
*----------------------------------------------------------------------
*
* TclpCreateTempFile --
*
|
| ︙ | | | ︙ | |
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
|
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) {
TmpFile *tmpFilePtr = (TmpFile *) ckalloc(sizeof(TmpFile));
tmpFilePtr->file.type = WIN32S_TMPFILE;
tmpFilePtr->file.handle = handle;
lstrcpyA(tmpFilePtr->name, (char *) name);
return (TclFile) tmpFilePtr;
} else {
return MakeFile(handle);
}
error:
TclWinConvertError(GetLastError());
CloseHandle(handle);
(*tclWinProcs->deleteFileProc)((TCHAR *) name);
return NULL;
|
|
|
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
|
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) {
TmpFile *tmpFilePtr = (TmpFile *) ckalloc(sizeof(TmpFile));
tmpFilePtr->file.type = WIN32S_TMPFILE;
tmpFilePtr->file.handle = handle;
lstrcpyA(tmpFilePtr->name, (char *) name);
return (TclFile) tmpFilePtr;
} else {
return TclWinMakeFile(handle);
}
error:
TclWinConvertError(GetLastError());
CloseHandle(handle);
(*tclWinProcs->deleteFileProc)((TCHAR *) name);
return NULL;
|
| ︙ | | | ︙ | |
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
|
* read side of pipe. */
TclFile *writePipe) /* Location to store file handle for
* write side of pipe. */
{
HANDLE readHandle, writeHandle;
if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) {
*readPipe = MakeFile(readHandle);
*writePipe = MakeFile(writeHandle);
return 1;
}
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) {
WinPipe *readPipePtr, *writePipePtr;
char buf[MAX_PATH];
int bytes;
|
|
|
|
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
|
* read side of pipe. */
TclFile *writePipe) /* Location to store file handle for
* write side of pipe. */
{
HANDLE readHandle, writeHandle;
if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) {
*readPipe = TclWinMakeFile(readHandle);
*writePipe = TclWinMakeFile(writeHandle);
return 1;
}
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) {
WinPipe *readPipePtr, *writePipePtr;
char buf[MAX_PATH];
int bytes;
|
| ︙ | | | ︙ | |
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
|
infoPtr->validMask |= TCL_WRITABLE;
}
/*
* For backward compatibility with previous versions of Tcl, we
* use "file%d" as the base name for pipes even though it would
* be more natural to use "pipe%d".
*/
wsprintfA(channelName, "file%d", channelId);
infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
(ClientData) infoPtr, infoPtr->validMask);
/*
* Pipes have AUTO translation mode on Windows and ^Z eof char, which
* means that a ^Z will be appended to them at close. This is needed
* for Windows programs that expect a ^Z at EOF.
|
>
>
|
|
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
|
infoPtr->validMask |= TCL_WRITABLE;
}
/*
* For backward compatibility with previous versions of Tcl, we
* use "file%d" as the base name for pipes even though it would
* be more natural to use "pipe%d".
* Use the pointer to keep the channel names unique, in case
* channels share handles (stdin/stdout).
*/
wsprintfA(channelName, "file%lx", infoPtr);
infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
(ClientData) infoPtr, infoPtr->validMask);
/*
* Pipes have AUTO translation mode on Windows and ^Z eof char, which
* means that a ^Z will be appended to them at close. This is needed
* for Windows programs that expect a ^Z at EOF.
|
| ︙ | | | ︙ | |
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
|
errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle,
TCL_READABLE);
ckfree((char *) filePtr);
}
} else {
errChan = NULL;
}
result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
errChan);
if (pipePtr->numPids > 0) {
ckfree((char *) pipePtr->pidPtr);
}
ckfree((char*) pipePtr);
if (errorCode == 0) {
return result;
}
return errorCode;
|
>
>
>
>
>
>
|
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
|
errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle,
TCL_READABLE);
ckfree((char *) filePtr);
}
} else {
errChan = NULL;
}
result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
errChan);
if (pipePtr->numPids > 0) {
ckfree((char *) pipePtr->pidPtr);
}
if (pipePtr->writeBuf != NULL) {
ckfree(pipePtr->writeBuf);
}
ckfree((char*) pipePtr);
if (errorCode == 0) {
return result;
}
return errorCode;
|
| ︙ | | | ︙ | |