Diff
Not logged in

Differences From Artifact [9ba548b78d]:

To Artifact [247bebd85b]:


1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
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 $
 * 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
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 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);
264
265
266
267
268
269
270







271
272
273
274
275
276
277








278
279
280
281
282
283
284
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);
	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
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);
    initialized = 0;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
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







-
+













-
-
+
+







	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * MakeFile --
 * 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.
 *
 *----------------------------------------------------------------------
 */

static TclFile
MakeFile(
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
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 MakeFile(handle);
	return TclWinMakeFile(handle);
    } else {
	return (TclFile) NULL;
    }
}

/*
 *----------------------------------------------------------------------
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
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 MakeFile(handle);
    return TclWinMakeFile(handle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCreateTempFile --
 *
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
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 MakeFile(handle);
	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
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 = MakeFile(readHandle);
	*writePipe = MakeFile(writeHandle);
	*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
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%d", channelId);
    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
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;