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__ |