#!/bin/sh
# the next line restarts using expect \
exec expect "$0" -- "$@"
#
# Edrx, 2004dec16
# Current version: 2004dec29
#
# eegchannel: run an interactive program accepting input from a "channel".
# eegchannel is a version of eeg/eeg4 in which the sending of a command to
# the spawned process is triggered by a SIGUSR1, not by a M-L.
# Usage:
#
#   eegchannel <channelname> <prog> [<arg1> [<arg2> ...]]
#
# For example:
#
#   eegchannel A bash
#
# will invoke "bash" and run it interactively, with no keyboard or
# output translation; but eegchannel will create a file eeg.A.pid and
# will use it and a file called eeg.A.str to establish a
# (unidirectional) extra communication channel from the outside world
# to the spawned process ("bash" in this case). If we do
#
#   echo 'echo $[1+2]' > $EEVTMPDIR/eeg.A.str
#   kill -USR1 $(cat $EEVTMPDIR/eeg.A.pid)
#
# we are storing a line of input ("echo $[1+2]\n") in eeg.A.str and
# then saying to eegchannel "send that to the process you're
# controlling". From the point of view of the controlled process,
# thanks to Expect's usual magic, things will be exactly as if the
# user typed interactively "echo $[1+2]" and then a "return".
#
# For a high-level example of how this can be used see:
#   (find-eevfile "doc/eechannel.png")
#   (find-eev "eev-dev.el" "eechannel-do-this-line")
#
# (find-eev "eeg4" "misc")
# (find-eev "eeg4" "arguments")
# (find-eev "eeg4" "dospawn")

proc readfile {fname} {
  set ch [open $fname r]; set str [read $ch]; close $ch; return $str
}
proc writefile {fname str} {
  set ch [open $fname w]; puts -nonewline $ch $str; close $ch
}
proc getenv {key {defaultvalue {}}} {
  global env; expr {[info exist env($key)]?$env($key):$defaultvalue}
}
proc EEVTMPDIR {} { getenv EEVTMPDIR [getenv HOME]/eev-current/tmp }

proc rmlastnewline {str} { regexp "^(.*)\n\$" $str -> str; return $str }
proc pidfile {} { global channel; return [EEVTMPDIR]/eeg.${channel}.pid }
proc strfile {} { global channel; return [EEVTMPDIR]/eeg.${channel}.str }

set channel [lindex $argv 0];   # first argument
set argv [lrange $argv 1 end];  # discard first argument

writefile [pidfile] "[pid]\n"
trap {send [readfile [strfile]]} USR1

eval spawn -noecho $argv
stty raw;               # A relic. Why this? For \n -> \r translation?
interact

#  Local Variables:
#  mode:                 tcl
#  coding:               raw-text-unix
#  ee-anchor-format:     "«%s»"
#  End: