Spec-Zone.ru › Ruby 3.2

модуль PTY

Создаёт и управляет псевдотерминалами (PTY). См. также ru.wikipedia.org/wiki/Псевдотерминал

PTY позволяет вам выделять новые терминалы, используя ::open или ::spawn новый терминал со специфической командой.

Пример

В этом примере мы изменим тип буферизации в команде factor, предполагая, что фактор использует stdio для буферизации stdout.

Если IO.pipe используется вместо PTY.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

Лицензия

© Авторское право 1998 года Акинори Ито.

Этот программный продукт может быть свободно перераспределён для этой цели, полностью или частично, при условии, что данное уведомление об авторских правах включено во все копии данного программного обеспечения и приложений, а также производных от него работ.

Данный программный продукт предоставляется «как есть», без каких-либо гарантий, явных или подразумеваемых, касательно любых вопросов, включая, но не ограничиваясь, гарантиями пригодности для определённой цели или коммерческой пригодности, или результатами, полученными от использования данного программного обеспечения.

Методы публичного класса

check(pid, raise = false) → Process::Status or nil Показать исходный код
check(pid, true) → nil or raises 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_RETURN(Qnil);
}

Проверяет статус дочернего процесса, указанного pid. Возвращает nil если процесс всё ещё активен.

Если процесс не активен, и raise было true, будет вызвано исключение PTY::ChildExited. В противном случае он вернёт экземпляр Process::Status.

pid

Идентификатор процесса для проверки

raise

Если true и процесс, идентифицированный как pid, больше не активен, будет вызвано исключение PTY::ChildExited.

spawn([env,] command_line) { |r, w, pid| ... } Показать исходный код
spawn([env,] command_line) → [r, w, pid]
spawn([env,] command, arguments, ...) { |r, w, pid| ... }
spawn([env,] command, arguments, ...) → [r, w, 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;
}

Запускает указанную команду в новом выделенном pty. Вы также можете использовать псевдоним ::getpty.

Контролирующий tty команды устанавливается на раб-устройство pty, а её стандартный ввод/вывод/ошибки перенаправляются на раб-устройство.

env — необязательный хэш, предоставляющий дополнительные переменные окружения для запущенного pty.

# sets FOO to "bar"
PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "bar\r\n"
# unsets FOO
PTY.spawn({"FOO"=>nil}, "printenv", "FOO") { |r,w,pid| p r.read } #=> ""

command и command_line — полные команды для запуска, основанные на String. Любые дополнительные arguments будут переданы команде.

Возвращаемые значения

В режиме без блока возвращается массив из трёх элементов, [r, w, pid].

В блочном режиме эти же значения будут переданы блоку:

r

Чтимый IO содержащий стандартный вывод и стандартную ошибку команды

w

Пишущий IO представляющий стандартный ввод команды

pid

Идентификатор процесса для команды.

open → [master_io, slave_file] Показать исходный код
open {|(master_io, slave_file)| ... } → block value
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;
}

Выделяет pty (псевдотерминал).

В блочном режиме, передаёт массив из двух элементов (master_io, slave_file) и возвращает значение блока из open.

И IO, и File закрываются после выполнения блока, если они не были закрыты ранее.

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

мастер pty как IO.

slave_file

раб pty как File. Путь к устройству терминала доступен через slave_file.path

IO#raw! используется для отключения преобразования символов перевода строки:

require 'io/console'
PTY.open {|m, s|
  s.raw!
  # ...
}
spawn([env,] command_line) { |r, w, pid| ... } Показать исходный код
spawn([env,] command_line) → [r, w, pid]
spawn([env,] command, arguments, ...) { |r, w, pid| ... }
spawn([env,] command, arguments, ...) → [r, w, 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;
}

Запускает указанную команду в новом выделенном pty. Вы также можете использовать псевдоним ::getpty.

Контролирующий tty команды устанавливается на раб-устройство pty, а её стандартный ввод/вывод/ошибки перенаправляются на раб-устройство.

env — необязательный хэш, предоставляющий дополнительные переменные окружения для запущенного pty.

# sets FOO to "bar"
PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "bar\r\n"
# unsets FOO
PTY.spawn({"FOO"=>nil}, "printenv", "FOO") { |r,w,pid| p r.read } #=> ""

command и command_line — полные команды для запуска, основанные на String. Любые дополнительные arguments будут переданы команде.

Возвращаемые значения

В режиме без блока возвращается массив из трёх элементов, [r, w, pid].

В блочном режиме эти же значения будут переданы блоку:

r

Чтимый IO содержащий стандартный вывод и стандартную ошибку команды

w

Пишущий IO представляющий стандартный ввод команды

pid

Идентификатор процесса для команды.

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API