Specifications
CHAPTER 5. IMPLEMENTATION 39
Each stage is realized by a specific component of the Input Abstraction Layer daemon.
Functions for the first and fifth stage are implemented by the module loader. Stage one
performs the detection and verification of available modules. Each valid module is added to a
double linked list. Once the modules are detected, stage two is invoked. The configuration file
parser is responsible for setting up the configuration for both the daemon and the modules.
This applies to the parser of the command line options, too. The command line parser is
invoked at the third stage. At this point everything but the D-BUS environment is set up.
The daemon establishes a connection to the system message bus and creates the abstract
output interface at the fourth stage. Afterwards, the modules are started (stage five) and the
daemon enters the event loop (stage six).
Module Loader
The daemon’s linchpin is the implementation of the module loader. The module loader provides
the functionality to add and remove modules avoiding a recompilation of the whole daemon.
This fact makes the Input Abstraction Layer flexible to a high degree. As discussed, the
modules are implemented as dynamically loaded shared libraries. The dynamic linking of
the modules involves the following problem: at compile time the daemon can not make any
assumptions about the modules available at run time. Thus, the daemon needs to detect the
modules at start up.
The daemon invokes the detection by calling the function modules scan() of the module
loader. This function validates all shared object files (file extension .so) in the directory
MODULE DIR. The macro MODULE DIR is determined at compile time. It defines the directory
where mo dules of the Input Abstraction Layer are located. By default, MODULE DIR is set to
/usr/lib/ial/modules. Once modules scan() has found a file with the extension .so, the
verification routine module verify() gets invoked. As a parameter, the file which has to be
verified needs to be passed to module verify():
gboolean module_verify(char *filename);
As discussed in Section §5.3, an Input Abstraction Layer module has to define the function
mod get data(). The function module verify() determines if the given file filename provides
the symbol mod get data by using the module loader’s function dl function(). The two
arguments filename and symbol have to be passed to dl function():
void *dl_function(char *filename, const char *symbol);
First, dl function() determines if the file filename actually is a shared object file. This
check is realized by using dlopen(3). If the given file is not a shared object, dlopen returns
NULL—the verification failed. Otherwise, if the file is a shared object dlopen loads the shared
object and returns a handle (void pointer). This handle is used to examine if the shared object
provides the required symbol mod get data. To accomplish this check, dlsym(3) is used. As
function arguments, dlsym requires the handle provided by dlopen and the symbol symbol
passed to the function dl function(). On success, dlsym returns the address where symbol
mod get data is loaded into memory. This address corresponds to a function pointer of the
module’s function mod get data(). Figure 5.5 shows the module verification. A module must