From: "Mr. Sunblade" Date: 2002-06-11T23:47:35+09:00 Subject: hostent extension problem - returning the ip address 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 #include #include #ifdef __cplusplus extern "C" { #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif VALUE cHost; static void host_free(void* p) { free(p); } 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 #include #include /* 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; }