exec_function
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | exec_function [2006/08/29 20:18] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | # $EPIC: exec_function.txt, | ||
+ | ======Synopsis: | ||
+ | $__exec__(< | ||
+ | |||
+ | ======Technical: | ||
+ | * If the < | ||
+ | * Otherwise, < | ||
+ | * This function returns 3 (three) FDs, which are pipes to/from STDIN, STDOUT and STDERR of the forked process respectively. | ||
+ | * The first FD returned (STDIN) is a write mode FD. | ||
+ | * The subsequent FDs (STDOUT and STDERR) are read mode FDs. | ||
+ | * The FDs returned can be used with $[[read]](), | ||
+ | * Writing to a pipe that is full will cause epic to block. | ||
+ | * Reading from a pipe that is empty will cause epic to block. | ||
+ | * When epic is blocked waiting for a < | ||
+ | * The write pipes will remain full while < | ||
+ | * The read pipes will remain empty while < | ||
+ | * The only guaranteed way to prevent deadlock is to examine the way the program reads and writes its input/ | ||
+ | * This function is relatively new. The /[[exec command|exec]] command may be better suited to your needs given the semantic difficulty of coding with this function. | ||
+ | * Unlike the /[[exec command|exec]] command, < | ||
+ | |||
+ | ======Practical: | ||
+ | This function offers an easier interface and a finer grain control | ||
+ | over the process than /[[exec command|exec]], | ||
+ | dangerous to use. | ||
+ | |||
+ | You could use this function to implement real time text filtering or | ||
+ | scrambling using the unix tool " | ||
+ | |||
+ | $exec() might be a better alternative to $[[perl function|perl]]() and | ||
+ | $[[tcl function|tcl]]() for people who wish to distribute their scripts | ||
+ | and need a certain level of compatibility that the embedded languages | ||
+ | don't provide. | ||
+ | |||
+ | ======Returns: | ||
+ | One writable FD and two readable FDs. | ||
+ | |||
+ | ======Examples: | ||
+ | < | ||
+ | # | ||
+ | # An example of what we can expect. | ||
+ | # | ||
+ | |||
+ | fe ($exec(tr a-zA-Z A-Za-z)) fd { | ||
+ | echo $write($fd qwerASDF): | ||
+ | } | ||
+ | |||
+ | # | ||
+ | # Output | ||
+ | # | ||
+ | |||
+ | Out1: 9::0 # STDIN wrote 9 bytes (including NL), read failed, | ||
+ | Out2: -1: | ||
+ | Out3: -1::0 # STDERR write failed, read nothing, | ||
+ | |||
+ | # FD close succeeded in all cases. | ||
+ | |||
+ | # | ||
+ | # Fortunately for us, md5sums i/o is very predictable. | ||
+ | # some other programs uses the EOF of its input as a signal to start | ||
+ | # delivering output, so it is always safe for $exec() so long as we | ||
+ | # do not attempt to read its output before closing its input. | ||
+ | # | ||
+ | # Note that the technique we use here can be used for most programs | ||
+ | # and all filters if we restrain ourselves from writing too much data | ||
+ | # to STDIN. Exactly how much data can be written depends on the "pipe | ||
+ | # size" ulimit which can be changed with the ulimit command in any(?) | ||
+ | # bourne compatible shell. | ||
+ | # | ||
+ | # Also note that in these examples, the FDs that aren't used are | ||
+ | # closed before processing begins rather than after. | ||
+ | # important to do this because if the program tries to read/write | ||
+ | # a closed FD, it will always return immediately rather than | ||
+ | # blocking. | ||
+ | |||
+ | alias md5 { | ||
+ | # a fast way to set three local variables. | ||
+ | fe ($exec(md5sum)) in out err {break} | ||
+ | @ close($err) | ||
+ | @ write($in $*) | ||
+ | @ close($in) | ||
+ | @ function_return = read($out) | ||
+ | @ close($out) | ||
+ | } | ||
+ | |||
+ | # | ||
+ | # Translate upper to lower and lower to upper using a perl script. | ||
+ | # The critical thing about this alias is the $|=1 in the perl script, | ||
+ | # which turns autoflush on so that we receive the output immediately | ||
+ | # after feeding it the input. | ||
+ | # do this, which makes it unsuitable for this application. | ||
+ | # | ||
+ | # Anyway, the reason this is critical is that we're going to $exec() | ||
+ | # the perl script outside of the alias, perhaps at bootup, and leave | ||
+ | # it running in the background forever with the assumption that every | ||
+ | # line we give it is going to give us precisely one line back. Of | ||
+ | # course, this is a very delicate thing since errors are going to | ||
+ | # accumulate. | ||
+ | # | ||
+ | # Also, note the double quotes where we might normally use single | ||
+ | # quotes in the shell. | ||
+ | # to epics " | ||
+ | # under these rules, though you can escape " | ||
+ | # the relevant parts of your script in braces like I have for this | ||
+ | # example. | ||
+ | # | ||
+ | |||
+ | fe ($exec(perl -lpe " | ||
+ | @ :: | ||
+ | @ :: | ||
+ | @ close($err) | ||
+ | break | ||
+ | } | ||
+ | |||
+ | alias transcase { | ||
+ | @ write($transcase.in $*) | ||
+ | return $read($transcase.out) | ||
+ | } | ||
+ | </ | ||
exec_function.txt · Last modified: 2006/08/29 20:18 by 127.0.0.1