diff options
Diffstat (limited to 'doc/chan.n')
-rw-r--r-- | doc/chan.n | 238 |
1 files changed, 176 insertions, 62 deletions
@@ -1,4 +1,4 @@ -'\" +'\" '\" Copyright (c) 2005-2006 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution @@ -31,22 +31,35 @@ otherwise. Note that this only ever returns 1 when the channel has been configured to be non-blocking; all Tcl channels have blocking turned on by default. .TP -\fBchan close \fIchannelId\fR +\fBchan close \fIchannelId\fR ?\fIdirection\fR? . Close and destroy the channel called \fIchannelId\fR. Note that this deletes all existing file-events registered on the channel. +.VS 8.6 +If the \fIdirection\fR argument (which must be \fBread\fR or \fBwrite\fR or +any unique abbreviation of them) is present, the channel will only be +half-closed, so that it can go from being read-write to write-only or +read-only respectively. If a read-only channel is closed for reading, it is +the same as if the channel is fully closed, and respectively similar for +write-only channels. Without the \fIdirection\fR argument, the channel is +closed for both reading and writing (but only if those directions are +currently open). It is an error to close a read-only channel for writing, or a +write-only channel for reading. +.VE 8.6 .RS .PP As part of closing the channel, all buffered output is flushed to the -channel's output device, any buffered input is discarded, the -underlying operating system resource is closed and \fIchannelId\fR -becomes unavailable for future use. -.PP -If the channel is blocking, the command does not return until all -output is flushed. If the channel is nonblocking and there is -unflushed output, the channel remains open and the command returns -immediately; output will be flushed in the background and the channel -will be closed when all the flushing is complete. +channel's output device (only if the channel is ceasing to be writable), any +buffered input is discarded (only if the channel is ceasing to be readable), +the underlying operating system resource is closed and \fIchannelId\fR becomes +unavailable for future use (both only if the channel is being completely +closed). +.PP +If the channel is blocking and the channel is ceasing to be writable, the +command does not return until all output is flushed. If the channel is +non-blocking and there is unflushed output, the channel remains open and the +command returns immediately; output will be flushed in the background and the +channel will be closed when all the flushing is complete. .PP If \fIchannelId\fR is a blocking channel for a command pipeline then \fBchan close\fR waits for the child processes to complete. @@ -56,10 +69,12 @@ makes \fIchannelId\fR unavailable in the invoking interpreter but has no other effect until all of the sharing interpreters have closed the channel. When the last interpreter in which the channel is registered invokes \fBchan close\fR (or \fBclose\fR), the cleanup actions -described above occur. See the \fBinterp\fR command for a description -of channel sharing. +described above occur. With half-closing, the half-close of the channel only +applies to the current interpreter's view of the channel until all channels +have closed it in that direction (or completely). +See the \fBinterp\fR command for a description of channel sharing. .PP -Channels are automatically closed when an interpreter is destroyed and +Channels are automatically fully closed when an interpreter is destroyed and when the process exits. Channels are switched to blocking mode, to ensure that all output is correctly flushed before the process exits. .PP @@ -67,6 +82,13 @@ The command returns an empty string, and may generate an error if an error occurs while flushing output. If a command in a command pipeline created with \fBopen\fR returns an error, \fBchan close\fR generates an error (similar to the \fBexec\fR command.) +.PP +.VS 8.6 +Note that half-closes of sockets and command pipelines can have important side +effects because they result in a shutdown() or close() of the underlying +system resource, which can change how other processes or systems respond to +the Tcl program. +.VE 8.6 .RE .TP \fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... @@ -85,20 +107,21 @@ the command sets each of the named options to the corresponding .PP The options described below are supported for all channels. In addition, each channel type may add options that only it supports. See -the manual entry for the command that creates each type of channels -for the options that that specific type of channel supports. For -example, see the manual entry for the \fBsocket\fR command for its -additional options. +the manual entry for the command that creates each type of channel +for the options supported by that specific type of channel. For +example, see the manual entry for the \fBsocket\fR command for additional +options for sockets, and the \fBopen\fR command for additional options for +serial devices. .TP \fB\-blocking\fR \fIboolean\fR . The \fB\-blocking\fR option determines whether I/O operations on the channel can cause the process to block indefinitely. The value of the option must be a proper boolean value. Channels are normally in -blocking mode; if a channel is placed into nonblocking mode it will +blocking mode; if a channel is placed into non-blocking mode it will affect the operation of the \fBchan gets\fR, \fBchan read\fR, \fBchan puts\fR, \fBchan flush\fR, and \fBchan close\fR commands; see the -documentation for those commands for details. For nonblocking mode to +documentation for those commands for details. For non-blocking mode to work correctly, the application must be using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or invoking the \fBvwait\fR command). @@ -177,7 +200,7 @@ generate an error. .TP \fB\-translation\fR \fImode\fR .TP -\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR +\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR . In Tcl scripts the end of a line is always represented using a single newline character (\en). However, in actual files and devices the end @@ -217,7 +240,7 @@ all platforms Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBcrlf\fR. The default setting for \fB\-translation\fR is \fBauto\fR for both input and output. .TP -\fBbinary\fR +\fBbinary\fR . No end-of-line translations are performed. This is nearly identical to \fBlf\fR mode, except that in addition \fBbinary\fR mode also sets @@ -264,12 +287,14 @@ slow destinations like network sockets. .RS .PP The \fBchan copy\fR command transfers data from \fIinputChan\fR until -end of file or \fIsize\fR bytes have been transferred. If no -\fB\-size\fR argument is given, then the copy goes until end of file. -All the data read from \fIinputChan\fR is copied to \fIoutputChan\fR. -Without the \fB\-command\fR option, \fBchan copy\fR blocks until the -copy is complete and returns the number of bytes written to -\fIoutputChan\fR. +end of file or \fIsize\fR bytes or characters have been transferred; +\fIsize\fR is in bytes if the two channels are using the same encoding, +and is in characters otherwise. If no \fB\-size\fR argument is given, +then the copy goes until end of file. All the data read from +\fIinputChan\fR is copied to \fIoutputChan\fR. Without the +\fB\-command\fR option, \fBchan copy\fR blocks until the copy is +complete and returns the number of bytes or characters (using the same +rules as for the \fB\-size\fR option) written to \fIoutputChan\fR. .PP The \fB\-command\fR argument makes \fBchan copy\fR work in the background. In this case it returns immediately and the @@ -328,7 +353,7 @@ This subcommand creates a new script level channel using the command prefix \fIcmdPrefix\fR as its handler. Any such channel is called a \fBreflected\fR channel. The specified command prefix, \fBcmdPrefix\fR, must be a non-empty list, and should provide the API described in the -\fBreflectedchan\fR manual page. The handle of the new channel is +\fBrefchan\fR manual page. The handle of the new channel is returned as the result of the \fBchan create\fR command, and the channel is open. Use either \fBclose\fR or \fBchan close\fR to remove the channel. @@ -347,7 +372,7 @@ mode, or an error is thrown. .PP The command prefix is executed in the global namespace, at the top of call stack, following the appending of arguments as described in the -\fBreflectedchan\fR manual page. Command resolution happens at the +\fBrefchan\fR manual page. Command resolution happens at the time of the call. Renaming the command, or destroying it means that the next call of a handler method may fail, causing the channel command invoking the handler to fail as well. Depending on the @@ -376,7 +401,7 @@ commands. When a thread or interpreter is deleted, all channels created with this subcommand and using this thread/interpreter as their computing base are deleted as well, in all interpreters they have been shared -with or moved into, and in whatever thread they have been transfered +with or moved into, and in whatever thread they have been transferred to. While this pulls the rug out under the other thread(s) and/or interpreter(s), this cannot be avoided. Trying to use such a channel will cause the generation of a regular error about unknown channel @@ -430,7 +455,7 @@ be readable if there is unread data in an input buffer, except in the special case where the most recent attempt to read from the channel was a \fBchan gets\fR call that could not find a complete line in the input buffer. This feature allows a file to be read a line at a time -in nonblocking mode using events. A channel is also considered to be +in non-blocking mode using events. A channel is also considered to be readable if an end of file or error condition is present on the underlying file or device. It is important for \fIscript\fR to check for these conditions and handle them appropriately; for example, if @@ -445,12 +470,12 @@ Note that client sockets opened in asynchronous mode become writable when they become connected or if the connection fails. .PP Event-driven I/O works best for channels that have been placed into -nonblocking mode with the \fBchan configure\fR command. In blocking +non-blocking mode with the \fBchan configure\fR command. In blocking mode, a \fBchan puts\fR command may block if you give it more data than the underlying file or device can accept, and a \fBchan gets\fR or \fBchan read\fR command will block if you attempt to read more data than is ready; no events will be processed while the commands block. -In nonblocking mode \fBchan puts\fR, \fBchan read\fR, and \fBchan +In non-blocking mode \fBchan puts\fR, \fBchan read\fR, and \fBchan gets\fR never block. .PP The script for a file event is executed at global level (outside the @@ -470,7 +495,7 @@ is written. .PP If the channel is in blocking mode the command does not return until all the buffered output has been flushed to the channel. If the -channel is in nonblocking mode, the command may return before all +channel is in non-blocking mode, the command may return before all buffered output has been flushed; the remainder will be flushed in the background as fast as the underlying file or device is able to absorb it. @@ -493,7 +518,7 @@ If an end-of-file occurs while part way through reading a line, the partial line will be returned (or written into \fIvarName\fR). When \fIvarName\fR is not specified, the end-of-file case can be distinguished from an empty line using the \fBchan eof\fR command, and -the partial-line-but-nonblocking case can be distinguished with the +the partial-line-but-non-blocking case can be distinguished with the \fBchan blocked\fR command. .RE .TP @@ -507,13 +532,46 @@ only those channel names that match it (according to the rules of . Depending on whether \fImode\fR is \fBinput\fR or \fBoutput\fR, returns the number of -bytes of input or output (respectively) currently buffered -internally for \fIchannelId\fR (especially useful in a readable event +bytes of input or output (respectively) currently buffered +internally for \fIchannelId\fR (especially useful in a readable event callback to impose application-specific limits on input line lengths to avoid a potential denial-of-service attack where a hostile user crafts an extremely long line that exceeds the available memory to buffer it). Returns -1 if the channel was not opened for the mode in question. .TP +\fBchan pipe\fR +.VS 8.6 +Creates a standalone pipe whose read- and write-side channels are +returned as a 2-element list, the first element being the read side and +the second the write side. Can be useful e.g. to redirect +separately \fBstderr\fR and \fBstdout\fR from a subprocess. To do +this, spawn with "2>@" or +">@" redirection operators onto the write side of a pipe, and then +immediately close it in the parent. This is necessary to get an EOF on +the read side once the child has exited or otherwise closed its output. +.RS +.PP +Note that the pipe buffering semantics can vary at the operating system level +substantially; it is not safe to assume that a write performed on the output +side of the pipe will appear instantly to the input side. This is a +fundamental difference and Tcl cannot conceal it. The overall stream semantics +\fIare\fR compatible, so blocking reads and writes will not see most of the +differences, but the details of what exactly gets written when are not. This +is most likely to show up when using pipelines for testing; care should be +taken to ensure that deadlocks do not occur and that potential short reads are +allowed for. +.RE +.VE 8.6 +.TP +\fBchan pop \fIchannelId\fR +.VS 8.6 +Removes the topmost transformation from the channel \fIchannelId\fR, if there +is any. If there are no transformations added to \fIchannelId\fR, this is +equivalent to \fBchan close\fR of that channel. The result is normally the +empty string, but can be an error in some situations (i.e. where the +underlying system stream is closed and that results in an error). +.VE 8.6 +.TP \fBchan postevent \fIchannelId eventSpec\fR . This subcommand is used by command handlers specified with \fBchan @@ -539,7 +597,7 @@ other interpreter will cause this subcommand to report an error. Another restriction is that it is not possible to post events that the I/O core has not registered an interest in. Trying to do so will cause the method to throw an error. See the command handler method -\fBwatch\fR described in \fBreflectedchan\fR, the document specifying +\fBwatch\fR described in \fBrefchan\fR, the document specifying the API of command handlers for reflected channels. .PP This command is \fBsafe\fR and made accessible to safe interpreters. @@ -550,6 +608,18 @@ a trusted interpreter. \fBChan event\fR handlers are \fIalways\fR executed in the interpreter that set them up. .RE .TP +\fBchan push \fIchannelId cmdPrefix\fR +.VS 8.6 +Adds a new transformation on top of the channel \fIchannelId\fR. The +\fIcmdPrefix\fR argument describes a list of one or more words which represent +a handler that will be used to implement the transformation. The command +prefix must provide the API described in the \fBtranschan\fR manual page. +The result of this subcommand is a handle to the transformation. Note that it +is important to make sure that the transformation is capable of supporting the +channel mode that it is used with or this can make the channel neither +readable nor writable. +.VE 8.6 +.TP \fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR . Writes \fIstring\fR to the channel named \fIchannelId\fR followed by a @@ -574,16 +644,16 @@ flush\fR command. .PP When the output buffer fills up, the \fBchan puts\fR command will normally block until all the buffered data has been accepted for -output by the operating system. If \fIchannelId\fR is in nonblocking +output by the operating system. If \fIchannelId\fR is in non-blocking mode then the \fBchan puts\fR command will not block even if the operating system cannot accept the data. Instead, Tcl continues to buffer the data and writes it in the background as fast as the underlying file or device can accept it. The application must use the -Tcl event loop for nonblocking output to work; otherwise Tcl never +Tcl event loop for non-blocking output to work; otherwise Tcl never finds out that the file or device is ready for more output data. It is possible for an arbitrarily large amount of data to be buffered for -a channel in nonblocking mode, which could consume a large amount of -memory. To avoid wasting memory, nonblocking I/O should normally be +a channel in non-blocking mode, which could consume a large amount of +memory. To avoid wasting memory, non-blocking I/O should normally be used in an event-driven fashion with the \fBchan event\fR command (do not invoke \fBchan puts\fR unless you have recently been notified via a file event that the channel is ready for more output data). @@ -603,7 +673,7 @@ given to indicate that any trailing newline in the string that has been read should be trimmed. .RS .PP -If \fIchannelId\fR is in nonblocking mode, \fBchan read\fR may not +If \fIchannelId\fR is in non-blocking mode, \fBchan read\fR may not read as many characters as requested: once all available input has been read, the command will return the data that is available rather than blocking for more input. If the channel is configured to use a @@ -619,10 +689,12 @@ channel (see \fBchan configure\fR above for a discussion on the ways in which \fBchan configure\fR will alter input). .PP When reading from a serial port, most applications should configure -the serial port channel to be nonblocking, like this: +the serial port channel to be non-blocking, like this: +.PP .CS \fBchan configure \fIchannelId \fB\-blocking \fI0\fR. .CE +.PP Then \fBchan read\fR behaves much like described above. Note that most serial ports are comparatively slow; it is entirely possible to get a \fBreadable\fR event for each character read from them. Care @@ -670,7 +742,7 @@ position after the end of file. The \fIorigin\fR argument defaults to \fBstart\fR. .PP \fBChan seek\fR flushes all buffered output for the channel before the -command returns, even if the channel is in nonblocking mode. It also +command returns, even if the channel is in non-blocking mode. It also discards any buffered and unread input. This command returns an empty string. An error occurs if this command is applied to channels whose underlying file or device does not support seeking. @@ -695,7 +767,9 @@ Sets the byte length of the underlying data stream for the channel named \fIchannelId\fR to be \fIlength\fR (or to the current byte offset within the underlying data stream if \fIlength\fR is omitted). The channel is flushed before truncation. -.SH EXAMPLE +. +.SH EXAMPLES +.PP This opens a file using a known encoding (CP1252, a very common encoding on Windows), searches for a string, rewrites that part, and truncates the file after a further two lines. @@ -707,30 +781,70 @@ set offset 0 \fI# Search for string "FOOBAR" in the file\fR while {[\fBchan gets\fR $f line] >= 0} { - set idx [string first FOOBAR $line] - if {$idx > -1} { - \fI# Found it; rewrite line\fR + set idx [string first FOOBAR $line] + if {$idx > -1} { + \fI# Found it; rewrite line\fR - \fBchan seek\fR $f [expr {$offset + $idx}] - \fBchan puts\fR -nonewline $f BARFOO + \fBchan seek\fR $f [expr {$offset + $idx}] + \fBchan puts\fR -nonewline $f BARFOO - \fI# Skip to end of following line, and truncate\fR - \fBchan gets\fR $f - \fBchan gets\fR $f - \fBchan truncate\fR $f + \fI# Skip to end of following line, and truncate\fR + \fBchan gets\fR $f + \fBchan gets\fR $f + \fBchan truncate\fR $f - \fI# Stop searching the file now\fR - break - } + \fI# Stop searching the file now\fR + break + } - \fI# Save offset of start of next line for later\fR - set offset [\fBchan tell\fR $f] + \fI# Save offset of start of next line for later\fR + set offset [\fBchan tell\fR $f] } \fBchan close\fR $f .CE +.PP +A network server that does echoing of its input line-by-line without +preventing servicing of other connections at the same time. +.PP +.CS +# This is a very simple logger... +proc log {message} { + \fBchan puts\fR 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" + \fBchan configure\fR $chan -blocking 0 -buffering line + \fBchan event\fR $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} { + \fBchan gets\fR $chan line + if {[\fBchan eof\fR $chan]} { + log "finishing connection from $clientName" + \fBchan close\fR $chan + } elseif {![\fBchan blocked\fR $chan]} { + # Didn't block waiting for end-of-line + log "$clientName - $line" + \fBchan puts\fR $chan $line + } +} + +# Create the server socket and enter the event-loop to wait +# for incoming connections... +socket -server connect 12345 +vwait forever +.CE .SH "SEE ALSO" close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n), fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n), -socket(n), tell(n), refchan(n) +socket(n), tell(n), refchan(n), transchan(n) .SH KEYWORDS channel, input, output, events, offset +'\" Local Variables: +'\" mode: nroff +'\" End: |