首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

PTY

PTY允许您使用:: open或::使用特定命令产生新终端来分配新终端。

在这个例子中,我们将更改factor命令中的缓冲类型,假定该因子使用stdio进行标准输出缓冲。

如果使用IO.pipe而不是:: open,则此代码会因为因子的stdout被完全缓冲而死锁。

代码语言:javascript
复制
# 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

代码语言:javascript
复制
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。

代码语言:javascript
复制
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

该命令的进程标识符。

代码语言:javascript
复制
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块和文件将在块完成后关闭。

代码语言:javascript
复制
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]

代码语言:javascript
复制
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! 可用于禁用换行符:

代码语言:javascript
复制
require 'io/console'
PTY.open {|m, s|
  s.raw!
  ...
}
代码语言:javascript
复制
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

该命令的进程标识符。

代码语言:javascript
复制
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;
}

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com