# Trying to bind to pwd.h/getpwent\_r

**URL:** <https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057>\
**Category:** Help & Support\
**Created:** [August 5, 2024, 3:13pm UTC](https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057 "2024-08-05T15:13:11Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [August 5, 2024, 3:13pm UTC](https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057/1 "2024-08-05T15:13:11Z")

</div>

Hey everyone,  
This is my first attempt to write a binding to LibC, I appreciate any guidance.  
Specifically, I am trying to write a C binding to getpwent\_r - the documentation is here: [getpwent\_r(3) - Linux manual page](https://www.man7.org/linux/man-pages/man3/getpwent_r.3.html)

I have been trying to use [crystal/src/crystal/system/unix/user.cr at master · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/blob/master/src/crystal/system/unix/user.cr) as reference.

Here’s what I have so far:

```auto
lib LibC
  fun getpwent_r(pwstore : Passwd*, buf : Int32*, bufsize : LibC::SizeT, result : Passwd**) : LibC::Int
end

pwd = uninitialized LibC::Passwd
pwd_pointer = Pointer(LibC::Passwd).null
buf = uninitialized Int32
LibC.getpwent_r(pointerof(pwd), pointerof(buf), 4096, pointerof(pwd_pointer)).tap do
  puts pwd_pointer.value
end

```

I run it with a simple:

```auto
crystal run src/lib_nss3/lib_nss3.cr

```

Output:

```auto
LibC::Passwd(@pw_name=Pointer(UInt8)@0x7ffe150b721c, @pw_passwd=Pointer(UInt8)@0x7ffe150b7221, @pw_uid=0, @pw_gid=0, @pw_gecos=Pointer(UInt8)@0x7ffe150b7227, @pw_dir=Pointer(UInt8)@0x7ffe150b722e, @pw_shell=Pointer(UInt8)@0x7ffe150b722e)

```

I was expecting to get a list of users from the system, what am I missing to get to that ?

---

<div class="post-metadata">

**Author:** ![sol.vin](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/sol.vin/32/73_2.png) [@sol.vin](https://forum.crystal-lang.org/u/sol.vin)\
**Post date:** [August 5, 2024, 3:34pm UTC](https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057/2 "2024-08-05T15:34:04Z")

</div>

1. It seems like it’s replying with what you want, most often `Pointer(UInt8)` is actually a string, try reading it like that using `String.new` ([docs](https://crystal-lang.org/api/1.13.1/String.html#new%28chars%3APointer%28UInt8%29%2Cbytesize%2Csize%3D0%29-class-method))
2. You may want to bind `getpwent` instead as the [docs](https://man7.org/linux/man-pages/man3/getpwent_r.3.html#NOTES) for `getpwent_r` warn that

```auto
       The function getpwent_r() is not really reentrant since it shares
       the reading position in the stream with all other threads.

```

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [August 5, 2024, 4:40pm UTC](https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057/3 "2024-08-05T16:40:33Z")

</div>

thank you so much @sol.vin !

So now I have this:

```auto
lib LibC
  fun setpwent
  fun getpwent_r(pwstore : Passwd*, buf : Int32*, bufsize : LibC::SizeT, result : Passwd**) : LibC::Int
  fun endpwent
end

pwd = uninitialized LibC::Passwd
pwd_pointer = Pointer(LibC::Passwd).null
buf = uninitialized Int32

LibC.setpwent # start from the beginning of the file
while LibC.getpwent_r(pointerof(pwd), pointerof(buf), 4096, pointerof(pwd_pointer)) == 0
  username = String.new(pwd_pointer.value.@pw_name)
  uid = pwd_pointer.value.@pw_uid
  puts "#{username},#{uid}"

end
LibC.endpwent # close password database

```

and output:

```auto
crystal run src/lib_nss3/lib_nss3.cr 
root(�2�,0
bin,2
sys,3
man,6
lp,7
mail(�2�,8
news(�2�,9
irc,39
Invalid memory access (signal 11) at address 0x6e69676f6c
[0x55f195df9b36] *Exception::CallStack::print_backtrace:Nil +118 in /home/weirdbricks/.cache/crystal/crystal-run-lib_nss3.tmp
[0x55f195de9016] ~procProc(Int32, Pointer(LibC::SiginfoT), Pointer(Void), Nil) +310 in /home/weirdbricks/.cache/crystal/crystal-run-lib_nss3.tmp
Program exited because of an invalid memory access

```

The list of users is incomplete. Would you happen to know why I see those weird characters and why I’m getting that error?

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [August 5, 2024, 8:33pm UTC](https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057/4 "2024-08-05T20:33:24Z")

</div>

`buf` needs to be bigger. `Int32` is just 4 bytes. But you’re telling `getpwent_r` the buffer size would be 4096 bytes. This leads to corrupted strings and eventually invalid memory access.

Try `buf = uninitialized StaticArray(UInt8, 4096)` instead.  
Also the data type of `buf` is `char*` which equals to `UInt8*` in Crystal.

This works:

```cr
lib LibC
  fun setpwent
  fun getpwent_r(pwstore : Passwd*, buf : LibC::Char*, bufsize : LibC::SizeT, result : Passwd**) : LibC::Int
  fun endpwent
end

pwd = uninitialized LibC::Passwd
pwd_pointer = Pointer(LibC::Passwd).null
buf = uninitialized StaticArray(UInt8, 4096)

LibC.setpwent # start from the beginning of the file
while LibC.getpwent_r(pointerof(pwd), buf, buf.size, pointerof(pwd_pointer)) == 0
  username = String.new(pwd_pointer.value.@pw_name)
  uid = pwd_pointer.value.@pw_uid
  puts "#{username},#{uid}"

end
LibC.endpwent # close password database

```

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [August 6, 2024, 2:05am UTC](https://forum.crystal-lang.org/t/trying-to-bind-to-pwd-h-getpwent-r/7057/5 "2024-08-06T02:05:12Z")

</div>

it works! thank you so much @straight-shoota
