Impressum
GoTo:
Home
 
Café BilderBuch Akazien Verlag   
 
Lesezeichen [ Info # QR-Code # Projekte ]Do 19 Okt 2017 12:52:40


 huecker.com # Grundlagen der Programmierung | Tcl Tutorial.
--

 

. Invoking Subprocesses from Tcl - exec, open .

[ Previous | Index | Next ]

So far the lessons have dealt with programming within the Tcl interpreter. However, Tcl is also useful as a scripting language to tie other packages together. To accomplish this function, Tcl has methods for invoking subprocesses.

There are two ways to invoke a subprocess from Tcl:

  • open ...... run a new program with I/O connected to a file descriptor
  • exec ...... run a new program as a subprocess

The open call is the same call that is used to open a file. If the first character in the file name argument is a pipe symbol (|), then open will treat the rest of the argument as a program name, and will exec that program with the standard input or output connected to a file descriptor. A pipe can be opened to a sub-process for reading, writing or both reading and writing.

If the file is opened for both reading and writing you must be aware that the pipes are buffered. The output from a puts command will be saved in an I/O buffer until the buffer is full, or until you execute a flush command to force it to be transmitted to the subprocess. The output of the subprocess will not be available to a read or gets until the I/O buffer for the subprocess has filled its output buffer.

The exec call is similar to invoking a program (or a set of programs piped together) from the shell prompt or in a unix shell script. It supports several styles of output redirection, or it can return the output of the sub-process as the return of the exec call.

open |progName ?access?
Returns a file descriptor for the pipe. The progName argument must start with the pipe symbol. If progName is enclosed in quotes or braces, it can include arguments to the subprocess.
exec ?switches? arg1 ?arg2? ... ?argN?
Exec treats its arguments as the names and arguments for a set of subprocesses to execute. If the first args start with a "-", then they are treated as switches to the exec command, instead of being invoked as subprocesses or subprocess options.

Switches are:

-keepnewline
Retains a trailing newline in the pipeline's output. Normally a trailing newline will be deleted.
--
Marks the end of the switches. The next string will be treated as arg1, even if it starts with a "-"

Arg1 - argN can be one of:

  • the name of a program to execute
  • an command line argument for the subprocess
  • an I/O redirection instruction.

There are many permutations to the I/O redirection commands. The main subset of these commands is:

|
Pipes the standard output of the command preceeding the pipe symbol into the standard input of the command following the pipe symbol.
< fileName
The first program in the pipe will read input from fileName.
< @ fileID
The first program in the pipe will read input from the Tcl descriptor fileID. FileID is the value returned from an open ... "r" command.
< < value
The first program in the pipe will read value as its input.
> fileName
The output of the last program in the pipe will be sent to fileName. Any previous contents of fileName will be lost.
> > fileName
The output of the last program in the pipe will be appended to fileName.
2> fileName
The standard error from all the programs in the pipe will be sent to fileName. Any previous contents of fileName will be lost.
2> > fileName
The standard error from all the programs in the pipe will be appended to fileName.
> @ fileID
The output from the last program in the pipe will be written to fileID. FileID is the value returned from an open ... "w" command.

If you are familiar with shell programming, there are a few differences to be aware of when you are writing Tcl scripts that use the exec and open calls.

  • You don't need the quotes that you would put around arguments to escape them from the shell expanding them. In the example, the argument to set is not put in quotes. If it were put in quotes, the quotes would be passed to set, instead of being stripped off (as the shell does), and set would report an error.
  • If you use the open |cmd "r+" construct, you must follow each puts with a flush to force Tcl to send the command from its buffer to the program. The output from the subprocess may be buffered in its output buffer. - You can sometimes force the output from the sub-process to flush by sending an exit command to the process. You can also use the fconfigure command to make a channel unbuffered. The expect extension to Tcl provides a much better interface to other programs, which handles the buffering problem.
  • If one of the commands in an open |cmd fails the open does not return an error. However, attempting to read input from the file descriptor with gets $file will return an empty string. Using the gets $file input construct will return a character count of -1. - Put quotes around the s/.Q//g in the example to see this behavior.
  • If one of the commands in an exec call fails to execute, the exec will return an error, and the error output will include the last line describing the error.

--

. Example .

   # Create a unique (mostly) file name for a Tcl program
   set tempFileName "TEMPDIR/inv_[pid].tcl"

   # Open the output file, and write a simple program to it

   set outfl [open $tempFileName w]

    puts $outfl {
     set len [gets stdin line]
     if {$len < 5} {exit -1}

     for {set i $len} {$i >= 0} {incr i -1} {
      append l2 [string range $line $i $i]
     }
     puts $l2
     exit 0;
    }

   # Flush and close the file
    flush $outfl
   close $outfl

   # Run the new Tcl file interactively
   # Open a pipe to the program
   set io [open "|TCL_INTERP $tempFileName" r+]

   # send a string to the new program
   # *MUST FLUSH*
   puts $io "This will come back backwards."
   flush $io

   # Get the reply, and display it.
   set len [gets $io line]

   puts  "To reverse: 'This will come back backwards.'"
   puts "Reversed is: $line"
   puts "The line is $len characters long"

   # Run the program with input defined in an exec call

   set invert [exec TCL_INTERP $tempFileName << \
	"ABLE WAS I ERE I SAW ELBA"]

   # display the results
   puts "The inversion of 'ABLE WAS I ERE I SAW ELBA' is \n $invert"

   # Clean up
   file delete $tempFileName
  

--
[ Home | Top ]
[ . Previous | Index | Next . ]
Der Inhalt dieser Seite wurde am 24.05.2016 um 12.17 Uhr aktualisiert.
Navigation Seminare Magic Software Projekte Publikationen Kontakt Home
 
   huecker dot com * Germany
© 1999, 2017 Franz-Josef Hücker. All Rights Reserved.
Send Page Print Page LinkedIn follow me on twitter RSS Feeds & Podcasts