In Files

  • pty/pty.c

Namespace

Class/Module Index [+]

Quicksearch

PTY

Creates and managed pseudo terminals (PTYs). See also en.wikipedia.org/wiki/Pseudo_terminal

Public Class Methods

check(pid, raise = false) => Process::Status or nil click to toggle source
check(pid, true) => nil or raises PTY::ChildExited

Checks the status of the child process specified by pid. Returns nil if the process is still alive. If the process is not alive, will return a Process::Status or raise a PTY::ChildExited (if raise was true).

pid

The process id of the process to check

raise

If true and the process identified by pid is no longer alive a PTY::ChildExited is raised.

Returns nil or a Process::Status when raise is false.

 
               static VALUE
pty_check(int argc, VALUE *argv, VALUE self)
{
    VALUE pid, exc;
    pid_t cpid;
    int status;

    rb_scan_args(argc, argv, "11", &pid, &exc);
    cpid = rb_waitpid(NUM2PIDT(pid), &status, WNOHANG|WUNTRACED);
    if (cpid == -1 || cpid == 0) return Qnil;

    if (!RTEST(exc)) return rb_last_status_get();
    raise_from_check(cpid, status);
    return Qnil;                /* not reached */
}
            
getpty(command_line) { |r, w, pid| ... } click to toggle source
getpty(command_line) => [r, w, pid]
getpty(command, args, ...) { |r, w, pid| ... }
getpty(command, args, ...) => [r, w, pid]

Spawns the specified command on a newly allocated pty.

The command’s controlling tty is set to the slave device of the pty and its standard input/output/error is redirected to the slave device.

command_line

The full command line to run

command

The command to run, as a String.

args

Zero or more arguments, as Strings, representing the arguments to command

In the non-block form this returns an array of size three, [r, w, pid]. In the block form the block will be called with these as arguments, |r,w,pid|:

r

An IO that can be read from that contains the command’s standard output and standard error

w

An IO that can be written to that is the command’s standard input

pid

The process identifier for the command.

 
               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_mode_flags("r");
    rfptr->fd = info.fd;
    rfptr->pathv = rb_obj_freeze(rb_str_new_cstr(SlaveName));

    wfptr->mode = rb_io_mode_flags("w") | FMODE_SYNC;
    wfptr->fd = 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] click to toggle source
open {|master_io, slave_file| ... } => block value

Allocates a pty (pseudo-terminal).

In the non-block form, returns a two element array, [master_io, slave_file].

In the block form, yields two arguments master_io, slave_file and the value of the block is returned from open.

The IO and File are both closed after the block completes if they haven’t been already closed.

The arguments in both forms are:

master_io

the master of the pty, as an IO.

slave_file

the slave of the pty, as a File. The path to the terminal device is available via slave_file.path

Example

PTY.open {|m, s|
  p m      #=> #<IO:masterpty:/dev/pts/1>
  p s      #=> #<File:/dev/pts/1>
  p s.path #=> "/dev/pts/1"
}

# Change the buffering type in factor command,
# assuming that factor uses stdio for stdout buffering.
# If IO.pipe is used instead of PTY.open,
# this code deadlocks because factor's stdout is fully buffered.
require 'io/console' # for IO#raw!
m, s = PTY.open
s.raw! # disable newline conversion.
r, w = IO.pipe
pid = spawn("factor", :in=>r, :out=>s)
r.close
s.close
w.puts "42"
p m.gets #=> "42: 2 3 7\n"
w.puts "144"
p m.gets #=> "144: 2 2 2 2 3 3\n"
w.close
# The result of read operation when pty slave is closed is platform
# dependent.
ret = begin
        m.gets          # FreeBSD returns nil.
      rescue Errno::EIO # GNU/Linux raises EIO.
        nil
      end
p ret #=> nil
 
               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| ... } click to toggle source
spawn(command_line) => [r, w, pid]
spawn(command, args, ...) { |r, w, pid| ... }
spawn(command, args, ...) => [r, w, pid]

Spawns the specified command on a newly allocated pty.

The command’s controlling tty is set to the slave device of the pty and its standard input/output/error is redirected to the slave device.

command_line

The full command line to run

command

The command to run, as a String.

args

Zero or more arguments, as Strings, representing the arguments to command

In the non-block form this returns an array of size three, [r, w, pid]. In the block form the block will be called with these as arguments, |r,w,pid|:

r

An IO that can be read from that contains the command’s standard output and standard error

w

An IO that can be written to that is the command’s standard input

pid

The process identifier for the command.

 
               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_mode_flags("r");
    rfptr->fd = info.fd;
    rfptr->pathv = rb_obj_freeze(rb_str_new_cstr(SlaveName));

    wfptr->mode = rb_io_mode_flags("w") | FMODE_SYNC;
    wfptr->fd = 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;
}
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus