| ︙ | | |
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
|
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
|
-
+
+
+
|
* Removes the console event source.
*
*----------------------------------------------------------------------
*/
static void
ConsoleExitHandler(
ClientData clientData) /* Old window proc. */
ClientData dummy) /* Old window proc. */
{
(void)dummy;
Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
}
/*
*----------------------------------------------------------------------
*
* ProcExitHandler --
|
| ︙ | | |
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
|
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
|
-
+
+
+
|
* Resets the process list.
*
*----------------------------------------------------------------------
*/
static void
ProcExitHandler(
ClientData clientData) /* Old window proc. */
ClientData dummy) /* Old window proc. */
{
(void)dummy;
Tcl_MutexLock(&consoleMutex);
initialized = 0;
Tcl_MutexUnlock(&consoleMutex);
}
/*
*----------------------------------------------------------------------
|
| ︙ | | |
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
|
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
|
-
+
+
|
* Adjusts the block time if needed.
*
*----------------------------------------------------------------------
*/
void
ConsoleSetupProc(
ClientData data, /* Not used. */
ClientData dummy, /* Not used. */
int flags) /* Event flags as passed to Tcl_DoOneEvent. */
{
ConsoleInfo *infoPtr;
Tcl_Time blockTime = { 0, 0 };
int block = 1;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
(void)dummy;
if (!(flags & TCL_FILE_EVENTS)) {
return;
}
/*
* Look to see if any events are already pending. If they are, poll.
|
| ︙ | | |
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
|
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
|
-
+
+
|
* May queue an event.
*
*----------------------------------------------------------------------
*/
static void
ConsoleCheckProc(
ClientData data, /* Not used. */
ClientData dummy, /* Not used. */
int flags) /* Event flags as passed to Tcl_DoOneEvent. */
{
ConsoleInfo *infoPtr;
int needEvent;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
(void)dummy;
if (!(flags & TCL_FILE_EVENTS)) {
return;
}
/*
* Queue events for any ready consoles that don't already have events
|
| ︙ | | |
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
|
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
|
-
+
|
if (infoPtr->watchMask & TCL_READABLE) {
if (WaitForRead(infoPtr, 0) >= 0) {
needEvent = 1;
}
}
if (needEvent) {
ConsoleEvent *evPtr = Tcl_Alloc(sizeof(ConsoleEvent));
ConsoleEvent *evPtr = (ConsoleEvent *)Tcl_Alloc(sizeof(ConsoleEvent));
infoPtr->flags |= CONSOLE_PENDING;
evPtr->header.proc = ConsoleEventProc;
evPtr->infoPtr = infoPtr;
Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
}
}
|
| ︙ | | |
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
|
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
|
-
+
|
static int
ConsoleBlockModeProc(
ClientData instanceData, /* Instance data for channel. */
int mode) /* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
/*
* Consoles on Windows can not be switched between blocking and
* nonblocking, hence we have to emulate the behavior. This is done in the
* input function by checking against a bit in the state. We set or unset
* the bit here to cause the input function to emulate the correct
* behavior.
|
| ︙ | | |
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
|
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
|
-
+
-
+
+
|
*
*----------------------------------------------------------------------
*/
static int
ConsoleCloseProc(
ClientData instanceData, /* Pointer to ConsoleInfo structure. */
Tcl_Interp *interp) /* For error reporting. */
Tcl_Interp *dummy) /* For error reporting. */
{
ConsoleInfo *consolePtr = instanceData;
ConsoleInfo *consolePtr = (ConsoleInfo *)instanceData;
int errorCode = 0;
ConsoleInfo *infoPtr, **nextPtrPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
(void)dummy;
/*
* 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 console.
*/
|
| ︙ | | |
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
|
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
|
-
+
|
ConsoleInputProc(
ClientData instanceData, /* Console 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. */
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
DWORD count, bytesRead = 0;
int result;
*errorCode = 0;
/*
* Synchronize with the reader thread.
|
| ︙ | | |
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
|
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
|
-
+
|
static int
ConsoleOutputProc(
ClientData instanceData, /* Console state. */
const char *buf, /* The data buffer. */
int toWrite, /* How many bytes to write? */
int *errorCode) /* Where to store error code. */
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
ConsoleThreadInfo *threadInfo = &infoPtr->writer;
DWORD bytesWritten, timeout;
*errorCode = 0;
/* avoid blocking if pipe-thread exited */
timeout = (infoPtr->flags & CONSOLE_ASYNC) || !TclPipeThreadIsAlive(&threadInfo->TI)
|
| ︙ | | |
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
|
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
|
-
+
|
* Reallocate the buffer to be large enough to hold the data.
*/
if (infoPtr->writeBuf) {
Tcl_Free(infoPtr->writeBuf);
}
infoPtr->writeBufLen = toWrite;
infoPtr->writeBuf = Tcl_Alloc(toWrite);
infoPtr->writeBuf = (char *)Tcl_Alloc(toWrite);
}
memcpy(infoPtr->writeBuf, buf, toWrite);
infoPtr->toWrite = toWrite;
ResetEvent(threadInfo->readyEvent);
TclPipeThreadSignal(&threadInfo->TI);
bytesWritten = toWrite;
} else {
|
| ︙ | | |
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
|
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
|
-
+
|
ConsoleWatchProc(
ClientData instanceData, /* Console state. */
int mask) /* What events to watch for, OR-ed combination
* of TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
ConsoleInfo **nextPtrPtr, *ptr;
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
int oldMask = infoPtr->watchMask;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
* Since most of the work is handled by the background threads, we just
* need to update the watchMask and then force the notifier to poll once.
*/
|
| ︙ | | |
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
|
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
|
-
+
+
|
static int
ConsoleGetHandleProc(
ClientData instanceData, /* The console state. */
int direction, /* TCL_READABLE or TCL_WRITABLE. */
ClientData *handlePtr) /* Where to store the handle. */
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
(void)direction;
*handlePtr = infoPtr->handle;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
|
| ︙ | | |
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
|
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
|
-
+
|
static int
WaitForRead(
ConsoleInfo *infoPtr, /* Console state. */
int blocking) /* Indicates whether call should be blocking
* or not. */
{
DWORD timeout, count;
HANDLE *handle = infoPtr->handle;
HANDLE *handle = (HANDLE *)infoPtr->handle;
ConsoleThreadInfo *threadInfo = &infoPtr->reader;
INPUT_RECORD input;
while (1) {
/*
* Synchronize with the reader thread.
*/
|
| ︙ | | |
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
|
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
|
-
+
|
if (!TclPipeThreadWaitForSignal(&pipeTI)) {
/* exit */
break;
}
if (!infoPtr) {
infoPtr = (ConsoleInfo *)pipeTI->clientData;
handle = infoPtr->handle;
handle = (HANDLE *)infoPtr->handle;
threadInfo = &infoPtr->reader;
}
/*
* Look for data on the console, but first ignore any events that are
* not KEY_EVENTs.
|
| ︙ | | |
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
|
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
|
-
+
|
*/
if (!TclPipeThreadWaitForSignal(&pipeTI)) {
/* exit */
break;
}
if (!infoPtr) {
infoPtr = (ConsoleInfo *)pipeTI->clientData;
handle = infoPtr->handle;
handle = (HANDLE *)infoPtr->handle;
threadInfo = &infoPtr->writer;
}
buf = infoPtr->writeBuf;
toWrite = infoPtr->toWrite;
/*
|
| ︙ | | |
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
|
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
|
-
+
|
ConsoleInit();
/*
* See if a channel with this handle already exists.
*/
infoPtr = Tcl_Alloc(sizeof(ConsoleInfo));
infoPtr = (ConsoleInfo *)Tcl_Alloc(sizeof(ConsoleInfo));
memset(infoPtr, 0, sizeof(ConsoleInfo));
infoPtr->validMask = permissions;
infoPtr->handle = handle;
infoPtr->channel = (Tcl_Channel) NULL;
wsprintfA(encoding, "cp%d", GetConsoleCP());
|
| ︙ | | |
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
|
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
|
-
+
|
*/
static void
ConsoleThreadActionProc(
ClientData instanceData,
int action)
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
/*
* We do not access firstConsolePtr in the thread structures. This is not
* for all serials managed by the thread, but only those we are watching.
* Removal of the filevent handlers before transfer thus takes care of
* this structure.
*/
|
| ︙ | | |
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
|
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
|
-
+
|
static int
ConsoleSetOptionProc(
ClientData instanceData, /* File state. */
Tcl_Interp *interp, /* For error reporting - can be NULL. */
const char *optionName, /* Which option to set? */
const char *value) /* New value for option. */
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
int len = strlen(optionName);
int vlen = strlen(value);
/*
* Option -inputmode normal|password|raw
*/
|
| ︙ | | |
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
|
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
|
-
+
|
static int
ConsoleGetOptionProc(
ClientData instanceData, /* File state. */
Tcl_Interp *interp, /* For error reporting - can be NULL. */
const char *optionName, /* Option to get. */
Tcl_DString *dsPtr) /* Where to store value(s). */
{
ConsoleInfo *infoPtr = instanceData;
ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
int valid = 0; /* Flag if valid option parsed. */
unsigned int len;
char buf[TCL_INTEGER_SPACE];
if (optionName == NULL) {
len = 0;
} else {
|
| ︙ | | |