Libmu_sieve is GNU implementation of the mail filtering language Sieve. The library is built around a Sieve Machine --- an abstract computer constructed specially to handle mail filtering tasks. This computer has two registers: program counter and numeric accumulator; a runtime stack of unlimited depth and the code segment. A set of functions is provided for creating and destroying instances of Sieve Machine, manipulating its internal data, compiling and executing a sieve program.

The following is a typical scenario of using libmu_sieve:

 1. Application program creates the instance of sieve machine.

 2. Then mu_sieve_compile function is called to translate the Sieve source into an equivalent program executable by the Machine

 3. A mailbox is opened and associated with the Machine

 4. The Machine executes the program over the mailbox

 5. When the execution of the program is finished, all messages upon which an action was executed other than keep are marked with the delete flag. Thus, running mailbox_expunge upon the mailbox finishes the job, leaving in the mailbox only those messages that were preserved by the filter.

 6. Finally, the instance of Sieve Machine is destroyed and the resources allocated for it are reclaimed.

The following sections describe in detail the functions from the Sieve Library.

Sieve Data Types
----------------

 -- Data Type: sieve_machine_t
     This is an opaque data type representing a pointer to an instance of sieve machine. The sieve_machine_t keeps all information necessary for compiling and executing the script.

     It is created by sieve_machine_create() and destroyed by sieve_machine_destroy(). The functions for manipulating this data type are described in Manipulating the Sieve Machine.

 -- Data Type: mu_sieve_data_type
     This enumeration keeps the possible types of sieve data. These are:

     SVT_VOID
          No datatype.

     SVT_NUMBER
          Numeric type.

     SVT_STRING
          Character string.

     SVT_STRING_LIST
          A mu_list_t. Each item in this list represents a character string.

     SVT_TAG
          A sieve tag. See mu_sieve_runtime_tag_t below.

     SVT_IDENT
          A character string representing an identifier.

     SVT_POINTER
          An opaque pointer.

 -- Data Type: mu_sieve_value_t
     The mu_sieve_value_t keeps an instance of sieve data. It is defined as follows:

          typedef struct
          {
            mu_sieve_data_type type;        /* Type of the data */
            union {
              char *string;                 /* String value or identifier */
              size_t number;                /* Numeric value */
              mu_list_t list;               /* List value */
              mu_sieve_runtime_tag_t *tag;  /* Tag value */
              void *ptr;                    /* Pointer value */
            } v;
          }
          mu_sieve_value_t;

     Depending on the value of type member, following members of the union v keep the actual value:

     SVT_VOID
          Never appears.

     SVT_NUMBER
          The numeric value is kept in number member.

     SVT_STRING
          The string is kept in string member.

     SVT_STRING_LIST
          The list itself is pointed to by list member

     SVT_TAG
          The tag value is pointed to by tag member.

     SVT_IDENT
          The string member points to the identifier name.

     SVT_POINTER
          The data are pointed to by ptr member.

 -- Data Type: mu_sieve_tag_def_t
     This structure represents a definition of a tagged (optional) argument to a sieve action or test. It is defined as follows:

          typedef struct
          {
            char *name;                 /* Tag name */
            mu_sieve_data_type argtype; /* Type of tag argument. */
          }
          mu_sieve_tag_def_t;

     The name member points to the tag's name without leading colon. The argtype is set to SVT_VOID if the tag does not take argument, or to the type of the argument otherwise.

 -- Data Type: mu_sieve_runtime_tag_t
     This structure represents the tagged (optional) argument at a runtime. It is defined as:

          struct mu_sieve_runtime_tag
          {
            char *tag;                   /* Tag name */
            mu_sieve_value_t *arg;       /* Tag argument (if any) */
          };

     The arg member is NULL if the tag does not take an argument.

 -- Data Type: mu_sieve_locus_t
     Objects of this type represent a location in the Sieve source file:

          typedef struct
          {
            const char *source_file;
            size_t source_line;
          }
          mu_sieve_locus_t;

 -- Data Type: mu_sieve_handler_t

     This is a pointer to function handler for a sieve action or test. It is defined as follows:

          typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t MACH,
                                             mu_list_t ARGS,
                                             mu_list_t TAGS);

     The arguments to the handler have the following meaning:

     mach
          Sieve machine being processed.

     args
          A list of required arguments to the handler

     tags
          A list of optional arguments (tags).

 -- Data Type: mu_sieve_printf_t
     A pointer to a diagnostic output function. It is defined as follows:

          typedef int (*mu_sieve_printf_t) (void *DATA,
                                            const char *FMT, va_list AP);

     data
          A pointer to application specific data.  It is set using the mu_sieve_set_data call.

     fmt
          Printf-like format string.

     ap
          Other arguments.

 -- Data Type: mu_sieve_parse_error_t
     This data type is declared as follows:

          typedef int (*mu_sieve_parse_error_t) (void *DATA,
                                                 const char *FILENAME,
                                                 int LINENO,
                                                 const char *FMT,
                                                 va_list AP);

     It is used to declare error handlers for parsing errors. The application-specific data are passed in the DATA argument. Arguments FILENAME and LINE indicate the location of the error in the source text, while FMT and AP give verbose description of the error.

 -- Data Type: mu_sieve_action_log_t
     A pointer to the application-specific logging function:

          typedef void (*mu_sieve_action_log_t) (void *DATA,
                                                 const mu_sieve_locus_t *LOCUS,
                                                 size_t MSGNO,
                                                 mu_message_t MSG,
                                                 const char *ACTION,
                                                 const char *FMT,
                                                 va_list AP);

     data
          Application-specific data.

     locus
          Location in the Sieve source file.

     script
          Name of the sieve script being executed.

     msgno
          Ordinal number of the message in mailbox, if appropriate. When execution is started using sieve_message(), this argument is zero.

     msg
          The message this action is executed upon.

     action
          The name of the action.

     fmt
     var
          These two arguments give the detailed description of the action.

 -- Data Type: mu_sieve_relcmp_t
 -- Data Type: mu_sieve_relcmpn_t

          typedef int (*mu_sieve_relcmp_t) (int, int);
          typedef int (*mu_sieve_relcmpn_t) (size_t, size_t);

 -- Data Type: mu_sieve_comparator_t

          typedef int (*mu_sieve_comparator_t) (const char *, const char *);

     A pointer to the comparator handler function. The function compares its two operands and returns 1 if they are equal, and 0 otherwise. Notice, that the sense of the return value is inverted in comparison with most standard libc functions like stcmp(), etc.

 -- Data Type: mu_sieve_retrieve_t

          typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx,
                                              char **pval);

     A pointer to generic retriever function. See description of mu_sieve_vlist_compare() for details of its usage.

 -- Data Type: mu_sieve_destructor_t

          typedef void (*mu_sieve_destructor_t) (void *data);

     A pointer to destructor function. The function frees any resources associated with data. See the description of mu_sieve_machine_add_destructor() for more information.

 -- Data Type: mu_sieve_tag_checker_t

          typedef int (*mu_sieve_tag_checker_t) (const char *NAME,
                                                 mu_list_t TAGS,
                                                 mu_list_t ARGS)

     A pointer to tag checker function. The purpose of the function is to perform compilation-time consistency test on tags. Its arguments are:

     name
          Name of the test or action whose tags are being checked.

     tags
          A list of mu_sieve_runtime_tag_t representing tags.

     args
          A list of mu_sieve_value_t representing required arguments to NAME.

     The function is allowed to make any changes in TAGS and ARGS. It should return 0 if the syntax is correct and non-zero otherwise. It is responsible for issuing the diagnostics in the latter case. [FIXME: describe how to do that]

Manipulating the Sieve Machine
------------------------------

This subsection describes functions used to create an instance of the sieve machine, read or alter its internal fields and destroy it.

 -- Function: int mu_sieve_machine_create (mu_sieve_machine_t *MACH)

     The mu_sieve_machine_create() function creates an instance of a sieve machine.  A pointer to the instance itself is returned in the argument MACH. The function returns 0 on success, and a non-zero error code otherwise.

 -- Function: void mu_sieve_machine_destroy (mu_sieve_machine_t *PMACH)

     This function destroys the instance of sieve machine pointed to by MACH parameter. After execution of mu_sieve_machine_destroy() PMACH contains NULL. The destructors registered with mu_sieve_machine_add_destructor() are executed in LIFO order.

 -- Function: int mu_sieve_machine_add_destructor (mu_sieve_machine_t MACH, mu_sieve_destructor_t DESTR, void *PTR);

     This function registers a destructor function DEST. The purpose of the destructor is to free any resources associated with the item PTR. The destructor function takes a single argument --- a pointer to the data being destroyed. All registered destructors are called in reverse order upon execution of mu_sieve_machine_destroy(). Here's a short example of the use of this function:

          static void
          free_regex (void *data)
          {
            regfree ((regex_t*)data);
          }

          int
          match_part_checker (const char *name, list_t tags, list_t args)
          {
            regex_t *regex;

            /* Initialise the regex: */
            regex = mu_sieve_malloc (mach, sizeof (*regex));
            /* Make sure it will be freed when necessary */
            mu_sieve_machine_add_destructor (sieve_machine, free_regex, regex);
            .
            .
            .
          }

 -- Function: void * mu_sieve_get_data (mu_sieve_machine_t MACH)
     This function returns the application-specific data associated with the instance of sieve machine. See mu_sieve_machine_create().

 -- Function: mu_message_t mu_sieve_get_message (mu_sieve_machine_t MACH)
     This function returns the current message.

 -- Function: size_t mu_sieve_get_message_num (mu_sieve_machine_t MACH)
     This function returns the current message number in the mailbox. If there are no mailbox, i.e. the execution of the sieve code is started with mu_sieve_message, this function returns 1.

 -- Function: int mu_sieve_get_debug_level (mu_sieve_machine_t MACH)
     Returns the debug level set for this instance of sieve machine.

 -- Function: mu_ticket_t mu_sieve_get_ticket (mu_sieve_machine_t MACH)
     Returns the authentication ticket for this machine.

 -- Function: mu_mailer_t mu_sieve_get_mailer (mu_sieve_machine_t MACH)
     Returns the mailer.

 -- Function: int mu_sieve_get_locus (mu_sieve_machine_t MACH, mu_sieve_locus_t *LOCUS)
     Returns the locus in the Sieve source file corresponding to the code pointer where the Sieve machine currently is.

 -- Function: char * mu_sieve_get_daemon_email (mu_sieve_machine_t MACH)
     This function returns the daemon email associated with this instance of sieve machine. The daemon email is an email address used in envelope from addresses of automatic reply messages. By default its local part is <MAILER-DAEMON> and the domain part is the machine name.

 -- Function: void mu_sieve_set_error (mu_sieve_machine_t MACH, mu_sieve_printf_t ERROR_PRINTER)
     This function sets the error printer function for the machine. If it is not set, the default error printer will be used. It is defined as follows:

          int
          _sieve_default_error_printer (void *unused, const char *fmt,
                                        va_list ap)
          {
            return mu_verror (fmt, ap);
          }

 -- Function: void mu_sieve_set_parse_error (mu_sieve_machine_t MACH, mu_sieve_parse_error_t P)
     This function sets the parse error printer function for the machine. If it is not set, the default parse error printer will be used. It is defined as follows:

          int
          _sieve_default_parse_error (void *unused,
                                      const char *filename, int lineno,
                                      const char *fmt, va_list ap)
          {
            if (filename)
              fprintf (stderr, "%s:%d: ", filename, lineno);
            vfprintf (stderr, fmt, ap);
            fprintf (stderr, "\n");
            return 0;
          }

 -- Function: void mu_sieve_set_debug (mu_sieve_machine_t MACH, mu_sieve_printf_t DEBUG);
     This function sets the debug printer function for the machine. If it is not set, the default debug printer is NULL which means no debugging information will be displayed.

 -- Function: void mu_sieve_set_debug_level (mu_sieve_machine_t MACH, mu_debug_t DBG, int LEVEL)
     This function sets the debug level for the given instance of sieve machine. The DBG argument is the mu_debug_t object to be used with mailutils library, the LEVEL argument specifies the debugging level for the sieve library itself. It is a bitwise or of the following values:

     MU_SIEVE_DEBUG_TRACE
          Trace the execution of the sieve script.

     MU_SIEVE_DEBUG_INSTR
          Print the sieve machine instructions as they are executed.

     MU_SIEVE_DEBUG_DISAS
          Dump the disassembled code of the sieve machine. Do not run it.

     MU_SIEVE_DRY_RUN
          Do not executed the actions, only show what would have been done.

 -- Function: void mu_sieve_set_logger (mu_sieve_machine_t MACH, mu_sieve_action_log_t LOGGER)
     This function sets the logger function. By default the logger function is NULL, which means that the executed actions are not logged.

 -- Function: void mu_sieve_set_ticket (mu_sieve_machine_t MACH, mu_ticket_t TICKET)
     This function sets the authentication ticket to be used with this machine.

 -- Function: void mu_sieve_set_mailer (mu_sieve_machine_t MACH, mu_mailer_t MAILER)
     This function sets the mailer. The default mailer is "sendmail:".

 -- Function: void mu_sieve_set_daemon_email (mu_sieve_machine_t MACH, const char *EMAIL)
     This functions sets the daemon email for reject and redirect actions.

 -- Function: int mu_sieve_is_dry_run (mu_sieve_machine_t MACH)
     The mu_sieve_is_dry_run() returns 1 if the machine is in dry run state, i.e. it will only log the actions that would have been executed without actually executing them. The dry run state is set by calling mu_sieve_set_debug_level() if its last argument has the MU_SIEVE_DRY_RUN bit set.

 -- Function: const char * mu_sieve_type_str (mu_sieve_data_type TYPE)
     Returns the string representation for the given sieve data type. The return value is a pointer to a static constant string.

Logging and Diagnostic Functions
--------------------------------

 -- Function: void mu_sieve_error (mu_sieve_machine_t MACH, const char *FMT, ...)
     Format and output an error message using error printer of the machine MACH.

 -- Function: void mu_sieve_debug (mu_sieve_machine_t MACH, const char *FMT, ...)
     Format and output a debug message using debug printer of the machine MACH.

 -- Function: void mu_sieve_log_action (mu_sieve_machine_t MACH, const char *ACTION, const char *FMT, ...)
     Log a sieve action using logger function associated with the machine MACH.

 -- Function: void mu_sieve_abort (mu_sieve_machine_t MACH)
     Immediately abort the execution of the script.

Symbol Space Functions
----------------------

 -- Function: mu_sieve_register_t * mu_sieve_test_lookup (mu_sieve_machine_t MACH, const char *NAME)
     Find a register object describing the test NAME. Returns NULL if no such test exists.

 -- Function: mu_sieve_register_t * mu_sieve_action_lookup (mu_sieve_machine_t MACH, const char *NAME)
     Find a register object describing the action NAME. Returns NULL if no such action exists.

 -- Function: int mu_sieve_register_test (mu_sieve_machine_t MACH, const char *NAME, mu_sieve_handler_t HANDLER, mu_sieve_data_type *ARG_TYPES, mu_sieve_tag_group_t *TAGS, int REQUIRED)

 -- Function: int mu_sieve_register_action (mu_sieve_machine_t MACH, const char *NAME, mu_sieve_handler_t HANDLER, mu_sieve_data_type *ARG_TYPES, mu_sieve_tag_group_t *TAGS, int REQUIRED)

 -- Function: int mu_sieve_register_comparator (mu_sieve_machine_t MACH, const char *NAME, int REQUIRED, mu_sieve_comparator_t IS, mu_sieve_comparator_t CONTAINS, mu_sieve_comparator_t MATCHES, mu_sieve_comparator_t REGEX, mu_sieve_comparator_t EQ)

 -- Function: int mu_sieve_tag_lookup (mu_list_t TAGLIST, char *NAME, mu_sieve_value_t **ARG)

 -- Function: int mu_sieve_load_ext (mu_sieve_machine_t MACH, const char *NAME)

Memory Allocation
-----------------

The following functions act as their libc counterparts. The allocated memory is associated with the MACH argument and is automatically freed upon the call to mu_sieve_machine_destroy (MACH).

 -- Function: void * mu_sieve_malloc (mu_sieve_machine_t MACH, size_t SIZE)
     Allocates SIZE bytes and returns a pointer to the allocated memory.

 -- Function: char * mu_sieve_strdup (mu_sieve_machine_t MACH, const char *STR)
     This function returns a pointer to a new string  which is a duplicate of the string STR.

 -- Function: void * mu_sieve_realloc (mu_sieve_machine_t MACH, void *PTR, size_t SIZE)
     Changes the size of the memory block pointed to by PTR to SIZE bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If PTR is NULL, the call is equivalent to mu_sieve_malloc(MACH, SIZE); if SIZE is equal to zero, the call is equivalent to mu_sieve_free(PTR). Unless PTR is NULL, it must have been returned by an earlier call to mu_sieve_malloc() or mu_sieve_realloc().

 -- Function: void mu_sieve_free (mu_sieve_machine_t MACH, void *PTR)
     mu_sieve_free() frees the memory space pointed to by PTR and detaches it from the destructor list of MACH. The PTR must have been returned by a previous call to mu_sieve_malloc() or mu_sieve_realloc(). Otherwise, or if mu_sieve_mfree(PTR) has already been called before, undefined behaviour occurs.

     If PTR is NULL, no operation is performed.

Compiling and Executing the Script
----------------------------------

 -- Function: int mu_sieve_compile (mu_sieve_machine_t MACH, const char *NAME)
     Compile the sieve script from the file NAME.

 -- Function: int mu_sieve_mailbox (mu_sieve_machine_t MACH, mu_mailbox_t MBOX)
     Execute the code from the given instance of sieve machine MACH over each message in the mailbox MBOX.

 -- Function: int mu_sieve_message (mu_sieve_machine_t MACH, mu_message_t MESSAGE)
     Execute the code from the given instance of sieve machine MACH over the MESSAGE.

 -- Function: int mu_sieve_disass (mu_sieve_machine_t MACH)
     Dump the disassembled code of the sieve machine MACH.

Writing Loadable Commands
-------------------------

This section contains an example of how to write external loadable commands for GNU libmu_sieve.

          [file numaddr.inc not included]