@c This is part of the GNU Mailutils manual. @c Copyright (C) 1999-2004, 2006-2007, 2009-2012, 2014-2016 Free @c Software Foundation, Inc. @c See file mailutils.texi for copying conditions. @comment ******************************************************************* @code{Libmu_sieve} is GNU implementation of the mail filtering language Sieve. The library is built around a @dfn{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 @code{libmu_sieve}: @enumerate @item Application program creates the instance of sieve machine. @item Then @code{mu_sieve_compile} function is called to translate the Sieve source into an equivalent program executable by the Machine @item A mailbox is opened and associated with the Machine @item The Machine executes the program over the mailbox @item When the execution of the program is finished, all messages upon which an action was executed other than @code{keep} are marked with the delete flag. Thus, running @code{mailbox_expunge} upon the mailbox finishes the job, leaving in the mailbox only those messages that were preserved by the filter. @item Finally, the instance of Sieve Machine is destroyed and the resources allocated for it are reclaimed. @end enumerate The following sections describe in detail the functions from the Sieve Library. @menu * Sieve Data Types:: * Manipulating the Sieve Machine:: * Logging and Diagnostic Functions:: * String Accessors:: * Argument Accessors:: * Symbol Space Functions:: * Memory Allocation:: * Compiling and Executing the Script:: * Writing Loadable Commands:: @end menu @node Sieve Data Types @subsection Sieve Data Types @deftp {Data Type} mu_sieve_machine_t This is an opaque data type representing a pointer to an instance of sieve machine. The @code{mu_sieve_machine_t} keeps all information necessary for compiling and executing the script. It is created by @code{mu_sieve_machine_create()} and destroyed by @code{mu_sieve_machine_destroy()}. The functions for manipulating this data type are described in @ref{Manipulating the Sieve Machine}. @end deftp @deftp {Data Type} mu_sieve_data_type This enumeration keeps the possible types of sieve data. These are: @table @code @item SVT_VOID No datatype. @item SVT_NUMBER Numeric type. @item SVT_STRING Character string. @item SVT_STRING_LIST A list of strings. @item SVT_TAG A sieve tag. This data type is available only during the compilation. On runtime, all tags are converted to one of the above types, depending on their arguments. Tags without arguments are converted to SVT_VOID. @end table @end deftp @deftp {Data Type} mu_sieve_value_t The @code{mu_sieve_value_t} keeps an instance of sieve data. It is defined as follows: @smallexample @group typedef struct @{ union mu_sieve_value_storage @{ char *string; size_t number; struct mu_sieve_slice list; @}; typedef struct @{ mu_sieve_data_type type; char *tag; union mu_sieve_value_storage v; @} mu_sieve_value_t; @} mu_sieve_value_t; @end group @end smallexample Depending on the value of @code{type} member, following members of the union @code{v} keep the actual value: @table @code @item SVT_VOID No associated value. @item SVT_NUMBER The numeric value is kept in the @code{number} member. @item SVT_STRING_LIST @itemx SVT_STRING The list is identified by the @code{list} member of the union @code{mu_sieve_value_storage}. This member is defined as follows: @example struct mu_sieve_slice @{ size_t first; /* Index of the first string */ size_t count; /* Number of strings */ @}; @end example The @code{first} member identifies the first string in the list. The @code{count} member gives the number of strings in the list. If the data type is @code{SVT_STRING}, @code{count} is guaranteed to be 1. The string itself can be accessed using the @code{mu_sieve_string} function (@pxref{String Accessors}). For example, the following code fragment iterates over all strings in the list: @example size_t i; mu_sieve_value_t *val; for (i = 0; i < val->v.list.count; i++) @{ char *string; string = mu_sieve_string (mach, &val->v.list, i); ... @} @end example @item SVT_TAG Never appears. @end table @end deftp @deftp {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: @smallexample @group typedef struct @{ char *name; /* Tag name */ mu_sieve_data_type argtype; /* Type of tag argument. */ @} mu_sieve_tag_def_t; @end group @end smallexample The @code{name} member points to the tag's name @emph{without leading colon}. The @code{argtype} is set to @code{SVT_VOID} if the tag does not take argument, or to the type of the argument otherwise. @end deftp @deftp {Data Type} mu_sieve_handler_t This is a pointer to function handler for a sieve action or test. It is defined as follows: @smallexample typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t @var{mach}); @end smallexample The @var{mach} argument is the machine being worked upon. The rest of data can be obtained from it. @deftp {Data Type} mu_sieve_action_log_t A pointer to the application-specific logging function: @smallexample typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t @var{mach}, const char *@var{action}, const char *@var{fmt}, va_list @var{ap}); @end smallexample @table @var @item nach The sieve machine. @item action The name of the action. @item fmt A @code{printf}-style format string. @item ap Arguments for the format. @end table @end deftp @deftp {Data Type} mu_sieve_relcmp_t @deftpx {Data Type} mu_sieve_relcmpn_t @smallexample typedef int (*mu_sieve_relcmp_t) (int, int); typedef int (*mu_sieve_relcmpn_t) (size_t, size_t); @end smallexample @end deftp @deftp {Data Type} mu_sieve_comparator_t @smallexample typedef int (*mu_sieve_comparator_t) (const char *, const char *); @end smallexample A pointer to the comparator handler function. The function compares its two operands and returns 1 if they are equal, and 0 otherwise. @emph{Notice}, that the sense of the return value is inverted in comparison with most standard libc functions like @code{stcmp()}, etc. @end deftp @deftp {Data Type} mu_sieve_retrieve_t @smallexample typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx, char **pval); @end smallexample A pointer to generic retriever function. See description of @code{mu_sieve_vlist_compare()} for details of its usage. @end deftp @deftp {Data Type} mu_sieve_destructor_t @smallexample typedef void (*mu_sieve_destructor_t) (void *data); @end smallexample A pointer to destructor function. The function frees any resources associated with @code{data}. See the description of @code{mu_sieve_machine_add_destructor()} for more information. @end deftp @deftp {Data Type} mu_sieve_tag_checker_t @smallexample typedef int (*mu_sieve_tag_checker_t) (const char *@var{name}) @end smallexample A pointer to tag checker function. The purpose of the function is to perform compilation-time consistency test on tags. The function is allowed to make any changes in @var{tags} and @var{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] @end deftp @node Manipulating the Sieve Machine @subsection 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. @deftypefun int mu_sieve_machine_create (mu_sieve_machine_t *@var{mach}) The @code{mu_sieve_machine_create()} function creates an instance of a sieve machine. A pointer to the instance itself is returned in the argument @var{mach}. The function returns 0 on success, and a non-zero error code otherwise. @end deftypefun @deftypefun void mu_sieve_machine_destroy (mu_sieve_machine_t *@var{pmach}) This function destroys the instance of sieve machine pointed to by @var{mach} parameter. After execution of @code{mu_sieve_machine_destroy()} @var{pmach} contains @code{NULL}. The destructors registered with @code{mu_sieve_machine_add_destructor()} are executed in @sc{lifo} order. @end deftypefun @deftypefun int mu_sieve_machine_add_destructor (mu_sieve_machine_t @var{mach}, mu_sieve_destructor_t @var{destr}, void *@var{ptr}); This function registers a destructor function @var{dest}. The purpose of the destructor is to free any resources associated with the item @var{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 @code{mu_sieve_machine_destroy()}. @deftypefun {void *} mu_sieve_get_data (mu_sieve_machine_t @var{mach}) This function returns the application-specific data associated with the instance of sieve machine. See @code{mu_sieve_machine_create()}. @end deftypefun @deftypefun mu_message_t mu_sieve_get_message (mu_sieve_machine_t @var{mach}) This function returns the current message. @end deftypefun @deftypefun size_t mu_sieve_get_message_num (mu_sieve_machine_t @var{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 @code{mu_sieve_message}, this function returns 1. @end deftypefun @deftypefun int mu_sieve_get_debug_level (mu_sieve_machine_t @var{mach}) Returns the debug level set for this instance of sieve machine. @end deftypefun @deftypefun mu_mailer_t mu_sieve_get_mailer (mu_sieve_machine_t @var{mach}) Returns the mailer. @end deftypefun @deftypefun int mu_sieve_get_locus (mu_sieve_machine_t @var{mach}, @ struct mu_locus *@var{locus}) Returns the locus in the Sieve source file corresponding to the code pointer where the Sieve machine currently is. @end deftypefun @deftypefun {char *} mu_sieve_get_daemon_email (mu_sieve_machine_t @var{mach}) This function returns the @dfn{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 @samp{} and the domain part is the machine name. @end deftypefun @deftypefun void mu_sieve_get_diag_stream (mu_sieve_machine_t @var{mach}, @ mu_stream_t *@var{pstr}) Get a reference to the machine's diagnostic stream. The obtained stream must be dereferenced by using @code{mu_stream_unref} or @code{mu_stream_destroy}, when no longer needed. @end deftypefun @deftypefun void mu_sieve_set_diag_stream (mu_sieve_machine_t @var{mach}, mu_stream_t @var{stream} Register @var{stream} as the diagnostic stream for this machine. The reference count of @var{stream} is increased. @end deftypefun @deftypefun void mu_sieve_get_dbg_stream (mu_sieve_machine_t @var{mach}, @ mu_stream_t *@var{pstr}) Get a reference to the machine's debug output stream. The obtained stream must be dereferenced by using @code{mu_stream_unref} or @code{mu_stream_destroy}, when no longer needed. @end deftypefun @deftypefun void mu_sieve_set_dbg_stream (mu_sieve_machine_t @var{mach}, mu_stream_t @var{stream}) Register @var{stream} as the debug output stream for this machine. The reference count of @var{stream} is increased. @end deftypefun @deftypefun void mu_sieve_set_logger (mu_sieve_machine_t @var{mach}, mu_sieve_action_log_t @var{logger}) This function sets the logger function. By default the logger function is @code{NULL}, which means that the executed actions are not logged. @end deftypefun @deftypefun void mu_sieve_set_mailer (mu_sieve_machine_t @var{mach}, mu_mailer_t @var{mailer}) This function sets the mailer. The default mailer is @code{"sendmail:"}. @end deftypefun @deftypefun void mu_sieve_set_daemon_email (mu_sieve_machine_t @var{mach}, const char *@var{email}) This functions sets the @dfn{daemon email} for @code{reject} and @code{redirect} actions. @end deftypefun @deftypefun int mu_sieve_is_dry_run (mu_sieve_machine_t @var{mach}) The @code{mu_sieve_is_dry_run()} returns 1 if the machine is in @dfn{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 @code{mu_sieve_set_debug_level()} if its last argument has the @code{MU_SIEVE_DRY_RUN} bit set. @end deftypefun @deftypefun {const char *} mu_sieve_type_str (mu_sieve_data_type @var{type}) Returns the string representation for the given sieve data type. The return value is a pointer to a static constant string. @end deftypefun @node Logging and Diagnostic Functions @subsection Logging and Diagnostic Functions @deftypefun void mu_sieve_error (mu_sieve_machine_t @var{mach}, const char *@var{fmt}, @dots{}) Format and output an error message using error printer of the machine @var{mach}. @end deftypefun @deftypefun void mu_sieve_debug (mu_sieve_machine_t @var{mach}, const char *@var{fmt}, @dots{}) Format and output a debug message using debug printer of the machine @var{mach}. @end deftypefun @deftypefun void mu_sieve_log_action (mu_sieve_machine_t @var{mach}, const char *@var{action}, const char *@var{fmt}, @dots{}) Log a sieve action using logger function associated with the machine @var{mach}. @end deftypefun @deftypefun void mu_sieve_abort (mu_sieve_machine_t @var{mach}) Immediately abort the execution of the script. @end deftypefun @node String Accessors @subsection String Accessors Strings are stored in a special memory area within the Sieve machine, which is called @dfn{string space}. A string is identified by its index in the string space. Array of strings is represented internally as a contiguous area within the string space that holds one or more strings. An array is identified by the index of its first element and number of elements in it: @example struct mu_sieve_slice @{ size_t first; /* Index of the first object */ size_t count; /* Number of objects */ @}; @end example A single sieve string is represented by an array of strings with zero @code{count}. To obtain actual value of a string, use the @code{mu_sieve_string} function: @deftypefun {char *} mu_sieve_string (mu_sieve_machine_t @var{mach}, @ mu_sieve_slice_t @var{slice}, @ size_t @var{n}) Return actual textual value of the @var{n}th string in the array @var{slice} of the Sieve machine @var{mach}. If the @code{variables} extension is required, the returned value will have variables expanded. @end deftypefun Two functions are provided for manipulating raw string values. Each string in the string space is kept in the following structure: @example typedef struct mu_sieve_string @{ unsigned constant:1; /* String is constant */ unsigned changed:1; /* String value has changed */ char *orig; /* String original value */ char *exp; /* Actual string value after expansion */ void *rx; /* Pointer to the corresponding regular expr */ @} mu_sieve_string_t; @end example All fields in this structure shall be deemed constant. Sieve code (such as new actions or tests) should never try to change any of them. The meaning of its fields is: @deftypecv Field {struct mu_sieve_string} unsigned constant Zero if the string is subject to variable expansion and 1 otherwise. This field is defined when compiling the Sieve script. @end deftypecv @deftypecv Field {struct mu_sieve_string} unsigned changed This field is @samp{1} if the expanded value of the string has changed since it was retrieved for the last time. This is used by the Sieve machine to determine whether the associated regular expression (if any) needs to be recompiled. This field is modified by the string accessor functions. Obviously, if @code{constant == 1}, then @code{changed == 0}. @end deftypecv @deftypecv Field {struct mu_sieve_string} {char *} orig A pointer to the original string value, as it appeared in the Sieve script source file. @end deftypecv @deftypecv Field {struct mu_sieve_string} {char *} exp A pointer to the string value after expansion. Valid only if @code{constant == 0}. @end deftypecv @deftypecv Field {struct mu_sieve_string} {void *} rx Points to the memory area containig the compiled regular expression corresponding to that string. This member is valid, e.g. if the string represents the second argument of a test used with @code{:match} or @code{:regex} tag. @end deftypecv The raw string values are accessed via the following two functions: @deftypefun {mu_sieve_string_t *} mu_sieve_string_raw (mu_sieve_machine_t @var{mach}, @ mu_sieve_slice_t @var{slice}, @ size_t @var{n}) Returns pointer to the structure representing @var{n}th string in slice @var{slice}. A runtime exception is raised if @var{n} is out of range represented by @var{slice}. Extension writers should treat this as a constant object. @end deftypefun @deftypefun {char *} mu_sieve_string_get (mu_sieve_machine_t @var{mach}, @ mu_sieve_string_t *@var{string}) Evaluate @var{string} and return its textual representation. If the @code{variables} extension is required, this function performs variable substitution. @end deftypefun @node Argument Accessors @subsection Argument Accessors @node Symbol Space Functions @subsection Symbol Space Functions @deftypefun {mu_sieve_register_t *} mu_sieve_test_lookup (mu_sieve_machine_t @var{mach}, const char *@var{name}) Find a register object describing the test @var{name}. Returns @code{NULL} if no such test exists. @end deftypefun @deftypefun {mu_sieve_register_t *} mu_sieve_action_lookup (mu_sieve_machine_t @var{mach}, const char *@var{name}) Find a register object describing the action @var{name}. Returns @code{NULL} if no such action exists. @end deftypefun @deftypefun int mu_sieve_register_test (mu_sieve_machine_t @var{mach}, const char *@var{name}, mu_sieve_handler_t @var{handler}, mu_sieve_data_type *@var{arg_types}, mu_sieve_tag_group_t *@var{tags}, int @var{required}) @end deftypefun @deftypefun int mu_sieve_register_action (mu_sieve_machine_t @var{mach}, const char *@var{name}, mu_sieve_handler_t @var{handler}, mu_sieve_data_type *@var{arg_types}, mu_sieve_tag_group_t *@var{tags}, int @var{required}) @end deftypefun @deftypefun int mu_sieve_register_comparator (mu_sieve_machine_t @var{mach}, const char *@var{name}, int @var{required}, mu_sieve_comparator_t @var{is}, mu_sieve_comparator_t @var{contains}, mu_sieve_comparator_t @var{matches}, mu_sieve_comparator_t @var{regex}, mu_sieve_comparator_t @var{eq}) @end deftypefun @deftypefun int mu_sieve_tag_lookup (mu_list_t @var{taglist}, char *@var{name}, mu_sieve_value_t **@var{arg}) @end deftypefun @deftypefun int mu_sieve_load_ext (mu_sieve_machine_t @var{mach}, const char *@var{name}) @end deftypefun @node Memory Allocation @subsection Memory Allocation The following functions act as their libc counterparts. The allocated memory is associated with the @var{mach} argument and is automatically freed upon the call to @code{mu_sieve_machine_destroy (@var{mach})}. @deftypefun {void *} mu_sieve_malloc (mu_sieve_machine_t @var{mach}, size_t @var{size}) Allocates @var{size} bytes and returns a pointer to the allocated memory. @end deftypefun @deftypefun {char *} mu_sieve_strdup (mu_sieve_machine_t @var{mach}, const char *@var{str}) This function returns a pointer to a new string which is a duplicate of the string @var{str}. @end deftypefun @deftypefun {void *} mu_sieve_realloc (mu_sieve_machine_t @var{mach}, void *@var{ptr}, size_t @var{size}) Changes the size of the memory block pointed to by @var{ptr} to @var{size} bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If @var{ptr} is @code{NULL}, the call is equivalent to @code{mu_sieve_malloc(@var{mach}, @var{size})}; if @var{size} is equal to zero, the call is equivalent to @code{mu_sieve_free(@var{ptr})}. Unless @var{ptr} is @code{NULL}, it must have been returned by an earlier call to @code{mu_sieve_malloc()} or @code{mu_sieve_realloc()}. @end deftypefun @deftypefun void mu_sieve_free (mu_sieve_machine_t @var{mach}, void *@var{ptr}) @code{mu_sieve_free()} frees the memory space pointed to by @var{ptr} and detaches it from the destructor list of @var{mach}. The @var{ptr} must have been returned by a previous call to @code{mu_sieve_malloc()} or @code{mu_sieve_realloc()}. Otherwise, or if @code{mu_sieve_mfree(@var{ptr})} has already been called before, undefined behaviour occurs. If @var{ptr} is @code{NULL}, no operation is performed. @end deftypefun @node Compiling and Executing the Script @subsection Compiling and Executing the Script @deftypefun int mu_sieve_compile (mu_sieve_machine_t @var{mach}, const char *@var{name}) Compile the sieve script from the file @var{name}. @end deftypefun @deftypefun int mu_sieve_mailbox (mu_sieve_machine_t @var{mach}, mu_mailbox_t @var{mbox}) Execute the code from the given instance of sieve machine @var{mach} over each message in the mailbox @var{mbox}. @end deftypefun @deftypefun int mu_sieve_message (mu_sieve_machine_t @var{mach}, mu_message_t @var{message}) Execute the code from the given instance of sieve machine @var{mach} over the @var{message}. @end deftypefun @deftypefun int mu_sieve_disass (mu_sieve_machine_t @var{mach}) Dump the disassembled code of the sieve machine @var{mach}. @end deftypefun @node Writing Loadable Commands @subsection Writing Loadable Commands This section contains an example of how to write external loadable commands for GNU libmu_sieve. @smallexample @include numaddr.inc @end smallexample