Module: PTY
- Defined in:
- pty.c
Defined Under Namespace
Classes: ChildExited
Class Method Summary collapse
-
.check ⇒ Object
Checks the status of the child process specified by
pid
. -
.getpty ⇒ Object
Spawns the specified command on a newly allocated pty.
-
.open ⇒ Object
Allocates a pty (pseudo-terminal).
-
.spawn ⇒ Object
Spawns the specified command on a newly allocated pty.
Class Method Details
.check(pid, raise = false) ⇒ Process::Status? .check(pid, true) ⇒ nil, 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 aPTY::ChildExited
is raised.
Returns nil or a Process::Status
when raise
is false.
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
# File 'pty.c', line 652
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 */
}
|
.spawn(command_line) {|r, w, pid| ... } ⇒ Object .spawn(command_line) ⇒ Array .spawn(command, args, ...) {|r, w, pid| ... } ⇒ Object .spawn(command, args, ...) ⇒ Array .getpty(command_line) {|r, w, pid| ... } ⇒ Object .getpty(command_line) ⇒ Array .getpty(command, args, ...) {|r, w, pid| ... } ⇒ Object .getpty(command, args, ...) ⇒ Array
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.
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
# File 'pty.c', line 570
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 ⇒ Array .open {|master_io, slave_file| ... } ⇒ Object
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
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'pty.c', line 502
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| ... } ⇒ Object .spawn(command_line) ⇒ Array .spawn(command, args, ...) {|r, w, pid| ... } ⇒ Object .spawn(command, args, ...) ⇒ Array .getpty(command_line) {|r, w, pid| ... } ⇒ Object .getpty(command_line) ⇒ Array .getpty(command, args, ...) {|r, w, pid| ... } ⇒ Object .getpty(command, args, ...) ⇒ Array
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.
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
# File 'pty.c', line 570
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;
}
|