tl;dr
this works with the GNU version of libc (haven't tried it with uclibc yet)
from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
_fields_ = [ ('sysname', c_char * 65),
('nodename', c_char * 65),
('release', c_char * 65),
('version', c_char * 65),
('machine', c_char * 65),
('domain', c_char * 65) ]
gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.nodename
The following code segfaults; I'm not sure what I'm doing wrong.
from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
_fields_ = [ ('sysname', c_char_p),
('nodename', c_char_p),
('release', c_char_p),
('version', c_char_p),
('machine', c_char_p) ]
utsname = uts_struct()
libc.uname(byref(utsname))
print utsname.sysname
This does the same thing:
from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
_fields_ = [ ('sysname', c_char_p),
('nodename', c_char_p),
('release', c_char_p),
('version', c_char_p),
('machine', c_char_p) ]
utsname = uts_struct()
utsname_pointer = pointer(utsname)
libc.uname(utsname_pointer)
print utsname.sysname
I must be messing up something basic...
(I am aware of os.uname()
, this is just an exercise in understanding, which I am failing)
I referenced the uname manual here: http://www.cl.cam.ac.uk/cgi-bin/manpage?2+uname
What am I doing wrong?
Edit:
Thanks to Nemo I'm able to get the data;
>>> from ctypes import *
>>> libc = CDLL('libc.so.6')
>>> gnar = create_string_buffer(512)
>>> libc.uname(byref(gnar))
0
>>> print gnar.value
Linux
>>>
However, I'm assuming I'm only getting 'Linux' because the items are NULL delimited, as are regulator strings. Any way to read past the NULL?
Edit2:
Based on Nemos comment, I've tried this- which doesn't work, but I thought it might be a step in the right direction... errors with:
Traceback (most recent call last):
File "gnar.py", line 18, in <module>
utsname = uts_struct(gnar)
TypeError: incompatible types, c_char_Array_512 instance instead of c_char_p instance
Is this just un-doable?
from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
_fields_ = [ ('sysname', c_char_p),
('nodename', c_char_p),
('release', c_char_p),
('version', c_char_p),
('machine', c_char_p) ]
gnar = create_string_buffer(512)
libc.uname(byref(gnar))
utsname = uts_struct(gnar)
Edit3: ( im going for the longest post ever... =P )
from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
_fields_ = [ ('sysname', c_char * 65),
('nodename', c_char * 65),
('release', c_char * 65),
('version', c_char * 65),
('machine', c_char * 65) ]
gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.machine
This works, however, it segfaults after it prints the value...
Final edit:
The following works- I am of course using the GNU version of libc. (im on an Ubuntu machine) so adding the field for the domain is all it took to stop the segfault. It makes sense in hind sight. :)
from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
_fields_ = [ ('sysname', c_char * 65),
('nodename', c_char * 65),
('release', c_char * 65),
('version', c_char * 65),
('machine', c_char * 65),
('domain', c_char * 65) ]
gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.nodename
According to this uname man page, The structure contains arrays of implementation-defined size, not char* (c_char_p). Have you looked at the structure definition in sys/utsname.h
? You have to match the exact structure definition. The data type should probably be c_char * n
where n is the size of the array from that field found in sys/utsname.h
.
Alternatively, you should be able to access all the strings in your first Edit by using print gnar.raw
, as long as the buffer is big enough for the whole structure.