document [PATCH] lib/feature.pm
[p5sagit/p5-mst-13.2.git] / lib / Net / Cmd.pm
CommitLineData
b3f6f6a6 1# Net::Cmd.pm
406c51ee 2#
7cf5cf7c 3# Copyright (c) 1995-2006 Graham Barr <gbarr@pobox.com>. All rights reserved.
406c51ee 4# This program is free software; you can redistribute it and/or
5# modify it under the same terms as Perl itself.
6
7package Net::Cmd;
8
9require 5.001;
10require Exporter;
11
12use strict;
13use vars qw(@ISA @EXPORT $VERSION);
14use Carp;
12df23ee 15use Symbol 'gensym';
406c51ee 16
686337f3 17BEGIN {
18 if ($^O eq 'os390') {
19 require Convert::EBCDIC;
b3f6f6a6 20
21 # Convert::EBCDIC->import;
686337f3 22 }
23}
24
1c756492 25BEGIN {
26 if (!eval { require utf8 }) {
27 *is_utf8 = sub { 0 };
28 }
29 elsif (eval { utf8::is_utf8(undef); 1 }) {
30 *is_utf8 = \&utf8::is_utf8;
31 }
32 elsif (eval { require Encode; Encode::is_utf8(undef); 1 }) {
33 *is_utf8 = \&Encode::is_utf8;
34 }
35 else {
36 *is_utf8 = sub { $_[0] =~ /[^\x00-\xff]/ };
37 }
38}
b3f6f6a6 39
1c756492 40$VERSION = "2.29";
406c51ee 41@ISA = qw(Exporter);
42@EXPORT = qw(CMD_INFO CMD_OK CMD_MORE CMD_REJECT CMD_ERROR CMD_PENDING);
43
b3f6f6a6 44
45sub CMD_INFO {1}
46sub CMD_OK {2}
47sub CMD_MORE {3}
48sub CMD_REJECT {4}
49sub CMD_ERROR {5}
50sub CMD_PENDING {0}
406c51ee 51
52my %debug = ();
53
686337f3 54my $tr = $^O eq 'os390' ? Convert::EBCDIC->new() : undef;
55
686337f3 56
b3f6f6a6 57sub toebcdic {
58 my $cmd = shift;
59
60 unless (exists ${*$cmd}{'net_cmd_asciipeer'}) {
61 my $string = $_[0];
62 my $ebcdicstr = $tr->toebcdic($string);
63 ${*$cmd}{'net_cmd_asciipeer'} = $string !~ /^\d+/ && $ebcdicstr =~ /^\d+/;
686337f3 64 }
65
66 ${*$cmd}{'net_cmd_asciipeer'}
67 ? $tr->toebcdic($_[0])
68 : $_[0];
69}
70
b3f6f6a6 71
72sub toascii {
686337f3 73 my $cmd = shift;
74 ${*$cmd}{'net_cmd_asciipeer'}
75 ? $tr->toascii($_[0])
76 : $_[0];
77}
78
406c51ee 79
b3f6f6a6 80sub _print_isa {
81 no strict qw(refs);
406c51ee 82
b3f6f6a6 83 my $pkg = shift;
84 my $cmd = $pkg;
406c51ee 85
b3f6f6a6 86 $debug{$pkg} ||= 0;
406c51ee 87
b3f6f6a6 88 my %done = ();
89 my @do = ($pkg);
90 my %spc = ($pkg, "");
406c51ee 91
b3f6f6a6 92 while ($pkg = shift @do) {
93 next if defined $done{$pkg};
406c51ee 94
b3f6f6a6 95 $done{$pkg} = 1;
406c51ee 96
b3f6f6a6 97 my $v =
98 defined ${"${pkg}::VERSION"}
99 ? "(" . ${"${pkg}::VERSION"} . ")"
100 : "";
406c51ee 101
b3f6f6a6 102 my $spc = $spc{$pkg};
103 $cmd->debug_print(1, "${spc}${pkg}${v}\n");
104
105 if (@{"${pkg}::ISA"}) {
106 @spc{@{"${pkg}::ISA"}} = (" " . $spc{$pkg}) x @{"${pkg}::ISA"};
107 unshift(@do, @{"${pkg}::ISA"});
406c51ee 108 }
109 }
406c51ee 110}
111
406c51ee 112
b3f6f6a6 113sub debug {
114 @_ == 1 or @_ == 2 or croak 'usage: $obj->debug([LEVEL])';
406c51ee 115
b3f6f6a6 116 my ($cmd, $level) = @_;
117 my $pkg = ref($cmd) || $cmd;
118 my $oldval = 0;
119
120 if (ref($cmd)) {
121 $oldval = ${*$cmd}{'net_cmd_debug'} || 0;
406c51ee 122 }
b3f6f6a6 123 else {
124 $oldval = $debug{$pkg} || 0;
406c51ee 125 }
126
b3f6f6a6 127 return $oldval
406c51ee 128 unless @_ == 2;
129
b3f6f6a6 130 $level = $debug{$pkg} || 0
406c51ee 131 unless defined $level;
132
b3f6f6a6 133 _print_isa($pkg)
134 if ($level && !exists $debug{$pkg});
406c51ee 135
b3f6f6a6 136 if (ref($cmd)) {
137 ${*$cmd}{'net_cmd_debug'} = $level;
406c51ee 138 }
b3f6f6a6 139 else {
140 $debug{$pkg} = $level;
406c51ee 141 }
142
b3f6f6a6 143 $oldval;
406c51ee 144}
145
406c51ee 146
b3f6f6a6 147sub message {
148 @_ == 1 or croak 'usage: $obj->message()';
149
150 my $cmd = shift;
406c51ee 151
b3f6f6a6 152 wantarray
153 ? @{${*$cmd}{'net_cmd_resp'}}
154 : join("", @{${*$cmd}{'net_cmd_resp'}});
406c51ee 155}
156
b3f6f6a6 157
406c51ee 158sub debug_text { $_[2] }
159
b3f6f6a6 160
161sub debug_print {
162 my ($cmd, $out, $text) = @_;
163 print STDERR $cmd, ($out ? '>>> ' : '<<< '), $cmd->debug_text($out, $text);
406c51ee 164}
165
406c51ee 166
b3f6f6a6 167sub code {
168 @_ == 1 or croak 'usage: $obj->code()';
169
170 my $cmd = shift;
406c51ee 171
b3f6f6a6 172 ${*$cmd}{'net_cmd_code'} = "000"
173 unless exists ${*$cmd}{'net_cmd_code'};
406c51ee 174
b3f6f6a6 175 ${*$cmd}{'net_cmd_code'};
406c51ee 176}
177
406c51ee 178
b3f6f6a6 179sub status {
180 @_ == 1 or croak 'usage: $obj->status()';
406c51ee 181
b3f6f6a6 182 my $cmd = shift;
183
184 substr(${*$cmd}{'net_cmd_code'}, 0, 1);
406c51ee 185}
186
406c51ee 187
b3f6f6a6 188sub set_status {
189 @_ == 3 or croak 'usage: $obj->set_status(CODE, MESSAGE)';
190
191 my $cmd = shift;
192 my ($code, $resp) = @_;
406c51ee 193
b3f6f6a6 194 $resp = [$resp]
195 unless ref($resp);
406c51ee 196
b3f6f6a6 197 (${*$cmd}{'net_cmd_code'}, ${*$cmd}{'net_cmd_resp'}) = ($code, $resp);
406c51ee 198
b3f6f6a6 199 1;
406c51ee 200}
201
406c51ee 202
b3f6f6a6 203sub command {
204 my $cmd = shift;
205
206 unless (defined fileno($cmd)) {
686337f3 207 $cmd->set_status("599", "Connection closed");
208 return $cmd;
209 }
210
211
b3f6f6a6 212 $cmd->dataend()
213 if (exists ${*$cmd}{'net_cmd_last_ch'});
406c51ee 214
b3f6f6a6 215 if (scalar(@_)) {
216 local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS';
686337f3 217
b3f6f6a6 218 my $str = join(
219 " ",
220 map {
221 /\n/
222 ? do { my $n = $_; $n =~ tr/\n/ /; $n }
223 : $_;
224 } @_
225 );
226 $str = $cmd->toascii($str) if $tr;
227 $str .= "\015\012";
406c51ee 228
b3f6f6a6 229 my $len = length $str;
230 my $swlen;
686337f3 231
b3f6f6a6 232 $cmd->close
233 unless (defined($swlen = syswrite($cmd, $str, $len)) && $swlen == $len);
406c51ee 234
b3f6f6a6 235 $cmd->debug_print(1, $str)
236 if ($cmd->debug);
406c51ee 237
b3f6f6a6 238 ${*$cmd}{'net_cmd_resp'} = []; # the response
239 ${*$cmd}{'net_cmd_code'} = "000"; # Made this one up :-)
406c51ee 240 }
241
b3f6f6a6 242 $cmd;
406c51ee 243}
244
406c51ee 245
b3f6f6a6 246sub ok {
247 @_ == 1 or croak 'usage: $obj->ok()';
248
249 my $code = $_[0]->code;
250 0 < $code && $code < 400;
406c51ee 251}
252
406c51ee 253
b3f6f6a6 254sub unsupported {
255 my $cmd = shift;
256
257 ${*$cmd}{'net_cmd_resp'} = ['Unsupported command'];
258 ${*$cmd}{'net_cmd_code'} = 580;
259 0;
406c51ee 260}
261
406c51ee 262
b3f6f6a6 263sub getline {
264 my $cmd = shift;
265
266 ${*$cmd}{'net_cmd_lines'} ||= [];
406c51ee 267
b3f6f6a6 268 return shift @{${*$cmd}{'net_cmd_lines'}}
406c51ee 269 if scalar(@{${*$cmd}{'net_cmd_lines'}});
270
b3f6f6a6 271 my $partial = defined(${*$cmd}{'net_cmd_partial'}) ? ${*$cmd}{'net_cmd_partial'} : "";
272 my $fd = fileno($cmd);
686337f3 273
b3f6f6a6 274 return undef
275 unless defined $fd;
406c51ee 276
b3f6f6a6 277 my $rin = "";
278 vec($rin, $fd, 1) = 1;
406c51ee 279
b3f6f6a6 280 my $buf;
406c51ee 281
b3f6f6a6 282 until (scalar(@{${*$cmd}{'net_cmd_lines'}})) {
283 my $timeout = $cmd->timeout || undef;
284 my $rout;
7cf5cf7c 285
b3f6f6a6 286 my $select_ret = select($rout = $rin, undef, undef, $timeout);
287 if ($select_ret > 0) {
288 unless (sysread($cmd, $buf = "", 1024)) {
289 carp(ref($cmd) . ": Unexpected EOF on command channel")
290 if $cmd->debug;
291 $cmd->close;
292 return undef;
293 }
406c51ee 294
b3f6f6a6 295 substr($buf, 0, 0) = $partial; ## prepend from last sysread
406c51ee 296
b3f6f6a6 297 my @buf = split(/\015?\012/, $buf, -1); ## break into lines
406c51ee 298
b3f6f6a6 299 $partial = pop @buf;
406c51ee 300
b3f6f6a6 301 push(@{${*$cmd}{'net_cmd_lines'}}, map {"$_\n"} @buf);
406c51ee 302
303 }
b3f6f6a6 304 else {
305 my $msg = $select_ret ? "Error or Interrupted: $!" : "Timeout";
306 carp("$cmd: $msg") if ($cmd->debug);
307 return undef;
406c51ee 308 }
309 }
310
b3f6f6a6 311 ${*$cmd}{'net_cmd_partial'} = $partial;
406c51ee 312
b3f6f6a6 313 if ($tr) {
314 foreach my $ln (@{${*$cmd}{'net_cmd_lines'}}) {
315 $ln = $cmd->toebcdic($ln);
686337f3 316 }
317 }
318
b3f6f6a6 319 shift @{${*$cmd}{'net_cmd_lines'}};
406c51ee 320}
321
406c51ee 322
b3f6f6a6 323sub ungetline {
324 my ($cmd, $str) = @_;
325
326 ${*$cmd}{'net_cmd_lines'} ||= [];
327 unshift(@{${*$cmd}{'net_cmd_lines'}}, $str);
406c51ee 328}
329
b3f6f6a6 330
331sub parse_response {
332 return ()
406c51ee 333 unless $_[1] =~ s/^(\d\d\d)(.?)//o;
b3f6f6a6 334 ($1, $2 eq "-");
406c51ee 335}
336
406c51ee 337
b3f6f6a6 338sub response {
339 my $cmd = shift;
340 my ($code, $more) = (undef) x 2;
406c51ee 341
b3f6f6a6 342 ${*$cmd}{'net_cmd_resp'} ||= [];
406c51ee 343
b3f6f6a6 344 while (1) {
345 my $str = $cmd->getline();
406c51ee 346
b3f6f6a6 347 return CMD_ERROR
348 unless defined($str);
406c51ee 349
b3f6f6a6 350 $cmd->debug_print(0, $str)
351 if ($cmd->debug);
352
353 ($code, $more) = $cmd->parse_response($str);
354 unless (defined $code) {
355 $cmd->ungetline($str);
356 last;
406c51ee 357 }
358
b3f6f6a6 359 ${*$cmd}{'net_cmd_code'} = $code;
406c51ee 360
b3f6f6a6 361 push(@{${*$cmd}{'net_cmd_resp'}}, $str);
406c51ee 362
b3f6f6a6 363 last unless ($more);
364 }
406c51ee 365
b3f6f6a6 366 substr($code, 0, 1);
406c51ee 367}
368
406c51ee 369
b3f6f6a6 370sub read_until_dot {
371 my $cmd = shift;
372 my $fh = shift;
373 my $arr = [];
406c51ee 374
b3f6f6a6 375 while (1) {
376 my $str = $cmd->getline() or return undef;
406c51ee 377
b3f6f6a6 378 $cmd->debug_print(0, $str)
379 if ($cmd->debug & 4);
406c51ee 380
b3f6f6a6 381 last if ($str =~ /^\.\r?\n/o);
406c51ee 382
b3f6f6a6 383 $str =~ s/^\.\././o;
384
385 if (defined $fh) {
386 print $fh $str;
406c51ee 387 }
b3f6f6a6 388 else {
389 push(@$arr, $str);
406c51ee 390 }
391 }
392
b3f6f6a6 393 $arr;
406c51ee 394}
395
406c51ee 396
b3f6f6a6 397sub datasend {
398 my $cmd = shift;
399 my $arr = @_ == 1 && ref($_[0]) ? $_[0] : \@_;
400 my $line = join("", @$arr);
401
1c756492 402 # encode to individual utf8 bytes if
403 # $line is a string (in internal UTF-8)
404 utf8::encode($line) if is_utf8($line);
b3f6f6a6 405
406 return 0 unless defined(fileno($cmd));
406c51ee 407
b3f6f6a6 408 my $last_ch = ${*$cmd}{'net_cmd_last_ch'};
409 $last_ch = ${*$cmd}{'net_cmd_last_ch'} = "\012" unless defined $last_ch;
f92f3fcb 410
b3f6f6a6 411 return 1 unless length $line;
406c51ee 412
b3f6f6a6 413 if ($cmd->debug) {
414 foreach my $b (split(/\n/, $line)) {
415 $cmd->debug_print(1, "$b\n");
416 }
406c51ee 417 }
418
b3f6f6a6 419 $line =~ tr/\r\n/\015\012/ unless "\r" eq "\015";
406c51ee 420
f92f3fcb 421 my $first_ch = '';
422
423 if ($last_ch eq "\015") {
424 $first_ch = "\012" if $line =~ s/^\012//;
425 }
426 elsif ($last_ch eq "\012") {
427 $first_ch = "." if $line =~ /^\./;
428 }
429
b3f6f6a6 430 $line =~ s/\015?\012(\.?)/\015\012$1$1/sg;
406c51ee 431
b3f6f6a6 432 substr($line, 0, 0) = $first_ch;
f92f3fcb 433
b3f6f6a6 434 ${*$cmd}{'net_cmd_last_ch'} = substr($line, -1, 1);
406c51ee 435
b3f6f6a6 436 my $len = length($line);
437 my $offset = 0;
438 my $win = "";
439 vec($win, fileno($cmd), 1) = 1;
440 my $timeout = $cmd->timeout || undef;
406c51ee 441
b3f6f6a6 442 local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS';
dea4d7df 443
b3f6f6a6 444 while ($len) {
445 my $wout;
446 my $s = select(undef, $wout = $win, undef, $timeout);
447 if ((defined $s and $s > 0) or -f $cmd) # -f for testing on win32
406c51ee 448 {
b3f6f6a6 449 my $w = syswrite($cmd, $line, $len, $offset);
450 unless (defined($w)) {
451 carp("$cmd: $!") if $cmd->debug;
452 return undef;
406c51ee 453 }
b3f6f6a6 454 $len -= $w;
455 $offset += $w;
406c51ee 456 }
b3f6f6a6 457 else {
458 carp("$cmd: Timeout") if ($cmd->debug);
459 return undef;
406c51ee 460 }
461 }
462
b3f6f6a6 463 1;
406c51ee 464}
465
406c51ee 466
b3f6f6a6 467sub rawdatasend {
468 my $cmd = shift;
469 my $arr = @_ == 1 && ref($_[0]) ? $_[0] : \@_;
470 my $line = join("", @$arr);
406c51ee 471
b3f6f6a6 472 return 0 unless defined(fileno($cmd));
473
474 return 1
dea4d7df 475 unless length($line);
406c51ee 476
b3f6f6a6 477 if ($cmd->debug) {
478 my $b = "$cmd>>> ";
479 print STDERR $b, join("\n$b", split(/\n/, $line)), "\n";
406c51ee 480 }
dea4d7df 481
b3f6f6a6 482 my $len = length($line);
483 my $offset = 0;
484 my $win = "";
485 vec($win, fileno($cmd), 1) = 1;
486 my $timeout = $cmd->timeout || undef;
487
488 local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS';
489 while ($len) {
490 my $wout;
491 if (select(undef, $wout = $win, undef, $timeout) > 0) {
492 my $w = syswrite($cmd, $line, $len, $offset);
493 unless (defined($w)) {
494 carp("$cmd: $!") if $cmd->debug;
495 return undef;
dea4d7df 496 }
b3f6f6a6 497 $len -= $w;
498 $offset += $w;
dea4d7df 499 }
b3f6f6a6 500 else {
501 carp("$cmd: Timeout") if ($cmd->debug);
502 return undef;
dea4d7df 503 }
406c51ee 504 }
505
b3f6f6a6 506 1;
dea4d7df 507}
508
dea4d7df 509
b3f6f6a6 510sub dataend {
511 my $cmd = shift;
512
513 return 0 unless defined(fileno($cmd));
dea4d7df 514
b3f6f6a6 515 my $ch = ${*$cmd}{'net_cmd_last_ch'};
516 my $tosend;
f92f3fcb 517
b3f6f6a6 518 if (!defined $ch) {
519 return 1;
520 }
521 elsif ($ch ne "\012") {
522 $tosend = "\015\012";
523 }
f92f3fcb 524
b3f6f6a6 525 $tosend .= ".\015\012";
dea4d7df 526
b3f6f6a6 527 local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS';
dea4d7df 528
b3f6f6a6 529 $cmd->debug_print(1, ".\n")
530 if ($cmd->debug);
406c51ee 531
b3f6f6a6 532 syswrite($cmd, $tosend, length $tosend);
406c51ee 533
b3f6f6a6 534 delete ${*$cmd}{'net_cmd_last_ch'};
406c51ee 535
b3f6f6a6 536 $cmd->response() == CMD_OK;
406c51ee 537}
538
12df23ee 539# read and write to tied filehandle
540sub tied_fh {
541 my $cmd = shift;
542 ${*$cmd}{'net_cmd_readbuf'} = '';
543 my $fh = gensym();
b3f6f6a6 544 tie *$fh, ref($cmd), $cmd;
12df23ee 545 return $fh;
546}
547
548# tie to myself
549sub TIEHANDLE {
550 my $class = shift;
b3f6f6a6 551 my $cmd = shift;
12df23ee 552 return $cmd;
553}
554
555# Tied filehandle read. Reads requested data length, returning
556# end-of-file when the dot is encountered.
557sub READ {
558 my $cmd = shift;
b3f6f6a6 559 my ($len, $offset) = @_[1, 2];
12df23ee 560 return unless exists ${*$cmd}{'net_cmd_readbuf'};
561 my $done = 0;
562 while (!$done and length(${*$cmd}{'net_cmd_readbuf'}) < $len) {
b3f6f6a6 563 ${*$cmd}{'net_cmd_readbuf'} .= $cmd->getline() or return;
564 $done++ if ${*$cmd}{'net_cmd_readbuf'} =~ s/^\.\r?\n\Z//m;
12df23ee 565 }
566
567 $_[0] = '';
b3f6f6a6 568 substr($_[0], $offset + 0) = substr(${*$cmd}{'net_cmd_readbuf'}, 0, $len);
569 substr(${*$cmd}{'net_cmd_readbuf'}, 0, $len) = '';
12df23ee 570 delete ${*$cmd}{'net_cmd_readbuf'} if $done;
571
572 return length $_[0];
573}
574
b3f6f6a6 575
12df23ee 576sub READLINE {
577 my $cmd = shift;
b3f6f6a6 578
12df23ee 579 # in this context, we use the presence of readbuf to
580 # indicate that we have not yet reached the eof
581 return unless exists ${*$cmd}{'net_cmd_readbuf'};
582 my $line = $cmd->getline;
583 return if $line =~ /^\.\r?\n/;
584 $line;
585}
586
b3f6f6a6 587
12df23ee 588sub PRINT {
589 my $cmd = shift;
b3f6f6a6 590 my ($buf, $len, $offset) = @_;
591 $len ||= length($buf);
12df23ee 592 $offset += 0;
b3f6f6a6 593 return unless $cmd->datasend(substr($buf, $offset, $len));
594 ${*$cmd}{'net_cmd_sending'}++; # flag that we should call dataend()
12df23ee 595 return $len;
596}
597
b3f6f6a6 598
12df23ee 599sub CLOSE {
600 my $cmd = shift;
b3f6f6a6 601 my $r = exists(${*$cmd}{'net_cmd_sending'}) ? $cmd->dataend : 1;
12df23ee 602 delete ${*$cmd}{'net_cmd_readbuf'};
603 delete ${*$cmd}{'net_cmd_sending'};
604 $r;
605}
606
406c51ee 6071;
608
609__END__
610
611
612=head1 NAME
613
614Net::Cmd - Network Command class (as used by FTP, SMTP etc)
615
616=head1 SYNOPSIS
617
618 use Net::Cmd;
686337f3 619
406c51ee 620 @ISA = qw(Net::Cmd);
621
622=head1 DESCRIPTION
623
624C<Net::Cmd> is a collection of methods that can be inherited by a sub class
625of C<IO::Handle>. These methods implement the functionality required for a
626command based protocol, for example FTP and SMTP.
627
628=head1 USER METHODS
629
630These methods provide a user interface to the C<Net::Cmd> object.
631
632=over 4
633
634=item debug ( VALUE )
635
636Set the level of debug information for this object. If C<VALUE> is not given
637then the current state is returned. Otherwise the state is changed to
638C<VALUE> and the previous state returned.
639
510179aa 640Different packages
641may implement different levels of debug but a non-zero value results in
406c51ee 642copies of all commands and responses also being sent to STDERR.
643
644If C<VALUE> is C<undef> then the debug level will be set to the default
645debug level for the class.
646
647This method can also be called as a I<static> method to set/get the default
648debug level for a given class.
649
650=item message ()
651
652Returns the text message returned from the last command
653
654=item code ()
655
656Returns the 3-digit code from the last command. If a command is pending
657then the value 0 is returned
658
659=item ok ()
660
661Returns non-zero if the last code value was greater than zero and
662less than 400. This holds true for most command servers. Servers
663where this does not hold may override this method.
664
665=item status ()
666
667Returns the most significant digit of the current status code. If a command
668is pending then C<CMD_PENDING> is returned.
669
670=item datasend ( DATA )
671
672Send data to the remote server, converting LF to CRLF. Any line starting
673with a '.' will be prefixed with another '.'.
674C<DATA> may be an array or a reference to an array.
675
676=item dataend ()
677
678End the sending of data to the remote server. This is done by ensuring that
679the data already sent ends with CRLF then sending '.CRLF' to end the
680transmission. Once this data has been sent C<dataend> calls C<response> and
681returns true if C<response> returns CMD_OK.
682
683=back
684
685=head1 CLASS METHODS
686
687These methods are not intended to be called by the user, but used or
688over-ridden by a sub-class of C<Net::Cmd>
689
690=over 4
691
692=item debug_print ( DIR, TEXT )
693
694Print debugging information. C<DIR> denotes the direction I<true> being
695data being sent to the server. Calls C<debug_text> before printing to
696STDERR.
697
698=item debug_text ( TEXT )
699
700This method is called to print debugging information. TEXT is
701the text being sent. The method should return the text to be printed
702
703This is primarily meant for the use of modules such as FTP where passwords
704are sent, but we do not want to display them in the debugging information.
705
706=item command ( CMD [, ARGS, ... ])
707
708Send a command to the command server. All arguments a first joined with
709a space character and CRLF is appended, this string is then sent to the
710command server.
711
712Returns undef upon failure
713
714=item unsupported ()
715
716Sets the status code to 580 and the response text to 'Unsupported command'.
717Returns zero.
718
719=item response ()
720
721Obtain a response from the server. Upon success the most significant digit
722of the status code is returned. Upon failure, timeout etc., I<undef> is
723returned.
724
725=item parse_response ( TEXT )
726
727This method is called by C<response> as a method with one argument. It should
728return an array of 2 values, the 3-digit status code and a flag which is true
729when this is part of a multi-line response and this line is not the list.
730
731=item getline ()
732
733Retrieve one line, delimited by CRLF, from the remote server. Returns I<undef>
734upon failure.
735
736B<NOTE>: If you do use this method for any reason, please remember to add
737some C<debug_print> calls into your method.
738
739=item ungetline ( TEXT )
740
741Unget a line of text from the server.
742
dea4d7df 743=item rawdatasend ( DATA )
744
745Send data to the remote server without performing any conversions. C<DATA>
746is a scalar.
747
406c51ee 748=item read_until_dot ()
749
750Read data from the remote server until a line consisting of a single '.'.
751Any lines starting with '..' will have one of the '.'s removed.
752
753Returns a reference to a list containing the lines, or I<undef> upon failure.
754
12df23ee 755=item tied_fh ()
756
757Returns a filehandle tied to the Net::Cmd object. After issuing a
758command, you may read from this filehandle using read() or <>. The
759filehandle will return EOF when the final dot is encountered.
760Similarly, you may write to the filehandle in order to send data to
3c4b39be 761the server after issuing a command that expects data to be written.
12df23ee 762
763See the Net::POP3 and Net::SMTP modules for examples of this.
764
406c51ee 765=back
766
767=head1 EXPORTS
768
769C<Net::Cmd> exports six subroutines, five of these, C<CMD_INFO>, C<CMD_OK>,
510179aa 770C<CMD_MORE>, C<CMD_REJECT> and C<CMD_ERROR>, correspond to possible results
406c51ee 771of C<response> and C<status>. The sixth is C<CMD_PENDING>.
772
773=head1 AUTHOR
774
775Graham Barr <gbarr@pobox.com>
776
777=head1 COPYRIGHT
778
7cf5cf7c 779Copyright (c) 1995-2006 Graham Barr. All rights reserved.
406c51ee 780This program is free software; you can redistribute it and/or modify
781it under the same terms as Perl itself.
782
783=cut