|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
#!/bin/sh
# the next line restarts using expect \
exec expect "$0" -- "$@"
# (find-man "tclsh" "#!")
# _ _
# ___ ___ ___| |__ __ _ _ __ _ __ ___| |
# / _ \/ _ \/ __| '_ \ / _` | '_ \| '_ \ / _ \ |
# | __/ __/ (__| | | | (_| | | | | | | | __/ |
# \___|\___|\___|_| |_|\__,_|_| |_|_| |_|\___|_|
#
# eechannel: run an interactive program accepting input from a "channel".
#
# This is a "temporarily ugly" rewrite of a script that had very nice
# headers, and that can still be found at:
# <http://angg.twu.net/eev-current/eegchannel>
# <http://angg.twu.net/eev-current/eegchannel.html>
#
# The present version has far less quirks (I hope), and its
# documentation and tests are at:
# (find-eev "eev-intro.el" "find-channels-intro")
# (find-channels-intro)
# (find-channels-intro "Downloading and testing")
#
# Please bear with its current ugliness for a while! Cheers! =)
# Edrx, 2013feb11
# Copyright (C) 2004,2007,2012 Free Software Foundation, Inc.
#
# This file is part of GNU eev.
#
# GNU eev is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU eev is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Emacs; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
# Author: Eduardo Ochs <eduardoochs@gmail.com>
# Maintainer: Eduardo Ochs <eduardoochs@gmail.com>
# Version: 2013feb11
# Keywords: e-scripts, processes
#
# Latest version: <http://angg.twu.net/bin/eechannel>
# htmlized: <http://angg.twu.net/bin/eechannel.html>
# eechannel: run an interactive program accepting input from a "channel".
# eechannel 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:
#
# eechannel [-v] <channelname> <prog> [<args>]
#
# For example:
#
# eechannel A bash
#
# will invoke "bash" and run it interactively, with no keyboard or
# output translation; but eechannel 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 eechannel "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/shot-f9.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 pidfile {} { global channel; return [EEVTMPDIR]/eech.${channel}.pid }
proc strfile {} { global channel; return [EEVTMPDIR]/eech.${channel}.str }
proc rmlastnewline {str} { regexp "^(.*)\n\$" $str -> str; return $str }
set verbose 0
if {[lindex $argv 0] == "-v"} { # if the first arg is "-v" then
set verbose 1; # set verbose to 1 and
set argv [lrange $argv 1 end]; # discard that first argument
}
# (find-man "3tcl if")
# (find-books "__comp/__comp.el" "ousterhout")
# (find-tcltktext "")
set channel [lindex $argv 0]; # first argument: channel
set progandargs [lrange $argv 1 end]; # other arguments: target prog and args
if {[llength $argv] < 2} {
puts "Usage: eechannel \[-v\] <channelname> <prog> \[<args>\]"
exit
}
proc runtimeinfo {} {
global channel progandargs
return "Expect binary: [info nameofexecutable]
Expect script: [file normalize [info script]]
Expect pid: [pid]
Channel name: $channel
Target program: $progandargs
Target pwd: [pwd]/
\$EEVTMPDIR: [getenv EEVTMPDIR]
Temp dir: [EEVTMPDIR]/
Pid file: [pidfile]
Command file: [strfile]
Signal: SIGUSR1
Send cmd with: echo '<cmd>' > [strfile]
Send sig with: kill -USR1 \$(cat [pidfile])"
}
if {$verbose} {
puts [runtimeinfo]
}
# set argv [lrange $argv 1 end]; # discard first argument
# (find-sh0 "eechannel")
# (find-sh "eechannel -v")
# (find-sh0 "eechannel -v")
# (find-sh "eechannel -v A")
# (find-sh "eechannel -v A prog arg1 arg2")
# exit
writefile [pidfile] "[pid]\n"
trap {send -- [readfile [strfile]]} USR1
# Transmit resizings. From <http://www.hadron.org/~hatch/goodies/rrr>.
trap {
stty rows [stty rows] columns [stty columns] < $spawn_out(slave,name)
} WINCH
# puts ([lrange $argv 1 end])
# eval spawn -noecho $argv
eval spawn -noecho [lrange $argv 1 end]
# eval spawn [lrange $argv 1 end]
# stty raw; # A relic. Why this? For \n -> \r translation?
interact
# Local Variables:jjj
# mode: tcl
# coding: raw-text-unix
# ee-anchor-format: "proc %s"
# End: