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
/* 
 * 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;