[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mkfifo



Tomohiro Shibata wrote:

>  There has been some discuttion on the mailing list on how to make
> bidirectional communication between clisp and other programs using Unix.
> below is one solutoin provided by Mr. Haible.
   >>  (shell "mkfifo /tmp/wish-in")
   >>  (shell "mkfifo /tmp/wish-out")
   >>  (setq *lisp-to-wish-stream*
   >>	 (make-two-way-stream (open "/tmp/wish-out" :direction :input)
   >>			      (open "/tmp/wish-in" :direction :output)
   >>  ) )
   >>  (shell "wish < /tmp/wish-in > /tmp/wish-out")
   >>  (delete-file "/tmp/wish-in")
   >>  (delete-file "/tmp/wish-out")
>
>  As for my check, it doesn't work as they are seen above.
> when (open pipename-out :direction :input) is entered, prompt never comes.
> But (open pipename-in :direction :output) is entered, I can get 
> #<FILE-HANDLE-STREAM #"out">.
> I think only it can work in case of `:direction :io '. And I tried:
	   >>  (shell "command < pipename-in > pipename-out") ,
> but I couln't succeed. Has Mr. Hoefling already succeeded to connect
> with WISH?
> Any suggestion and information are welcome.

As I am directly adressed, here my response. In my masters thesis I am using 
clisp under linux and UNIX (Sun). The graphical user interface for my program
is written in tcl/tk by another student and he has tried to explain his solution
for the problem for you. His solution is rather special and is realized mostly 
in tcl and not in clisp, but it could be done in a similar way in C with another
UNIX-process.
Here is his solution:
________________________________________________________________________________

My solution works completely the other way round:
I don't call wish from within lisp, but start the lisp interpreter from
within the wish. I think this is more useful because normally i want to evaluate
lisp functions in response to tk events.
I need the "addinput patch" which is available at harbor.ecn.purdue.edu.

The following code works with tcl7.0/tk3.3 and a widget shell with the appropriate patch applied.

# the proc ChildProcess forks a new process from exec file cmd
# and sets it's stdio to inPipe/outPipe

proc ChildProcess {cmd inPipe outPipe } {
    if {[set childPid [fork]] == 0} {
	   # overwrite stdin with inPipe
           dup $inPipe stdin
           # close the inPipe at the lisp side
           close $inPipe
	   # do the same with stdout/stderr
           dup $outPipe stdout
           dup $outPipe stderr
           close $outPipe
           # disconnect process from terminal (useful for signal handling)
           id process group set
           # run cmd (lisp,shell, or whatever)
           execl $cmd
           # will never make it here...
       }
    return $childPid
}

# create fifo (named pipe)
# set your path to the mknod binary here!
proc mkfifo name {
#  set mknod /bin/mknod # linux
  set mknod /usr/etc/mknod # sun
   catch { exec $mknod $name p } msg
   if { "$msg" != "" } { puts stderr $msg }
}

# send lisp command to lisp interp.
proc to-lisp {cmd} {
    global tclOutPipe
    puts $tclOutPipe $cmd
    flush $tclOutPipe
}

# signal handler
proc quitCmd  { } {
    global tclOutPipe tclInPipe tclDataInPipe
    catch {
        to-lisp "(quit)"
        removeinput $tclInPipe
        removeinput $tclDataInPipe
        close $tclOutPipe
        close $tclInPipe
        close $tclDataInPipe
        unlink [format "/tmp/wishin-%d" [pid] ]
    }
    destroy .
}

# handlers for receiving input from one of the pipes
# the catch is needed for suns where i get some strange error message
proc process-toplevel {event fileid} {
    catch {
        if { [gets $fileid line] < 0 } {
            quitCmd
        } else { 
		echo toplevel: $line
        }
    }
}

proc process-data {event fileid} {
    catch {
        if { [lgets $fileid line] < 0 } {
            quitCmd
        } else { 
		echo data: $line
        }
    } msg
    if { "$msg" != "" } { puts stderr $msg }
}

# main program:
# first i create two pipes for communication to/from lisp *terminal-io*.

    pipe lispInPipe tclOutPipe
    pipe tclInPipe lispOutPipe 

# next i create a named pipe for data communication lisp -> wish (i want to read lisp data
# from within tcl)
    set pipename [format "/tmp/wishin-%d" [pid] ]
    mkfifo $pipename
# the named pipe MUST be opened non-blocking, because otherwise it will hang
# until the other side is opened (see unix manual) 
    set tclDataInPipe [open $pipename {RDONLY NONBLOCK} ]
# sorry, but i don't know if this is really necessary - at least it doesn't cause harm ....
    fcntl $tclInPipe NONBLOCK 1
    fcntl $tclDataInPipe NONBLOCK 0
# install addinput handlers
    addinput -read $tclInPipe "process-toplevel %E %F"
    addinput -read $tclDataInPipe "process-data %E %F"
# fork off clisp

    ChildProcess clisp $lispInPipe $lispOutPipe
# set signal handler so that clisp gets terminated when you kill wish
    signal trap { SIGTERM SIGQUIT SIGINT } quitCmd

________________________________________________________________________________

I hope this answer helps at least those who use the combination wish/clisp.

*********************************************************************
Bjoern HOEFLING, DFKI, Postfach 2080, W-67608 Kaiserslautern, Germany
hoefling@dfki.uni-kl.de   Phone: +49-631-205-3487         Fax:  -3210
*********************************************************************