| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package IO::Pty::Easy; |
|
2
|
|
|
|
|
|
|
BEGIN { |
|
3
|
14
|
|
|
14
|
|
416635
|
$IO::Pty::Easy::AUTHORITY = 'cpan:DOY'; |
|
4
|
|
|
|
|
|
|
} |
|
5
|
|
|
|
|
|
|
{ |
|
6
|
|
|
|
|
|
|
$IO::Pty::Easy::VERSION = '0.09'; |
|
7
|
|
|
|
|
|
|
} |
|
8
|
14
|
|
|
14
|
|
130
|
use warnings; |
|
|
14
|
|
|
|
|
828
|
|
|
|
14
|
|
|
|
|
452
|
|
|
9
|
14
|
|
|
14
|
|
85
|
use strict; |
|
|
14
|
|
|
|
|
37
|
|
|
|
14
|
|
|
|
|
569
|
|
|
10
|
|
|
|
|
|
|
# ABSTRACT: Easy interface to IO::Pty |
|
11
|
|
|
|
|
|
|
|
|
12
|
14
|
|
|
14
|
|
85
|
use Carp; |
|
|
14
|
|
|
|
|
44
|
|
|
|
14
|
|
|
|
|
1729
|
|
|
13
|
14
|
|
|
14
|
|
16263
|
use POSIX (); |
|
|
14
|
|
|
|
|
121531
|
|
|
|
14
|
|
|
|
|
530
|
|
|
14
|
14
|
|
|
14
|
|
132
|
use Scalar::Util qw(weaken); |
|
|
14
|
|
|
|
|
27
|
|
|
|
14
|
|
|
|
|
1744
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
14
|
|
|
14
|
|
86
|
use base 'IO::Pty'; |
|
|
14
|
|
|
|
|
27
|
|
|
|
14
|
|
|
|
|
14845
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub new { |
|
21
|
16
|
|
|
16
|
1
|
237
|
my $class = shift; |
|
22
|
16
|
|
|
|
|
66
|
my %args = @_; |
|
23
|
|
|
|
|
|
|
|
|
24
|
16
|
|
|
|
|
51
|
my $handle_pty_size = 1; |
|
25
|
16
|
50
|
|
|
|
96
|
$handle_pty_size = delete $args{handle_pty_size} |
|
26
|
|
|
|
|
|
|
if exists $args{handle_pty_size}; |
|
27
|
16
|
50
|
|
|
|
451
|
$handle_pty_size = 0 unless POSIX::isatty(*STDIN); |
|
28
|
16
|
|
|
|
|
4389
|
my $def_max_read_chars = 8192; |
|
29
|
16
|
50
|
|
|
|
113
|
$def_max_read_chars = delete $args{def_max_read_chars} |
|
30
|
|
|
|
|
|
|
if exists $args{def_max_read_chars}; |
|
31
|
16
|
|
|
|
|
32
|
my $raw = 1; |
|
32
|
16
|
50
|
|
|
|
71
|
$raw = delete $args{raw} |
|
33
|
|
|
|
|
|
|
if exists $args{raw}; |
|
34
|
|
|
|
|
|
|
|
|
35
|
16
|
|
|
|
|
200
|
my $self = $class->SUPER::new(%args); |
|
36
|
16
|
|
|
|
|
24088
|
bless $self, $class; |
|
37
|
16
|
|
|
|
|
89
|
$self->handle_pty_size($handle_pty_size); |
|
38
|
16
|
|
|
|
|
72
|
$self->def_max_read_chars($def_max_read_chars); |
|
39
|
16
|
|
|
|
|
36
|
${*{$self}}{io_pty_easy_raw} = $raw; |
|
|
16
|
|
|
|
|
25
|
|
|
|
16
|
|
|
|
|
57
|
|
|
40
|
16
|
|
|
|
|
32
|
${*{$self}}{io_pty_easy_final_output} = ''; |
|
|
16
|
|
|
|
|
33
|
|
|
|
16
|
|
|
|
|
62
|
|
|
41
|
16
|
|
|
|
|
388
|
${*{$self}}{io_pty_easy_did_handle_pty_size} = 0; |
|
|
16
|
|
|
|
|
39
|
|
|
|
16
|
|
|
|
|
66
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
16
|
|
|
|
|
74
|
return $self; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub spawn { |
|
48
|
20
|
|
|
20
|
1
|
27655
|
my $self = shift; |
|
49
|
20
|
|
|
|
|
233
|
my $slave = $self->slave; |
|
50
|
|
|
|
|
|
|
|
|
51
|
20
|
50
|
|
|
|
2150
|
croak "Attempt to spawn a subprocess when one is already running" |
|
52
|
|
|
|
|
|
|
if $self->is_active; |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# set up a pipe to use for keeping track of the child process during exec |
|
55
|
20
|
|
|
|
|
53
|
my ($readp, $writep); |
|
56
|
20
|
50
|
|
|
|
722
|
unless (pipe($readp, $writep)) { |
|
57
|
0
|
|
|
|
|
0
|
croak "Failed to create a pipe"; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
20
|
|
|
|
|
200
|
$writep->autoflush(1); |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# fork a child process |
|
62
|
|
|
|
|
|
|
# if the exec fails, signal the parent by sending the errno across the pipe |
|
63
|
|
|
|
|
|
|
# if the exec succeeds, perl will close the pipe, and the sysread will |
|
64
|
|
|
|
|
|
|
# return due to EOF |
|
65
|
20
|
|
|
|
|
62593
|
${*{$self}}{io_pty_easy_pid} = fork; |
|
|
20
|
|
|
|
|
638
|
|
|
|
20
|
|
|
|
|
1980
|
|
|
66
|
20
|
100
|
|
|
|
1104
|
unless ($self->pid) { |
|
67
|
8
|
|
|
|
|
475
|
close $readp; |
|
68
|
8
|
|
|
|
|
940
|
$self->make_slave_controlling_terminal; |
|
69
|
8
|
|
|
|
|
9439
|
close $self; |
|
70
|
8
|
50
|
|
|
|
2003
|
$slave->clone_winsize_from(\*STDIN) if $self->handle_pty_size; |
|
71
|
8
|
50
|
|
|
|
101
|
$slave->set_raw if ${*{$self}}{io_pty_easy_raw}; |
|
|
8
|
|
|
|
|
57
|
|
|
|
8
|
|
|
|
|
312
|
|
|
72
|
|
|
|
|
|
|
# reopen the standard file descriptors in the child to point to the |
|
73
|
|
|
|
|
|
|
# pty rather than wherever they have been pointing during the script's |
|
74
|
|
|
|
|
|
|
# execution |
|
75
|
8
|
50
|
|
|
|
4300
|
open(STDIN, '<&', $slave->fileno) |
|
76
|
|
|
|
|
|
|
or carp "Couldn't reopen STDIN for reading"; |
|
77
|
8
|
50
|
|
|
|
1075
|
open(STDOUT, '>&', $slave->fileno) |
|
78
|
|
|
|
|
|
|
or carp "Couldn't reopen STDOUT for writing"; |
|
79
|
8
|
50
|
|
|
|
9213
|
open(STDERR, '>&', $slave->fileno) |
|
80
|
|
|
|
|
|
|
or carp "Couldn't reopen STDERR for writing"; |
|
81
|
8
|
|
|
|
|
434
|
close $slave; |
|
82
|
8
|
|
|
|
|
53
|
{ exec(@_) }; |
|
|
8
|
|
|
|
|
0
|
|
|
83
|
0
|
|
|
|
|
0
|
print $writep $! + 0; |
|
84
|
0
|
|
|
|
|
0
|
carp "Cannot exec(@_): $!"; |
|
85
|
0
|
|
|
|
|
0
|
exit 1; |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
12
|
|
|
|
|
459
|
close $writep; |
|
89
|
12
|
|
|
|
|
922
|
$self->close_slave; |
|
90
|
|
|
|
|
|
|
# this sysread will block until either we get an EOF from the other end of |
|
91
|
|
|
|
|
|
|
# the pipe being closed due to the exec, or until the child process sends |
|
92
|
|
|
|
|
|
|
# us the errno of the exec call after it fails |
|
93
|
12
|
|
|
|
|
505
|
my $errno; |
|
94
|
12
|
|
|
|
|
6394956
|
my $read_bytes = sysread($readp, $errno, 256); |
|
95
|
12
|
50
|
|
|
|
446
|
unless (defined $read_bytes) { |
|
96
|
|
|
|
|
|
|
# XXX: should alarm here and follow up with SIGKILL if the process |
|
97
|
|
|
|
|
|
|
# refuses to die |
|
98
|
0
|
|
|
|
|
0
|
kill TERM => $self->pid; |
|
99
|
0
|
|
|
|
|
0
|
close $readp; |
|
100
|
0
|
|
|
|
|
0
|
$self->_wait_for_inactive; |
|
101
|
0
|
|
|
|
|
0
|
croak "Cannot sync with child: $!"; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
12
|
|
|
|
|
410
|
close $readp; |
|
104
|
12
|
100
|
|
|
|
109
|
if ($read_bytes > 0) { |
|
105
|
1
|
|
|
|
|
11
|
$errno = $errno + 0; |
|
106
|
1
|
|
|
|
|
8
|
$self->_wait_for_inactive; |
|
107
|
1
|
|
|
|
|
467
|
croak "Cannot exec(@_): $errno"; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
11
|
50
|
|
|
|
143
|
if ($self->handle_pty_size) { |
|
111
|
0
|
|
|
|
|
0
|
my $weakself = weaken($self); |
|
112
|
|
|
|
|
|
|
$SIG{WINCH} = sub { |
|
113
|
0
|
0
|
|
0
|
|
0
|
return unless $weakself; |
|
114
|
0
|
|
|
|
|
0
|
$weakself->slave->clone_winsize_from(\*STDIN); |
|
115
|
0
|
0
|
|
|
|
0
|
kill WINCH => $weakself->pid if $weakself->is_active; |
|
116
|
0
|
|
|
|
|
0
|
}; |
|
117
|
0
|
|
|
|
|
0
|
${*{$self}}{io_pty_easy_did_handle_pty_size} = 1; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub read { |
|
123
|
7
|
|
|
7
|
1
|
51
|
my $self = shift; |
|
124
|
7
|
|
|
|
|
423
|
my ($timeout, $max_chars) = @_; |
|
125
|
7
|
|
33
|
|
|
98
|
$max_chars ||= $self->def_max_read_chars; |
|
126
|
|
|
|
|
|
|
|
|
127
|
7
|
|
|
|
|
29
|
my $rin = ''; |
|
128
|
7
|
|
|
|
|
52
|
vec($rin, fileno($self), 1) = 1; |
|
129
|
7
|
|
|
|
|
336107
|
my $nfound = select($rin, undef, undef, $timeout); |
|
130
|
7
|
|
|
|
|
308
|
my $buf; |
|
131
|
7
|
100
|
|
|
|
74
|
if ($nfound > 0) { |
|
132
|
4
|
|
|
|
|
120
|
my $nchars = sysread($self, $buf, $max_chars); |
|
133
|
4
|
50
|
33
|
|
|
98
|
$buf = '' if defined($nchars) && $nchars == 0; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
7
|
50
|
|
|
|
24
|
if (length(${*{$self}}{io_pty_easy_final_output}) > 0) { |
|
|
7
|
|
|
|
|
17
|
|
|
|
7
|
|
|
|
|
205
|
|
|
136
|
14
|
|
|
14
|
|
397412
|
no warnings 'uninitialized'; |
|
|
14
|
|
|
|
|
35
|
|
|
|
14
|
|
|
|
|
12359
|
|
|
137
|
0
|
|
|
|
|
0
|
$buf = ${*{$self}}{io_pty_easy_final_output} . $buf; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
138
|
0
|
|
|
|
|
0
|
${*{$self}}{io_pty_easy_final_output} = ''; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
139
|
|
|
|
|
|
|
} |
|
140
|
7
|
|
|
|
|
784
|
return $buf; |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub write { |
|
145
|
8
|
|
|
8
|
1
|
120
|
my $self = shift; |
|
146
|
8
|
|
|
|
|
57
|
my ($text, $timeout) = @_; |
|
147
|
|
|
|
|
|
|
|
|
148
|
8
|
|
|
|
|
59
|
my $win = ''; |
|
149
|
8
|
|
|
|
|
81
|
vec($win, fileno($self), 1) = 1; |
|
150
|
8
|
|
|
|
|
200509
|
my $nfound = select(undef, $win, undef, $timeout); |
|
151
|
8
|
|
|
|
|
35
|
my $nchars; |
|
152
|
8
|
100
|
|
|
|
68
|
if ($nfound > 0) { |
|
153
|
6
|
|
|
|
|
3996384
|
$nchars = syswrite($self, $text); |
|
154
|
|
|
|
|
|
|
} |
|
155
|
8
|
|
|
|
|
162
|
return $nchars; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub is_active { |
|
160
|
87
|
|
|
87
|
1
|
1762
|
my $self = shift; |
|
161
|
|
|
|
|
|
|
|
|
162
|
87
|
100
|
|
|
|
301
|
return 0 unless defined $self->pid; |
|
163
|
|
|
|
|
|
|
|
|
164
|
39
|
100
|
|
|
|
256
|
if (defined(my $fd = fileno($self))) { |
|
165
|
|
|
|
|
|
|
# XXX FreeBSD 7.0 will not allow a session leader to exit until the |
|
166
|
|
|
|
|
|
|
# kernel tty output buffer is empty. Make it so. |
|
167
|
30
|
|
|
|
|
88
|
my $rin = ''; |
|
168
|
30
|
|
|
|
|
201
|
vec($rin, $fd, 1) = 1; |
|
169
|
30
|
|
|
|
|
414
|
my $nfound = select($rin, undef, undef, 0); |
|
170
|
30
|
100
|
|
|
|
158
|
if ($nfound > 0) { |
|
171
|
10
|
|
|
|
|
27
|
sysread($self, ${*{$self}}{io_pty_easy_final_output}, |
|
|
10
|
|
|
|
|
132
|
|
|
|
10
|
|
|
|
|
368
|
|
|
172
|
|
|
|
|
|
|
$self->def_max_read_chars, |
|
173
|
10
|
|
|
|
|
33
|
length ${*{$self}}{io_pty_easy_final_output}); |
|
|
10
|
|
|
|
|
20
|
|
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
39
|
|
|
|
|
190
|
my $active = kill 0 => $self->pid; |
|
178
|
39
|
50
|
|
|
|
223
|
if ($active) { |
|
179
|
39
|
|
|
|
|
306
|
my $pid = waitpid($self->pid, POSIX::WNOHANG()); |
|
180
|
39
|
100
|
|
|
|
154
|
$active = 0 if $pid == $self->pid; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
39
|
100
|
|
|
|
154
|
if (!$active) { |
|
183
|
12
|
|
|
|
|
97
|
$SIG{WINCH} = 'DEFAULT' |
|
184
|
12
|
50
|
|
|
|
33
|
if ${*{$self}}{io_pty_easy_did_handle_pty_size}; |
|
|
12
|
|
|
|
|
24
|
|
|
185
|
12
|
|
|
|
|
61
|
${*{$self}}{io_pty_easy_did_handle_pty_size} = 0; |
|
|
12
|
|
|
|
|
30
|
|
|
|
12
|
|
|
|
|
42
|
|
|
186
|
12
|
|
|
|
|
33
|
delete ${*{$self}}{io_pty_easy_pid}; |
|
|
12
|
|
|
|
|
79
|
|
|
|
12
|
|
|
|
|
68
|
|
|
187
|
|
|
|
|
|
|
} |
|
188
|
39
|
|
|
|
|
122459
|
return $active; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub kill { |
|
193
|
25
|
|
|
25
|
1
|
14652
|
my $self = shift; |
|
194
|
25
|
|
|
|
|
74
|
my ($sig, $non_blocking) = @_; |
|
195
|
25
|
100
|
|
|
|
215
|
$sig = "TERM" unless defined $sig; |
|
196
|
|
|
|
|
|
|
|
|
197
|
25
|
|
|
|
|
44
|
my $kills; |
|
198
|
25
|
100
|
|
|
|
130
|
$kills = kill $sig => $self->pid if $self->is_active; |
|
199
|
25
|
100
|
|
|
|
199
|
$self->_wait_for_inactive unless $non_blocking; |
|
200
|
|
|
|
|
|
|
|
|
201
|
25
|
|
|
|
|
1091
|
return $kills; |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub close { |
|
206
|
15
|
|
|
15
|
1
|
29988
|
my $self = shift; |
|
207
|
|
|
|
|
|
|
|
|
208
|
15
|
|
|
|
|
773
|
close $self; |
|
209
|
15
|
|
|
|
|
82
|
$self->kill; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub handle_pty_size { |
|
214
|
35
|
|
|
35
|
1
|
363
|
my $self = shift; |
|
215
|
35
|
100
|
|
|
|
178
|
${*{$self}}{io_pty_easy_handle_pty_size} = $_[0] if @_; |
|
|
16
|
|
|
|
|
33
|
|
|
|
16
|
|
|
|
|
63
|
|
|
216
|
35
|
|
|
|
|
94
|
${*{$self}}{io_pty_easy_handle_pty_size}; |
|
|
35
|
|
|
|
|
68
|
|
|
|
35
|
|
|
|
|
1588
|
|
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub def_max_read_chars { |
|
221
|
33
|
|
|
33
|
1
|
73
|
my $self = shift; |
|
222
|
33
|
100
|
|
|
|
145
|
${*{$self}}{io_pty_easy_def_max_read_chars} = $_[0] if @_; |
|
|
16
|
|
|
|
|
31
|
|
|
|
16
|
|
|
|
|
67
|
|
|
223
|
33
|
|
|
|
|
76
|
${*{$self}}{io_pty_easy_def_max_read_chars}; |
|
|
33
|
|
|
|
|
45
|
|
|
|
33
|
|
|
|
|
151
|
|
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub pid { |
|
228
|
237
|
|
|
237
|
1
|
566
|
my $self = shift; |
|
229
|
237
|
|
|
|
|
320
|
${*{$self}}{io_pty_easy_pid}; |
|
|
237
|
|
|
|
|
313
|
|
|
|
237
|
|
|
|
|
2947
|
|
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub _wait_for_inactive { |
|
233
|
24
|
|
|
24
|
|
48
|
my $self = shift; |
|
234
|
|
|
|
|
|
|
|
|
235
|
24
|
|
|
|
|
103
|
select(undef, undef, undef, 0.01) while $self->is_active; |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub DESTROY { |
|
239
|
8
|
|
|
8
|
|
7338
|
my $self = shift; |
|
240
|
8
|
|
|
|
|
27
|
local $@; |
|
241
|
8
|
|
|
|
|
63
|
local $?; |
|
242
|
8
|
|
|
|
|
50
|
$self->close; |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
1; |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
__END__ |