line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Documentation at the __END__ |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package IO::Pty; |
4
|
|
|
|
|
|
|
|
5
|
4
|
|
|
4
|
|
285838
|
use strict; |
|
4
|
|
|
|
|
38
|
|
|
4
|
|
|
|
|
121
|
|
6
|
4
|
|
|
4
|
|
23
|
use Carp; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
233
|
|
7
|
4
|
|
|
4
|
|
1772
|
use IO::Tty qw(TIOCSCTTY TCSETCTTY TIOCNOTTY); |
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
17
|
|
8
|
4
|
|
|
4
|
|
32
|
use IO::File; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
532
|
|
9
|
|
|
|
|
|
|
require POSIX; |
10
|
|
|
|
|
|
|
|
11
|
4
|
|
|
4
|
|
28
|
use vars qw(@ISA $VERSION); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
4156
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
$VERSION = '1.16'; # 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
|
2776017
|
my ($class) = $_[0] || "IO::Pty"; |
21
|
6
|
50
|
|
|
|
171
|
$class = ref($class) if ref($class); |
22
|
6
|
50
|
|
|
|
77
|
@_ <= 1 or croak 'usage: new $class'; |
23
|
|
|
|
|
|
|
|
24
|
6
|
|
|
|
|
6829
|
my ( $ptyfd, $ttyfd, $ttyname ) = pty_allocate(); |
25
|
|
|
|
|
|
|
|
26
|
6
|
50
|
|
|
|
129
|
croak "Cannot open a pty" if not defined $ptyfd; |
27
|
|
|
|
|
|
|
|
28
|
6
|
|
|
|
|
360
|
my $pty = $class->SUPER::new_from_fd( $ptyfd, "r+" ); |
29
|
6
|
50
|
|
|
|
2061
|
croak "Cannot create a new $class from fd $ptyfd: $!" if not $pty; |
30
|
6
|
|
|
|
|
252
|
$pty->autoflush(1); |
31
|
6
|
|
|
|
|
780
|
bless $pty => $class; |
32
|
|
|
|
|
|
|
|
33
|
6
|
|
|
|
|
158
|
my $slave = IO::Tty->new_from_fd( $ttyfd, "r+" ); |
34
|
6
|
50
|
|
|
|
642
|
croak "Cannot create a new IO::Tty from fd $ttyfd: $!" if not $slave; |
35
|
6
|
|
|
|
|
124
|
$slave->autoflush(1); |
36
|
|
|
|
|
|
|
|
37
|
6
|
|
|
|
|
388
|
${*$pty}{'io_pty_slave'} = $slave; |
|
6
|
|
|
|
|
98
|
|
38
|
6
|
|
|
|
|
43
|
${*$pty}{'io_pty_ttyname'} = $ttyname; |
|
6
|
|
|
|
|
53
|
|
39
|
6
|
|
|
|
|
17
|
${*$slave}{'io_tty_ttyname'} = $ttyname; |
|
6
|
|
|
|
|
125
|
|
40
|
|
|
|
|
|
|
|
41
|
6
|
|
|
|
|
45
|
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
|
|
|
|
|
|
|
sub close_slave { |
51
|
3
|
50
|
|
3
|
1
|
3144
|
@_ == 1 or croak 'usage: $pty->close_slave();'; |
52
|
|
|
|
|
|
|
|
53
|
3
|
|
|
|
|
32
|
my $master = shift; |
54
|
|
|
|
|
|
|
|
55
|
3
|
50
|
|
|
|
21
|
if ( exists ${*$master}{'io_pty_slave'} ) { |
|
3
|
|
|
|
|
148
|
|
56
|
3
|
|
|
|
|
39
|
close ${*$master}{'io_pty_slave'}; |
|
3
|
|
|
|
|
85
|
|
57
|
3
|
|
|
|
|
49
|
delete ${*$master}{'io_pty_slave'}; |
|
3
|
|
|
|
|
196
|
|
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub slave { |
62
|
2
|
50
|
|
2
|
1
|
898
|
@_ == 1 or croak 'usage: $pty->slave();'; |
63
|
|
|
|
|
|
|
|
64
|
2
|
|
|
|
|
27
|
my $master = shift; |
65
|
|
|
|
|
|
|
|
66
|
2
|
50
|
|
|
|
15
|
if ( exists ${*$master}{'io_pty_slave'} ) { |
|
2
|
|
|
|
|
85
|
|
67
|
2
|
|
|
|
|
12
|
return ${*$master}{'io_pty_slave'}; |
|
2
|
|
|
|
|
48
|
|
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
0
|
|
|
|
|
|
my $tty = ${*$master}{'io_pty_ttyname'}; |
|
0
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
my $slave = new IO::Tty; |
73
|
|
|
|
|
|
|
|
74
|
0
|
0
|
|
|
|
|
$slave->open( $tty, O_RDWR | O_NOCTTY ) |
75
|
|
|
|
|
|
|
|| croak "Cannot open slave $tty: $!"; |
76
|
|
|
|
|
|
|
|
77
|
0
|
|
|
|
|
|
return $slave; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub make_slave_controlling_terminal { |
81
|
0
|
0
|
|
0
|
1
|
|
@_ == 1 or croak 'usage: $pty->make_slave_controlling_terminal();'; |
82
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
my $self = shift; |
84
|
0
|
|
|
|
|
|
local (*DEVTTY); |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# loose controlling terminal explicitly |
87
|
0
|
0
|
|
|
|
|
if ( defined TIOCNOTTY ) { |
88
|
0
|
0
|
|
|
|
|
if ( open( \*DEVTTY, "/dev/tty" ) ) { |
89
|
0
|
|
|
|
|
|
ioctl( \*DEVTTY, TIOCNOTTY, 0 ); |
90
|
0
|
|
|
|
|
|
close \*DEVTTY; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Create a new 'session', lose controlling terminal. |
95
|
0
|
0
|
|
|
|
|
if ( POSIX::setsid() == -1 ) { |
96
|
0
|
0
|
|
|
|
|
warn "setsid() failed, strange behavior may result: $!\r\n" if $^W; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
if ( open( \*DEVTTY, "/dev/tty" ) ) { |
100
|
0
|
0
|
|
|
|
|
warn "Could not disconnect from controlling terminal?!\n" if $^W; |
101
|
0
|
|
|
|
|
|
close \*DEVTTY; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# now open slave, this should set it as controlling tty on some systems |
105
|
0
|
|
|
|
|
|
my $ttyname = ${*$self}{'io_pty_ttyname'}; |
|
0
|
|
|
|
|
|
|
106
|
0
|
|
|
|
|
|
my $slv = new IO::Tty; |
107
|
0
|
0
|
|
|
|
|
$slv->open( $ttyname, O_RDWR ) |
108
|
|
|
|
|
|
|
or croak "Cannot open slave $ttyname: $!"; |
109
|
|
|
|
|
|
|
|
110
|
0
|
0
|
|
|
|
|
if ( not exists ${*$self}{'io_pty_slave'} ) { |
|
0
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
${*$self}{'io_pty_slave'} = $slv; |
|
0
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
} |
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
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
elsif ( defined TCSETCTTY ) { |
125
|
0
|
0
|
|
|
|
|
if ( not defined ioctl( ${*$self}{'io_pty_slave'}, TCSETCTTY, 0 ) ) { |
|
0
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
|
warn "warning: TCSETCTTY failed, slave might not be set as controlling terminal: $!" if $^W; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
else { |
130
|
0
|
0
|
|
|
|
|
warn "warning: You have neither TIOCSCTTY nor TCSETCTTY on your system\n" if $^W; |
131
|
0
|
|
|
|
|
|
return 0; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
0
|
0
|
|
|
|
|
if ( not open( \*DEVTTY, "/dev/tty" ) ) { |
136
|
0
|
|
|
|
|
|
warn "Error: could not connect pty as controlling terminal!\n"; |
137
|
0
|
|
|
|
|
|
return undef; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
else { |
140
|
0
|
|
|
|
|
|
close \*DEVTTY; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
return 1; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
*clone_winsize_from = \&IO::Tty::clone_winsize_from; |
147
|
|
|
|
|
|
|
*get_winsize = \&IO::Tty::get_winsize; |
148
|
|
|
|
|
|
|
*set_winsize = \&IO::Tty::set_winsize; |
149
|
|
|
|
|
|
|
*set_raw = \&IO::Tty::set_raw; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
1; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
__END__ |