PTY
module PTY
PTY允许您使用:: open或::使用特定命令产生新终端来分配新终端。
例
在这个例子中,我们将更改factor
命令中的缓冲类型,假定该因子使用stdio进行标准输出缓冲。
如果使用IO.pipe而不是:: open,则此代码会因为因子的stdout被完全缓冲而死锁。
# start by requiring the standard library PTY
require 'pty'
master, slave = PTY.open
read, write = IO.pipe
pid = spawn("factor", :in=>read, :out=>slave)
read.close # we dont need the read
slave.close # or the slave
# pipe "42" to the factor command
write.puts "42"
# output the response from factor
p master.gets #=> "42: 2 3 7\n"
# pipe "144" to factor and print out the response
write.puts "144"
p master.gets #=> "144: 2 2 2 2 3 3\n"
write.close # close the pipe
# The result of read operation when pty slave is closed is platform
# dependent.
ret = begin
master.gets # FreeBSD returns nil.
rescue Errno::EIO # GNU/Linux raises EIO.
nil
end
p ret #=> nil
License
C) Copyright 1998 by Akinori Ito.
This software may be redistributed freely for this purpose, in full
or in part, provided that this entire copyright notice is included
on any copies of this software and applications and derivations thereof.
This software is provided on an "as is" basis, without warranty of any
kind, either expressed or implied, as to any matter including, but not
limited to warranty of fitness of purpose, or merchantability, or
results obtained from use of this software.
公共类方法
检查(pid,raise = false)→Process :: Status或零显示源
检查(pid,true)→无或提高PTY :: ChildExited
检查由指定的子进程的状态pid
。nil
如果进程仍然存在,则返回。
如果进程不存在,并且raise
为真,则会引发PTY :: ChildExited异常。否则,它将返回一个Process :: Status实例。
pid
要检查的进程的进程ID
raise
如果true
并且确定的过程pid
不再存在,则会提出PTY :: ChildExited。
static VALUE
pty_check(int argc, VALUE *argv, VALUE self)
{
VALUE pid, exc;
rb_pid_t cpid;
int status;
const int flag =
#ifdef WNOHANG
WNOHANG|
#endif
#ifdef WUNTRACED
WUNTRACED|
#endif
0;
rb_scan_args(argc, argv, "11", &pid, &exc
cpid = rb_waitpid(NUM2PIDT(pid), &status, flag
if (cpid == -1 || cpid == 0) return Qnil;
if (!RTEST(exc)) return rb_last_status_get(
raise_from_check(cpid, status
UNREACHABLE;
}
spawn(command_line) { |r, w, pid| ... } Show source
spawn(command_line) → r, w, pid
spawn(command, arguments, ...) { |r, w, pid| ... }
spawn(command, arguments, ...) → r, w, pid
在新分配的pty上产生指定的命令。你也可以使用别名:: getpty。
命令的控制tty设置为pty的从设备,其标准输入/输出/错误被重定向到从设备。
command
并且command_line
是给定String的完整命令。任何额外的arguments
将被传递给命令。
返回值
在非块形式中,这将返回一个大小为3的数组[r, w, pid]
。
在块形式中,这些相同的值将被赋予块:
r
包含命令的标准输出和标准错误的可读IO
w
一个可写的IO,是命令的标准输入
pid
该命令的进程标识符。
static VALUE
pty_getpty(int argc, VALUE *argv, VALUE self)
{
VALUE res;
struct pty_info info;
rb_io_t *wfptr,*rfptr;
VALUE rport = rb_obj_alloc(rb_cFile
VALUE wport = rb_obj_alloc(rb_cFile
char SlaveName[DEVICELEN];
MakeOpenFile(rport, rfptr
MakeOpenFile(wport, wfptr
establishShell(argc, argv, &info, SlaveName
rfptr->mode = rb_io_modestr_fmode("r"
rfptr->fd = info.fd;
rfptr->pathv = rb_obj_freeze(rb_str_new_cstr(SlaveName)
wfptr->mode = rb_io_modestr_fmode("w") | FMODE_SYNC;
wfptr->fd = rb_cloexec_dup(info.fd
if (wfptr->fd == -1)
rb_sys_fail("dup()"
rb_update_max_fd(wfptr->fd
wfptr->pathv = rfptr->pathv;
res = rb_ary_new2(3
rb_ary_store(res,0,(VALUE)rport
rb_ary_store(res,1,(VALUE)wport
rb_ary_store(res,2,PIDT2NUM(info.child_pid)
if (rb_block_given_p()) {
rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info
return Qnil;
}
return res;
}
open → master_io, slave_file()
open {|master_io, slave_file| ... } → block value
Allocates a pty (pseudo-terminal).
在块形式中,生成两个参数,master_io, slave_file
并返回块的值open
。
如果块尚未关闭,IO块和文件将在块完成后关闭。
PTY.open {|master, slave|
p master #=> #<IO:masterpty:/dev/pts/1>
p slave #=> #<File:/dev/pts/1>
p slave.path #=> "/dev/pts/1"
}
在非块形式中,返回一个两元素数组,[master_io, slave_file]
。
master, slave = PTY.open
# do something with master for IO, or the slave file
两种形式的论点是:
master_io
作为IO的主人。
slave_file
作为文件的pty的奴隶。通过终端设备的路径可用slave_file.path
IO#raw! 可用于禁用换行符:
require 'io/console'
PTY.open {|m, s|
s.raw!
...
}
static VALUE
pty_open(VALUE klass)
{
int master_fd, slave_fd;
char slavename[DEVICELEN];
VALUE master_io, slave_file;
rb_io_t *master_fptr, *slave_fptr;
VALUE assoc;
getDevice(&master_fd, &slave_fd, slavename, 1
master_io = rb_obj_alloc(rb_cIO
MakeOpenFile(master_io, master_fptr
master_fptr->mode = FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX;
master_fptr->fd = master_fd;
master_fptr->pathv = rb_obj_freeze(rb_sprintf("masterpty:%s", slavename)
slave_file = rb_obj_alloc(rb_cFile
MakeOpenFile(slave_file, slave_fptr
slave_fptr->mode = FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX | FMODE_TTY;
slave_fptr->fd = slave_fd;
slave_fptr->pathv = rb_obj_freeze(rb_str_new_cstr(slavename)
assoc = rb_assoc_new(master_io, slave_file
if (rb_block_given_p()) {
return rb_ensure(rb_yield, assoc, pty_close_pty, assoc
}
return assoc;
}
spawn(command_line) { |r, w, pid| ... } Show source
spawn(command_line) → r, w, pid
spawn(command, arguments, ...) { |r, w, pid| ... }
spawn(command, arguments, ...) → r, w, pid
在新分配的pty上产生指定的命令。你也可以使用别名:: getpty。
命令的控制tty设置为pty的从设备,其标准输入/输出/错误被重定向到从设备。
command
并且command_line
是给定String的完整命令。任何额外的arguments
将被传递给命令。
返回值
在非块形式中,这将返回一个大小为3的数组[r, w, pid]
。
在块形式中,这些相同的值将被赋予块:
r
包含命令的标准输出和标准错误的可读IO
w
一个可写的IO,是命令的标准输入
pid
该命令的进程标识符。
static VALUE
pty_getpty(int argc, VALUE *argv, VALUE self)
{
VALUE res;
struct pty_info info;
rb_io_t *wfptr,*rfptr;
VALUE rport = rb_obj_alloc(rb_cFile
VALUE wport = rb_obj_alloc(rb_cFile
char SlaveName[DEVICELEN];
MakeOpenFile(rport, rfptr
MakeOpenFile(wport, wfptr
establishShell(argc, argv, &info, SlaveName
rfptr->mode = rb_io_modestr_fmode("r"
rfptr->fd = info.fd;
rfptr->pathv = rb_obj_freeze(rb_str_new_cstr(SlaveName)
wfptr->mode = rb_io_modestr_fmode("w") | FMODE_SYNC;
wfptr->fd = rb_cloexec_dup(info.fd
if (wfptr->fd == -1)
rb_sys_fail("dup()"
rb_update_max_fd(wfptr->fd
wfptr->pathv = rfptr->pathv;
res = rb_ary_new2(3
rb_ary_store(res,0,(VALUE)rport
rb_ary_store(res,1,(VALUE)wport
rb_ary_store(res,2,PIDT2NUM(info.child_pid)
if (rb_block_given_p()) {
rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info
return Qnil;
}
return res;
}