1/* 2 * tclIO.c -- 3 * 4 * This file provides the generic portions (those that are the same on 5 * all platforms and for all channel types) of Tcl's IO facilities. 6 * 7 * Copyright (c) 1998-2000 Ajuba Solutions 8 * Copyright (c) 1995-1997 Sun Microsystems, Inc. 9 * 10 * See the file "license.terms" for information on usage and redistribution 11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 * 13 * RCS: @(#) $Id: tclIO.c,v 1.61.2.28 2008/04/15 18:31:01 andreas_kupries Exp $ 14 */ 15 16#include "tclInt.h" 17#include "tclPort.h" 18#include "tclIO.h" 19#include <assert.h> 20 21#ifndef TCL_INHERIT_STD_CHANNELS 22#define TCL_INHERIT_STD_CHANNELS 1 23#endif 24 25 26/* 27 * All static variables used in this file are collected into a single 28 * instance of the following structure. For multi-threaded implementations, 29 * there is one instance of this structure for each thread. 30 * 31 * Notice that different structures with the same name appear in other 32 * files. The structure defined below is used in this file only. 33 */ 34 35typedef struct ThreadSpecificData { 36 37 /* 38 * This variable holds the list of nested ChannelHandlerEventProc 39 * invocations. 40 */ 41 NextChannelHandler *nestedHandlerPtr; 42 43 /* 44 * List of all channels currently open, indexed by ChannelState, 45 * as only one ChannelState exists per set of stacked channels. 46 */ 47 ChannelState *firstCSPtr; 48#ifdef oldcode 49 /* 50 * Has a channel exit handler been created yet? 51 */ 52 int channelExitHandlerCreated; 53 54 /* 55 * Has the channel event source been created and registered with the 56 * notifier? 57 */ 58 int channelEventSourceCreated; 59#endif 60 /* 61 * Static variables to hold channels for stdin, stdout and stderr. 62 */ 63 Tcl_Channel stdinChannel; 64 int stdinInitialized; 65 Tcl_Channel stdoutChannel; 66 int stdoutInitialized; 67 Tcl_Channel stderrChannel; 68 int stderrInitialized; 69 70} ThreadSpecificData; 71 72static Tcl_ThreadDataKey dataKey; 73 74/* 75 * Static functions in this file: 76 */ 77 78static ChannelBuffer * AllocChannelBuffer _ANSI_ARGS_((int length)); 79static void ChannelTimerProc _ANSI_ARGS_(( 80 ClientData clientData)); 81static int CheckChannelErrors _ANSI_ARGS_((ChannelState *statePtr, 82 int direction)); 83static int CheckFlush _ANSI_ARGS_((Channel *chanPtr, 84 ChannelBuffer *bufPtr, int newlineFlag)); 85static int CheckForDeadChannel _ANSI_ARGS_((Tcl_Interp *interp, 86 ChannelState *statePtr)); 87static void CheckForStdChannelsBeingClosed _ANSI_ARGS_(( 88 Tcl_Channel chan)); 89static void CleanupChannelHandlers _ANSI_ARGS_(( 90 Tcl_Interp *interp, Channel *chanPtr)); 91static int CloseChannel _ANSI_ARGS_((Tcl_Interp *interp, 92 Channel *chanPtr, int errorCode)); 93static void CommonGetsCleanup _ANSI_ARGS_((Channel *chanPtr, 94 Tcl_Encoding encoding)); 95static int CopyAndTranslateBuffer _ANSI_ARGS_(( 96 ChannelState *statePtr, char *result, 97 int space)); 98static int CopyBuffer _ANSI_ARGS_(( 99 Channel *chanPtr, char *result, int space)); 100static int CopyData _ANSI_ARGS_((CopyState *csPtr, int mask)); 101static void CopyEventProc _ANSI_ARGS_((ClientData clientData, 102 int mask)); 103static void CreateScriptRecord _ANSI_ARGS_(( 104 Tcl_Interp *interp, Channel *chanPtr, 105 int mask, Tcl_Obj *scriptPtr)); 106static void DeleteChannelTable _ANSI_ARGS_(( 107 ClientData clientData, Tcl_Interp *interp)); 108static void DeleteScriptRecord _ANSI_ARGS_((Tcl_Interp *interp, 109 Channel *chanPtr, int mask)); 110static int DetachChannel _ANSI_ARGS_((Tcl_Interp *interp, 111 Tcl_Channel chan)); 112static void DiscardInputQueued _ANSI_ARGS_((ChannelState *statePtr, 113 int discardSavedBuffers)); 114static void DiscardOutputQueued _ANSI_ARGS_(( 115 ChannelState *chanPtr)); 116static int DoRead _ANSI_ARGS_((Channel *chanPtr, char *srcPtr, 117 int slen)); 118static int DoWrite _ANSI_ARGS_((Channel *chanPtr, CONST char *src, 119 int srcLen)); 120static int DoReadChars _ANSI_ARGS_ ((Channel* chan, 121 Tcl_Obj* objPtr, int toRead, int appendFlag)); 122static int DoWriteChars _ANSI_ARGS_ ((Channel* chan, 123 CONST char* src, int len)); 124static int FilterInputBytes _ANSI_ARGS_((Channel *chanPtr, 125 GetsState *statePtr)); 126static int FlushChannel _ANSI_ARGS_((Tcl_Interp *interp, 127 Channel *chanPtr, int calledFromAsyncFlush)); 128static Tcl_HashTable * GetChannelTable _ANSI_ARGS_((Tcl_Interp *interp)); 129static int GetInput _ANSI_ARGS_((Channel *chanPtr)); 130static int HaveVersion _ANSI_ARGS_((Tcl_ChannelType *typePtr, 131 Tcl_ChannelTypeVersion minimumVersion)); 132static void PeekAhead _ANSI_ARGS_((Channel *chanPtr, 133 char **dstEndPtr, GetsState *gsPtr)); 134static int ReadBytes _ANSI_ARGS_((ChannelState *statePtr, 135 Tcl_Obj *objPtr, int charsLeft, 136 int *offsetPtr)); 137static int ReadChars _ANSI_ARGS_((ChannelState *statePtr, 138 Tcl_Obj *objPtr, int charsLeft, 139 int *offsetPtr, int *factorPtr)); 140static void RecycleBuffer _ANSI_ARGS_((ChannelState *statePtr, 141 ChannelBuffer *bufPtr, int mustDiscard)); 142static int StackSetBlockMode _ANSI_ARGS_((Channel *chanPtr, 143 int mode)); 144static int SetBlockMode _ANSI_ARGS_((Tcl_Interp *interp, 145 Channel *chanPtr, int mode)); 146static void StopCopy _ANSI_ARGS_((CopyState *csPtr)); 147static int TranslateInputEOL _ANSI_ARGS_((ChannelState *statePtr, 148 char *dst, CONST char *src, 149 int *dstLenPtr, int *srcLenPtr)); 150static int TranslateOutputEOL _ANSI_ARGS_((ChannelState *statePtr, 151 char *dst, CONST char *src, 152 int *dstLenPtr, int *srcLenPtr)); 153static void UpdateInterest _ANSI_ARGS_((Channel *chanPtr)); 154static int WriteBytes _ANSI_ARGS_((Channel *chanPtr, 155 CONST char *src, int srcLen)); 156static int WriteChars _ANSI_ARGS_((Channel *chanPtr, 157 CONST char *src, int srcLen)); 158 159#define BUSY_STATE(st,fl) \ 160 ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ 161 (((st)->csPtrW) && ((fl) & TCL_WRITABLE))) 162 163#define MAX_CHANNEL_BUFFER_SIZE (1024*1024) 164 165/* 166 *--------------------------------------------------------------------------- 167 * 168 * TclInitIOSubsystem -- 169 * 170 * Initialize all resources used by this subsystem on a per-process 171 * basis. 172 * 173 * Results: 174 * None. 175 * 176 * Side effects: 177 * Depends on the memory subsystems. 178 * 179 *--------------------------------------------------------------------------- 180 */ 181 182void 183TclInitIOSubsystem() 184{ 185 /* 186 * By fetching thread local storage we take care of 187 * allocating it for each thread. 188 */ 189 (void) TCL_TSD_INIT(&dataKey); 190} 191 192/* 193 *------------------------------------------------------------------------- 194 * 195 * TclFinalizeIOSubsystem -- 196 * 197 * Releases all resources used by this subsystem on a per-thread 198 * basis. Closes all extant channels that have not already been 199 * closed because they were not owned by any interp. 200 * 201 * Results: 202 * None. 203 * 204 * Side effects: 205 * Depends on encoding and memory subsystems. 206 * 207 *------------------------------------------------------------------------- 208 */ 209 210 /* ARGSUSED */ 211void 212TclFinalizeIOSubsystem(void) 213{ 214 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 215 Channel *chanPtr = NULL; /* Iterates over open channels. */ 216 ChannelState *statePtr; /* State of channel stack */ 217 int active = 1; /* Flag == 1 while there's still work to do */ 218 219 /* 220 * Walk all channel state structures known to this thread and 221 * close corresponding channels. 222 */ 223 224 while (active) { 225 226 /* 227 * Iterate through the open channel list, and find the first 228 * channel that isn't dead. We start from the head of the list 229 * each time, because the close action on one channel can close 230 * others. 231 */ 232 233 active = 0; 234 for (statePtr = tsdPtr->firstCSPtr; 235 statePtr != NULL; 236 statePtr = statePtr->nextCSPtr) { 237 chanPtr = statePtr->topChanPtr; 238 if (!(statePtr->flags & (CHANNEL_INCLOSE|CHANNEL_CLOSED|CHANNEL_DEAD))) { 239 active = 1; 240 break; 241 } 242 } 243 244 /* 245 * We've found a live channel. Close it. 246 */ 247 248 if (active) { 249 250 /* 251 * Set the channel back into blocking mode to ensure that we 252 * wait for all data to flush out. 253 */ 254 255 (void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr, 256 "-blocking", "on"); 257 258 if ((chanPtr == (Channel *) tsdPtr->stdinChannel) || 259 (chanPtr == (Channel *) tsdPtr->stdoutChannel) || 260 (chanPtr == (Channel *) tsdPtr->stderrChannel)) { 261 /* 262 * Decrement the refcount which was earlier artificially 263 * bumped up to keep the channel from being closed. 264 */ 265 266 statePtr->refCount--; 267 } 268 269 if (statePtr->refCount <= 0) { 270 /* 271 * Close it only if the refcount indicates that the channel 272 * is not referenced from any interpreter. If it is, that 273 * interpreter will close the channel when it gets destroyed. 274 */ 275 276 (void) Tcl_Close(NULL, (Tcl_Channel) chanPtr); 277 } else { 278 /* 279 * The refcount is greater than zero, so flush the channel. 280 */ 281 282 Tcl_Flush((Tcl_Channel) chanPtr); 283 284 /* 285 * Call the device driver to actually close the underlying 286 * device for this channel. 287 */ 288 289 if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { 290 (chanPtr->typePtr->closeProc)(chanPtr->instanceData, NULL); 291 } else { 292 (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, 293 NULL, 0); 294 } 295 296 /* 297 * Finally, we clean up the fields in the channel data 298 * structure since all of them have been deleted already. 299 * We mark the channel with CHANNEL_DEAD to prevent any 300 * further IO operations 301 * on it. 302 */ 303 304 chanPtr->instanceData = NULL; 305 statePtr->flags |= CHANNEL_DEAD; 306 } 307 } 308 } 309 310 TclpFinalizeSockets(); 311 TclpFinalizePipes(); 312} 313 314 315/* 316 *---------------------------------------------------------------------- 317 * 318 * Tcl_SetStdChannel -- 319 * 320 * This function is used to change the channels that are used 321 * for stdin/stdout/stderr in new interpreters. 322 * 323 * Results: 324 * None 325 * 326 * Side effects: 327 * None. 328 * 329 *---------------------------------------------------------------------- 330 */ 331 332void 333Tcl_SetStdChannel(channel, type) 334 Tcl_Channel channel; 335 int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ 336{ 337 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 338 switch (type) { 339 case TCL_STDIN: 340 tsdPtr->stdinInitialized = 1; 341 tsdPtr->stdinChannel = channel; 342 break; 343 case TCL_STDOUT: 344 tsdPtr->stdoutInitialized = 1; 345 tsdPtr->stdoutChannel = channel; 346 break; 347 case TCL_STDERR: 348 tsdPtr->stderrInitialized = 1; 349 tsdPtr->stderrChannel = channel; 350 break; 351 } 352} 353 354/* 355 *---------------------------------------------------------------------- 356 * 357 * Tcl_GetStdChannel -- 358 * 359 * Returns the specified standard channel. 360 * 361 * Results: 362 * Returns the specified standard channel, or NULL. 363 * 364 * Side effects: 365 * May cause the creation of a standard channel and the underlying 366 * file. 367 * 368 *---------------------------------------------------------------------- 369 */ 370Tcl_Channel 371Tcl_GetStdChannel(type) 372 int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ 373{ 374 Tcl_Channel channel = NULL; 375 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 376 377 /* 378 * If the channels were not created yet, create them now and 379 * store them in the static variables. 380 */ 381 382 switch (type) { 383 case TCL_STDIN: 384 if (!tsdPtr->stdinInitialized) { 385 tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN); 386 tsdPtr->stdinInitialized = 1; 387 388 /* 389 * Artificially bump the refcount to ensure that the channel 390 * is only closed on exit. 391 * 392 * NOTE: Must only do this if stdinChannel is not NULL. It 393 * can be NULL in situations where Tcl is unable to connect 394 * to the standard input. 395 */ 396 397 if (tsdPtr->stdinChannel != (Tcl_Channel) NULL) { 398 (void) Tcl_RegisterChannel((Tcl_Interp *) NULL, 399 tsdPtr->stdinChannel); 400 } 401 } 402 channel = tsdPtr->stdinChannel; 403 break; 404 case TCL_STDOUT: 405 if (!tsdPtr->stdoutInitialized) { 406 tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT); 407 tsdPtr->stdoutInitialized = 1; 408 if (tsdPtr->stdoutChannel != (Tcl_Channel) NULL) { 409 (void) Tcl_RegisterChannel((Tcl_Interp *) NULL, 410 tsdPtr->stdoutChannel); 411 } 412 } 413 channel = tsdPtr->stdoutChannel; 414 break; 415 case TCL_STDERR: 416 if (!tsdPtr->stderrInitialized) { 417 tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR); 418 tsdPtr->stderrInitialized = 1; 419 if (tsdPtr->stderrChannel != (Tcl_Channel) NULL) { 420 (void) Tcl_RegisterChannel((Tcl_Interp *) NULL, 421 tsdPtr->stderrChannel); 422 } 423 } 424 channel = tsdPtr->stderrChannel; 425 break; 426 } 427 return channel; 428} 429 430 431/* 432 *---------------------------------------------------------------------- 433 * 434 * Tcl_CreateCloseHandler 435 * 436 * Creates a close callback which will be called when the channel is 437 * closed. 438 * 439 * Results: 440 * None. 441 * 442 * Side effects: 443 * Causes the callback to be called in the future when the channel 444 * will be closed. 445 * 446 *---------------------------------------------------------------------- 447 */ 448 449void 450Tcl_CreateCloseHandler(chan, proc, clientData) 451 Tcl_Channel chan; /* The channel for which to create the 452 * close callback. */ 453 Tcl_CloseProc *proc; /* The callback routine to call when the 454 * channel will be closed. */ 455 ClientData clientData; /* Arbitrary data to pass to the 456 * close callback. */ 457{ 458 ChannelState *statePtr; 459 CloseCallback *cbPtr; 460 461 statePtr = ((Channel *) chan)->state; 462 463 cbPtr = (CloseCallback *) ckalloc((unsigned) sizeof(CloseCallback)); 464 cbPtr->proc = proc; 465 cbPtr->clientData = clientData; 466 467 cbPtr->nextPtr = statePtr->closeCbPtr; 468 statePtr->closeCbPtr = cbPtr; 469} 470 471/* 472 *---------------------------------------------------------------------- 473 * 474 * Tcl_DeleteCloseHandler -- 475 * 476 * Removes a callback that would have been called on closing 477 * the channel. If there is no matching callback then this 478 * function has no effect. 479 * 480 * Results: 481 * None. 482 * 483 * Side effects: 484 * The callback will not be called in the future when the channel 485 * is eventually closed. 486 * 487 *---------------------------------------------------------------------- 488 */ 489 490void 491Tcl_DeleteCloseHandler(chan, proc, clientData) 492 Tcl_Channel chan; /* The channel for which to cancel the 493 * close callback. */ 494 Tcl_CloseProc *proc; /* The procedure for the callback to 495 * remove. */ 496 ClientData clientData; /* The callback data for the callback 497 * to remove. */ 498{ 499 ChannelState *statePtr; 500 CloseCallback *cbPtr, *cbPrevPtr; 501 502 statePtr = ((Channel *) chan)->state; 503 for (cbPtr = statePtr->closeCbPtr, cbPrevPtr = (CloseCallback *) NULL; 504 cbPtr != (CloseCallback *) NULL; 505 cbPtr = cbPtr->nextPtr) { 506 if ((cbPtr->proc == proc) && (cbPtr->clientData == clientData)) { 507 if (cbPrevPtr == (CloseCallback *) NULL) { 508 statePtr->closeCbPtr = cbPtr->nextPtr; 509 } 510 ckfree((char *) cbPtr); 511 break; 512 } else { 513 cbPrevPtr = cbPtr; 514 } 515 } 516} 517 518/* 519 *---------------------------------------------------------------------- 520 * 521 * GetChannelTable -- 522 * 523 * Gets and potentially initializes the channel table for an 524 * interpreter. If it is initializing the table it also inserts 525 * channels for stdin, stdout and stderr if the interpreter is 526 * trusted. 527 * 528 * Results: 529 * A pointer to the hash table created, for use by the caller. 530 * 531 * Side effects: 532 * Initializes the channel table for an interpreter. May create 533 * channels for stdin, stdout and stderr. 534 * 535 *---------------------------------------------------------------------- 536 */ 537 538static Tcl_HashTable * 539GetChannelTable(interp) 540 Tcl_Interp *interp; 541{ 542 Tcl_HashTable *hTblPtr; /* Hash table of channels. */ 543 Tcl_Channel stdinChan, stdoutChan, stderrChan; 544 545 hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); 546 if (hTblPtr == (Tcl_HashTable *) NULL) { 547 hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable)); 548 Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS); 549 550 (void) Tcl_SetAssocData(interp, "tclIO", 551 (Tcl_InterpDeleteProc *) DeleteChannelTable, 552 (ClientData) hTblPtr); 553 554 /* 555 * If the interpreter is trusted (not "safe"), insert channels 556 * for stdin, stdout and stderr (possibly creating them in the 557 * process). 558 */ 559 560 if (Tcl_IsSafe(interp) == 0) { 561 stdinChan = Tcl_GetStdChannel(TCL_STDIN); 562 if (stdinChan != NULL) { 563 Tcl_RegisterChannel(interp, stdinChan); 564 } 565 stdoutChan = Tcl_GetStdChannel(TCL_STDOUT); 566 if (stdoutChan != NULL) { 567 Tcl_RegisterChannel(interp, stdoutChan); 568 } 569 stderrChan = Tcl_GetStdChannel(TCL_STDERR); 570 if (stderrChan != NULL) { 571 Tcl_RegisterChannel(interp, stderrChan); 572 } 573 } 574 575 } 576 return hTblPtr; 577} 578 579/* 580 *---------------------------------------------------------------------- 581 * 582 * DeleteChannelTable -- 583 * 584 * Deletes the channel table for an interpreter, closing any open 585 * channels whose refcount reaches zero. This procedure is invoked 586 * when an interpreter is deleted, via the AssocData cleanup 587 * mechanism. 588 * 589 * Results: 590 * None. 591 * 592 * Side effects: 593 * Deletes the hash table of channels. May close channels. May flush 594 * output on closed channels. Removes any channeEvent handlers that were 595 * registered in this interpreter. 596 * 597 *---------------------------------------------------------------------- 598 */ 599 600static void 601DeleteChannelTable(clientData, interp) 602 ClientData clientData; /* The per-interpreter data structure. */ 603 Tcl_Interp *interp; /* The interpreter being deleted. */ 604{ 605 Tcl_HashTable *hTblPtr; /* The hash table. */ 606 Tcl_HashSearch hSearch; /* Search variable. */ 607 Tcl_HashEntry *hPtr; /* Search variable. */ 608 Channel *chanPtr; /* Channel being deleted. */ 609 ChannelState *statePtr; /* State of Channel being deleted. */ 610 EventScriptRecord *sPtr, *prevPtr, *nextPtr; 611 /* Variables to loop over all channel events 612 * registered, to delete the ones that refer 613 * to the interpreter being deleted. */ 614 615 /* 616 * Delete all the registered channels - this will close channels whose 617 * refcount reaches zero. 618 */ 619 620 hTblPtr = (Tcl_HashTable *) clientData; 621 for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); 622 hPtr != (Tcl_HashEntry *) NULL; 623 hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) { 624 625 chanPtr = (Channel *) Tcl_GetHashValue(hPtr); 626 statePtr = chanPtr->state; 627 628 /* 629 * Remove any fileevents registered in this interpreter. 630 */ 631 632 for (sPtr = statePtr->scriptRecordPtr, 633 prevPtr = (EventScriptRecord *) NULL; 634 sPtr != (EventScriptRecord *) NULL; 635 sPtr = nextPtr) { 636 nextPtr = sPtr->nextPtr; 637 if (sPtr->interp == interp) { 638 if (prevPtr == (EventScriptRecord *) NULL) { 639 statePtr->scriptRecordPtr = nextPtr; 640 } else { 641 prevPtr->nextPtr = nextPtr; 642 } 643 644 Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, 645 TclChannelEventScriptInvoker, (ClientData) sPtr); 646 647 Tcl_DecrRefCount(sPtr->scriptPtr); 648 ckfree((char *) sPtr); 649 } else { 650 prevPtr = sPtr; 651 } 652 } 653 654 /* 655 * Cannot call Tcl_UnregisterChannel because that procedure calls 656 * Tcl_GetAssocData to get the channel table, which might already 657 * be inaccessible from the interpreter structure. Instead, we 658 * emulate the behavior of Tcl_UnregisterChannel directly here. 659 */ 660 661 Tcl_DeleteHashEntry(hPtr); 662 statePtr->refCount--; 663 if (statePtr->refCount <= 0) { 664 if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) { 665 (void) Tcl_Close(interp, (Tcl_Channel) chanPtr); 666 } 667 } 668 } 669 Tcl_DeleteHashTable(hTblPtr); 670 ckfree((char *) hTblPtr); 671} 672 673/* 674 *---------------------------------------------------------------------- 675 * 676 * CheckForStdChannelsBeingClosed -- 677 * 678 * Perform special handling for standard channels being closed. When 679 * given a standard channel, if the refcount is now 1, it means that 680 * the last reference to the standard channel is being explicitly 681 * closed. Now bump the refcount artificially down to 0, to ensure the 682 * normal handling of channels being closed will occur. Also reset the 683 * static pointer to the channel to NULL, to avoid dangling references. 684 * 685 * Results: 686 * None. 687 * 688 * Side effects: 689 * Manipulates the refcount on standard channels. May smash the global 690 * static pointer to a standard channel. 691 * 692 *---------------------------------------------------------------------- 693 */ 694 695static void 696CheckForStdChannelsBeingClosed(chan) 697 Tcl_Channel chan; 698{ 699 ChannelState *statePtr = ((Channel *) chan)->state; 700 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 701 702 if ((chan == tsdPtr->stdinChannel) && (tsdPtr->stdinInitialized)) { 703 if (statePtr->refCount < 2) { 704 statePtr->refCount = 0; 705 tsdPtr->stdinChannel = NULL; 706 return; 707 } 708 } else if ((chan == tsdPtr->stdoutChannel) 709 && (tsdPtr->stdoutInitialized)) { 710 if (statePtr->refCount < 2) { 711 statePtr->refCount = 0; 712 tsdPtr->stdoutChannel = NULL; 713 return; 714 } 715 } else if ((chan == tsdPtr->stderrChannel) 716 && (tsdPtr->stderrInitialized)) { 717 if (statePtr->refCount < 2) { 718 statePtr->refCount = 0; 719 tsdPtr->stderrChannel = NULL; 720 return; 721 } 722 } 723} 724 725/* 726 *---------------------------------------------------------------------- 727 * 728 * Tcl_IsStandardChannel -- 729 * 730 * Test if the given channel is a standard channel. No attempt 731 * is made to check if the channel or the standard channels 732 * are initialized or otherwise valid. 733 * 734 * Results: 735 * Returns 1 if true, 0 if false. 736 * 737 * Side effects: 738 * None. 739 * 740 *---------------------------------------------------------------------- 741 */ 742int 743Tcl_IsStandardChannel(chan) 744 Tcl_Channel chan; /* Channel to check. */ 745{ 746 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 747 748 if ((chan == tsdPtr->stdinChannel) 749 || (chan == tsdPtr->stdoutChannel) 750 || (chan == tsdPtr->stderrChannel)) { 751 return 1; 752 } else { 753 return 0; 754 } 755} 756 757/* 758 *---------------------------------------------------------------------- 759 * 760 * Tcl_RegisterChannel -- 761 * 762 * Adds an already-open channel to the channel table of an interpreter. 763 * If the interpreter passed as argument is NULL, it only increments 764 * the channel refCount. 765 * 766 * Results: 767 * None. 768 * 769 * Side effects: 770 * May increment the reference count of a channel. 771 * 772 *---------------------------------------------------------------------- 773 */ 774 775void 776Tcl_RegisterChannel(interp, chan) 777 Tcl_Interp *interp; /* Interpreter in which to add the channel. */ 778 Tcl_Channel chan; /* The channel to add to this interpreter 779 * channel table. */ 780{ 781 Tcl_HashTable *hTblPtr; /* Hash table of channels. */ 782 Tcl_HashEntry *hPtr; /* Search variable. */ 783 int new; /* Is the hash entry new or does it exist? */ 784 Channel *chanPtr; /* The actual channel. */ 785 ChannelState *statePtr; /* State of the actual channel. */ 786 787 /* 788 * Always (un)register bottom-most channel in the stack. This makes 789 * management of the channel list easier because no manipulation is 790 * necessary during (un)stack operation. 791 */ 792 chanPtr = ((Channel *) chan)->state->bottomChanPtr; 793 statePtr = chanPtr->state; 794 795 if (statePtr->channelName == (CONST char *) NULL) { 796 panic("Tcl_RegisterChannel: channel without name"); 797 } 798 if (interp != (Tcl_Interp *) NULL) { 799 hTblPtr = GetChannelTable(interp); 800 hPtr = Tcl_CreateHashEntry(hTblPtr, statePtr->channelName, &new); 801 if (new == 0) { 802 if (chan == (Tcl_Channel) Tcl_GetHashValue(hPtr)) { 803 return; 804 } 805 806 panic("Tcl_RegisterChannel: duplicate channel names"); 807 } 808 Tcl_SetHashValue(hPtr, (ClientData) chanPtr); 809 } 810 811 statePtr->refCount++; 812} 813 814/* 815 *---------------------------------------------------------------------- 816 * 817 * Tcl_UnregisterChannel -- 818 * 819 * Deletes the hash entry for a channel associated with an interpreter. 820 * If the interpreter given as argument is NULL, it only decrements the 821 * reference count. (This all happens in the Tcl_DetachChannel helper 822 * function). 823 * 824 * Finally, if the reference count of the channel drops to zero, 825 * it is deleted. 826 * 827 * Results: 828 * A standard Tcl result. 829 * 830 * Side effects: 831 * Calls Tcl_DetachChannel which deletes the hash entry for a channel 832 * associated with an interpreter. 833 * 834 * May delete the channel, which can have a variety of consequences, 835 * especially if we are forced to close the channel. 836 * 837 *---------------------------------------------------------------------- 838 */ 839 840int 841Tcl_UnregisterChannel(interp, chan) 842 Tcl_Interp *interp; /* Interpreter in which channel is defined. */ 843 Tcl_Channel chan; /* Channel to delete. */ 844{ 845 ChannelState *statePtr; /* State of the real channel. */ 846 847 statePtr = ((Channel *) chan)->state->bottomChanPtr->state; 848 849 if (statePtr->flags & CHANNEL_INCLOSE) { 850 if (interp != (Tcl_Interp*) NULL) { 851 Tcl_AppendResult(interp, 852 "Illegal recursive call to close through close-handler of channel", 853 (char *) NULL); 854 } 855 return TCL_ERROR; 856 } 857 858 if (DetachChannel(interp, chan) != TCL_OK) { 859 return TCL_OK; 860 } 861 862 statePtr = ((Channel *) chan)->state->bottomChanPtr->state; 863 864 /* 865 * Perform special handling for standard channels being closed. If the 866 * refCount is now 1 it means that the last reference to the standard 867 * channel is being explicitly closed, so bump the refCount down 868 * artificially to 0. This will ensure that the channel is actually 869 * closed, below. Also set the static pointer to NULL for the channel. 870 */ 871 872 CheckForStdChannelsBeingClosed(chan); 873 874 /* 875 * If the refCount reached zero, close the actual channel. 876 */ 877 878 if (statePtr->refCount <= 0) { 879 880 /* 881 * Ensure that if there is another buffer, it gets flushed 882 * whether or not we are doing a background flush. 883 */ 884 885 if ((statePtr->curOutPtr != NULL) && 886 (statePtr->curOutPtr->nextAdded > 887 statePtr->curOutPtr->nextRemoved)) { 888 statePtr->flags |= BUFFER_READY; 889 } 890 Tcl_Preserve((ClientData)statePtr); 891 if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) { 892 /* We don't want to re-enter Tcl_Close */ 893 if (!(statePtr->flags & CHANNEL_CLOSED)) { 894 if (Tcl_Close(interp, chan) != TCL_OK) { 895 statePtr->flags |= CHANNEL_CLOSED; 896 Tcl_Release((ClientData)statePtr); 897 return TCL_ERROR; 898 } 899 } 900 } 901 statePtr->flags |= CHANNEL_CLOSED; 902 Tcl_Release((ClientData)statePtr); 903 } 904 return TCL_OK; 905} 906 907/* 908 *---------------------------------------------------------------------- 909 * 910 * Tcl_DetachChannel -- 911 * 912 * Deletes the hash entry for a channel associated with an interpreter. 913 * If the interpreter given as argument is NULL, it only decrements the 914 * reference count. Even if the ref count drops to zero, the 915 * channel is NOT closed or cleaned up. This allows a channel to 916 * be detached from an interpreter and left in the same state it 917 * was in when it was originally returned by 'Tcl_OpenFileChannel', 918 * for example. 919 * 920 * This function cannot be used on the standard channels, and 921 * will return TCL_ERROR if that is attempted. 922 * 923 * This function should only be necessary for special purposes 924 * in which you need to generate a pristine channel from one 925 * that has already been used. All ordinary purposes will almost 926 * always want to use Tcl_UnregisterChannel instead. 927 * 928 * Provided the channel is not attached to any other interpreter, 929 * it can then be closed with Tcl_Close, rather than with 930 * Tcl_UnregisterChannel. 931 * 932 * Results: 933 * A standard Tcl result. If the channel is not currently registered 934 * with the given interpreter, TCL_ERROR is returned, otherwise 935 * TCL_OK. However no error messages are left in the interp's result. 936 * 937 * Side effects: 938 * Deletes the hash entry for a channel associated with an 939 * interpreter. 940 * 941 *---------------------------------------------------------------------- 942 */ 943 944int 945Tcl_DetachChannel(interp, chan) 946 Tcl_Interp *interp; /* Interpreter in which channel is defined. */ 947 Tcl_Channel chan; /* Channel to delete. */ 948{ 949 if (Tcl_IsStandardChannel(chan)) { 950 return TCL_ERROR; 951 } 952 953 return DetachChannel(interp, chan); 954} 955 956/* 957 *---------------------------------------------------------------------- 958 * 959 * DetachChannel -- 960 * 961 * Deletes the hash entry for a channel associated with an interpreter. 962 * If the interpreter given as argument is NULL, it only decrements the 963 * reference count. Even if the ref count drops to zero, the 964 * channel is NOT closed or cleaned up. This allows a channel to 965 * be detached from an interpreter and left in the same state it 966 * was in when it was originally returned by 'Tcl_OpenFileChannel', 967 * for example. 968 * 969 * Results: 970 * A standard Tcl result. If the channel is not currently registered 971 * with the given interpreter, TCL_ERROR is returned, otherwise 972 * TCL_OK. However no error messages are left in the interp's result. 973 * 974 * Side effects: 975 * Deletes the hash entry for a channel associated with an 976 * interpreter. 977 * 978 *---------------------------------------------------------------------- 979 */ 980 981static int 982DetachChannel(interp, chan) 983 Tcl_Interp *interp; /* Interpreter in which channel is defined. */ 984 Tcl_Channel chan; /* Channel to delete. */ 985{ 986 Tcl_HashTable *hTblPtr; /* Hash table of channels. */ 987 Tcl_HashEntry *hPtr; /* Search variable. */ 988 Channel *chanPtr; /* The real IO channel. */ 989 ChannelState *statePtr; /* State of the real channel. */ 990 991 /* 992 * Always (un)register bottom-most channel in the stack. This makes 993 * management of the channel list easier because no manipulation is 994 * necessary during (un)stack operation. 995 */ 996 chanPtr = ((Channel *) chan)->state->bottomChanPtr; 997 statePtr = chanPtr->state; 998 999 if (interp != (Tcl_Interp *) NULL) { 1000 hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); 1001 if (hTblPtr == (Tcl_HashTable *) NULL) { 1002 return TCL_ERROR; 1003 } 1004 hPtr = Tcl_FindHashEntry(hTblPtr, statePtr->channelName); 1005 if (hPtr == (Tcl_HashEntry *) NULL) { 1006 return TCL_ERROR; 1007 } 1008 if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) { 1009 return TCL_ERROR; 1010 } 1011 Tcl_DeleteHashEntry(hPtr); 1012 1013 /* 1014 * Remove channel handlers that refer to this interpreter, so that they 1015 * will not be present if the actual close is delayed and more events 1016 * happen on the channel. This may occur if the channel is shared 1017 * between several interpreters, or if the channel has async 1018 * flushing active. 1019 */ 1020 1021 CleanupChannelHandlers(interp, chanPtr); 1022 } 1023 1024 statePtr->refCount--; 1025 1026 return TCL_OK; 1027} 1028 1029 1030/* 1031 *--------------------------------------------------------------------------- 1032 * 1033 * Tcl_GetChannel -- 1034 * 1035 * Finds an existing Tcl_Channel structure by name in a given 1036 * interpreter. This function is public because it is used by 1037 * channel-type-specific functions. 1038 * 1039 * Results: 1040 * A Tcl_Channel or NULL on failure. If failed, interp's result 1041 * object contains an error message. *modePtr is filled with the 1042 * modes in which the channel was opened. 1043 * 1044 * Side effects: 1045 * None. 1046 * 1047 *--------------------------------------------------------------------------- 1048 */ 1049 1050Tcl_Channel 1051Tcl_GetChannel(interp, chanName, modePtr) 1052 Tcl_Interp *interp; /* Interpreter in which to find or create 1053 * the channel. */ 1054 CONST char *chanName; /* The name of the channel. */ 1055 int *modePtr; /* Where to store the mode in which the 1056 * channel was opened? Will contain an ORed 1057 * combination of TCL_READABLE and 1058 * TCL_WRITABLE, if non-NULL. */ 1059{ 1060 Channel *chanPtr; /* The actual channel. */ 1061 Tcl_HashTable *hTblPtr; /* Hash table of channels. */ 1062 Tcl_HashEntry *hPtr; /* Search variable. */ 1063 CONST char *name; /* Translated name. */ 1064 1065 /* 1066 * Substitute "stdin", etc. Note that even though we immediately 1067 * find the channel using Tcl_GetStdChannel, we still need to look 1068 * it up in the specified interpreter to ensure that it is present 1069 * in the channel table. Otherwise, safe interpreters would always 1070 * have access to the standard channels. 1071 */ 1072 1073 name = chanName; 1074 if ((chanName[0] == 's') && (chanName[1] == 't')) { 1075 chanPtr = NULL; 1076 if (strcmp(chanName, "stdin") == 0) { 1077 chanPtr = (Channel *) Tcl_GetStdChannel(TCL_STDIN); 1078 } else if (strcmp(chanName, "stdout") == 0) { 1079 chanPtr = (Channel *) Tcl_GetStdChannel(TCL_STDOUT); 1080 } else if (strcmp(chanName, "stderr") == 0) { 1081 chanPtr = (Channel *) Tcl_GetStdChannel(TCL_STDERR); 1082 } 1083 if (chanPtr != NULL) { 1084 name = chanPtr->state->channelName; 1085 } 1086 } 1087 1088 hTblPtr = GetChannelTable(interp); 1089 hPtr = Tcl_FindHashEntry(hTblPtr, name); 1090 if (hPtr == (Tcl_HashEntry *) NULL) { 1091 Tcl_AppendResult(interp, "can not find channel named \"", 1092 chanName, "\"", (char *) NULL); 1093 return NULL; 1094 } 1095 1096 /* 1097 * Always return bottom-most channel in the stack. This one lives 1098 * the longest - other channels may go away unnoticed. 1099 * The other APIs compensate where necessary to retrieve the 1100 * topmost channel again. 1101 */ 1102 chanPtr = (Channel *) Tcl_GetHashValue(hPtr); 1103 chanPtr = chanPtr->state->bottomChanPtr; 1104 if (modePtr != NULL) { 1105 *modePtr = (chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE)); 1106 } 1107 1108 return (Tcl_Channel) chanPtr; 1109} 1110 1111/* 1112 *---------------------------------------------------------------------- 1113 * 1114 * Tcl_CreateChannel -- 1115 * 1116 * Creates a new entry in the hash table for a Tcl_Channel 1117 * record. 1118 * 1119 * Results: 1120 * Returns the new Tcl_Channel. 1121 * 1122 * Side effects: 1123 * Creates a new Tcl_Channel instance and inserts it into the 1124 * hash table. 1125 * 1126 *---------------------------------------------------------------------- 1127 */ 1128 1129Tcl_Channel 1130Tcl_CreateChannel(typePtr, chanName, instanceData, mask) 1131 Tcl_ChannelType *typePtr; /* The channel type record. */ 1132 CONST char *chanName; /* Name of channel to record. */ 1133 ClientData instanceData; /* Instance specific data. */ 1134 int mask; /* TCL_READABLE & TCL_WRITABLE to indicate 1135 * if the channel is readable, writable. */ 1136{ 1137 Channel *chanPtr; /* The channel structure newly created. */ 1138 ChannelState *statePtr; /* The stack-level independent state info 1139 * for the channel. */ 1140 CONST char *name; 1141 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 1142 1143 /* 1144 * With the change of the Tcl_ChannelType structure to use a version in 1145 * 8.3.2+, we have to make sure that our assumption that the structure 1146 * remains a binary compatible size is true. 1147 * 1148 * If this assertion fails on some system, then it can be removed 1149 * only if the user recompiles code with older channel drivers in 1150 * the new system as well. 1151 */ 1152 1153 assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc*)); 1154 1155 /* 1156 * JH: We could subsequently memset these to 0 to avoid the 1157 * numerous assignments to 0/NULL below. 1158 */ 1159 chanPtr = (Channel *) ckalloc((unsigned) sizeof(Channel)); 1160 statePtr = (ChannelState *) ckalloc((unsigned) sizeof(ChannelState)); 1161 chanPtr->state = statePtr; 1162 1163 chanPtr->instanceData = instanceData; 1164 chanPtr->typePtr = typePtr; 1165 1166 /* 1167 * Set all the bits that are part of the stack-independent state 1168 * information for the channel. 1169 */ 1170 1171 if (chanName != (char *) NULL) { 1172 char *tmp = ckalloc((unsigned) (strlen(chanName) + 1)); 1173 statePtr->channelName = tmp; 1174 strcpy(tmp, chanName); 1175 } else { 1176 panic("Tcl_CreateChannel: NULL channel name"); 1177 } 1178 1179 statePtr->flags = mask; 1180 1181 /* 1182 * Set the channel to system default encoding. 1183 */ 1184 1185 statePtr->encoding = NULL; 1186 name = Tcl_GetEncodingName(NULL); 1187 if (strcmp(name, "binary") != 0) { 1188 statePtr->encoding = Tcl_GetEncoding(NULL, name); 1189 } 1190 statePtr->inputEncodingState = NULL; 1191 statePtr->inputEncodingFlags = TCL_ENCODING_START; 1192 statePtr->outputEncodingState = NULL; 1193 statePtr->outputEncodingFlags = TCL_ENCODING_START; 1194 1195 /* 1196 * Set the channel up initially in AUTO input translation mode to 1197 * accept "\n", "\r" and "\r\n". Output translation mode is set to 1198 * a platform specific default value. The eofChar is set to 0 for both 1199 * input and output, so that Tcl does not look for an in-file EOF 1200 * indicator (e.g. ^Z) and does not append an EOF indicator to files. 1201 */ 1202 1203 statePtr->inputTranslation = TCL_TRANSLATE_AUTO; 1204 statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; 1205 statePtr->inEofChar = 0; 1206 statePtr->outEofChar = 0; 1207 1208 statePtr->unreportedError = 0; 1209 statePtr->refCount = 0; 1210 statePtr->closeCbPtr = (CloseCallback *) NULL; 1211 statePtr->curOutPtr = (ChannelBuffer *) NULL; 1212 statePtr->outQueueHead = (ChannelBuffer *) NULL; 1213 statePtr->outQueueTail = (ChannelBuffer *) NULL; 1214 statePtr->saveInBufPtr = (ChannelBuffer *) NULL; 1215 statePtr->inQueueHead = (ChannelBuffer *) NULL; 1216 statePtr->inQueueTail = (ChannelBuffer *) NULL; 1217 statePtr->chPtr = (ChannelHandler *) NULL; 1218 statePtr->interestMask = 0; 1219 statePtr->scriptRecordPtr = (EventScriptRecord *) NULL; 1220 statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; 1221 statePtr->timer = NULL; 1222 statePtr->csPtrR = NULL; 1223 statePtr->csPtrW = NULL; 1224 1225 statePtr->outputStage = NULL; 1226 if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { 1227 statePtr->outputStage = (char *) 1228 ckalloc((unsigned) (statePtr->bufSize + 2)); 1229 } 1230 1231 /* 1232 * As we are creating the channel, it is obviously the top for now 1233 */ 1234 statePtr->topChanPtr = chanPtr; 1235 statePtr->bottomChanPtr = chanPtr; 1236 chanPtr->downChanPtr = (Channel *) NULL; 1237 chanPtr->upChanPtr = (Channel *) NULL; 1238 chanPtr->inQueueHead = (ChannelBuffer*) NULL; 1239 chanPtr->inQueueTail = (ChannelBuffer*) NULL; 1240 1241 /* 1242 * Link the channel into the list of all channels; create an on-exit 1243 * handler if there is not one already, to close off all the channels 1244 * in the list on exit. 1245 * 1246 * JH: Could call Tcl_SpliceChannel, but need to avoid NULL check. 1247 * 1248 * TIP #218. 1249 * AK: Just initialize the field to NULL before invoking Tcl_SpliceChannel 1250 * We need Tcl_SpliceChannel, for the threadAction calls. 1251 * There is no real reason to duplicate all of this. 1252 * NOTE: All drivers using thread actions now have to perform their TSD 1253 * manipulation only in their thread action proc. Doing it when 1254 * creating their instance structures will collide with the thread 1255 * action activity and lead to damaged lists. 1256 */ 1257 1258 statePtr->nextCSPtr = (ChannelState *) NULL; 1259 Tcl_SpliceChannel ((Tcl_Channel) chanPtr); 1260 1261 /* 1262 * Install this channel in the first empty standard channel slot, if 1263 * the channel was previously closed explicitly. 1264 */ 1265#if TCL_INHERIT_STD_CHANNELS 1266 if ((tsdPtr->stdinChannel == NULL) && 1267 (tsdPtr->stdinInitialized == 1)) { 1268 Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDIN); 1269 Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); 1270 } else if ((tsdPtr->stdoutChannel == NULL) && 1271 (tsdPtr->stdoutInitialized == 1)) { 1272 Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDOUT); 1273 Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); 1274 } else if ((tsdPtr->stderrChannel == NULL) && 1275 (tsdPtr->stderrInitialized == 1)) { 1276 Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDERR); 1277 Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); 1278 } 1279#endif 1280 return (Tcl_Channel) chanPtr; 1281} 1282 1283/* 1284 *---------------------------------------------------------------------- 1285 * 1286 * Tcl_StackChannel -- 1287 * 1288 * Replaces an entry in the hash table for a Tcl_Channel 1289 * record. The replacement is a new channel with same name, 1290 * it supercedes the replaced channel. Input and output of 1291 * the superceded channel is now going through the newly 1292 * created channel and allows the arbitrary filtering/manipulation 1293 * of the dataflow. 1294 * 1295 * Andreas Kupries <a.kupries@westend.com>, 12/13/1998 1296 * "Trf-Patch for filtering channels" 1297 * 1298 * Results: 1299 * Returns the new Tcl_Channel, which actually contains the 1300 * saved information about prevChan. 1301 * 1302 * Side effects: 1303 * A new channel structure is allocated and linked below 1304 * the existing channel. The channel operations and client 1305 * data of the existing channel are copied down to the newly 1306 * created channel, and the current channel has its operations 1307 * replaced by the new typePtr. 1308 * 1309 *---------------------------------------------------------------------- 1310 */ 1311 1312Tcl_Channel 1313Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan) 1314 Tcl_Interp *interp; /* The interpreter we are working in */ 1315 Tcl_ChannelType *typePtr; /* The channel type record for the new 1316 * channel. */ 1317 ClientData instanceData; /* Instance specific data for the new 1318 * channel. */ 1319 int mask; /* TCL_READABLE & TCL_WRITABLE to indicate 1320 * if the channel is readable, writable. */ 1321 Tcl_Channel prevChan; /* The channel structure to replace */ 1322{ 1323 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 1324 Channel *chanPtr, *prevChanPtr; 1325 ChannelState *statePtr; 1326 1327 /* 1328 * Find the given channel in the list of all channels. 1329 * If we don't find it, then it was never registered correctly. 1330 * 1331 * This operation should occur at the top of a channel stack. 1332 */ 1333 1334 statePtr = (ChannelState *) tsdPtr->firstCSPtr; 1335 prevChanPtr = ((Channel *) prevChan)->state->topChanPtr; 1336 1337 while ((statePtr != NULL) && (statePtr->topChanPtr != prevChanPtr)) { 1338 statePtr = statePtr->nextCSPtr; 1339 } 1340 1341 if (statePtr == NULL) { 1342 if (interp) { 1343 Tcl_AppendResult(interp, "couldn't find state for channel \"", 1344 Tcl_GetChannelName(prevChan), "\"", (char *) NULL); 1345 } 1346 return (Tcl_Channel) NULL; 1347 } 1348 1349 /* 1350 * Here we check if the given "mask" matches the "flags" 1351 * of the already existing channel. 1352 * 1353 * | - | R | W | RW | 1354 * --+---+---+---+----+ <=> 0 != (chan->mask & prevChan->mask) 1355 * - | | | | | 1356 * R | | + | | + | The superceding channel is allowed to 1357 * W | | | + | + | restrict the capabilities of the 1358 * RW| | + | + | + | superceded one ! 1359 * --+---+---+---+----+ 1360 */ 1361 1362 if ((mask & (statePtr->flags & (TCL_READABLE | TCL_WRITABLE))) == 0) { 1363 if (interp) { 1364 Tcl_AppendResult(interp, 1365 "reading and writing both disallowed for channel \"", 1366 Tcl_GetChannelName(prevChan), "\"", (char *) NULL); 1367 } 1368 return (Tcl_Channel) NULL; 1369 } 1370 1371 /* 1372 * Flush the buffers. This ensures that any data still in them 1373 * at this time is not handled by the new transformation. Restrict 1374 * this to writable channels. Take care to hide a possible bg-copy 1375 * in progress from Tcl_Flush and the CheckForChannelErrors inside. 1376 */ 1377 1378 if ((mask & TCL_WRITABLE) != 0) { 1379 CopyState *csPtrR; 1380 CopyState *csPtrW; 1381 1382 csPtrR = statePtr->csPtrR; 1383 statePtr->csPtrR = (CopyState*) NULL; 1384 1385 csPtrW = statePtr->csPtrW; 1386 statePtr->csPtrW = (CopyState*) NULL; 1387 1388 if (Tcl_Flush((Tcl_Channel) prevChanPtr) != TCL_OK) { 1389 statePtr->csPtrR = csPtrR; 1390 statePtr->csPtrW = csPtrW; 1391 if (interp) { 1392 Tcl_AppendResult(interp, "could not flush channel \"", 1393 Tcl_GetChannelName(prevChan), "\"", (char *) NULL); 1394 } 1395 return (Tcl_Channel) NULL; 1396 } 1397 1398 statePtr->csPtrR = csPtrR; 1399 statePtr->csPtrW = csPtrW; 1400 } 1401 /* 1402 * Discard any input in the buffers. They are not yet read by the 1403 * user of the channel, so they have to go through the new 1404 * transformation before reading. As the buffers contain the 1405 * untransformed form their contents are not only useless but actually 1406 * distorts our view of the system. 1407 * 1408 * To preserve the information without having to read them again and 1409 * to avoid problems with the location in the channel (seeking might 1410 * be impossible) we move the buffers from the common state structure 1411 * into the channel itself. We use the buffers in the channel below 1412 * the new transformation to hold the data. In the future this allows 1413 * us to write transformations which pre-read data and push the unused 1414 * part back when they are going away. 1415 */ 1416 1417 if (((mask & TCL_READABLE) != 0) && 1418 (statePtr->inQueueHead != (ChannelBuffer*) NULL)) { 1419 /* 1420 * Remark: It is possible that the channel buffers contain data from 1421 * some earlier push-backs. 1422 */ 1423 1424 statePtr->inQueueTail->nextPtr = prevChanPtr->inQueueHead; 1425 prevChanPtr->inQueueHead = statePtr->inQueueHead; 1426 1427 if (prevChanPtr->inQueueTail == (ChannelBuffer*) NULL) { 1428 prevChanPtr->inQueueTail = statePtr->inQueueTail; 1429 } 1430 1431 statePtr->inQueueHead = (ChannelBuffer*) NULL; 1432 statePtr->inQueueTail = (ChannelBuffer*) NULL; 1433 } 1434 1435 chanPtr = (Channel *) ckalloc((unsigned) sizeof(Channel)); 1436 1437 /* 1438 * Save some of the current state into the new structure, 1439 * reinitialize the parts which will stay with the transformation. 1440 * 1441 * Remarks: 1442 */ 1443 1444 chanPtr->state = statePtr; 1445 chanPtr->instanceData = instanceData; 1446 chanPtr->typePtr = typePtr; 1447 chanPtr->downChanPtr = prevChanPtr; 1448 chanPtr->upChanPtr = (Channel *) NULL; 1449 chanPtr->inQueueHead = (ChannelBuffer*) NULL; 1450 chanPtr->inQueueTail = (ChannelBuffer*) NULL; 1451 1452 /* 1453 * Place new block at the head of a possibly existing list of previously 1454 * stacked channels. 1455 */ 1456 1457 prevChanPtr->upChanPtr = chanPtr; 1458 statePtr->topChanPtr = chanPtr; 1459 1460 return (Tcl_Channel) chanPtr; 1461} 1462 1463/* 1464 *---------------------------------------------------------------------- 1465 * 1466 * Tcl_UnstackChannel -- 1467 * 1468 * Unstacks an entry in the hash table for a Tcl_Channel 1469 * record. This is the reverse to 'Tcl_StackChannel'. 1470 * 1471 * Results: 1472 * A standard Tcl result. 1473 * 1474 * Side effects: 1475 * If TCL_ERROR is returned, the posix error code will be set 1476 * with Tcl_SetErrno. 1477 * 1478 *---------------------------------------------------------------------- 1479 */ 1480 1481int 1482Tcl_UnstackChannel (interp, chan) 1483 Tcl_Interp *interp; /* The interpreter we are working in */ 1484 Tcl_Channel chan; /* The channel to unstack */ 1485{ 1486 Channel *chanPtr = (Channel *) chan; 1487 ChannelState *statePtr = chanPtr->state; 1488 int result = 0; 1489 1490 /* 1491 * This operation should occur at the top of a channel stack. 1492 */ 1493 1494 chanPtr = statePtr->topChanPtr; 1495 1496 if (chanPtr->downChanPtr != (Channel *) NULL) { 1497 /* 1498 * Instead of manipulating the per-thread / per-interp list/hashtable 1499 * of registered channels we wind down the state of the transformation, 1500 * and then restore the state of underlying channel into the old 1501 * structure. 1502 */ 1503 Channel *downChanPtr = chanPtr->downChanPtr; 1504 1505 /* 1506 * Flush the buffers. This ensures that any data still in them 1507 * at this time _is_ handled by the transformation we are unstacking 1508 * right now. Restrict this to writable channels. Take care to hide 1509 * a possible bg-copy in progress from Tcl_Flush and the 1510 * CheckForChannelErrors inside. 1511 */ 1512 1513 if (statePtr->flags & TCL_WRITABLE) { 1514 CopyState *csPtrR; 1515 CopyState *csPtrW; 1516 1517 csPtrR = statePtr->csPtrR; 1518 statePtr->csPtrR = (CopyState*) NULL; 1519 1520 csPtrW = statePtr->csPtrW; 1521 statePtr->csPtrW = (CopyState*) NULL; 1522 1523 if (Tcl_Flush((Tcl_Channel) chanPtr) != TCL_OK) { 1524 statePtr->csPtrR = csPtrR; 1525 statePtr->csPtrW = csPtrW; 1526 if (interp) { 1527 Tcl_AppendResult(interp, "could not flush channel \"", 1528 Tcl_GetChannelName((Tcl_Channel) chanPtr), "\"", 1529 (char *) NULL); 1530 } 1531 return TCL_ERROR; 1532 } 1533 1534 statePtr->csPtrR = csPtrR; 1535 statePtr->csPtrW = csPtrW; 1536 } 1537 1538 /* 1539 * Anything in the input queue and the push-back buffers of 1540 * the transformation going away is transformed data, but not 1541 * yet read. As unstacking means that the caller does not want 1542 * to see transformed data any more we have to discard these 1543 * bytes. To avoid writing an analogue to 'DiscardInputQueued' 1544 * we move the information in the push back buffers to the 1545 * input queue and then call 'DiscardInputQueued' on that. 1546 */ 1547 1548 if (((statePtr->flags & TCL_READABLE) != 0) && 1549 ((statePtr->inQueueHead != (ChannelBuffer*) NULL) || 1550 (chanPtr->inQueueHead != (ChannelBuffer*) NULL))) { 1551 1552 if ((statePtr->inQueueHead != (ChannelBuffer*) NULL) && 1553 (chanPtr->inQueueHead != (ChannelBuffer*) NULL)) { 1554 statePtr->inQueueTail->nextPtr = chanPtr->inQueueHead; 1555 statePtr->inQueueTail = chanPtr->inQueueTail; 1556 statePtr->inQueueHead = statePtr->inQueueTail; 1557 1558 } else if (chanPtr->inQueueHead != (ChannelBuffer*) NULL) { 1559 statePtr->inQueueHead = chanPtr->inQueueHead; 1560 statePtr->inQueueTail = chanPtr->inQueueTail; 1561 } 1562 1563 chanPtr->inQueueHead = (ChannelBuffer*) NULL; 1564 chanPtr->inQueueTail = (ChannelBuffer*) NULL; 1565 1566 DiscardInputQueued (statePtr, 0); 1567 } 1568 1569 statePtr->topChanPtr = downChanPtr; 1570 downChanPtr->upChanPtr = (Channel *) NULL; 1571 1572 /* 1573 * Leave this link intact for closeproc 1574 * chanPtr->downChanPtr = (Channel *) NULL; 1575 */ 1576 1577 /* 1578 * Close and free the channel driver state. 1579 */ 1580 1581 if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { 1582 result = (chanPtr->typePtr->closeProc)(chanPtr->instanceData, 1583 interp); 1584 } else { 1585 result = (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, 1586 interp, 0); 1587 } 1588 1589 chanPtr->typePtr = NULL; 1590 /* 1591 * AK: Tcl_NotifyChannel may hold a reference to this block of memory 1592 */ 1593 Tcl_EventuallyFree((ClientData) chanPtr, TCL_DYNAMIC); 1594 UpdateInterest(downChanPtr); 1595 1596 if (result != 0) { 1597 Tcl_SetErrno(result); 1598 return TCL_ERROR; 1599 } 1600 } else { 1601 /* 1602 * This channel does not cover another one. 1603 * Simply do a close, if necessary. 1604 */ 1605 1606 if (statePtr->refCount <= 0) { 1607 if (Tcl_Close(interp, chan) != TCL_OK) { 1608 return TCL_ERROR; 1609 } 1610 } 1611 } 1612 1613 return TCL_OK; 1614} 1615 1616/* 1617 *---------------------------------------------------------------------- 1618 * 1619 * Tcl_GetStackedChannel -- 1620 * 1621 * Determines whether the specified channel is stacked upon another. 1622 * 1623 * Results: 1624 * NULL if the channel is not stacked upon another one, or a reference 1625 * to the channel it is stacked upon. This reference can be used in 1626 * queries, but modification is not allowed. 1627 * 1628 * Side effects: 1629 * None. 1630 * 1631 *---------------------------------------------------------------------- 1632 */ 1633 1634Tcl_Channel 1635Tcl_GetStackedChannel(chan) 1636 Tcl_Channel chan; 1637{ 1638 Channel *chanPtr = (Channel *) chan; /* The actual channel. */ 1639 1640 return (Tcl_Channel) chanPtr->downChanPtr; 1641} 1642 1643/* 1644 *---------------------------------------------------------------------- 1645 * 1646 * Tcl_GetTopChannel -- 1647 * 1648 * Returns the top channel of a channel stack. 1649 * 1650 * Results: 1651 * NULL if the channel is not stacked upon another one, or a reference 1652 * to the channel it is stacked upon. This reference can be used in 1653 * queries, but modification is not allowed. 1654 * 1655 * Side effects: 1656 * None. 1657 * 1658 *---------------------------------------------------------------------- 1659 */ 1660 1661Tcl_Channel 1662Tcl_GetTopChannel(chan) 1663 Tcl_Channel chan; 1664{ 1665 Channel *chanPtr = (Channel *) chan; /* The actual channel. */ 1666 1667 return (Tcl_Channel) chanPtr->state->topChanPtr; 1668} 1669 1670/* 1671 *---------------------------------------------------------------------- 1672 * 1673 * Tcl_GetChannelInstanceData -- 1674 * 1675 * Returns the client data associated with a channel. 1676 * 1677 * Results: 1678 * The client data. 1679 * 1680 * Side effects: 1681 * None. 1682 * 1683 *---------------------------------------------------------------------- 1684 */ 1685 1686ClientData 1687Tcl_GetChannelInstanceData(chan) 1688 Tcl_Channel chan; /* Channel for which to return client data. */ 1689{ 1690 Channel *chanPtr = (Channel *) chan; /* The actual channel. */ 1691 1692 return chanPtr->instanceData; 1693} 1694 1695/* 1696 *---------------------------------------------------------------------- 1697 * 1698 * Tcl_GetChannelThread -- 1699 * 1700 * Given a channel structure, returns the thread managing it. 1701 * TIP #10 1702 * 1703 * Results: 1704 * Returns the id of the thread managing the channel. 1705 * 1706 * Side effects: 1707 * None. 1708 * 1709 *---------------------------------------------------------------------- 1710 */ 1711 1712Tcl_ThreadId 1713Tcl_GetChannelThread(chan) 1714 Tcl_Channel chan; /* The channel to return managing thread for. */ 1715{ 1716 Channel *chanPtr = (Channel *) chan; /* The actual channel. */ 1717 1718 return chanPtr->state->managingThread; 1719} 1720 1721/* 1722 *---------------------------------------------------------------------- 1723 * 1724 * Tcl_GetChannelType -- 1725 * 1726 * Given a channel structure, returns the channel type structure. 1727 * 1728 * Results: 1729 * Returns a pointer to the channel type structure. 1730 * 1731 * Side effects: 1732 * None. 1733 * 1734 *---------------------------------------------------------------------- 1735 */ 1736 1737Tcl_ChannelType * 1738Tcl_GetChannelType(chan) 1739 Tcl_Channel chan; /* The channel to return type for. */ 1740{ 1741 Channel *chanPtr = (Channel *) chan; /* The actual channel. */ 1742 1743 return chanPtr->typePtr; 1744} 1745 1746/* 1747 *---------------------------------------------------------------------- 1748 * 1749 * Tcl_GetChannelMode -- 1750 * 1751 * Computes a mask indicating whether the channel is open for 1752 * reading and writing. 1753 * 1754 * Results: 1755 * An OR-ed combination of TCL_READABLE and TCL_WRITABLE. 1756 * 1757 * Side effects: 1758 * None. 1759 * 1760 *---------------------------------------------------------------------- 1761 */ 1762 1763int 1764Tcl_GetChannelMode(chan) 1765 Tcl_Channel chan; /* The channel for which the mode is 1766 * being computed. */ 1767{ 1768 ChannelState *statePtr = ((Channel *) chan)->state; 1769 /* State of actual channel. */ 1770 1771 return (statePtr->flags & (TCL_READABLE | TCL_WRITABLE)); 1772} 1773 1774/* 1775 *---------------------------------------------------------------------- 1776 * 1777 * Tcl_GetChannelName -- 1778 * 1779 * Returns the string identifying the channel name. 1780 * 1781 * Results: 1782 * The string containing the channel name. This memory is 1783 * owned by the generic layer and should not be modified by 1784 * the caller. 1785 * 1786 * Side effects: 1787 * None. 1788 * 1789 *---------------------------------------------------------------------- 1790 */ 1791 1792CONST char * 1793Tcl_GetChannelName(chan) 1794 Tcl_Channel chan; /* The channel for which to return the name. */ 1795{ 1796 ChannelState *statePtr; /* State of actual channel. */ 1797 1798 statePtr = ((Channel *) chan)->state; 1799 return statePtr->channelName; 1800} 1801 1802/* 1803 *---------------------------------------------------------------------- 1804 * 1805 * Tcl_GetChannelHandle -- 1806 * 1807 * Returns an OS handle associated with a channel. 1808 * 1809 * Results: 1810 * Returns TCL_OK and places the handle in handlePtr, or returns 1811 * TCL_ERROR on failure. 1812 * 1813 * Side effects: 1814 * None. 1815 * 1816 *---------------------------------------------------------------------- 1817 */ 1818 1819int 1820Tcl_GetChannelHandle(chan, direction, handlePtr) 1821 Tcl_Channel chan; /* The channel to get file from. */ 1822 int direction; /* TCL_WRITABLE or TCL_READABLE. */ 1823 ClientData *handlePtr; /* Where to store handle */ 1824{ 1825 Channel *chanPtr; /* The actual channel. */ 1826 ClientData handle; 1827 int result; 1828 1829 chanPtr = ((Channel *) chan)->state->bottomChanPtr; 1830 result = (chanPtr->typePtr->getHandleProc)(chanPtr->instanceData, 1831 direction, &handle); 1832 if (handlePtr) { 1833 *handlePtr = handle; 1834 } 1835 return result; 1836} 1837 1838/* 1839 *--------------------------------------------------------------------------- 1840 * 1841 * AllocChannelBuffer -- 1842 * 1843 * A channel buffer has BUFFER_PADDING bytes extra at beginning to 1844 * hold any bytes of a native-encoding character that got split by 1845 * the end of the previous buffer and need to be moved to the 1846 * beginning of the next buffer to make a contiguous string so it 1847 * can be converted to UTF-8. 1848 * 1849 * A channel buffer has BUFFER_PADDING bytes extra at the end to 1850 * hold any bytes of a native-encoding character (generated from a 1851 * UTF-8 character) that overflow past the end of the buffer and 1852 * need to be moved to the next buffer. 1853 * 1854 * Results: 1855 * A newly allocated channel buffer. 1856 * 1857 * Side effects: 1858 * None. 1859 * 1860 *--------------------------------------------------------------------------- 1861 */ 1862 1863static ChannelBuffer * 1864AllocChannelBuffer(length) 1865 int length; /* Desired length of channel buffer. */ 1866{ 1867 ChannelBuffer *bufPtr; 1868 int n; 1869 1870 n = length + CHANNELBUFFER_HEADER_SIZE + BUFFER_PADDING + BUFFER_PADDING; 1871 bufPtr = (ChannelBuffer *) ckalloc((unsigned) n); 1872 bufPtr->nextAdded = BUFFER_PADDING; 1873 bufPtr->nextRemoved = BUFFER_PADDING; 1874 bufPtr->bufLength = length + BUFFER_PADDING; 1875 bufPtr->nextPtr = (ChannelBuffer *) NULL; 1876 return bufPtr; 1877} 1878 1879/* 1880 *---------------------------------------------------------------------- 1881 * 1882 * RecycleBuffer -- 1883 * 1884 * Helper function to recycle input and output buffers. Ensures 1885 * that two input buffers are saved (one in the input queue and 1886 * another in the saveInBufPtr field) and that curOutPtr is set 1887 * to a buffer. Only if these conditions are met is the buffer 1888 * freed to the OS. 1889 * 1890 * Results: 1891 * None. 1892 * 1893 * Side effects: 1894 * May free a buffer to the OS. 1895 * 1896 *---------------------------------------------------------------------- 1897 */ 1898 1899static void 1900RecycleBuffer(statePtr, bufPtr, mustDiscard) 1901 ChannelState *statePtr; /* ChannelState in which to recycle buffers. */ 1902 ChannelBuffer *bufPtr; /* The buffer to recycle. */ 1903 int mustDiscard; /* If nonzero, free the buffer to the 1904 * OS, always. */ 1905{ 1906 /* 1907 * Do we have to free the buffer to the OS? 1908 */ 1909 1910 if (mustDiscard) { 1911 ckfree((char *) bufPtr); 1912 return; 1913 } 1914 1915 /* 1916 * Only save buffers which are at least as big as the requested 1917 * buffersize for the channel. This is to honor dynamic changes 1918 * of the buffersize made by the user. 1919 */ 1920 1921 if ((bufPtr->bufLength - BUFFER_PADDING) < statePtr->bufSize) { 1922 ckfree((char *) bufPtr); 1923 return; 1924 } 1925 1926 /* 1927 * Only save buffers for the input queue if the channel is readable. 1928 */ 1929 1930 if (statePtr->flags & TCL_READABLE) { 1931 if (statePtr->inQueueHead == (ChannelBuffer *) NULL) { 1932 statePtr->inQueueHead = bufPtr; 1933 statePtr->inQueueTail = bufPtr; 1934 goto keepit; 1935 } 1936 if (statePtr->saveInBufPtr == (ChannelBuffer *) NULL) { 1937 statePtr->saveInBufPtr = bufPtr; 1938 goto keepit; 1939 } 1940 } 1941 1942 /* 1943 * Only save buffers for the output queue if the channel is writable. 1944 */ 1945 1946 if (statePtr->flags & TCL_WRITABLE) { 1947 if (statePtr->curOutPtr == (ChannelBuffer *) NULL) { 1948 statePtr->curOutPtr = bufPtr; 1949 goto keepit; 1950 } 1951 } 1952 1953 /* 1954 * If we reached this code we return the buffer to the OS. 1955 */ 1956 1957 ckfree((char *) bufPtr); 1958 return; 1959 1960 keepit: 1961 bufPtr->nextRemoved = BUFFER_PADDING; 1962 bufPtr->nextAdded = BUFFER_PADDING; 1963 bufPtr->nextPtr = (ChannelBuffer *) NULL; 1964} 1965 1966/* 1967 *---------------------------------------------------------------------- 1968 * 1969 * DiscardOutputQueued -- 1970 * 1971 * Discards all output queued in the output queue of a channel. 1972 * 1973 * Results: 1974 * None. 1975 * 1976 * Side effects: 1977 * Recycles buffers. 1978 * 1979 *---------------------------------------------------------------------- 1980 */ 1981 1982static void 1983DiscardOutputQueued(statePtr) 1984 ChannelState *statePtr; /* ChannelState for which to discard output. */ 1985{ 1986 ChannelBuffer *bufPtr; 1987 1988 while (statePtr->outQueueHead != (ChannelBuffer *) NULL) { 1989 bufPtr = statePtr->outQueueHead; 1990 statePtr->outQueueHead = bufPtr->nextPtr; 1991 RecycleBuffer(statePtr, bufPtr, 0); 1992 } 1993 statePtr->outQueueHead = (ChannelBuffer *) NULL; 1994 statePtr->outQueueTail = (ChannelBuffer *) NULL; 1995} 1996 1997/* 1998 *---------------------------------------------------------------------- 1999 * 2000 * CheckForDeadChannel -- 2001 * 2002 * This function checks is a given channel is Dead. 2003 * (A channel that has been closed but not yet deallocated.) 2004 * 2005 * Results: 2006 * True (1) if channel is Dead, False (0) if channel is Ok 2007 * 2008 * Side effects: 2009 * None 2010 * 2011 *---------------------------------------------------------------------- 2012 */ 2013 2014static int 2015CheckForDeadChannel(interp, statePtr) 2016 Tcl_Interp *interp; /* For error reporting (can be NULL) */ 2017 ChannelState *statePtr; /* The channel state to check. */ 2018{ 2019 if (statePtr->flags & CHANNEL_DEAD) { 2020 Tcl_SetErrno(EINVAL); 2021 if (interp) { 2022 Tcl_AppendResult(interp, 2023 "unable to access channel: invalid channel", 2024 (char *) NULL); 2025 } 2026 return 1; 2027 } 2028 return 0; 2029} 2030 2031/* 2032 *---------------------------------------------------------------------- 2033 * 2034 * FlushChannel -- 2035 * 2036 * This function flushes as much of the queued output as is possible 2037 * now. If calledFromAsyncFlush is nonzero, it is being called in an 2038 * event handler to flush channel output asynchronously. 2039 * 2040 * Results: 2041 * 0 if successful, else the error code that was returned by the 2042 * channel type operation. 2043 * 2044 * Side effects: 2045 * May produce output on a channel. May block indefinitely if the 2046 * channel is synchronous. May schedule an async flush on the channel. 2047 * May recycle memory for buffers in the output queue. 2048 * 2049 *---------------------------------------------------------------------- 2050 */ 2051 2052static int 2053FlushChannel(interp, chanPtr, calledFromAsyncFlush) 2054 Tcl_Interp *interp; /* For error reporting during close. */ 2055 Channel *chanPtr; /* The channel to flush on. */ 2056 int calledFromAsyncFlush; /* If nonzero then we are being 2057 * called from an asynchronous 2058 * flush callback. */ 2059{ 2060 ChannelState *statePtr = chanPtr->state; 2061 /* State of the channel stack. */ 2062 ChannelBuffer *bufPtr; /* Iterates over buffered output 2063 * queue. */ 2064 int toWrite; /* Amount of output data in current 2065 * buffer available to be written. */ 2066 int written; /* Amount of output data actually 2067 * written in current round. */ 2068 int errorCode = 0; /* Stores POSIX error codes from 2069 * channel driver operations. */ 2070 int wroteSome = 0; /* Set to one if any data was 2071 * written to the driver. */ 2072 2073 /* 2074 * Prevent writing on a dead channel -- a channel that has been closed 2075 * but not yet deallocated. This can occur if the exit handler for the 2076 * channel deallocation runs before all channels are deregistered in 2077 * all interpreters. 2078 */ 2079 2080 if (CheckForDeadChannel(interp, statePtr)) return -1; 2081 2082 /* 2083 * Loop over the queued buffers and attempt to flush as 2084 * much as possible of the queued output to the channel. 2085 */ 2086 2087 while (1) { 2088 2089 /* 2090 * If the queue is empty and there is a ready current buffer, OR if 2091 * the current buffer is full, then move the current buffer to the 2092 * queue. 2093 */ 2094 2095 if (((statePtr->curOutPtr != (ChannelBuffer *) NULL) && 2096 (statePtr->curOutPtr->nextAdded == statePtr->curOutPtr->bufLength)) 2097 || ((statePtr->flags & BUFFER_READY) && 2098 (statePtr->outQueueHead == (ChannelBuffer *) NULL))) { 2099 statePtr->flags &= (~(BUFFER_READY)); 2100 statePtr->curOutPtr->nextPtr = (ChannelBuffer *) NULL; 2101 if (statePtr->outQueueHead == (ChannelBuffer *) NULL) { 2102 statePtr->outQueueHead = statePtr->curOutPtr; 2103 } else { 2104 statePtr->outQueueTail->nextPtr = statePtr->curOutPtr; 2105 } 2106 statePtr->outQueueTail = statePtr->curOutPtr; 2107 statePtr->curOutPtr = (ChannelBuffer *) NULL; 2108 } 2109 bufPtr = statePtr->outQueueHead; 2110 2111 /* 2112 * If we are not being called from an async flush and an async 2113 * flush is active, we just return without producing any output. 2114 */ 2115 2116 if ((!calledFromAsyncFlush) && 2117 (statePtr->flags & BG_FLUSH_SCHEDULED)) { 2118 return 0; 2119 } 2120 2121 /* 2122 * If the output queue is still empty, break out of the while loop. 2123 */ 2124 2125 if (bufPtr == (ChannelBuffer *) NULL) { 2126 break; /* Out of the "while (1)". */ 2127 } 2128 2129 /* 2130 * Produce the output on the channel. 2131 */ 2132 2133 toWrite = bufPtr->nextAdded - bufPtr->nextRemoved; 2134 if (toWrite == 0) { 2135 written = 0; 2136 } else { 2137 written = (chanPtr->typePtr->outputProc) (chanPtr->instanceData, 2138 bufPtr->buf + bufPtr->nextRemoved, toWrite, 2139 &errorCode); 2140 } 2141 2142 /* 2143 * If the write failed completely attempt to start the asynchronous 2144 * flush mechanism and break out of this loop - do not attempt to 2145 * write any more output at this time. 2146 */ 2147 2148 if (written < 0) { 2149 2150 /* 2151 * If the last attempt to write was interrupted, simply retry. 2152 */ 2153 2154 if (errorCode == EINTR) { 2155 errorCode = 0; 2156 continue; 2157 } 2158 2159 /* 2160 * If the channel is non-blocking and we would have blocked, 2161 * start a background flushing handler and break out of the loop. 2162 */ 2163 2164 if ((errorCode == EWOULDBLOCK) || (errorCode == EAGAIN)) { 2165 /* 2166 * This used to check for CHANNEL_NONBLOCKING, and panic 2167 * if the channel was blocking. However, it appears 2168 * that setting stdin to -blocking 0 has some effect on 2169 * the stdout when it's a tty channel (dup'ed underneath) 2170 */ 2171 if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) { 2172 statePtr->flags |= BG_FLUSH_SCHEDULED; 2173 UpdateInterest(chanPtr); 2174 } 2175 errorCode = 0; 2176 break; 2177 } 2178 2179 /* 2180 * Decide whether to report the error upwards or defer it. 2181 */ 2182 2183 if (calledFromAsyncFlush) { 2184 if (statePtr->unreportedError == 0) { 2185 statePtr->unreportedError = errorCode; 2186 } 2187 } else { 2188 Tcl_SetErrno(errorCode); 2189 if (interp != NULL) { 2190 2191 /* 2192 * Casting away CONST here is safe because the 2193 * TCL_VOLATILE flag guarantees CONST treatment 2194 * of the Posix error string. 2195 */ 2196 2197 Tcl_SetResult(interp, 2198 (char *) Tcl_PosixError(interp), TCL_VOLATILE); 2199 } 2200 } 2201 2202 /* 2203 * When we get an error we throw away all the output 2204 * currently queued. 2205 */ 2206 2207 DiscardOutputQueued(statePtr); 2208 continue; 2209 } else { 2210 wroteSome = 1; 2211 } 2212 2213 bufPtr->nextRemoved += written; 2214 2215 /* 2216 * If this buffer is now empty, recycle it. 2217 */ 2218 2219 if (bufPtr->nextRemoved == bufPtr->nextAdded) { 2220 statePtr->outQueueHead = bufPtr->nextPtr; 2221 if (statePtr->outQueueHead == (ChannelBuffer *) NULL) { 2222 statePtr->outQueueTail = (ChannelBuffer *) NULL; 2223 } 2224 RecycleBuffer(statePtr, bufPtr, 0); 2225 } 2226 } /* Closes "while (1)". */ 2227 2228 /* 2229 * If we wrote some data while flushing in the background, we are done. 2230 * We can't finish the background flush until we run out of data and 2231 * the channel becomes writable again. This ensures that all of the 2232 * pending data has been flushed at the system level. 2233 */ 2234 2235 if (statePtr->flags & BG_FLUSH_SCHEDULED) { 2236 if (wroteSome) { 2237 return errorCode; 2238 } else if (statePtr->outQueueHead == (ChannelBuffer *) NULL) { 2239 statePtr->flags &= (~(BG_FLUSH_SCHEDULED)); 2240 (chanPtr->typePtr->watchProc)(chanPtr->instanceData, 2241 statePtr->interestMask); 2242 } 2243 } 2244 2245 /* 2246 * If the channel is flagged as closed, delete it when the refCount 2247 * drops to zero, the output queue is empty and there is no output 2248 * in the current output buffer. 2249 */ 2250 2251 if ((statePtr->flags & CHANNEL_CLOSED) && (statePtr->refCount <= 0) && 2252 (statePtr->outQueueHead == (ChannelBuffer *) NULL) && 2253 ((statePtr->curOutPtr == (ChannelBuffer *) NULL) || 2254 (statePtr->curOutPtr->nextAdded == 2255 statePtr->curOutPtr->nextRemoved))) { 2256 return CloseChannel(interp, chanPtr, errorCode); 2257 } 2258 return errorCode; 2259} 2260 2261/* 2262 *---------------------------------------------------------------------- 2263 * 2264 * CloseChannel -- 2265 * 2266 * Utility procedure to close a channel and free associated resources. 2267 * 2268 * If the channel was stacked, then the it will copy the necessary 2269 * elements of the NEXT channel into the TOP channel, in essence 2270 * unstacking the channel. The NEXT channel will then be freed. 2271 * 2272 * If the channel was not stacked, then we will free all the bits 2273 * for the TOP channel, including the data structure itself. 2274 * 2275 * Results: 2276 * 1 if the channel was stacked, 0 otherwise. 2277 * 2278 * Side effects: 2279 * May close the actual channel; may free memory. 2280 * May change the value of errno. 2281 * 2282 *---------------------------------------------------------------------- 2283 */ 2284 2285static int 2286CloseChannel(interp, chanPtr, errorCode) 2287 Tcl_Interp *interp; /* For error reporting. */ 2288 Channel *chanPtr; /* The channel to close. */ 2289 int errorCode; /* Status of operation so far. */ 2290{ 2291 int result = 0; /* Of calling driver close 2292 * operation. */ 2293 ChannelState *statePtr; /* state of the channel stack. */ 2294 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 2295 2296 if (chanPtr == NULL) { 2297 return result; 2298 } 2299 statePtr = chanPtr->state; 2300 2301 /* 2302 * No more input can be consumed so discard any leftover input. 2303 */ 2304 2305 DiscardInputQueued(statePtr, 1); 2306 2307 /* 2308 * Discard a leftover buffer in the current output buffer field. 2309 */ 2310 2311 if (statePtr->curOutPtr != (ChannelBuffer *) NULL) { 2312 ckfree((char *) statePtr->curOutPtr); 2313 statePtr->curOutPtr = (ChannelBuffer *) NULL; 2314 } 2315 2316 /* 2317 * The caller guarantees that there are no more buffers 2318 * queued for output. 2319 */ 2320 2321 if (statePtr->outQueueHead != (ChannelBuffer *) NULL) { 2322 panic("TclFlush, closed channel: queued output left"); 2323 } 2324 2325 /* 2326 * If the EOF character is set in the channel, append that to the 2327 * output device. 2328 */ 2329 2330 if ((statePtr->outEofChar != 0) && (statePtr->flags & TCL_WRITABLE)) { 2331 int dummy; 2332 char c; 2333 2334 c = (char) statePtr->outEofChar; 2335 (chanPtr->typePtr->outputProc) (chanPtr->instanceData, &c, 1, &dummy); 2336 } 2337 2338 /* 2339 * Remove this channel from of the list of all channels. 2340 */ 2341 Tcl_CutChannel((Tcl_Channel) chanPtr); 2342 2343 /* 2344 * Close and free the channel driver state. 2345 */ 2346 2347 if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { 2348 result = (chanPtr->typePtr->closeProc)(chanPtr->instanceData, interp); 2349 } else { 2350 result = (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, interp, 2351 0); 2352 } 2353 2354 /* 2355 * Some resources can be cleared only if the bottom channel 2356 * in a stack is closed. All the other channels in the stack 2357 * are not allowed to remove. 2358 */ 2359 2360 if (chanPtr == statePtr->bottomChanPtr) { 2361 if (statePtr->channelName != (char *) NULL) { 2362 ckfree((char *) statePtr->channelName); 2363 statePtr->channelName = NULL; 2364 } 2365 2366 Tcl_FreeEncoding(statePtr->encoding); 2367 if (statePtr->outputStage != NULL) { 2368 ckfree((char *) statePtr->outputStage); 2369 statePtr->outputStage = (char *) NULL; 2370 } 2371 } 2372 2373 /* 2374 * If we are being called synchronously, report either 2375 * any latent error on the channel or the current error. 2376 */ 2377 2378 if (statePtr->unreportedError != 0) { 2379 errorCode = statePtr->unreportedError; 2380 } 2381 if (errorCode == 0) { 2382 errorCode = result; 2383 if (errorCode != 0) { 2384 Tcl_SetErrno(errorCode); 2385 } 2386 } 2387 2388 /* 2389 * Cancel any outstanding timer. 2390 */ 2391 2392 Tcl_DeleteTimerHandler(statePtr->timer); 2393 2394 /* 2395 * Mark the channel as deleted by clearing the type structure. 2396 */ 2397 2398 if (chanPtr->downChanPtr != (Channel *) NULL) { 2399 Channel *downChanPtr = chanPtr->downChanPtr; 2400 2401 statePtr->nextCSPtr = tsdPtr->firstCSPtr; 2402 tsdPtr->firstCSPtr = statePtr; 2403 2404 statePtr->topChanPtr = downChanPtr; 2405 downChanPtr->upChanPtr = (Channel *) NULL; 2406 chanPtr->typePtr = NULL; 2407 2408 Tcl_EventuallyFree((ClientData) chanPtr, TCL_DYNAMIC); 2409 return Tcl_Close(interp, (Tcl_Channel) downChanPtr); 2410 } 2411 2412 /* 2413 * There is only the TOP Channel, so we free the remaining 2414 * pointers we have and then ourselves. Since this is the 2415 * last of the channels in the stack, make sure to free the 2416 * ChannelState structure associated with it. We use 2417 * Tcl_EventuallyFree to allow for any last 2418 */ 2419 chanPtr->typePtr = NULL; 2420 2421 Tcl_EventuallyFree((ClientData) statePtr, TCL_DYNAMIC); 2422 Tcl_EventuallyFree((ClientData) chanPtr, TCL_DYNAMIC); 2423 2424 return errorCode; 2425} 2426 2427/* 2428 *---------------------------------------------------------------------- 2429 * 2430 * Tcl_CutChannel -- 2431 * 2432 * Removes a channel from the (thread-)global list of all channels 2433 * (in that thread). This is actually the statePtr for the stack 2434 * of channel. 2435 * 2436 * Results: 2437 * Nothing. 2438 * 2439 * Side effects: 2440 * Resets the field 'nextCSPtr' of the specified channel state to NULL. 2441 * 2442 * NOTE: 2443 * The channel to cut out of the list must not be referenced 2444 * in any interpreter. This is something this procedure cannot 2445 * check (despite the refcount) because the caller usually wants 2446 * fiddle with the channel (like transfering it to a different 2447 * thread) and thus keeps the refcount artifically high to prevent 2448 * its destruction. 2449 * 2450 *---------------------------------------------------------------------- 2451 */ 2452 2453void 2454Tcl_CutChannel(chan) 2455 Tcl_Channel chan; /* The channel being removed. Must 2456 * not be referenced in any 2457 * interpreter. */ 2458{ 2459 ThreadSpecificData* tsdPtr = TCL_TSD_INIT(&dataKey); 2460 ChannelState *prevCSPtr; /* Preceding channel state in list of 2461 * all states - used to splice a 2462 * channel out of the list on close. */ 2463 ChannelState *statePtr = ((Channel *) chan)->state; 2464 /* state of the channel stack. */ 2465 Tcl_DriverThreadActionProc *threadActionProc; 2466 2467 /* 2468 * Remove this channel from of the list of all channels 2469 * (in the current thread). 2470 */ 2471 2472 if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) { 2473 tsdPtr->firstCSPtr = statePtr->nextCSPtr; 2474 } else { 2475 for (prevCSPtr = tsdPtr->firstCSPtr; 2476 prevCSPtr && (prevCSPtr->nextCSPtr != statePtr); 2477 prevCSPtr = prevCSPtr->nextCSPtr) { 2478 /* Empty loop body. */ 2479 } 2480 if (prevCSPtr == (ChannelState *) NULL) { 2481 panic("FlushChannel: damaged channel list"); 2482 } 2483 prevCSPtr->nextCSPtr = statePtr->nextCSPtr; 2484 } 2485 2486 statePtr->nextCSPtr = (ChannelState *) NULL; 2487 2488 /* TIP #218, Channel Thread Actions */ 2489 threadActionProc = Tcl_ChannelThreadActionProc (Tcl_GetChannelType (chan)); 2490 if (threadActionProc != NULL) { 2491 (*threadActionProc) (Tcl_GetChannelInstanceData(chan), 2492 TCL_CHANNEL_THREAD_REMOVE); 2493 } 2494} 2495 2496/* 2497 *---------------------------------------------------------------------- 2498 * 2499 * Tcl_SpliceChannel -- 2500 * 2501 * Adds a channel to the (thread-)global list of all channels 2502 * (in that thread). Expects that the field 'nextChanPtr' in 2503 * the channel is set to NULL. 2504 * 2505 * Results: 2506 * Nothing. 2507 * 2508 * Side effects: 2509 * Nothing. 2510 * 2511 * NOTE: 2512 * The channel to splice into the list must not be referenced in any 2513 * interpreter. This is something this procedure cannot check 2514 * (despite the refcount) because the caller usually wants figgle 2515 * with the channel (like transfering it to a different thread) 2516 * and thus keeps the refcount artifically high to prevent its 2517 * destruction. 2518 * 2519 *---------------------------------------------------------------------- 2520 */ 2521 2522void 2523Tcl_SpliceChannel(chan) 2524 Tcl_Channel chan; /* The channel being added. Must 2525 * not be referenced in any 2526 * interpreter. */ 2527{ 2528 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 2529 ChannelState *statePtr = ((Channel *) chan)->state; 2530 Tcl_DriverThreadActionProc *threadActionProc; 2531 2532 if (statePtr->nextCSPtr != (ChannelState *) NULL) { 2533 panic("Tcl_SpliceChannel: trying to add channel used in different list"); 2534 } 2535 2536 statePtr->nextCSPtr = tsdPtr->firstCSPtr; 2537 tsdPtr->firstCSPtr = statePtr; 2538 2539 /* 2540 * TIP #10. Mark the current thread as the new one managing this 2541 * channel. Note: 'Tcl_GetCurrentThread' returns sensible 2542 * values even for a non-threaded core. 2543 */ 2544 2545 statePtr->managingThread = Tcl_GetCurrentThread (); 2546 2547 /* TIP #218, Channel Thread Actions */ 2548 threadActionProc = Tcl_ChannelThreadActionProc (Tcl_GetChannelType (chan)); 2549 if (threadActionProc != NULL) { 2550 (*threadActionProc) (Tcl_GetChannelInstanceData(chan), 2551 TCL_CHANNEL_THREAD_INSERT); 2552 } 2553} 2554 2555/* 2556 *---------------------------------------------------------------------- 2557 * 2558 * Tcl_Close -- 2559 * 2560 * Closes a channel. 2561 * 2562 * Results: 2563 * A standard Tcl result. 2564 * 2565 * Side effects: 2566 * Closes the channel if this is the last reference. 2567 * 2568 * NOTE: 2569 * Tcl_Close removes the channel as far as the user is concerned. 2570 * However, it may continue to exist for a while longer if it has 2571 * a background flush scheduled. The device itself is eventually 2572 * closed and the channel record removed, in CloseChannel, above. 2573 * 2574 *---------------------------------------------------------------------- 2575 */ 2576 2577 /* ARGSUSED */ 2578int 2579Tcl_Close(interp, chan) 2580 Tcl_Interp *interp; /* Interpreter for errors. */ 2581 Tcl_Channel chan; /* The channel being closed. Must 2582 * not be referenced in any 2583 * interpreter. */ 2584{ 2585 CloseCallback *cbPtr; /* Iterate over close callbacks 2586 * for this channel. */ 2587 Channel *chanPtr; /* The real IO channel. */ 2588 ChannelState *statePtr; /* State of real IO channel. */ 2589 int result; /* Of calling FlushChannel. */ 2590 2591 if (chan == (Tcl_Channel) NULL) { 2592 return TCL_OK; 2593 } 2594 2595 /* 2596 * Perform special handling for standard channels being closed. If the 2597 * refCount is now 1 it means that the last reference to the standard 2598 * channel is being explicitly closed, so bump the refCount down 2599 * artificially to 0. This will ensure that the channel is actually 2600 * closed, below. Also set the static pointer to NULL for the channel. 2601 */ 2602 2603 CheckForStdChannelsBeingClosed(chan); 2604 2605 /* 2606 * This operation should occur at the top of a channel stack. 2607 */ 2608 2609 chanPtr = (Channel *) chan; 2610 statePtr = chanPtr->state; 2611 chanPtr = statePtr->topChanPtr; 2612 2613 if (statePtr->refCount > 0) { 2614 panic("called Tcl_Close on channel with refCount > 0"); 2615 } 2616 2617 if (statePtr->flags & CHANNEL_INCLOSE) { 2618 if (interp) { 2619 Tcl_AppendResult(interp, 2620 "Illegal recursive call to close through close-handler of channel", 2621 (char *) NULL); 2622 } 2623 return TCL_ERROR; 2624 } 2625 statePtr->flags |= CHANNEL_INCLOSE; 2626 2627 /* 2628 * When the channel has an escape sequence driven encoding such as 2629 * iso2022, the terminated escape sequence must write to the buffer. 2630 */ 2631 if ((statePtr->encoding != NULL) && (statePtr->curOutPtr != NULL) 2632 && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) { 2633 statePtr->outputEncodingFlags |= TCL_ENCODING_END; 2634 WriteChars(chanPtr, "", 0); 2635 } 2636 2637 Tcl_ClearChannelHandlers(chan); 2638 2639 /* 2640 * Invoke the registered close callbacks and delete their records. 2641 */ 2642 2643 while (statePtr->closeCbPtr != (CloseCallback *) NULL) { 2644 cbPtr = statePtr->closeCbPtr; 2645 statePtr->closeCbPtr = cbPtr->nextPtr; 2646 (cbPtr->proc) (cbPtr->clientData); 2647 ckfree((char *) cbPtr); 2648 } 2649 2650 statePtr->flags &= ~CHANNEL_INCLOSE; 2651 2652 /* 2653 * Ensure that the last output buffer will be flushed. 2654 */ 2655 2656 if ((statePtr->curOutPtr != (ChannelBuffer *) NULL) && 2657 (statePtr->curOutPtr->nextAdded > statePtr->curOutPtr->nextRemoved)) { 2658 statePtr->flags |= BUFFER_READY; 2659 } 2660 2661 /* 2662 * If this channel supports it, close the read side, since we don't need it 2663 * anymore and this will help avoid deadlocks on some channel types. 2664 */ 2665 2666 if (chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) { 2667 result = (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, interp, 2668 TCL_CLOSE_READ); 2669 } else { 2670 result = 0; 2671 } 2672 2673 /* 2674 * The call to FlushChannel will flush any queued output and invoke 2675 * the close function of the channel driver, or it will set up the 2676 * channel to be flushed and closed asynchronously. 2677 */ 2678 2679 statePtr->flags |= CHANNEL_CLOSED; 2680 if ((FlushChannel(interp, chanPtr, 0) != 0) || (result != 0)) { 2681 return TCL_ERROR; 2682 } 2683 return TCL_OK; 2684} 2685 2686/* 2687 *---------------------------------------------------------------------- 2688 * 2689 * Tcl_ClearChannelHandlers -- 2690 * 2691 * Removes all channel handlers and event scripts from the channel, 2692 * cancels all background copies involving the channel and any interest 2693 * in events. 2694 * 2695 * Results: 2696 * None. 2697 * 2698 * Side effects: 2699 * See above. Deallocates memory. 2700 * 2701 *---------------------------------------------------------------------- 2702 */ 2703 2704void 2705Tcl_ClearChannelHandlers (channel) 2706 Tcl_Channel channel; 2707{ 2708 ChannelHandler *chPtr, *chNext; /* Iterate over channel handlers. */ 2709 EventScriptRecord *ePtr, *eNextPtr; /* Iterate over eventscript records. */ 2710 Channel *chanPtr; /* The real IO channel. */ 2711 ChannelState *statePtr; /* State of real IO channel. */ 2712 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 2713 NextChannelHandler *nhPtr; 2714 2715 /* 2716 * This operation should occur at the top of a channel stack. 2717 */ 2718 2719 chanPtr = (Channel *) channel; 2720 statePtr = chanPtr->state; 2721 chanPtr = statePtr->topChanPtr; 2722 2723 /* 2724 * Cancel any outstanding timer. 2725 */ 2726 2727 Tcl_DeleteTimerHandler(statePtr->timer); 2728 2729 /* 2730 * Remove any references to channel handlers for this channel that 2731 * may be about to be invoked. 2732 */ 2733 2734 for (nhPtr = tsdPtr->nestedHandlerPtr; 2735 nhPtr != (NextChannelHandler *) NULL; 2736 nhPtr = nhPtr->nestedHandlerPtr) { 2737 if (nhPtr->nextHandlerPtr && 2738 (nhPtr->nextHandlerPtr->chanPtr == chanPtr)) { 2739 nhPtr->nextHandlerPtr = NULL; 2740 } 2741 } 2742 2743 /* 2744 * Remove all the channel handler records attached to the channel 2745 * itself. 2746 */ 2747 2748 for (chPtr = statePtr->chPtr; 2749 chPtr != (ChannelHandler *) NULL; 2750 chPtr = chNext) { 2751 chNext = chPtr->nextPtr; 2752 ckfree((char *) chPtr); 2753 } 2754 statePtr->chPtr = (ChannelHandler *) NULL; 2755 2756 /* 2757 * Cancel any pending copy operation. 2758 */ 2759 2760 StopCopy(statePtr->csPtrR); 2761 StopCopy(statePtr->csPtrW); 2762 2763 /* 2764 * Must set the interest mask now to 0, otherwise infinite loops 2765 * will occur if Tcl_DoOneEvent is called before the channel is 2766 * finally deleted in FlushChannel. This can happen if the channel 2767 * has a background flush active. 2768 */ 2769 2770 statePtr->interestMask = 0; 2771 2772 /* 2773 * Remove any EventScript records for this channel. 2774 */ 2775 2776 for (ePtr = statePtr->scriptRecordPtr; 2777 ePtr != (EventScriptRecord *) NULL; 2778 ePtr = eNextPtr) { 2779 eNextPtr = ePtr->nextPtr; 2780 Tcl_DecrRefCount(ePtr->scriptPtr); 2781 ckfree((char *) ePtr); 2782 } 2783 statePtr->scriptRecordPtr = (EventScriptRecord *) NULL; 2784} 2785 2786/* 2787 *---------------------------------------------------------------------- 2788 * 2789 * Tcl_Write -- 2790 * 2791 * Puts a sequence of bytes into an output buffer, may queue the 2792 * buffer for output if it gets full, and also remembers whether the 2793 * current buffer is ready e.g. if it contains a newline and we are in 2794 * line buffering mode. Compensates stacking, i.e. will redirect the 2795 * data from the specified channel to the topmost channel in a stack. 2796 * 2797 * No encoding conversions are applied to the bytes being read. 2798 * 2799 * Results: 2800 * The number of bytes written or -1 in case of error. If -1, 2801 * Tcl_GetErrno will return the error code. 2802 * 2803 * Side effects: 2804 * May buffer up output and may cause output to be produced on the 2805 * channel. 2806 * 2807 *---------------------------------------------------------------------- 2808 */ 2809 2810int 2811Tcl_Write(chan, src, srcLen) 2812 Tcl_Channel chan; /* The channel to buffer output for. */ 2813 CONST char *src; /* Data to queue in output buffer. */ 2814 int srcLen; /* Length of data in bytes, or < 0 for 2815 * strlen(). */ 2816{ 2817 /* 2818 * Always use the topmost channel of the stack 2819 */ 2820 Channel *chanPtr; 2821 ChannelState *statePtr; /* state info for channel */ 2822 2823 statePtr = ((Channel *) chan)->state; 2824 chanPtr = statePtr->topChanPtr; 2825 2826 if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { 2827 return -1; 2828 } 2829 2830 if (srcLen < 0) { 2831 srcLen = strlen(src); 2832 } 2833 return DoWrite(chanPtr, src, srcLen); 2834} 2835 2836/* 2837 *---------------------------------------------------------------------- 2838 * 2839 * Tcl_WriteRaw -- 2840 * 2841 * Puts a sequence of bytes into an output buffer, may queue the 2842 * buffer for output if it gets full, and also remembers whether the 2843 * current buffer is ready e.g. if it contains a newline and we are in 2844 * line buffering mode. Writes directly to the driver of the channel, 2845 * does not compensate for stacking. 2846 * 2847 * No encoding conversions are applied to the bytes being read. 2848 * 2849 * Results: 2850 * The number of bytes written or -1 in case of error. If -1, 2851 * Tcl_GetErrno will return the error code. 2852 * 2853 * Side effects: 2854 * May buffer up output and may cause output to be produced on the 2855 * channel. 2856 * 2857 *---------------------------------------------------------------------- 2858 */ 2859 2860int 2861Tcl_WriteRaw(chan, src, srcLen) 2862 Tcl_Channel chan; /* The channel to buffer output for. */ 2863 CONST char *src; /* Data to queue in output buffer. */ 2864 int srcLen; /* Length of data in bytes, or < 0 for 2865 * strlen(). */ 2866{ 2867 Channel *chanPtr = ((Channel *) chan); 2868 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 2869 int errorCode, written; 2870 2871 if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) { 2872 return -1; 2873 } 2874 2875 if (srcLen < 0) { 2876 srcLen = strlen(src); 2877 } 2878 2879 /* 2880 * Go immediately to the driver, do all the error handling by ourselves. 2881 * The code was stolen from 'FlushChannel'. 2882 */ 2883 2884 written = (chanPtr->typePtr->outputProc) (chanPtr->instanceData, 2885 src, srcLen, &errorCode); 2886 2887 if (written < 0) { 2888 Tcl_SetErrno(errorCode); 2889 } 2890 2891 return written; 2892} 2893 2894/* 2895 *--------------------------------------------------------------------------- 2896 * 2897 * Tcl_WriteChars -- 2898 * 2899 * Takes a sequence of UTF-8 characters and converts them for output 2900 * using the channel's current encoding, may queue the buffer for 2901 * output if it gets full, and also remembers whether the current 2902 * buffer is ready e.g. if it contains a newline and we are in 2903 * line buffering mode. Compensates stacking, i.e. will redirect the 2904 * data from the specified channel to the topmost channel in a stack. 2905 * 2906 * Results: 2907 * The number of bytes written or -1 in case of error. If -1, 2908 * Tcl_GetErrno will return the error code. 2909 * 2910 * Side effects: 2911 * May buffer up output and may cause output to be produced on the 2912 * channel. 2913 * 2914 *---------------------------------------------------------------------- 2915 */ 2916 2917int 2918Tcl_WriteChars(chan, src, len) 2919 Tcl_Channel chan; /* The channel to buffer output for. */ 2920 CONST char *src; /* UTF-8 characters to queue in output buffer. */ 2921 int len; /* Length of string in bytes, or < 0 for 2922 * strlen(). */ 2923{ 2924 ChannelState *statePtr; /* state info for channel */ 2925 2926 statePtr = ((Channel *) chan)->state; 2927 2928 if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { 2929 return -1; 2930 } 2931 2932 return DoWriteChars ((Channel*) chan, src, len); 2933} 2934 2935/* 2936 *--------------------------------------------------------------------------- 2937 * 2938 * DoWriteChars -- 2939 * 2940 * Takes a sequence of UTF-8 characters and converts them for output 2941 * using the channel's current encoding, may queue the buffer for 2942 * output if it gets full, and also remembers whether the current 2943 * buffer is ready e.g. if it contains a newline and we are in 2944 * line buffering mode. Compensates stacking, i.e. will redirect the 2945 * data from the specified channel to the topmost channel in a stack. 2946 * 2947 * Results: 2948 * The number of bytes written or -1 in case of error. If -1, 2949 * Tcl_GetErrno will return the error code. 2950 * 2951 * Side effects: 2952 * May buffer up output and may cause output to be produced on the 2953 * channel. 2954 * 2955 *---------------------------------------------------------------------- 2956 */ 2957 2958static int 2959DoWriteChars(chanPtr, src, len) 2960 Channel* chanPtr; /* The channel to buffer output for. */ 2961 CONST char *src; /* UTF-8 characters to queue in output buffer. */ 2962 int len; /* Length of string in bytes, or < 0 for 2963 * strlen(). */ 2964{ 2965 /* 2966 * Always use the topmost channel of the stack 2967 */ 2968 ChannelState *statePtr; /* state info for channel */ 2969 2970 statePtr = chanPtr->state; 2971 chanPtr = statePtr->topChanPtr; 2972 2973 if (len < 0) { 2974 len = strlen(src); 2975 } 2976 if (statePtr->encoding == NULL) { 2977 /* 2978 * Inefficient way to convert UTF-8 to byte-array, but the 2979 * code parallels the way it is done for objects. 2980 */ 2981 2982 Tcl_Obj *objPtr; 2983 int result; 2984 2985 objPtr = Tcl_NewStringObj(src, len); 2986 src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len); 2987 result = WriteBytes(chanPtr, src, len); 2988 Tcl_DecrRefCount(objPtr); 2989 return result; 2990 } 2991 return WriteChars(chanPtr, src, len); 2992} 2993 2994/* 2995 *--------------------------------------------------------------------------- 2996 * 2997 * Tcl_WriteObj -- 2998 * 2999 * Takes the Tcl object and queues its contents for output. If the 3000 * encoding of the channel is NULL, takes the byte-array representation 3001 * of the object and queues those bytes for output. Otherwise, takes 3002 * the characters in the UTF-8 (string) representation of the object 3003 * and converts them for output using the channel's current encoding. 3004 * May flush internal buffers to output if one becomes full or is ready 3005 * for some other reason, e.g. if it contains a newline and the channel 3006 * is in line buffering mode. 3007 * 3008 * Results: 3009 * The number of bytes written or -1 in case of error. If -1, 3010 * Tcl_GetErrno() will return the error code. 3011 * 3012 * Side effects: 3013 * May buffer up output and may cause output to be produced on the 3014 * channel. 3015 * 3016 *---------------------------------------------------------------------- 3017 */ 3018 3019int 3020Tcl_WriteObj(chan, objPtr) 3021 Tcl_Channel chan; /* The channel to buffer output for. */ 3022 Tcl_Obj *objPtr; /* The object to write. */ 3023{ 3024 /* 3025 * Always use the topmost channel of the stack 3026 */ 3027 Channel *chanPtr; 3028 ChannelState *statePtr; /* state info for channel */ 3029 char *src; 3030 int srcLen; 3031 3032 statePtr = ((Channel *) chan)->state; 3033 chanPtr = statePtr->topChanPtr; 3034 3035 if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { 3036 return -1; 3037 } 3038 if (statePtr->encoding == NULL) { 3039 src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen); 3040 return WriteBytes(chanPtr, src, srcLen); 3041 } else { 3042 src = Tcl_GetStringFromObj(objPtr, &srcLen); 3043 return WriteChars(chanPtr, src, srcLen); 3044 } 3045} 3046 3047/* 3048 *---------------------------------------------------------------------- 3049 * 3050 * WriteBytes -- 3051 * 3052 * Write a sequence of bytes into an output buffer, may queue the 3053 * buffer for output if it gets full, and also remembers whether the 3054 * current buffer is ready e.g. if it contains a newline and we are in 3055 * line buffering mode. 3056 * 3057 * Results: 3058 * The number of bytes written or -1 in case of error. If -1, 3059 * Tcl_GetErrno will return the error code. 3060 * 3061 * Side effects: 3062 * May buffer up output and may cause output to be produced on the 3063 * channel. 3064 * 3065 *---------------------------------------------------------------------- 3066 */ 3067 3068static int 3069WriteBytes(chanPtr, src, srcLen) 3070 Channel *chanPtr; /* The channel to buffer output for. */ 3071 CONST char *src; /* Bytes to write. */ 3072 int srcLen; /* Number of bytes to write. */ 3073{ 3074 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 3075 ChannelBuffer *bufPtr; 3076 char *dst; 3077 int dstMax, sawLF, savedLF, total, dstLen, toWrite; 3078 3079 total = 0; 3080 sawLF = 0; 3081 savedLF = 0; 3082 3083 /* 3084 * Loop over all bytes in src, storing them in output buffer with 3085 * proper EOL translation. 3086 */ 3087 3088 while (srcLen + savedLF > 0) { 3089 bufPtr = statePtr->curOutPtr; 3090 if (bufPtr == NULL) { 3091 bufPtr = AllocChannelBuffer(statePtr->bufSize); 3092 statePtr->curOutPtr = bufPtr; 3093 } 3094 dst = bufPtr->buf + bufPtr->nextAdded; 3095 dstMax = bufPtr->bufLength - bufPtr->nextAdded; 3096 dstLen = dstMax; 3097 3098 toWrite = dstLen; 3099 if (toWrite > srcLen) { 3100 toWrite = srcLen; 3101 } 3102 3103 if (savedLF) { 3104 /* 3105 * A '\n' was left over from last call to TranslateOutputEOL() 3106 * and we need to store it in this buffer. If the channel is 3107 * line-based, we will need to flush it. 3108 */ 3109 3110 *dst++ = '\n'; 3111 dstLen--; 3112 sawLF++; 3113 } 3114 sawLF += TranslateOutputEOL(statePtr, dst, src, &dstLen, &toWrite); 3115 dstLen += savedLF; 3116 savedLF = 0; 3117 3118 if (dstLen > dstMax) { 3119 savedLF = 1; 3120 dstLen = dstMax; 3121 } 3122 bufPtr->nextAdded += dstLen; 3123 if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) { 3124 return -1; 3125 } 3126 total += dstLen; 3127 src += toWrite; 3128 srcLen -= toWrite; 3129 sawLF = 0; 3130 } 3131 return total; 3132} 3133 3134/* 3135 *---------------------------------------------------------------------- 3136 * 3137 * WriteChars -- 3138 * 3139 * Convert UTF-8 bytes to the channel's external encoding and 3140 * write the produced bytes into an output buffer, may queue the 3141 * buffer for output if it gets full, and also remembers whether the 3142 * current buffer is ready e.g. if it contains a newline and we are in 3143 * line buffering mode. 3144 * 3145 * Results: 3146 * The number of bytes written or -1 in case of error. If -1, 3147 * Tcl_GetErrno will return the error code. 3148 * 3149 * Side effects: 3150 * May buffer up output and may cause output to be produced on the 3151 * channel. 3152 * 3153 *---------------------------------------------------------------------- 3154 */ 3155 3156static int 3157WriteChars(chanPtr, src, srcLen) 3158 Channel *chanPtr; /* The channel to buffer output for. */ 3159 CONST char *src; /* UTF-8 string to write. */ 3160 int srcLen; /* Length of UTF-8 string in bytes. */ 3161{ 3162 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 3163 ChannelBuffer *bufPtr; 3164 char *dst, *stage; 3165 int saved, savedLF, sawLF, total, dstLen, stageMax, dstWrote; 3166 int stageLen, toWrite, stageRead, endEncoding, result; 3167 int consumedSomething; 3168 Tcl_Encoding encoding; 3169 char safe[BUFFER_PADDING]; 3170 3171 total = 0; 3172 sawLF = 0; 3173 savedLF = 0; 3174 saved = 0; 3175 encoding = statePtr->encoding; 3176 3177 /* 3178 * Write the terminated escape sequence even if srcLen is 0. 3179 */ 3180 3181 endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0); 3182 3183 /* 3184 * Loop over all UTF-8 characters in src, storing them in staging buffer 3185 * with proper EOL translation. 3186 */ 3187 3188 consumedSomething = 1; 3189 while (consumedSomething && (srcLen + savedLF + endEncoding > 0)) { 3190 consumedSomething = 0; 3191 stage = statePtr->outputStage; 3192 stageMax = statePtr->bufSize; 3193 stageLen = stageMax; 3194 3195 toWrite = stageLen; 3196 if (toWrite > srcLen) { 3197 toWrite = srcLen; 3198 } 3199 3200 if (savedLF) { 3201 /* 3202 * A '\n' was left over from last call to TranslateOutputEOL() 3203 * and we need to store it in the staging buffer. If the 3204 * channel is line-based, we will need to flush the output 3205 * buffer (after translating the staging buffer). 3206 */ 3207 3208 *stage++ = '\n'; 3209 stageLen--; 3210 sawLF++; 3211 } 3212 sawLF += TranslateOutputEOL(statePtr, stage, src, &stageLen, &toWrite); 3213 3214 stage -= savedLF; 3215 stageLen += savedLF; 3216 savedLF = 0; 3217 3218 if (stageLen > stageMax) { 3219 savedLF = 1; 3220 stageLen = stageMax; 3221 } 3222 src += toWrite; 3223 srcLen -= toWrite; 3224 3225 /* 3226 * Loop over all UTF-8 characters in staging buffer, converting them 3227 * to external encoding, storing them in output buffer. 3228 */ 3229 3230 while (stageLen + saved + endEncoding > 0) { 3231 bufPtr = statePtr->curOutPtr; 3232 if (bufPtr == NULL) { 3233 bufPtr = AllocChannelBuffer(statePtr->bufSize); 3234 statePtr->curOutPtr = bufPtr; 3235 } 3236 dst = bufPtr->buf + bufPtr->nextAdded; 3237 dstLen = bufPtr->bufLength - bufPtr->nextAdded; 3238 3239 if (saved != 0) { 3240 /* 3241 * Here's some translated bytes left over from the last 3242 * buffer that we need to stick at the beginning of this 3243 * buffer. 3244 */ 3245 3246 memcpy((VOID *) dst, (VOID *) safe, (size_t) saved); 3247 bufPtr->nextAdded += saved; 3248 dst += saved; 3249 dstLen -= saved; 3250 saved = 0; 3251 } 3252 3253 result = Tcl_UtfToExternal(NULL, encoding, stage, stageLen, 3254 statePtr->outputEncodingFlags, 3255 &statePtr->outputEncodingState, dst, 3256 dstLen + BUFFER_PADDING, &stageRead, &dstWrote, NULL); 3257 3258 /* Fix for SF #506297, reported by Martin Forssen 3259 * <ruric@users.sourceforge.net>. 3260 * 3261 * The encoding chosen in the script exposing the bug writes out 3262 * three intro characters when TCL_ENCODING_START is set, but does 3263 * not consume any input as TCL_ENCODING_END is cleared. As some 3264 * output was generated the enclosing loop calls UtfToExternal 3265 * again, again with START set. Three more characters in the out 3266 * and still no use of input ... To break this infinite loop we 3267 * remove TCL_ENCODING_START from the set of flags after the first 3268 * call (no condition is required, the later calls remove an unset 3269 * flag, which is a no-op). This causes the subsequent calls to 3270 * UtfToExternal to consume and convert the actual input. 3271 */ 3272 3273 statePtr->outputEncodingFlags &= ~TCL_ENCODING_START; 3274 /* 3275 * The following code must be executed only when result is not 0. 3276 */ 3277 if (result && ((stageRead + dstWrote) == 0)) { 3278 /* 3279 * We have an incomplete UTF-8 character at the end of the 3280 * staging buffer. It will get moved to the beginning of the 3281 * staging buffer followed by more bytes from src. 3282 */ 3283 3284 src -= stageLen; 3285 srcLen += stageLen; 3286 stageLen = 0; 3287 savedLF = 0; 3288 break; 3289 } 3290 bufPtr->nextAdded += dstWrote; 3291 if (bufPtr->nextAdded > bufPtr->bufLength) { 3292 /* 3293 * When translating from UTF-8 to external encoding, we 3294 * allowed the translation to produce a character that 3295 * crossed the end of the output buffer, so that we would 3296 * get a completely full buffer before flushing it. The 3297 * extra bytes will be moved to the beginning of the next 3298 * buffer. 3299 */ 3300 3301 saved = bufPtr->nextAdded - bufPtr->bufLength; 3302 memcpy((VOID *) safe, (VOID *) (dst + dstLen), (size_t) saved); 3303 bufPtr->nextAdded = bufPtr->bufLength; 3304 } 3305 if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) { 3306 return -1; 3307 } 3308 3309 total += dstWrote; 3310 stage += stageRead; 3311 stageLen -= stageRead; 3312 sawLF = 0; 3313 3314 consumedSomething = 1; 3315 3316 /* 3317 * If all translated characters are written to the buffer, 3318 * endEncoding is set to 0 because the escape sequence may be 3319 * output. 3320 */ 3321 3322 if ((stageLen + saved == 0) && (result == 0)) { 3323 endEncoding = 0; 3324 } 3325 } 3326 } 3327 3328 /* If nothing was written and it happened because there was no progress 3329 * in the UTF conversion, we throw an error. 3330 */ 3331 3332 if (!consumedSomething && (total == 0)) { 3333 Tcl_SetErrno (EINVAL); 3334 return -1; 3335 } 3336 return total; 3337} 3338 3339/* 3340 *--------------------------------------------------------------------------- 3341 * 3342 * TranslateOutputEOL -- 3343 * 3344 * Helper function for WriteBytes() and WriteChars(). Converts the 3345 * '\n' characters in the source buffer into the appropriate EOL 3346 * form specified by the output translation mode. 3347 * 3348 * EOL translation stops either when the source buffer is empty 3349 * or the output buffer is full. 3350 * 3351 * When converting to CRLF mode and there is only 1 byte left in 3352 * the output buffer, this routine stores the '\r' in the last 3353 * byte and then stores the '\n' in the byte just past the end of the 3354 * buffer. The caller is responsible for passing in a buffer that 3355 * is large enough to hold the extra byte. 3356 * 3357 * Results: 3358 * The return value is 1 if a '\n' was translated from the source 3359 * buffer, or 0 otherwise -- this can be used by the caller to 3360 * decide to flush a line-based channel even though the channel 3361 * buffer is not full. 3362 * 3363 * *dstLenPtr is filled with how many bytes of the output buffer 3364 * were used. As mentioned above, this can be one more that 3365 * the output buffer's specified length if a CRLF was stored. 3366 * 3367 * *srcLenPtr is filled with how many bytes of the source buffer 3368 * were consumed. 3369 * 3370 * Side effects: 3371 * It may be obvious, but bears mentioning that when converting 3372 * in CRLF mode (which requires two bytes of storage in the output 3373 * buffer), the number of bytes consumed from the source buffer 3374 * will be less than the number of bytes stored in the output buffer. 3375 * 3376 *--------------------------------------------------------------------------- 3377 */ 3378 3379static int 3380TranslateOutputEOL(statePtr, dst, src, dstLenPtr, srcLenPtr) 3381 ChannelState *statePtr; /* Channel being read, for translation and 3382 * buffering modes. */ 3383 char *dst; /* Output buffer filled with UTF-8 chars by 3384 * applying appropriate EOL translation to 3385 * source characters. */ 3386 CONST char *src; /* Source UTF-8 characters. */ 3387 int *dstLenPtr; /* On entry, the maximum length of output 3388 * buffer in bytes. On exit, the number of 3389 * bytes actually used in output buffer. */ 3390 int *srcLenPtr; /* On entry, the length of source buffer. 3391 * On exit, the number of bytes read from 3392 * the source buffer. */ 3393{ 3394 char *dstEnd; 3395 int srcLen, newlineFound; 3396 3397 newlineFound = 0; 3398 srcLen = *srcLenPtr; 3399 3400 switch (statePtr->outputTranslation) { 3401 case TCL_TRANSLATE_LF: { 3402 for (dstEnd = dst + srcLen; dst < dstEnd; ) { 3403 if (*src == '\n') { 3404 newlineFound = 1; 3405 } 3406 *dst++ = *src++; 3407 } 3408 *dstLenPtr = srcLen; 3409 break; 3410 } 3411 case TCL_TRANSLATE_CR: { 3412 for (dstEnd = dst + srcLen; dst < dstEnd;) { 3413 if (*src == '\n') { 3414 *dst++ = '\r'; 3415 newlineFound = 1; 3416 src++; 3417 } else { 3418 *dst++ = *src++; 3419 } 3420 } 3421 *dstLenPtr = srcLen; 3422 break; 3423 } 3424 case TCL_TRANSLATE_CRLF: { 3425 /* 3426 * Since this causes the number of bytes to grow, we 3427 * start off trying to put 'srcLen' bytes into the 3428 * output buffer, but allow it to store more bytes, as 3429 * long as there's still source bytes and room in the 3430 * output buffer. 3431 */ 3432 3433 char *dstStart, *dstMax; 3434 CONST char *srcStart; 3435 3436 dstStart = dst; 3437 dstMax = dst + *dstLenPtr; 3438 3439 srcStart = src; 3440 3441 if (srcLen < *dstLenPtr) { 3442 dstEnd = dst + srcLen; 3443 } else { 3444 dstEnd = dst + *dstLenPtr; 3445 } 3446 while (dst < dstEnd) { 3447 if (*src == '\n') { 3448 if (dstEnd < dstMax) { 3449 dstEnd++; 3450 } 3451 *dst++ = '\r'; 3452 newlineFound = 1; 3453 } 3454 *dst++ = *src++; 3455 } 3456 *srcLenPtr = src - srcStart; 3457 *dstLenPtr = dst - dstStart; 3458 break; 3459 } 3460 default: { 3461 break; 3462 } 3463 } 3464 return newlineFound; 3465} 3466 3467/* 3468 *--------------------------------------------------------------------------- 3469 * 3470 * CheckFlush -- 3471 * 3472 * Helper function for WriteBytes() and WriteChars(). If the 3473 * channel buffer is ready to be flushed, flush it. 3474 * 3475 * Results: 3476 * The return value is -1 if there was a problem flushing the 3477 * channel buffer, or 0 otherwise. 3478 * 3479 * Side effects: 3480 * The buffer will be recycled if it is flushed. 3481 * 3482 *--------------------------------------------------------------------------- 3483 */ 3484 3485static int 3486CheckFlush(chanPtr, bufPtr, newlineFlag) 3487 Channel *chanPtr; /* Channel being read, for buffering mode. */ 3488 ChannelBuffer *bufPtr; /* Channel buffer to possibly flush. */ 3489 int newlineFlag; /* Non-zero if a the channel buffer 3490 * contains a newline. */ 3491{ 3492 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 3493 /* 3494 * The current buffer is ready for output: 3495 * 1. if it is full. 3496 * 2. if it contains a newline and this channel is line-buffered. 3497 * 3. if it contains any output and this channel is unbuffered. 3498 */ 3499 3500 if ((statePtr->flags & BUFFER_READY) == 0) { 3501 if (bufPtr->nextAdded == bufPtr->bufLength) { 3502 statePtr->flags |= BUFFER_READY; 3503 } else if (statePtr->flags & CHANNEL_LINEBUFFERED) { 3504 if (newlineFlag != 0) { 3505 statePtr->flags |= BUFFER_READY; 3506 } 3507 } else if (statePtr->flags & CHANNEL_UNBUFFERED) { 3508 statePtr->flags |= BUFFER_READY; 3509 } 3510 } 3511 if (statePtr->flags & BUFFER_READY) { 3512 if (FlushChannel(NULL, chanPtr, 0) != 0) { 3513 return -1; 3514 } 3515 } 3516 return 0; 3517} 3518 3519/* 3520 *--------------------------------------------------------------------------- 3521 * 3522 * Tcl_Gets -- 3523 * 3524 * Reads a complete line of input from the channel into a Tcl_DString. 3525 * 3526 * Results: 3527 * Length of line read (in characters) or -1 if error, EOF, or blocked. 3528 * If -1, use Tcl_GetErrno() to retrieve the POSIX error code for the 3529 * error or condition that occurred. 3530 * 3531 * Side effects: 3532 * May flush output on the channel. May cause input to be consumed 3533 * from the channel. 3534 * 3535 *--------------------------------------------------------------------------- 3536 */ 3537 3538int 3539Tcl_Gets(chan, lineRead) 3540 Tcl_Channel chan; /* Channel from which to read. */ 3541 Tcl_DString *lineRead; /* The line read will be appended to this 3542 * DString as UTF-8 characters. The caller 3543 * must have initialized it and is responsible 3544 * for managing the storage. */ 3545{ 3546 Tcl_Obj *objPtr; 3547 int charsStored, length; 3548 char *string; 3549 3550 objPtr = Tcl_NewObj(); 3551 charsStored = Tcl_GetsObj(chan, objPtr); 3552 if (charsStored > 0) { 3553 string = Tcl_GetStringFromObj(objPtr, &length); 3554 Tcl_DStringAppend(lineRead, string, length); 3555 } 3556 Tcl_DecrRefCount(objPtr); 3557 return charsStored; 3558} 3559 3560/* 3561 *--------------------------------------------------------------------------- 3562 * 3563 * Tcl_GetsObj -- 3564 * 3565 * Accumulate input from the input channel until end-of-line or 3566 * end-of-file has been seen. Bytes read from the input channel 3567 * are converted to UTF-8 using the encoding specified by the 3568 * channel. 3569 * 3570 * Results: 3571 * Number of characters accumulated in the object or -1 if error, 3572 * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the 3573 * POSIX error code for the error or condition that occurred. 3574 * 3575 * Side effects: 3576 * Consumes input from the channel. 3577 * 3578 * On reading EOF, leave channel pointing at EOF char. 3579 * On reading EOL, leave channel pointing after EOL, but don't 3580 * return EOL in dst buffer. 3581 * 3582 *--------------------------------------------------------------------------- 3583 */ 3584 3585int 3586Tcl_GetsObj(chan, objPtr) 3587 Tcl_Channel chan; /* Channel from which to read. */ 3588 Tcl_Obj *objPtr; /* The line read will be appended to this 3589 * object as UTF-8 characters. */ 3590{ 3591 GetsState gs; 3592 Channel *chanPtr = (Channel *) chan; 3593 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 3594 ChannelBuffer *bufPtr; 3595 int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved; 3596 Tcl_Encoding encoding; 3597 char *dst, *dstEnd, *eol, *eof; 3598 Tcl_EncodingState oldState; 3599 3600 /* 3601 * This operation should occur at the top of a channel stack. 3602 */ 3603 3604 chanPtr = statePtr->topChanPtr; 3605 3606 if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { 3607 copiedTotal = -1; 3608 goto done; 3609 } 3610 3611 bufPtr = statePtr->inQueueHead; 3612 encoding = statePtr->encoding; 3613 3614 /* 3615 * Preserved so we can restore the channel's state in case we don't 3616 * find a newline in the available input. 3617 */ 3618 3619 Tcl_GetStringFromObj(objPtr, &oldLength); 3620 oldFlags = statePtr->inputEncodingFlags; 3621 oldState = statePtr->inputEncodingState; 3622 oldRemoved = BUFFER_PADDING; 3623 if (bufPtr != NULL) { 3624 oldRemoved = bufPtr->nextRemoved; 3625 } 3626 3627 /* 3628 * If there is no encoding, use "iso8859-1" -- Tcl_GetsObj() doesn't 3629 * produce ByteArray objects. To avoid circularity problems, 3630 * "iso8859-1" is builtin to Tcl. 3631 */ 3632 3633 if (encoding == NULL) { 3634 encoding = Tcl_GetEncoding(NULL, "iso8859-1"); 3635 } 3636 3637 /* 3638 * Object used by FilterInputBytes to keep track of how much data has 3639 * been consumed from the channel buffers. 3640 */ 3641 3642 gs.objPtr = objPtr; 3643 gs.dstPtr = &dst; 3644 gs.encoding = encoding; 3645 gs.bufPtr = bufPtr; 3646 gs.state = oldState; 3647 gs.rawRead = 0; 3648 gs.bytesWrote = 0; 3649 gs.charsWrote = 0; 3650 gs.totalChars = 0; 3651 3652 dst = objPtr->bytes + oldLength; 3653 dstEnd = dst; 3654 3655 skip = 0; 3656 eof = NULL; 3657 inEofChar = statePtr->inEofChar; 3658 3659 while (1) { 3660 if (dst >= dstEnd) { 3661 if (FilterInputBytes(chanPtr, &gs) != 0) { 3662 goto restore; 3663 } 3664 dstEnd = dst + gs.bytesWrote; 3665 } 3666 3667 /* 3668 * Remember if EOF char is seen, then look for EOL anyhow, because 3669 * the EOL might be before the EOF char. 3670 */ 3671 3672 if (inEofChar != '\0') { 3673 for (eol = dst; eol < dstEnd; eol++) { 3674 if (*eol == inEofChar) { 3675 dstEnd = eol; 3676 eof = eol; 3677 break; 3678 } 3679 } 3680 } 3681 3682 /* 3683 * On EOL, leave current file position pointing after the EOL, but 3684 * don't store the EOL in the output string. 3685 */ 3686 3687 switch (statePtr->inputTranslation) { 3688 case TCL_TRANSLATE_LF: { 3689 for (eol = dst; eol < dstEnd; eol++) { 3690 if (*eol == '\n') { 3691 skip = 1; 3692 goto goteol; 3693 } 3694 } 3695 break; 3696 } 3697 case TCL_TRANSLATE_CR: { 3698 for (eol = dst; eol < dstEnd; eol++) { 3699 if (*eol == '\r') { 3700 skip = 1; 3701 goto goteol; 3702 } 3703 } 3704 break; 3705 } 3706 case TCL_TRANSLATE_CRLF: { 3707 for (eol = dst; eol < dstEnd; eol++) { 3708 if (*eol == '\r') { 3709 eol++; 3710 if (eol >= dstEnd) { 3711 int offset; 3712 3713 offset = eol - objPtr->bytes; 3714 dst = dstEnd; 3715 if (FilterInputBytes(chanPtr, &gs) != 0) { 3716 goto restore; 3717 } 3718 dstEnd = dst + gs.bytesWrote; 3719 eol = objPtr->bytes + offset; 3720 if (eol >= dstEnd) { 3721 skip = 0; 3722 goto goteol; 3723 } 3724 } 3725 if (*eol == '\n') { 3726 eol--; 3727 skip = 2; 3728 goto goteol; 3729 } 3730 } 3731 } 3732 break; 3733 } 3734 case TCL_TRANSLATE_AUTO: { 3735 eol = dst; 3736 skip = 1; 3737 if (statePtr->flags & INPUT_SAW_CR) { 3738 statePtr->flags &= ~INPUT_SAW_CR; 3739 if (*eol == '\n') { 3740 /* 3741 * Skip the raw bytes that make up the '\n'. 3742 */ 3743 3744 char tmp[1 + TCL_UTF_MAX]; 3745 int rawRead; 3746 3747 bufPtr = gs.bufPtr; 3748 Tcl_ExternalToUtf(NULL, gs.encoding, 3749 bufPtr->buf + bufPtr->nextRemoved, 3750 gs.rawRead, statePtr->inputEncodingFlags, 3751 &gs.state, tmp, 1 + TCL_UTF_MAX, &rawRead, 3752 NULL, NULL); 3753 bufPtr->nextRemoved += rawRead; 3754 gs.rawRead -= rawRead; 3755 gs.bytesWrote--; 3756 gs.charsWrote--; 3757 memmove(dst, dst + 1, (size_t) (dstEnd - dst)); 3758 dstEnd--; 3759 } 3760 } 3761 for (eol = dst; eol < dstEnd; eol++) { 3762 if (*eol == '\r') { 3763 eol++; 3764 if (eol == dstEnd) { 3765 /* 3766 * If buffer ended on \r, peek ahead to see if a 3767 * \n is available. 3768 */ 3769 3770 int offset; 3771 3772 offset = eol - objPtr->bytes; 3773 dst = dstEnd; 3774 PeekAhead(chanPtr, &dstEnd, &gs); 3775 eol = objPtr->bytes + offset; 3776 if (eol >= dstEnd) { 3777 eol--; 3778 statePtr->flags |= INPUT_SAW_CR; 3779 goto goteol; 3780 } 3781 } 3782 if (*eol == '\n') { 3783 skip++; 3784 } 3785 eol--; 3786 goto goteol; 3787 } else if (*eol == '\n') { 3788 goto goteol; 3789 } 3790 } 3791 } 3792 } 3793 if (eof != NULL) { 3794 /* 3795 * EOF character was seen. On EOF, leave current file position 3796 * pointing at the EOF character, but don't store the EOF 3797 * character in the output string. 3798 */ 3799 3800 dstEnd = eof; 3801 statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); 3802 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 3803 } 3804 if (statePtr->flags & CHANNEL_EOF) { 3805 skip = 0; 3806 eol = dstEnd; 3807 if (eol == objPtr->bytes + oldLength) { 3808 /* 3809 * If we didn't append any bytes before encountering EOF, 3810 * caller needs to see -1. 3811 */ 3812 3813 Tcl_SetObjLength(objPtr, oldLength); 3814 CommonGetsCleanup(chanPtr, encoding); 3815 copiedTotal = -1; 3816 goto done; 3817 } 3818 goto goteol; 3819 } 3820 dst = dstEnd; 3821 } 3822 3823 /* 3824 * Found EOL or EOF, but the output buffer may now contain too many 3825 * UTF-8 characters. We need to know how many raw bytes correspond to 3826 * the number of UTF-8 characters we want, plus how many raw bytes 3827 * correspond to the character(s) making up EOL (if any), so we can 3828 * remove the correct number of bytes from the channel buffer. 3829 */ 3830 3831 goteol: 3832 bufPtr = gs.bufPtr; 3833 statePtr->inputEncodingState = gs.state; 3834 Tcl_ExternalToUtf(NULL, gs.encoding, bufPtr->buf + bufPtr->nextRemoved, 3835 gs.rawRead, statePtr->inputEncodingFlags, 3836 &statePtr->inputEncodingState, dst, 3837 eol - dst + skip + TCL_UTF_MAX, &gs.rawRead, NULL, 3838 &gs.charsWrote); 3839 bufPtr->nextRemoved += gs.rawRead; 3840 3841 /* 3842 * Recycle all the emptied buffers. 3843 */ 3844 3845 Tcl_SetObjLength(objPtr, eol - objPtr->bytes); 3846 CommonGetsCleanup(chanPtr, encoding); 3847 statePtr->flags &= ~CHANNEL_BLOCKED; 3848 copiedTotal = gs.totalChars + gs.charsWrote - skip; 3849 goto done; 3850 3851 /* 3852 * Couldn't get a complete line. This only happens if we get a error 3853 * reading from the channel or we are non-blocking and there wasn't 3854 * an EOL or EOF in the data available. 3855 */ 3856 3857 restore: 3858 bufPtr = statePtr->inQueueHead; 3859 bufPtr->nextRemoved = oldRemoved; 3860 3861 for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { 3862 bufPtr->nextRemoved = BUFFER_PADDING; 3863 } 3864 CommonGetsCleanup(chanPtr, encoding); 3865 3866 statePtr->inputEncodingState = oldState; 3867 statePtr->inputEncodingFlags = oldFlags; 3868 Tcl_SetObjLength(objPtr, oldLength); 3869 3870 /* 3871 * We didn't get a complete line so we need to indicate to UpdateInterest 3872 * that the gets blocked. It will wait for more data instead of firing 3873 * a timer, avoiding a busy wait. This is where we are assuming that the 3874 * next operation is a gets. No more file events will be delivered on 3875 * this channel until new data arrives or some operation is performed 3876 * on the channel (e.g. gets, read, fconfigure) that changes the blocking 3877 * state. Note that this means a file event will not be delivered even 3878 * though a read would be able to consume the buffered data. 3879 */ 3880 3881 statePtr->flags |= CHANNEL_NEED_MORE_DATA; 3882 copiedTotal = -1; 3883 3884 done: 3885 /* 3886 * Update the notifier state so we don't block while there is still 3887 * data in the buffers. 3888 */ 3889 3890 UpdateInterest(chanPtr); 3891 return copiedTotal; 3892} 3893 3894/* 3895 *--------------------------------------------------------------------------- 3896 * 3897 * FilterInputBytes -- 3898 * 3899 * Helper function for Tcl_GetsObj. Produces UTF-8 characters from 3900 * raw bytes read from the channel. 3901 * 3902 * Consumes available bytes from channel buffers. When channel 3903 * buffers are exhausted, reads more bytes from channel device into 3904 * a new channel buffer. It is the caller's responsibility to 3905 * free the channel buffers that have been exhausted. 3906 * 3907 * Results: 3908 * The return value is -1 if there was an error reading from the 3909 * channel, 0 otherwise. 3910 * 3911 * Side effects: 3912 * Status object keeps track of how much data from channel buffers 3913 * has been consumed and where UTF-8 bytes should be stored. 3914 * 3915 *--------------------------------------------------------------------------- 3916 */ 3917 3918static int 3919FilterInputBytes(chanPtr, gsPtr) 3920 Channel *chanPtr; /* Channel to read. */ 3921 GetsState *gsPtr; /* Current state of gets operation. */ 3922{ 3923 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 3924 ChannelBuffer *bufPtr; 3925 char *raw, *rawStart, *rawEnd; 3926 char *dst; 3927 int offset, toRead, dstNeeded, spaceLeft, result, rawLen, length; 3928 Tcl_Obj *objPtr; 3929#define ENCODING_LINESIZE 20 /* Lower bound on how many bytes to convert 3930 * at a time. Since we don't know a priori 3931 * how many bytes of storage this many source 3932 * bytes will use, we actually need at least 3933 * ENCODING_LINESIZE * TCL_MAX_UTF bytes of 3934 * room. */ 3935 3936 objPtr = gsPtr->objPtr; 3937 3938 /* 3939 * Subtract the number of bytes that were removed from channel buffer 3940 * during last call. 3941 */ 3942 3943 bufPtr = gsPtr->bufPtr; 3944 if (bufPtr != NULL) { 3945 bufPtr->nextRemoved += gsPtr->rawRead; 3946 if (bufPtr->nextRemoved >= bufPtr->nextAdded) { 3947 bufPtr = bufPtr->nextPtr; 3948 } 3949 } 3950 gsPtr->totalChars += gsPtr->charsWrote; 3951 3952 if ((bufPtr == NULL) || (bufPtr->nextAdded == BUFFER_PADDING)) { 3953 /* 3954 * All channel buffers were exhausted and the caller still hasn't 3955 * seen EOL. Need to read more bytes from the channel device. 3956 * Side effect is to allocate another channel buffer. 3957 */ 3958 3959 read: 3960 if (statePtr->flags & CHANNEL_BLOCKED) { 3961 if (statePtr->flags & CHANNEL_NONBLOCKING) { 3962 gsPtr->charsWrote = 0; 3963 gsPtr->rawRead = 0; 3964 return -1; 3965 } 3966 statePtr->flags &= ~CHANNEL_BLOCKED; 3967 } 3968 if (GetInput(chanPtr) != 0) { 3969 gsPtr->charsWrote = 0; 3970 gsPtr->rawRead = 0; 3971 return -1; 3972 } 3973 bufPtr = statePtr->inQueueTail; 3974 gsPtr->bufPtr = bufPtr; 3975 } 3976 3977 /* 3978 * Convert some of the bytes from the channel buffer to UTF-8. Space in 3979 * objPtr's string rep is used to hold the UTF-8 characters. Grow the 3980 * string rep if we need more space. 3981 */ 3982 3983 rawStart = bufPtr->buf + bufPtr->nextRemoved; 3984 raw = rawStart; 3985 rawEnd = bufPtr->buf + bufPtr->nextAdded; 3986 rawLen = rawEnd - rawStart; 3987 3988 dst = *gsPtr->dstPtr; 3989 offset = dst - objPtr->bytes; 3990 toRead = ENCODING_LINESIZE; 3991 if (toRead > rawLen) { 3992 toRead = rawLen; 3993 } 3994 dstNeeded = toRead * TCL_UTF_MAX + 1; 3995 spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1; 3996 if (dstNeeded > spaceLeft) { 3997 length = offset * 2; 3998 if (offset < dstNeeded) { 3999 length = offset + dstNeeded; 4000 } 4001 length += TCL_UTF_MAX + 1; 4002 Tcl_SetObjLength(objPtr, length); 4003 spaceLeft = length - offset; 4004 dst = objPtr->bytes + offset; 4005 *gsPtr->dstPtr = dst; 4006 } 4007 gsPtr->state = statePtr->inputEncodingState; 4008 result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen, 4009 statePtr->inputEncodingFlags, &statePtr->inputEncodingState, 4010 dst, spaceLeft, &gsPtr->rawRead, &gsPtr->bytesWrote, 4011 &gsPtr->charsWrote); 4012 4013 /* 4014 * Make sure that if we go through 'gets', that we reset the 4015 * TCL_ENCODING_START flag still. [Bug #523988] 4016 */ 4017 statePtr->inputEncodingFlags &= ~TCL_ENCODING_START; 4018 4019 if (result == TCL_CONVERT_MULTIBYTE) { 4020 /* 4021 * The last few bytes in this channel buffer were the start of a 4022 * multibyte sequence. If this buffer was full, then move them to 4023 * the next buffer so the bytes will be contiguous. 4024 */ 4025 4026 ChannelBuffer *nextPtr; 4027 int extra; 4028 4029 nextPtr = bufPtr->nextPtr; 4030 if (bufPtr->nextAdded < bufPtr->bufLength) { 4031 if (gsPtr->rawRead > 0) { 4032 /* 4033 * Some raw bytes were converted to UTF-8. Fall through, 4034 * returning those UTF-8 characters because a EOL might be 4035 * present in them. 4036 */ 4037 } else if (statePtr->flags & CHANNEL_EOF) { 4038 /* 4039 * There was a partial character followed by EOF on the 4040 * device. Fall through, returning that nothing was found. 4041 */ 4042 4043 bufPtr->nextRemoved = bufPtr->nextAdded; 4044 } else { 4045 /* 4046 * There are no more cached raw bytes left. See if we can 4047 * get some more. 4048 */ 4049 4050 goto read; 4051 } 4052 } else { 4053 if (nextPtr == NULL) { 4054 nextPtr = AllocChannelBuffer(statePtr->bufSize); 4055 bufPtr->nextPtr = nextPtr; 4056 statePtr->inQueueTail = nextPtr; 4057 } 4058 extra = rawLen - gsPtr->rawRead; 4059 memcpy((VOID *) (nextPtr->buf + BUFFER_PADDING - extra), 4060 (VOID *) (raw + gsPtr->rawRead), (size_t) extra); 4061 nextPtr->nextRemoved -= extra; 4062 bufPtr->nextAdded -= extra; 4063 } 4064 } 4065 4066 gsPtr->bufPtr = bufPtr; 4067 return 0; 4068} 4069 4070/* 4071 *--------------------------------------------------------------------------- 4072 * 4073 * PeekAhead -- 4074 * 4075 * Helper function used by Tcl_GetsObj(). Called when we've seen a 4076 * \r at the end of the UTF-8 string and want to look ahead one 4077 * character to see if it is a \n. 4078 * 4079 * Results: 4080 * *gsPtr->dstPtr is filled with a pointer to the start of the range of 4081 * UTF-8 characters that were found by peeking and *dstEndPtr is filled 4082 * with a pointer to the bytes just after the end of the range. 4083 * 4084 * Side effects: 4085 * If no more raw bytes were available in one of the channel buffers, 4086 * tries to perform a non-blocking read to get more bytes from the 4087 * channel device. 4088 * 4089 *--------------------------------------------------------------------------- 4090 */ 4091 4092static void 4093PeekAhead(chanPtr, dstEndPtr, gsPtr) 4094 Channel *chanPtr; /* The channel to read. */ 4095 char **dstEndPtr; /* Filled with pointer to end of new range 4096 * of UTF-8 characters. */ 4097 GetsState *gsPtr; /* Current state of gets operation. */ 4098{ 4099 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 4100 ChannelBuffer *bufPtr; 4101 Tcl_DriverBlockModeProc *blockModeProc; 4102 int bytesLeft; 4103 4104 bufPtr = gsPtr->bufPtr; 4105 4106 /* 4107 * If there's any more raw input that's still buffered, we'll peek into 4108 * that. Otherwise, only get more data from the channel driver if it 4109 * looks like there might actually be more data. The assumption is that 4110 * if the channel buffer is filled right up to the end, then there 4111 * might be more data to read. 4112 */ 4113 4114 blockModeProc = NULL; 4115 if (bufPtr->nextPtr == NULL) { 4116 bytesLeft = bufPtr->nextAdded - (bufPtr->nextRemoved + gsPtr->rawRead); 4117 if (bytesLeft == 0) { 4118 if (bufPtr->nextAdded < bufPtr->bufLength) { 4119 /* 4120 * Don't peek ahead if last read was short read. 4121 */ 4122 4123 goto cleanup; 4124 } 4125 if ((statePtr->flags & CHANNEL_NONBLOCKING) == 0) { 4126 blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr); 4127 if (blockModeProc == NULL) { 4128 /* 4129 * Don't peek ahead if cannot set non-blocking mode. 4130 */ 4131 4132 goto cleanup; 4133 } 4134 StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING); 4135 } 4136 } 4137 } 4138 if (FilterInputBytes(chanPtr, gsPtr) == 0) { 4139 *dstEndPtr = *gsPtr->dstPtr + gsPtr->bytesWrote; 4140 } 4141 if (blockModeProc != NULL) { 4142 StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING); 4143 } 4144 return; 4145 4146 cleanup: 4147 bufPtr->nextRemoved += gsPtr->rawRead; 4148 gsPtr->rawRead = 0; 4149 gsPtr->totalChars += gsPtr->charsWrote; 4150 gsPtr->bytesWrote = 0; 4151 gsPtr->charsWrote = 0; 4152} 4153 4154/* 4155 *--------------------------------------------------------------------------- 4156 * 4157 * CommonGetsCleanup -- 4158 * 4159 * Helper function for Tcl_GetsObj() to restore the channel after 4160 * a "gets" operation. 4161 * 4162 * Results: 4163 * None. 4164 * 4165 * Side effects: 4166 * Encoding may be freed. 4167 * 4168 *--------------------------------------------------------------------------- 4169 */ 4170 4171static void 4172CommonGetsCleanup(chanPtr, encoding) 4173 Channel *chanPtr; 4174 Tcl_Encoding encoding; 4175{ 4176 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 4177 ChannelBuffer *bufPtr, *nextPtr; 4178 4179 bufPtr = statePtr->inQueueHead; 4180 for ( ; bufPtr != NULL; bufPtr = nextPtr) { 4181 nextPtr = bufPtr->nextPtr; 4182 if (bufPtr->nextRemoved < bufPtr->nextAdded) { 4183 break; 4184 } 4185 RecycleBuffer(statePtr, bufPtr, 0); 4186 } 4187 statePtr->inQueueHead = bufPtr; 4188 if (bufPtr == NULL) { 4189 statePtr->inQueueTail = NULL; 4190 } else { 4191 /* 4192 * If any multi-byte characters were split across channel buffer 4193 * boundaries, the split-up bytes were moved to the next channel 4194 * buffer by FilterInputBytes(). Move the bytes back to their 4195 * original buffer because the caller could change the channel's 4196 * encoding which could change the interpretation of whether those 4197 * bytes really made up multi-byte characters after all. 4198 */ 4199 4200 nextPtr = bufPtr->nextPtr; 4201 for ( ; nextPtr != NULL; nextPtr = bufPtr->nextPtr) { 4202 int extra; 4203 4204 extra = bufPtr->bufLength - bufPtr->nextAdded; 4205 if (extra > 0) { 4206 memcpy((VOID *) (bufPtr->buf + bufPtr->nextAdded), 4207 (VOID *) (nextPtr->buf + BUFFER_PADDING - extra), 4208 (size_t) extra); 4209 bufPtr->nextAdded += extra; 4210 nextPtr->nextRemoved = BUFFER_PADDING; 4211 } 4212 bufPtr = nextPtr; 4213 } 4214 } 4215 if (statePtr->encoding == NULL) { 4216 Tcl_FreeEncoding(encoding); 4217 } 4218} 4219 4220/* 4221 *---------------------------------------------------------------------- 4222 * 4223 * Tcl_Read -- 4224 * 4225 * Reads a given number of bytes from a channel. EOL and EOF 4226 * translation is done on the bytes being read, so the the number 4227 * of bytes consumed from the channel may not be equal to the 4228 * number of bytes stored in the destination buffer. 4229 * 4230 * No encoding conversions are applied to the bytes being read. 4231 * 4232 * Results: 4233 * The number of bytes read, or -1 on error. Use Tcl_GetErrno() 4234 * to retrieve the error code for the error that occurred. 4235 * 4236 * Side effects: 4237 * May cause input to be buffered. 4238 * 4239 *---------------------------------------------------------------------- 4240 */ 4241 4242int 4243Tcl_Read(chan, dst, bytesToRead) 4244 Tcl_Channel chan; /* The channel from which to read. */ 4245 char *dst; /* Where to store input read. */ 4246 int bytesToRead; /* Maximum number of bytes to read. */ 4247{ 4248 Channel *chanPtr = (Channel *) chan; 4249 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 4250 4251 /* 4252 * This operation should occur at the top of a channel stack. 4253 */ 4254 4255 chanPtr = statePtr->topChanPtr; 4256 4257 if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { 4258 return -1; 4259 } 4260 4261 return DoRead(chanPtr, dst, bytesToRead); 4262} 4263 4264/* 4265 *---------------------------------------------------------------------- 4266 * 4267 * Tcl_ReadRaw -- 4268 * 4269 * Reads a given number of bytes from a channel. EOL and EOF 4270 * translation is done on the bytes being read, so the the number 4271 * of bytes consumed from the channel may not be equal to the 4272 * number of bytes stored in the destination buffer. 4273 * 4274 * No encoding conversions are applied to the bytes being read. 4275 * 4276 * Results: 4277 * The number of bytes read, or -1 on error. Use Tcl_GetErrno() 4278 * to retrieve the error code for the error that occurred. 4279 * 4280 * Side effects: 4281 * May cause input to be buffered. 4282 * 4283 *---------------------------------------------------------------------- 4284 */ 4285 4286int 4287Tcl_ReadRaw(chan, bufPtr, bytesToRead) 4288 Tcl_Channel chan; /* The channel from which to read. */ 4289 char *bufPtr; /* Where to store input read. */ 4290 int bytesToRead; /* Maximum number of bytes to read. */ 4291{ 4292 Channel *chanPtr = (Channel *) chan; 4293 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 4294 int nread, result; 4295 int copied, copiedNow; 4296 4297 /* 4298 * The check below does too much because it will reject a call to this 4299 * function with a channel which is part of an 'fcopy'. But we have to 4300 * allow this here or else the chaining in the transformation drivers 4301 * will fail with 'file busy' error instead of retrieving and 4302 * transforming the data to copy. 4303 * 4304 * We let the check procedure now believe that there is no fcopy in 4305 * progress. A better solution than this might be an additional flag 4306 * argument to switch off specific checks. 4307 */ 4308 4309 if (CheckChannelErrors(statePtr, TCL_READABLE | CHANNEL_RAW_MODE) != 0) { 4310 return -1; 4311 } 4312 4313 /* 4314 * Check for information in the push-back buffers. If there is 4315 * some, use it. Go to the driver only if there is none (anymore) 4316 * and the caller requests more bytes. 4317 */ 4318 4319 for (copied = 0; copied < bytesToRead; copied += copiedNow) { 4320 copiedNow = CopyBuffer(chanPtr, bufPtr + copied, 4321 bytesToRead - copied); 4322 if (copiedNow == 0) { 4323 if (statePtr->flags & CHANNEL_EOF) { 4324 goto done; 4325 } 4326 if (statePtr->flags & CHANNEL_BLOCKED) { 4327 if (statePtr->flags & CHANNEL_NONBLOCKING) { 4328 goto done; 4329 } 4330 statePtr->flags &= (~(CHANNEL_BLOCKED)); 4331 } 4332 4333#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 4334 /* [SF Tcl Bug 943274]. Better emulation of non-blocking 4335 * channels for channels without BlockModeProc, by keeping 4336 * track of true fileevents generated by the OS == Data 4337 * waiting and reading if and only if we are sure to have 4338 * data. 4339 */ 4340 4341 if ((statePtr->flags & CHANNEL_NONBLOCKING) && 4342 (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) && 4343 !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) { 4344 4345 /* We bypass the driver, it would block, as no data is available */ 4346 nread = -1; 4347 result = EWOULDBLOCK; 4348 } else { 4349#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 4350 /* 4351 * Now go to the driver to get as much as is possible to 4352 * fill the remaining request. Do all the error handling 4353 * by ourselves. The code was stolen from 'GetInput' and 4354 * slightly adapted (different return value here). 4355 * 4356 * The case of 'bytesToRead == 0' at this point cannot happen. 4357 */ 4358 4359 nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData, 4360 bufPtr + copied, bytesToRead - copied, &result); 4361#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 4362 } 4363#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 4364 if (nread > 0) { 4365 /* 4366 * If we get a short read, signal up that we may be 4367 * BLOCKED. We should avoid calling the driver because 4368 * on some platforms we will block in the low level 4369 * reading code even though the channel is set into 4370 * nonblocking mode. 4371 */ 4372 4373 if (nread < (bytesToRead - copied)) { 4374 statePtr->flags |= CHANNEL_BLOCKED; 4375 } 4376 4377#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 4378 if (nread <= (bytesToRead - copied)) { 4379 /* [SF Tcl Bug 943274] We have read the available 4380 * data, clear flag */ 4381 statePtr->flags &= ~CHANNEL_HAS_MORE_DATA; 4382 } 4383#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 4384 } else if (nread == 0) { 4385 statePtr->flags |= CHANNEL_EOF; 4386 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 4387 } else if (nread < 0) { 4388 if ((result == EWOULDBLOCK) || (result == EAGAIN)) { 4389 if (copied > 0) { 4390 /* 4391 * Information that was copied earlier has precedence 4392 * over EAGAIN/WOULDBLOCK handling. 4393 */ 4394 return copied; 4395 } 4396 4397 statePtr->flags |= CHANNEL_BLOCKED; 4398 result = EAGAIN; 4399 } 4400 4401 Tcl_SetErrno(result); 4402 return -1; 4403 } 4404 4405 return copied + nread; 4406 } 4407 } 4408 4409done: 4410 return copied; 4411} 4412 4413/* 4414 *--------------------------------------------------------------------------- 4415 * 4416 * Tcl_ReadChars -- 4417 * 4418 * Reads from the channel until the requested number of characters 4419 * have been seen, EOF is seen, or the channel would block. EOL 4420 * and EOF translation is done. If reading binary data, the raw 4421 * bytes are wrapped in a Tcl byte array object. Otherwise, the raw 4422 * bytes are converted to UTF-8 using the channel's current encoding 4423 * and stored in a Tcl string object. 4424 * 4425 * Results: 4426 * The number of characters read, or -1 on error. Use Tcl_GetErrno() 4427 * to retrieve the error code for the error that occurred. 4428 * 4429 * Side effects: 4430 * May cause input to be buffered. 4431 * 4432 *--------------------------------------------------------------------------- 4433 */ 4434 4435int 4436Tcl_ReadChars(chan, objPtr, toRead, appendFlag) 4437 Tcl_Channel chan; /* The channel to read. */ 4438 Tcl_Obj *objPtr; /* Input data is stored in this object. */ 4439 int toRead; /* Maximum number of characters to store, 4440 * or -1 to read all available data (up to EOF 4441 * or when channel blocks). */ 4442 int appendFlag; /* If non-zero, data read from the channel 4443 * will be appended to the object. Otherwise, 4444 * the data will replace the existing contents 4445 * of the object. */ 4446 4447{ 4448 Channel* chanPtr = (Channel *) chan; 4449 ChannelState* statePtr = chanPtr->state; /* state info for channel */ 4450 4451 /* 4452 * This operation should occur at the top of a channel stack. 4453 */ 4454 4455 chanPtr = statePtr->topChanPtr; 4456 4457 if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { 4458 /* 4459 * Update the notifier state so we don't block while there is still 4460 * data in the buffers. 4461 */ 4462 UpdateInterest(chanPtr); 4463 return -1; 4464 } 4465 4466 return DoReadChars (chanPtr, objPtr, toRead, appendFlag); 4467} 4468/* 4469 *--------------------------------------------------------------------------- 4470 * 4471 * DoReadChars -- 4472 * 4473 * Reads from the channel until the requested number of characters 4474 * have been seen, EOF is seen, or the channel would block. EOL 4475 * and EOF translation is done. If reading binary data, the raw 4476 * bytes are wrapped in a Tcl byte array object. Otherwise, the raw 4477 * bytes are converted to UTF-8 using the channel's current encoding 4478 * and stored in a Tcl string object. 4479 * 4480 * Results: 4481 * The number of characters read, or -1 on error. Use Tcl_GetErrno() 4482 * to retrieve the error code for the error that occurred. 4483 * 4484 * Side effects: 4485 * May cause input to be buffered. 4486 * 4487 *--------------------------------------------------------------------------- 4488 */ 4489 4490static int 4491DoReadChars(chanPtr, objPtr, toRead, appendFlag) 4492 Channel* chanPtr; /* The channel to read. */ 4493 Tcl_Obj *objPtr; /* Input data is stored in this object. */ 4494 int toRead; /* Maximum number of characters to store, 4495 * or -1 to read all available data (up to EOF 4496 * or when channel blocks). */ 4497 int appendFlag; /* If non-zero, data read from the channel 4498 * will be appended to the object. Otherwise, 4499 * the data will replace the existing contents 4500 * of the object. */ 4501 4502{ 4503 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 4504 ChannelBuffer *bufPtr; 4505 int offset, factor, copied, copiedNow, result; 4506 Tcl_Encoding encoding; 4507#define UTF_EXPANSION_FACTOR 1024 4508 4509 /* 4510 * This operation should occur at the top of a channel stack. 4511 */ 4512 4513 chanPtr = statePtr->topChanPtr; 4514 encoding = statePtr->encoding; 4515 factor = UTF_EXPANSION_FACTOR; 4516 4517 if (appendFlag == 0) { 4518 if (encoding == NULL) { 4519 Tcl_SetByteArrayLength(objPtr, 0); 4520 } else { 4521 Tcl_SetObjLength(objPtr, 0); 4522 /* 4523 * We're going to access objPtr->bytes directly, so 4524 * we must ensure that this is actually a string 4525 * object (otherwise it might have been pure Unicode). 4526 */ 4527 Tcl_GetString(objPtr); 4528 } 4529 offset = 0; 4530 } else { 4531 if (encoding == NULL) { 4532 Tcl_GetByteArrayFromObj(objPtr, &offset); 4533 } else { 4534 Tcl_GetStringFromObj(objPtr, &offset); 4535 } 4536 } 4537 4538 for (copied = 0; (unsigned) toRead > 0; ) { 4539 copiedNow = -1; 4540 if (statePtr->inQueueHead != NULL) { 4541 if (encoding == NULL) { 4542 copiedNow = ReadBytes(statePtr, objPtr, toRead, &offset); 4543 } else { 4544 copiedNow = ReadChars(statePtr, objPtr, toRead, &offset, 4545 &factor); 4546 } 4547 4548 /* 4549 * If the current buffer is empty recycle it. 4550 */ 4551 4552 bufPtr = statePtr->inQueueHead; 4553 if (bufPtr->nextRemoved == bufPtr->nextAdded) { 4554 ChannelBuffer *nextPtr; 4555 4556 nextPtr = bufPtr->nextPtr; 4557 RecycleBuffer(statePtr, bufPtr, 0); 4558 statePtr->inQueueHead = nextPtr; 4559 if (nextPtr == NULL) { 4560 statePtr->inQueueTail = NULL; 4561 } 4562 } 4563 } 4564 if (copiedNow < 0) { 4565 if (statePtr->flags & CHANNEL_EOF) { 4566 break; 4567 } 4568 if (statePtr->flags & CHANNEL_BLOCKED) { 4569 if (statePtr->flags & CHANNEL_NONBLOCKING) { 4570 break; 4571 } 4572 statePtr->flags &= ~CHANNEL_BLOCKED; 4573 } 4574 result = GetInput(chanPtr); 4575 if (result != 0) { 4576 if (result == EAGAIN) { 4577 break; 4578 } 4579 copied = -1; 4580 goto done; 4581 } 4582 } else { 4583 copied += copiedNow; 4584 toRead -= copiedNow; 4585 } 4586 } 4587 statePtr->flags &= ~CHANNEL_BLOCKED; 4588 if (encoding == NULL) { 4589 Tcl_SetByteArrayLength(objPtr, offset); 4590 } else { 4591 Tcl_SetObjLength(objPtr, offset); 4592 } 4593 4594 done: 4595 /* 4596 * Update the notifier state so we don't block while there is still 4597 * data in the buffers. 4598 */ 4599 4600 UpdateInterest(chanPtr); 4601 return copied; 4602} 4603/* 4604 *--------------------------------------------------------------------------- 4605 * 4606 * ReadBytes -- 4607 * 4608 * Reads from the channel until the requested number of bytes have 4609 * been seen, EOF is seen, or the channel would block. Bytes from 4610 * the channel are stored in objPtr as a ByteArray object. EOL 4611 * and EOF translation are done. 4612 * 4613 * 'bytesToRead' can safely be a very large number because 4614 * space is only allocated to hold data read from the channel 4615 * as needed. 4616 * 4617 * Results: 4618 * The return value is the number of bytes appended to the object 4619 * and *offsetPtr is filled with the total number of bytes in the 4620 * object (greater than the return value if there were already bytes 4621 * in the object). 4622 * 4623 * Side effects: 4624 * None. 4625 * 4626 *--------------------------------------------------------------------------- 4627 */ 4628 4629static int 4630ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr) 4631 ChannelState *statePtr; /* State of the channel to read. */ 4632 Tcl_Obj *objPtr; /* Input data is appended to this ByteArray 4633 * object. Its length is how much space 4634 * has been allocated to hold data, not how 4635 * many bytes of data have been stored in the 4636 * object. */ 4637 int bytesToRead; /* Maximum number of bytes to store, 4638 * or < 0 to get all available bytes. 4639 * Bytes are obtained from the first 4640 * buffer in the queue -- even if this number 4641 * is larger than the number of bytes 4642 * available in the first buffer, only the 4643 * bytes from the first buffer are 4644 * returned. */ 4645 int *offsetPtr; /* On input, contains how many bytes of 4646 * objPtr have been used to hold data. On 4647 * output, filled with how many bytes are now 4648 * being used. */ 4649{ 4650 int toRead, srcLen, offset, length, srcRead, dstWrote; 4651 ChannelBuffer *bufPtr; 4652 char *src, *dst; 4653 4654 offset = *offsetPtr; 4655 4656 bufPtr = statePtr->inQueueHead; 4657 src = bufPtr->buf + bufPtr->nextRemoved; 4658 srcLen = bufPtr->nextAdded - bufPtr->nextRemoved; 4659 4660 toRead = bytesToRead; 4661 if ((unsigned) toRead > (unsigned) srcLen) { 4662 toRead = srcLen; 4663 } 4664 4665 dst = (char *) Tcl_GetByteArrayFromObj(objPtr, &length); 4666 if (toRead > length - offset - 1) { 4667 /* 4668 * Double the existing size of the object or make enough room to 4669 * hold all the characters we may get from the source buffer, 4670 * whichever is larger. 4671 */ 4672 4673 length = offset * 2; 4674 if (offset < toRead) { 4675 length = offset + toRead + 1; 4676 } 4677 dst = (char *) Tcl_SetByteArrayLength(objPtr, length); 4678 } 4679 dst += offset; 4680 4681 if (statePtr->flags & INPUT_NEED_NL) { 4682 statePtr->flags &= ~INPUT_NEED_NL; 4683 if ((srcLen == 0) || (*src != '\n')) { 4684 *dst = '\r'; 4685 *offsetPtr += 1; 4686 return 1; 4687 } 4688 *dst++ = '\n'; 4689 src++; 4690 srcLen--; 4691 toRead--; 4692 } 4693 4694 srcRead = srcLen; 4695 dstWrote = toRead; 4696 if (TranslateInputEOL(statePtr, dst, src, &dstWrote, &srcRead) != 0) { 4697 if (dstWrote == 0) { 4698 return -1; 4699 } 4700 } 4701 bufPtr->nextRemoved += srcRead; 4702 *offsetPtr += dstWrote; 4703 return dstWrote; 4704} 4705 4706/* 4707 *--------------------------------------------------------------------------- 4708 * 4709 * ReadChars -- 4710 * 4711 * Reads from the channel until the requested number of UTF-8 4712 * characters have been seen, EOF is seen, or the channel would 4713 * block. Raw bytes from the channel are converted to UTF-8 4714 * and stored in objPtr. EOL and EOF translation is done. 4715 * 4716 * 'charsToRead' can safely be a very large number because 4717 * space is only allocated to hold data read from the channel 4718 * as needed. 4719 * 4720 * Results: 4721 * The return value is the number of characters appended to 4722 * the object, *offsetPtr is filled with the number of bytes that 4723 * were appended, and *factorPtr is filled with the expansion 4724 * factor used to guess how many bytes of UTF-8 to allocate to 4725 * hold N source bytes. 4726 * 4727 * Side effects: 4728 * None. 4729 * 4730 *--------------------------------------------------------------------------- 4731 */ 4732 4733static int 4734ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr) 4735 ChannelState *statePtr; /* State of channel to read. */ 4736 Tcl_Obj *objPtr; /* Input data is appended to this object. 4737 * objPtr->length is how much space has been 4738 * allocated to hold data, not how many bytes 4739 * of data have been stored in the object. */ 4740 int charsToRead; /* Maximum number of characters to store, 4741 * or -1 to get all available characters. 4742 * Characters are obtained from the first 4743 * buffer in the queue -- even if this number 4744 * is larger than the number of characters 4745 * available in the first buffer, only the 4746 * characters from the first buffer are 4747 * returned. */ 4748 int *offsetPtr; /* On input, contains how many bytes of 4749 * objPtr have been used to hold data. On 4750 * output, filled with how many bytes are now 4751 * being used. */ 4752 int *factorPtr; /* On input, contains a guess of how many 4753 * bytes need to be allocated to hold the 4754 * result of converting N source bytes to 4755 * UTF-8. On output, contains another guess 4756 * based on the data seen so far. */ 4757{ 4758 int toRead, factor, offset, spaceLeft, length, srcLen, dstNeeded; 4759 int srcRead, dstWrote, numChars, dstRead; 4760 ChannelBuffer *bufPtr; 4761 char *src, *dst; 4762 Tcl_EncodingState oldState; 4763 int encEndFlagSuppressed = 0; 4764 4765 factor = *factorPtr; 4766 offset = *offsetPtr; 4767 4768 bufPtr = statePtr->inQueueHead; 4769 src = bufPtr->buf + bufPtr->nextRemoved; 4770 srcLen = bufPtr->nextAdded - bufPtr->nextRemoved; 4771 4772 toRead = charsToRead; 4773 if ((unsigned)toRead > (unsigned)srcLen) { 4774 toRead = srcLen; 4775 } 4776 4777 /* 4778 * 'factor' is how much we guess that the bytes in the source buffer 4779 * will expand when converted to UTF-8 chars. This guess comes from 4780 * analyzing how many characters were produced by the previous 4781 * pass. 4782 */ 4783 4784 dstNeeded = toRead * factor / UTF_EXPANSION_FACTOR; 4785 spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1; 4786 4787 if (dstNeeded > spaceLeft) { 4788 /* 4789 * Double the existing size of the object or make enough room to 4790 * hold all the characters we want from the source buffer, 4791 * whichever is larger. 4792 */ 4793 4794 length = offset * 2; 4795 if (offset < dstNeeded) { 4796 length = offset + dstNeeded; 4797 } 4798 spaceLeft = length - offset; 4799 length += TCL_UTF_MAX + 1; 4800 Tcl_SetObjLength(objPtr, length); 4801 } 4802 if (toRead == srcLen) { 4803 /* 4804 * Want to convert the whole buffer in one pass. If we have 4805 * enough space, convert it using all available space in object 4806 * rather than using the factor. 4807 */ 4808 4809 dstNeeded = spaceLeft; 4810 } 4811 dst = objPtr->bytes + offset; 4812 4813 /* 4814 * SF Tcl Bug 1462248 4815 * The cause of the crash reported in the referenced bug is this: 4816 * 4817 * - ReadChars, called with a single buffer, with a incomplete 4818 * multi-byte character at the end (only the first byte of it). 4819 * - Encoding translation fails, asks for more data 4820 * - Data is read, and eof is reached, TCL_ENCODING_END (TEE) is set. 4821 * - ReadChar is called again, converts the first buffer, but due 4822 * to TEE it does not check for incomplete multi-byte data, and the 4823 * character just after the end of the first buffer is a valid 4824 * completion of the multi-byte header in the actual buffer. The 4825 * conversion reads more characters from the buffer then present. 4826 * This causes nextRemoved to overshoot nextAdded and the next 4827 * reads compute a negative srcLen, cause further translations to 4828 * fail, causing copying of data into the next buffer using bad 4829 * arguments, causing the mecpy for to eventually fail. 4830 * 4831 * In the end it is a memory access bug spiraling out of control 4832 * if the conditions are _just so_. And ultimate cause is that TEE 4833 * is given to a conversion where it should not. TEE signals that 4834 * this is the last buffer. Except in our case it is not. 4835 * 4836 * My solution is to suppress TEE if the first buffer is not the 4837 * last. We will eventually need it given that EOF has been 4838 * reached, but not right now. This is what the new flag 4839 * "endEncSuppressFlag" is for. 4840 * 4841 * The bug in 'Tcl_Utf2UtfProc' where it read from memory behind 4842 * the actual buffer has been fixed as well, and fixes the problem 4843 * with the crash too, but this would still allow the generic 4844 * layer to accidentially break a multi-byte sequence if the 4845 * conditions are just right, because again the ExternalToUtf 4846 * would be successful where it should not. 4847 */ 4848 4849 if ((statePtr->inputEncodingFlags & TCL_ENCODING_END) && 4850 (bufPtr->nextPtr != NULL)) { 4851 4852 /* TEE is set for a buffer which is not the last. Squash it 4853 * for now, and restore it later, before yielding control to 4854 * our caller. 4855 */ 4856 4857 statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; 4858 encEndFlagSuppressed = 1; 4859 } 4860 4861 oldState = statePtr->inputEncodingState; 4862 if (statePtr->flags & INPUT_NEED_NL) { 4863 /* 4864 * We want a '\n' because the last character we saw was '\r'. 4865 */ 4866 4867 statePtr->flags &= ~INPUT_NEED_NL; 4868 Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen, 4869 statePtr->inputEncodingFlags, &statePtr->inputEncodingState, 4870 dst, TCL_UTF_MAX + 1, &srcRead, &dstWrote, &numChars); 4871 if ((dstWrote > 0) && (*dst == '\n')) { 4872 /* 4873 * The next char was a '\n'. Consume it and produce a '\n'. 4874 */ 4875 4876 bufPtr->nextRemoved += srcRead; 4877 } else { 4878 /* 4879 * The next char was not a '\n'. Produce a '\r'. 4880 */ 4881 4882 *dst = '\r'; 4883 } 4884 statePtr->inputEncodingFlags &= ~TCL_ENCODING_START; 4885 *offsetPtr += 1; 4886 4887 if (encEndFlagSuppressed) { 4888 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 4889 } 4890 return 1; 4891 } 4892 4893 Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen, 4894 statePtr->inputEncodingFlags, &statePtr->inputEncodingState, dst, 4895 dstNeeded + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars); 4896 4897 if (encEndFlagSuppressed) { 4898 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 4899 } 4900 4901 if (srcRead == 0) { 4902 /* 4903 * Not enough bytes in src buffer to make a complete char. Copy 4904 * the bytes to the next buffer to make a new contiguous string, 4905 * then tell the caller to fill the buffer with more bytes. 4906 */ 4907 4908 ChannelBuffer *nextPtr; 4909 4910 nextPtr = bufPtr->nextPtr; 4911 if (nextPtr == NULL) { 4912 if (srcLen > 0) { 4913 /* 4914 * There isn't enough data in the buffers to complete the next 4915 * character, so we need to wait for more data before the next 4916 * file event can be delivered. 4917 * 4918 * SF #478856. 4919 * 4920 * The exception to this is if the input buffer was 4921 * completely empty before we tried to convert its 4922 * contents. Nothing in, nothing out, and no incomplete 4923 * character data. The conversion before the current one 4924 * was complete. 4925 */ 4926 4927 statePtr->flags |= CHANNEL_NEED_MORE_DATA; 4928 } 4929 return -1; 4930 } 4931 4932 /* Space is made at the beginning of the buffer to copy the 4933 * previous unused bytes there. Check first if the buffer we 4934 * are using actually has enough space at its beginning for 4935 * the data we are copying. Because if not we will write over the 4936 * buffer management information, especially the 'nextPtr'. 4937 * 4938 * Note that the BUFFER_PADDING (See AllocChannelBuffer) is 4939 * used to prevent exactly this situation. I.e. it should 4940 * never happen. Therefore it is ok to panic should it happen 4941 * despite the precautions. 4942 */ 4943 4944 if (nextPtr->nextRemoved - srcLen < 0) { 4945 Tcl_Panic ("Buffer Underflow, BUFFER_PADDING not enough"); 4946 } 4947 4948 nextPtr->nextRemoved -= srcLen; 4949 memcpy((VOID *) (nextPtr->buf + nextPtr->nextRemoved), (VOID *) src, 4950 (size_t) srcLen); 4951 RecycleBuffer(statePtr, bufPtr, 0); 4952 statePtr->inQueueHead = nextPtr; 4953 return ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr); 4954 } 4955 4956 dstRead = dstWrote; 4957 if (TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead) != 0) { 4958 /* 4959 * Hit EOF char. How many bytes of src correspond to where the 4960 * EOF was located in dst? Run the conversion again with an 4961 * output buffer just big enough to hold the data so we can 4962 * get the correct value for srcRead. 4963 */ 4964 4965 if (dstWrote == 0) { 4966 return -1; 4967 } 4968 statePtr->inputEncodingState = oldState; 4969 Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen, 4970 statePtr->inputEncodingFlags, &statePtr->inputEncodingState, 4971 dst, dstRead + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars); 4972 TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead); 4973 } 4974 4975 /* 4976 * The number of characters that we got may be less than the number 4977 * that we started with because "\r\n" sequences may have been 4978 * turned into just '\n' in dst. 4979 */ 4980 4981 numChars -= (dstRead - dstWrote); 4982 4983 if ((unsigned) numChars > (unsigned) toRead) { 4984 /* 4985 * Got too many chars. 4986 */ 4987 4988 CONST char *eof; 4989 4990 eof = Tcl_UtfAtIndex(dst, toRead); 4991 statePtr->inputEncodingState = oldState; 4992 Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen, 4993 statePtr->inputEncodingFlags, &statePtr->inputEncodingState, 4994 dst, eof - dst + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars); 4995 dstRead = dstWrote; 4996 TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead); 4997 numChars -= (dstRead - dstWrote); 4998 } 4999 statePtr->inputEncodingFlags &= ~TCL_ENCODING_START; 5000 5001 bufPtr->nextRemoved += srcRead; 5002 if (dstWrote > srcRead + 1) { 5003 *factorPtr = dstWrote * UTF_EXPANSION_FACTOR / srcRead; 5004 } 5005 *offsetPtr += dstWrote; 5006 return numChars; 5007} 5008 5009/* 5010 *--------------------------------------------------------------------------- 5011 * 5012 * TranslateInputEOL -- 5013 * 5014 * Perform input EOL and EOF translation on the source buffer, 5015 * leaving the translated result in the destination buffer. 5016 * 5017 * Results: 5018 * The return value is 1 if the EOF character was found when copying 5019 * bytes to the destination buffer, 0 otherwise. 5020 * 5021 * Side effects: 5022 * None. 5023 * 5024 *--------------------------------------------------------------------------- 5025 */ 5026 5027static int 5028TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr) 5029 ChannelState *statePtr; /* Channel being read, for EOL translation 5030 * and EOF character. */ 5031 char *dstStart; /* Output buffer filled with chars by 5032 * applying appropriate EOL translation to 5033 * source characters. */ 5034 CONST char *srcStart; /* Source characters. */ 5035 int *dstLenPtr; /* On entry, the maximum length of output 5036 * buffer in bytes; must be <= *srcLenPtr. On 5037 * exit, the number of bytes actually used in 5038 * output buffer. */ 5039 int *srcLenPtr; /* On entry, the length of source buffer. 5040 * On exit, the number of bytes read from 5041 * the source buffer. */ 5042{ 5043 int dstLen, srcLen, inEofChar; 5044 CONST char *eof; 5045 5046 dstLen = *dstLenPtr; 5047 5048 eof = NULL; 5049 inEofChar = statePtr->inEofChar; 5050 if (inEofChar != '\0') { 5051 /* 5052 * Find EOF in translated buffer then compress out the EOL. The 5053 * source buffer may be much longer than the destination buffer -- 5054 * we only want to return EOF if the EOF has been copied to the 5055 * destination buffer. 5056 */ 5057 5058 CONST char *src, *srcMax; 5059 5060 srcMax = srcStart + *srcLenPtr; 5061 for (src = srcStart; src < srcMax; src++) { 5062 if (*src == inEofChar) { 5063 eof = src; 5064 srcLen = src - srcStart; 5065 if (srcLen < dstLen) { 5066 dstLen = srcLen; 5067 } 5068 *srcLenPtr = srcLen; 5069 break; 5070 } 5071 } 5072 } 5073 switch (statePtr->inputTranslation) { 5074 case TCL_TRANSLATE_LF: { 5075 if (dstStart != srcStart) { 5076 memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen); 5077 } 5078 srcLen = dstLen; 5079 break; 5080 } 5081 case TCL_TRANSLATE_CR: { 5082 char *dst, *dstEnd; 5083 5084 if (dstStart != srcStart) { 5085 memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen); 5086 } 5087 dstEnd = dstStart + dstLen; 5088 for (dst = dstStart; dst < dstEnd; dst++) { 5089 if (*dst == '\r') { 5090 *dst = '\n'; 5091 } 5092 } 5093 srcLen = dstLen; 5094 break; 5095 } 5096 case TCL_TRANSLATE_CRLF: { 5097 char *dst; 5098 CONST char *src, *srcEnd, *srcMax; 5099 5100 dst = dstStart; 5101 src = srcStart; 5102 srcEnd = srcStart + dstLen; 5103 srcMax = srcStart + *srcLenPtr; 5104 5105 for ( ; src < srcEnd; ) { 5106 if (*src == '\r') { 5107 src++; 5108 if (src >= srcMax) { 5109 statePtr->flags |= INPUT_NEED_NL; 5110 } else if (*src == '\n') { 5111 *dst++ = *src++; 5112 } else { 5113 *dst++ = '\r'; 5114 } 5115 } else { 5116 *dst++ = *src++; 5117 } 5118 } 5119 srcLen = src - srcStart; 5120 dstLen = dst - dstStart; 5121 break; 5122 } 5123 case TCL_TRANSLATE_AUTO: { 5124 char *dst; 5125 CONST char *src, *srcEnd, *srcMax; 5126 5127 dst = dstStart; 5128 src = srcStart; 5129 srcEnd = srcStart + dstLen; 5130 srcMax = srcStart + *srcLenPtr; 5131 5132 if ((statePtr->flags & INPUT_SAW_CR) && (src < srcMax)) { 5133 if (*src == '\n') { 5134 src++; 5135 } 5136 statePtr->flags &= ~INPUT_SAW_CR; 5137 } 5138 for ( ; src < srcEnd; ) { 5139 if (*src == '\r') { 5140 src++; 5141 if (src >= srcMax) { 5142 statePtr->flags |= INPUT_SAW_CR; 5143 } else if (*src == '\n') { 5144 if (srcEnd < srcMax) { 5145 srcEnd++; 5146 } 5147 src++; 5148 } 5149 *dst++ = '\n'; 5150 } else { 5151 *dst++ = *src++; 5152 } 5153 } 5154 srcLen = src - srcStart; 5155 dstLen = dst - dstStart; 5156 break; 5157 } 5158 default: { /* lint. */ 5159 return 0; 5160 } 5161 } 5162 *dstLenPtr = dstLen; 5163 5164 if ((eof != NULL) && (srcStart + srcLen >= eof)) { 5165 /* 5166 * EOF character was seen in EOL translated range. Leave current 5167 * file position pointing at the EOF character, but don't store the 5168 * EOF character in the output string. 5169 */ 5170 5171 statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); 5172 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 5173 statePtr->flags &= ~(INPUT_SAW_CR | INPUT_NEED_NL); 5174 return 1; 5175 } 5176 5177 *srcLenPtr = srcLen; 5178 return 0; 5179} 5180 5181/* 5182 *---------------------------------------------------------------------- 5183 * 5184 * Tcl_Ungets -- 5185 * 5186 * Causes the supplied string to be added to the input queue of 5187 * the channel, at either the head or tail of the queue. 5188 * 5189 * Results: 5190 * The number of bytes stored in the channel, or -1 on error. 5191 * 5192 * Side effects: 5193 * Adds input to the input queue of a channel. 5194 * 5195 *---------------------------------------------------------------------- 5196 */ 5197 5198int 5199Tcl_Ungets(chan, str, len, atEnd) 5200 Tcl_Channel chan; /* The channel for which to add the input. */ 5201 CONST char *str; /* The input itself. */ 5202 int len; /* The length of the input. */ 5203 int atEnd; /* If non-zero, add at end of queue; otherwise 5204 * add at head of queue. */ 5205{ 5206 Channel *chanPtr; /* The real IO channel. */ 5207 ChannelState *statePtr; /* State of actual channel. */ 5208 ChannelBuffer *bufPtr; /* Buffer to contain the data. */ 5209 int i, flags; 5210 5211 chanPtr = (Channel *) chan; 5212 statePtr = chanPtr->state; 5213 5214 /* 5215 * This operation should occur at the top of a channel stack. 5216 */ 5217 5218 chanPtr = statePtr->topChanPtr; 5219 5220 /* 5221 * CheckChannelErrors clears too many flag bits in this one case. 5222 */ 5223 5224 flags = statePtr->flags; 5225 if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { 5226 len = -1; 5227 goto done; 5228 } 5229 statePtr->flags = flags; 5230 5231 /* 5232 * If we have encountered a sticky EOF, just punt without storing. 5233 * (sticky EOF is set if we have seen the input eofChar, to prevent 5234 * reading beyond the eofChar). Otherwise, clear the EOF flags, and 5235 * clear the BLOCKED bit. We want to discover these conditions anew 5236 * in each operation. 5237 */ 5238 5239 if (statePtr->flags & CHANNEL_STICKY_EOF) { 5240 goto done; 5241 } 5242 statePtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF)); 5243 5244 bufPtr = AllocChannelBuffer(len); 5245 for (i = 0; i < len; i++) { 5246 bufPtr->buf[bufPtr->nextAdded++] = str[i]; 5247 } 5248 5249 if (statePtr->inQueueHead == (ChannelBuffer *) NULL) { 5250 bufPtr->nextPtr = (ChannelBuffer *) NULL; 5251 statePtr->inQueueHead = bufPtr; 5252 statePtr->inQueueTail = bufPtr; 5253 } else if (atEnd) { 5254 bufPtr->nextPtr = (ChannelBuffer *) NULL; 5255 statePtr->inQueueTail->nextPtr = bufPtr; 5256 statePtr->inQueueTail = bufPtr; 5257 } else { 5258 bufPtr->nextPtr = statePtr->inQueueHead; 5259 statePtr->inQueueHead = bufPtr; 5260 } 5261 5262 done: 5263 /* 5264 * Update the notifier state so we don't block while there is still 5265 * data in the buffers. 5266 */ 5267 5268 UpdateInterest(chanPtr); 5269 return len; 5270} 5271 5272/* 5273 *---------------------------------------------------------------------- 5274 * 5275 * Tcl_Flush -- 5276 * 5277 * Flushes output data on a channel. 5278 * 5279 * Results: 5280 * A standard Tcl result. 5281 * 5282 * Side effects: 5283 * May flush output queued on this channel. 5284 * 5285 *---------------------------------------------------------------------- 5286 */ 5287 5288int 5289Tcl_Flush(chan) 5290 Tcl_Channel chan; /* The Channel to flush. */ 5291{ 5292 int result; /* Of calling FlushChannel. */ 5293 Channel *chanPtr = (Channel *) chan; /* The actual channel. */ 5294 ChannelState *statePtr = chanPtr->state; /* State of actual channel. */ 5295 5296 /* 5297 * This operation should occur at the top of a channel stack. 5298 */ 5299 5300 chanPtr = statePtr->topChanPtr; 5301 5302 if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { 5303 return -1; 5304 } 5305 5306 /* 5307 * Force current output buffer to be output also. 5308 */ 5309 5310 if ((statePtr->curOutPtr != NULL) 5311 && (statePtr->curOutPtr->nextAdded > 0)) { 5312 statePtr->flags |= BUFFER_READY; 5313 } 5314 5315 result = FlushChannel(NULL, chanPtr, 0); 5316 if (result != 0) { 5317 return TCL_ERROR; 5318 } 5319 5320 return TCL_OK; 5321} 5322 5323/* 5324 *---------------------------------------------------------------------- 5325 * 5326 * DiscardInputQueued -- 5327 * 5328 * Discards any input read from the channel but not yet consumed 5329 * by Tcl reading commands. 5330 * 5331 * Results: 5332 * None. 5333 * 5334 * Side effects: 5335 * May discard input from the channel. If discardLastBuffer is zero, 5336 * leaves one buffer in place for back-filling. 5337 * 5338 *---------------------------------------------------------------------- 5339 */ 5340 5341static void 5342DiscardInputQueued(statePtr, discardSavedBuffers) 5343 ChannelState *statePtr; /* Channel on which to discard 5344 * the queued input. */ 5345 int discardSavedBuffers; /* If non-zero, discard all buffers including 5346 * last one. */ 5347{ 5348 ChannelBuffer *bufPtr, *nxtPtr; /* Loop variables. */ 5349 5350 bufPtr = statePtr->inQueueHead; 5351 statePtr->inQueueHead = (ChannelBuffer *) NULL; 5352 statePtr->inQueueTail = (ChannelBuffer *) NULL; 5353 for (; bufPtr != (ChannelBuffer *) NULL; bufPtr = nxtPtr) { 5354 nxtPtr = bufPtr->nextPtr; 5355 RecycleBuffer(statePtr, bufPtr, discardSavedBuffers); 5356 } 5357 5358 /* 5359 * If discardSavedBuffers is nonzero, must also discard any previously 5360 * saved buffer in the saveInBufPtr field. 5361 */ 5362 5363 if (discardSavedBuffers) { 5364 if (statePtr->saveInBufPtr != (ChannelBuffer *) NULL) { 5365 ckfree((char *) statePtr->saveInBufPtr); 5366 statePtr->saveInBufPtr = (ChannelBuffer *) NULL; 5367 } 5368 } 5369} 5370 5371/* 5372 *--------------------------------------------------------------------------- 5373 * 5374 * GetInput -- 5375 * 5376 * Reads input data from a device into a channel buffer. 5377 * 5378 * Results: 5379 * The return value is the Posix error code if an error occurred while 5380 * reading from the file, or 0 otherwise. 5381 * 5382 * Side effects: 5383 * Reads from the underlying device. 5384 * 5385 *--------------------------------------------------------------------------- 5386 */ 5387 5388static int 5389GetInput(chanPtr) 5390 Channel *chanPtr; /* Channel to read input from. */ 5391{ 5392 int toRead; /* How much to read? */ 5393 int result; /* Of calling driver. */ 5394 int nread; /* How much was read from channel? */ 5395 ChannelBuffer *bufPtr; /* New buffer to add to input queue. */ 5396 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 5397 5398 /* 5399 * Prevent reading from a dead channel -- a channel that has been closed 5400 * but not yet deallocated, which can happen if the exit handler for 5401 * channel cleanup has run but the channel is still registered in some 5402 * interpreter. 5403 */ 5404 5405 if (CheckForDeadChannel(NULL, statePtr)) { 5406 return EINVAL; 5407 } 5408 5409 /* 5410 * First check for more buffers in the pushback area of the 5411 * topmost channel in the stack and use them. They can be the 5412 * result of a transformation which went away without reading all 5413 * the information placed in the area when it was stacked. 5414 * 5415 * Two possibilities for the state: No buffers in it, or a single 5416 * empty buffer. In the latter case we can recycle it now. 5417 */ 5418 5419 if (chanPtr->inQueueHead != (ChannelBuffer*) NULL) { 5420 if (statePtr->inQueueHead != (ChannelBuffer*) NULL) { 5421 RecycleBuffer(statePtr, statePtr->inQueueHead, 0); 5422 statePtr->inQueueHead = (ChannelBuffer*) NULL; 5423 } 5424 5425 statePtr->inQueueHead = chanPtr->inQueueHead; 5426 statePtr->inQueueTail = chanPtr->inQueueTail; 5427 chanPtr->inQueueHead = (ChannelBuffer*) NULL; 5428 chanPtr->inQueueTail = (ChannelBuffer*) NULL; 5429 return 0; 5430 } 5431 5432 /* 5433 * Nothing in the pushback area, fall back to the usual handling 5434 * (driver, etc.) 5435 */ 5436 5437 /* 5438 * See if we can fill an existing buffer. If we can, read only 5439 * as much as will fit in it. Otherwise allocate a new buffer, 5440 * add it to the input queue and attempt to fill it to the max. 5441 */ 5442 5443 bufPtr = statePtr->inQueueTail; 5444 if ((bufPtr != NULL) && (bufPtr->nextAdded < bufPtr->bufLength)) { 5445 toRead = bufPtr->bufLength - bufPtr->nextAdded; 5446 } else { 5447 bufPtr = statePtr->saveInBufPtr; 5448 statePtr->saveInBufPtr = NULL; 5449 5450 /* 5451 * Check the actual buffersize against the requested 5452 * buffersize. Buffers which are smaller than requested are 5453 * squashed. This is done to honor dynamic changes of the 5454 * buffersize made by the user. 5455 */ 5456 5457 if ((bufPtr != NULL) && ((bufPtr->bufLength - BUFFER_PADDING) < statePtr->bufSize)) { 5458 ckfree((char *) bufPtr); 5459 bufPtr = NULL; 5460 } 5461 5462 if (bufPtr == NULL) { 5463 bufPtr = AllocChannelBuffer(statePtr->bufSize); 5464 } 5465 bufPtr->nextPtr = (ChannelBuffer *) NULL; 5466 5467 /* SF #427196: Use the actual size of the buffer to determine 5468 * the number of bytes to read from the channel and not the 5469 * size for new buffers. They can be different if the 5470 * buffersize was changed between reads. 5471 * 5472 * Note: This affects performance negatively if the buffersize 5473 * was extended but this small buffer is reused for all 5474 * subsequent reads. The system never uses buffers with the 5475 * requested bigger size in that case. An adjunct patch could 5476 * try and delete all unused buffers it encounters and which 5477 * are smaller than the formally requested buffersize. 5478 */ 5479 5480 toRead = bufPtr->bufLength - bufPtr->nextAdded; 5481 5482 if (statePtr->inQueueTail == NULL) { 5483 statePtr->inQueueHead = bufPtr; 5484 } else { 5485 statePtr->inQueueTail->nextPtr = bufPtr; 5486 } 5487 statePtr->inQueueTail = bufPtr; 5488 } 5489 5490 /* 5491 * If EOF is set, we should avoid calling the driver because on some 5492 * platforms it is impossible to read from a device after EOF. 5493 */ 5494 5495 if (statePtr->flags & CHANNEL_EOF) { 5496 return 0; 5497 } 5498 5499#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 5500 /* [SF Tcl Bug 943274]. Better emulation of non-blocking channels 5501 * for channels without BlockModeProc, by keeping track of true 5502 * fileevents generated by the OS == Data waiting and reading if 5503 * and only if we are sure to have data. 5504 */ 5505 5506 if ((statePtr->flags & CHANNEL_NONBLOCKING) && 5507 (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) && 5508 !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) { 5509 5510 /* Bypass the driver, it would block, as no data is available */ 5511 nread = -1; 5512 result = EWOULDBLOCK; 5513 } else { 5514#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 5515 5516 nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData, 5517 bufPtr->buf + bufPtr->nextAdded, toRead, &result); 5518 5519#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 5520 } 5521#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 5522 5523 if (nread > 0) { 5524 bufPtr->nextAdded += nread; 5525 5526 /* 5527 * If we get a short read, signal up that we may be BLOCKED. We 5528 * should avoid calling the driver because on some platforms we 5529 * will block in the low level reading code even though the 5530 * channel is set into nonblocking mode. 5531 */ 5532 5533 if (nread < toRead) { 5534 statePtr->flags |= CHANNEL_BLOCKED; 5535 } 5536 5537#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 5538 if (nread <= toRead) { 5539 /* [SF Tcl Bug 943274] We have read the available data, 5540 * clear flag */ 5541 statePtr->flags &= ~CHANNEL_HAS_MORE_DATA; 5542 } 5543#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 5544 5545 } else if (nread == 0) { 5546 statePtr->flags |= CHANNEL_EOF; 5547 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 5548 } else if (nread < 0) { 5549 if ((result == EWOULDBLOCK) || (result == EAGAIN)) { 5550 statePtr->flags |= CHANNEL_BLOCKED; 5551 result = EAGAIN; 5552 } 5553 Tcl_SetErrno(result); 5554 return result; 5555 } 5556 return 0; 5557} 5558 5559/* 5560 *---------------------------------------------------------------------- 5561 * 5562 * Tcl_Seek -- 5563 * 5564 * Implements seeking on Tcl Channels. This is a public function 5565 * so that other C facilities may be implemented on top of it. 5566 * 5567 * Results: 5568 * The new access point or -1 on error. If error, use Tcl_GetErrno() 5569 * to retrieve the POSIX error code for the error that occurred. 5570 * 5571 * Side effects: 5572 * May flush output on the channel. May discard queued input. 5573 * 5574 *---------------------------------------------------------------------- 5575 */ 5576 5577Tcl_WideInt 5578Tcl_Seek(chan, offset, mode) 5579 Tcl_Channel chan; /* The channel on which to seek. */ 5580 Tcl_WideInt offset; /* Offset to seek to. */ 5581 int mode; /* Relative to which location to seek? */ 5582{ 5583 Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ 5584 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 5585 int inputBuffered, outputBuffered; 5586 /* # bytes held in buffers. */ 5587 int result; /* Of device driver operations. */ 5588 Tcl_WideInt curPos; /* Position on the device. */ 5589 int wasAsync; /* Was the channel nonblocking before the 5590 * seek operation? If so, must restore to 5591 * nonblocking mode after the seek. */ 5592 5593 if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) { 5594 return Tcl_LongAsWide(-1); 5595 } 5596 5597 /* 5598 * Disallow seek on dead channels -- channels that have been closed but 5599 * not yet been deallocated. Such channels can be found if the exit 5600 * handler for channel cleanup has run but the channel is still 5601 * registered in an interpreter. 5602 */ 5603 5604 if (CheckForDeadChannel(NULL, statePtr)) { 5605 return Tcl_LongAsWide(-1); 5606 } 5607 5608 /* 5609 * This operation should occur at the top of a channel stack. 5610 */ 5611 5612 chanPtr = statePtr->topChanPtr; 5613 5614 /* 5615 * Disallow seek on channels whose type does not have a seek procedure 5616 * defined. This means that the channel does not support seeking. 5617 */ 5618 5619 if (chanPtr->typePtr->seekProc == (Tcl_DriverSeekProc *) NULL) { 5620 Tcl_SetErrno(EINVAL); 5621 return Tcl_LongAsWide(-1); 5622 } 5623 5624 /* 5625 * Compute how much input and output is buffered. If both input and 5626 * output is buffered, cannot compute the current position. 5627 */ 5628 5629 inputBuffered = Tcl_InputBuffered(chan); 5630 outputBuffered = Tcl_OutputBuffered(chan); 5631 5632 if ((inputBuffered != 0) && (outputBuffered != 0)) { 5633 Tcl_SetErrno(EFAULT); 5634 return Tcl_LongAsWide(-1); 5635 } 5636 5637 /* 5638 * If we are seeking relative to the current position, compute the 5639 * corrected offset taking into account the amount of unread input. 5640 */ 5641 5642 if (mode == SEEK_CUR) { 5643 offset -= inputBuffered; 5644 } 5645 5646 /* 5647 * Discard any queued input - this input should not be read after 5648 * the seek. 5649 */ 5650 5651 DiscardInputQueued(statePtr, 0); 5652 5653 /* 5654 * Reset EOF and BLOCKED flags. We invalidate them by moving the 5655 * access point. Also clear CR related flags. 5656 */ 5657 5658 statePtr->flags &= 5659 (~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | INPUT_SAW_CR)); 5660 5661 /* 5662 * If the channel is in asynchronous output mode, switch it back 5663 * to synchronous mode and cancel any async flush that may be 5664 * scheduled. After the flush, the channel will be put back into 5665 * asynchronous output mode. 5666 */ 5667 5668 wasAsync = 0; 5669 if (statePtr->flags & CHANNEL_NONBLOCKING) { 5670 wasAsync = 1; 5671 result = StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING); 5672 if (result != 0) { 5673 return Tcl_LongAsWide(-1); 5674 } 5675 statePtr->flags &= (~(CHANNEL_NONBLOCKING)); 5676 if (statePtr->flags & BG_FLUSH_SCHEDULED) { 5677 statePtr->flags &= (~(BG_FLUSH_SCHEDULED)); 5678 } 5679 } 5680 5681 /* 5682 * If the flush fails we cannot recover the original position. In 5683 * that case the seek is not attempted because we do not know where 5684 * the access position is - instead we return the error. FlushChannel 5685 * has already called Tcl_SetErrno() to report the error upwards. 5686 * If the flush succeeds we do the seek also. 5687 */ 5688 5689 if (FlushChannel(NULL, chanPtr, 0) != 0) { 5690 curPos = -1; 5691 } else { 5692 5693 /* 5694 * Now seek to the new position in the channel as requested by the 5695 * caller. Note that we prefer the wideSeekProc if that is 5696 * available and non-NULL... 5697 */ 5698 5699 if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && 5700 chanPtr->typePtr->wideSeekProc != NULL) { 5701 curPos = (chanPtr->typePtr->wideSeekProc) (chanPtr->instanceData, 5702 offset, mode, &result); 5703 } else if (offset < Tcl_LongAsWide(LONG_MIN) || 5704 offset > Tcl_LongAsWide(LONG_MAX)) { 5705 result = EOVERFLOW; 5706 curPos = Tcl_LongAsWide(-1); 5707 } else { 5708 curPos = Tcl_LongAsWide((chanPtr->typePtr->seekProc) ( 5709 chanPtr->instanceData, Tcl_WideAsLong(offset), mode, 5710 &result)); 5711 } 5712 if (curPos == Tcl_LongAsWide(-1)) { 5713 Tcl_SetErrno(result); 5714 } 5715 } 5716 5717 /* 5718 * Restore to nonblocking mode if that was the previous behavior. 5719 * 5720 * NOTE: Even if there was an async flush active we do not restore 5721 * it now because we already flushed all the queued output, above. 5722 */ 5723 5724 if (wasAsync) { 5725 statePtr->flags |= CHANNEL_NONBLOCKING; 5726 result = StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING); 5727 if (result != 0) { 5728 return Tcl_LongAsWide(-1); 5729 } 5730 } 5731 5732 return curPos; 5733} 5734 5735/* 5736 *---------------------------------------------------------------------- 5737 * 5738 * Tcl_Tell -- 5739 * 5740 * Returns the position of the next character to be read/written on 5741 * this channel. 5742 * 5743 * Results: 5744 * A nonnegative integer on success, -1 on failure. If failed, 5745 * use Tcl_GetErrno() to retrieve the POSIX error code for the 5746 * error that occurred. 5747 * 5748 * Side effects: 5749 * None. 5750 * 5751 *---------------------------------------------------------------------- 5752 */ 5753 5754Tcl_WideInt 5755Tcl_Tell(chan) 5756 Tcl_Channel chan; /* The channel to return pos for. */ 5757{ 5758 Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ 5759 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 5760 int inputBuffered, outputBuffered; /* # bytes held in buffers. */ 5761 int result; /* Of calling device driver. */ 5762 Tcl_WideInt curPos; /* Position on device. */ 5763 5764 if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) { 5765 return Tcl_LongAsWide(-1); 5766 } 5767 5768 /* 5769 * Disallow tell on dead channels -- channels that have been closed but 5770 * not yet been deallocated. Such channels can be found if the exit 5771 * handler for channel cleanup has run but the channel is still 5772 * registered in an interpreter. 5773 */ 5774 5775 if (CheckForDeadChannel(NULL, statePtr)) { 5776 return Tcl_LongAsWide(-1); 5777 } 5778 5779 /* 5780 * This operation should occur at the top of a channel stack. 5781 */ 5782 5783 chanPtr = statePtr->topChanPtr; 5784 5785 /* 5786 * Disallow tell on channels whose type does not have a seek procedure 5787 * defined. This means that the channel does not support seeking. 5788 */ 5789 5790 if (chanPtr->typePtr->seekProc == (Tcl_DriverSeekProc *) NULL) { 5791 Tcl_SetErrno(EINVAL); 5792 return Tcl_LongAsWide(-1); 5793 } 5794 5795 /* 5796 * Compute how much input and output is buffered. If both input and 5797 * output is buffered, cannot compute the current position. 5798 */ 5799 5800 inputBuffered = Tcl_InputBuffered(chan); 5801 outputBuffered = Tcl_OutputBuffered(chan); 5802 5803 if ((inputBuffered != 0) && (outputBuffered != 0)) { 5804 Tcl_SetErrno(EFAULT); 5805 return Tcl_LongAsWide(-1); 5806 } 5807 5808 /* 5809 * Get the current position in the device and compute the position 5810 * where the next character will be read or written. Note that we 5811 * prefer the wideSeekProc if that is available and non-NULL... 5812 */ 5813 5814 if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && 5815 chanPtr->typePtr->wideSeekProc != NULL) { 5816 curPos = (chanPtr->typePtr->wideSeekProc) (chanPtr->instanceData, 5817 Tcl_LongAsWide(0), SEEK_CUR, &result); 5818 } else { 5819 curPos = Tcl_LongAsWide((chanPtr->typePtr->seekProc) ( 5820 chanPtr->instanceData, 0, SEEK_CUR, &result)); 5821 } 5822 if (curPos == Tcl_LongAsWide(-1)) { 5823 Tcl_SetErrno(result); 5824 return Tcl_LongAsWide(-1); 5825 } 5826 if (inputBuffered != 0) { 5827 return curPos - inputBuffered; 5828 } 5829 return curPos + outputBuffered; 5830} 5831 5832/* 5833 *--------------------------------------------------------------------------- 5834 * 5835 * Tcl_SeekOld, Tcl_TellOld -- 5836 * 5837 * Backward-compatability versions of the seek/tell interface that 5838 * do not support 64-bit offsets. This interface is not documented 5839 * or expected to be supported indefinitely. 5840 * 5841 * Results: 5842 * As for Tcl_Seek and Tcl_Tell respectively, except truncated to 5843 * whatever value will fit in an 'int'. 5844 * 5845 * Side effects: 5846 * As for Tcl_Seek and Tcl_Tell respectively. 5847 * 5848 *--------------------------------------------------------------------------- 5849 */ 5850 5851int 5852Tcl_SeekOld(chan, offset, mode) 5853 Tcl_Channel chan; /* The channel on which to seek. */ 5854 int offset; /* Offset to seek to. */ 5855 int mode; /* Relative to which location to seek? */ 5856{ 5857 Tcl_WideInt wOffset, wResult; 5858 5859 wOffset = Tcl_LongAsWide((long)offset); 5860 wResult = Tcl_Seek(chan, wOffset, mode); 5861 return (int)Tcl_WideAsLong(wResult); 5862} 5863 5864int 5865Tcl_TellOld(chan) 5866 Tcl_Channel chan; /* The channel to return pos for. */ 5867{ 5868 Tcl_WideInt wResult; 5869 5870 wResult = Tcl_Tell(chan); 5871 return (int)Tcl_WideAsLong(wResult); 5872} 5873 5874/* 5875 *--------------------------------------------------------------------------- 5876 * 5877 * CheckChannelErrors -- 5878 * 5879 * See if the channel is in an ready state and can perform the 5880 * desired operation. 5881 * 5882 * Results: 5883 * The return value is 0 if the channel is OK, otherwise the 5884 * return value is -1 and errno is set to indicate the error. 5885 * 5886 * Side effects: 5887 * May clear the EOF and/or BLOCKED bits if reading from channel. 5888 * 5889 *--------------------------------------------------------------------------- 5890 */ 5891 5892static int 5893CheckChannelErrors(statePtr, flags) 5894 ChannelState *statePtr; /* Channel to check. */ 5895 int flags; /* Test if channel supports desired operation: 5896 * TCL_READABLE, TCL_WRITABLE. Also indicates 5897 * Raw read or write for special close 5898 * processing*/ 5899{ 5900 int direction = flags & (TCL_READABLE|TCL_WRITABLE); 5901 5902 /* 5903 * Check for unreported error. 5904 */ 5905 5906 if (statePtr->unreportedError != 0) { 5907 Tcl_SetErrno(statePtr->unreportedError); 5908 statePtr->unreportedError = 0; 5909 return -1; 5910 } 5911 5912 /* 5913 * Only the raw read and write operations are allowed during close 5914 * in order to drain data from stacked channels. 5915 */ 5916 5917 if ((statePtr->flags & CHANNEL_CLOSED) && 5918 ((flags & CHANNEL_RAW_MODE) == 0)) { 5919 Tcl_SetErrno(EACCES); 5920 return -1; 5921 } 5922 5923 /* 5924 * Fail if the channel is not opened for desired operation. 5925 */ 5926 5927 if ((statePtr->flags & direction) == 0) { 5928 Tcl_SetErrno(EACCES); 5929 return -1; 5930 } 5931 5932 /* 5933 * Fail if the channel is in the middle of a background copy. 5934 * 5935 * Don't do this tests for raw channels here or else the chaining in the 5936 * transformation drivers will fail with 'file busy' error instead of 5937 * retrieving and transforming the data to copy. 5938 */ 5939 5940 if (BUSY_STATE(statePtr,flags) && ((flags & CHANNEL_RAW_MODE) == 0)) { 5941 Tcl_SetErrno(EBUSY); 5942 return -1; 5943 } 5944 5945 if (direction == TCL_READABLE) { 5946 /* 5947 * If we have not encountered a sticky EOF, clear the EOF bit 5948 * (sticky EOF is set if we have seen the input eofChar, to prevent 5949 * reading beyond the eofChar). Also, always clear the BLOCKED bit. 5950 * We want to discover these conditions anew in each operation. 5951 */ 5952 5953 if ((statePtr->flags & CHANNEL_STICKY_EOF) == 0) { 5954 statePtr->flags &= ~CHANNEL_EOF; 5955 } 5956 statePtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA); 5957 } 5958 5959 return 0; 5960} 5961 5962/* 5963 *---------------------------------------------------------------------- 5964 * 5965 * Tcl_Eof -- 5966 * 5967 * Returns 1 if the channel is at EOF, 0 otherwise. 5968 * 5969 * Results: 5970 * 1 or 0, always. 5971 * 5972 * Side effects: 5973 * None. 5974 * 5975 *---------------------------------------------------------------------- 5976 */ 5977 5978int 5979Tcl_Eof(chan) 5980 Tcl_Channel chan; /* Does this channel have EOF? */ 5981{ 5982 ChannelState *statePtr = ((Channel *) chan)->state; 5983 /* State of real channel structure. */ 5984 5985 return ((statePtr->flags & CHANNEL_STICKY_EOF) || 5986 ((statePtr->flags & CHANNEL_EOF) && 5987 (Tcl_InputBuffered(chan) == 0))) ? 1 : 0; 5988} 5989 5990/* 5991 *---------------------------------------------------------------------- 5992 * 5993 * Tcl_InputBlocked -- 5994 * 5995 * Returns 1 if input is blocked on this channel, 0 otherwise. 5996 * 5997 * Results: 5998 * 0 or 1, always. 5999 * 6000 * Side effects: 6001 * None. 6002 * 6003 *---------------------------------------------------------------------- 6004 */ 6005 6006int 6007Tcl_InputBlocked(chan) 6008 Tcl_Channel chan; /* Is this channel blocked? */ 6009{ 6010 ChannelState *statePtr = ((Channel *) chan)->state; 6011 /* State of real channel structure. */ 6012 6013 return (statePtr->flags & CHANNEL_BLOCKED) ? 1 : 0; 6014} 6015 6016/* 6017 *---------------------------------------------------------------------- 6018 * 6019 * Tcl_InputBuffered -- 6020 * 6021 * Returns the number of bytes of input currently buffered in the 6022 * common internal buffer of a channel. 6023 * 6024 * Results: 6025 * The number of input bytes buffered, or zero if the channel is not 6026 * open for reading. 6027 * 6028 * Side effects: 6029 * None. 6030 * 6031 *---------------------------------------------------------------------- 6032 */ 6033 6034int 6035Tcl_InputBuffered(chan) 6036 Tcl_Channel chan; /* The channel to query. */ 6037{ 6038 ChannelState *statePtr = ((Channel *) chan)->state; 6039 /* State of real channel structure. */ 6040 ChannelBuffer *bufPtr; 6041 int bytesBuffered; 6042 6043 for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead; 6044 bufPtr != (ChannelBuffer *) NULL; 6045 bufPtr = bufPtr->nextPtr) { 6046 bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved); 6047 } 6048 6049 /* 6050 * Don't forget the bytes in the topmost pushback area. 6051 */ 6052 6053 for (bufPtr = statePtr->topChanPtr->inQueueHead; 6054 bufPtr != (ChannelBuffer *) NULL; 6055 bufPtr = bufPtr->nextPtr) { 6056 bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved); 6057 } 6058 6059 return bytesBuffered; 6060} 6061 6062/* 6063 *---------------------------------------------------------------------- 6064 * 6065 * Tcl_OutputBuffered -- 6066 * 6067 * Returns the number of bytes of output currently buffered in the 6068 * common internal buffer of a channel. 6069 * 6070 * Results: 6071 * The number of output bytes buffered, or zero if the channel is not 6072 * open for writing. 6073 * 6074 * Side effects: 6075 * None. 6076 * 6077 *---------------------------------------------------------------------- 6078 */ 6079 6080int 6081Tcl_OutputBuffered(chan) 6082 Tcl_Channel chan; /* The channel to query. */ 6083{ 6084 ChannelState *statePtr = ((Channel *) chan)->state; 6085 /* State of real channel structure. */ 6086 ChannelBuffer *bufPtr; 6087 int bytesBuffered; 6088 6089 for (bytesBuffered = 0, bufPtr = statePtr->outQueueHead; 6090 bufPtr != (ChannelBuffer *) NULL; 6091 bufPtr = bufPtr->nextPtr) { 6092 bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved); 6093 } 6094 if ((statePtr->curOutPtr != (ChannelBuffer *) NULL) && 6095 (statePtr->curOutPtr->nextAdded > statePtr->curOutPtr->nextRemoved)) { 6096 statePtr->flags |= BUFFER_READY; 6097 bytesBuffered += 6098 (statePtr->curOutPtr->nextAdded - statePtr->curOutPtr->nextRemoved); 6099 } 6100 6101 return bytesBuffered; 6102} 6103 6104/* 6105 *---------------------------------------------------------------------- 6106 * 6107 * Tcl_ChannelBuffered -- 6108 * 6109 * Returns the number of bytes of input currently buffered in the 6110 * internal buffer (push back area) of a channel. 6111 * 6112 * Results: 6113 * The number of input bytes buffered, or zero if the channel is not 6114 * open for reading. 6115 * 6116 * Side effects: 6117 * None. 6118 * 6119 *---------------------------------------------------------------------- 6120 */ 6121 6122int 6123Tcl_ChannelBuffered(chan) 6124 Tcl_Channel chan; /* The channel to query. */ 6125{ 6126 Channel *chanPtr = (Channel *) chan; 6127 /* real channel structure. */ 6128 ChannelBuffer *bufPtr; 6129 int bytesBuffered; 6130 6131 for (bytesBuffered = 0, bufPtr = chanPtr->inQueueHead; 6132 bufPtr != (ChannelBuffer *) NULL; 6133 bufPtr = bufPtr->nextPtr) { 6134 bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved); 6135 } 6136 6137 return bytesBuffered; 6138} 6139 6140/* 6141 *---------------------------------------------------------------------- 6142 * 6143 * Tcl_SetChannelBufferSize -- 6144 * 6145 * Sets the size of buffers to allocate to store input or output 6146 * in the channel. The size must be between 1 byte and 1 MByte. 6147 * 6148 * Results: 6149 * None. 6150 * 6151 * Side effects: 6152 * Sets the size of buffers subsequently allocated for this channel. 6153 * 6154 *---------------------------------------------------------------------- 6155 */ 6156 6157void 6158Tcl_SetChannelBufferSize(chan, sz) 6159 Tcl_Channel chan; /* The channel whose buffer size 6160 * to set. */ 6161 int sz; /* The size to set. */ 6162{ 6163 ChannelState *statePtr; /* State of real channel structure. */ 6164 6165 /* 6166 * Clip the buffer size to force it into the [1,1M] range 6167 */ 6168 6169 if (sz < 1) { 6170 sz = 1; 6171 } else if (sz > MAX_CHANNEL_BUFFER_SIZE) { 6172 sz = MAX_CHANNEL_BUFFER_SIZE; 6173 } 6174 6175 statePtr = ((Channel *) chan)->state; 6176 statePtr->bufSize = sz; 6177 6178 if (statePtr->outputStage != NULL) { 6179 ckfree((char *) statePtr->outputStage); 6180 statePtr->outputStage = NULL; 6181 } 6182 if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { 6183 statePtr->outputStage = (char *) 6184 ckalloc((unsigned) (statePtr->bufSize + 2)); 6185 } 6186} 6187 6188/* 6189 *---------------------------------------------------------------------- 6190 * 6191 * Tcl_GetChannelBufferSize -- 6192 * 6193 * Retrieves the size of buffers to allocate for this channel. 6194 * 6195 * Results: 6196 * The size. 6197 * 6198 * Side effects: 6199 * None. 6200 * 6201 *---------------------------------------------------------------------- 6202 */ 6203 6204int 6205Tcl_GetChannelBufferSize(chan) 6206 Tcl_Channel chan; /* The channel for which to find the 6207 * buffer size. */ 6208{ 6209 ChannelState *statePtr = ((Channel *) chan)->state; 6210 /* State of real channel structure. */ 6211 6212 return statePtr->bufSize; 6213} 6214 6215/* 6216 *---------------------------------------------------------------------- 6217 * 6218 * Tcl_BadChannelOption -- 6219 * 6220 * This procedure generates a "bad option" error message in an 6221 * (optional) interpreter. It is used by channel drivers when 6222 * a invalid Set/Get option is requested. Its purpose is to concatenate 6223 * the generic options list to the specific ones and factorize 6224 * the generic options error message string. 6225 * 6226 * Results: 6227 * TCL_ERROR. 6228 * 6229 * Side effects: 6230 * An error message is generated in interp's result object to 6231 * indicate that a command was invoked with the a bad option 6232 * The message has the form 6233 * bad option "blah": should be one of 6234 * <...generic options...>+<...specific options...> 6235 * "blah" is the optionName argument and "<specific options>" 6236 * is a space separated list of specific option words. 6237 * The function takes good care of inserting minus signs before 6238 * each option, commas after, and an "or" before the last option. 6239 * 6240 *---------------------------------------------------------------------- 6241 */ 6242 6243int 6244Tcl_BadChannelOption(interp, optionName, optionList) 6245 Tcl_Interp *interp; /* Current interpreter. (can be NULL)*/ 6246 CONST char *optionName; /* 'bad option' name */ 6247 CONST char *optionList; /* Specific options list to append 6248 * to the standard generic options. 6249 * can be NULL for generic options 6250 * only. 6251 */ 6252{ 6253 if (interp) { 6254 CONST char *genericopt = 6255 "blocking buffering buffersize encoding eofchar translation"; 6256 CONST char **argv; 6257 int argc, i; 6258 Tcl_DString ds; 6259 6260 Tcl_DStringInit(&ds); 6261 Tcl_DStringAppend(&ds, genericopt, -1); 6262 if (optionList && (*optionList)) { 6263 Tcl_DStringAppend(&ds, " ", 1); 6264 Tcl_DStringAppend(&ds, optionList, -1); 6265 } 6266 if (Tcl_SplitList(interp, Tcl_DStringValue(&ds), 6267 &argc, &argv) != TCL_OK) { 6268 panic("malformed option list in channel driver"); 6269 } 6270 Tcl_ResetResult(interp); 6271 Tcl_AppendResult(interp, "bad option \"", optionName, 6272 "\": should be one of ", (char *) NULL); 6273 argc--; 6274 for (i = 0; i < argc; i++) { 6275 Tcl_AppendResult(interp, "-", argv[i], ", ", (char *) NULL); 6276 } 6277 Tcl_AppendResult(interp, "or -", argv[i], (char *) NULL); 6278 Tcl_DStringFree(&ds); 6279 ckfree((char *) argv); 6280 } 6281 Tcl_SetErrno(EINVAL); 6282 return TCL_ERROR; 6283} 6284 6285/* 6286 *---------------------------------------------------------------------- 6287 * 6288 * Tcl_GetChannelOption -- 6289 * 6290 * Gets a mode associated with an IO channel. If the optionName arg 6291 * is non NULL, retrieves the value of that option. If the optionName 6292 * arg is NULL, retrieves a list of alternating option names and 6293 * values for the given channel. 6294 * 6295 * Results: 6296 * A standard Tcl result. Also sets the supplied DString to the 6297 * string value of the option(s) returned. 6298 * 6299 * Side effects: 6300 * None. 6301 * 6302 *---------------------------------------------------------------------- 6303 */ 6304 6305int 6306Tcl_GetChannelOption(interp, chan, optionName, dsPtr) 6307 Tcl_Interp *interp; /* For error reporting - can be NULL. */ 6308 Tcl_Channel chan; /* Channel on which to get option. */ 6309 CONST char *optionName; /* Option to get. */ 6310 Tcl_DString *dsPtr; /* Where to store value(s). */ 6311{ 6312 size_t len; /* Length of optionName string. */ 6313 char optionVal[128]; /* Buffer for sprintf. */ 6314 Channel *chanPtr = (Channel *) chan; 6315 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 6316 int flags; 6317 6318 /* 6319 * Disallow options on dead channels -- channels that have been closed but 6320 * not yet been deallocated. Such channels can be found if the exit 6321 * handler for channel cleanup has run but the channel is still 6322 * registered in an interpreter. 6323 */ 6324 6325 if (CheckForDeadChannel(interp, statePtr)) { 6326 return TCL_ERROR; 6327 } 6328 6329 /* 6330 * This operation should occur at the top of a channel stack. 6331 */ 6332 6333 chanPtr = statePtr->topChanPtr; 6334 6335 /* 6336 * If we are in the middle of a background copy, use the saved flags. 6337 */ 6338 6339 if (statePtr->csPtrR) { 6340 flags = statePtr->csPtrR->readFlags; 6341 } else if (statePtr->csPtrW) { 6342 flags = statePtr->csPtrW->writeFlags; 6343 } else { 6344 flags = statePtr->flags; 6345 } 6346 6347 /* 6348 * If the optionName is NULL it means that we want a list of all 6349 * options and values. 6350 */ 6351 6352 if (optionName == (char *) NULL) { 6353 len = 0; 6354 } else { 6355 len = strlen(optionName); 6356 } 6357 6358 if ((len == 0) || ((len > 2) && (optionName[1] == 'b') && 6359 (strncmp(optionName, "-blocking", len) == 0))) { 6360 if (len == 0) { 6361 Tcl_DStringAppendElement(dsPtr, "-blocking"); 6362 } 6363 Tcl_DStringAppendElement(dsPtr, 6364 (flags & CHANNEL_NONBLOCKING) ? "0" : "1"); 6365 if (len > 0) { 6366 return TCL_OK; 6367 } 6368 } 6369 if ((len == 0) || ((len > 7) && (optionName[1] == 'b') && 6370 (strncmp(optionName, "-buffering", len) == 0))) { 6371 if (len == 0) { 6372 Tcl_DStringAppendElement(dsPtr, "-buffering"); 6373 } 6374 if (flags & CHANNEL_LINEBUFFERED) { 6375 Tcl_DStringAppendElement(dsPtr, "line"); 6376 } else if (flags & CHANNEL_UNBUFFERED) { 6377 Tcl_DStringAppendElement(dsPtr, "none"); 6378 } else { 6379 Tcl_DStringAppendElement(dsPtr, "full"); 6380 } 6381 if (len > 0) { 6382 return TCL_OK; 6383 } 6384 } 6385 if ((len == 0) || ((len > 7) && (optionName[1] == 'b') && 6386 (strncmp(optionName, "-buffersize", len) == 0))) { 6387 if (len == 0) { 6388 Tcl_DStringAppendElement(dsPtr, "-buffersize"); 6389 } 6390 TclFormatInt(optionVal, statePtr->bufSize); 6391 Tcl_DStringAppendElement(dsPtr, optionVal); 6392 if (len > 0) { 6393 return TCL_OK; 6394 } 6395 } 6396 if ((len == 0) || 6397 ((len > 2) && (optionName[1] == 'e') && 6398 (strncmp(optionName, "-encoding", len) == 0))) { 6399 if (len == 0) { 6400 Tcl_DStringAppendElement(dsPtr, "-encoding"); 6401 } 6402 if (statePtr->encoding == NULL) { 6403 Tcl_DStringAppendElement(dsPtr, "binary"); 6404 } else { 6405 Tcl_DStringAppendElement(dsPtr, 6406 Tcl_GetEncodingName(statePtr->encoding)); 6407 } 6408 if (len > 0) { 6409 return TCL_OK; 6410 } 6411 } 6412 if ((len == 0) || 6413 ((len > 2) && (optionName[1] == 'e') && 6414 (strncmp(optionName, "-eofchar", len) == 0))) { 6415 if (len == 0) { 6416 Tcl_DStringAppendElement(dsPtr, "-eofchar"); 6417 } 6418 if (((flags & (TCL_READABLE|TCL_WRITABLE)) == 6419 (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { 6420 Tcl_DStringStartSublist(dsPtr); 6421 } 6422 if (flags & TCL_READABLE) { 6423 if (statePtr->inEofChar == 0) { 6424 Tcl_DStringAppendElement(dsPtr, ""); 6425 } else { 6426 char buf[4]; 6427 6428 sprintf(buf, "%c", statePtr->inEofChar); 6429 Tcl_DStringAppendElement(dsPtr, buf); 6430 } 6431 } 6432 if (flags & TCL_WRITABLE) { 6433 if (statePtr->outEofChar == 0) { 6434 Tcl_DStringAppendElement(dsPtr, ""); 6435 } else { 6436 char buf[4]; 6437 6438 sprintf(buf, "%c", statePtr->outEofChar); 6439 Tcl_DStringAppendElement(dsPtr, buf); 6440 } 6441 } 6442 if ( !(flags & (TCL_READABLE|TCL_WRITABLE))) { 6443 /* Not readable or writable (server socket) */ 6444 Tcl_DStringAppendElement(dsPtr, ""); 6445 } 6446 if (((flags & (TCL_READABLE|TCL_WRITABLE)) == 6447 (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { 6448 Tcl_DStringEndSublist(dsPtr); 6449 } 6450 if (len > 0) { 6451 return TCL_OK; 6452 } 6453 } 6454 if ((len == 0) || 6455 ((len > 1) && (optionName[1] == 't') && 6456 (strncmp(optionName, "-translation", len) == 0))) { 6457 if (len == 0) { 6458 Tcl_DStringAppendElement(dsPtr, "-translation"); 6459 } 6460 if (((flags & (TCL_READABLE|TCL_WRITABLE)) == 6461 (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { 6462 Tcl_DStringStartSublist(dsPtr); 6463 } 6464 if (flags & TCL_READABLE) { 6465 if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) { 6466 Tcl_DStringAppendElement(dsPtr, "auto"); 6467 } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) { 6468 Tcl_DStringAppendElement(dsPtr, "cr"); 6469 } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) { 6470 Tcl_DStringAppendElement(dsPtr, "crlf"); 6471 } else { 6472 Tcl_DStringAppendElement(dsPtr, "lf"); 6473 } 6474 } 6475 if (flags & TCL_WRITABLE) { 6476 if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) { 6477 Tcl_DStringAppendElement(dsPtr, "auto"); 6478 } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) { 6479 Tcl_DStringAppendElement(dsPtr, "cr"); 6480 } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) { 6481 Tcl_DStringAppendElement(dsPtr, "crlf"); 6482 } else { 6483 Tcl_DStringAppendElement(dsPtr, "lf"); 6484 } 6485 } 6486 if ( !(flags & (TCL_READABLE|TCL_WRITABLE))) { 6487 /* Not readable or writable (server socket) */ 6488 Tcl_DStringAppendElement(dsPtr, "auto"); 6489 } 6490 if (((flags & (TCL_READABLE|TCL_WRITABLE)) == 6491 (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { 6492 Tcl_DStringEndSublist(dsPtr); 6493 } 6494 if (len > 0) { 6495 return TCL_OK; 6496 } 6497 } 6498 if (chanPtr->typePtr->getOptionProc != (Tcl_DriverGetOptionProc *) NULL) { 6499 /* 6500 * let the driver specific handle additional options 6501 * and result code and message. 6502 */ 6503 6504 return (chanPtr->typePtr->getOptionProc) (chanPtr->instanceData, 6505 interp, optionName, dsPtr); 6506 } else { 6507 /* 6508 * no driver specific options case. 6509 */ 6510 6511 if (len == 0) { 6512 return TCL_OK; 6513 } 6514 return Tcl_BadChannelOption(interp, optionName, NULL); 6515 } 6516} 6517 6518/* 6519 *--------------------------------------------------------------------------- 6520 * 6521 * Tcl_SetChannelOption -- 6522 * 6523 * Sets an option on a channel. 6524 * 6525 * Results: 6526 * A standard Tcl result. On error, sets interp's result object 6527 * if interp is not NULL. 6528 * 6529 * Side effects: 6530 * May modify an option on a device. 6531 * 6532 *--------------------------------------------------------------------------- 6533 */ 6534 6535int 6536Tcl_SetChannelOption(interp, chan, optionName, newValue) 6537 Tcl_Interp *interp; /* For error reporting - can be NULL. */ 6538 Tcl_Channel chan; /* Channel on which to set mode. */ 6539 CONST char *optionName; /* Which option to set? */ 6540 CONST char *newValue; /* New value for option. */ 6541{ 6542 Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ 6543 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 6544 size_t len; /* Length of optionName string. */ 6545 int argc; 6546 CONST char **argv; 6547 6548 /* 6549 * If the channel is in the middle of a background copy, fail. 6550 */ 6551 6552 if (statePtr->csPtrR || statePtr->csPtrW) { 6553 if (interp) { 6554 Tcl_AppendResult(interp, 6555 "unable to set channel options: background copy in progress", 6556 (char *) NULL); 6557 } 6558 return TCL_ERROR; 6559 } 6560 6561 /* 6562 * Disallow options on dead channels -- channels that have been closed but 6563 * not yet been deallocated. Such channels can be found if the exit 6564 * handler for channel cleanup has run but the channel is still 6565 * registered in an interpreter. 6566 */ 6567 6568 if (CheckForDeadChannel(NULL, statePtr)) { 6569 return TCL_ERROR; 6570 } 6571 6572 /* 6573 * This operation should occur at the top of a channel stack. 6574 */ 6575 6576 chanPtr = statePtr->topChanPtr; 6577 6578 len = strlen(optionName); 6579 6580 if ((len > 2) && (optionName[1] == 'b') && 6581 (strncmp(optionName, "-blocking", len) == 0)) { 6582 int newMode; 6583 if (Tcl_GetBoolean(interp, newValue, &newMode) == TCL_ERROR) { 6584 return TCL_ERROR; 6585 } 6586 if (newMode) { 6587 newMode = TCL_MODE_BLOCKING; 6588 } else { 6589 newMode = TCL_MODE_NONBLOCKING; 6590 } 6591 return SetBlockMode(interp, chanPtr, newMode); 6592 } else if ((len > 7) && (optionName[1] == 'b') && 6593 (strncmp(optionName, "-buffering", len) == 0)) { 6594 len = strlen(newValue); 6595 if ((newValue[0] == 'f') && (strncmp(newValue, "full", len) == 0)) { 6596 statePtr->flags &= 6597 (~(CHANNEL_UNBUFFERED|CHANNEL_LINEBUFFERED)); 6598 } else if ((newValue[0] == 'l') && 6599 (strncmp(newValue, "line", len) == 0)) { 6600 statePtr->flags &= (~(CHANNEL_UNBUFFERED)); 6601 statePtr->flags |= CHANNEL_LINEBUFFERED; 6602 } else if ((newValue[0] == 'n') && 6603 (strncmp(newValue, "none", len) == 0)) { 6604 statePtr->flags &= (~(CHANNEL_LINEBUFFERED)); 6605 statePtr->flags |= CHANNEL_UNBUFFERED; 6606 } else { 6607 if (interp) { 6608 Tcl_AppendResult(interp, "bad value for -buffering: ", 6609 "must be one of full, line, or none", 6610 (char *) NULL); 6611 return TCL_ERROR; 6612 } 6613 } 6614 return TCL_OK; 6615 } else if ((len > 7) && (optionName[1] == 'b') && 6616 (strncmp(optionName, "-buffersize", len) == 0)) { 6617 int newBufferSize; 6618 if (Tcl_GetInt(interp, newValue, &newBufferSize) == TCL_ERROR) { 6619 return TCL_ERROR; 6620 } 6621 Tcl_SetChannelBufferSize(chan, newBufferSize); 6622 } else if ((len > 2) && (optionName[1] == 'e') && 6623 (strncmp(optionName, "-encoding", len) == 0)) { 6624 Tcl_Encoding encoding; 6625 6626 if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) { 6627 encoding = NULL; 6628 } else { 6629 encoding = Tcl_GetEncoding(interp, newValue); 6630 if (encoding == NULL) { 6631 return TCL_ERROR; 6632 } 6633 } 6634 /* 6635 * When the channel has an escape sequence driven encoding such as 6636 * iso2022, the terminated escape sequence must write to the buffer. 6637 */ 6638 if ((statePtr->encoding != NULL) && (statePtr->curOutPtr != NULL) 6639 && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) { 6640 statePtr->outputEncodingFlags |= TCL_ENCODING_END; 6641 WriteChars(chanPtr, "", 0); 6642 } 6643 Tcl_FreeEncoding(statePtr->encoding); 6644 statePtr->encoding = encoding; 6645 statePtr->inputEncodingState = NULL; 6646 statePtr->inputEncodingFlags = TCL_ENCODING_START; 6647 statePtr->outputEncodingState = NULL; 6648 statePtr->outputEncodingFlags = TCL_ENCODING_START; 6649 statePtr->flags &= ~CHANNEL_NEED_MORE_DATA; 6650 UpdateInterest(chanPtr); 6651 } else if ((len > 2) && (optionName[1] == 'e') && 6652 (strncmp(optionName, "-eofchar", len) == 0)) { 6653 if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) { 6654 return TCL_ERROR; 6655 } 6656 if (argc == 0) { 6657 statePtr->inEofChar = 0; 6658 statePtr->outEofChar = 0; 6659 } else if (argc == 1) { 6660 if (statePtr->flags & TCL_WRITABLE) { 6661 statePtr->outEofChar = (int) argv[0][0]; 6662 } 6663 if (statePtr->flags & TCL_READABLE) { 6664 statePtr->inEofChar = (int) argv[0][0]; 6665 } 6666 } else if (argc != 2) { 6667 if (interp) { 6668 Tcl_AppendResult(interp, 6669 "bad value for -eofchar: should be a list of zero,", 6670 " one, or two elements", (char *) NULL); 6671 } 6672 ckfree((char *) argv); 6673 return TCL_ERROR; 6674 } else { 6675 if (statePtr->flags & TCL_READABLE) { 6676 statePtr->inEofChar = (int) argv[0][0]; 6677 } 6678 if (statePtr->flags & TCL_WRITABLE) { 6679 statePtr->outEofChar = (int) argv[1][0]; 6680 } 6681 } 6682 if (argv != NULL) { 6683 ckfree((char *) argv); 6684 } 6685 6686 /* 6687 * [SF Tcl Bug 930851] Reset EOF and BLOCKED flags. Changing 6688 * the character which signals eof can transform a current eof 6689 * condition into a 'go ahead'. Ditto for blocked. 6690 */ 6691 6692 statePtr->flags &= (~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED)); 6693 6694 return TCL_OK; 6695 } else if ((len > 1) && (optionName[1] == 't') && 6696 (strncmp(optionName, "-translation", len) == 0)) { 6697 CONST char *readMode, *writeMode; 6698 6699 if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) { 6700 return TCL_ERROR; 6701 } 6702 6703 if (argc == 1) { 6704 readMode = (statePtr->flags & TCL_READABLE) ? argv[0] : NULL; 6705 writeMode = (statePtr->flags & TCL_WRITABLE) ? argv[0] : NULL; 6706 } else if (argc == 2) { 6707 readMode = (statePtr->flags & TCL_READABLE) ? argv[0] : NULL; 6708 writeMode = (statePtr->flags & TCL_WRITABLE) ? argv[1] : NULL; 6709 } else { 6710 if (interp) { 6711 Tcl_AppendResult(interp, 6712 "bad value for -translation: must be a one or two", 6713 " element list", (char *) NULL); 6714 } 6715 ckfree((char *) argv); 6716 return TCL_ERROR; 6717 } 6718 6719 if (readMode) { 6720 TclEolTranslation translation; 6721 if (*readMode == '\0') { 6722 translation = statePtr->inputTranslation; 6723 } else if (strcmp(readMode, "auto") == 0) { 6724 translation = TCL_TRANSLATE_AUTO; 6725 } else if (strcmp(readMode, "binary") == 0) { 6726 translation = TCL_TRANSLATE_LF; 6727 statePtr->inEofChar = 0; 6728 Tcl_FreeEncoding(statePtr->encoding); 6729 statePtr->encoding = NULL; 6730 } else if (strcmp(readMode, "lf") == 0) { 6731 translation = TCL_TRANSLATE_LF; 6732 } else if (strcmp(readMode, "cr") == 0) { 6733 translation = TCL_TRANSLATE_CR; 6734 } else if (strcmp(readMode, "crlf") == 0) { 6735 translation = TCL_TRANSLATE_CRLF; 6736 } else if (strcmp(readMode, "platform") == 0) { 6737 translation = TCL_PLATFORM_TRANSLATION; 6738 } else { 6739 if (interp) { 6740 Tcl_AppendResult(interp, 6741 "bad value for -translation: ", 6742 "must be one of auto, binary, cr, lf, crlf,", 6743 " or platform", (char *) NULL); 6744 } 6745 ckfree((char *) argv); 6746 return TCL_ERROR; 6747 } 6748 6749 /* 6750 * Reset the EOL flags since we need to look at any buffered 6751 * data to see if the new translation mode allows us to 6752 * complete the line. 6753 */ 6754 6755 if (translation != statePtr->inputTranslation) { 6756 statePtr->inputTranslation = translation; 6757 statePtr->flags &= ~(INPUT_SAW_CR); 6758 statePtr->flags &= ~(CHANNEL_NEED_MORE_DATA); 6759 UpdateInterest(chanPtr); 6760 } 6761 } 6762 if (writeMode) { 6763 if (*writeMode == '\0') { 6764 /* Do nothing. */ 6765 } else if (strcmp(writeMode, "auto") == 0) { 6766 /* 6767 * This is a hack to get TCP sockets to produce output 6768 * in CRLF mode if they are being set into AUTO mode. 6769 * A better solution for achieving this effect will be 6770 * coded later. 6771 */ 6772 6773 if (strcmp(Tcl_ChannelName(chanPtr->typePtr), "tcp") == 0) { 6774 statePtr->outputTranslation = TCL_TRANSLATE_CRLF; 6775 } else { 6776 statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; 6777 } 6778 } else if (strcmp(writeMode, "binary") == 0) { 6779 statePtr->outEofChar = 0; 6780 statePtr->outputTranslation = TCL_TRANSLATE_LF; 6781 Tcl_FreeEncoding(statePtr->encoding); 6782 statePtr->encoding = NULL; 6783 } else if (strcmp(writeMode, "lf") == 0) { 6784 statePtr->outputTranslation = TCL_TRANSLATE_LF; 6785 } else if (strcmp(writeMode, "cr") == 0) { 6786 statePtr->outputTranslation = TCL_TRANSLATE_CR; 6787 } else if (strcmp(writeMode, "crlf") == 0) { 6788 statePtr->outputTranslation = TCL_TRANSLATE_CRLF; 6789 } else if (strcmp(writeMode, "platform") == 0) { 6790 statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; 6791 } else { 6792 if (interp) { 6793 Tcl_AppendResult(interp, 6794 "bad value for -translation: ", 6795 "must be one of auto, binary, cr, lf, crlf,", 6796 " or platform", (char *) NULL); 6797 } 6798 ckfree((char *) argv); 6799 return TCL_ERROR; 6800 } 6801 } 6802 ckfree((char *) argv); 6803 return TCL_OK; 6804 } else if (chanPtr->typePtr->setOptionProc != NULL) { 6805 return (*chanPtr->typePtr->setOptionProc)(chanPtr->instanceData, 6806 interp, optionName, newValue); 6807 } else { 6808 return Tcl_BadChannelOption(interp, optionName, (char *) NULL); 6809 } 6810 6811 /* 6812 * If bufsize changes, need to get rid of old utility buffer. 6813 */ 6814 6815 if (statePtr->saveInBufPtr != NULL) { 6816 RecycleBuffer(statePtr, statePtr->saveInBufPtr, 1); 6817 statePtr->saveInBufPtr = NULL; 6818 } 6819 if (statePtr->inQueueHead != NULL) { 6820 if ((statePtr->inQueueHead->nextPtr == NULL) 6821 && (statePtr->inQueueHead->nextAdded == 6822 statePtr->inQueueHead->nextRemoved)) { 6823 RecycleBuffer(statePtr, statePtr->inQueueHead, 1); 6824 statePtr->inQueueHead = NULL; 6825 statePtr->inQueueTail = NULL; 6826 } 6827 } 6828 6829 /* 6830 * If encoding or bufsize changes, need to update output staging buffer. 6831 */ 6832 6833 if (statePtr->outputStage != NULL) { 6834 ckfree((char *) statePtr->outputStage); 6835 statePtr->outputStage = NULL; 6836 } 6837 if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { 6838 statePtr->outputStage = (char *) 6839 ckalloc((unsigned) (statePtr->bufSize + 2)); 6840 } 6841 return TCL_OK; 6842} 6843 6844/* 6845 *---------------------------------------------------------------------- 6846 * 6847 * CleanupChannelHandlers -- 6848 * 6849 * Removes channel handlers that refer to the supplied interpreter, 6850 * so that if the actual channel is not closed now, these handlers 6851 * will not run on subsequent events on the channel. This would be 6852 * erroneous, because the interpreter no longer has a reference to 6853 * this channel. 6854 * 6855 * Results: 6856 * None. 6857 * 6858 * Side effects: 6859 * Removes channel handlers. 6860 * 6861 *---------------------------------------------------------------------- 6862 */ 6863 6864static void 6865CleanupChannelHandlers(interp, chanPtr) 6866 Tcl_Interp *interp; 6867 Channel *chanPtr; 6868{ 6869 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 6870 EventScriptRecord *sPtr, *prevPtr, *nextPtr; 6871 6872 /* 6873 * Remove fileevent records on this channel that refer to the 6874 * given interpreter. 6875 */ 6876 6877 for (sPtr = statePtr->scriptRecordPtr, 6878 prevPtr = (EventScriptRecord *) NULL; 6879 sPtr != (EventScriptRecord *) NULL; 6880 sPtr = nextPtr) { 6881 nextPtr = sPtr->nextPtr; 6882 if (sPtr->interp == interp) { 6883 if (prevPtr == (EventScriptRecord *) NULL) { 6884 statePtr->scriptRecordPtr = nextPtr; 6885 } else { 6886 prevPtr->nextPtr = nextPtr; 6887 } 6888 6889 Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, 6890 TclChannelEventScriptInvoker, (ClientData) sPtr); 6891 6892 Tcl_DecrRefCount(sPtr->scriptPtr); 6893 ckfree((char *) sPtr); 6894 } else { 6895 prevPtr = sPtr; 6896 } 6897 } 6898} 6899 6900/* 6901 *---------------------------------------------------------------------- 6902 * 6903 * Tcl_NotifyChannel -- 6904 * 6905 * This procedure is called by a channel driver when a driver 6906 * detects an event on a channel. This procedure is responsible 6907 * for actually handling the event by invoking any channel 6908 * handler callbacks. 6909 * 6910 * Results: 6911 * None. 6912 * 6913 * Side effects: 6914 * Whatever the channel handler callback procedure does. 6915 * 6916 *---------------------------------------------------------------------- 6917 */ 6918 6919void 6920Tcl_NotifyChannel(channel, mask) 6921 Tcl_Channel channel; /* Channel that detected an event. */ 6922 int mask; /* OR'ed combination of TCL_READABLE, 6923 * TCL_WRITABLE, or TCL_EXCEPTION: indicates 6924 * which events were detected. */ 6925{ 6926 Channel *chanPtr = (Channel *) channel; 6927 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 6928 ChannelHandler *chPtr; 6929 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 6930 NextChannelHandler nh; 6931 Channel* upChanPtr; 6932 Tcl_ChannelType* upTypePtr; 6933 6934#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 6935 /* [SF Tcl Bug 943274] 6936 * For a non-blocking channel without blockmodeproc we keep track 6937 * of actual input coming from the OS so that we can do a credible 6938 * imitation of non-blocking behaviour. 6939 */ 6940 6941 if ((mask & TCL_READABLE) && 6942 (statePtr->flags & CHANNEL_NONBLOCKING) && 6943 (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) && 6944 !(statePtr->flags & CHANNEL_TIMER_FEV)) { 6945 6946 statePtr->flags |= CHANNEL_HAS_MORE_DATA; 6947 } 6948#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 6949 6950 /* 6951 * In contrast to the other API functions this procedure walks towards 6952 * the top of a stack and not down from it. 6953 * 6954 * The channel calling this procedure is the one who generated the event, 6955 * and thus does not take part in handling it. IOW, its HandlerProc is 6956 * not called, instead we begin with the channel above it. 6957 * 6958 * This behaviour also allows the transformation channels to 6959 * generate their own events and pass them upward. 6960 */ 6961 6962 while (mask && (chanPtr->upChanPtr != ((Channel*) NULL))) { 6963 Tcl_DriverHandlerProc* upHandlerProc; 6964 6965 upChanPtr = chanPtr->upChanPtr; 6966 upTypePtr = upChanPtr->typePtr; 6967 upHandlerProc = Tcl_ChannelHandlerProc(upTypePtr); 6968 if (upHandlerProc != NULL) { 6969 mask = (*upHandlerProc) (upChanPtr->instanceData, mask); 6970 } 6971 6972 /* ELSE: 6973 * Ignore transformations which are unable to handle the event 6974 * coming from below. Assume that they don't change the mask and 6975 * pass it on. 6976 */ 6977 6978 chanPtr = upChanPtr; 6979 } 6980 6981 channel = (Tcl_Channel) chanPtr; 6982 6983 /* 6984 * Here we have either reached the top of the stack or the mask is 6985 * empty. We break out of the procedure if it is the latter. 6986 */ 6987 6988 if (!mask) { 6989 return; 6990 } 6991 6992 /* 6993 * We are now above the topmost channel in a stack and have events 6994 * left. Now call the channel handlers as usual. 6995 * 6996 * Preserve the channel struct in case the script closes it. 6997 */ 6998 6999 Tcl_Preserve((ClientData) channel); 7000 Tcl_Preserve((ClientData) statePtr); 7001 7002 /* 7003 * If we are flushing in the background, be sure to call FlushChannel 7004 * for writable events. Note that we have to discard the writable 7005 * event so we don't call any write handlers before the flush is 7006 * complete. 7007 */ 7008 7009 if ((statePtr->flags & BG_FLUSH_SCHEDULED) && (mask & TCL_WRITABLE)) { 7010 FlushChannel(NULL, chanPtr, 1); 7011 mask &= ~TCL_WRITABLE; 7012 } 7013 7014 /* 7015 * Add this invocation to the list of recursive invocations of 7016 * ChannelHandlerEventProc. 7017 */ 7018 7019 nh.nextHandlerPtr = (ChannelHandler *) NULL; 7020 nh.nestedHandlerPtr = tsdPtr->nestedHandlerPtr; 7021 tsdPtr->nestedHandlerPtr = &nh; 7022 7023 for (chPtr = statePtr->chPtr; chPtr != (ChannelHandler *) NULL; ) { 7024 /* 7025 * If this channel handler is interested in any of the events that 7026 * have occurred on the channel, invoke its procedure. 7027 */ 7028 7029 if ((chPtr->mask & mask) != 0) { 7030 nh.nextHandlerPtr = chPtr->nextPtr; 7031 (*(chPtr->proc))(chPtr->clientData, mask); 7032 chPtr = nh.nextHandlerPtr; 7033 } else { 7034 chPtr = chPtr->nextPtr; 7035 } 7036 } 7037 7038 /* 7039 * Update the notifier interest, since it may have changed after 7040 * invoking event handlers. Skip that if the channel was deleted 7041 * in the call to the channel handler. 7042 */ 7043 7044 if (chanPtr->typePtr != NULL) { 7045 UpdateInterest(chanPtr); 7046 } 7047 7048 Tcl_Release((ClientData) statePtr); 7049 Tcl_Release((ClientData) channel); 7050 7051 tsdPtr->nestedHandlerPtr = nh.nestedHandlerPtr; 7052} 7053 7054/* 7055 *---------------------------------------------------------------------- 7056 * 7057 * UpdateInterest -- 7058 * 7059 * Arrange for the notifier to call us back at appropriate times 7060 * based on the current state of the channel. 7061 * 7062 * Results: 7063 * None. 7064 * 7065 * Side effects: 7066 * May schedule a timer or driver handler. 7067 * 7068 *---------------------------------------------------------------------- 7069 */ 7070 7071static void 7072UpdateInterest(chanPtr) 7073 Channel *chanPtr; /* Channel to update. */ 7074{ 7075 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 7076 int mask = statePtr->interestMask; 7077 7078 /* 7079 * If there are flushed buffers waiting to be written, then 7080 * we need to watch for the channel to become writable. 7081 */ 7082 7083 if (statePtr->flags & BG_FLUSH_SCHEDULED) { 7084 mask |= TCL_WRITABLE; 7085 } 7086 7087 /* 7088 * If there is data in the input queue, and we aren't waiting for more 7089 * data, then we need to schedule a timer so we don't block in the 7090 * notifier. Also, cancel the read interest so we don't get duplicate 7091 * events. 7092 */ 7093 7094 if (mask & TCL_READABLE) { 7095 if (!(statePtr->flags & CHANNEL_NEED_MORE_DATA) 7096 && (statePtr->inQueueHead != (ChannelBuffer *) NULL) 7097 && (statePtr->inQueueHead->nextRemoved < 7098 statePtr->inQueueHead->nextAdded)) { 7099 mask &= ~TCL_READABLE; 7100 7101 /* 7102 * Andreas Kupries, April 11, 2003 7103 * 7104 * Some operating systems (Solaris 2.6 and higher (but not 7105 * Solaris 2.5, go figure)) generate READABLE and 7106 * EXCEPTION events when select()'ing [*] on a plain file, 7107 * even if EOF was not yet reached. This is a problem in 7108 * the following situation: 7109 * 7110 * - An extension asks to get both READABLE and EXCEPTION 7111 * events. 7112 * - It reads data into a buffer smaller than the buffer 7113 * used by Tcl itself. 7114 * - It does not process all events in the event queue, but 7115 * only only one, at least in some situations. 7116 * 7117 * In that case we can get into a situation where 7118 * 7119 * - Tcl drops READABLE here, because it has data in its own 7120 * buffers waiting to be read by the extension. 7121 * - A READABLE event is syntesized via timer. 7122 * - The OS still reports the EXCEPTION condition on the file. 7123 * - And the extension gets the EXCPTION event first, and 7124 * handles this as EOF. 7125 * 7126 * End result ==> Premature end of reading from a file. 7127 * 7128 * The concrete example is 'Expect', and its [expect] 7129 * command (and at the C-level, deep in the bowels of 7130 * Expect, 'exp_get_next_event'. See marker 'SunOS' for 7131 * commentary in that function too). 7132 * 7133 * [*] As the Tcl notifier does. See also for marker 7134 * 'SunOS' in file 'exp_event.c' of Expect. 7135 * 7136 * Our solution here is to drop the interest in the 7137 * EXCEPTION events too. This compiles on all platforms, 7138 * and also passes the testsuite on all of them. 7139 */ 7140 7141 mask &= ~TCL_EXCEPTION; 7142 7143 if (!statePtr->timer) { 7144 statePtr->timer = Tcl_CreateTimerHandler(0, ChannelTimerProc, 7145 (ClientData) chanPtr); 7146 } 7147 } 7148 } 7149 (chanPtr->typePtr->watchProc)(chanPtr->instanceData, mask); 7150} 7151 7152/* 7153 *---------------------------------------------------------------------- 7154 * 7155 * ChannelTimerProc -- 7156 * 7157 * Timer handler scheduled by UpdateInterest to monitor the 7158 * channel buffers until they are empty. 7159 * 7160 * Results: 7161 * None. 7162 * 7163 * Side effects: 7164 * May invoke channel handlers. 7165 * 7166 *---------------------------------------------------------------------- 7167 */ 7168 7169static void 7170ChannelTimerProc(clientData) 7171 ClientData clientData; 7172{ 7173 Channel *chanPtr = (Channel *) clientData; 7174 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 7175 7176 if (!(statePtr->flags & CHANNEL_NEED_MORE_DATA) 7177 && (statePtr->interestMask & TCL_READABLE) 7178 && (statePtr->inQueueHead != (ChannelBuffer *) NULL) 7179 && (statePtr->inQueueHead->nextRemoved < 7180 statePtr->inQueueHead->nextAdded)) { 7181 /* 7182 * Restart the timer in case a channel handler reenters the 7183 * event loop before UpdateInterest gets called by Tcl_NotifyChannel. 7184 */ 7185 7186 statePtr->timer = Tcl_CreateTimerHandler(0, ChannelTimerProc, 7187 (ClientData) chanPtr); 7188 7189#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 7190 /* Set the TIMER flag to notify the higher levels that the 7191 * driver might have no data for us. We do this only if we are 7192 * in non-blocking mode and the driver has no BlockModeProc 7193 * because only then we really don't know if the driver will 7194 * block or not. A similar test is done in "PeekAhead". 7195 */ 7196 7197 if ((statePtr->flags & CHANNEL_NONBLOCKING) && 7198 (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL)) { 7199 statePtr->flags |= CHANNEL_TIMER_FEV; 7200 } 7201#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 7202 7203 Tcl_Preserve((ClientData) statePtr); 7204 Tcl_NotifyChannel((Tcl_Channel)chanPtr, TCL_READABLE); 7205 7206#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 7207 statePtr->flags &= ~CHANNEL_TIMER_FEV; 7208#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 7209 7210 Tcl_Release((ClientData) statePtr); 7211 } else { 7212 statePtr->timer = NULL; 7213 UpdateInterest(chanPtr); 7214 } 7215} 7216 7217/* 7218 *---------------------------------------------------------------------- 7219 * 7220 * Tcl_CreateChannelHandler -- 7221 * 7222 * Arrange for a given procedure to be invoked whenever the 7223 * channel indicated by the chanPtr arg becomes readable or 7224 * writable. 7225 * 7226 * Results: 7227 * None. 7228 * 7229 * Side effects: 7230 * From now on, whenever the I/O channel given by chanPtr becomes 7231 * ready in the way indicated by mask, proc will be invoked. 7232 * See the manual entry for details on the calling sequence 7233 * to proc. If there is already an event handler for chan, proc 7234 * and clientData, then the mask will be updated. 7235 * 7236 *---------------------------------------------------------------------- 7237 */ 7238 7239void 7240Tcl_CreateChannelHandler(chan, mask, proc, clientData) 7241 Tcl_Channel chan; /* The channel to create the handler for. */ 7242 int mask; /* OR'ed combination of TCL_READABLE, 7243 * TCL_WRITABLE, and TCL_EXCEPTION: 7244 * indicates conditions under which 7245 * proc should be called. Use 0 to 7246 * disable a registered handler. */ 7247 Tcl_ChannelProc *proc; /* Procedure to call for each 7248 * selected event. */ 7249 ClientData clientData; /* Arbitrary data to pass to proc. */ 7250{ 7251 ChannelHandler *chPtr; 7252 Channel *chanPtr = (Channel *) chan; 7253 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 7254 7255 /* 7256 * Check whether this channel handler is not already registered. If 7257 * it is not, create a new record, else reuse existing record (smash 7258 * current values). 7259 */ 7260 7261 for (chPtr = statePtr->chPtr; 7262 chPtr != (ChannelHandler *) NULL; 7263 chPtr = chPtr->nextPtr) { 7264 if ((chPtr->chanPtr == chanPtr) && (chPtr->proc == proc) && 7265 (chPtr->clientData == clientData)) { 7266 break; 7267 } 7268 } 7269 if (chPtr == (ChannelHandler *) NULL) { 7270 chPtr = (ChannelHandler *) ckalloc((unsigned) sizeof(ChannelHandler)); 7271 chPtr->mask = 0; 7272 chPtr->proc = proc; 7273 chPtr->clientData = clientData; 7274 chPtr->chanPtr = chanPtr; 7275 chPtr->nextPtr = statePtr->chPtr; 7276 statePtr->chPtr = chPtr; 7277 } 7278 7279 /* 7280 * The remainder of the initialization below is done regardless of 7281 * whether or not this is a new record or a modification of an old 7282 * one. 7283 */ 7284 7285 chPtr->mask = mask; 7286 7287 /* 7288 * Recompute the interest mask for the channel - this call may actually 7289 * be disabling an existing handler. 7290 */ 7291 7292 statePtr->interestMask = 0; 7293 for (chPtr = statePtr->chPtr; 7294 chPtr != (ChannelHandler *) NULL; 7295 chPtr = chPtr->nextPtr) { 7296 statePtr->interestMask |= chPtr->mask; 7297 } 7298 7299 UpdateInterest(statePtr->topChanPtr); 7300} 7301 7302/* 7303 *---------------------------------------------------------------------- 7304 * 7305 * Tcl_DeleteChannelHandler -- 7306 * 7307 * Cancel a previously arranged callback arrangement for an IO 7308 * channel. 7309 * 7310 * Results: 7311 * None. 7312 * 7313 * Side effects: 7314 * If a callback was previously registered for this chan, proc and 7315 * clientData , it is removed and the callback will no longer be called 7316 * when the channel becomes ready for IO. 7317 * 7318 *---------------------------------------------------------------------- 7319 */ 7320 7321void 7322Tcl_DeleteChannelHandler(chan, proc, clientData) 7323 Tcl_Channel chan; /* The channel for which to remove the 7324 * callback. */ 7325 Tcl_ChannelProc *proc; /* The procedure in the callback to delete. */ 7326 ClientData clientData; /* The client data in the callback 7327 * to delete. */ 7328 7329{ 7330 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 7331 ChannelHandler *chPtr, *prevChPtr; 7332 Channel *chanPtr = (Channel *) chan; 7333 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 7334 NextChannelHandler *nhPtr; 7335 7336 /* 7337 * Find the entry and the previous one in the list. 7338 */ 7339 7340 for (prevChPtr = (ChannelHandler *) NULL, chPtr = statePtr->chPtr; 7341 chPtr != (ChannelHandler *) NULL; 7342 chPtr = chPtr->nextPtr) { 7343 if ((chPtr->chanPtr == chanPtr) && (chPtr->clientData == clientData) 7344 && (chPtr->proc == proc)) { 7345 break; 7346 } 7347 prevChPtr = chPtr; 7348 } 7349 7350 /* 7351 * If not found, return without doing anything. 7352 */ 7353 7354 if (chPtr == (ChannelHandler *) NULL) { 7355 return; 7356 } 7357 7358 /* 7359 * If ChannelHandlerEventProc is about to process this handler, tell it to 7360 * process the next one instead - we are going to delete *this* one. 7361 */ 7362 7363 for (nhPtr = tsdPtr->nestedHandlerPtr; 7364 nhPtr != (NextChannelHandler *) NULL; 7365 nhPtr = nhPtr->nestedHandlerPtr) { 7366 if (nhPtr->nextHandlerPtr == chPtr) { 7367 nhPtr->nextHandlerPtr = chPtr->nextPtr; 7368 } 7369 } 7370 7371 /* 7372 * Splice it out of the list of channel handlers. 7373 */ 7374 7375 if (prevChPtr == (ChannelHandler *) NULL) { 7376 statePtr->chPtr = chPtr->nextPtr; 7377 } else { 7378 prevChPtr->nextPtr = chPtr->nextPtr; 7379 } 7380 ckfree((char *) chPtr); 7381 7382 /* 7383 * Recompute the interest list for the channel, so that infinite loops 7384 * will not result if Tcl_DeleteChannelHandler is called inside an 7385 * event. 7386 */ 7387 7388 statePtr->interestMask = 0; 7389 for (chPtr = statePtr->chPtr; 7390 chPtr != (ChannelHandler *) NULL; 7391 chPtr = chPtr->nextPtr) { 7392 statePtr->interestMask |= chPtr->mask; 7393 } 7394 7395 UpdateInterest(statePtr->topChanPtr); 7396} 7397 7398/* 7399 *---------------------------------------------------------------------- 7400 * 7401 * DeleteScriptRecord -- 7402 * 7403 * Delete a script record for this combination of channel, interp 7404 * and mask. 7405 * 7406 * Results: 7407 * None. 7408 * 7409 * Side effects: 7410 * Deletes a script record and cancels a channel event handler. 7411 * 7412 *---------------------------------------------------------------------- 7413 */ 7414 7415static void 7416DeleteScriptRecord(interp, chanPtr, mask) 7417 Tcl_Interp *interp; /* Interpreter in which script was to be 7418 * executed. */ 7419 Channel *chanPtr; /* The channel for which to delete the 7420 * script record (if any). */ 7421 int mask; /* Events in mask must exactly match mask 7422 * of script to delete. */ 7423{ 7424 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 7425 EventScriptRecord *esPtr, *prevEsPtr; 7426 7427 for (esPtr = statePtr->scriptRecordPtr, 7428 prevEsPtr = (EventScriptRecord *) NULL; 7429 esPtr != (EventScriptRecord *) NULL; 7430 prevEsPtr = esPtr, esPtr = esPtr->nextPtr) { 7431 if ((esPtr->interp == interp) && (esPtr->mask == mask)) { 7432 if (esPtr == statePtr->scriptRecordPtr) { 7433 statePtr->scriptRecordPtr = esPtr->nextPtr; 7434 } else { 7435 prevEsPtr->nextPtr = esPtr->nextPtr; 7436 } 7437 7438 Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, 7439 TclChannelEventScriptInvoker, (ClientData) esPtr); 7440 7441 Tcl_DecrRefCount(esPtr->scriptPtr); 7442 ckfree((char *) esPtr); 7443 7444 break; 7445 } 7446 } 7447} 7448 7449/* 7450 *---------------------------------------------------------------------- 7451 * 7452 * CreateScriptRecord -- 7453 * 7454 * Creates a record to store a script to be executed when a specific 7455 * event fires on a specific channel. 7456 * 7457 * Results: 7458 * None. 7459 * 7460 * Side effects: 7461 * Causes the script to be stored for later execution. 7462 * 7463 *---------------------------------------------------------------------- 7464 */ 7465 7466static void 7467CreateScriptRecord(interp, chanPtr, mask, scriptPtr) 7468 Tcl_Interp *interp; /* Interpreter in which to execute 7469 * the stored script. */ 7470 Channel *chanPtr; /* Channel for which script is to 7471 * be stored. */ 7472 int mask; /* Set of events for which script 7473 * will be invoked. */ 7474 Tcl_Obj *scriptPtr; /* Pointer to script object. */ 7475{ 7476 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 7477 EventScriptRecord *esPtr; 7478 7479 for (esPtr = statePtr->scriptRecordPtr; 7480 esPtr != (EventScriptRecord *) NULL; 7481 esPtr = esPtr->nextPtr) { 7482 if ((esPtr->interp == interp) && (esPtr->mask == mask)) { 7483 Tcl_DecrRefCount(esPtr->scriptPtr); 7484 esPtr->scriptPtr = (Tcl_Obj *) NULL; 7485 break; 7486 } 7487 } 7488 if (esPtr == (EventScriptRecord *) NULL) { 7489 esPtr = (EventScriptRecord *) ckalloc((unsigned) 7490 sizeof(EventScriptRecord)); 7491 Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask, 7492 TclChannelEventScriptInvoker, (ClientData) esPtr); 7493 esPtr->nextPtr = statePtr->scriptRecordPtr; 7494 statePtr->scriptRecordPtr = esPtr; 7495 } 7496 esPtr->chanPtr = chanPtr; 7497 esPtr->interp = interp; 7498 esPtr->mask = mask; 7499 Tcl_IncrRefCount(scriptPtr); 7500 esPtr->scriptPtr = scriptPtr; 7501} 7502 7503/* 7504 *---------------------------------------------------------------------- 7505 * 7506 * TclChannelEventScriptInvoker -- 7507 * 7508 * Invokes a script scheduled by "fileevent" for when the channel 7509 * becomes ready for IO. This function is invoked by the channel 7510 * handler which was created by the Tcl "fileevent" command. 7511 * 7512 * Results: 7513 * None. 7514 * 7515 * Side effects: 7516 * Whatever the script does. 7517 * 7518 *---------------------------------------------------------------------- 7519 */ 7520 7521void 7522TclChannelEventScriptInvoker(clientData, mask) 7523 ClientData clientData; /* The script+interp record. */ 7524 int mask; /* Not used. */ 7525{ 7526 Tcl_Interp *interp; /* Interpreter in which to eval the script. */ 7527 Channel *chanPtr; /* The channel for which this handler is 7528 * registered. */ 7529 EventScriptRecord *esPtr; /* The event script + interpreter to eval it 7530 * in. */ 7531 int result; /* Result of call to eval script. */ 7532 7533 esPtr = (EventScriptRecord *) clientData; 7534 chanPtr = esPtr->chanPtr; 7535 mask = esPtr->mask; 7536 interp = esPtr->interp; 7537 7538 /* 7539 * We must preserve the interpreter so we can report errors on it 7540 * later. Note that we do not need to preserve the channel because 7541 * that is done by Tcl_NotifyChannel before calling channel handlers. 7542 */ 7543 7544 Tcl_Preserve((ClientData) interp); 7545 result = Tcl_EvalObjEx(interp, esPtr->scriptPtr, TCL_EVAL_GLOBAL); 7546 7547 /* 7548 * On error, cause a background error and remove the channel handler 7549 * and the script record. 7550 * 7551 * NOTE: Must delete channel handler before causing the background error 7552 * because the background error may want to reinstall the handler. 7553 */ 7554 7555 if (result != TCL_OK) { 7556 if (chanPtr->typePtr != NULL) { 7557 DeleteScriptRecord(interp, chanPtr, mask); 7558 } 7559 Tcl_BackgroundError(interp); 7560 } 7561 Tcl_Release((ClientData) interp); 7562} 7563 7564/* 7565 *---------------------------------------------------------------------- 7566 * 7567 * Tcl_FileEventObjCmd -- 7568 * 7569 * This procedure implements the "fileevent" Tcl command. See the 7570 * user documentation for details on what it does. This command is 7571 * based on the Tk command "fileevent" which in turn is based on work 7572 * contributed by Mark Diekhans. 7573 * 7574 * Results: 7575 * A standard Tcl result. 7576 * 7577 * Side effects: 7578 * May create a channel handler for the specified channel. 7579 * 7580 *---------------------------------------------------------------------- 7581 */ 7582 7583 /* ARGSUSED */ 7584int 7585Tcl_FileEventObjCmd(clientData, interp, objc, objv) 7586 ClientData clientData; /* Not used. */ 7587 Tcl_Interp *interp; /* Interpreter in which the channel 7588 * for which to create the handler 7589 * is found. */ 7590 int objc; /* Number of arguments. */ 7591 Tcl_Obj *CONST objv[]; /* Argument objects. */ 7592{ 7593 Channel *chanPtr; /* The channel to create 7594 * the handler for. */ 7595 ChannelState *statePtr; /* state info for channel */ 7596 Tcl_Channel chan; /* The opaque type for the channel. */ 7597 char *chanName; 7598 int modeIndex; /* Index of mode argument. */ 7599 int mask; 7600 static CONST char *modeOptions[] = {"readable", "writable", NULL}; 7601 static int maskArray[] = {TCL_READABLE, TCL_WRITABLE}; 7602 7603 if ((objc != 3) && (objc != 4)) { 7604 Tcl_WrongNumArgs(interp, 1, objv, "channelId event ?script?"); 7605 return TCL_ERROR; 7606 } 7607 if (Tcl_GetIndexFromObj(interp, objv[2], modeOptions, "event name", 0, 7608 &modeIndex) != TCL_OK) { 7609 return TCL_ERROR; 7610 } 7611 mask = maskArray[modeIndex]; 7612 7613 chanName = Tcl_GetString(objv[1]); 7614 chan = Tcl_GetChannel(interp, chanName, NULL); 7615 if (chan == (Tcl_Channel) NULL) { 7616 return TCL_ERROR; 7617 } 7618 chanPtr = (Channel *) chan; 7619 statePtr = chanPtr->state; 7620 if ((statePtr->flags & mask) == 0) { 7621 Tcl_AppendResult(interp, "channel is not ", 7622 (mask == TCL_READABLE) ? "readable" : "writable", 7623 (char *) NULL); 7624 return TCL_ERROR; 7625 } 7626 7627 /* 7628 * If we are supposed to return the script, do so. 7629 */ 7630 7631 if (objc == 3) { 7632 EventScriptRecord *esPtr; 7633 for (esPtr = statePtr->scriptRecordPtr; 7634 esPtr != (EventScriptRecord *) NULL; 7635 esPtr = esPtr->nextPtr) { 7636 if ((esPtr->interp == interp) && (esPtr->mask == mask)) { 7637 Tcl_SetObjResult(interp, esPtr->scriptPtr); 7638 break; 7639 } 7640 } 7641 return TCL_OK; 7642 } 7643 7644 /* 7645 * If we are supposed to delete a stored script, do so. 7646 */ 7647 7648 if (*(Tcl_GetString(objv[3])) == '\0') { 7649 DeleteScriptRecord(interp, chanPtr, mask); 7650 return TCL_OK; 7651 } 7652 7653 /* 7654 * Make the script record that will link between the event and the 7655 * script to invoke. This also creates a channel event handler which 7656 * will evaluate the script in the supplied interpreter. 7657 */ 7658 7659 CreateScriptRecord(interp, chanPtr, mask, objv[3]); 7660 7661 return TCL_OK; 7662} 7663 7664/* 7665 *---------------------------------------------------------------------- 7666 * 7667 * TclCopyChannel -- 7668 * 7669 * This routine copies data from one channel to another, either 7670 * synchronously or asynchronously. If a command script is 7671 * supplied, the operation runs in the background. The script 7672 * is invoked when the copy completes. Otherwise the function 7673 * waits until the copy is completed before returning. 7674 * 7675 * Results: 7676 * A standard Tcl result. 7677 * 7678 * Side effects: 7679 * May schedule a background copy operation that causes both 7680 * channels to be marked busy. 7681 * 7682 *---------------------------------------------------------------------- 7683 */ 7684 7685int 7686TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr) 7687 Tcl_Interp *interp; /* Current interpreter. */ 7688 Tcl_Channel inChan; /* Channel to read from. */ 7689 Tcl_Channel outChan; /* Channel to write to. */ 7690 int toRead; /* Amount of data to copy, or -1 for all. */ 7691 Tcl_Obj *cmdPtr; /* Pointer to script to execute or NULL. */ 7692{ 7693 Channel *inPtr = (Channel *) inChan; 7694 Channel *outPtr = (Channel *) outChan; 7695 ChannelState *inStatePtr, *outStatePtr; 7696 int readFlags, writeFlags; 7697 CopyState *csPtr; 7698 int nonBlocking = (cmdPtr) ? CHANNEL_NONBLOCKING : 0; 7699 7700 inStatePtr = inPtr->state; 7701 outStatePtr = outPtr->state; 7702 7703 if (BUSY_STATE(inStatePtr,TCL_READABLE)) { 7704 if (interp) { 7705 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"", 7706 Tcl_GetChannelName(inChan), "\" is busy", NULL); 7707 } 7708 return TCL_ERROR; 7709 } 7710 if (BUSY_STATE(outStatePtr,TCL_WRITABLE)) { 7711 if (interp) { 7712 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"", 7713 Tcl_GetChannelName(outChan), "\" is busy", NULL); 7714 } 7715 return TCL_ERROR; 7716 } 7717 7718 readFlags = inStatePtr->flags; 7719 writeFlags = outStatePtr->flags; 7720 7721 /* 7722 * Set up the blocking mode appropriately. Background copies need 7723 * non-blocking channels. Foreground copies need blocking channels. 7724 * If there is an error, restore the old blocking mode. 7725 */ 7726 7727 if (nonBlocking != (readFlags & CHANNEL_NONBLOCKING)) { 7728 if (SetBlockMode(interp, inPtr, 7729 nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING) 7730 != TCL_OK) { 7731 return TCL_ERROR; 7732 } 7733 } 7734 if (inPtr != outPtr) { 7735 if (nonBlocking != (writeFlags & CHANNEL_NONBLOCKING)) { 7736 if (SetBlockMode(NULL, outPtr, 7737 nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING) 7738 != TCL_OK) { 7739 if (nonBlocking != (readFlags & CHANNEL_NONBLOCKING)) { 7740 SetBlockMode(NULL, inPtr, 7741 (readFlags & CHANNEL_NONBLOCKING) 7742 ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); 7743 return TCL_ERROR; 7744 } 7745 } 7746 } 7747 } 7748 7749 /* 7750 * Make sure the output side is unbuffered. 7751 */ 7752 7753 outStatePtr->flags = (outStatePtr->flags & ~(CHANNEL_LINEBUFFERED)) 7754 | CHANNEL_UNBUFFERED; 7755 7756 /* 7757 * Allocate a new CopyState to maintain info about the current copy in 7758 * progress. This structure will be deallocated when the copy is 7759 * completed. 7760 */ 7761 7762 csPtr = (CopyState*) ckalloc(sizeof(CopyState) + inStatePtr->bufSize); 7763 csPtr->bufSize = inStatePtr->bufSize; 7764 csPtr->readPtr = inPtr; 7765 csPtr->writePtr = outPtr; 7766 csPtr->readFlags = readFlags; 7767 csPtr->writeFlags = writeFlags; 7768 csPtr->toRead = toRead; 7769 csPtr->total = 0; 7770 csPtr->interp = interp; 7771 if (cmdPtr) { 7772 Tcl_IncrRefCount(cmdPtr); 7773 } 7774 csPtr->cmdPtr = cmdPtr; 7775 7776 inStatePtr->csPtrR = csPtr; 7777 outStatePtr->csPtrW = csPtr; 7778 7779 /* 7780 * Start copying data between the channels. 7781 */ 7782 7783 return CopyData(csPtr, 0); 7784} 7785 7786/* 7787 *---------------------------------------------------------------------- 7788 * 7789 * CopyData -- 7790 * 7791 * This function implements the lowest level of the copying 7792 * mechanism for TclCopyChannel. 7793 * 7794 * Results: 7795 * Returns TCL_OK on success, else TCL_ERROR. 7796 * 7797 * Side effects: 7798 * Moves data between channels, may create channel handlers. 7799 * 7800 *---------------------------------------------------------------------- 7801 */ 7802 7803static int 7804CopyData(csPtr, mask) 7805 CopyState *csPtr; /* State of copy operation. */ 7806 int mask; /* Current channel event flags. */ 7807{ 7808 Tcl_Interp *interp; 7809 Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL; 7810 Tcl_Channel inChan, outChan; 7811 ChannelState *inStatePtr, *outStatePtr; 7812 int result = TCL_OK, size, total, sizeb; 7813 char* buffer; 7814 7815 int inBinary, outBinary, sameEncoding; /* Encoding control */ 7816 int underflow; /* input underflow */ 7817 7818 inChan = (Tcl_Channel) csPtr->readPtr; 7819 outChan = (Tcl_Channel) csPtr->writePtr; 7820 inStatePtr = csPtr->readPtr->state; 7821 outStatePtr = csPtr->writePtr->state; 7822 interp = csPtr->interp; 7823 cmdPtr = csPtr->cmdPtr; 7824 7825 /* 7826 * Copy the data the slow way, using the translation mechanism. 7827 * 7828 * Note: We have make sure that we use the topmost channel in a stack 7829 * for the copying. The caller uses Tcl_GetChannel to access it, and 7830 * thus gets the bottom of the stack. 7831 */ 7832 7833 inBinary = (inStatePtr->encoding == NULL); 7834 outBinary = (outStatePtr->encoding == NULL); 7835 sameEncoding = (inStatePtr->encoding == outStatePtr->encoding); 7836 7837 if (!(inBinary || sameEncoding)) { 7838 bufObj = Tcl_NewObj (); 7839 Tcl_IncrRefCount (bufObj); 7840 } 7841 7842 while (csPtr->toRead != 0) { 7843 /* 7844 * Check for unreported background errors. 7845 */ 7846 7847 if (inStatePtr->unreportedError != 0) { 7848 Tcl_SetErrno(inStatePtr->unreportedError); 7849 inStatePtr->unreportedError = 0; 7850 goto readError; 7851 } 7852 if (outStatePtr->unreportedError != 0) { 7853 Tcl_SetErrno(outStatePtr->unreportedError); 7854 outStatePtr->unreportedError = 0; 7855 goto writeError; 7856 } 7857 7858 if (cmdPtr && (mask == 0)) { 7859 /* 7860 * In async mode, we skip reading synchronously and fake an 7861 * underflow instead to prime the readable fileevent. 7862 */ 7863 7864 size = 0; 7865 underflow = 1; 7866 } else { 7867 /* 7868 * Read up to bufSize bytes. 7869 */ 7870 7871 if ((csPtr->toRead == -1) || (csPtr->toRead > csPtr->bufSize)) { 7872 sizeb = csPtr->bufSize; 7873 } else { 7874 sizeb = csPtr->toRead; 7875 } 7876 7877 if (inBinary || sameEncoding) { 7878 size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb); 7879 } else { 7880 size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, 0 /* No append */); 7881 } 7882 underflow = (size >= 0) && (size < sizeb); /* input underflow */ 7883 } 7884 7885 if (size < 0) { 7886 readError: 7887 errObj = Tcl_NewObj(); 7888 Tcl_AppendStringsToObj(errObj, "error reading \"", 7889 Tcl_GetChannelName(inChan), "\": ", 7890 Tcl_PosixError(interp), (char *) NULL); 7891 break; 7892 } else if (underflow) { 7893 /* 7894 * We had an underflow on the read side. If we are at 7895 * EOF, and not in the synchronous part of an asynchronous 7896 * fcopy, then the copying is done, otherwise set up a 7897 * channel handler to detect when the channel becomes 7898 * readable again. 7899 */ 7900 7901 if ((size == 0) && Tcl_Eof(inChan) && !(cmdPtr && (mask == 0))) { 7902 break; 7903 } 7904 if (((!Tcl_Eof(inChan)) || (cmdPtr && (mask == 0))) && 7905 !(mask & TCL_READABLE)) { 7906 if (mask & TCL_WRITABLE) { 7907 Tcl_DeleteChannelHandler(outChan, CopyEventProc, 7908 (ClientData) csPtr); 7909 } 7910 Tcl_CreateChannelHandler(inChan, TCL_READABLE, 7911 CopyEventProc, (ClientData) csPtr); 7912 } 7913 if (size == 0) { 7914 if (bufObj != (Tcl_Obj*) NULL) { 7915 Tcl_DecrRefCount (bufObj); 7916 bufObj = (Tcl_Obj*) NULL; 7917 } 7918 return TCL_OK; 7919 } 7920 } 7921 7922 /* 7923 * Now write the buffer out. 7924 */ 7925 7926 if (inBinary || sameEncoding) { 7927 buffer = csPtr->buffer; 7928 sizeb = size; 7929 } else { 7930 buffer = Tcl_GetStringFromObj (bufObj, &sizeb); 7931 } 7932 7933 if (outBinary || sameEncoding) { 7934 sizeb = DoWrite(outStatePtr->topChanPtr, buffer, sizeb); 7935 } else { 7936 sizeb = DoWriteChars(outStatePtr->topChanPtr, buffer, sizeb); 7937 } 7938 7939 /* 7940 * [Bug 2895565]. At this point 'size' still contains the number of 7941 * bytes or characters which have been read. We keep this to later to 7942 * update the totals and toRead information, see marker (UP) below. We 7943 * must not overwrite it with 'sizeb', which is the number of written 7944 * bytes or characters, and both EOL translation and encoding 7945 * conversion may have changed this number unpredictably in relation 7946 * to 'size' (It can be smaller or larger, in the latter case able to 7947 * drive toRead below -1, causing infinite looping). Completely 7948 * unsuitable for updating totals and toRead. 7949 */ 7950 7951 if (sizeb < 0) { 7952 writeError: 7953 errObj = Tcl_NewObj(); 7954 Tcl_AppendStringsToObj(errObj, "error writing \"", 7955 Tcl_GetChannelName(outChan), "\": ", 7956 Tcl_PosixError(interp), (char *) NULL); 7957 break; 7958 } 7959 7960 /* 7961 * Update the current byte count. Do it now so the count is 7962 * valid before a return or break takes us out of the loop. 7963 * The invariant at the top of the loop should be that 7964 * csPtr->toRead holds the number of bytes left to copy. 7965 */ 7966 7967 if (csPtr->toRead != -1) { 7968 csPtr->toRead -= size; 7969 } 7970 csPtr->total += size; 7971 7972 /* 7973 * Break loop if EOF && (size>0) 7974 */ 7975 7976 if (Tcl_Eof(inChan)) { 7977 break; 7978 } 7979 7980 /* 7981 * Check to see if the write is happening in the background. If so, 7982 * stop copying and wait for the channel to become writable again. 7983 * After input underflow we already installed a readable handler 7984 * therefore we don't need a writable handler. 7985 */ 7986 7987 if ( ! underflow && (outStatePtr->flags & BG_FLUSH_SCHEDULED) ) { 7988 if (!(mask & TCL_WRITABLE)) { 7989 if (mask & TCL_READABLE) { 7990 Tcl_DeleteChannelHandler(inChan, CopyEventProc, 7991 (ClientData) csPtr); 7992 } 7993 Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, 7994 CopyEventProc, (ClientData) csPtr); 7995 } 7996 if (bufObj != (Tcl_Obj*) NULL) { 7997 Tcl_DecrRefCount (bufObj); 7998 bufObj = (Tcl_Obj*) NULL; 7999 } 8000 return TCL_OK; 8001 } 8002 8003 /* 8004 * For background copies, we only do one buffer per invocation so 8005 * we don't starve the rest of the system. 8006 */ 8007 8008 if (cmdPtr && (csPtr->toRead != 0)) { 8009 /* 8010 * The first time we enter this code, there won't be a 8011 * channel handler established yet, so do it here. 8012 */ 8013 8014 if (mask == 0) { 8015 Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, 8016 CopyEventProc, (ClientData) csPtr); 8017 } 8018 if (bufObj != (Tcl_Obj*) NULL) { 8019 Tcl_DecrRefCount (bufObj); 8020 bufObj = (Tcl_Obj*) NULL; 8021 } 8022 return TCL_OK; 8023 } 8024 } /* while */ 8025 8026 if (bufObj != (Tcl_Obj*) NULL) { 8027 Tcl_DecrRefCount (bufObj); 8028 bufObj = (Tcl_Obj*) NULL; 8029 } 8030 8031 /* 8032 * Make the callback or return the number of bytes transferred. 8033 * The local total is used because StopCopy frees csPtr. 8034 */ 8035 8036 total = csPtr->total; 8037 if (cmdPtr && interp) { 8038 /* 8039 * Get a private copy of the command so we can mutate it 8040 * by adding arguments. Note that StopCopy frees our saved 8041 * reference to the original command obj. 8042 */ 8043 8044 cmdPtr = Tcl_DuplicateObj(cmdPtr); 8045 Tcl_IncrRefCount(cmdPtr); 8046 StopCopy(csPtr); 8047 Tcl_Preserve((ClientData) interp); 8048 8049 Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(total)); 8050 if (errObj) { 8051 Tcl_ListObjAppendElement(interp, cmdPtr, errObj); 8052 } 8053 if (Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL) != TCL_OK) { 8054 Tcl_BackgroundError(interp); 8055 result = TCL_ERROR; 8056 } 8057 Tcl_DecrRefCount(cmdPtr); 8058 Tcl_Release((ClientData) interp); 8059 } else { 8060 StopCopy(csPtr); 8061 if (interp) { 8062 if (errObj) { 8063 Tcl_SetObjResult(interp, errObj); 8064 result = TCL_ERROR; 8065 } else { 8066 Tcl_ResetResult(interp); 8067 Tcl_SetIntObj(Tcl_GetObjResult(interp), total); 8068 } 8069 } 8070 } 8071 return result; 8072} 8073 8074/* 8075 *---------------------------------------------------------------------- 8076 * 8077 * DoRead -- 8078 * 8079 * Reads a given number of bytes from a channel. 8080 * 8081 * No encoding conversions are applied to the bytes being read. 8082 * 8083 * Results: 8084 * The number of characters read, or -1 on error. Use Tcl_GetErrno() 8085 * to retrieve the error code for the error that occurred. 8086 * 8087 * Side effects: 8088 * May cause input to be buffered. 8089 * 8090 *---------------------------------------------------------------------- 8091 */ 8092 8093static int 8094DoRead(chanPtr, bufPtr, toRead) 8095 Channel *chanPtr; /* The channel from which to read. */ 8096 char *bufPtr; /* Where to store input read. */ 8097 int toRead; /* Maximum number of bytes to read. */ 8098{ 8099 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 8100 int copied; /* How many characters were copied into 8101 * the result string? */ 8102 int copiedNow; /* How many characters were copied from 8103 * the current input buffer? */ 8104 int result; /* Of calling GetInput. */ 8105 8106 /* 8107 * If we have not encountered a sticky EOF, clear the EOF bit. Either 8108 * way clear the BLOCKED bit. We want to discover these anew during 8109 * each operation. 8110 */ 8111 8112 if (!(statePtr->flags & CHANNEL_STICKY_EOF)) { 8113 statePtr->flags &= ~CHANNEL_EOF; 8114 } 8115 statePtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA); 8116 8117 for (copied = 0; copied < toRead; copied += copiedNow) { 8118 copiedNow = CopyAndTranslateBuffer(statePtr, bufPtr + copied, 8119 toRead - copied); 8120 if (copiedNow == 0) { 8121 if (statePtr->flags & CHANNEL_EOF) { 8122 goto done; 8123 } 8124 if (statePtr->flags & CHANNEL_BLOCKED) { 8125 if (statePtr->flags & CHANNEL_NONBLOCKING) { 8126 goto done; 8127 } 8128 statePtr->flags &= (~(CHANNEL_BLOCKED)); 8129 } 8130 result = GetInput(chanPtr); 8131 if (result != 0) { 8132 if (result != EAGAIN) { 8133 copied = -1; 8134 } 8135 goto done; 8136 } 8137 } 8138 } 8139 8140 statePtr->flags &= (~(CHANNEL_BLOCKED)); 8141 8142 done: 8143 /* 8144 * Update the notifier state so we don't block while there is still 8145 * data in the buffers. 8146 */ 8147 8148 UpdateInterest(chanPtr); 8149 return copied; 8150} 8151 8152/* 8153 *---------------------------------------------------------------------- 8154 * 8155 * CopyAndTranslateBuffer -- 8156 * 8157 * Copy at most one buffer of input to the result space, doing 8158 * eol translations according to mode in effect currently. 8159 * 8160 * Results: 8161 * Number of bytes stored in the result buffer (as opposed to the 8162 * number of bytes read from the channel). May return 8163 * zero if no input is available to be translated. 8164 * 8165 * Side effects: 8166 * Consumes buffered input. May deallocate one buffer. 8167 * 8168 *---------------------------------------------------------------------- 8169 */ 8170 8171static int 8172CopyAndTranslateBuffer(statePtr, result, space) 8173 ChannelState *statePtr; /* Channel state from which to read input. */ 8174 char *result; /* Where to store the copied input. */ 8175 int space; /* How many bytes are available in result 8176 * to store the copied input? */ 8177{ 8178 ChannelBuffer *bufPtr; /* The buffer from which to copy bytes. */ 8179 int bytesInBuffer; /* How many bytes are available to be 8180 * copied in the current input buffer? */ 8181 int copied; /* How many characters were already copied 8182 * into the destination space? */ 8183 int i; /* Iterates over the copied input looking 8184 * for the input eofChar. */ 8185 8186 /* 8187 * If there is no input at all, return zero. The invariant is that either 8188 * there is no buffer in the queue, or if the first buffer is empty, it 8189 * is also the last buffer (and thus there is no input in the queue). 8190 * Note also that if the buffer is empty, we leave it in the queue. 8191 */ 8192 8193 if (statePtr->inQueueHead == (ChannelBuffer *) NULL) { 8194 return 0; 8195 } 8196 bufPtr = statePtr->inQueueHead; 8197 bytesInBuffer = bufPtr->nextAdded - bufPtr->nextRemoved; 8198 8199 copied = 0; 8200 switch (statePtr->inputTranslation) { 8201 case TCL_TRANSLATE_LF: { 8202 if (bytesInBuffer == 0) { 8203 return 0; 8204 } 8205 8206 /* 8207 * Copy the current chunk into the result buffer. 8208 */ 8209 8210 if (bytesInBuffer < space) { 8211 space = bytesInBuffer; 8212 } 8213 memcpy((VOID *) result, 8214 (VOID *) (bufPtr->buf + bufPtr->nextRemoved), 8215 (size_t) space); 8216 bufPtr->nextRemoved += space; 8217 copied = space; 8218 break; 8219 } 8220 case TCL_TRANSLATE_CR: { 8221 char *end; 8222 8223 if (bytesInBuffer == 0) { 8224 return 0; 8225 } 8226 8227 /* 8228 * Copy the current chunk into the result buffer, then 8229 * replace all \r with \n. 8230 */ 8231 8232 if (bytesInBuffer < space) { 8233 space = bytesInBuffer; 8234 } 8235 memcpy((VOID *) result, 8236 (VOID *) (bufPtr->buf + bufPtr->nextRemoved), 8237 (size_t) space); 8238 bufPtr->nextRemoved += space; 8239 copied = space; 8240 8241 for (end = result + copied; result < end; result++) { 8242 if (*result == '\r') { 8243 *result = '\n'; 8244 } 8245 } 8246 break; 8247 } 8248 case TCL_TRANSLATE_CRLF: { 8249 char *src, *end, *dst; 8250 int curByte; 8251 8252 /* 8253 * If there is a held-back "\r" at EOF, produce it now. 8254 */ 8255 8256 if (bytesInBuffer == 0) { 8257 if ((statePtr->flags & (INPUT_SAW_CR | CHANNEL_EOF)) == 8258 (INPUT_SAW_CR | CHANNEL_EOF)) { 8259 result[0] = '\r'; 8260 statePtr->flags &= ~INPUT_SAW_CR; 8261 return 1; 8262 } 8263 return 0; 8264 } 8265 8266 /* 8267 * Copy the current chunk and replace "\r\n" with "\n" 8268 * (but not standalone "\r"!). 8269 */ 8270 8271 if (bytesInBuffer < space) { 8272 space = bytesInBuffer; 8273 } 8274 memcpy((VOID *) result, 8275 (VOID *) (bufPtr->buf + bufPtr->nextRemoved), 8276 (size_t) space); 8277 bufPtr->nextRemoved += space; 8278 copied = space; 8279 8280 end = result + copied; 8281 dst = result; 8282 for (src = result; src < end; src++) { 8283 curByte = *src; 8284 if (curByte == '\n') { 8285 statePtr->flags &= ~INPUT_SAW_CR; 8286 } else if (statePtr->flags & INPUT_SAW_CR) { 8287 statePtr->flags &= ~INPUT_SAW_CR; 8288 *dst = '\r'; 8289 dst++; 8290 } 8291 if (curByte == '\r') { 8292 statePtr->flags |= INPUT_SAW_CR; 8293 } else { 8294 *dst = (char) curByte; 8295 dst++; 8296 } 8297 } 8298 copied = dst - result; 8299 break; 8300 } 8301 case TCL_TRANSLATE_AUTO: { 8302 char *src, *end, *dst; 8303 int curByte; 8304 8305 if (bytesInBuffer == 0) { 8306 return 0; 8307 } 8308 8309 /* 8310 * Loop over the current buffer, converting "\r" and "\r\n" 8311 * to "\n". 8312 */ 8313 8314 if (bytesInBuffer < space) { 8315 space = bytesInBuffer; 8316 } 8317 memcpy((VOID *) result, 8318 (VOID *) (bufPtr->buf + bufPtr->nextRemoved), 8319 (size_t) space); 8320 bufPtr->nextRemoved += space; 8321 copied = space; 8322 8323 end = result + copied; 8324 dst = result; 8325 for (src = result; src < end; src++) { 8326 curByte = *src; 8327 if (curByte == '\r') { 8328 statePtr->flags |= INPUT_SAW_CR; 8329 *dst = '\n'; 8330 dst++; 8331 } else { 8332 if ((curByte != '\n') || 8333 !(statePtr->flags & INPUT_SAW_CR)) { 8334 *dst = (char) curByte; 8335 dst++; 8336 } 8337 statePtr->flags &= ~INPUT_SAW_CR; 8338 } 8339 } 8340 copied = dst - result; 8341 break; 8342 } 8343 default: { 8344 panic("unknown eol translation mode"); 8345 } 8346 } 8347 8348 /* 8349 * If an in-stream EOF character is set for this channel, check that 8350 * the input we copied so far does not contain the EOF char. If it does, 8351 * copy only up to and excluding that character. 8352 */ 8353 8354 if (statePtr->inEofChar != 0) { 8355 for (i = 0; i < copied; i++) { 8356 if (result[i] == (char) statePtr->inEofChar) { 8357 /* 8358 * Set sticky EOF so that no further input is presented 8359 * to the caller. 8360 */ 8361 8362 statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); 8363 statePtr->inputEncodingFlags |= TCL_ENCODING_END; 8364 copied = i; 8365 break; 8366 } 8367 } 8368 } 8369 8370 /* 8371 * If the current buffer is empty recycle it. 8372 */ 8373 8374 if (bufPtr->nextRemoved == bufPtr->nextAdded) { 8375 statePtr->inQueueHead = bufPtr->nextPtr; 8376 if (statePtr->inQueueHead == (ChannelBuffer *) NULL) { 8377 statePtr->inQueueTail = (ChannelBuffer *) NULL; 8378 } 8379 RecycleBuffer(statePtr, bufPtr, 0); 8380 } 8381 8382 /* 8383 * Return the number of characters copied into the result buffer. 8384 * This may be different from the number of bytes consumed, because 8385 * of EOL translations. 8386 */ 8387 8388 return copied; 8389} 8390 8391/* 8392 *---------------------------------------------------------------------- 8393 * 8394 * CopyBuffer -- 8395 * 8396 * Copy at most one buffer of input to the result space. 8397 * 8398 * Results: 8399 * Number of bytes stored in the result buffer. May return 8400 * zero if no input is available. 8401 * 8402 * Side effects: 8403 * Consumes buffered input. May deallocate one buffer. 8404 * 8405 *---------------------------------------------------------------------- 8406 */ 8407 8408static int 8409CopyBuffer(chanPtr, result, space) 8410 Channel *chanPtr; /* Channel from which to read input. */ 8411 char *result; /* Where to store the copied input. */ 8412 int space; /* How many bytes are available in result 8413 * to store the copied input? */ 8414{ 8415 ChannelBuffer *bufPtr; /* The buffer from which to copy bytes. */ 8416 int bytesInBuffer; /* How many bytes are available to be 8417 * copied in the current input buffer? */ 8418 int copied; /* How many characters were already copied 8419 * into the destination space? */ 8420 8421 /* 8422 * If there is no input at all, return zero. The invariant is that 8423 * either there is no buffer in the queue, or if the first buffer 8424 * is empty, it is also the last buffer (and thus there is no 8425 * input in the queue). Note also that if the buffer is empty, we 8426 * don't leave it in the queue, but recycle it. 8427 */ 8428 8429 if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { 8430 return 0; 8431 } 8432 bufPtr = chanPtr->inQueueHead; 8433 bytesInBuffer = bufPtr->nextAdded - bufPtr->nextRemoved; 8434 8435 copied = 0; 8436 8437 if (bytesInBuffer == 0) { 8438 RecycleBuffer(chanPtr->state, bufPtr, 0); 8439 chanPtr->inQueueHead = (ChannelBuffer*) NULL; 8440 chanPtr->inQueueTail = (ChannelBuffer*) NULL; 8441 return 0; 8442 } 8443 8444 /* 8445 * Copy the current chunk into the result buffer. 8446 */ 8447 8448 if (bytesInBuffer < space) { 8449 space = bytesInBuffer; 8450 } 8451 8452 memcpy((VOID *) result, 8453 (VOID *) (bufPtr->buf + bufPtr->nextRemoved), 8454 (size_t) space); 8455 bufPtr->nextRemoved += space; 8456 copied = space; 8457 8458 /* 8459 * We don't care about in-stream EOF characters here as the data 8460 * read here may still flow through one or more transformations, 8461 * i.e. is not in its final state yet. 8462 */ 8463 8464 /* 8465 * If the current buffer is empty recycle it. 8466 */ 8467 8468 if (bufPtr->nextRemoved == bufPtr->nextAdded) { 8469 chanPtr->inQueueHead = bufPtr->nextPtr; 8470 if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { 8471 chanPtr->inQueueTail = (ChannelBuffer *) NULL; 8472 } 8473 RecycleBuffer(chanPtr->state, bufPtr, 0); 8474 } 8475 8476 /* 8477 * Return the number of characters copied into the result buffer. 8478 */ 8479 8480 return copied; 8481} 8482 8483/* 8484 *---------------------------------------------------------------------- 8485 * 8486 * DoWrite -- 8487 * 8488 * Puts a sequence of characters into an output buffer, may queue the 8489 * buffer for output if it gets full, and also remembers whether the 8490 * current buffer is ready e.g. if it contains a newline and we are in 8491 * line buffering mode. 8492 * 8493 * Results: 8494 * The number of bytes written or -1 in case of error. If -1, 8495 * Tcl_GetErrno will return the error code. 8496 * 8497 * Side effects: 8498 * May buffer up output and may cause output to be produced on the 8499 * channel. 8500 * 8501 *---------------------------------------------------------------------- 8502 */ 8503 8504static int 8505DoWrite(chanPtr, src, srcLen) 8506 Channel *chanPtr; /* The channel to buffer output for. */ 8507 CONST char *src; /* Data to write. */ 8508 int srcLen; /* Number of bytes to write. */ 8509{ 8510 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 8511 ChannelBuffer *outBufPtr; /* Current output buffer. */ 8512 int foundNewline; /* Did we find a newline in output? */ 8513 char *dPtr; 8514 CONST char *sPtr; /* Search variables for newline. */ 8515 int crsent; /* In CRLF eol translation mode, 8516 * remember the fact that a CR was 8517 * output to the channel without 8518 * its following NL. */ 8519 int i; /* Loop index for newline search. */ 8520 int destCopied; /* How many bytes were used in this 8521 * destination buffer to hold the 8522 * output? */ 8523 int totalDestCopied; /* How many bytes total were 8524 * copied to the channel buffer? */ 8525 int srcCopied; /* How many bytes were copied from 8526 * the source string? */ 8527 char *destPtr; /* Where in line to copy to? */ 8528 8529 /* 8530 * If we are in network (or windows) translation mode, record the fact 8531 * that we have not yet sent a CR to the channel. 8532 */ 8533 8534 crsent = 0; 8535 8536 /* 8537 * Loop filling buffers and flushing them until all output has been 8538 * consumed. 8539 */ 8540 8541 srcCopied = 0; 8542 totalDestCopied = 0; 8543 8544 while (srcLen > 0) { 8545 8546 /* 8547 * Make sure there is a current output buffer to accept output. 8548 */ 8549 8550 if (statePtr->curOutPtr == (ChannelBuffer *) NULL) { 8551 statePtr->curOutPtr = AllocChannelBuffer(statePtr->bufSize); 8552 } 8553 8554 outBufPtr = statePtr->curOutPtr; 8555 8556 destCopied = outBufPtr->bufLength - outBufPtr->nextAdded; 8557 if (destCopied > srcLen) { 8558 destCopied = srcLen; 8559 } 8560 8561 destPtr = outBufPtr->buf + outBufPtr->nextAdded; 8562 switch (statePtr->outputTranslation) { 8563 case TCL_TRANSLATE_LF: 8564 srcCopied = destCopied; 8565 memcpy((VOID *) destPtr, (VOID *) src, (size_t) destCopied); 8566 break; 8567 case TCL_TRANSLATE_CR: 8568 srcCopied = destCopied; 8569 memcpy((VOID *) destPtr, (VOID *) src, (size_t) destCopied); 8570 for (dPtr = destPtr; dPtr < destPtr + destCopied; dPtr++) { 8571 if (*dPtr == '\n') { 8572 *dPtr = '\r'; 8573 } 8574 } 8575 break; 8576 case TCL_TRANSLATE_CRLF: 8577 for (srcCopied = 0, dPtr = destPtr, sPtr = src; 8578 dPtr < destPtr + destCopied; 8579 dPtr++, sPtr++, srcCopied++) { 8580 if (*sPtr == '\n') { 8581 if (crsent) { 8582 *dPtr = '\n'; 8583 crsent = 0; 8584 } else { 8585 *dPtr = '\r'; 8586 crsent = 1; 8587 sPtr--, srcCopied--; 8588 } 8589 } else { 8590 *dPtr = *sPtr; 8591 } 8592 } 8593 break; 8594 case TCL_TRANSLATE_AUTO: 8595 panic("Tcl_Write: AUTO output translation mode not supported"); 8596 default: 8597 panic("Tcl_Write: unknown output translation mode"); 8598 } 8599 8600 /* 8601 * The current buffer is ready for output if it is full, or if it 8602 * contains a newline and this channel is line-buffered, or if it 8603 * contains any output and this channel is unbuffered. 8604 */ 8605 8606 outBufPtr->nextAdded += destCopied; 8607 if (!(statePtr->flags & BUFFER_READY)) { 8608 if (outBufPtr->nextAdded == outBufPtr->bufLength) { 8609 statePtr->flags |= BUFFER_READY; 8610 } else if (statePtr->flags & CHANNEL_LINEBUFFERED) { 8611 for (sPtr = src, i = 0, foundNewline = 0; 8612 (i < srcCopied) && (!foundNewline); 8613 i++, sPtr++) { 8614 if (*sPtr == '\n') { 8615 foundNewline = 1; 8616 break; 8617 } 8618 } 8619 if (foundNewline) { 8620 statePtr->flags |= BUFFER_READY; 8621 } 8622 } else if (statePtr->flags & CHANNEL_UNBUFFERED) { 8623 statePtr->flags |= BUFFER_READY; 8624 } 8625 } 8626 8627 totalDestCopied += srcCopied; 8628 src += srcCopied; 8629 srcLen -= srcCopied; 8630 8631 if (statePtr->flags & BUFFER_READY) { 8632 if (FlushChannel(NULL, chanPtr, 0) != 0) { 8633 return -1; 8634 } 8635 } 8636 } /* Closes "while" */ 8637 8638 return totalDestCopied; 8639} 8640 8641/* 8642 *---------------------------------------------------------------------- 8643 * 8644 * CopyEventProc -- 8645 * 8646 * This routine is invoked as a channel event handler for 8647 * the background copy operation. It is just a trivial wrapper 8648 * around the CopyData routine. 8649 * 8650 * Results: 8651 * None. 8652 * 8653 * Side effects: 8654 * None. 8655 * 8656 *---------------------------------------------------------------------- 8657 */ 8658 8659static void 8660CopyEventProc(clientData, mask) 8661 ClientData clientData; 8662 int mask; 8663{ 8664 (void) CopyData((CopyState *)clientData, mask); 8665} 8666 8667/* 8668 *---------------------------------------------------------------------- 8669 * 8670 * StopCopy -- 8671 * 8672 * This routine halts a copy that is in progress. 8673 * 8674 * Results: 8675 * None. 8676 * 8677 * Side effects: 8678 * Removes any pending channel handlers and restores the blocking 8679 * and buffering modes of the channels. The CopyState is freed. 8680 * 8681 *---------------------------------------------------------------------- 8682 */ 8683 8684static void 8685StopCopy(csPtr) 8686 CopyState *csPtr; /* State for bg copy to stop . */ 8687{ 8688 ChannelState *inStatePtr, *outStatePtr; 8689 int nonBlocking; 8690 8691 if (!csPtr) { 8692 return; 8693 } 8694 8695 inStatePtr = csPtr->readPtr->state; 8696 outStatePtr = csPtr->writePtr->state; 8697 8698 /* 8699 * Restore the old blocking mode and output buffering mode. 8700 */ 8701 8702 nonBlocking = (csPtr->readFlags & CHANNEL_NONBLOCKING); 8703 if (nonBlocking != (inStatePtr->flags & CHANNEL_NONBLOCKING)) { 8704 SetBlockMode(NULL, csPtr->readPtr, 8705 nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); 8706 } 8707 if (csPtr->readPtr != csPtr->writePtr) { 8708 nonBlocking = (csPtr->writeFlags & CHANNEL_NONBLOCKING); 8709 if (nonBlocking != (outStatePtr->flags & CHANNEL_NONBLOCKING)) { 8710 SetBlockMode(NULL, csPtr->writePtr, 8711 nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); 8712 } 8713 } 8714 outStatePtr->flags &= ~(CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); 8715 outStatePtr->flags |= 8716 csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); 8717 8718 if (csPtr->cmdPtr) { 8719 Tcl_DeleteChannelHandler((Tcl_Channel)csPtr->readPtr, CopyEventProc, 8720 (ClientData)csPtr); 8721 if (csPtr->readPtr != csPtr->writePtr) { 8722 Tcl_DeleteChannelHandler((Tcl_Channel)csPtr->writePtr, 8723 CopyEventProc, (ClientData)csPtr); 8724 } 8725 Tcl_DecrRefCount(csPtr->cmdPtr); 8726 } 8727 inStatePtr->csPtrR = NULL; 8728 outStatePtr->csPtrW = NULL; 8729 ckfree((char*) csPtr); 8730} 8731 8732/* 8733 *---------------------------------------------------------------------- 8734 * 8735 * StackSetBlockMode -- 8736 * 8737 * This function sets the blocking mode for a channel, iterating 8738 * through each channel in a stack and updates the state flags. 8739 * 8740 * Results: 8741 * 0 if OK, result code from failed blockModeProc otherwise. 8742 * 8743 * Side effects: 8744 * Modifies the blocking mode of the channel and possibly generates 8745 * an error. 8746 * 8747 *---------------------------------------------------------------------- 8748 */ 8749 8750static int 8751StackSetBlockMode(chanPtr, mode) 8752 Channel *chanPtr; /* Channel to modify. */ 8753 int mode; /* One of TCL_MODE_BLOCKING or 8754 * TCL_MODE_NONBLOCKING. */ 8755{ 8756 int result = 0; 8757 Tcl_DriverBlockModeProc *blockModeProc; 8758 8759 /* 8760 * Start at the top of the channel stack 8761 */ 8762 8763 chanPtr = chanPtr->state->topChanPtr; 8764 while (chanPtr != (Channel *) NULL) { 8765 blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr); 8766 if (blockModeProc != NULL) { 8767 result = (*blockModeProc) (chanPtr->instanceData, mode); 8768 if (result != 0) { 8769 Tcl_SetErrno(result); 8770 return result; 8771 } 8772 } 8773 chanPtr = chanPtr->downChanPtr; 8774 } 8775 return 0; 8776} 8777 8778/* 8779 *---------------------------------------------------------------------- 8780 * 8781 * SetBlockMode -- 8782 * 8783 * This function sets the blocking mode for a channel and updates 8784 * the state flags. 8785 * 8786 * Results: 8787 * A standard Tcl result. 8788 * 8789 * Side effects: 8790 * Modifies the blocking mode of the channel and possibly generates 8791 * an error. 8792 * 8793 *---------------------------------------------------------------------- 8794 */ 8795 8796static int 8797SetBlockMode(interp, chanPtr, mode) 8798 Tcl_Interp *interp; /* Interp for error reporting. */ 8799 Channel *chanPtr; /* Channel to modify. */ 8800 int mode; /* One of TCL_MODE_BLOCKING or 8801 * TCL_MODE_NONBLOCKING. */ 8802{ 8803 ChannelState *statePtr = chanPtr->state; /* state info for channel */ 8804 int result = 0; 8805 8806 result = StackSetBlockMode(chanPtr, mode); 8807 if (result != 0) { 8808 if (interp != (Tcl_Interp *) NULL) { 8809 Tcl_AppendResult(interp, "error setting blocking mode: ", 8810 Tcl_PosixError(interp), (char *) NULL); 8811 } 8812 return TCL_ERROR; 8813 } 8814 if (mode == TCL_MODE_BLOCKING) { 8815 statePtr->flags &= (~(CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED)); 8816 } else { 8817 statePtr->flags |= CHANNEL_NONBLOCKING; 8818 } 8819 return TCL_OK; 8820} 8821 8822/* 8823 *---------------------------------------------------------------------- 8824 * 8825 * Tcl_GetChannelNames -- 8826 * 8827 * Return the names of all open channels in the interp. 8828 * 8829 * Results: 8830 * TCL_OK or TCL_ERROR. 8831 * 8832 * Side effects: 8833 * Interp result modified with list of channel names. 8834 * 8835 *---------------------------------------------------------------------- 8836 */ 8837 8838int 8839Tcl_GetChannelNames(interp) 8840 Tcl_Interp *interp; /* Interp for error reporting. */ 8841{ 8842 return Tcl_GetChannelNamesEx(interp, (char *) NULL); 8843} 8844 8845/* 8846 *---------------------------------------------------------------------- 8847 * 8848 * Tcl_GetChannelNamesEx -- 8849 * 8850 * Return the names of open channels in the interp filtered 8851 * filtered through a pattern. If pattern is NULL, it returns 8852 * all the open channels. 8853 * 8854 * Results: 8855 * TCL_OK or TCL_ERROR. 8856 * 8857 * Side effects: 8858 * Interp result modified with list of channel names. 8859 * 8860 *---------------------------------------------------------------------- 8861 */ 8862 8863int 8864Tcl_GetChannelNamesEx(interp, pattern) 8865 Tcl_Interp *interp; /* Interp for error reporting. */ 8866 CONST char *pattern; /* pattern to filter on. */ 8867{ 8868 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 8869 ChannelState *statePtr; 8870 CONST char *name; /* name for channel */ 8871 Tcl_Obj *resultPtr; /* pointer to result object */ 8872 Tcl_HashTable *hTblPtr; /* Hash table of channels. */ 8873 Tcl_HashEntry *hPtr; /* Search variable. */ 8874 Tcl_HashSearch hSearch; /* Search variable. */ 8875 8876 if (interp == (Tcl_Interp *) NULL) { 8877 return TCL_OK; 8878 } 8879 8880 /* 8881 * Get the channel table that stores the channels registered 8882 * for this interpreter. 8883 */ 8884 hTblPtr = GetChannelTable(interp); 8885 resultPtr = Tcl_GetObjResult(interp); 8886 8887 for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); 8888 hPtr != (Tcl_HashEntry *) NULL; 8889 hPtr = Tcl_NextHashEntry(&hSearch)) { 8890 8891 statePtr = ((Channel *) Tcl_GetHashValue(hPtr))->state; 8892 if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) { 8893 name = "stdin"; 8894 } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stdoutChannel) { 8895 name = "stdout"; 8896 } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stderrChannel) { 8897 name = "stderr"; 8898 } else { 8899 /* 8900 * This is also stored in Tcl_GetHashKey(hTblPtr, hPtr), 8901 * but it's simpler to just grab the name from the statePtr. 8902 */ 8903 name = statePtr->channelName; 8904 } 8905 8906 if (((pattern == NULL) || Tcl_StringMatch(name, pattern)) && 8907 (Tcl_ListObjAppendElement(interp, resultPtr, 8908 Tcl_NewStringObj(name, -1)) != TCL_OK)) { 8909 return TCL_ERROR; 8910 } 8911 } 8912 return TCL_OK; 8913} 8914 8915/* 8916 *---------------------------------------------------------------------- 8917 * 8918 * Tcl_IsChannelRegistered -- 8919 * 8920 * Checks whether the channel is associated with the interp. 8921 * See also Tcl_RegisterChannel and Tcl_UnregisterChannel. 8922 * 8923 * Results: 8924 * 0 if the channel is not registered in the interpreter, 1 else. 8925 * 8926 * Side effects: 8927 * None. 8928 * 8929 *---------------------------------------------------------------------- 8930 */ 8931 8932int 8933Tcl_IsChannelRegistered (interp, chan) 8934 Tcl_Interp* interp; /* The interp to query of the channel */ 8935 Tcl_Channel chan; /* The channel to check */ 8936{ 8937 Tcl_HashTable *hTblPtr; /* Hash table of channels. */ 8938 Tcl_HashEntry *hPtr; /* Search variable. */ 8939 Channel *chanPtr; /* The real IO channel. */ 8940 ChannelState *statePtr; /* State of the real channel. */ 8941 8942 /* 8943 * Always check bottom-most channel in the stack. This is the one 8944 * that gets registered. 8945 */ 8946 chanPtr = ((Channel *) chan)->state->bottomChanPtr; 8947 statePtr = chanPtr->state; 8948 8949 hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); 8950 if (hTblPtr == (Tcl_HashTable *) NULL) { 8951 return 0; 8952 } 8953 hPtr = Tcl_FindHashEntry(hTblPtr, statePtr->channelName); 8954 if (hPtr == (Tcl_HashEntry *) NULL) { 8955 return 0; 8956 } 8957 if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) { 8958 return 0; 8959 } 8960 8961 return 1; 8962} 8963 8964/* 8965 *---------------------------------------------------------------------- 8966 * 8967 * Tcl_IsChannelShared -- 8968 * 8969 * Checks whether the channel is shared by multiple interpreters. 8970 * 8971 * Results: 8972 * A boolean value (0 = Not shared, 1 = Shared). 8973 * 8974 * Side effects: 8975 * None. 8976 * 8977 *---------------------------------------------------------------------- 8978 */ 8979 8980int 8981Tcl_IsChannelShared (chan) 8982 Tcl_Channel chan; /* The channel to query */ 8983{ 8984 ChannelState *statePtr = ((Channel *) chan)->state; 8985 /* State of real channel structure. */ 8986 8987 return ((statePtr->refCount > 1) ? 1 : 0); 8988} 8989 8990/* 8991 *---------------------------------------------------------------------- 8992 * 8993 * Tcl_IsChannelExisting -- 8994 * 8995 * Checks whether a channel of the given name exists in the 8996 * (thread)-global list of all channels. 8997 * See Tcl_GetChannelNamesEx for function exposed at the Tcl level. 8998 * 8999 * Results: 9000 * A boolean value (0 = Does not exist, 1 = Does exist). 9001 * 9002 * Side effects: 9003 * None. 9004 * 9005 *---------------------------------------------------------------------- 9006 */ 9007 9008int 9009Tcl_IsChannelExisting(chanName) 9010 CONST char* chanName; /* The name of the channel to look for. */ 9011{ 9012 ChannelState *statePtr; 9013 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 9014 CONST char *name; 9015 int chanNameLen; 9016 9017 chanNameLen = strlen(chanName); 9018 for (statePtr = tsdPtr->firstCSPtr; 9019 statePtr != NULL; 9020 statePtr = statePtr->nextCSPtr) { 9021 if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) { 9022 name = "stdin"; 9023 } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stdoutChannel) { 9024 name = "stdout"; 9025 } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stderrChannel) { 9026 name = "stderr"; 9027 } else { 9028 name = statePtr->channelName; 9029 } 9030 9031 /* Bug 2333466. Include \0 in the compare to prevent partial matching on prefixes. 9032 */ 9033 if ((*chanName == *name) && 9034 (memcmp(name, chanName, (size_t) chanNameLen+1) == 0)) { 9035 return 1; 9036 } 9037 } 9038 9039 return 0; 9040} 9041 9042/* 9043 *---------------------------------------------------------------------- 9044 * 9045 * Tcl_ChannelName -- 9046 * 9047 * Return the name of the channel type. 9048 * 9049 * Results: 9050 * A pointer the name of the channel type. 9051 * 9052 * Side effects: 9053 * None. 9054 * 9055 *---------------------------------------------------------------------- 9056 */ 9057 9058CONST char * 9059Tcl_ChannelName(chanTypePtr) 9060 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9061{ 9062 return chanTypePtr->typeName; 9063} 9064 9065/* 9066 *---------------------------------------------------------------------- 9067 * 9068 * Tcl_ChannelVersion -- 9069 * 9070 * Return the of version of the channel type. 9071 * 9072 * Results: 9073 * One of the TCL_CHANNEL_VERSION_* constants from tcl.h 9074 * 9075 * Side effects: 9076 * None. 9077 * 9078 *---------------------------------------------------------------------- 9079 */ 9080 9081Tcl_ChannelTypeVersion 9082Tcl_ChannelVersion(chanTypePtr) 9083 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9084{ 9085 if (chanTypePtr->version == TCL_CHANNEL_VERSION_2) { 9086 return TCL_CHANNEL_VERSION_2; 9087 } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_3) { 9088 return TCL_CHANNEL_VERSION_3; 9089 } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_4) { 9090 return TCL_CHANNEL_VERSION_4; 9091 } else { 9092 /* 9093 * In <v2 channel versions, the version field is occupied 9094 * by the Tcl_DriverBlockModeProc 9095 */ 9096 return TCL_CHANNEL_VERSION_1; 9097 } 9098} 9099 9100/* 9101 *---------------------------------------------------------------------- 9102 * 9103 * HaveVersion -- 9104 * 9105 * Return whether a channel type is (at least) of a given version. 9106 * 9107 * Results: 9108 * True if the minimum version is exceeded by the version actually 9109 * present. 9110 * 9111 * Side effects: 9112 * None. 9113 * 9114 *---------------------------------------------------------------------- 9115 */ 9116 9117static int 9118HaveVersion(chanTypePtr, minimumVersion) 9119 Tcl_ChannelType *chanTypePtr; 9120 Tcl_ChannelTypeVersion minimumVersion; 9121{ 9122 Tcl_ChannelTypeVersion actualVersion = Tcl_ChannelVersion(chanTypePtr); 9123 9124 return ((int)actualVersion) >= ((int)minimumVersion); 9125} 9126 9127/* 9128 *---------------------------------------------------------------------- 9129 * 9130 * Tcl_ChannelBlockModeProc -- 9131 * 9132 * Return the Tcl_DriverBlockModeProc of the channel type. 9133 * 9134 * Results: 9135 * A pointer to the proc. 9136 * 9137 * Side effects: 9138 * None. 9139 * 9140 *---------------------------------------------------------------------- */ 9141 9142Tcl_DriverBlockModeProc * 9143Tcl_ChannelBlockModeProc(chanTypePtr) 9144 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9145{ 9146 if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) { 9147 return chanTypePtr->blockModeProc; 9148 } else { 9149 /* 9150 * The v1 structure had the blockModeProc in a different place. 9151 */ 9152 return (Tcl_DriverBlockModeProc *) (chanTypePtr->version); 9153 } 9154} 9155 9156/* 9157 *---------------------------------------------------------------------- 9158 * 9159 * Tcl_ChannelCloseProc -- 9160 * 9161 * Return the Tcl_DriverCloseProc of the channel type. 9162 * 9163 * Results: 9164 * A pointer to the proc. 9165 * 9166 * Side effects: 9167 * None. 9168 * 9169 *---------------------------------------------------------------------- 9170 */ 9171 9172Tcl_DriverCloseProc * 9173Tcl_ChannelCloseProc(chanTypePtr) 9174 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9175{ 9176 return chanTypePtr->closeProc; 9177} 9178 9179/* 9180 *---------------------------------------------------------------------- 9181 * 9182 * Tcl_ChannelClose2Proc -- 9183 * 9184 * Return the Tcl_DriverClose2Proc of the channel type. 9185 * 9186 * Results: 9187 * A pointer to the proc. 9188 * 9189 * Side effects: 9190 * None. 9191 * 9192 *---------------------------------------------------------------------- 9193 */ 9194 9195Tcl_DriverClose2Proc * 9196Tcl_ChannelClose2Proc(chanTypePtr) 9197 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9198{ 9199 return chanTypePtr->close2Proc; 9200} 9201 9202/* 9203 *---------------------------------------------------------------------- 9204 * 9205 * Tcl_ChannelInputProc -- 9206 * 9207 * Return the Tcl_DriverInputProc of the channel type. 9208 * 9209 * Results: 9210 * A pointer to the proc. 9211 * 9212 * Side effects: 9213 * None. 9214 * 9215 *---------------------------------------------------------------------- 9216 */ 9217 9218Tcl_DriverInputProc * 9219Tcl_ChannelInputProc(chanTypePtr) 9220 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9221{ 9222 return chanTypePtr->inputProc; 9223} 9224 9225/* 9226 *---------------------------------------------------------------------- 9227 * 9228 * Tcl_ChannelOutputProc -- 9229 * 9230 * Return the Tcl_DriverOutputProc of the channel type. 9231 * 9232 * Results: 9233 * A pointer to the proc. 9234 * 9235 * Side effects: 9236 * None. 9237 * 9238 *---------------------------------------------------------------------- 9239 */ 9240 9241Tcl_DriverOutputProc * 9242Tcl_ChannelOutputProc(chanTypePtr) 9243 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9244{ 9245 return chanTypePtr->outputProc; 9246} 9247 9248/* 9249 *---------------------------------------------------------------------- 9250 * 9251 * Tcl_ChannelSeekProc -- 9252 * 9253 * Return the Tcl_DriverSeekProc of the channel type. 9254 * 9255 * Results: 9256 * A pointer to the proc. 9257 * 9258 * Side effects: 9259 * None. 9260 * 9261 *---------------------------------------------------------------------- 9262 */ 9263 9264Tcl_DriverSeekProc * 9265Tcl_ChannelSeekProc(chanTypePtr) 9266 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9267{ 9268 return chanTypePtr->seekProc; 9269} 9270 9271/* 9272 *---------------------------------------------------------------------- 9273 * 9274 * Tcl_ChannelSetOptionProc -- 9275 * 9276 * Return the Tcl_DriverSetOptionProc of the channel type. 9277 * 9278 * Results: 9279 * A pointer to the proc. 9280 * 9281 * Side effects: 9282 * None. 9283 * 9284 *---------------------------------------------------------------------- 9285 */ 9286 9287Tcl_DriverSetOptionProc * 9288Tcl_ChannelSetOptionProc(chanTypePtr) 9289 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9290{ 9291 return chanTypePtr->setOptionProc; 9292} 9293 9294/* 9295 *---------------------------------------------------------------------- 9296 * 9297 * Tcl_ChannelGetOptionProc -- 9298 * 9299 * Return the Tcl_DriverGetOptionProc of the channel type. 9300 * 9301 * Results: 9302 * A pointer to the proc. 9303 * 9304 * Side effects: 9305 * None. 9306 * 9307 *---------------------------------------------------------------------- 9308 */ 9309 9310Tcl_DriverGetOptionProc * 9311Tcl_ChannelGetOptionProc(chanTypePtr) 9312 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9313{ 9314 return chanTypePtr->getOptionProc; 9315} 9316 9317/* 9318 *---------------------------------------------------------------------- 9319 * 9320 * Tcl_ChannelWatchProc -- 9321 * 9322 * Return the Tcl_DriverWatchProc of the channel type. 9323 * 9324 * Results: 9325 * A pointer to the proc. 9326 * 9327 * Side effects: 9328 * None. 9329 * 9330 *---------------------------------------------------------------------- 9331 */ 9332 9333Tcl_DriverWatchProc * 9334Tcl_ChannelWatchProc(chanTypePtr) 9335 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9336{ 9337 return chanTypePtr->watchProc; 9338} 9339 9340/* 9341 *---------------------------------------------------------------------- 9342 * 9343 * Tcl_ChannelGetHandleProc -- 9344 * 9345 * Return the Tcl_DriverGetHandleProc of the channel type. 9346 * 9347 * Results: 9348 * A pointer to the proc. 9349 * 9350 * Side effects: 9351 * None. 9352 * 9353 *---------------------------------------------------------------------- 9354 */ 9355 9356Tcl_DriverGetHandleProc * 9357Tcl_ChannelGetHandleProc(chanTypePtr) 9358 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9359{ 9360 return chanTypePtr->getHandleProc; 9361} 9362 9363/* 9364 *---------------------------------------------------------------------- 9365 * 9366 * Tcl_ChannelFlushProc -- 9367 * 9368 * Return the Tcl_DriverFlushProc of the channel type. 9369 * 9370 * Results: 9371 * A pointer to the proc. 9372 * 9373 * Side effects: 9374 * None. 9375 * 9376 *---------------------------------------------------------------------- 9377 */ 9378 9379Tcl_DriverFlushProc * 9380Tcl_ChannelFlushProc(chanTypePtr) 9381 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9382{ 9383 if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) { 9384 return chanTypePtr->flushProc; 9385 } else { 9386 return NULL; 9387 } 9388} 9389 9390/* 9391 *---------------------------------------------------------------------- 9392 * 9393 * Tcl_ChannelHandlerProc -- 9394 * 9395 * Return the Tcl_DriverHandlerProc of the channel type. 9396 * 9397 * Results: 9398 * A pointer to the proc. 9399 * 9400 * Side effects: 9401 * None. 9402 * 9403 *---------------------------------------------------------------------- 9404 */ 9405 9406Tcl_DriverHandlerProc * 9407Tcl_ChannelHandlerProc(chanTypePtr) 9408 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9409{ 9410 if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) { 9411 return chanTypePtr->handlerProc; 9412 } else { 9413 return NULL; 9414 } 9415} 9416 9417/* 9418 *---------------------------------------------------------------------- 9419 * 9420 * Tcl_ChannelWideSeekProc -- 9421 * 9422 * Return the Tcl_DriverWideSeekProc of the channel type. 9423 * 9424 * Results: 9425 * A pointer to the proc. 9426 * 9427 * Side effects: 9428 * None. 9429 * 9430 *---------------------------------------------------------------------- 9431 */ 9432 9433Tcl_DriverWideSeekProc * 9434Tcl_ChannelWideSeekProc(chanTypePtr) 9435 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9436{ 9437 if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_3)) { 9438 return chanTypePtr->wideSeekProc; 9439 } else { 9440 return NULL; 9441 } 9442} 9443 9444/* 9445 *---------------------------------------------------------------------- 9446 * 9447 * Tcl_ChannelThreadActionProc -- 9448 * 9449 * Return the Tcl_DriverThreadActionProc of the channel type. 9450 * 9451 * Results: 9452 * A pointer to the proc. 9453 * 9454 * Side effects: 9455 * None. 9456 * 9457 *---------------------------------------------------------------------- 9458 */ 9459 9460Tcl_DriverThreadActionProc * 9461Tcl_ChannelThreadActionProc(chanTypePtr) 9462 Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ 9463{ 9464 if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) { 9465 return chanTypePtr->threadActionProc; 9466 } else { 9467 return NULL; 9468 } 9469} 9470 9471#if 0 9472/* For future debugging work, a simple function to print the flags of 9473 * a channel in semi-readable form. 9474 */ 9475 9476static int 9477DumpFlags (str, flags) 9478 char* str; 9479 int flags; 9480{ 9481 char buf [20]; 9482 int i = 0; 9483 9484 if (flags & TCL_READABLE) {buf[i] = 'r';} else {buf [i]='_';}; i++; 9485 if (flags & TCL_WRITABLE) {buf[i] = 'w';} else {buf [i]='_';}; i++; 9486 if (flags & CHANNEL_NONBLOCKING) {buf[i] = 'n';} else {buf [i]='_';}; i++; 9487 if (flags & CHANNEL_LINEBUFFERED) {buf[i] = 'l';} else {buf [i]='_';}; i++; 9488 if (flags & CHANNEL_UNBUFFERED) {buf[i] = 'u';} else {buf [i]='_';}; i++; 9489 if (flags & BUFFER_READY) {buf[i] = 'R';} else {buf [i]='_';}; i++; 9490 if (flags & BG_FLUSH_SCHEDULED) {buf[i] = 'F';} else {buf [i]='_';}; i++; 9491 if (flags & CHANNEL_CLOSED) {buf[i] = 'c';} else {buf [i]='_';}; i++; 9492 if (flags & CHANNEL_EOF) {buf[i] = 'E';} else {buf [i]='_';}; i++; 9493 if (flags & CHANNEL_STICKY_EOF) {buf[i] = 'S';} else {buf [i]='_';}; i++; 9494 if (flags & CHANNEL_BLOCKED) {buf[i] = 'B';} else {buf [i]='_';}; i++; 9495 if (flags & INPUT_SAW_CR) {buf[i] = '/';} else {buf [i]='_';}; i++; 9496 if (flags & INPUT_NEED_NL) {buf[i] = '*';} else {buf [i]='_';}; i++; 9497 if (flags & CHANNEL_DEAD) {buf[i] = 'D';} else {buf [i]='_';}; i++; 9498 if (flags & CHANNEL_RAW_MODE) {buf[i] = 'R';} else {buf [i]='_';}; i++; 9499#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING 9500 if (flags & CHANNEL_TIMER_FEV) {buf[i] = 'T';} else {buf [i]='_';}; i++; 9501 if (flags & CHANNEL_HAS_MORE_DATA) {buf[i] = 'H';} else {buf [i]='_';}; i++; 9502#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ 9503 if (flags & CHANNEL_INCLOSE) {buf[i] = 'x';} else {buf [i]='_';}; i++; 9504 buf [i] ='\0'; 9505 9506 fprintf (stderr,"%s: %s\n", str, buf); fflush(stderr); 9507 return 0; 9508} 9509#endif 9510