line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# You may distribute under the terms of either the GNU General Public License |
2
|
|
|
|
|
|
|
# or the Artistic License (the same terms as Perl itself) |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# (C) Paul Evans, 2006-2012,2016 -- leonerd@leonerd.org.uk |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package IPC::PerlSSH; |
7
|
|
|
|
|
|
|
|
8
|
12
|
|
|
12
|
|
262788
|
use strict; |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
359
|
|
9
|
12
|
|
|
12
|
|
48
|
use warnings; |
|
12
|
|
|
|
|
16
|
|
|
12
|
|
|
|
|
353
|
|
10
|
|
|
|
|
|
|
|
11
|
12
|
|
|
12
|
|
47
|
use base qw( IPC::PerlSSH::Base ); |
|
12
|
|
|
|
|
18
|
|
|
12
|
|
|
|
|
5175
|
|
12
|
|
|
|
|
|
|
|
13
|
12
|
|
|
12
|
|
5495
|
use IPC::Open2; |
|
12
|
|
|
|
|
46774
|
|
|
12
|
|
|
|
|
671
|
|
14
|
|
|
|
|
|
|
|
15
|
12
|
|
|
12
|
|
153
|
use Carp; |
|
12
|
|
|
|
|
17
|
|
|
12
|
|
|
|
|
11582
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '0.17'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
our $READLEN = 256*1024; # 256KiB |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 NAME |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
C - execute remote perl code over an SSH link |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 SYNOPSIS |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
use IPC::PerlSSH; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
my $ips = IPC::PerlSSH->new( Host => "over.there" ); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
$ips->eval( "use POSIX qw( uname )" ); |
32
|
|
|
|
|
|
|
my @remote_uname = $ips->eval( "uname()" ); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# We can pass arguments |
35
|
|
|
|
|
|
|
$ips->eval( 'open FILE, ">", $_[0]; print FILE $_[1]; close FILE;', |
36
|
|
|
|
|
|
|
"foo.txt", "Hello, world!" ); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# We can pre-compile stored procedures |
39
|
|
|
|
|
|
|
$ips->store( "get_file", 'local $/; |
40
|
|
|
|
|
|
|
open FILE, "<", $_[0]; |
41
|
|
|
|
|
|
|
$_ = ; |
42
|
|
|
|
|
|
|
close FILE; |
43
|
|
|
|
|
|
|
return $_;' ); |
44
|
|
|
|
|
|
|
foreach my $file ( @files ) { |
45
|
|
|
|
|
|
|
my $content = $ips->call( "get_file", $file ); |
46
|
|
|
|
|
|
|
... |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# We can use existing libraries for remote stored procedures |
50
|
|
|
|
|
|
|
$ips->use_library( "FS", qw( readfile ) ); |
51
|
|
|
|
|
|
|
foreach my $file ( @files ) { |
52
|
|
|
|
|
|
|
my $content = $ips->call( "readfile", $file ); |
53
|
|
|
|
|
|
|
... |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head1 DESCRIPTION |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
This module provides an object class that provides a mechanism to execute perl |
59
|
|
|
|
|
|
|
code in a remote instance of perl running on another host, communicated via an |
60
|
|
|
|
|
|
|
SSH link or similar connection. Where it differs from most other IPC modules |
61
|
|
|
|
|
|
|
is that no special software is required on the remote end, other than the |
62
|
|
|
|
|
|
|
ability to run perl. In particular, it is not required that the |
63
|
|
|
|
|
|
|
C module is installed there. Nor are any special administrative |
64
|
|
|
|
|
|
|
rights required; any account that has shell access and can execute the perl |
65
|
|
|
|
|
|
|
binary on the remote host can use this module. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head2 Argument Passing |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
The arguments to, and return values from, remote code are always transferred |
70
|
|
|
|
|
|
|
as lists of strings. This has the following effects on various types of |
71
|
|
|
|
|
|
|
values: |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=over 8 |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item * |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
String values are passed as they stand. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item * |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Booleans and integers will become stringified, but will work as expected once |
82
|
|
|
|
|
|
|
they reach the other side of the connection. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=item * |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Floating-point numbers will get converted to a decimal notation, which may |
87
|
|
|
|
|
|
|
lose precision. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=item * |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
A single array of strings, or a single hash of string values, can be passed |
92
|
|
|
|
|
|
|
by-value as a list, possibly after positional arguments: |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
$ips->store( 'foo', 'my ( $arg, @list ) = @_; ...' ); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
$ips->store( 'bar', 'my %opts = @_; ...' ); |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item * |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
No reference value, including IO handles, can be passed; instead it will be |
101
|
|
|
|
|
|
|
stringified. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=back |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
To pass or return a more complex structure, consider using a module such as |
106
|
|
|
|
|
|
|
L, which can serialise the structure into a plain string, to be |
107
|
|
|
|
|
|
|
deserialised on the remote end. Be aware however, that C was only |
108
|
|
|
|
|
|
|
added to core in perl 5.7.3, so if the remote perl is older, it may not be |
109
|
|
|
|
|
|
|
available. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
To work with remote IO handles, see the L module. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=cut |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 CONSTRUCTORS |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=cut |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head2 new (with Host) |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
$ips = IPC::PerlSSH->new( Host => $host, ... ) |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Returns a new instance of a C object connected to the specified |
124
|
|
|
|
|
|
|
host. The following arguments can be specified: |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=over 8 |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item Host => STRING |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Connect to a named host. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=item Port => INT |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Optionally specify a non-default port. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item Perl => STRING |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Optionally pass in the path to the perl binary in the remote host. |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item User => STRING |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Optionally pass in an alternative username |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=item SshPath => STRING |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Optionally specify a different path to the F binary |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item SshOptions => ARRAY |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Optionally specify any other options to pass to the F binary, in an |
151
|
|
|
|
|
|
|
C reference |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=back |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head2 new (with Command) |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
$ips = IPC::PerlSSH->new( Command => \@command, ... ) |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Returns a new instance of a C object which uses the STDIN/STDOUT |
160
|
|
|
|
|
|
|
streams of a command it executes, as the streams to communicate with the |
161
|
|
|
|
|
|
|
remote F. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=over 8 |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=item Command => ARRAY |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Specifies the command to execute |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=item Command => STRING |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Shorthand form for executing a single simple path |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=back |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
The C key can be used to create an C running perl |
176
|
|
|
|
|
|
|
directly on the local machine, for example; so that the "remote" perl is in |
177
|
|
|
|
|
|
|
fact running locally, but still in its own process. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
my $ips = IPC::PerlSSH->new( Command => $^X ); |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 new (with Readh + Writeh) |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
$ips = IPC::PerlSSH->new( Readh => $rd, Writeh => $wr ) |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Returns a new instance of a C object using a given pair of |
186
|
|
|
|
|
|
|
filehandles to read from and write to the remote F process. It is |
187
|
|
|
|
|
|
|
allowable for both filehandles to be the same - for example using a socket. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head2 new (with Readfunc + Writefunc) |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
$ips = IPC::PerlSSH->new( Readfunc => \&read, Writefunc => \&write ) |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Returns a new instance of a C object using a given pair of |
194
|
|
|
|
|
|
|
functions as read and write operators. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
Usually this form won't be used in practice; it largely exists to assist the |
197
|
|
|
|
|
|
|
test scripts. But since it works, it is included in the interface in case the |
198
|
|
|
|
|
|
|
earlier alternatives are not suitable. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
The functions are called as |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
$len = $Readfunc->( my $buffer, $maxlen ); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
$len = $Writewrite->( $buffer ); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
In each case, the returned value should be the number of bytes read or |
207
|
|
|
|
|
|
|
written. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=cut |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub new |
212
|
|
|
|
|
|
|
{ |
213
|
12
|
|
|
12
|
1
|
2886
|
my $class = shift; |
214
|
12
|
|
|
|
|
45
|
my %opts = @_; |
215
|
|
|
|
|
|
|
|
216
|
12
|
|
|
|
|
59
|
my $self = bless { |
217
|
|
|
|
|
|
|
readbuff => "", |
218
|
|
|
|
|
|
|
stored => {}, |
219
|
|
|
|
|
|
|
}, $class; |
220
|
|
|
|
|
|
|
|
221
|
12
|
|
|
|
|
37
|
my ( $readfunc, $writefunc ) = ( delete $opts{Readfunc}, delete $opts{Writefunc} ); |
222
|
|
|
|
|
|
|
|
223
|
12
|
|
|
|
|
21
|
my $pid = delete $opts{Pid}; |
224
|
|
|
|
|
|
|
|
225
|
12
|
100
|
66
|
|
|
77
|
if( !defined $readfunc || !defined $writefunc ) { |
226
|
11
|
|
|
|
|
26
|
my ( $readh, $writeh ) = ( delete $opts{Readh}, delete $opts{Writeh} ); |
227
|
|
|
|
|
|
|
|
228
|
11
|
100
|
66
|
|
|
42
|
if( !defined $readh || !defined $writeh ) { |
229
|
10
|
|
|
|
|
94
|
my @command = $self->build_command_from( \%opts ); |
230
|
10
|
|
|
|
|
53
|
$pid = open2( $readh, $writeh, @command ); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
$readfunc = sub { |
234
|
73
|
|
|
73
|
|
97088
|
sysread( $readh, $_[0], $_[1] ); |
235
|
11
|
|
|
|
|
25633
|
}; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
$writefunc = sub { |
238
|
83
|
|
|
83
|
|
2544
|
syswrite( $writeh, $_[0] ); |
239
|
11
|
|
|
|
|
62
|
}; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
12
|
50
|
|
|
|
93
|
keys %opts and |
243
|
|
|
|
|
|
|
croak "Unexpected ->new keys - " . join ", ", sort keys %opts; |
244
|
|
|
|
|
|
|
|
245
|
12
|
|
|
|
|
155
|
$self->{pid} = $pid; |
246
|
12
|
|
|
|
|
35
|
$self->{readfunc} = $readfunc; |
247
|
12
|
|
|
|
|
279
|
$self->{writefunc} = $writefunc; |
248
|
|
|
|
|
|
|
|
249
|
12
|
|
|
|
|
133
|
$self->send_firmware; |
250
|
|
|
|
|
|
|
|
251
|
12
|
|
|
|
|
76
|
return $self; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub write |
255
|
|
|
|
|
|
|
{ |
256
|
89
|
|
|
89
|
0
|
112
|
my $self = shift; |
257
|
89
|
|
|
|
|
111
|
my ( $data ) = @_; |
258
|
|
|
|
|
|
|
|
259
|
89
|
|
|
|
|
222
|
$self->{writefunc}->( $data ); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub read_message |
263
|
|
|
|
|
|
|
{ |
264
|
77
|
|
|
77
|
0
|
102
|
my $self = shift; |
265
|
|
|
|
|
|
|
|
266
|
77
|
|
|
|
|
81
|
my ( $message, @args ); |
267
|
|
|
|
|
|
|
|
268
|
77
|
|
|
|
|
173
|
while( !defined $message ) { |
269
|
78
|
|
|
|
|
68
|
my $b; |
270
|
78
|
100
|
|
|
|
184
|
$self->{readfunc}->( $b, $READLEN ) or return ( "CLOSED" ); |
271
|
77
|
|
|
|
|
367
|
$self->{readbuff} .= $b; |
272
|
77
|
|
|
|
|
399
|
( $message, @args ) = $self->parse_message( $self->{readbuff} ); |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
76
|
|
|
|
|
1988
|
return ( $message, @args ); |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=head1 METHODS |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=cut |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head2 eval |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
@result = $ips->eval( $code, @args ) |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
This method evaluates code in the remote host, passing arguments and returning |
287
|
|
|
|
|
|
|
the result. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
The code should be passed in a string, and is evaluated using a string |
290
|
|
|
|
|
|
|
C in the remote host, in list context. If this method is called in |
291
|
|
|
|
|
|
|
scalar context, then only the first element of the returned list is returned. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
If the remote code threw an exception, then this function propagates it as a |
294
|
|
|
|
|
|
|
plain string. If the remote process exits before responding, this will be |
295
|
|
|
|
|
|
|
propagated as an exception. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=cut |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub eval |
300
|
|
|
|
|
|
|
{ |
301
|
18
|
|
|
18
|
1
|
15951
|
my $self = shift; |
302
|
18
|
|
|
|
|
534
|
my ( $code, @args ) = @_; |
303
|
|
|
|
|
|
|
|
304
|
18
|
|
|
|
|
188
|
$self->write_message( "EVAL", $code, @args ); |
305
|
|
|
|
|
|
|
|
306
|
18
|
|
|
|
|
80
|
my ( $ret, @retargs ) = $self->read_message; |
307
|
|
|
|
|
|
|
|
308
|
18
|
100
|
|
|
|
249
|
if( $ret eq "RETURNED" ) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# If the caller didn't want an array and we received more than one result |
310
|
|
|
|
|
|
|
# from the far end; we'll just have to throw it away... |
311
|
17
|
100
|
|
|
|
2174
|
return wantarray ? @retargs : $retargs[0]; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
elsif( $ret eq "DIED" ) { |
314
|
0
|
|
|
|
|
0
|
my ( $message ) = @retargs; |
315
|
0
|
0
|
|
|
|
0
|
if( $message =~ m/^While compiling code:.* at \(eval \d+\) line (\d+)/ ) { |
316
|
0
|
|
|
|
|
0
|
$message .= " ==> " . (split m/\n/, $code)[$1 - 1] . "\n"; |
317
|
|
|
|
|
|
|
} |
318
|
0
|
|
|
|
|
0
|
die "Remote host threw an exception:\n$message"; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
elsif( $ret eq "CLOSED" ) { |
321
|
1
|
|
|
|
|
18
|
die "Remote connection closed\n"; |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
else { |
324
|
0
|
|
|
|
|
0
|
die "Unknown return result $ret\n"; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=head2 store |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
$ips->store( $name, $code ) |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
$ips->store( %funcs ) |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
This method sends code to the remote host to store in named procedure(s) which |
335
|
|
|
|
|
|
|
can be executed later. The code should be passed in strings. |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
While the code is not executed, it will still be compiled into CODE references |
338
|
|
|
|
|
|
|
in the remote host. Any compile errors that occur will be throw as exceptions |
339
|
|
|
|
|
|
|
by this method. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
Multiple functions may be passed in a hash, to reduce the number of network |
342
|
|
|
|
|
|
|
roundtrips, which may help latency. |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
=cut |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub store |
347
|
|
|
|
|
|
|
{ |
348
|
7
|
|
|
7
|
1
|
2995
|
my $self = shift; |
349
|
7
|
|
|
|
|
26
|
my %funcs = @_; |
350
|
|
|
|
|
|
|
|
351
|
7
|
|
|
|
|
22
|
foreach my $name ( keys %funcs ) { |
352
|
7
|
100
|
|
|
|
22
|
$self->_has_stored_code( $name ) and croak "Already have a stored function called '$name'"; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
5
|
|
|
|
|
22
|
$self->write_message( "STORE", %funcs ); |
356
|
|
|
|
|
|
|
|
357
|
5
|
|
|
|
|
18
|
my ( $ret, @retargs ) = $self->read_message; |
358
|
|
|
|
|
|
|
|
359
|
5
|
50
|
|
|
|
22
|
if( $ret eq "OK" ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
360
|
5
|
|
|
|
|
30
|
$self->{stored}{$_} = 1 for keys %funcs; |
361
|
5
|
|
|
|
|
16
|
return; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
elsif( $ret eq "DIED" ) { |
364
|
0
|
|
|
|
|
0
|
my ( $message ) = @retargs; |
365
|
0
|
0
|
|
|
|
0
|
if( $message =~ m/^While compiling code for (\S+):.* at \(eval \d+\) line (\d+)/ ) { |
366
|
0
|
|
|
|
|
0
|
my $code = $funcs{$1}; |
367
|
0
|
|
|
|
|
0
|
$message .= " ==> " . (split m/\n/, $code)[$2 - 1] . "\n"; |
368
|
|
|
|
|
|
|
} |
369
|
0
|
|
|
|
|
0
|
die "Remote host threw an exception:\n$message"; |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
elsif( $ret eq "CLOSED" ) { |
372
|
0
|
|
|
|
|
0
|
die "Remote connection closed\n"; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
else { |
375
|
0
|
|
|
|
|
0
|
die "Unknown return result $ret\n"; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub _has_stored_code |
380
|
|
|
|
|
|
|
{ |
381
|
131
|
|
|
131
|
|
159
|
my $self = shift; |
382
|
131
|
|
|
|
|
121
|
my ( $name ) = @_; |
383
|
131
|
|
|
|
|
838
|
return exists $self->{stored}{$name}; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=head2 bind |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
$ips->bind( $name, $code ) |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
This method is identical to the C method, except that the remote |
391
|
|
|
|
|
|
|
function will be available as a plain function within the local perl |
392
|
|
|
|
|
|
|
program, as a function of the given name in the caller's package. |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=cut |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
sub bind |
397
|
|
|
|
|
|
|
{ |
398
|
2
|
|
|
2
|
1
|
863
|
my $self = shift; |
399
|
2
|
|
|
|
|
5
|
my ( $name, $code ) = @_; |
400
|
|
|
|
|
|
|
|
401
|
2
|
|
|
|
|
6
|
$self->store( $name, $code ); |
402
|
|
|
|
|
|
|
|
403
|
2
|
|
|
|
|
8
|
my $caller = (caller)[0]; |
404
|
|
|
|
|
|
|
{ |
405
|
12
|
|
|
12
|
|
77
|
no strict 'refs'; |
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
5264
|
|
|
2
|
|
|
|
|
5
|
|
406
|
2
|
|
|
2
|
|
15
|
*{$caller."::$name"} = sub { $self->call( $name, @_ ) }; |
|
2
|
|
|
|
|
20
|
|
|
2
|
|
|
|
|
12
|
|
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=head2 call |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
@result = $ips->call( $name, @args ) |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
This method invokes a remote method that has earlier been defined using the |
415
|
|
|
|
|
|
|
C or C methods. The arguments are passed and the result is |
416
|
|
|
|
|
|
|
returned in the same way as with the C method. |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
If an exception occurs during execution, it is propagated and thrown by this |
419
|
|
|
|
|
|
|
method. If the remote process exits before responding, this will be propagated |
420
|
|
|
|
|
|
|
as an exception. |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=cut |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
sub call |
425
|
|
|
|
|
|
|
{ |
426
|
48
|
|
|
48
|
1
|
69936
|
my $self = shift; |
427
|
48
|
|
|
|
|
136
|
my ( $name, @args ) = @_; |
428
|
|
|
|
|
|
|
|
429
|
48
|
50
|
|
|
|
118
|
$self->_has_stored_code( $name ) or croak "Do not have a stored function called '$name'"; |
430
|
|
|
|
|
|
|
|
431
|
48
|
|
|
|
|
175
|
$self->write_message( "CALL", $name, @args ); |
432
|
|
|
|
|
|
|
|
433
|
48
|
|
|
|
|
118
|
my ( $ret, @retargs ) = $self->read_message; |
434
|
|
|
|
|
|
|
|
435
|
48
|
50
|
|
|
|
109
|
if( $ret eq "RETURNED" ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# If the caller didn't want an array and we received more than one result |
437
|
|
|
|
|
|
|
# from the far end; we'll just have to throw it away... |
438
|
48
|
100
|
|
|
|
216
|
return wantarray ? @retargs : $retargs[0]; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
elsif( $ret eq "DIED" ) { |
441
|
0
|
|
|
|
|
0
|
die "Remote host threw an exception:\n$retargs[0]"; |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
elsif( $ret eq "CLOSED" ) { |
444
|
0
|
|
|
|
|
0
|
die "Remote connection closed\n"; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
else { |
447
|
0
|
|
|
|
|
0
|
die "Unknown return result $ret\n"; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=head2 use_library |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
$ips->use_library( $library, @funcs ) |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
This method loads a library of code from a module, and stores them to the |
456
|
|
|
|
|
|
|
remote perl by calling C on each one. The C<$library> name may be a |
457
|
|
|
|
|
|
|
full class name, or a name within the C space. |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
If the C<@funcs> list is non-empty, then only those named functions are stored |
460
|
|
|
|
|
|
|
(analogous to the C |
461
|
|
|
|
|
|
|
libraries that define many functions, only a few of which are actually used. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
For more information, see L. |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=cut |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
sub use_library |
468
|
|
|
|
|
|
|
{ |
469
|
9
|
|
|
9
|
1
|
1913
|
my $self = shift; |
470
|
|
|
|
|
|
|
|
471
|
9
|
|
|
|
|
51
|
my ( $package, $funcs ) = $self->load_library_pkg( @_ ); |
472
|
|
|
|
|
|
|
|
473
|
6
|
100
|
|
|
|
27
|
$self->{stored_pkg}{$package} and delete $funcs->{_init}; |
474
|
|
|
|
|
|
|
|
475
|
6
|
|
|
|
|
72
|
$self->write_message( "STOREPKG", $package, %$funcs ); |
476
|
|
|
|
|
|
|
|
477
|
6
|
|
|
|
|
24
|
my ( $ret, @retargs ) = $self->read_message; |
478
|
|
|
|
|
|
|
|
479
|
6
|
50
|
|
|
|
50
|
if( $ret eq "OK" ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
480
|
6
|
|
|
|
|
18
|
$self->{stored_pkg}{$package} = 1; |
481
|
6
|
|
|
|
|
80
|
$self->{stored}{$_} = 1 for keys %$funcs; |
482
|
6
|
|
|
|
|
33
|
return; |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
elsif( $ret eq "DIED" ) { |
485
|
0
|
|
|
|
|
0
|
die "Remote host threw an exception:\n$retargs[0]"; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
elsif( $ret eq "CLOSED" ) { |
488
|
0
|
|
|
|
|
0
|
die "Remote connection closed\n"; |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
else { |
491
|
0
|
|
|
|
|
0
|
die "Unknown return result $ret\n"; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
sub DESTROY |
496
|
|
|
|
|
|
|
{ |
497
|
10
|
|
|
10
|
|
6967
|
my $self = shift; |
498
|
|
|
|
|
|
|
|
499
|
10
|
|
|
|
|
161
|
undef $self->{readfunc}; |
500
|
10
|
|
|
|
|
967
|
undef $self->{writefunc}; |
501
|
|
|
|
|
|
|
# This will clean up the closures, and hence close the filehandles that are |
502
|
|
|
|
|
|
|
# referenced by them. The remote perl will then shut down, and we can wait |
503
|
|
|
|
|
|
|
# for the child process to exit |
504
|
|
|
|
|
|
|
|
505
|
10
|
100
|
|
|
|
3840
|
waitpid $self->{pid}, 0 if defined $self->{pid}; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
=head1 AUTHOR |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
Paul Evans |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=cut |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
0x55AA; |