API Subsets
In order to have a specific set of functions intercepted, libgreat introduces a concept of API Subsets. The intention is that the functions intercepted correspond to various sections of their respected standards, and that we may select subsets of these groups. Let's take a look at rand(), which is intercepted to return constants. You can see this in c99/stdlib_prng.c:
/* C99 7.20.2.1 The rand function */ int rand(void) { if (!great_subset("stdlib:prng:rand") && !great_subset("stdlib:prng:srand")) { return great_c99.rand(); } /* guts of rand() here */ }
great_c99.rand is a pointer to the underlying system's rand(). So our implementation defaults to that if great_subset() says that our particular subset - named stdlib:prng:rand - is not selected for use.
Note also that we only default if srand is also not selected; it makes no sense to have one without the other, as the behaviour would break the standard semantics, since seeding would not produce the same sequence.
So, each function intercepted has a name selected from the list of active subsets. These names are fairly self-explanatory - for example, we have stdlib:memory:malloc, where "memory" is an arbitary group name intended to represent the structure within the C standard.
You can see the subset interface at shared/subset.h.
To select by these names, pass the environment variable $GREAT_SUBSETS, which takes a list of regular expressions. SelectingSubsets explains this from the user's perspective. The logs give a little insight into what's going on here:
clarion% LD_PRELOAD=libgreat_c99.so GREAT_SUBSETS='/:rand$' zsh -c 'echo $RANDOM $RANDOM $RANDOM' Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_RANDOM_SEED INFO: Defaulting to 5489 Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_SUBSETS INFO: Registered subset: /:rand$/ Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:srand DEFAULT Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_PROBABILITY INFO: Defaulting to 0.5 Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:rand DEFAULT Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_PROBABILITY INFO: Defaulting to 0.5 Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:rand [C99 7.20.2.1 P4] IB: Returning constant Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_PROBABILITY INFO: Defaulting to 0.5 Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:rand [C99 7.20.2.1 P4] IB: Returning constant 10962 7 7 clarion%
This overrides the default subset of /./, which matches everything. So in this example, zsh runs without incident, as things like malloc() are left as-is.