# FFI, getutxent question

**URL:** <https://www.ruby-forum.com/t/ffi-getutxent-question/173447>\
**Category:** Ruby\
**Created:** [August 9, 2009, 5:19am UTC](https://www.ruby-forum.com/t/ffi-getutxent-question/173447 "2009-08-09T05:19:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [August 9, 2009, 5:19am UTC](https://www.ruby-forum.com/t/ffi-getutxent-question/173447/1 "2009-08-09T05:19:55Z")

</div>

Hi

According to the man page, the prototypes for getutxent(), setutxent()  
and endutxent() are as follows:

void endutxent(void);  
struct utmpx \* getutxent(void);  
void setutxent(void);

So, I declared them like so:

require ‘ffi’

class Info  
extend FFI::Library

```
attach_function :setutxent, [], :void
attach_function :getutxent, [], :pointer
attach_function :endutxent, [], :void

def self.getstuff
   begin
      setutxent()
      p getutxent() # NULL Pointer ???
   ensure
      endutxent()
   end
end

```

end

Info.getstuff # Null Pointer object

However, the call to getutxent() returns a NULL pointer. I’m guessing I  
have to tell it what kind of pointer to return, but I wasn’t sure how to  
do that. How do I do that?

Regards,

Dan

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [August 9, 2009, 10:54am UTC](https://www.ruby-forum.com/t/ffi-getutxent-question/173447/2 "2009-08-09T10:54:25Z")

</div>

Daniel B. wrote:

> Info.getstuff # Null Pointer object

Your script runs smoothly on my system (Ubuntu Linux) returning a proper  
NativePointer object. It seems that the issue is related to your  
environment rather then FFI.

> However, the call to getutxent() returns a NULL pointer. I’m guessing I  
> have to tell it what kind of pointer to return, but I wasn’t sure how to  
> do that. How do I do that?

You don’t. Once you get a proper pointer object you’ll use it to  
instantiate the Utmpx class:

Utmpx.new(getutxent)

The Utmpx class will be a subclass of FFI::Struct that mirrors the  
layout of the C counterpart. Moreover, as I can see from libc reference  
manual[1], utmpx has nested structs within. The good news is that  
Ruby-FFI has support for nested structs. The bad one is that you have to  
define all the nested structs by hand:

class Pid \< FFI::Struct  
layout …  
end

…

class Utmpx \< FFI::Struct  
layout :ut\_type, :short,  
:ut\_pid, Pid  
…  
end

Regards,  
Andrea

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [August 9, 2009, 3:55pm UTC](https://www.ruby-forum.com/t/ffi-getutxent-question/173447/3 "2009-08-09T15:55:24Z")

</div>

Daniel B. wrote:

> I tried this but I’m still having trouble. Part of the problem may be  
> that I’m not sure how to declare char[] struct members. The docs  
> indicate there’s a :char\_array type, but FFI doesn’t seem to like it.

Yeah, the docs on the Kenai wiki are pretty out of date at the moment.  
We’ll fix them when we’ll finish the migration on github. Basically, you  
can declare array types in this way:

[type, num]

where type can be:

- a native type like :char, :int, :short, …
- a subclass of FFI::Struct

and num is the number of the elements of the array.

I made some changes on your script and I pasted a working version here:

> <https://gist.github.com/remogatto/164777>

Keep in mind that the script is working on my system (Ubuntu 32bit) but  
might not work on yours. Indeed, as you can see looking at the C header  
file “/usr/include/bits/utmpx.h”, there are a bunch of precompiler  
conditional branches that made structs definitions platform-dependent.

Regards,  
Andrea

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [August 9, 2009, 2:22pm UTC](https://www.ruby-forum.com/t/ffi-getutxent-question/173447/4 "2009-08-09T14:22:28Z")

</div>

On Aug 9, 2:54 am, Andrea F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Daniel B. wrote:
> 
> > Info.getstuff # Null Pointer object
> 
> Your script runs smoothly on my system (Ubuntu Linux) returning a proper  
> NativePointer object. It seems that the issue is related to your  
> environment rather then FFI.

Ah, yes. I was on OS X. I tried again on Linux.

> The Utmpx class will be a subclass of FFI::Struct that mirrors the  
> layout of the C counterpart. Moreover, as I can see from libc reference  
> manual[1], utmpx has nested structs within. The good news is that  
> Ruby-FFI has support for nested structs. The bad one is that you have to  
> define all the nested structs by hand:
> 
> class Pid \< FFI::Struct  
> layout …  
> end

Looks like FFI has a :pid\_t type.

I tried this but I’m still having trouble. Part of the problem may be  
that I’m not sure how to declare char[] struct members. The docs  
indicate there’s a :char\_array type, but FFI doesn’t seem to like it.

require ‘ffi’

class Info  
extend FFI::Library

BOOT\_TIME = 2

attach\_function :setutxent, [], :void  
attach\_function :getutxent, [], :pointer  
attach\_function :endutxent, [], :void

class Timeval \< FFI::Struct  
layout(:tv\_sec, :long, :tv\_usec, :long)  
end

class Utmpx \< FFI::Struct  
layout(  
:ut\_user, :char, 32  
:ut\_id, :char, 4  
:ut\_line, :char, 32  
:ut\_pid, :pid\_t,  
:ut\_type, :short,  
:ut\_tv, Timeval  
)  
end

def self.getstuff  
time = nil

```
  begin
     setutxent()
     while ent = Utmpx.new(getutxent())
        if ent[:ut_type] == BOOT_TIME
           time = Time.new(ent[:ut_tv][:tv_sec], ent[:ut_tv]

```

[:tv\_usec])  
break  
end  
end  
ensure  
endutxent()  
end

```
  time

```

end  
end

Info.getstuff

ruby boot\_time.rb  
boot\_time.rb:33:in `[]': NULL Pointer access attempted (FFI::NullPointerError) from boot_time.rb:33:in `getstuff’  
from boot\_time.rb:46

Where line 33 is the ent[:ut\_type] reference.

Any suggestions?

Regards,

Dan
