File Coverage

blib/lib/IO/Pty.pm
Criterion Covered Total %
statement 48 93 51.6
branch 9 58 15.5
condition 1 2 50.0
subroutine 8 10 80.0
pod 5 5 100.0
total 71 168 42.2


line stmt bran cond sub pod time code
1             # Documentation at the __END__
2              
3             package IO::Pty;
4              
5 4     4   279876 use strict;
  4         41  
  4         133  
6 4     4   20 use Carp;
  4         8  
  4         239  
7 4     4   2463 use IO::Tty qw(TIOCSCTTY TCSETCTTY TIOCNOTTY);
  4         15  
  4         19  
8 4     4   31 use IO::File;
  4         9  
  4         502  
9             require POSIX;
10              
11 4     4   25 use vars qw(@ISA $VERSION);
  4         8  
  4         4291  
12              
13             $VERSION = '1.15'; # keep same as in Tty.pm
14              
15             @ISA = qw(IO::Handle);
16             eval { local $^W = 0; undef local $SIG{__DIE__}; require IO::Stty };
17             push @ISA, "IO::Stty" if (not $@); # if IO::Stty is installed
18              
19             sub new {
20 6   50 6 1 2737927 my ($class) = $_[0] || "IO::Pty";
21 6 50       71 $class = ref($class) if ref($class);
22 6 50       72 @_ <= 1 or croak 'usage: new $class';
23              
24 6         5024 my ($ptyfd, $ttyfd, $ttyname) = pty_allocate();
25              
26 6 50       52 croak "Cannot open a pty" if not defined $ptyfd;
27              
28 6         310 my $pty = $class->SUPER::new_from_fd($ptyfd, "r+");
29 6 50       1454 croak "Cannot create a new $class from fd $ptyfd: $!" if not $pty;
30 6         183 $pty->autoflush(1);
31 6         560 bless $pty => $class;
32              
33 6         163 my $slave = IO::Tty->new_from_fd($ttyfd, "r+");
34 6 50       513 croak "Cannot create a new IO::Tty from fd $ttyfd: $!" if not $slave;
35 6         65 $slave->autoflush(1);
36              
37 6         240 ${*$pty}{'io_pty_slave'} = $slave;
  6         57  
38 6         17 ${*$pty}{'io_pty_ttyname'} = $ttyname;
  6         32  
39 6         18 ${*$slave}{'io_tty_ttyname'} = $ttyname;
  6         32  
40              
41 6         44 return $pty;
42             }
43              
44             sub ttyname {
45 0 0   0 1 0 @_ == 1 or croak 'usage: $pty->ttyname();';
46 0         0 my $pty = shift;
47 0         0 ${*$pty}{'io_pty_ttyname'};
  0         0  
48             }
49              
50              
51             sub close_slave {
52 3 50   3 1 2374 @_ == 1 or croak 'usage: $pty->close_slave();';
53              
54 3         42 my $master = shift;
55              
56 3 50       24 if (exists ${*$master}{'io_pty_slave'}) {
  3         147  
57 3         35 close ${*$master}{'io_pty_slave'};
  3         79  
58 3         46 delete ${*$master}{'io_pty_slave'};
  3         176  
59             }
60             }
61              
62             sub slave {
63 2 50   2 1 872 @_ == 1 or croak 'usage: $pty->slave();';
64              
65 2         25 my $master = shift;
66              
67 2 50       19 if (exists ${*$master}{'io_pty_slave'}) {
  2         58  
68 2         25 return ${*$master}{'io_pty_slave'};
  2         44  
69             }
70              
71 0           my $tty = ${*$master}{'io_pty_ttyname'};
  0            
72              
73 0           my $slave = new IO::Tty;
74              
75 0 0         $slave->open($tty, O_RDWR | O_NOCTTY) ||
76             croak "Cannot open slave $tty: $!";
77              
78 0           return $slave;
79             }
80              
81             sub make_slave_controlling_terminal {
82 0 0   0 1   @_ == 1 or croak 'usage: $pty->make_slave_controlling_terminal();';
83              
84 0           my $self = shift;
85 0           local(*DEVTTY);
86              
87             # loose controlling terminal explicitly
88 0 0         if (defined TIOCNOTTY) {
89 0 0         if (open (\*DEVTTY, "/dev/tty")) {
90 0           ioctl( \*DEVTTY, TIOCNOTTY, 0 );
91 0           close \*DEVTTY;
92             }
93             }
94              
95             # Create a new 'session', lose controlling terminal.
96 0 0         if (POSIX::setsid() == -1) {
97 0 0         warn "setsid() failed, strange behavior may result: $!\r\n" if $^W;
98             }
99              
100 0 0         if (open(\*DEVTTY, "/dev/tty")) {
101 0 0         warn "Could not disconnect from controlling terminal?!\n" if $^W;
102 0           close \*DEVTTY;
103             }
104              
105             # now open slave, this should set it as controlling tty on some systems
106 0           my $ttyname = ${*$self}{'io_pty_ttyname'};
  0            
107 0           my $slv = new IO::Tty;
108 0 0         $slv->open($ttyname, O_RDWR)
109             or croak "Cannot open slave $ttyname: $!";
110              
111 0 0         if (not exists ${*$self}{'io_pty_slave'}) {
  0            
112 0           ${*$self}{'io_pty_slave'} = $slv;
  0            
113             } else {
114 0           $slv->close;
115             }
116              
117             # Acquire a controlling terminal if this doesn't happen automatically
118 0 0         if (not open(\*DEVTTY, "/dev/tty")) {
119 0 0         if (defined TIOCSCTTY) {
    0          
120 0 0         if (not defined ioctl( ${*$self}{'io_pty_slave'}, TIOCSCTTY, 0 )) {
  0            
121 0 0         warn "warning: TIOCSCTTY failed, slave might not be set as controlling terminal: $!" if $^W;
122             }
123             } elsif (defined TCSETCTTY) {
124 0 0         if (not defined ioctl( ${*$self}{'io_pty_slave'}, TCSETCTTY, 0 )) {
  0            
125 0 0         warn "warning: TCSETCTTY failed, slave might not be set as controlling terminal: $!" if $^W;
126             }
127             } else {
128 0 0         warn "warning: You have neither TIOCSCTTY nor TCSETCTTY on your system\n" if $^W;
129 0           return 0;
130             }
131             }
132              
133 0 0         if (not open(\*DEVTTY, "/dev/tty")) {
134 0           warn "Error: could not connect pty as controlling terminal!\n";
135 0           return undef;
136             } else {
137 0           close \*DEVTTY;
138             }
139            
140 0           return 1;
141             }
142              
143             *clone_winsize_from = \&IO::Tty::clone_winsize_from;
144             *get_winsize = \&IO::Tty::get_winsize;
145             *set_winsize = \&IO::Tty::set_winsize;
146             *set_raw = \&IO::Tty::set_raw;
147              
148             1;
149              
150             __END__