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

The gethost* (e.g. gethostbyaddr) functions document that if h_errno is supported by C, h_errno is returned in $? if a call fails. I would like to ascribe meaning to the returned value.

Where are the symbolic values (e.g. from C's netdb.h) such as TRY_AGAIN and HOST_NOT_FOUND defined in Perl? Is there a hstrerror() equivalent?

Thanks.

This communication may not represent my employer's views, if any, on the matters discussed.

Replies are listed 'Best First'.
Re: h_errno constants?
by Perlbotics (Archbishop) on Jun 21, 2009 at 10:25 UTC

    I think Errno does what you require. Additionally, you can search for the file Errno.pm on your computer and see what's locally available.

    Update: Ok, I misunderstood your question. The following is ultra-fragile, but works here (YMMV):

    use strict; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my %h_error_symbol; # maps errno to symbol my %h_error_text = ( NETDB_INTERNAL => "See errno.", NETDB_SUCCESS => "No problem.", HOST_NOT_FOUND => "Authoritative Answer Host not found.", TRY_AGAIN => "Non-Authoritative Host not found, or SERVERFAIL +.", NO_RECOVERY => "Non recoverable errors, FORMERR, REFUSED, NOTIM +P.", NO_DATA => "Valid name, no data record of requested type.", NO_ADDRESS => "No address, look for MX record.", ); # we later try to find a mapping errno-->symbol open my $errdb, '<', '/usr/include/netdb.h' or die; while (my $line = <$errdb>) { if (my ($symbol, $val) = $line =~ /^\s*\#\s*define\s+([^_]\w+)\s+(-? +\d+)/) { next unless exists $h_error_text{$symbol}; # skip irrelevant symbo +ls die "FATAL: $symbol = $val - conflicts with $h_error_symbol{$val} +\n" if exists $h_error_symbol{$val}; $h_error_symbol{$val} = $symbol; } } close $errdb or die; sub hstrerror { my $errno = shift; return exists $h_error_text{$h_error_symbol{$errno}} ? $h_error_text{$h_error_symbol{$errno}} : "other h_error \#$errno"; } sub h_error_symbol { my $errno = shift; return exists $h_error_symbol{$errno} ? $h_error_symbol{$errno} : "GENERIC_H_ERROR_$errno"; } # Demo: print "Example: 1 -> ", h_error_symbol(1), " / ", hstrerror(1), "\n"; print Dumper(\%h_error_symbol);
    Example: 1 -> HOST_NOT_FOUND / Authoritative Answer Host not found. $VAR1 = { '-1' => 'NETDB_INTERNAL', '0' => 'NETDB_SUCCESS', '1' => 'HOST_NOT_FOUND', '2' => 'TRY_AGAIN', '3' => 'NO_RECOVERY', '4' => 'NO_DATA' };

      Thanks for the solution. I agree it's fragile, and have entered perlbug 66804 requesting a robust fix in the core.

      I refered to this thread so that it can serve as a basis for the robust fix. Meantime, I'll use your code for my immediate needs. Thanks again.

      This communication may not represent my employer's views, if any, on the matters discussed.

Re: h_errno constants?
by tlhackque (Beadle) on Jun 21, 2009 at 14:54 UTC
    Here's my interim solution:
    package HErrno; # tlhackque - roughly based on a scheme by Perlbotics # in http://www.perlmonks.org/index.pl?node_id=773351 # # use HErrno.pm; # # print $herrno{$?} # String from h_errno # print $herrno{NETDB_SUCCESS} # String from name or value # use HErrno.pm qw( :NAMES ); # Constant (subroutines) for all name +s # use HErrno.pm qw ( HOST_NOT_FOUND ); # Constant for one name # # my h_errno = $? # if( h_errno == HOST_NOT_FOUND ) ... # our (@EXPORT, @EXPORT_OK,%EXPORT_TAGS,@ISA,%herrno,$VERSION); use Exporter (); use strict; $VERSION = "0.01_00"; $VERSION = eval $VERSION; @ISA = qw(Exporter); @EXPORT = qw(%herrno); BEGIN { %herrno = ( # Symbols to obtain => error string to return. NETDB_INTERNAL => "See errno.", NETDB_SUCCESS => "No problem.", HOST_NOT_FOUND => "Authoritative Answer Host not found.", TRY_AGAIN => "Non-Authoritative Host not found, or SER +VERFAIL.", NO_RECOVERY => "Non recoverable errors, FORMERR, REFUSED +, NOTIMP.", NO_DATA => "Valid name, no data record of requested +type.", NO_ADDRESS => "No address, look for MX record.", ); @EXPORT_OK = ( qw(NO_ADDRESS) ); %EXPORT_TAGS = ( NAMES => [qw(NO_ADDRESS)] ); # Get symbol values from netdb.h. This isn't robust... open my $errdb, '<', '/usr/include/netdb.h' or die; while (my $line = <$errdb>) { if (my ($symbol, $val) = $line =~ /^\s*\#\s*define\s+([^_]\w+)\s+( +-?\d+)/) { next unless exists $herrno{$symbol}; # skip irrelevant symbols die "FATAL: $symbol = $val - conflicts with $herrno{$val}\n" if exists $herrno{$val}; # Map numeric codes to text strings $herrno{$val} = $herrno{$symbol}; # Provide a symbolic value { no strict 'refs' ; *{$symbol} = sub () { $val; }; } # Export the symbol & add to the NAMES tag push @EXPORT_OK, $symbol; push @{$EXPORT_TAGS{NAMES}}, $symbol; } } # NO_ADDRESS is an alias for NO_DATA sub NO_ADDRESS() { NO_DATA() }; close $errdb or die; } 1; __END__

    This communication may not represent my employer's views, if any, on the matters discussed.

Re: h_errno consants?
by Anonymous Monk on Jun 21, 2009 at 10:21 UTC

      Re: .1 - Yes, I've been there. That confirms that h_errno is returned in $?. I don't see where to get the netdb.h constants or strings. All the detail is about the case where it returns subprocess exit status -- not the value of h_errno.

      Re: .2 - Thanks, but Errno.pm gives the symbolic equivalents of the errno variable. I'm looking for symbolic constants for h_errno. Note the leading h_ - this is the errno-like variable used by the network information database routines.

      This communication may not represent my employer's views, if any, on the matters discussed.

        I don't see the where to get the netdb.h constants or strings.

        Or what you see is that you can't get them from perl :|