| ︙ | | | ︙ | |
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
* This structure describes the channel type structure for command pipe based
* I/O.
*/
static const Tcl_ChannelType pipeChannelType = {
"pipe", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
NULL, /* 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 */
};
|
|
|
|
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
* This structure describes the channel type structure for command pipe based
* I/O.
*/
static const Tcl_ChannelType pipeChannelType = {
"pipe", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
NULL, /* Old 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, /* New close proc */
PipeBlockModeProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
NULL, /* wide seek proc */
PipeThreadActionProc, /* thread action proc */
NULL /* truncate */
};
|
| ︙ | | | ︙ | |
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
|
int
TclpCreateProcess(
Tcl_Interp *interp, /* Interpreter in which to leave errors that
* occurred when creating the child process.
* Error messages from the child process
* itself are sent to errorFile. */
size_t argc, /* Number of arguments in following array. */
const char **argv, /* Array of argument strings. argv[0] contains
* the name of the executable converted to
* native format (using the
* Tcl_TranslateFileName call). Additional
* arguments have not been converted. */
TclFile inputFile, /* If non-NULL, gives the file to use as input
* for the child process. If inputFile file is
|
|
|
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
|
int
TclpCreateProcess(
Tcl_Interp *interp, /* Interpreter in which to leave errors that
* occurred when creating the child process.
* Error messages from the child process
* itself are sent to errorFile. */
size_t argc, /* Number of arguments in following array. */
const char **argv, /* Array of argument strings. argv[0] contains
* the name of the executable converted to
* native format (using the
* Tcl_TranslateFileName call). Additional
* arguments have not been converted. */
TclFile inputFile, /* If non-NULL, gives the file to use as input
* for the child process. If inputFile file is
|
| ︙ | | | ︙ | |
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
|
return special;
}
static void
BuildCommandLine(
const char *executable, /* Full path of executable (including
* extension). Replacement for argv[0]. */
size_t argc, /* Number of arguments. */
const char **argv, /* Argument strings in UTF. */
Tcl_DString *linePtr) /* Initialized Tcl_DString that receives the
* command line (WCHAR). */
{
const char *arg, *start, *special, *bspos;
int quote = 0;
size_t i;
|
|
|
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
|
return special;
}
static void
BuildCommandLine(
const char *executable, /* Full path of executable (including
* extension). Replacement for argv[0]. */
size_t argc, /* Number of arguments. */
const char **argv, /* Argument strings in UTF. */
Tcl_DString *linePtr) /* Initialized Tcl_DString that receives the
* command line (WCHAR). */
{
const char *arg, *start, *special, *bspos;
int quote = 0;
size_t i;
|
| ︙ | | | ︙ | |
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
|
*start != '\0' &&
(quote & (CL_ESCAPE|CL_QUOTE)) != (CL_ESCAPE|CL_QUOTE);
start++) {
if (*start & 0x80) {
continue;
}
if (TclIsSpaceProc(*start)) {
quote |= CL_QUOTE; /* quote only */
if (bspos) { /* if backslash found, escape & quote */
quote |= CL_ESCAPE;
break;
}
continue;
}
if (strchr(specMetaChars, *start)) {
quote |= (CL_ESCAPE|CL_QUOTE); /* escape & quote */
|
|
|
|
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
|
*start != '\0' &&
(quote & (CL_ESCAPE|CL_QUOTE)) != (CL_ESCAPE|CL_QUOTE);
start++) {
if (*start & 0x80) {
continue;
}
if (TclIsSpaceProc(*start)) {
quote |= CL_QUOTE; /* quote only */
if (bspos) { /* if backslash found, escape & quote */
quote |= CL_ESCAPE;
break;
}
continue;
}
if (strchr(specMetaChars, *start)) {
quote |= (CL_ESCAPE|CL_QUOTE); /* escape & quote */
|
| ︙ | | | ︙ | |
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
|
if (readFile != NULL) {
/*
* Start the background reader thread.
*/
infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL);
infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread,
TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr, infoPtr->readable),
0, NULL);
SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);
infoPtr->validMask |= TCL_READABLE;
} else {
infoPtr->readTI = NULL;
infoPtr->readThread = 0;
}
if (writeFile != NULL) {
/*
* Start the background writer thread.
*/
infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL);
infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread,
TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr, infoPtr->writable),
0, NULL);
SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST);
infoPtr->validMask |= TCL_WRITABLE;
} else {
infoPtr->writeTI = NULL;
infoPtr->writeThread = 0;
}
|
|
|
|
|
|
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
|
if (readFile != NULL) {
/*
* Start the background reader thread.
*/
infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL);
infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread,
TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr, infoPtr->readable),
0, NULL);
SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);
infoPtr->validMask |= TCL_READABLE;
} else {
infoPtr->readTI = NULL;
infoPtr->readThread = 0;
}
if (writeFile != NULL) {
/*
* Start the background writer thread.
*/
infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL);
infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread,
TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr, infoPtr->writable),
0, NULL);
SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST);
infoPtr->validMask |= TCL_WRITABLE;
} else {
infoPtr->writeTI = NULL;
infoPtr->writeThread = 0;
}
|
| ︙ | | | ︙ | |
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
|
* Sets the device into blocking or non-blocking mode.
*
*----------------------------------------------------------------------
*/
static int
PipeBlockModeProc(
void *instanceData, /* Instance data for channel. */
int mode) /* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
/*
* Pipes on Windows can not be switched between blocking and nonblocking,
|
|
|
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
|
* Sets the device into blocking or non-blocking mode.
*
*----------------------------------------------------------------------
*/
static int
PipeBlockModeProc(
void *instanceData, /* Instance data for channel. */
int mode) /* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
/*
* Pipes on Windows can not be switched between blocking and nonblocking,
|
| ︙ | | | ︙ | |
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
|
* Closes the physical channel.
*
*----------------------------------------------------------------------
*/
static int
PipeClose2Proc(
void *instanceData, /* Pointer to PipeInfo structure. */
Tcl_Interp *interp, /* For error reporting. */
int flags) /* Flags that indicate which side to close. */
{
PipeInfo *pipePtr = (PipeInfo *) instanceData;
Tcl_Channel errChan;
int errorCode, result;
PipeInfo *infoPtr, **nextPtrPtr;
|
|
|
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
|
* Closes the physical channel.
*
*----------------------------------------------------------------------
*/
static int
PipeClose2Proc(
void *instanceData, /* Pointer to PipeInfo structure. */
Tcl_Interp *interp, /* For error reporting. */
int flags) /* Flags that indicate which side to close. */
{
PipeInfo *pipePtr = (PipeInfo *) instanceData;
Tcl_Channel errChan;
int errorCode, result;
PipeInfo *infoPtr, **nextPtrPtr;
|
| ︙ | | | ︙ | |
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
|
/*
* Clean up the background thread if necessary. Note that this must be
* done before we can close the file, since the thread may be blocking
* trying to read from the pipe.
*/
if (pipePtr->readThread) {
TclPipeThreadStop(&pipePtr->readTI, pipePtr->readThread);
CloseHandle(pipePtr->readThread);
CloseHandle(pipePtr->readable);
pipePtr->readThread = NULL;
}
if (TclpCloseFile(pipePtr->readFile) != 0) {
errorCode = errno;
}
pipePtr->validMask &= ~TCL_READABLE;
pipePtr->readFile = NULL;
}
if ((!flags || flags & TCL_CLOSE_WRITE) && (pipePtr->writeFile != NULL)) {
if (pipePtr->writeThread) {
/*
* Wait for the writer thread to finish the current buffer, then
* terminate the thread and close the handles. If the channel is
* nonblocking or may block during exit, bail out since the worker
* thread is not interruptible and we want TIP#398-fast-exit.
*/
if ((pipePtr->flags & PIPE_ASYNC) && inExit) {
/* give it a chance to leave honorably */
TclPipeThreadStopSignal(&pipePtr->writeTI, pipePtr->writable);
if (WaitForSingleObject(pipePtr->writable, 20) == WAIT_TIMEOUT) {
return EWOULDBLOCK;
}
} else {
WaitForSingleObject(pipePtr->writable, inExit ? 5000 : INFINITE);
}
TclPipeThreadStop(&pipePtr->writeTI, pipePtr->writeThread);
CloseHandle(pipePtr->writable);
CloseHandle(pipePtr->writeThread);
pipePtr->writeThread = NULL;
|
<
<
<
>
<
<
<
|
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
|
/*
* Clean up the background thread if necessary. Note that this must be
* done before we can close the file, since the thread may be blocking
* trying to read from the pipe.
*/
if (pipePtr->readThread) {
TclPipeThreadStop(&pipePtr->readTI, pipePtr->readThread);
CloseHandle(pipePtr->readThread);
CloseHandle(pipePtr->readable);
pipePtr->readThread = NULL;
}
if (TclpCloseFile(pipePtr->readFile) != 0) {
errorCode = errno;
}
pipePtr->validMask &= ~TCL_READABLE;
pipePtr->readFile = NULL;
}
if ((!flags || flags & TCL_CLOSE_WRITE) && (pipePtr->writeFile != NULL)) {
if (pipePtr->writeThread) {
/*
* Wait for the writer thread to finish the current buffer, then
* terminate the thread and close the handles. If the channel is
* nonblocking or may block during exit, bail out since the worker
* thread is not interruptible and we want TIP#398-fast-exit.
*/
if ((pipePtr->flags & PIPE_ASYNC) && inExit) {
/* give it a chance to leave honorably */
TclPipeThreadStopSignal(&pipePtr->writeTI, pipePtr->writable);
if (WaitForSingleObject(pipePtr->writable, 20) == WAIT_TIMEOUT) {
return EWOULDBLOCK;
}
} else {
WaitForSingleObject(pipePtr->writable, inExit ? 5000 : INFINITE);
}
TclPipeThreadStop(&pipePtr->writeTI, pipePtr->writeThread);
CloseHandle(pipePtr->writable);
CloseHandle(pipePtr->writeThread);
pipePtr->writeThread = NULL;
|
| ︙ | | | ︙ | |
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
|
* Reads input from the actual channel.
*
*----------------------------------------------------------------------
*/
static int
PipeInputProc(
void *instanceData, /* Pipe state. */
char *buf, /* Where to store data read. */
int bufSize, /* How much space is available in the
* buffer? */
int *errorCode) /* Where to store error code. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
WinFile *filePtr = (WinFile*) infoPtr->readFile;
|
|
|
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
|
* Reads input from the actual channel.
*
*----------------------------------------------------------------------
*/
static int
PipeInputProc(
void *instanceData, /* Pipe state. */
char *buf, /* Where to store data read. */
int bufSize, /* How much space is available in the
* buffer? */
int *errorCode) /* Where to store error code. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
WinFile *filePtr = (WinFile*) infoPtr->readFile;
|
| ︙ | | | ︙ | |
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
|
* Writes output on the actual channel.
*
*----------------------------------------------------------------------
*/
static int
PipeOutputProc(
void *instanceData, /* Pipe state. */
const char *buf, /* The data buffer. */
int toWrite, /* How many bytes to write? */
int *errorCode) /* Where to store error code. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
WinFile *filePtr = (WinFile*) infoPtr->writeFile;
DWORD bytesWritten, timeout;
|
|
|
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
|
* Writes output on the actual channel.
*
*----------------------------------------------------------------------
*/
static int
PipeOutputProc(
void *instanceData, /* Pipe state. */
const char *buf, /* The data buffer. */
int toWrite, /* How many bytes to write? */
int *errorCode) /* Where to store error code. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
WinFile *filePtr = (WinFile*) infoPtr->writeFile;
DWORD bytesWritten, timeout;
|
| ︙ | | | ︙ | |
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
|
}
}
return bytesWritten;
error:
*errorCode = errno;
return -1;
}
/*
*----------------------------------------------------------------------
*
* PipeEventProc --
*
|
<
|
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
|
}
}
return bytesWritten;
error:
*errorCode = errno;
return -1;
}
/*
*----------------------------------------------------------------------
*
* PipeEventProc --
*
|
| ︙ | | | ︙ | |
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
|
* None.
*
*----------------------------------------------------------------------
*/
static void
PipeWatchProc(
void *instanceData, /* Pipe state. */
int mask) /* What events to watch for, OR-ed combination
* of TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
PipeInfo **nextPtrPtr, *ptr;
PipeInfo *infoPtr = (PipeInfo *) instanceData;
int oldMask = infoPtr->watchMask;
|
|
|
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
|
* None.
*
*----------------------------------------------------------------------
*/
static void
PipeWatchProc(
void *instanceData, /* Pipe state. */
int mask) /* What events to watch for, OR-ed combination
* of TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
PipeInfo **nextPtrPtr, *ptr;
PipeInfo *infoPtr = (PipeInfo *) instanceData;
int oldMask = infoPtr->watchMask;
|
| ︙ | | | ︙ | |
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
|
* None.
*
*----------------------------------------------------------------------
*/
static int
PipeGetHandleProc(
void *instanceData, /* The pipe state. */
int direction, /* TCL_READABLE or TCL_WRITABLE */
void **handlePtr) /* Where to store the handle. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
WinFile *filePtr;
if (direction == TCL_READABLE && infoPtr->readFile) {
filePtr = (WinFile*) infoPtr->readFile;
*handlePtr = (void *)filePtr->handle;
|
|
|
|
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
|
* None.
*
*----------------------------------------------------------------------
*/
static int
PipeGetHandleProc(
void *instanceData, /* The pipe state. */
int direction, /* TCL_READABLE or TCL_WRITABLE */
void **handlePtr) /* Where to store the handle. */
{
PipeInfo *infoPtr = (PipeInfo *) instanceData;
WinFile *filePtr;
if (direction == TCL_READABLE && infoPtr->readFile) {
filePtr = (WinFile*) infoPtr->readFile;
*handlePtr = (void *)filePtr->handle;
|
| ︙ | | | ︙ | |
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
|
const WCHAR *baseStr = L"TCL";
length = 3 * sizeof(WCHAR);
memcpy(namePtr, baseStr, length);
namePtr += length;
}
counter = TclpGetClicks() % 65533;
counter2 = 1024; /* Only try this many times! Prevents
* an infinite loop. */
do {
char number[TCL_INTEGER_SPACE + 4];
snprintf(number, sizeof(number), "%d.TMP", counter);
counter = (unsigned short) (counter + 1);
Tcl_DStringInit(&buf);
|
|
|
|
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
|
const WCHAR *baseStr = L"TCL";
length = 3 * sizeof(WCHAR);
memcpy(namePtr, baseStr, length);
namePtr += length;
}
counter = TclpGetClicks() % 65533;
counter2 = 1024; /* Only try this many times! Prevents
* an infinite loop. */
do {
char number[TCL_INTEGER_SPACE + 4];
snprintf(number, sizeof(number), "%d.TMP", counter);
counter = (unsigned short) (counter + 1);
Tcl_DStringInit(&buf);
|
| ︙ | | | ︙ | |