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