A part of [stdio], this ''[file handle]'' is opened by default for each application making use of the stdio package of code. It is also the name of the standard input channel in Tcl (though Tcl doesn't use stdio). This input file may correspond to a disk file, pipe, terminal device, or other construct. To refer to the stdin filehandle in Tcl, use the string '''stdin''' as the channel name when using [gets]. A quite distinct use of the same word refers to the stdin [package] [Stephen Uhler] includes with [tclhttpd]. <> ** The stdin channel** An example of reassigning stdin and providing a prompt and capturing user input for tclsh. #!/usr/bin/tclsh # by Mike Tuxford # # the handler for stdin proc localHandler {} { # get the data from stdin gets stdin data # client will exit if you type "exit". How original! if {$data == "exit"} { exit } else { # process your data here, or pass it to another proc # or pass it to a local/remote server # return a new pseudo-prompt puts -nonewline stdout \ "[clock format [clock seconds] -format "%H:%M:%S"] Tcl> " flush stdout } return } # assign our event handler for stdin fileevent stdin readable localHandler # send a startup message and initial prompt puts -nonewline stdout \ "Tcl pseudo-prompt activated... \ \n[clock format [clock seconds] -format "%H:%M:%S"] Tcl> " flush stdout # enter the tcl event loop vwait __forever__ [Mike Tuxford] ---- You can even use it with inetd for an instant TCP/IP server: in your services file: test 10000/tcp in your /etc/inetd.conf: test stream tcp /home/user/develop/program.tcl program.tcl Then in your program just read stdin like above and that's it! [jnc] ---- The entry in inetd.conf, at least for Linux 2.4.20+, should be test stream tcp nowait root /home/user/develop/program.tcl program.tcl [TK] ---- [SB]: Turn off buffering on [stdout] to use repetitive -nonewline in interactive input with tclsh: fconfigure stdout -buffering none puts -nonewline "Give me your input: " gets stdin first puts -nonewline "Give me another input: " gets stdin second puts "First you told me $first and then $second" ---- Question: Using "gets stdin myVar" doesn't WAIT for the user to enter stuff... it simply reads from the stdin stream. Any idea how to make it wait? I tried: while {[[gets stdin myVar] < 0} {} This works...but of course takes 100% CPU.. .ew. Answer: Well, gets will wait until some newline terminated text is available on the stdin file descriptor. However, if the user typed ahead, or the input is coming from a file, then of course, no waiting is necessary. If what you really want to do is "gather input from the user's terminal after prompting, disgarding anything previously typed', then you probably want to mess with [stty] on Unix like systems. I don't know what the equivalent would be on Windows. Solution: It turns out that by default?, [expect] 8.4 was causing the behavior, (as running expect 8.3 or tclsh did not produce this problem). Issuing a command: fconfigure stdin -blocking 1 Enabled blocking once again on the standard input, and then of course waiting occured! ---- See also [read both a file and stdin], ---- [LV] Could someone add info (or a pointer) regarding the techniques a Tcl developer must use to be able to interact with stdin when running on Windows using a wish based tcl interpreter? ---- [rpremuz] How to check if stdin corresponds to a terminal or a file/pipe? [DKF]: If stdin is a terminal (or serial line; they're the same at the device driver layer on Unix) or a network client [socket], Tcl automatically detects it and makes the channel be of the right type, enabling extra options for [fconfigure]. We don't do anything for pipes at the moment; Tcl treats them the same as files and any differences you see are due to the OS. ---- Question: I'm using a package (DpTcl) that takes the handle of a socket as an argument. My program is invoked through telnet so stdin is a (pty in front of a) socket, yet if I pass stdin as the socket I think I'll get <> when DpTcl goes to write to it. How can I merge stdin and stdout back to be one socket? [DKF]: Not easy. You'd have to write your own channel type to act as the merged front end, and even then you'd be stuck if you then wanted to hand off to a sub-process. If you are up to scripting your own channels, see [chan create][http://www.tcl.tk/man/tcl8.5/TclCmd/chan.htm] and [http://www.tcl.tk/man/tcl8.5/TclCmd/refchan.htm] for details. Mmm, thanks! Could I create a channel with [Expect]? The approach that occurs to me is to create a real socket, hand one end into DpTcl and have [interact] drive the other end from stdin and stdout; is there any simpler approach? ---- ** The stdin package ** [daapp] This is extract of stdin package from [tclhttpd] without history control. I use to develop [comm] based server from [Emacs], very convenient. Without this [comm] will not work in interactive tclsh. namespace eval stdin { variable version 0.1 variable command "" variable detach 0 } proc stdin::Read {prompt} { variable command variable detach if {[eof stdin]} { set detach 1 fileevent stdin readable {} return } else { append command [gets stdin] if {[info complete $command]} { catch {uplevel #0 $command} result puts -nonewline "$result\n$prompt" flush stdout set command "" } else { append command \n } return } } proc stdin::attach {{prompt "% "}} { variable command variable detach puts -nonewline $prompt flush stdout fileevent stdin readable [list [namespace current]::Read $prompt] vwait detach } package provide stdin $stdin::version To use it simply type: $ tclsh % package require stdin % stdin::attach "stdin % " or add to your .tclshrc: if { $tcl_interactive || [info exists ::env(EMACS)]} { package require stdin stdin::attach "stdin % " } <> Glossary | Channel | Package