Overview | Index by: file name |
procedure name |
procedure call |
annotation
pty.tcl
(annotations | original source)
#
# Copyright (C) 2010 Alexandros Stergiakis <alsterg@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#//#
# Execute an external system command on its own PTY.
#
# This is apropriate for executiong external commands that require a controling
# terminal, such as vi, more, less, and telnet from busybox. 'ptyexec' does not
# return until command has finished, but while it is executing the event loop
# is served. The external application can be forced to terminate prematurely.
#//#
namespace eval pty {
namespace export ptyexec ptykill ptyresize
variable term 0
variable busy 0
# Execute an external program like "exec" does, but in its own PTY.
# Some interactive programs like 'vi', 'more', 'less', 'telnet', 'sh' assume that they are
# connected on a pty. If this is not the case (like when using "exec"), they malfunction.
#
# The external command takes control of Standard I/O of the session.
#
# Execution can be interrupted by the user with the break key sequence: Ctrl ^ + x/
# This is enforced in session.tcl by calling ptykill (see below).
#
# It supports the syntax of 'bgexec' and also:
# -root : Execute without root priviledges.
#
# @param args Optional parameters, the program to execute, and arguments to the executable
# @return Nothing if not error occurs, otherwise the error (and options).
# @error
proc ptyexec {args} {
variable term 0
variable busy
# XXX -root & --
if {[lindex $args 0] eq {-root}} {
set args [lrange $args 1 end]
}
if {$busy} {
error "there is an on-going ptyexec session for this thread; only one is allowed per session at any time"
}
set stdin_e [fileevent stdin readable]
fileevent stdin readable {}
set stdin_s [fconfigure stdin]
set stdout_s [fconfigure stdout]
set stderr_s [fconfigure stderr]
fconfigure stdin -buffering none -blocking 1 -translation auto
fconfigure stdout -buffering line -blocking 1 -translation auto
fconfigure stderr -buffering line -blocking 1 -translation auto
set busy 1
catch {
bgexec ::pty::term pty {*}$args >@ stdout <@ stdin 2>@ stderr
} result options
set busy 0
fconfigure stdin {*}$stdin_s
fconfigure stdout {*}$stdout_s
fconfigure stderr {*}$stderr_s
fileevent stdin readable $stdin_e
# Ignore error if we forced termination.
# The error in this case is always: Child process terminated unexpectedly
if {[lindex $term 0] eq {KILLED}} return
return -options $options $result
}
# Kill an ongoing ptyexec execution.
proc ptykill {} {
variable term 1
}
# Resize the window size of the PTY of an ongoing ptyexec session.
proc ptyresize {} {
# XXX
}
} ;# Namespace ends
Overview | Index by: file name |
procedure name |
procedure call |
annotation
File generated 2010-03-13 at 22:28.