Next: , Up: mfmod   [Contents][Index]


4.25.1 Loadable Library

External functions in the loadable library must be declared as

int funcname(long count, MFMOD_PARAM *param, MFMOD_PARAM *retval);

The MFMOD_PARAM type is declared in the header file mailfromd/mfmod.h, which must be included at the start of the source code.

mfmod type: MFMOD_PARAM type string number

This type is defined as follows:

typedef struct mfmod_param {
        mfmod_data_type type;
        union {
                char *string;
                long number;
                mu_message_t message;
        };
} MFMOD_PARAM;

The type fields defines the type of the data represented by the object. Its possible values are:

mfmod constant: mfmod_string

String data.

mfmod constant: mfmod_number

Numeric data.

mfmod constant: mfmod_message

A mailutils message object (mu_message_t).

The actual data are accessed as string, number, or message, depending on the value of type.

The first parameter in the external function declaration, count, is the number of arguments passed to that function. Actual arguments are passed in the MFMOD_PARAM array param. The function should never modify its elements. If the function returns a value to MFL, it must pass it in the retval parameter. For example, the following code returns the numeric value ‘1’:

retval->type = mfmod_number;
retval->number = 1;

To return a string value, allocate it using malloc, calloc or a similar function, like this:

retval->type = mfmod_string;
retval->string = strdup("text");

If a message is returned, it should be created using mailutils message creation primitives. Mailutils will call mu_message_destroy on it, when it is no longer used.

The return value (in the C sense) of the function is used to determine whether it succeeded or not. Zero means success. Returning -1 causes a runtime exception e_failure with a generic error text indicating the names of the module and function that caused the exception. Any other non-zero value is treated as a mailfromd exception code (see Exceptions). In this case an additional textual explanation of the error can be supplied in the retval variable, whose type must then be set to mfmod_string. This explanation string must be allocated using malloc.

To facilitate error handling, the following functions are provided (declared in the mailfromd/mfmod.h header file):

mfmod: int mfmod_error (MFMOD_PARAM *retval, int ecode, char const *fmt, ...)

Raises exception ecode with the error message formatted from the variadic arguments using printf-style format string fmt.

Example use:

if (error_condition)
   return mfmod_error(retval, "error %s occurred", error_text);
mfmod: int mfmod_error_argtype (MFMOD_PARAM *param, MFMOD_PARAM *retval, int n, int exptype)

Reports argument type mismatch error (e_inval with appropriately formatted error text). Arguments are:

param
retval

The two arguments passed to the interface function.

n

0-based index of the erroneous argument in param.

exptype

Expected data type of param[n].

You will seldom need to use this function directly. Instead, use the ASSERT_ARGTYPE macro described below.

mfmod: char const * mfmod_data_type_str(mfmod_data_type type)

Returns the MFL name of the mfmod data type type.

The following convenience macros are provided for checking the number of argument and their types and returning error if necessary:

mfmod macro: ASSERT_ARGCOUNT (MFMOD_PARAM *retval, long count, long expcount)

Assert that the number of arguments (count) equals the expected number (expcount). If it does not, return the e_inval exception with a descriptive error text.

retval and count are corresponding arguments from the calling function.

mfmod macro: ASSERT_ARGTYPE (MFMOD_PARAM *param, MFMOD_PARAM *retval, int n, int exptype)

Check if the data type of the nth parameter (i.e. param[n]) is exptype and return the e_inval exception if it does not.

As an example, suppose you want to write an interface to the system crypt function. The loadable library source, mfmod_crypt.c, will look as follows:

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mailfromd/mfmod.h>
#include <mailfromd/exceptions.h>

/*
 * Arguments:
 *   param[0] - key string to hash.
 *   param[1] - salt value.
 */
int
cryptval(long count, MFMOD_PARAM *param, MFMOD_PARAM *retval)
{
     char *hash;

     /* Check if input arguments are correct: */
     ASSERT_ARGCOUNT(retval, count, 2);
     ASSERT_ARGTYPE(param, retval, 0, mfmod_string);
     ASSERT_ARGTYPE(param, retval, 1, mfmod_string);

     /* Hash the key string. */
     hash = crypt(param[0].string, param[1].string);

     /* Return string to MFL */
     retval->type = mfmod_string;
     retval->string = strdup(hash);

     /* Throw exception if out of memory */
     if (retval->string == NULL)
          return -1;

     return 0;
}

The exact way of building a loadable library from this source file depends on the operating system. For example, on GNU/Linux you would do:

cc -shared -fPIC -DPIC -omfmod_crypt.so -lcrypt mfmod_crypt.c

The preferred and portable way of doing so is via libtool (see Shared library support for GNU in Libtool). Mailfromd provides a special command mfmodnew that creates infrastructure necessary for building loadable modules. See mfmodnew.


Next: , Up: mfmod   [Contents][Index]