Warning: this is an htmlized version!
The original is across this link,
and the conversion rules are here.
(Re)generate: (find-channels-intro)
Source code:  (find-eev "eev-intro.el" "find-channels-intro")
More intros:  (find-eev-quick-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.

Before eepitch had been invented, eev had two other ways to send
commands to external shell-like programs. The first way,
described here,

  (find-prepared-intro "\n`ee'\n")

was technically very simple: running `M-x eev' would save a
series of commands - usually the contents of the region - into a
temporary script file, and then the user would type something
like `ee' at the prompt of a ("prepared") shell; that would
make it read the saved commands and execute them.

Here we will describe the second of the Old Ways - one in which
the target program, which is usually a shell running in an xterm,
is sent a signal saying "execute the command NOW" as soon as a
command is saved into a temporary file by Emacs. The difficulty
is that this requires not only a directory for temporary files,
but also an Expect script, which acts as an intermediary that
listens to signals and handles them pretending that the saved
commands came from the keyboard... and, as some people have said,
this is "a nightmare to set up".

Here we explain the protocol - which can be adapted to other
cases too, like, for example, to make Emacs talk to SmallTalk
environments and to computer algebra systems with GUIs - and we
will present several tests that should help with troubleshooting.

The innards
Let's start with a detailed low-level view of of what we have
just summarized as to "save a command into a temporary file,
then send a signal to the external program etc etc".

Warning: this document is still VERY INCOMPLETE, and some parts
of it are just notes, drafts, and links that may not work for
you... =(

  (find-eev "eegchannel")
  (find-eev "anim/")
  (find-eev "anim/channels.anim")

The protocol, in diagrams
Here's a diagram that shows roughly what we have when X is
running both an Emacs and an xterm, each in a separate window.
Many details have been omitted - for examples, the real
communication happens through fifos and ptys, that are not shown
- but it's easy to build a complete diagram from this. The arrows
indicate flow of information.

             keyboard  mouse      display	    	  
                 |       |           ^		   
                 v       v           |		   
            |                            |	   
            |             X              |	   
            |                            |	   
   key/mouse | ^ display    key/mouse | ^ display   
      events v | commands      events v | commands       
         +---------+              +---------+       
         |         |              |         |       
         |  emacs  |              |  xterm  |       
         |         |              |         |       
         +---------+              +---------+       
                            chars and | ^ chars and 
                              signals v | signals   
                                  |         |       
                                  |   sh    |       
                                  |         |       

To make the external shell at the right able to receive commands
from Emacs we will insert a program between the "xterm" and the
"sh" boxes - an Expect script called eechannel, that will
usually be totally transparent, in the sense that it will let all
the chars and signals that it receives pass through it without

The trick is that "eechannel" will also be "listening to
commands from the outside", according to the following protocol:

  1) each instance of eechannel "listens" to a fixed, named
     "channel"; for simplicity, let's suppose that this name is

  2) When an eechannel receives a signal SIGUSR1 it reads a
     string from the file "eech.A.str" and sends that to the
     shell, as if the user had typed that.

  3) To make it simpler to send the signal, when eechannel starts
     up it saves its pid into the file "eech.A.pid".

That protocol can be depicted as the four horizontal arrows
below; the temporal order is from top to bottom.

				    |             |
				    |    xterm    |
				    |             |
   +-----------+                         |  ^	  
   |           | --> eeg.A.str           v  |     
   |   emacs   | <-- eeg.A.pid      +-------------+
   |           | -----------------> |             |
   +-----------+     eeg.A.str ---> | eechannel A |
                                    |             |
                                         |  ^	
				         v  |	
				    |             |
				    |     sh      |
				    |             |

When Emacs wants to send a line, say, "cd /tmp/", to eechannel,
it does this:

  1) "--> eeg.A.str     "   writes "cd /tmp/" into eech.A.str,
  2) "<-- eeg.A.pid     "   reads eechannel's pid from eech.B.str,
  3) "----------------->"   sends a signal SIGUSR1 to that pid,
  4) "    eeg.A.str --->"   ...and when eechannel receives a SIGUSR1
                                 it reads the contents of eech.A.str and
                                 sends that to its spawned shell.

Actually there's something else - how these programs are started.
If we run just "xterm", it behaves in its default way, and runs
a shell. But if we run

  "xterm -e eechannel A /bin/sh"

then xterm runs "eechannel A /bin/sh" instead of just
"/bin/sh"; and "eechannel A /bin/sh" runs "/bin/sh".

Also, evaluating this

  (find-bgprocess "xterm")

from Emacs runs an xterm, which runs a shell; evaluating either
of these sexps,

  (find-bgprocess "xterm -e eechannel A /bin/sh")
  (find-bgprocess "xterm -e eechannel A $SHELL")

runs an xterm, which runs the "eechannel" script, which runs a
shell. The sexp

  (eexterm "A")

is a shorthand for the one using "$SHELL". Also, note that
"eechannel A ..." saves its pid into "eech.A.pid".

The diagram that shows what happens when we run `(eexterm "A")'
is this one, below - note that the four arrows of the sending
protocol are not shown.

                |            |
                |     X      |
                |            |
               /  ^       \  ^
              v  /         v  \
   +-----------+            +-------------+
   |           | initiates  |             |
   |   emacs   |:::::::::::>|    xterm    |
   |           |            |             |
   +-----------+            +-------------+
                              ::   |  ^   
                              \/   v  |   
                            |             |
              eeg.A.pid <-- | eechannel A |
                            |             |
                              ::   |  ^   
                              \/   v  |  
                            |             |
                            |     sh      |
                            |             |

Downloading and testing eechannel
Here I'll suppose that the directory "~/bin/" exists and is in
your PATH. Run this to download the "eechannel" script and make
it executable:

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
cd ~/bin/
# See:  http://angg.twu.net/bin/eechannel.html
wget -n http://angg.twu.net/bin/eechannel
chmod 755 eechannel

Now let's test - from Emacs - if a local copy of "eechannel"
exists, is in your PATH, and can be executed (remember that it
needs Expect). Calling "eechannel" with not enough arguments
should yield a nice error message.

  (find-fline "~/bin/eechannel")
  (find-sh    "~/bin/eechannel")
  (find-sh          "eechannel")

It uses the environment variable EEVTMPDIR to decide where the
temporary files - ee.CHANNELAME.pid, ee.CHANNELNAME.str - will
be, so let's check that this directory exists:

       (getenv "EEVTMPDIR")
  (find-fline "$EEVTMPDIR/")

Running eechannel with a first argument "-v" should show a lot
of info, and then save the pid at eech.CHANNELAME.pid and run the
given command. Let's try with a command that exits immediately.

  (find-sh "eechannel -v A /bin/true")
  (find-fline "$EEVTMPDIR/" "eech.A.pid")

Now let's verify - using just eepitch, without xterm at this
moment - whether eechannel is being able to receive signals. In
the eepitch script below, two `(find-sh0 "kill ...")'s should
each make the controlled program receive a command - at the first
"kill" an "echo 2", at the second an "echo 3".

* (eepitch-comint "A" "eechannel -v A /bin/sh")
* (eepitch-kill)
* (eepitch-comint "A" "eechannel -v A /bin/sh")
echo 1

* (find-sh0 "             cat $EEVTMPDIR/eech.A.pid")
* (find-sh0 "echo 'echo 2'  > $EEVTMPDIR/eech.A.str")
* (find-sh0 "             cat $EEVTMPDIR/eech.A.str")
* (find-sh0 "kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)")
* (find-sh0 "echo 'echo 3'  > $EEVTMPDIR/eech.A.str")
* (find-sh0 "kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)")
echo 4

If the eepitched shell did run "echo 1", "echo 2", "echo
3", "echo 4", then things are working - "echo 1" and "echo
4" were sent through eepitch, but "echo 3" and "echo 4" were
sent though channels.

Now let's check if we can run an xterm, and if it can run an
eechannel-ed shell instead of a plain shell. Check if the second
sexp above starts an xterm, displays the info from "eechannel
-v", and then runs a shell:

  (find-bgprocess "xterm")
  (find-bgprocess "xterm -e eechannel -v A $SHELL")
  (find-bgprocess "xterm -e eechannel    A $SHELL")

if that worked, run the four sexps below with <f8>,

* (find-sh0 "echo 'echo 1'  > $EEVTMPDIR/eech.A.str")
* (find-sh0 "kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)")
* (find-sh0 "echo 'echo 2'  > $EEVTMPDIR/eech.A.str")
* (find-sh0 "kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)")

and check if the eechannel-ed shell in the xterm has received the
commands "echo 1" and "echo 2". If it did, try the
higher-level version below - but use <f9>s on each line instead
of the <f8>s:

* (eexterm "A")
echo 3
echo 4

If that worked, we're done. =)

Several xterms

* (eexterm "A")
* (eexterm "B")
# listen on port 1234
netcat -l -p 1234

* (eexterm "A")
# Send things to port 1234 (on localhost)
  echo hi
  sleep 1
  echo bye
  sleep 1
} | netcat -q O localhost 1234

[NOT DONE YET. The rest is (recyclable) garbage.]

(Old stuff:)

  emacs runs: (find-bgprocess "xterm -T 'channel A' -e eegchannel A /bin/sh")
  xterm runs:                                          eegchannel A /bin/sh
  eegchannel saves its pid at ~/.eev/eeg.A.pid and runs:            /bin/sh

At this point the xterm is running a shell that is "listening on
channel A"; eegchannel pretends to be transparent and passes all
characters and signals in the vertical arrows transparently - but when
it receives a certain signal (a SIGUSR1) it reads the contents from
the file ~/.eev/eeg.A.str and passes it to the shell, as if those
characters were coming from the xterm - i.e., as if the used had typed

Here are the details of this "protocol":
when we type F9 on a line containing "echo foo",

  emacs saves the string "echo foo\n" into ~/.eev/A.str,
  emacs reads the pid of eegchannel from ~/.eev/eeg.A.pid (say, "1022"),
  emacs runs "kill -USR1 1022",
  eegchannel reads the string from ~/.eev/A.str, and sends it to the shell.

NOTE: one frequent question is: "why are you using two normal files
and SIGUSR1s for the communication between emacs and eegchannel,
instead of making them talk through a fifo?" - the answer is: try to
explain the details of fifos - including creation - to someone who
knows little about the inner workings of a *NIX kernel and who is
uncomfortable to accept another kind of black box... The way with two
files and SIGUSR1s is simpler, works well enough, and I've been able
to write all the code for it in a few hours - and I still don't know
enough about fifos to implement a fifo version of this.

and another one, that was mostly used to control external
programs running in dedicated xterms. You can see an animation
demonstrating it - and an explanation of what each line does -


How to set it up
[To be written]

                 ssh edrx@other.machine
  eegchannel A   ssh edrx@other.machine
  (find-prepared-intro "\n`ee'\n")
  (find-eev "anim/channels.anim")