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: