Scroll to navigation

chan(3tcl) Tcl Built-In Commands chan(3tcl)


NAME

chan - Reads, writes and manipulates channels.

SYNOPSIS

chan operation ?arg arg ...?


DESCRIPTION

chan provides several operations for reading from, writing to, and otherwise manipulating channels, e.g. those created by open and socket, or the default channels stdin, stdout or stderr which correspond respectively to the standard input, output, and error streams of the process. Any unique abbreviation for operation is acceptable. Available operations are:

Returns 1 when the channel is in non-blocking mode and the last input operation on the channel failed because it would have otherwise caused the process to block, and 0 otherwise. Each Tcl channel is in blocking mode unless configured otherwise.
Closes and destroys the named channel, deleting any existing event handlers established for the channel, and returns the empty string. If direction is given, it is “read” or “write” or any unique abbreviation of those words, and only that side of the channel is closed. I.e. a read-write channel may become read-only or write-only. Closing a read-only channel for reading, or closing a write-only channel for writing is the same as simply closing the channel. It is an error to close a read-only channel for writing or to close a write-only channel for reading.

When a channel is closed for writing, any buffered output on the channel is flushed. When a channel is closed for reading, any buffered input is discarded. When a channel is destroyed the underlying resource is closed and the channel is thereafter unavailable.

chan close fully flushes any output before closing the write side of a channel unless it is non-blocking mode, where it returns immediately and the channel is flushed in the background before finally being closed.

chan close may return an error if an error occurs while flushing output. If a process in a command pipeline created by open returns an error (either by returning a non-zero exit code or writing to its standard error file descriptor), chan close generates an error in the same manner as exec.

Closing one side of a socket or command pipeline may lead to the shutdown() or close() of the underlying system resource, leading to a reaction from whatever is on the other side of the pipeline or socket.

If the channel for a command pipeline is in blocking mode, chan close waits for the connected processes to complete.

chan close only affects the current interpreter. If the channel is open in any other interpreter, its state is unchanged there. See interp for a description of channel sharing.

When the last interpreter sharing a channel is destroyed, the channel is switched to blocking mode and fully flushed and then closed.

Channels are automatically closed when an interpreter is destroyed and when the process exits. From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT, which when set and not equal to “0” restores the previous behavior.

Configures or reports the configuration of channelName.

If no optionName or value arguments are given, chan configure returns a dictionary of option names and values for the channel. If optionName is supplied without a value, chan configure returns the current value of the named option. If one or more pairs of optionName and value are supplied, chan configure sets each of the named options to the corresponding value and returns the empty string.

The options described below are supported for all channels. Each type of channel may provide additional options. Those options are described in the relevant documentation. For example, additional options are documented for socket, and also for serial devices at open.

If -blocking is set to true, which is the default, reading from or writing to the channel may cause the process to block indefinitely. Otherwise, operations such as chan gets, chan read, chan puts, chan flush, and chan close take care not to block. Non-blocking mode in generally requires that the event loop is entered, e.g. by calling Tcl_DoOneEvent or vwait or by using Tk, to give Tcl a chance to process events on the channel.
If newValue is full, which is the default, output is buffered until the internal buffer is full or until chan flush is called. If newValue is line, output is flushed each time a end-of-line character is written. If newValue is none, output is flushed after every output operation. For stdin, stdout, and channels that connect to terminal-like devices, the default value is line. For stderr the default value is none.
newSize, an integer no greater than one million, is the size in bytes of any input or output buffers subsequently allocated for this channel.
Sets the encoding of the channel. name is either one of the names returned by encoding names, or “binary” . Input is converted from the encoding into Unicode, and output is converted from Unicode to the encoding.

binary is an alias for iso8859-1. This alone is not sufficient for working with binary data. Use -translation binary instead.

The encoding of a new channel is the value of encoding system, which returns the platform- and locale-dependent system encoding used to interface with the operating system,

char signals the end of the data when it is encountered in the input. If char is the empty string, there is no special character that marks the end of the data.

The default value is the empty string. The acceptable range is \x01 - \x7F. A value outside this range results in an error.

Specifies the encoding profile to be used on the channel. The encoding transforms in use for the channel's input and output will then be subject to the rules of that profile. Any failures will result in a channel error. See PROFILES in the encoding(3tcl) documentation for details about encoding profiles.
In Tcl a single line feed (\n) represents the end of a line. However, at the destination the end of a line may be represented differently on different platforms, or even for different devices on the same platform. For example, under UNIX line feed is used in files and a carriage-return-linefeed sequence is normally used in network connections. Therefore, on input, e.g. with chan gets and chan read, each external end-of-line character is translated into a line feed. On output, e.g. with chan puts, each line feed is translated to the external end-of-line character. The default translation, auto, handles all the common cases, and -translation provides explicit control over the end-of-line character.

Returns the input translation for a read-only channel, the output translation for a write-only channel, and both the input translation and the the output translation for a read-write channel. When two translations are given, they are the input and output translation, respectively. When only one translation is given for a read-write channel, it is the translation for both input and output. The following values are currently supported:

The default. For input each occurrence of a line feed (lf), carriage return (cr), or carriage return followed by a line feed (crlf) is translated into a line feed. For output, each line feed is translated into a platform-specific representation: For all Unix variants it is lf, and for all Windows variants it is crlf, except that for sockets on all platforms it is crlf for both input and output.
Like lf, no end-of-line translation is performed, but in addition, sets -eofchar to the empty string to disable it, and sets -encoding to iso8859-1. With this one setting, a channel is fully configured for binary input and output: Each byte read from the channel becomes the Unicode character having the same value as that byte, and each character written to the channel becomes a single byte in the output. This makes it possible to work seamlessly with binary data as long as each character in the data remains in the range of 0 to 255 so that there is no distinction between binary data and text. For example, A JPEG image can be read from a such a channel, manipulated, and then written back to such a channel.
The end of a line is represented in the external data by a single carriage return character. For input, each carriage return is translated to a line feed, and for output each line feed character is translated to a carriage return.
The end of a line is represented in the external data by a carriage return character followed by a line feed. For input, each carriage-return-linefeed sequence is translated to a line feed. For output, each line feed is translated to a carriage-return-linefeed sequence. This translation is typically used for network connections, and also on Windows systems.
The end of a line in the external data is represented by a line feed so no translations occur during either input or output. This translation is typically used on UNIX platforms,
Reads characters from inputChan and writes them to outputChan until all characters are copied, blocking until the copy is complete and returning the number of characters copied. Leverages internal buffers to avoid extra copies and to avoid buffering too much data in main memory when copying large files to slow destinations like network sockets.

-size limits the number of characters copied.

If -command is given, chan copy returns immediately, works in the background, and calls callback when the copy completes, providing as an additional argument the number of characters written to outputChan. If an error occurs during the background copy, another argument provides message for the error. inputChan and outputChan are automatically configured for non-blocking mode if needed. Background copying only works correctly if events are being processed, e.g. via vwait or Tk.

During a background copy no other read operation may be performed on inputChan, and no write operation may be performed on outputChan. However, write operations may by performed on inputChan and read operations may be performed on outputChan, as exhibited by the bidirectional copy example below.

If either inputChan or outputChan is closed while the copy is in progress, copying ceases and no callback is made. If inputChan is closed all data already queued is written to outputChan.

There should be no event handler established for inputChan because it may become readable during a background copy. An attempt to read or write from within an event handler results result in the error, "channel busy". Any wrong-sided I/O attempted (by a fileevent handler or otherwise) results in a “channel busy” error.

EXAMPLES

The first example transfers the contents of one channel exactly to another. Note that when copying one file to another, it is better to use file copy which also copies file metadata (e.g. the file access permissions) where possible.

fconfigure $in -translation binary
fconfigure $out -translation binary
fcopy $in $out

This second example shows how the callback gets passed the number of bytes transferred. It also uses vwait to put the application into the event loop. Of course, this simplified example could be done without the command callback.

proc Cleanup {in out bytes {error {}}} {

global total
set total $bytes
close $in
close $out
if {[string length $error] != 0} {
# error occurred during the copy
} } set in [open $file1] set out [socket $server $port] fcopy $in $out -command [list Cleanup $in $out] vwait total

The third example copies in chunks and tests for end of file in the command callback.

proc CopyMore {in out chunk bytes {error {}}} {

global total done
incr total $bytes
if {([string length $error] != 0) || [eof $in]} {
set done $total
close $in
close $out
} else {
fcopy $in $out -size $chunk \
-command [list CopyMore $in $out $chunk]
} } set in [open $file1] set out [socket $server $port] set chunk 1024 set total 0 fcopy $in $out -size $chunk \
-command [list CopyMore $in $out $chunk] vwait done

The fourth example starts an asynchronous, bidirectional fcopy between two sockets. Those could also be pipes from two [open "|hal 9000" r+] (though their conversation would remain secret to the script, since all four fileevent slots are busy).

set flows 2
proc Done {dir args} {

global flows done
puts "$dir is over."
incr flows -1
if {$flows<=0} {set done 1} } fcopy $sok1 $sok2 -command [list Done UP] fcopy $sok2 $sok1 -command [list Done DOWN] vwait done
Creates a new channel, called a reflected channel, with cmdPrefix as its handler, and returns the name of the channel. cmdPrefix is the first words of a command that provides the interface for a refchan.

Imode is a list of one or more of the strings “read” or “write”, indicating whether the channel is a read channel, a write channel, or both. It is an error if the handler does not support the chosen mode.

The handler is called as needed from the global namespace at the top level, and command resolution happens there at the time of the call. If the handler is renamed or deleted any subsequent attempt to call it is an error, which may not be able to describe the failure.

The handler is always called in the interpreter and thread it was created in, even if the channel was shared with or moved into a different interpreter in a different thread. This is achieved through event dispatch, so if the event loop is not entered, e.g. by calling Tcl_DoOneEvent or vwait or using Tk, the thread performing the channel operation blocks indefinitely, resulting in deadlock.

One side of a channel may be in one thread while the other side is in a different thread, providing a stream-oriented bridge between the threads. This provides a method for regular stream communication between threads as an alternative to sending commands.

When the interpreter the handler is in is deleted each channel associated with the handler is deleted as well, regardless of which interpreter or thread it is currently in or shared with.

chan create is safe and is accessible to safe interpreters. The handler is always called in the safe interpreter it was created in.

Returns 1 if the last read on the channel failed because the end of the data was already reached, and 0 otherwise.
Arranges for the given script, called a channel event handler, to be called whenever the given event, one of “readable” or “writable” occurs on the given channel, replacing any script that was previously set. If script is the empty string the current handler is deleted. It is also deleted when the channel is closed. If script is omitted, either the existing script or the empty string is returned. The event loop must be entered, e.g. via vwait or update, or by using Tk, for handlers to be evaluated.

script is evaluated at the global level in the interpreter it was established in. Any resulting error is handled in the background, i.e. via interp bgerror. In order to prevent an endless loop due to a buggy handler, the handler is deleted if script returns an error so that it is not evaluated again.

Without an event handler, chan gets or chan read on a channel in blocking mode may block until data becomes available, become during which the thread is unable to perform other work or respond to events on other channels. This could cause the application to appear to “freeze up” . Channel event handlers allow events on the channel to direct channel handling so that the reader or writer can continue to perform other processing while waiting for a channel to become available and then handle channel operations when the channel is ready for the operation.

A “readable” event occurs when there is data that can be read from the channel and also when there is an error on the channel. The handler must check for these conditions and handle them appropriately. For example, a handler that does not check whether the end of the data has been reached may be repeatedly evaluated in a busy loop until the channel is closed.

A “writable” event occurs when at least one byte of data can be written, or if there is an error on the channel. A client socket opened in non-blocking mode becomes writable when it becomes connected or if the connection fails.

Event-driven channel handling works best for channels in non-blocking mode. A channel in blocking mode blocks when chan puts writes more data than the channel can accept at the moment, and when chan gets or chan read requests more data than is currently available. When a channel blocks, the thread can not do any other processing or service any other events. A channel in non-blocking mode allows a thread to carry on with other work and get back to the channel at the right time.

For a channel in blocking mode, flushes all buffered output to the destination, and then returns. For a channel in non-blocking mode, returns immediately while all buffered output is flushed in the background as soon as possible.
Returns the next line from the channel, removing the trailing line feed, or if varName is given, assigns the line to that variable and returns the number of characters read. the line that was read, removing the trailing line feed, or returns the empty string if there is no data to return and the end of the file has been reached, or in non-blocking mode, if no complete line is currently available. If varName is given, assigns the line that was read to variable named varName and returns the number of characters that were read, or -1 if there no data available and the end of the channel was reached or the channel is in non-blocking mode.

If the end of the channel is reached the data read so far is returned or assigned to varName. When varName is not given, chan eof may indicate that the empty string means that the end of the data has been reached, and chan blocked may indicate that that the empty string means there isn't currently enough data do return the next line.

Returns a list of all channel names, or if pattern is given, only those names that match according to the rules of string match.
Returns the number of bytes of input when mode is “input” , or output when mode is “output” , that are currently internally buffered for the channel. Useful in a readable event callback to impose limits on input line length to avoid a potential denial-of-service attack where an extremely long line exceeds the available memory to buffer it. Returns -1 if the channel was not opened for the mode in question.
Creates a pipe, i.e. a readable channel and a writable channel, and returns the names of the readable channel and the writable channel. Data written to the writable channel can be read from the readable channel. Because the pipe is a real system-level pipe, it can be connected to other processes using redirection. For example, to redirect stderr from a subprocess into one channel, and stdout into another, exec with "2>@" and ">@", each onto the writable side of a pipe, closing the writable side immediately thereafter so that EOF is signaled on the read side once the subprocess has closed its output, typically on exit.

Due to buffering, data written to one side of a pipe might not immediately become available on the other side. Tcl's own buffers can be configured via chan configure -buffering, but overall behaviour still depends on operating system buffers outside of Tcl's control. Once the write side of the channel is closed, any data remaining in the buffers is flushed through to the read side. It may be useful to arrange for the connected process to flush at some point after writing to the channel or to have it use some system-provided mechanism to configure buffering. When two pipes are connected to the same process, one to send data to the process, and one to read data from the process, a deadlock may occur if the channels are in blocking mode: If reading, the channel may block waiting for data that can never come because buffers are only flushed on subsequent writes, and if writing, the channel may block while waiting for the buffers to become free, which can never happen because the reader can not read while the writer is blocking. To avoid this issue, either put the channels into non-blocking mode and use event handlers, or place the read channel and the write channel in separate interpreters in separate threads.

Removes the topmost transformation handler from the channel if there is one, and closes the channel otherwise. The result is normally the empty string, but may be an error in some situations, e.g. when closing the underlying resource results in an error.
For use by handlers established with chan create. Notifies Tcl that that one or more event(s) listed in eventSpec, each of which is either “read” or “write.” , have occurred.

For use only by handlers for a channel created by chan create. It is an error to post an event for any other channel.

Since only the handler for a reflected channel channel should post events it is an error to post an event from any interpreter other than the interpreter that created the channel.

It is an error to post an event that the channel has no interest in. See watch in the refchan documentation for more information

chan postevent is available in safe interpreters, as any handler for a reflected channel would have been created, and will be evaluated in that interpreter as well.

Adds a new transformation handler on top of the channel and returns a handle for the transformation. cmdPrefix is the first words of a command that provides the interface documented for transchan, and transforms data on the channel, It is an error if handler does not support the mode(s) the channel is in.
Writes string and a line feed to the channel. If -nonewline is given, the trailing line feed is not written. The default channel is stdout.

Each line feed in the output is translated according to the configuration of -translation.

Because Tcl internally buffers output, characters written to a channel may not immediately be available at the destination. Tcl normally delays output until the buffer is full or the channel is closed. chan flush forces output in the direction of the destination.

When the output for a channel in blocking mode fills up, chan puts blocks until space in the buffer is available again, but for a channel in non-blocking mode, it returns immediately and the data is written in the background as fast possible, constrained by the speed at which as the destination accepts it. Output to a channel in non-blocking mode only works properly when the application enters the event loop, giving Tcl a chance to find out that the destination is ready to accept more data. When a channel is in non-blocking mode, Tcl's internal buffers can hold an arbitrary amount of data, possibly consuming a large amount of memory. To avoid wasting memory, channels in non-blocking mode should normally be handled using chan event, where the application only invokes chan puts after being recently notified through a file event handler that the channel is ready for more output data.

Reads and returns the next numChars characters from the channel. If numChars is omitted, all available characters up to the end of the file are read, or if the channel is in non-blocking mode, all currently-available characters are read. If there is an error on the channel, reading ceases and an error is returned. If numChars is not given, -nonewline may be given, causing any any trailing line feed to be trimmed.

If the channel is in non-blocking mode, fewer characters than requested may be returned. If the channel is configured to use a multi-byte encoding, bytes that do not form a complete character are retained in the buffers until enough bytes to complete the character accumulate, or the end of the data is reached. -nonewline is ignored if characters are returned before reaching the end of the file.

Each end-of-line sequence according to the value of -translation is translated into a line feed.

When reading from a serial port, most applications should configure the serial port channel to be in non-blocking mode, but not necessarily use an event handler since most serial ports are comparatively slow. It is entirely possible to get a readable event for each individual character. In blocking mode, chan read blocks forever when reading to the end of the data if there is no chan configure -eofchar configured for the channel.

Sets the current position for the data in the channel to integer offset bytes relative to origin. A negative offset moves the current position backwards from the origin. origin is one of the following:
The origin is the start of the data. This is the default.
The origin is the current position.
The origin is the end of the data.

Chan seek flushes all buffered output even if the channel is in non-blocking mode, discards any buffered and unread input, and returns the empty string or an error if the channel does not support seeking.

offset values are byte offsets, not character offsets. Unlike chan read, both chan seek and chan tell operate in terms of bytes, not characters,

Returns the offset in bytes of the current position in the underlying data, or -1 if the channel does not suport seeking. The value can be passed to chan seek to set current position to that offset.
Flushes the channel and truncates the data in the channel to length bytes, or to the current position in bytes if length is omitted.

EXAMPLES

In the following example a file is opened using the encoding CP1252, which is common on Windows, searches for a string, rewrites that part, and truncates the file two lines later.

set f [open somefile.txt r+]
chan configure $f -encoding cp1252
set offset 0
# Search for string "FOOBAR" in the file
while {[chan gets $f line] >= 0} {

set idx [string first FOOBAR $line]
if {$idx >= 0} {
# Found it; rewrite line
chan seek $f [expr {$offset + $idx}]
chan puts -nonewline $f BARFOO
# Skip to end of following line, and truncate
chan gets $f
chan gets $f
chan truncate $f
# Stop searching the file now
break
}
# Save offset of start of next line for later
set offset [chan tell $f] } chan close $f

A network server that echoes its input line-by-line without preventing servicing of other connections at the same time:

# This is a very simple logger...
proc log message {

chan puts stdout $message } # This is called whenever a new client connects to the server proc connect {chan host port} {
set clientName [format <%s:%d> $host $port]
log "connection from $clientName"
chan configure $chan -blocking 0 -buffering line
chan event $chan readable [list echoLine $chan $clientName] } # This is called whenever either at least one byte of input # data is available, or the channel was closed by the client. proc echoLine {chan clientName} {
chan gets $chan line
if {[chan eof $chan]} {
log "finishing connection from $clientName"
chan close $chan
} elseif {![chan blocked $chan]} {
# Didn't block waiting for end-of-line
log "$clientName - $line"
chan puts $chan $line
} } # Create the server socket and enter the event-loop to wait # for incoming connections... socket -server connect 12345 vwait forever

SEE ALSO

close(3tcl), eof(3tcl), fblocked(3tcl), fconfigure(3tcl), fcopy(3tcl), file(3tcl), fileevent(3tcl), flush(3tcl), gets(3tcl), open(3tcl), puts(3tcl), read(3tcl), seek(3tcl), socket(3tcl), tell(3tcl), refchan(3tcl), transchan(3tcl)

KEYWORDS

channel, input, output, events, offset

8.5 Tcl