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