Diff
Not logged in

Differences From Artifact [d36be8f8a7]:

To Artifact [876ef70408]:


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.35.2.13 2005/12/02 18:43:11 dgp Exp $
 * RCS: @(#) $Id: tclWinPipe.c,v 1.35.2.14 2006/04/28 16:10:51 dgp Exp $
 */

#include "tclWinInt.h"

#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
183
184
185
186
187
188
189

190
191
192
193
194
195
196







-







			    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 void		PipeExitHandler(ClientData clientData);
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);
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235







-
+














+







/*
 * This structure describes the channel type structure for command pipe based
 * I/O.
 */

static Tcl_ChannelType pipeChannelType = {
    "pipe",			/* Type name. */
    TCL_CHANNEL_VERSION_4,	/* v4 channel */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    TCL_CLOSE2PROC,		/* Close proc. */
    PipeInputProc,		/* Input proc. */
    PipeOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    NULL,			/* Set option proc. */
    NULL,			/* Get option proc. */
    PipeWatchProc,		/* Set up notifier to watch the channel. */
    PipeGetHandleProc,		/* Get an OS handle from channel. */
    PipeClose2Proc,		/* close2proc */
    PipeBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc */
    PipeThreadActionProc,	/* thread action proc */
    NULL,                       /* truncate */
};

/*
 *----------------------------------------------------------------------
 *
 * PipeInit --
 *
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
292
293


294
295
296
297
298

299
300
301

302
303
304
305
306
307


308
309
310
311
312
313
314
315


316
317
318
319
320
321
322
323
324
325
326
327
328
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
292

293



294



295






296
297








298
299






300
301
302
303
304
305
306







-






-
+

-
-
+
+










-
-
+
+
-

-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-







    }

    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    if (tsdPtr == NULL) {
	tsdPtr = TCL_TSD_INIT(&dataKey);
	tsdPtr->firstPipePtr = NULL;
	Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL);
	Tcl_CreateThreadExitHandler(PipeExitHandler, NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PipeExitHandler --
 * TclpFinalizePipes --
 *
 *	This function is called to cleanup the pipe module before Tcl is
 *	unloaded.
 *	This function is called from Tcl_FinalizeThread to finalize the
 *	platform specific pipe subsystem.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Removes the pipe event source.
 *
 *----------------------------------------------------------------------
 */

static void
PipeExitHandler(
void
TclpFinalizePipes(void)
    ClientData clientData)	/* Old window proc */
{
    Tcl_DeleteEventSource(PipeSetupProc, PipeCheckProc, NULL);
}

    ThreadSpecificData *tsdPtr;
/*
 *----------------------------------------------------------------------
 *

 * TclpFinalizePipes --
 *
 *	This function is called to cleanup the process list before Tcl is
 *	unloaded.
 *
 * Results:
    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    if (tsdPtr != NULL) {
 *	None.
 *
 * Side effects:
 *	Resets the process list.
 *
 *----------------------------------------------------------------------
 */

	Tcl_DeleteEventSource(PipeSetupProc, PipeCheckProc, NULL);
    }
void
TclpFinalizePipes(void)
{
    Tcl_MutexLock(&pipeMutex);
    initialized = 0;
    Tcl_MutexUnlock(&pipeMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * PipeSetupProc --
 *
1191
1192
1193
1194
1195
1196
1197




1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233




























1234
1235

1236
1237
1238

1239




1240
1241
1242
1243
1244
1245
1246
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186





























1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214


1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231







+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+



+

+
+
+
+







	     * 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_Obj *tclExePtr, *pipeDllPtr;
		int i, fileExists;
		char *start,*end;
		Tcl_DString pipeDll;

		Tcl_DStringInit(&pipeDll);
		Tcl_DStringAppend(&pipeDll, TCL_PIPE_DLL, -1);
		tclExePtr = TclGetObjNameOfExecutable();
		start = Tcl_GetStringFromObj(tclExePtr, &i);
		for (end = start + (i-1); end > start; end--) {
		    if (*end == '/') {
			break;
		    }
		}
		if (*end != '/') {
		    Tcl_Panic("no / in executable path name");
		}
		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_Panic("Tcl pipe dll \"%s\" not found",
			Tcl_DStringValue(&pipeDll));
	    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",
		}
		Tcl_DStringAppend(&cmdLine, Tcl_DStringValue(&pipeDll), -1);
			(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);
	}
    }

    /*
     * cmdLine gets the full command line used to invoke the executable,
     * including the name of the executable itself. The command line arguments
     * in argv[] are stored in cmdLine separated by spaces. Special characters