Cassidy has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to connect to a sendmail port and make sure it is running.

I tried sysread($sock, $input, 3) in hopes that it would kick out if nothing was returned. When I connect to port 25 $input is assinged what it should be(220). If I connect to port 80 (apache doesn't initially send anything) sysread() will block because there is nothing to read. Is there a way to make sysread() kick out if there is nothing to read? Should I be using a different function?

Here is the code ... any ideas?

#!/usr/local/bin/perl -w use IO::Socket; $addr="127.0.0.1"; $port="80"; $sock = IO::Socket::INET->new(PeerAddr => "$addr", PeerPort => "$port", Proto => 'tcp', Timeout => '1',); if ($sock) { $sock->autoflush(1); print "I am going into sysread()\n"; $foo = sysread($sock, $input, 3); chomp($input); print "Came out of sysread() with \$input as:\n$input\n\sysread() r +eturned: $foo\n"; $sock->close; if ($input eq "") { print "We have no input. Sendmail must be down. +" } elsif ($input =~ /220/) { print "We seem to have gotten the correct + response\n"; } else { print "Dosn't look like a sendmail port\n"; } } else { print "It didn\'t connect ... must be down\n"; }
And if you would rather see it left justified go here.

Edit kudra, 2001-10-09 Replaced pre with code

Replies are listed 'Best First'.
Re: sysread()
by pjf (Curate) on Oct 09, 2001 at 06:19 UTC
    Good advice above, although be careful of non-blocking mode in a case like this, you could find yourself repeatedly calling sysread when there's nothing to read (which will chew your CPU), or sleeping un-necessarily (which isn't too bad, but not ideal).

    Here's an example of using select instead to wait three seconds for a response.

    use IO::Select; # Do socket creation and checking... # Now play with IO::Select so we can wait three seconds for # a result. my $selector = IO::Select->new($sock); if ($selector->can_read(3)) { # 3 second timeout. # Do reading and checking stuff... } else { # Waited three seconds and couldn't read. Bummer. }
    Note that if you receive a success from ->can_read, but when you do attempt a sysread you receive 0 or undef, it means that the remote end disconnected or (much less likely) an error occured.

    See IO::Select for more information on using this wonderful tool.

    Cheers,
    Paul

    P.S. In the code above you're connecting to port 80, whereas SMTP daemons like sendmail usually live on port 25. I assume this is just a typo.

      another issue i ran into recent with something like this: sysread() doesn't seem to guarantee that the number of bytes read are, in fact, the number of bytes that were actually read. i had to ( with the help of a co-worker ) stick in some 'error-checking' to ensure that sysread DID in fact deliver the requested number of bytes.

      we ended up implementing this:

      sub send_packet { my ($socket, $packet) = @_; my $length = length($packet); my $lengthbuf = pack("N", $length); my $rc = syswrite($socket, $lengthbuf, 4); die "syswrite (length): $!\n" if $rc != 4; my $byteswritten = 0; while ($byteswritten < $length) { my $rc = syswrite($socket, $packet, length($packet)); die "SEND_PACKET: sysread (data): $!\n" if $rc < 0; $packet = substr($packet, $rc, -1); $byteswritten += $rc; } }
      and that fixed some blocking we encountered - even when IO::Select said a socket was readable.
Re: sysread()
by Fletch (Bishop) on Oct 09, 2001 at 05:26 UTC

    Set the socket to non-blocking mode (perldoc -q blocking) or set an alarm (perldoc -f alarm).

Re: sysread()
by chromatic (Archbishop) on Oct 09, 2001 at 06:04 UTC