Wednesday, September 08, 2010

[Book review] The Art of Unix Programming

Long time I wrote about a book here.
The Art of Unix Programming by Eric Steve Raymond
well, I honestly like such books on philosophy of Unix, the right way
of doing things on Unix etc ... :)
you may still feel that the review on Amazon where someone said ESR `paints
a 1 sided picture` is right. But there are numerous things which cannot be found
in any other place.
We have "Unix design patterns", "conventions for Unix command line options" etc
The "Rules" of Unix are very neatly explained.
And for the light relief, we have "Rootless root" :), which is also available on
ESR's website, my favorite is the one on GUI :-D LOL!

And I love the cover page image - of the Zen master teaching to the novice :)

And what else ? ... am I forgetting something!?, ... let me read it again! :)

Friday, July 16, 2010

AUTOLOAD in C

Recently, I attended a Perl training on Advanced Perl
(actually, I attended just to kill time, and most of the
subject matter being covered there was known to me :) )
and when learning perl modules, I came across AUTOLOAD

In brief, AUTOLOAD is like a default in a module, when one
tries to invoke a function which is not implemented in the
module, perl calls the function with name AUTOLOAD
passing the function name.
Having AUTOLOAD gives rise to interesting uses - atleast in
Perl. One can handle multiple calls in AUTOLOAD giving the
impression that there are lot of functions defined in the
library - especially useful when method names are like
get_a() get_b() get_c() etc.

I was trying to implement this in C, and its pretty
straight forward. All we need is a dynamic library and a
a default handler - which we shall call catch_all()
The only difference here would be, the responsibility
to call catch_all() will be with the invoker of the lib
(maybe this can be hidden behind neat APIs)

Lets create a library with a function and a catch_all

/* sotest.c */
#include
#include

void name1 ()
{
printf ("\n SOTEST: called %s\n", __FUNCTION__);
}
/* this is our AUTOLOAD method, which takes 1 param - name */
void catch_all (char *name)
{
/* If someone tried to call method hello() in this module */
if (0 == strcmp(name, "hello")) {
printf ("\n SOTEST: called hello()\n");
} else
printf ("\n SOTEST: %s, %s()\n", __FUNCTION__, name);
}

make lib: gcc -c -fPIC sotest.c; gcc -shared -fPIC -o libsotest.so sotest.o

Now for the invoker:

/* callso.c */
#include
#include

int main (int argc, char *argv[])
{
void *handle, (*fp)() = NULL, (*gfp)() = NULL;
char *fname = NULL;

if (argc <>\n", argv[0]);
exit (1);
}
fname = argv[1]; /* The function to be invoked in the lib */

handle = dlopen("./libsotest.so", RTLD_LOCAL | RTLD_LAZY);

fp = dlsym(handle, fname);
if (fp) {
fp(); /* If the named function exists, invoke it */
} else {
gfp = dlsym(handle, "catch_all");
gfp ? gfp(fname): 0; /* call the default handler if not */
}

return 0;
}

compile: gcc -L. callso.c -lsotest -ldl # Assume current dir, set LD_LIBRARY_PATH

Simple !. isn't it ? :)