Ruby 2.4

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

检查由指定的子进程的状态pidnil如果进程仍然存在,则返回。

如果进程不存在,并且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; }