Hi all,
Ruby 1.6.7 on Solaris 8
I’m writing an extension that simply returns the hostname or ip addresses
for a given host. I’m having a problem with core dumps, however, and I
think it’s because I’m not wrapping the return value from hptr->h_addr_list
(a pointer to an array of pointers that contain in_addr{}). I’ve tried a
few things and though it will compile, it continues to core dump/seg fault.
Any ideas? Here’s my source (including extconf.rb source in comments):
/* my extconf.rb:
require ‘mkmf’
Solaris needs the socket lib to work
if RUBY_PLATFORM =~ /solaris/
have_library(‘socket’)
have_library(‘nsl’)
end
create_makefile(‘sys/host’)
*/
#include “ruby.h”
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#ifdef __cplusplus
extern “C”
{
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
VALUE cHost;
static void host_free(void* p)
{
free§;
}
static VALUE host_hostname()
{
char h[MAXHOSTNAMELEN];
int rv;
rv = gethostname(h,sizeof(h));
if(rv != 0){
rb_exit(INT2NUM(rv));
}
return rb_str_new2(h);
}
static VALUE host_ip_addr()
{
char h[MAXHOSTNAMELEN];
char str[INET_ADDRSTRLEN];
char *pptr;
struct hostent hp;
int rv;
Data_Wrap_Struct(cHost,0,host_free,hp);
rv = gethostname(h,sizeof(h));
if(rv != 0){
rb_exit(INT2NUM(rv));
}
hp = gethostbyname(h);
pptr = hp->h_addr_list;
Data_Wrap_Struct(cHost,0,host_free,pptr); /* problem here? */
if( rb_block_given() ){
rb_yield(rb_str_new2(inet_ntop(hp->h_addrtype,*pptr,str,sizeof(str))));
}
else{
VALUE results = rb_ary_new();
for( ; *pptr != NULL; pptr++){
rb_ary_push(results,rb_str_new2(inet_ntop(hp->h_addrtype,*pptr,str,sizeof(st
r))));
}
return results;
}
}
void Init_host()
{
VALUE sys_mSys;
sys_mSys = rb_define_module(“Sys”);
cHost = rb_define_class_under(sys_mSys, “Host”, rb_cObject);
rb_define_singleton_method(cHost, “hostname”, host_hostname, 0);
rb_define_singleton_method(cHost, “ip_addr”, host_ip_addr, 0);
}
#ifdef __cplusplus
}
#endif
···
==============
Here’s some equivalent C source code (that works, btw):
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
/* Compile with -lsocket option to gcc on Solaris or it will fail */
int main(){
long addr;
char *ptr, **pptr;
char str[INET_ADDRSTRLEN];
struct hostent* hp;
hp = gethostbyname(“v55host11.interprise.com”);
printf(“Address length: %i\n”, hp->h_length);
printf(“Name: %s\n”, hp->h_name);
pptr = hp->h_addr_list;
for( ; *pptr != NULL; pptr++){
printf(“Address: %s\n”, inet_ntop(hp->h_addrtype, *pptr, str,
sizeof(str)));
}
return 1;
}