Version 15 of stdin

Updated 2007-03-02 23:39:06

A part of stdio, this file handle is opened by default for each application making use of the stdio package of code.

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 when using gets .

A quite distinct use of the same word refers to the stdin package Stephen Uhler includes with tclhttpd.


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!

JC


Has Jeremy Cowgar tested this? According to the man page the /etc/inetd.conf entry should be:

           service name
           socket type
           protocol
           wait/nowait[.max]
           user[.group]
           server program
           server program arguments

where the arguments include the program name.

With this change, inetd loops and quits after 35 or so tries to run the program. This is the debug output:

   someone wants test
   30302 execl /home/user/develop/program.tcl
   30302 reaped, status 100
   restored test, fd 13

Tom Kuiper


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"

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.


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 issue. (As running expect 8.3 or tclsh did not procude this problem) Issuing a command:

 fconfigure stdin -blocking 1

Enabled blocking once again on the standard input, and then of course waiting occured!


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?


Category Glossary