So I’m making some headway on a kerberos 5 extension for ruby. It’s
limited at the moment to authorizing a user, changing a user password,
creating principals, and deleting principals, but it’s working. Now
I’m trying to refactor it a bit and need some assistance. I’ve never
really coded in C before so bear with me…
In kerberos when doing an administration function I first need to
initialize the system with the credentials of an administrative user
like so, with handle being a void pointer initialized to NULL. The
following kerberos function will fill handle with a handle for the
connection which I can use in subsequent calls to other kadm5
functions.
kadm5_init_with_password(auser, apass, KADM5_ADMIN_SERVICE, NULL,
KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &handle);
Now what I’d like is to return that handle to ruby and be able to pass
it back into my C extension when it’s needed, such as when needing to
call the following kerberos function.
kadm5_create_principal(handle, &princ, mask, pass);
So how would I do this? If I understand void pointers correctly,
handle could be any type after the call to kadm5_init_with_password,
so it seems I would want to check it’s type after it’s set, then find
the right type/structure to convert it to or wrap it in before passing
it back to ruby? Not that I know how to do that:)
Chris
On 9/18/06, snacktime [email protected] wrote:
it back to ruby? Not that I know how to do that:)
Chris
Void* is almost always the same size as the native integer. (There is
legitimate controversy over this point but you can depend on it for all
ends
and intents.) So when the kerb function returns having filled in your
void*,
you can cast it to a native unsigned and then pass it back to Ruby as a
VALUE returned from INT2NUM. (I wouldn’t use INT2FIX because you’ll need
all
of the native resolution.) To pass the value back into C, convert it to
an
int with NUM2INT and cast to a void*. I would expect (but can’t say for
sure) that this will work on 64-bit platforms (where void* is eight
bytes
wide) as long as the Ruby conversion functions are defined on the native
integer.
Better to wrap it as a data type in Ruby, which gives you a ruby VALUE
which references the native data. There’s a simple macro to grab the
original pointer given the VALUE.
DEC Alpha doesn’t necessarily have sizeof(int) == sizeof(void *), so
please don’t assume so. I hate fixing code that does that.
Aria (A kerberos user, too!)
Well I’ll do the grunt work and then when I release it I’ll accept
patches from those with more C experience than I have. I actually
can’t remember if I ever wrote a C program before, but I’ve been
meaning to learn it so I figured this was as good a project as any
since we have some use for kerberos bindings.
On Tue, 2006-09-19 at 03:39 +0900, Francis C. wrote:
KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &handle);
the right type/structure to convert it to or wrap it in before passing
it back to ruby? Not that I know how to do that:)
Void* is almost always the same size as the native integer. (There is
legitimate controversy over this point but you can depend on it for all ends
and intents.)
Better to wrap it as a data type in Ruby, which gives you a ruby VALUE
which references the native data. There’s a simple macro to grab the
original pointer given the VALUE.
DEC Alpha doesn’t necessarily have sizeof(int) == sizeof(void *), so
please don’t assume so. I hate fixing code that does that.
Aria (A kerberos user, too!)
On 9/18/06, Aredridel [email protected] wrote:
DEC Alpha doesn’t necessarily have sizeof(int) == sizeof(void *), so
please don’t assume so. I hate fixing code that does that.
It’s been over five years since the last time I programmed an Alpha in
C. Do
you have Ruby running on yours? Are you running DEC/Unix on them? As I
recall, pointers are always a flat 64-bits on Alpha but ints come in
several
flavors, so you would have to cast the void* carefully to keep from
narrowing it, but it would fit just fine in a Ruby Bignum.
Are you suggesting to use StringValue and StringValuePtr, and treat the
void* as a char*?
One more unrelated question. I’m trying to think of the best way to
do the interface, particularly how to access error messages and what
to return to the caller. For most functions the caller just needs to
know if the function returned true, or if there was an error a way to
get the error message. So, I could for example return 0 on success or
the error message number on failure. Or I could return true/false,
store any error message number in a C global variable, and then have a
function which returns the text error message if the original function
returned false.
The latter seems more intuitive. For example
krb = Krb5.new
if krb.authenticate_with_password(user,pass)
authenticated
else
p krb.errstr
end
As opposed to:
res = krb.authenticate(user,pass)
if res == 0
authenticated
else
p krb.errstr(res)
end
And in the case where a method returns a handle that will be used
later, I’m thinking return the handle on success, and on failure
return nil and make the error available via krb.errstr?
Chris
On 9/18/06, snacktime [email protected] wrote:
The latter seems more intuitive. For example
And in the case where a method returns a handle that will be used
later, I’m thinking return the handle on success, and on failure
return nil and make the error available via krb.errstr?
I’m guessing because I haven’t seen your code but I’d say it’s much
more Ruby-esque to return a boolean value rather than a zero (which
Ruby evaluates true). Hiding the error string behind an accessor makes
sense if it will be accessed infrequently. You do have to remember to
clear it on every call into your extension.
Why make your user touch the handle at all? Can you hide it inside
your Krb5 objects with instance_eval, and just supply it yourself when
you need to pass it to the kerb library?
Why make your user touch the handle at all? Can you hide it inside
your Krb5 objects with instance_eval, and just supply it yourself when
you need to pass it to the kerb library?
I’m not picturing this for some reason, can you elaborate?
Chris