Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more
Creates and managed pseudo terminals (PTYs). See also en.wikipedia.org/wiki/Pseudo_terminal
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 */ }
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; }
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
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; }
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; }