package Net::Hotline::Shared; ## Copyright(c) 1998-2002 by John C. Siracusa. All rights reserved. This ## program is free software; you can redistribute it and/or modify it under ## the same terms as Perl itself. use strict; use Carp; use IO::Handle; use POSIX qw(F_GETFL F_SETFL O_NONBLOCK EINTR EWOULDBLOCK EAGAIN); use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS $VERSION); require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw(_encode _write _read _hexdump _debug _set_blocking); %EXPORT_TAGS = (all => \@EXPORT_OK); $VERSION = '0.80'; sub _debug { if($Net::Hotline::Client::DEBUG) { print STDERR join('', @_); } } sub _encode { my($data) = join('', @_); my($i, $len, $enc); $len = length($data); $enc = ''; for($i = 0; $i < $len; $i++) { $enc .= pack("C", (255 - unpack("C", substr($data, $i, 1)))); } return $enc; } sub _write { my($fh, $data_ref, $length) = @_; my($written, $offset); $offset = 0; while($length > 0) # Handle partial writes { $written = syswrite($fh, $$data_ref, $length, $offset); next if($! == EINTR); unless(defined($written)) { next if($! == EWOULDBLOCK || $! == EAGAIN); croak("System write error(", $! + 0, "): $!\n"); } $length -= $written; $offset += $written; } return $offset; } sub _read { my($fh, $data_ref, $length, $blocking) = @_; my($offset) = 0; my($read) = 0; $blocking = 1 unless(defined($blocking)); #_debug("Reading $length..."); while($length > 0) # Handle partial reads { $read = sysread($fh, $$data_ref, $length, $offset); unless(defined($read)) { next if($! == EINTR); # Once we read a little bit, we keep readinuntil we get it all # Otherwise, we can return undef and treat it as a WOULDBLOCK if($blocking || $offset > 0) { next } else { return } } $offset += $read; $length -= $read; } #_debug("read $offset ($length)\n"); return($offset); } sub _set_blocking { my($fh, $blocking) = @_; if($IO::VERSION >= 1.19) # The easy way, with the IO module { $fh->blocking($blocking); } else # The hard way...not 100% successful :-/ { my($flags) = fcntl($fh, F_GETFL, 0); defined($flags) || croak "Can't get flags for socket: $!\n"; if($blocking) { fcntl($fh, F_SETFL, $flags & ~O_NONBLOCK) || croak "Can't make socket blocking: $!\n"; } else { fcntl($fh, F_SETFL, $flags | O_NONBLOCK) || croak "Can't make socket nonblocking: $!\n"; } } } sub _hexdump { my($data) = join('', @_); my($ret, $hex, $ascii, $len, $i); $len = length($data); for($i = 0; $i < $len; $i++) { if($i > 0) { if($i % 4 == 0) { $hex .= ' '; } if($i % 16 == 0) { $ret .= "$hex$ascii\n"; $ascii = $hex = ''; } } $hex .= sprintf("%02x ", ord(substr($data, $i, 1))); $ascii .= sprintf("%c", (ord(substr($data, $i, 1)) > 31 and ord(substr($data, $i, 1)) < 127) ? ord(substr($data, $i, 1)) : 46); } if(length($hex) < 50) { $hex .= ' ' x (50 - length($hex)); } $ret .= "$hex $ascii\n"; return $ret; } 1;