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
|