line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Net::Cmd.pm |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Copyright (C) 1995-2006 Graham Barr. All rights reserved. |
4
|
|
|
|
|
|
|
# Copyright (C) 2013-2016, 2020 Steve Hay. All rights reserved. |
5
|
|
|
|
|
|
|
# This module is free software; you can redistribute it and/or modify it under |
6
|
|
|
|
|
|
|
# the same terms as Perl itself, i.e. under the terms of either the GNU General |
7
|
|
|
|
|
|
|
# Public License or the Artistic License, as specified in the F file. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Net::Cmd; |
10
|
|
|
|
|
|
|
|
11
|
17
|
|
|
17
|
|
89324
|
use 5.008001; |
|
17
|
|
|
|
|
73
|
|
12
|
|
|
|
|
|
|
|
13
|
17
|
|
|
17
|
|
89
|
use strict; |
|
17
|
|
|
|
|
37
|
|
|
17
|
|
|
|
|
488
|
|
14
|
17
|
|
|
17
|
|
107
|
use warnings; |
|
17
|
|
|
|
|
29
|
|
|
17
|
|
|
|
|
486
|
|
15
|
|
|
|
|
|
|
|
16
|
17
|
|
|
17
|
|
82
|
use Carp; |
|
17
|
|
|
|
|
35
|
|
|
17
|
|
|
|
|
900
|
|
17
|
17
|
|
|
17
|
|
101
|
use Exporter; |
|
17
|
|
|
|
|
29
|
|
|
17
|
|
|
|
|
661
|
|
18
|
17
|
|
|
17
|
|
626
|
use Symbol 'gensym'; |
|
17
|
|
|
|
|
845
|
|
|
17
|
|
|
|
|
1142
|
|
19
|
17
|
|
|
17
|
|
635
|
use Errno 'EINTR'; |
|
17
|
|
|
|
|
1510
|
|
|
17
|
|
|
|
|
2111
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
BEGIN { |
22
|
17
|
50
|
|
17
|
|
1293
|
if ($^O eq 'os390') { |
23
|
0
|
|
|
|
|
0
|
require Convert::EBCDIC; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Convert::EBCDIC->import; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our $VERSION = "3.13"; |
30
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
31
|
|
|
|
|
|
|
our @EXPORT = qw(CMD_INFO CMD_OK CMD_MORE CMD_REJECT CMD_ERROR CMD_PENDING); |
32
|
|
|
|
|
|
|
|
33
|
17
|
|
|
17
|
|
118
|
use constant CMD_INFO => 1; |
|
17
|
|
|
|
|
76
|
|
|
17
|
|
|
|
|
1433
|
|
34
|
17
|
|
|
17
|
|
109
|
use constant CMD_OK => 2; |
|
17
|
|
|
|
|
27
|
|
|
17
|
|
|
|
|
941
|
|
35
|
17
|
|
|
17
|
|
100
|
use constant CMD_MORE => 3; |
|
17
|
|
|
|
|
28
|
|
|
17
|
|
|
|
|
864
|
|
36
|
17
|
|
|
17
|
|
129
|
use constant CMD_REJECT => 4; |
|
17
|
|
|
|
|
31
|
|
|
17
|
|
|
|
|
911
|
|
37
|
17
|
|
|
17
|
|
125
|
use constant CMD_ERROR => 5; |
|
17
|
|
|
|
|
39
|
|
|
17
|
|
|
|
|
1036
|
|
38
|
17
|
|
|
17
|
|
99
|
use constant CMD_PENDING => 0; |
|
17
|
|
|
|
|
30
|
|
|
17
|
|
|
|
|
837
|
|
39
|
|
|
|
|
|
|
|
40
|
17
|
|
|
17
|
|
100
|
use constant DEF_REPLY_CODE => 421; |
|
17
|
|
|
|
|
29
|
|
|
17
|
|
|
|
|
6266
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my %debug = (); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $tr = $^O eq 'os390' ? Convert::EBCDIC->new() : undef; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub toebcdic { |
47
|
0
|
|
|
0
|
0
|
0
|
my $cmd = shift; |
48
|
|
|
|
|
|
|
|
49
|
0
|
0
|
|
|
|
0
|
unless (exists ${*$cmd}{'net_cmd_asciipeer'}) { |
|
0
|
|
|
|
|
0
|
|
50
|
0
|
|
|
|
|
0
|
my $string = $_[0]; |
51
|
0
|
|
|
|
|
0
|
my $ebcdicstr = $tr->toebcdic($string); |
52
|
0
|
|
0
|
|
|
0
|
${*$cmd}{'net_cmd_asciipeer'} = $string !~ /^\d+/ && $ebcdicstr =~ /^\d+/; |
|
0
|
|
|
|
|
0
|
|
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
0
|
0
|
|
|
|
0
|
${*$cmd}{'net_cmd_asciipeer'} |
|
0
|
|
|
|
|
0
|
|
56
|
|
|
|
|
|
|
? $tr->toebcdic($_[0]) |
57
|
|
|
|
|
|
|
: $_[0]; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub toascii { |
62
|
0
|
|
|
0
|
0
|
0
|
my $cmd = shift; |
63
|
0
|
0
|
|
|
|
0
|
${*$cmd}{'net_cmd_asciipeer'} |
|
0
|
|
|
|
|
0
|
|
64
|
|
|
|
|
|
|
? $tr->toascii($_[0]) |
65
|
|
|
|
|
|
|
: $_[0]; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub _print_isa { |
70
|
17
|
|
|
17
|
|
124
|
no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
17
|
|
|
|
|
29
|
|
|
17
|
|
|
|
|
61953
|
|
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
0
|
|
0
|
my $pkg = shift; |
73
|
0
|
|
|
|
|
0
|
my $cmd = $pkg; |
74
|
|
|
|
|
|
|
|
75
|
0
|
|
0
|
|
|
0
|
$debug{$pkg} ||= 0; |
76
|
|
|
|
|
|
|
|
77
|
0
|
|
|
|
|
0
|
my %done = (); |
78
|
0
|
|
|
|
|
0
|
my @do = ($pkg); |
79
|
0
|
|
|
|
|
0
|
my %spc = ($pkg, ""); |
80
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
0
|
while ($pkg = shift @do) { |
82
|
0
|
0
|
|
|
|
0
|
next if defined $done{$pkg}; |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
0
|
$done{$pkg} = 1; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
my $v = |
87
|
0
|
|
|
|
|
0
|
defined ${"${pkg}::VERSION"} |
88
|
0
|
0
|
|
|
|
0
|
? "(" . ${"${pkg}::VERSION"} . ")" |
|
0
|
|
|
|
|
0
|
|
89
|
|
|
|
|
|
|
: ""; |
90
|
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
0
|
my $spc = $spc{$pkg}; |
92
|
0
|
|
|
|
|
0
|
$cmd->debug_print(1, "${spc}${pkg}${v}\n"); |
93
|
|
|
|
|
|
|
|
94
|
0
|
0
|
|
|
|
0
|
if (@{"${pkg}::ISA"}) { |
|
0
|
|
|
|
|
0
|
|
95
|
0
|
|
|
|
|
0
|
@spc{@{"${pkg}::ISA"}} = (" " . $spc{$pkg}) x @{"${pkg}::ISA"}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
96
|
0
|
|
|
|
|
0
|
unshift(@do, @{"${pkg}::ISA"}); |
|
0
|
|
|
|
|
0
|
|
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub debug { |
103
|
98
|
50
|
66
|
98
|
1
|
500
|
@_ == 1 or @_ == 2 or croak 'usage: $obj->debug([$level])'; |
104
|
|
|
|
|
|
|
|
105
|
98
|
|
|
|
|
253
|
my ($cmd, $level) = @_; |
106
|
98
|
|
33
|
|
|
290
|
my $pkg = ref($cmd) || $cmd; |
107
|
98
|
|
|
|
|
193
|
my $oldval = 0; |
108
|
|
|
|
|
|
|
|
109
|
98
|
50
|
|
|
|
234
|
if (ref($cmd)) { |
110
|
98
|
|
50
|
|
|
154
|
$oldval = ${*$cmd}{'net_cmd_debug'} || 0; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
else { |
113
|
0
|
|
0
|
|
|
0
|
$oldval = $debug{$pkg} || 0; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
98
|
100
|
|
|
|
426
|
return $oldval |
117
|
|
|
|
|
|
|
unless @_ == 2; |
118
|
|
|
|
|
|
|
|
119
|
9
|
50
|
0
|
|
|
67
|
$level = $debug{$pkg} || 0 |
120
|
|
|
|
|
|
|
unless defined $level; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
_print_isa($pkg) |
123
|
9
|
50
|
33
|
|
|
48
|
if ($level && !exists $debug{$pkg}); |
124
|
|
|
|
|
|
|
|
125
|
9
|
50
|
|
|
|
38
|
if (ref($cmd)) { |
126
|
9
|
|
|
|
|
19
|
${*$cmd}{'net_cmd_debug'} = $level; |
|
9
|
|
|
|
|
81
|
|
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
else { |
129
|
0
|
|
|
|
|
0
|
$debug{$pkg} = $level; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
9
|
|
|
|
|
89
|
$oldval; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub message { |
137
|
16
|
50
|
|
16
|
1
|
98
|
@_ == 1 or croak 'usage: $obj->message()'; |
138
|
|
|
|
|
|
|
|
139
|
16
|
|
|
|
|
43
|
my $cmd = shift; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
wantarray |
142
|
10
|
|
|
|
|
31
|
? @{${*$cmd}{'net_cmd_resp'}} |
|
10
|
|
|
|
|
77
|
|
143
|
16
|
100
|
|
|
|
128
|
: join("", @{${*$cmd}{'net_cmd_resp'}}); |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
123
|
|
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
|
147
|
0
|
|
|
0
|
1
|
0
|
sub debug_text { $_[2] } |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub debug_print { |
151
|
0
|
|
|
0
|
1
|
0
|
my ($cmd, $out, $text) = @_; |
152
|
0
|
0
|
|
|
|
0
|
print STDERR $cmd, ($out ? '>>> ' : '<<< '), $cmd->debug_text($out, $text); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub code { |
157
|
6
|
50
|
|
6
|
1
|
24
|
@_ == 1 or croak 'usage: $obj->code()'; |
158
|
|
|
|
|
|
|
|
159
|
6
|
|
|
|
|
10
|
my $cmd = shift; |
160
|
|
|
|
|
|
|
|
161
|
0
|
|
|
|
|
0
|
${*$cmd}{'net_cmd_code'} = $cmd->DEF_REPLY_CODE |
162
|
6
|
50
|
|
|
|
15
|
unless exists ${*$cmd}{'net_cmd_code'}; |
|
6
|
|
|
|
|
22
|
|
163
|
|
|
|
|
|
|
|
164
|
6
|
|
|
|
|
11
|
${*$cmd}{'net_cmd_code'}; |
|
6
|
|
|
|
|
21
|
|
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub status { |
169
|
0
|
0
|
|
0
|
1
|
0
|
@_ == 1 or croak 'usage: $obj->status()'; |
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
0
|
my $cmd = shift; |
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
0
|
substr(${*$cmd}{'net_cmd_code'}, 0, 1); |
|
0
|
|
|
|
|
0
|
|
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub set_status { |
178
|
21
|
50
|
|
21
|
0
|
74
|
@_ == 3 or croak 'usage: $obj->set_status($code, $resp)'; |
179
|
|
|
|
|
|
|
|
180
|
21
|
|
|
|
|
43
|
my $cmd = shift; |
181
|
21
|
|
|
|
|
49
|
my ($code, $resp) = @_; |
182
|
|
|
|
|
|
|
|
183
|
21
|
50
|
|
|
|
142
|
$resp = defined $resp ? [$resp] : [] |
|
|
50
|
|
|
|
|
|
184
|
|
|
|
|
|
|
unless ref($resp); |
185
|
|
|
|
|
|
|
|
186
|
21
|
|
|
|
|
58
|
(${*$cmd}{'net_cmd_code'}, ${*$cmd}{'net_cmd_resp'}) = ($code, $resp); |
|
21
|
|
|
|
|
145
|
|
|
21
|
|
|
|
|
143
|
|
187
|
|
|
|
|
|
|
|
188
|
21
|
|
|
|
|
64
|
1; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub _syswrite_with_timeout { |
192
|
56
|
|
|
56
|
|
186
|
my $cmd = shift; |
193
|
56
|
|
|
|
|
133
|
my $line = shift; |
194
|
|
|
|
|
|
|
|
195
|
56
|
|
|
|
|
98
|
my $len = length($line); |
196
|
56
|
|
|
|
|
81
|
my $offset = 0; |
197
|
56
|
|
|
|
|
136
|
my $win = ""; |
198
|
56
|
|
|
|
|
234
|
vec($win, fileno($cmd), 1) = 1; |
199
|
56
|
|
100
|
|
|
584
|
my $timeout = $cmd->timeout || undef; |
200
|
56
|
|
|
|
|
490
|
my $initial = time; |
201
|
56
|
|
|
|
|
89
|
my $pending = $timeout; |
202
|
|
|
|
|
|
|
|
203
|
56
|
50
|
|
|
|
1611
|
local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS'; |
204
|
|
|
|
|
|
|
|
205
|
56
|
|
|
|
|
227
|
while ($len) { |
206
|
56
|
|
|
|
|
78
|
my $wout; |
207
|
56
|
|
|
|
|
531
|
my $nfound = select(undef, $wout = $win, undef, $pending); |
208
|
56
|
50
|
33
|
|
|
389
|
if ((defined $nfound and $nfound > 0) or -f $cmd) # -f for testing on win32 |
|
|
0
|
33
|
|
|
|
|
209
|
|
|
|
|
|
|
{ |
210
|
56
|
|
|
|
|
1396
|
my $w = syswrite($cmd, $line, $len, $offset); |
211
|
56
|
50
|
|
|
|
2502
|
if (! defined($w) ) { |
212
|
0
|
|
|
|
|
0
|
my $err = $!; |
213
|
0
|
|
|
|
|
0
|
$cmd->close; |
214
|
0
|
|
|
|
|
0
|
$cmd->_set_status_closed($err); |
215
|
0
|
|
|
|
|
0
|
return; |
216
|
|
|
|
|
|
|
} |
217
|
56
|
|
|
|
|
116
|
$len -= $w; |
218
|
56
|
|
|
|
|
175
|
$offset += $w; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
elsif ($nfound == -1) { |
221
|
0
|
0
|
|
|
|
0
|
if ( $! == EINTR ) { |
222
|
0
|
0
|
|
|
|
0
|
if ( defined($timeout) ) { |
223
|
0
|
0
|
|
|
|
0
|
redo if ($pending = $timeout - ( time - $initial ) ) > 0; |
224
|
0
|
|
|
|
|
0
|
$cmd->_set_status_timeout; |
225
|
0
|
|
|
|
|
0
|
return; |
226
|
|
|
|
|
|
|
} |
227
|
0
|
|
|
|
|
0
|
redo; |
228
|
|
|
|
|
|
|
} |
229
|
0
|
|
|
|
|
0
|
my $err = $!; |
230
|
0
|
|
|
|
|
0
|
$cmd->close; |
231
|
0
|
|
|
|
|
0
|
$cmd->_set_status_closed($err); |
232
|
0
|
|
|
|
|
0
|
return; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
else { |
235
|
0
|
|
|
|
|
0
|
$cmd->_set_status_timeout; |
236
|
0
|
|
|
|
|
0
|
return; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
56
|
|
|
|
|
1034
|
return 1; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub _set_status_timeout { |
244
|
0
|
|
|
0
|
|
0
|
my $cmd = shift; |
245
|
0
|
|
0
|
|
|
0
|
my $pkg = ref($cmd) || $cmd; |
246
|
|
|
|
|
|
|
|
247
|
0
|
|
|
|
|
0
|
$cmd->set_status($cmd->DEF_REPLY_CODE, "[$pkg] Timeout"); |
248
|
0
|
0
|
|
|
|
0
|
carp(ref($cmd) . ": " . (caller(1))[3] . "(): timeout") if $cmd->debug; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub _set_status_closed { |
252
|
0
|
|
|
0
|
|
0
|
my $cmd = shift; |
253
|
0
|
|
|
|
|
0
|
my $err = shift; |
254
|
0
|
|
0
|
|
|
0
|
my $pkg = ref($cmd) || $cmd; |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
0
|
$cmd->set_status($cmd->DEF_REPLY_CODE, "[$pkg] Connection closed"); |
257
|
0
|
0
|
|
|
|
0
|
carp(ref($cmd) . ": " . (caller(1))[3] |
258
|
|
|
|
|
|
|
. "(): unexpected EOF on command channel: $err") if $cmd->debug; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub _is_closed { |
262
|
65
|
|
|
65
|
|
122
|
my $cmd = shift; |
263
|
65
|
50
|
|
|
|
345
|
if (!defined fileno($cmd)) { |
264
|
0
|
|
|
|
|
0
|
$cmd->_set_status_closed($!); |
265
|
0
|
|
|
|
|
0
|
return 1; |
266
|
|
|
|
|
|
|
} |
267
|
65
|
|
|
|
|
545
|
return 0; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub command { |
271
|
19
|
|
|
19
|
1
|
59
|
my $cmd = shift; |
272
|
|
|
|
|
|
|
|
273
|
19
|
50
|
|
|
|
191
|
return $cmd |
274
|
|
|
|
|
|
|
if $cmd->_is_closed; |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
$cmd->dataend() |
277
|
19
|
50
|
|
|
|
52
|
if (exists ${*$cmd}{'net_cmd_last_ch'}); |
|
19
|
|
|
|
|
87
|
|
278
|
|
|
|
|
|
|
|
279
|
19
|
50
|
|
|
|
89
|
if (scalar(@_)) { |
280
|
|
|
|
|
|
|
my $str = join( |
281
|
|
|
|
|
|
|
" ", |
282
|
|
|
|
|
|
|
map { |
283
|
19
|
|
|
|
|
70
|
/\n/ |
284
|
26
|
50
|
|
|
|
464
|
? do { my $n = $_; $n =~ tr/\n/ /; $n } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
285
|
|
|
|
|
|
|
: $_; |
286
|
|
|
|
|
|
|
} @_ |
287
|
|
|
|
|
|
|
); |
288
|
19
|
50
|
|
|
|
98
|
$str = $cmd->toascii($str) if $tr; |
289
|
19
|
|
|
|
|
53
|
$str .= "\015\012"; |
290
|
|
|
|
|
|
|
|
291
|
19
|
50
|
|
|
|
77
|
$cmd->debug_print(1, $str) |
292
|
|
|
|
|
|
|
if ($cmd->debug); |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# though documented to return undef on failure, the legacy behavior |
295
|
|
|
|
|
|
|
# was to return $cmd even on failure, so this odd construct does that |
296
|
19
|
50
|
|
|
|
349
|
$cmd->_syswrite_with_timeout($str) |
297
|
|
|
|
|
|
|
or return $cmd; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
19
|
|
|
|
|
110
|
$cmd; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub ok { |
305
|
0
|
0
|
|
0
|
1
|
0
|
@_ == 1 or croak 'usage: $obj->ok()'; |
306
|
|
|
|
|
|
|
|
307
|
0
|
|
|
|
|
0
|
my $code = $_[0]->code; |
308
|
0
|
0
|
|
|
|
0
|
0 < $code && $code < 400; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub unsupported { |
313
|
0
|
|
|
0
|
1
|
0
|
my $cmd = shift; |
314
|
|
|
|
|
|
|
|
315
|
0
|
|
|
|
|
0
|
$cmd->set_status(580, 'Unsupported command'); |
316
|
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
0
|
0; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub getline { |
322
|
10
|
|
|
10
|
1
|
96
|
my $cmd = shift; |
323
|
|
|
|
|
|
|
|
324
|
10
|
|
100
|
|
|
31
|
${*$cmd}{'net_cmd_lines'} ||= []; |
|
10
|
|
|
|
|
224
|
|
325
|
|
|
|
|
|
|
|
326
|
2
|
|
|
|
|
15
|
return shift @{${*$cmd}{'net_cmd_lines'}} |
|
2
|
|
|
|
|
9
|
|
327
|
10
|
100
|
|
|
|
24
|
if scalar(@{${*$cmd}{'net_cmd_lines'}}); |
|
10
|
|
|
|
|
44
|
|
|
10
|
|
|
|
|
83
|
|
328
|
|
|
|
|
|
|
|
329
|
8
|
100
|
|
|
|
50
|
my $partial = defined(${*$cmd}{'net_cmd_partial'}) ? ${*$cmd}{'net_cmd_partial'} : ""; |
|
8
|
|
|
|
|
98
|
|
|
5
|
|
|
|
|
17
|
|
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
return |
332
|
8
|
50
|
|
|
|
162
|
if $cmd->_is_closed; |
333
|
|
|
|
|
|
|
|
334
|
8
|
|
|
|
|
68
|
my $fd = fileno($cmd); |
335
|
8
|
|
|
|
|
46
|
my $rin = ""; |
336
|
8
|
|
|
|
|
39
|
vec($rin, $fd, 1) = 1; |
337
|
|
|
|
|
|
|
|
338
|
8
|
|
|
|
|
39
|
my $buf; |
339
|
|
|
|
|
|
|
|
340
|
8
|
|
|
|
|
31
|
until (scalar(@{${*$cmd}{'net_cmd_lines'}})) { |
|
16
|
|
|
|
|
56
|
|
|
16
|
|
|
|
|
109
|
|
341
|
8
|
|
50
|
|
|
208
|
my $timeout = $cmd->timeout || undef; |
342
|
8
|
|
|
|
|
140
|
my $rout; |
343
|
|
|
|
|
|
|
|
344
|
8
|
|
|
|
|
502
|
my $select_ret = select($rout = $rin, undef, undef, $timeout); |
345
|
8
|
50
|
|
|
|
86
|
if ($select_ret > 0) { |
346
|
8
|
50
|
|
|
|
154
|
unless (sysread($cmd, $buf = "", 1024)) { |
347
|
0
|
|
|
|
|
0
|
my $err = $!; |
348
|
0
|
|
|
|
|
0
|
$cmd->close; |
349
|
0
|
|
|
|
|
0
|
$cmd->_set_status_closed($err); |
350
|
0
|
|
|
|
|
0
|
return; |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
|
353
|
8
|
|
|
|
|
45
|
substr($buf, 0, 0) = $partial; ## prepend from last sysread |
354
|
|
|
|
|
|
|
|
355
|
8
|
|
|
|
|
145
|
my @buf = split(/\015?\012/, $buf, -1); ## break into lines |
356
|
|
|
|
|
|
|
|
357
|
8
|
|
|
|
|
41
|
$partial = pop @buf; |
358
|
|
|
|
|
|
|
|
359
|
8
|
|
|
|
|
19
|
push(@{${*$cmd}{'net_cmd_lines'}}, map {"$_\n"} @buf); |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
66
|
|
|
10
|
|
|
|
|
58
|
|
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
else { |
363
|
0
|
|
|
|
|
0
|
$cmd->_set_status_timeout; |
364
|
0
|
|
|
|
|
0
|
return; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
8
|
|
|
|
|
26
|
${*$cmd}{'net_cmd_partial'} = $partial; |
|
8
|
|
|
|
|
105
|
|
369
|
|
|
|
|
|
|
|
370
|
8
|
50
|
|
|
|
50
|
if ($tr) { |
371
|
0
|
|
|
|
|
0
|
foreach my $ln (@{${*$cmd}{'net_cmd_lines'}}) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
372
|
0
|
|
|
|
|
0
|
$ln = $cmd->toebcdic($ln); |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
8
|
|
|
|
|
39
|
shift @{${*$cmd}{'net_cmd_lines'}}; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
57
|
|
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub ungetline { |
381
|
0
|
|
|
0
|
1
|
0
|
my ($cmd, $str) = @_; |
382
|
|
|
|
|
|
|
|
383
|
0
|
|
0
|
|
|
0
|
${*$cmd}{'net_cmd_lines'} ||= []; |
|
0
|
|
|
|
|
0
|
|
384
|
0
|
|
|
|
|
0
|
unshift(@{${*$cmd}{'net_cmd_lines'}}, $str); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub parse_response { |
389
|
|
|
|
|
|
|
return () |
390
|
26
|
50
|
|
26
|
1
|
273
|
unless $_[1] =~ s/^(\d\d\d)(.?)//o; |
391
|
26
|
|
|
|
|
201
|
($1, $2 eq "-"); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub response { |
396
|
21
|
|
|
21
|
1
|
56
|
my $cmd = shift; |
397
|
21
|
|
|
|
|
92
|
my ($code, $more) = (undef) x 2; |
398
|
|
|
|
|
|
|
|
399
|
21
|
|
|
|
|
426
|
$cmd->set_status($cmd->DEF_REPLY_CODE, undef); # initialize the response |
400
|
|
|
|
|
|
|
|
401
|
21
|
|
|
|
|
34
|
while (1) { |
402
|
26
|
|
|
|
|
427
|
my $str = $cmd->getline(); |
403
|
|
|
|
|
|
|
|
404
|
26
|
50
|
|
|
|
158297
|
return CMD_ERROR |
405
|
|
|
|
|
|
|
unless defined($str); |
406
|
|
|
|
|
|
|
|
407
|
26
|
50
|
|
|
|
99
|
$cmd->debug_print(0, $str) |
408
|
|
|
|
|
|
|
if ($cmd->debug); |
409
|
|
|
|
|
|
|
|
410
|
26
|
|
|
|
|
236
|
($code, $more) = $cmd->parse_response($str); |
411
|
26
|
50
|
|
|
|
109
|
unless (defined $code) { |
412
|
0
|
0
|
|
|
|
0
|
carp("$cmd: response(): parse error in '$str'") if ($cmd->debug); |
413
|
0
|
|
|
|
|
0
|
$cmd->ungetline($str); |
414
|
0
|
|
|
|
|
0
|
$@ = $str; # $@ used as tunneling hack |
415
|
0
|
|
|
|
|
0
|
return CMD_ERROR; |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
26
|
|
|
|
|
49
|
${*$cmd}{'net_cmd_code'} = $code; |
|
26
|
|
|
|
|
93
|
|
419
|
|
|
|
|
|
|
|
420
|
26
|
|
|
|
|
48
|
push(@{${*$cmd}{'net_cmd_resp'}}, $str); |
|
26
|
|
|
|
|
41
|
|
|
26
|
|
|
|
|
107
|
|
421
|
|
|
|
|
|
|
|
422
|
26
|
100
|
|
|
|
77
|
last unless ($more); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
21
|
50
|
|
|
|
76
|
return unless defined $code; |
426
|
21
|
|
|
|
|
155
|
substr($code, 0, 1); |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub read_until_dot { |
431
|
0
|
|
|
0
|
1
|
0
|
my $cmd = shift; |
432
|
0
|
|
|
|
|
0
|
my $fh = shift; |
433
|
0
|
|
|
|
|
0
|
my $arr = []; |
434
|
|
|
|
|
|
|
|
435
|
0
|
|
|
|
|
0
|
while (1) { |
436
|
0
|
0
|
|
|
|
0
|
my $str = $cmd->getline() or return; |
437
|
|
|
|
|
|
|
|
438
|
0
|
0
|
|
|
|
0
|
$cmd->debug_print(0, $str) |
439
|
|
|
|
|
|
|
if ($cmd->debug & 4); |
440
|
|
|
|
|
|
|
|
441
|
0
|
0
|
|
|
|
0
|
last if ($str =~ /^\.\r?\n/o); |
442
|
|
|
|
|
|
|
|
443
|
0
|
|
|
|
|
0
|
$str =~ s/^\.\././o; |
444
|
|
|
|
|
|
|
|
445
|
0
|
0
|
|
|
|
0
|
if (defined $fh) { |
446
|
0
|
|
|
|
|
0
|
print $fh $str; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
else { |
449
|
0
|
|
|
|
|
0
|
push(@$arr, $str); |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
0
|
|
|
|
|
0
|
$arr; |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
sub datasend { |
458
|
22
|
|
|
22
|
1
|
7817
|
my $cmd = shift; |
459
|
22
|
50
|
66
|
|
|
137
|
my $arr = @_ == 1 && ref($_[0]) ? $_[0] : \@_; |
460
|
22
|
|
|
|
|
70
|
my $line = join("", @$arr); |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
# Perls < 5.10.1 (with the exception of 5.8.9) have a performance problem with |
463
|
|
|
|
|
|
|
# the substitutions below when dealing with strings stored internally in |
464
|
|
|
|
|
|
|
# UTF-8, so downgrade them (if possible). |
465
|
|
|
|
|
|
|
# Data passed to datasend() should be encoded to octets upstream already so |
466
|
|
|
|
|
|
|
# shouldn't even have the UTF-8 flag on to start with, but if it so happens |
467
|
|
|
|
|
|
|
# that the octets are stored in an upgraded string (as can sometimes occur) |
468
|
|
|
|
|
|
|
# then they would still downgrade without fail anyway. |
469
|
|
|
|
|
|
|
# Only Unicode codepoints > 0xFF stored in an upgraded string will fail to |
470
|
|
|
|
|
|
|
# downgrade. We fail silently in that case, and a "Wide character in print" |
471
|
|
|
|
|
|
|
# warning will be emitted later by syswrite(). |
472
|
22
|
50
|
33
|
|
|
62
|
utf8::downgrade($line, 1) if $] < 5.010001 && $] != 5.008009; |
473
|
|
|
|
|
|
|
|
474
|
22
|
50
|
|
|
|
55
|
return 0 |
475
|
|
|
|
|
|
|
if $cmd->_is_closed; |
476
|
|
|
|
|
|
|
|
477
|
22
|
|
|
|
|
39
|
my $last_ch = ${*$cmd}{'net_cmd_last_ch'}; |
|
22
|
|
|
|
|
75
|
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# We have not send anything yet, so last_ch = "\012" means we are at the start of a line |
480
|
22
|
100
|
|
|
|
64
|
$last_ch = ${*$cmd}{'net_cmd_last_ch'} = "\012" unless defined $last_ch; |
|
16
|
|
|
|
|
49
|
|
481
|
|
|
|
|
|
|
|
482
|
22
|
100
|
|
|
|
56
|
return 1 unless length $line; |
483
|
|
|
|
|
|
|
|
484
|
21
|
50
|
|
|
|
52
|
if ($cmd->debug) { |
485
|
0
|
|
|
|
|
0
|
foreach my $b (split(/\n/, $line)) { |
486
|
0
|
|
|
|
|
0
|
$cmd->debug_print(1, "$b\n"); |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
21
|
|
|
|
|
27
|
$line =~ tr/\r\n/\015\012/ unless "\r" eq "\015"; |
491
|
|
|
|
|
|
|
|
492
|
21
|
|
|
|
|
33
|
my $first_ch = ''; |
493
|
|
|
|
|
|
|
|
494
|
21
|
100
|
|
|
|
62
|
if ($last_ch eq "\015") { |
|
|
100
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# Remove \012 so it does not get prefixed with another \015 below |
496
|
|
|
|
|
|
|
# and escape the . if there is one following it because the fixup |
497
|
|
|
|
|
|
|
# below will not find it |
498
|
4
|
50
|
|
|
|
55
|
$first_ch = "\012" if $line =~ s/^\012(\.?)/$1$1/; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
elsif ($last_ch eq "\012") { |
501
|
|
|
|
|
|
|
# Fixup below will not find the . as the first character of the buffer |
502
|
16
|
100
|
|
|
|
59
|
$first_ch = "." if $line =~ /^\./; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
21
|
|
|
|
|
134
|
$line =~ s/\015?\012(\.?)/\015\012$1$1/sg; |
506
|
|
|
|
|
|
|
|
507
|
21
|
|
|
|
|
52
|
substr($line, 0, 0) = $first_ch; |
508
|
|
|
|
|
|
|
|
509
|
21
|
|
|
|
|
39
|
${*$cmd}{'net_cmd_last_ch'} = substr($line, -1, 1); |
|
21
|
|
|
|
|
50
|
|
510
|
|
|
|
|
|
|
|
511
|
21
|
50
|
|
|
|
56
|
$cmd->_syswrite_with_timeout($line) |
512
|
|
|
|
|
|
|
or return; |
513
|
|
|
|
|
|
|
|
514
|
21
|
|
|
|
|
110
|
1; |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
sub rawdatasend { |
519
|
0
|
|
|
0
|
1
|
0
|
my $cmd = shift; |
520
|
0
|
0
|
0
|
|
|
0
|
my $arr = @_ == 1 && ref($_[0]) ? $_[0] : \@_; |
521
|
0
|
|
|
|
|
0
|
my $line = join("", @$arr); |
522
|
|
|
|
|
|
|
|
523
|
0
|
0
|
|
|
|
0
|
return 0 |
524
|
|
|
|
|
|
|
if $cmd->_is_closed; |
525
|
|
|
|
|
|
|
|
526
|
0
|
0
|
|
|
|
0
|
return 1 |
527
|
|
|
|
|
|
|
unless length($line); |
528
|
|
|
|
|
|
|
|
529
|
0
|
0
|
|
|
|
0
|
if ($cmd->debug) { |
530
|
0
|
|
|
|
|
0
|
my $b = "$cmd>>> "; |
531
|
0
|
|
|
|
|
0
|
print STDERR $b, join("\n$b", split(/\n/, $line)), "\n"; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
0
|
0
|
|
|
|
0
|
$cmd->_syswrite_with_timeout($line) |
535
|
|
|
|
|
|
|
or return; |
536
|
|
|
|
|
|
|
|
537
|
0
|
|
|
|
|
0
|
1; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
sub dataend { |
542
|
16
|
|
|
16
|
1
|
11295
|
my $cmd = shift; |
543
|
|
|
|
|
|
|
|
544
|
16
|
50
|
|
|
|
39
|
return 0 |
545
|
|
|
|
|
|
|
if $cmd->_is_closed; |
546
|
|
|
|
|
|
|
|
547
|
16
|
|
|
|
|
25
|
my $ch = ${*$cmd}{'net_cmd_last_ch'}; |
|
16
|
|
|
|
|
53
|
|
548
|
16
|
|
|
|
|
26
|
my $tosend; |
549
|
|
|
|
|
|
|
|
550
|
16
|
50
|
|
|
|
66
|
if (!defined $ch) { |
|
|
100
|
|
|
|
|
|
551
|
0
|
|
|
|
|
0
|
return 1; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
elsif ($ch ne "\012") { |
554
|
6
|
|
|
|
|
10
|
$tosend = "\015\012"; |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
16
|
|
|
|
|
31
|
$tosend .= ".\015\012"; |
558
|
|
|
|
|
|
|
|
559
|
16
|
50
|
|
|
|
44
|
$cmd->debug_print(1, ".\n") |
560
|
|
|
|
|
|
|
if ($cmd->debug); |
561
|
|
|
|
|
|
|
|
562
|
16
|
50
|
|
|
|
41
|
$cmd->_syswrite_with_timeout($tosend) |
563
|
|
|
|
|
|
|
or return 0; |
564
|
|
|
|
|
|
|
|
565
|
16
|
|
|
|
|
39
|
delete ${*$cmd}{'net_cmd_last_ch'}; |
|
16
|
|
|
|
|
67
|
|
566
|
|
|
|
|
|
|
|
567
|
16
|
|
|
|
|
60
|
$cmd->response() == CMD_OK; |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
# read and write to tied filehandle |
571
|
|
|
|
|
|
|
sub tied_fh { |
572
|
0
|
|
|
0
|
1
|
|
my $cmd = shift; |
573
|
0
|
|
|
|
|
|
${*$cmd}{'net_cmd_readbuf'} = ''; |
|
0
|
|
|
|
|
|
|
574
|
0
|
|
|
|
|
|
my $fh = gensym(); |
575
|
0
|
|
|
|
|
|
tie *$fh, ref($cmd), $cmd; |
576
|
0
|
|
|
|
|
|
return $fh; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# tie to myself |
580
|
|
|
|
|
|
|
sub TIEHANDLE { |
581
|
0
|
|
|
0
|
|
|
my $class = shift; |
582
|
0
|
|
|
|
|
|
my $cmd = shift; |
583
|
0
|
|
|
|
|
|
return $cmd; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# Tied filehandle read. Reads requested data length, returning |
587
|
|
|
|
|
|
|
# end-of-file when the dot is encountered. |
588
|
|
|
|
|
|
|
sub READ { |
589
|
0
|
|
|
0
|
|
|
my $cmd = shift; |
590
|
0
|
|
|
|
|
|
my ($len, $offset) = @_[1, 2]; |
591
|
0
|
0
|
|
|
|
|
return unless exists ${*$cmd}{'net_cmd_readbuf'}; |
|
0
|
|
|
|
|
|
|
592
|
0
|
|
|
|
|
|
my $done = 0; |
593
|
0
|
|
0
|
|
|
|
while (!$done and length(${*$cmd}{'net_cmd_readbuf'}) < $len) { |
|
0
|
|
|
|
|
|
|
594
|
0
|
0
|
|
|
|
|
${*$cmd}{'net_cmd_readbuf'} .= $cmd->getline() or return; |
|
0
|
|
|
|
|
|
|
595
|
0
|
0
|
|
|
|
|
$done++ if ${*$cmd}{'net_cmd_readbuf'} =~ s/^\.\r?\n\Z//m; |
|
0
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
0
|
|
|
|
|
|
$_[0] = ''; |
599
|
0
|
|
|
|
|
|
substr($_[0], $offset + 0) = substr(${*$cmd}{'net_cmd_readbuf'}, 0, $len); |
|
0
|
|
|
|
|
|
|
600
|
0
|
|
|
|
|
|
substr(${*$cmd}{'net_cmd_readbuf'}, 0, $len) = ''; |
|
0
|
|
|
|
|
|
|
601
|
0
|
0
|
|
|
|
|
delete ${*$cmd}{'net_cmd_readbuf'} if $done; |
|
0
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
|
603
|
0
|
|
|
|
|
|
return length $_[0]; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
sub READLINE { |
608
|
0
|
|
|
0
|
|
|
my $cmd = shift; |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
# in this context, we use the presence of readbuf to |
611
|
|
|
|
|
|
|
# indicate that we have not yet reached the eof |
612
|
0
|
0
|
|
|
|
|
return unless exists ${*$cmd}{'net_cmd_readbuf'}; |
|
0
|
|
|
|
|
|
|
613
|
0
|
|
|
|
|
|
my $line = $cmd->getline; |
614
|
0
|
0
|
|
|
|
|
return if $line =~ /^\.\r?\n/; |
615
|
0
|
|
|
|
|
|
$line; |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
sub PRINT { |
620
|
0
|
|
|
0
|
|
|
my $cmd = shift; |
621
|
0
|
|
|
|
|
|
my ($buf, $len, $offset) = @_; |
622
|
0
|
|
0
|
|
|
|
$len ||= length($buf); |
623
|
0
|
|
|
|
|
|
$offset += 0; |
624
|
0
|
0
|
|
|
|
|
return unless $cmd->datasend(substr($buf, $offset, $len)); |
625
|
0
|
|
|
|
|
|
${*$cmd}{'net_cmd_sending'}++; # flag that we should call dataend() |
|
0
|
|
|
|
|
|
|
626
|
0
|
|
|
|
|
|
return $len; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
sub CLOSE { |
631
|
0
|
|
|
0
|
|
|
my $cmd = shift; |
632
|
0
|
0
|
|
|
|
|
my $r = exists(${*$cmd}{'net_cmd_sending'}) ? $cmd->dataend : 1; |
|
0
|
|
|
|
|
|
|
633
|
0
|
|
|
|
|
|
delete ${*$cmd}{'net_cmd_readbuf'}; |
|
0
|
|
|
|
|
|
|
634
|
0
|
|
|
|
|
|
delete ${*$cmd}{'net_cmd_sending'}; |
|
0
|
|
|
|
|
|
|
635
|
0
|
|
|
|
|
|
$r; |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
1; |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
__END__ |