| Current File : //usr/tmp/par-6c6566/cache-9ab9fe47781b3f807c8b3ee838b58c73318324f4/inc/lib/IO/Pty.pm |
#line 1 "IO/Pty.pm"
# Documentation at the __END__
package IO::Pty;
use strict;
use Carp;
use IO::Tty qw(TIOCSCTTY TCSETCTTY TIOCNOTTY);
use IO::File;
require POSIX;
use vars qw(@ISA $VERSION);
$VERSION = '1.12'; # keep same as in Tty.pm
@ISA = qw(IO::Handle);
eval { local $^W = 0; undef local $SIG{__DIE__}; require IO::Stty };
push @ISA, "IO::Stty" if (not $@); # if IO::Stty is installed
sub new {
my ($class) = $_[0] || "IO::Pty";
$class = ref($class) if ref($class);
@_ <= 1 or croak 'usage: new $class';
my ($ptyfd, $ttyfd, $ttyname) = pty_allocate();
croak "Cannot open a pty" if not defined $ptyfd;
my $pty = $class->SUPER::new_from_fd($ptyfd, "r+");
croak "Cannot create a new $class from fd $ptyfd: $!" if not $pty;
$pty->autoflush(1);
bless $pty => $class;
my $slave = IO::Tty->new_from_fd($ttyfd, "r+");
croak "Cannot create a new IO::Tty from fd $ttyfd: $!" if not $slave;
$slave->autoflush(1);
${*$pty}{'io_pty_slave'} = $slave;
${*$pty}{'io_pty_ttyname'} = $ttyname;
${*$slave}{'io_tty_ttyname'} = $ttyname;
return $pty;
}
sub ttyname {
@_ == 1 or croak 'usage: $pty->ttyname();';
my $pty = shift;
${*$pty}{'io_pty_ttyname'};
}
sub close_slave {
@_ == 1 or croak 'usage: $pty->close_slave();';
my $master = shift;
if (exists ${*$master}{'io_pty_slave'}) {
close ${*$master}{'io_pty_slave'};
delete ${*$master}{'io_pty_slave'};
}
}
sub slave {
@_ == 1 or croak 'usage: $pty->slave();';
my $master = shift;
if (exists ${*$master}{'io_pty_slave'}) {
return ${*$master}{'io_pty_slave'};
}
my $tty = ${*$master}{'io_pty_ttyname'};
my $slave = new IO::Tty;
$slave->open($tty, O_RDWR | O_NOCTTY) ||
croak "Cannot open slave $tty: $!";
return $slave;
}
sub make_slave_controlling_terminal {
@_ == 1 or croak 'usage: $pty->make_slave_controlling_terminal();';
my $self = shift;
local(*DEVTTY);
# loose controlling terminal explicitly
if (defined TIOCNOTTY) {
if (open (\*DEVTTY, "/dev/tty")) {
ioctl( \*DEVTTY, TIOCNOTTY, 0 );
close \*DEVTTY;
}
}
# Create a new 'session', lose controlling terminal.
if (not POSIX::setsid()) {
warn "setsid() failed, strange behavior may result: $!\r\n" if $^W;
}
if (open(\*DEVTTY, "/dev/tty")) {
warn "Could not disconnect from controlling terminal?!\n" if $^W;
close \*DEVTTY;
}
# now open slave, this should set it as controlling tty on some systems
my $ttyname = ${*$self}{'io_pty_ttyname'};
my $slv = new IO::Tty;
$slv->open($ttyname, O_RDWR)
or croak "Cannot open slave $ttyname: $!";
if (not exists ${*$self}{'io_pty_slave'}) {
${*$self}{'io_pty_slave'} = $slv;
} else {
$slv->close;
}
# Acquire a controlling terminal if this doesn't happen automatically
if (not open(\*DEVTTY, "/dev/tty")) {
if (defined TIOCSCTTY) {
if (not defined ioctl( ${*$self}{'io_pty_slave'}, TIOCSCTTY, 0 )) {
warn "warning: TIOCSCTTY failed, slave might not be set as controlling terminal: $!" if $^W;
}
} elsif (defined TCSETCTTY) {
if (not defined ioctl( ${*$self}{'io_pty_slave'}, TCSETCTTY, 0 )) {
warn "warning: TCSETCTTY failed, slave might not be set as controlling terminal: $!" if $^W;
}
} else {
warn "warning: You have neither TIOCSCTTY nor TCSETCTTY on your system\n" if $^W;
return 0;
}
}
if (not open(\*DEVTTY, "/dev/tty")) {
warn "Error: could not connect pty as controlling terminal!\n";
return undef;
} else {
close \*DEVTTY;
}
return 1;
}
*clone_winsize_from = \&IO::Tty::clone_winsize_from;
*get_winsize = \&IO::Tty::get_winsize;
*set_winsize = \&IO::Tty::set_winsize;
*set_raw = \&IO::Tty::set_raw;
1;
__END__
#line 339