<!DOCTYPE html PUBLIC "XSLT-compat"> <html lang="en-GB"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" type="text/css" href="../../../../common.css"> <meta name="author" content="The Exim Project. <http://www.exim.org/>"> <meta name="copyright" content="Copyright ©2010 The Exim Project. All rights reserved"> <meta name="description" content="Exim is a message transfer agent (MTA) developed at the University of Cambridge for use on Unix systems connected to the Internet."> <meta name="keywords" content="exim,smtp,mta,email"> <meta name="robots" content="noodp,noydir,index,follow"> <meta name="viewport" content="width=device-width"> <title>42. Adding a local scan function to Exim</title> <link rel="stylesheet" type="text/css" href="../../../../doc/chapter.css"> <link rel="canonical" href="http://www.exim.org/exim-html-current/doc/html/spec_html/ch42.html"> </head> <body> <h1 id="header"><a href="../../../..">Exim Internet Mailer</a></h1> <div id="outer"> <ul id="nav_flow" class="nav"> <li><a href="../../../../index.html">Home</a></li> <li><a href="../../../../mirrors.html">Download</a></li> <li><a href="../../../../docs.html">Documentation</a></li> <li><a href="../../../../maillist.html">Mailing Lists</a></li> <li><a href="http://wiki.exim.org/">Wiki</a></li> <li><a href="http://www.exim.org/bugzilla/">Bugs</a></li> <li><a href="../../../../credits.html">Credits</a></li> <li class="search"><form action="http://www.google.com/search" method="get"> <span class="search_field_container"><input type="search" name="q" placeholder="Search Docs" class="search_field"></span><input type="hidden" name="hl" value="en"><input type="hidden" name="ie" value="UTF-8"><input type="hidden" name="as_qdr" value="all"><input type="hidden" name="q" value="site:www.exim.org"><input type="hidden" name="q" value="inurl:exim-html-current"> </form></li> </ul> <div id="inner"><div id="content"> <a class="previous_page" href="ch41.html"><-previous</a><a class="next_page" href="ch43.html">next-></a><div id="chapter" class="chapter"> <h2 id="CHAPlocalscan" class="">Chapter 42 - Adding a local scan function to Exim</h2> <p> In these days of email worms, viruses, and ever-increasing spam, some sites want to apply a lot of checking to messages before accepting them. </p> <p> The content scanning extension (chapter <a href="ch41.html" title="41. Content scanning at ACL time">41</a>) has facilities for passing messages to external virus and spam scanning software. You can also do a certain amount in Exim itself through string expansions and the <span class="docbook_option">condition</span> condition in the ACL that runs after the SMTP DATA command or the ACL for non-SMTP messages (see chapter <a href="ch40.html" title="40. Access control lists">40</a>), but this has its limitations. </p> <p> To allow for further customization to a site’s own requirements, there is the possibility of linking Exim with a private message scanning function, written in C. If you want to run code that is written in something other than C, you can of course use a little C stub to call it. </p> <p> The local scan function is run once for every incoming message, at the point when Exim is just about to accept the message. It can therefore be used to control non-SMTP messages from local processes as well as messages arriving via SMTP. </p> <p> Exim applies a timeout to calls of the local scan function, and there is an option called <span class="docbook_option">local_scan_timeout</span> for setting it. The default is 5 minutes. Zero means “no timeout”. Exim also sets up signal handlers for SIGSEGV, SIGILL, SIGFPE, and SIGBUS before calling the local scan function, so that the most common types of crash are caught. If the timeout is exceeded or one of those signals is caught, the incoming message is rejected with a temporary error if it is an SMTP message. For a non-SMTP message, the message is dropped and Exim ends with a non-zero code. The incident is logged on the main and reject logs. </p> <div class="section"> <h3 id="SECID207" class="">1. Building Exim to use a local scan function</h3> <p> To make use of the local scan function feature, you must tell Exim where your function is before building Exim, by setting LOCAL_SCAN_SOURCE in your <span class="docbook_filename">Local/Makefile</span>. A recommended place to put it is in the <span class="docbook_filename">Local</span> directory, so you might set </p> <div class="docbook_literallayout"><pre> LOCAL_SCAN_SOURCE=Local/local_scan.c </pre></div> <p> for example. The function must be called <span class="docbook_function">local_scan()</span>. It is called by Exim after it has received a message, when the success return code is about to be sent. This is after all the ACLs have been run. The return code from your function controls whether the message is actually accepted or not. There is a commented template function (that just accepts the message) in the file _src/local_scan.c_. </p> <p> If you want to make use of Exim’s run time configuration file to set options for your <span class="docbook_function">local_scan()</span> function, you must also set </p> <div class="docbook_literallayout"><pre> LOCAL_SCAN_HAS_OPTIONS=yes </pre></div> <p> in <span class="docbook_filename">Local/Makefile</span> (see section <a href="ch42.html#SECTconoptloc" title="42. Adding a local scan function to Exim">42.3</a> below). </p> </div> <div class="section"> <h3 id="SECTapiforloc" class="">2. API for local_scan()</h3> <p> You must include this line near the start of your code: </p> <div class="docbook_literallayout"><pre> #include "local_scan.h" </pre></div> <p> This header file defines a number of variables and other values, and the prototype for the function itself. Exim is coded to use unsigned char values almost exclusively, and one of the things this header defines is a shorthand for <code class="docbook_literal">unsigned char</code> called <code class="docbook_literal">uschar</code>. It also contains the following macro definitions, to simplify casting character strings and pointers to character strings: </p> <div class="docbook_literallayout"><pre> #define CS (char *) #define CCS (const char *) #define CSS (char **) #define US (unsigned char *) #define CUS (const unsigned char *) #define USS (unsigned char **) </pre></div> <p> The function prototype for <span class="docbook_function">local_scan()</span> is: </p> <div class="docbook_literallayout"><pre> extern int local_scan(int fd, uschar **return_text); </pre></div> <p> The arguments are as follows: </p> <ul> <li> <p> <span class="docbook_option">fd</span> is a file descriptor for the file that contains the body of the message (the -D file). The file is open for reading and writing, but updating it is not recommended. <span class="docbook_emphasis">Warning</span>: You must <span class="docbook_emphasis">not</span> close this file descriptor. </p> <p> The descriptor is positioned at character 19 of the file, which is the first character of the body itself, because the first 19 characters are the message id followed by <code class="docbook_literal">-D</code> and a newline. If you rewind the file, you should use the macro SPOOL_DATA_START_OFFSET to reset to the start of the data, just in case this changes in some future version. </p> </li> <li> <p> <span class="docbook_option">return_text</span> is an address which you can use to return a pointer to a text string at the end of the function. The value it points to on entry is NULL. </p> </li> </ul> <p> The function must return an <span class="docbook_option">int</span> value which is one of the following macros: </p> <dl> <dt><code class="docbook_literal">LOCAL_SCAN_ACCEPT</code></dt> <dd> <p> The message is accepted. If you pass back a string of text, it is saved with the message, and made available in the variable $local_scan_data. No newlines are permitted (if there are any, they are turned into spaces) and the maximum length of text is 1000 characters. </p> </dd> <dt><code class="docbook_literal">LOCAL_SCAN_ACCEPT_FREEZE</code></dt> <dd> <p> This behaves as LOCAL_SCAN_ACCEPT, except that the accepted message is queued without immediate delivery, and is frozen. </p> </dd> <dt><code class="docbook_literal">LOCAL_SCAN_ACCEPT_QUEUE</code></dt> <dd> <p> This behaves as LOCAL_SCAN_ACCEPT, except that the accepted message is queued without immediate delivery. </p> </dd> <dt><code class="docbook_literal">LOCAL_SCAN_REJECT</code></dt> <dd> <p> The message is rejected; the returned text is used as an error message which is passed back to the sender and which is also logged. Newlines are permitted – they cause a multiline response for SMTP rejections, but are converted to <code class="docbook_literal">\n</code> in log lines. If no message is given, “Administrative prohibition” is used. </p> </dd> <dt><code class="docbook_literal">LOCAL_SCAN_TEMPREJECT</code></dt> <dd> <p> The message is temporarily rejected; the returned text is used as an error message as for LOCAL_SCAN_REJECT. If no message is given, “Temporary local problem” is used. </p> </dd> <dt><code class="docbook_literal">LOCAL_SCAN_REJECT_NOLOGHDR</code></dt> <dd> <p> This behaves as LOCAL_SCAN_REJECT, except that the header of the rejected message is not written to the reject log. It has the effect of unsetting the <span class="docbook_option">rejected_header</span> log selector for just this rejection. If <span class="docbook_option">rejected_header</span> is already unset (see the discussion of the <span class="docbook_option">log_selection</span> option in section <a href="ch49.html#SECTlogselector" title="49. Log files">49.15</a>), this code is the same as LOCAL_SCAN_REJECT. </p> </dd> <dt><code class="docbook_literal">LOCAL_SCAN_TEMPREJECT_NOLOGHDR</code></dt> <dd> <p> This code is a variation of LOCAL_SCAN_TEMPREJECT in the same way that LOCAL_SCAN_REJECT_NOLOGHDR is a variation of LOCAL_SCAN_REJECT. </p> </dd> </dl> <p> If the message is not being received by interactive SMTP, rejections are reported by writing to <span class="docbook_option">stderr</span> or by sending an email, as configured by the <span class="docbook_option">-oe</span> command line options. </p> </div> <div class="section"> <h3 id="SECTconoptloc" class="">3. Configuration options for local_scan()</h3> <p> It is possible to have option settings in the main configuration file that set values in static variables in the <span class="docbook_function">local_scan()</span> module. If you want to do this, you must have the line </p> <div class="docbook_literallayout"><pre> LOCAL_SCAN_HAS_OPTIONS=yes </pre></div> <p> in your <span class="docbook_filename">Local/Makefile</span> when you build Exim. (This line is in <span class="docbook_filename">OS/Makefile-Default</span>, commented out). Then, in the <span class="docbook_function">local_scan()</span> source file, you must define static variables to hold the option values, and a table to define them. </p> <p> The table must be a vector called <span class="docbook_option">local_scan_options</span>, of type <code class="docbook_literal">optionlist</code>. Each entry is a triplet, consisting of a name, an option type, and a pointer to the variable that holds the value. The entries must appear in alphabetical order. Following <span class="docbook_option">local_scan_options</span> you must also define a variable called <span class="docbook_option">local_scan_options_count</span> that contains the number of entries in the table. Here is a short example, showing two kinds of option: </p> <div class="docbook_literallayout"><pre> static int my_integer_option = 42; static uschar *my_string_option = US"a default string"; optionlist local_scan_options[] = { { "my_integer", opt_int, &my_integer_option }, { "my_string", opt_stringptr, &my_string_option } }; int local_scan_options_count = sizeof(local_scan_options)/sizeof(optionlist); </pre></div> <p> The values of the variables can now be changed from Exim’s runtime configuration file by including a local scan section as in this example: </p> <div class="docbook_literallayout"><pre> begin local_scan my_integer = 99 my_string = some string of text... </pre></div> <p> The available types of option data are as follows: </p> <dl> <dt><span class="docbook_emphasis">opt_bool</span></dt> <dd> <p> This specifies a boolean (true/false) option. The address should point to a variable of type <code class="docbook_literal">BOOL</code>, which will be set to TRUE or FALSE, which are macros that are defined as “1” and “0”, respectively. If you want to detect whether such a variable has been set at all, you can initialize it to TRUE_UNSET. (BOOL variables are integers underneath, so can hold more than two values.) </p> </dd> <dt><span class="docbook_emphasis">opt_fixed</span></dt> <dd> <p> This specifies a fixed point number, such as is used for load averages. The address should point to a variable of type <code class="docbook_literal">int</code>. The value is stored multiplied by 1000, so, for example, 1.4142 is truncated and stored as 1414. </p> </dd> <dt><span class="docbook_emphasis">opt_int</span></dt> <dd> <p> This specifies an integer; the address should point to a variable of type <code class="docbook_literal">int</code>. The value may be specified in any of the integer formats accepted by Exim. </p> </dd> <dt><span class="docbook_emphasis">opt_mkint</span></dt> <dd> <p> This is the same as <span class="docbook_option">opt_int</span>, except that when such a value is output in a <span class="docbook_option">-bP</span> listing, if it is an exact number of kilobytes or megabytes, it is printed with the suffix K or M. </p> </dd> <dt><span class="docbook_emphasis">opt_octint</span></dt> <dd> <p> This also specifies an integer, but the value is always interpreted as an octal integer, whether or not it starts with the digit zero, and it is always output in octal. </p> </dd> <dt><span class="docbook_emphasis">opt_stringptr</span></dt> <dd> <p> This specifies a string value; the address must be a pointer to a variable that points to a string (for example, of type <code class="docbook_literal">uschar *</code>). </p> </dd> <dt><span class="docbook_emphasis">opt_time</span></dt> <dd> <p> This specifies a time interval value. The address must point to a variable of type <code class="docbook_literal">int</code>. The value that is placed there is a number of seconds. </p> </dd> </dl> <p> If the <span class="docbook_option">-bP</span> command line option is followed by <code class="docbook_literal">local_scan</code>, Exim prints out the values of all the <span class="docbook_function">local_scan()</span> options. </p> </div> <div class="section"> <h3 id="SECID208" class="">4. Available Exim variables</h3> <p> The header <span class="docbook_filename">local_scan.h</span> gives you access to a number of C variables. These are the only ones that are guaranteed to be maintained from release to release. Note, however, that you can obtain the value of any Exim expansion variable, including $recipients, by calling <span class="docbook_emphasis">expand_string()</span>. The exported C variables are as follows: </p> <dl> <dt><span class="docbook_emphasis">int body_linecount</span></dt> <dd> <p> This variable contains the number of lines in the message’s body. </p> </dd> <dt><span class="docbook_emphasis">int body_zerocount</span></dt> <dd> <p> This variable contains the number of binary zero bytes in the message’s body. </p> </dd> <dt><span class="docbook_emphasis">unsigned int debug_selector</span></dt> <dd> <p> This variable is set to zero when no debugging is taking place. Otherwise, it is a bitmap of debugging selectors. Two bits are identified for use in <span class="docbook_function">local_scan()</span>; they are defined as macros: </p> <ul> <li> <p> The <code class="docbook_literal">D_v</code> bit is set when <span class="docbook_option">-v</span> was present on the command line. This is a testing option that is not privileged – any caller may set it. All the other selector bits can be set only by admin users. </p> </li> <li> <p> The <code class="docbook_literal">D_local_scan</code> bit is provided for use by <span class="docbook_function">local_scan()</span>; it is set by the <code class="docbook_literal">+local_scan</code> debug selector. It is not included in the default set of debugging bits. </p> </li> </ul> <p> Thus, to write to the debugging output only when <code class="docbook_literal">+local_scan</code> has been selected, you should use code like this: </p> <div class="docbook_literallayout"><pre> if ((debug_selector & D_local_scan) != 0) debug_printf("xxx", ...); </pre></div> </dd> <dt><span class="docbook_emphasis">uschar *expand_string_message</span></dt> <dd> <p> After a failing call to <span class="docbook_emphasis">expand_string()</span> (returned value NULL), the variable <span class="docbook_option">expand_string_message</span> contains the error message, zero-terminated. </p> </dd> <dt><span class="docbook_emphasis">header_line *header_list</span></dt> <dd> <p> A pointer to a chain of header lines. The <span class="docbook_option">header_line</span> structure is discussed below. </p> </dd> <dt><span class="docbook_emphasis">header_line *header_last</span></dt> <dd> <p> A pointer to the last of the header lines. </p> </dd> <dt><span class="docbook_emphasis">uschar *headers_charset</span></dt> <dd> <p> The value of the <span class="docbook_option">headers_charset</span> configuration option. </p> </dd> <dt><span class="docbook_emphasis">BOOL host_checking</span></dt> <dd> <p> This variable is TRUE during a host checking session that is initiated by the <span class="docbook_option">-bh</span> command line option. </p> </dd> <dt><span class="docbook_emphasis">uschar *interface_address</span></dt> <dd> <p> The IP address of the interface that received the message, as a string. This is NULL for locally submitted messages. </p> </dd> <dt><span class="docbook_emphasis">int interface_port</span></dt> <dd> <p> The port on which this message was received. When testing with the <span class="docbook_option">-bh</span> command line option, the value of this variable is -1 unless a port has been specified via the <span class="docbook_option">-oMi</span> option. </p> </dd> <dt><span class="docbook_emphasis">uschar *message_id</span></dt> <dd> <p> This variable contains Exim’s message id for the incoming message (the value of $message_exim_id) as a zero-terminated string. </p> </dd> <dt><span class="docbook_emphasis">uschar *received_protocol</span></dt> <dd> <p> The name of the protocol by which the message was received. </p> </dd> <dt><span class="docbook_emphasis">int recipients_count</span></dt> <dd> <p> The number of accepted recipients. </p> </dd> <dt><span class="docbook_emphasis">recipient_item *recipients_list</span></dt> <dd> <p> The list of accepted recipients, held in a vector of length <span class="docbook_option">recipients_count</span>. The <span class="docbook_option">recipient_item</span> structure is discussed below. You can add additional recipients by calling <span class="docbook_emphasis">receive_add_recipient()</span> (see below). You can delete recipients by removing them from the vector and adjusting the value in <span class="docbook_option">recipients_count</span>. In particular, by setting <span class="docbook_option">recipients_count</span> to zero you remove all recipients. If you then return the value <code class="docbook_literal">LOCAL_SCAN_ACCEPT</code>, the message is accepted, but immediately blackholed. To replace the recipients, you can set <span class="docbook_option">recipients_count</span> to zero and then call <span class="docbook_emphasis">receive_add_recipient()</span> as often as needed. </p> </dd> <dt><span class="docbook_emphasis">uschar *sender_address</span></dt> <dd> <p> The envelope sender address. For bounce messages this is the empty string. </p> </dd> <dt><span class="docbook_emphasis">uschar *sender_host_address</span></dt> <dd> <p> The IP address of the sending host, as a string. This is NULL for locally-submitted messages. </p> </dd> <dt><span class="docbook_emphasis">uschar *sender_host_authenticated</span></dt> <dd> <p> The name of the authentication mechanism that was used, or NULL if the message was not received over an authenticated SMTP connection. </p> </dd> <dt><span class="docbook_emphasis">uschar *sender_host_name</span></dt> <dd> <p> The name of the sending host, if known. </p> </dd> <dt><span class="docbook_emphasis">int sender_host_port</span></dt> <dd> <p> The port on the sending host. </p> </dd> <dt><span class="docbook_emphasis">BOOL smtp_input</span></dt> <dd> <p> This variable is TRUE for all SMTP input, including BSMTP. </p> </dd> <dt><span class="docbook_emphasis">BOOL smtp_batched_input</span></dt> <dd> <p> This variable is TRUE for BSMTP input. </p> </dd> <dt><span class="docbook_emphasis">int store_pool</span></dt> <dd> <p> The contents of this variable control which pool of memory is used for new requests. See section <a href="ch42.html#SECTmemhanloc" title="42. Adding a local scan function to Exim">42.8</a> for details. </p> </dd> </dl> </div> <div class="section"> <h3 id="SECID209" class="">5. Structure of header lines</h3> <p> The <span class="docbook_option">header_line</span> structure contains the members listed below. You can add additional header lines by calling the <span class="docbook_emphasis">header_add()</span> function (see below). You can cause header lines to be ignored (deleted) by setting their type to *. </p> <dl> <dt><span class="docbook_emphasis">struct header_line *next</span></dt> <dd> <p> A pointer to the next header line, or NULL for the last line. </p> </dd> <dt><span class="docbook_emphasis">int type</span></dt> <dd> <p> A code identifying certain headers that Exim recognizes. The codes are printing characters, and are documented in chapter <a href="ch53.html" title="53. Format of spool files">53</a> of this manual. Notice in particular that any header line whose type is * is not transmitted with the message. This flagging is used for header lines that have been rewritten, or are to be removed (for example, <span class="docbook_emphasis">Envelope-sender:</span> header lines.) Effectively, * means “deleted”. </p> </dd> <dt><span class="docbook_emphasis">int slen</span></dt> <dd> <p> The number of characters in the header line, including the terminating and any internal newlines. </p> </dd> <dt><span class="docbook_emphasis">uschar *text</span></dt> <dd> <p> A pointer to the text of the header. It always ends with a newline, followed by a zero byte. Internal newlines are preserved. </p> </dd> </dl> </div> <div class="section"> <h3 id="SECID210" class="">6. Structure of recipient items</h3> <p> The <span class="docbook_option">recipient_item</span> structure contains these members: </p> <dl> <dt><span class="docbook_emphasis">uschar *address</span></dt> <dd> <p> This is a pointer to the recipient address as it was received. </p> </dd> <dt><span class="docbook_emphasis">int pno</span></dt> <dd> <p> This is used in later Exim processing when top level addresses are created by the <span class="docbook_option">one_time</span> option. It is not relevant at the time <span class="docbook_function">local_scan()</span> is run and must always contain -1 at this stage. </p> </dd> <dt><span class="docbook_emphasis">uschar *errors_to</span></dt> <dd> <p> If this value is not NULL, bounce messages caused by failing to deliver to the recipient are sent to the address it contains. In other words, it overrides the envelope sender for this one recipient. (Compare the <span class="docbook_option">errors_to</span> generic router option.) If a <span class="docbook_function">local_scan()</span> function sets an <span class="docbook_option">errors_to</span> field to an unqualified address, Exim qualifies it using the domain from <span class="docbook_option">qualify_recipient</span>. When <span class="docbook_function">local_scan()</span> is called, the <span class="docbook_option">errors_to</span> field is NULL for all recipients. </p> </dd> </dl> </div> <div class="section"> <h3 id="SECID211" class="">7. Available Exim functions</h3> <p> The header <span class="docbook_filename">local_scan.h</span> gives you access to a number of Exim functions. These are the only ones that are guaranteed to be maintained from release to release: </p> <dl> <dt><span class="docbook_emphasis">pid_t child_open(uschar **argv, uschar **envp, int newumask, int *infdptr, int *outfdptr, BOOL make_leader)</span></dt> <dd> <p> This function creates a child process that runs the command specified by <span class="docbook_option">argv</span>. The environment for the process is specified by <span class="docbook_option">envp</span>, which can be NULL if no environment variables are to be passed. A new umask is supplied for the process in <span class="docbook_option">newumask</span>. </p> <p> Pipes to the standard input and output of the new process are set up and returned to the caller via the <span class="docbook_option">infdptr</span> and <span class="docbook_option">outfdptr</span> arguments. The standard error is cloned to the standard output. If there are any file descriptors “in the way” in the new process, they are closed. If the final argument is TRUE, the new process is made into a process group leader. </p> <p> The function returns the pid of the new process, or -1 if things go wrong. </p> </dd> <dt><span class="docbook_emphasis">int child_close(pid_t pid, int timeout)</span></dt> <dd> <p> This function waits for a child process to terminate, or for a timeout (in seconds) to expire. A timeout value of zero means wait as long as it takes. The return value is as follows: </p> <ul> <li> <p> >= 0 </p> <p> The process terminated by a normal exit and the value is the process ending status. </p> </li> <li> <p> < 0 and > –256 </p> <p> The process was terminated by a signal and the value is the negation of the signal number. </p> </li> <li> <p> –256 </p> <p> The process timed out. </p> </li> <li> <p> –257 </p> <p> The was some other error in wait(); <span class="docbook_option">errno</span> is still set. </p> </li> </ul> </dd> <dt><span class="docbook_emphasis">pid_t child_open_exim(int *fd)</span></dt> <dd> <p> This function provide you with a means of submitting a new message to Exim. (Of course, you can also call <span class="docbook_filename">/usr/sbin/sendmail</span> yourself if you want, but this packages it all up for you.) The function creates a pipe, forks a subprocess that is running </p> <div class="docbook_literallayout"><pre> exim -t -oem -oi -f <> </pre></div> <p> and returns to you (via the <code class="docbook_literal">int *</code> argument) a file descriptor for the pipe that is connected to the standard input. The yield of the function is the PID of the subprocess. You can then write a message to the file descriptor, with recipients in <span class="docbook_emphasis">To:</span>, <span class="docbook_emphasis">Cc:</span>, and/or <span class="docbook_emphasis">Bcc:</span> header lines. </p> <p> When you have finished, call <span class="docbook_emphasis">child_close()</span> to wait for the process to finish and to collect its ending status. A timeout value of zero is usually fine in this circumstance. Unless you have made a mistake with the recipient addresses, you should get a return code of zero. </p> </dd> <dt><span class="docbook_emphasis">pid_t child_open_exim2(int *fd, uschar *sender, uschar *sender_authentication)</span></dt> <dd> <p> This function is a more sophisticated version of <span class="docbook_emphasis">child_open()</span>. The command that it runs is: </p> <div class="docbook_literallayout"><pre> <code class="docbook_literal">exim -t -oem -oi -f </code><span class="docbook_emphasis">sender</span><code class="docbook_literal"> -oMas </code><span class="docbook_emphasis">sender_authentication</span> </pre></div> <p> The third argument may be NULL, in which case the <span class="docbook_option">-oMas</span> option is omitted. </p> </dd> <dt><span class="docbook_emphasis">void debug_printf(char *, ...)</span></dt> <dd> <p> This is Exim’s debugging function, with arguments as for <span class="docbook_emphasis">(printf()</span>. The output is written to the standard error stream. If no debugging is selected, calls to <span class="docbook_emphasis">debug_printf()</span> have no effect. Normally, you should make calls conditional on the <code class="docbook_literal">local_scan</code> debug selector by coding like this: </p> <div class="docbook_literallayout"><pre> if ((debug_selector & D_local_scan) != 0) debug_printf("xxx", ...); </pre></div> </dd> <dt><span class="docbook_emphasis">uschar *expand_string(uschar *string)</span></dt> <dd> <p> This is an interface to Exim’s string expansion code. The return value is the expanded string, or NULL if there was an expansion failure. The C variable <span class="docbook_option">expand_string_message</span> contains an error message after an expansion failure. If expansion does not change the string, the return value is the pointer to the input string. Otherwise, the return value points to a new block of memory that was obtained by a call to <span class="docbook_emphasis">store_get()</span>. See section <a href="ch42.html#SECTmemhanloc" title="42. Adding a local scan function to Exim">42.8</a> below for a discussion of memory handling. </p> </dd> <dt><span class="docbook_emphasis">void header_add(int type, char *format, ...)</span></dt> <dd> <p> This function allows you to an add additional header line at the end of the existing ones. The first argument is the type, and should normally be a space character. The second argument is a format string and any number of substitution arguments as for <span class="docbook_function">sprintf()</span>. You may include internal newlines if you want, and you must ensure that the string ends with a newline. </p> </dd> <dt><span class="docbook_emphasis">void header_add_at_position(BOOL after, uschar *name, BOOL topnot, int type, char *format, ...)</span></dt> <dd> <p> This function adds a new header line at a specified point in the header chain. The header itself is specified as for <span class="docbook_emphasis">header_add()</span>. </p> <p> If <span class="docbook_option">name</span> is NULL, the new header is added at the end of the chain if <span class="docbook_option">after</span> is true, or at the start if <span class="docbook_option">after</span> is false. If <span class="docbook_option">name</span> is not NULL, the header lines are searched for the first non-deleted header that matches the name. If one is found, the new header is added before it if <span class="docbook_option">after</span> is false. If <span class="docbook_option">after</span> is true, the new header is added after the found header and any adjacent subsequent ones with the same name (even if marked “deleted”). If no matching non-deleted header is found, the <span class="docbook_option">topnot</span> option controls where the header is added. If it is true, addition is at the top; otherwise at the bottom. Thus, to add a header after all the <span class="docbook_emphasis">Received:</span> headers, or at the top if there are no <span class="docbook_emphasis">Received:</span> headers, you could use </p> <div class="docbook_literallayout"><pre> header_add_at_position(TRUE, US"Received", TRUE, ' ', "X-xxx: ..."); </pre></div> <p> Normally, there is always at least one non-deleted <span class="docbook_emphasis">Received:</span> header, but there may not be if <span class="docbook_option">received_header_text</span> expands to an empty string. </p> </dd> <dt><span class="docbook_emphasis">void header_remove(int occurrence, uschar *name)</span></dt> <dd> <p> This function removes header lines. If <span class="docbook_option">occurrence</span> is zero or negative, all occurrences of the header are removed. If occurrence is greater than zero, that particular instance of the header is removed. If no header(s) can be found that match the specification, the function does nothing. </p> </dd> <dt><span class="docbook_emphasis">BOOL header_testname(header_line *hdr, uschar *name, int length, BOOL notdel)</span></dt> <dd> <p> This function tests whether the given header has the given name. It is not just a string comparison, because white space is permitted between the name and the colon. If the <span class="docbook_option">notdel</span> argument is true, a false return is forced for all “deleted” headers; otherwise they are not treated specially. For example: </p> <div class="docbook_literallayout"><pre> if (header_testname(h, US"X-Spam", 6, TRUE)) ... </pre></div> </dd> <dt><span class="docbook_emphasis">uschar *lss_b64encode(uschar *cleartext, int length)</span></dt> <dd> <p> This function base64-encodes a string, which is passed by address and length. The text may contain bytes of any value, including zero. The result is passed back in dynamic memory that is obtained by calling <span class="docbook_emphasis">store_get()</span>. It is zero-terminated. </p> </dd> <dt><span class="docbook_emphasis">int lss_b64decode(uschar *codetext, uschar **cleartext)</span></dt> <dd> <p> This function decodes a base64-encoded string. Its arguments are a zero-terminated base64-encoded string and the address of a variable that is set to point to the result, which is in dynamic memory. The length of the decoded string is the yield of the function. If the input is invalid base64 data, the yield is -1. A zero byte is added to the end of the output string to make it easy to interpret as a C string (assuming it contains no zeros of its own). The added zero byte is not included in the returned count. </p> </dd> <dt><span class="docbook_emphasis">int lss_match_domain(uschar *domain, uschar *list)</span></dt> <dd> <p> This function checks for a match in a domain list. Domains are always matched caselessly. The return value is one of the following: </p> <div class="docbook_literallayout"><pre> <code class="docbook_literal">OK </code> match succeeded <code class="docbook_literal">FAIL </code> match failed <code class="docbook_literal">DEFER </code> match deferred </pre></div> <p> DEFER is usually caused by some kind of lookup defer, such as the inability to contact a database. </p> </dd> <dt><span class="docbook_emphasis">int lss_match_local_part(uschar *localpart, uschar *list, BOOL caseless)</span></dt> <dd> <p> This function checks for a match in a local part list. The third argument controls case-sensitivity. The return values are as for <span class="docbook_emphasis">lss_match_domain()</span>. </p> </dd> <dt><span class="docbook_emphasis">int lss_match_address(uschar *address, uschar *list, BOOL caseless)</span></dt> <dd> <p> This function checks for a match in an address list. The third argument controls the case-sensitivity of the local part match. The domain is always matched caselessly. The return values are as for <span class="docbook_emphasis">lss_match_domain()</span>. </p> </dd> <dt><span class="docbook_emphasis">int lss_match_host(uschar *host_name, uschar *host_address, uschar *list)</span></dt> <dd> <p> This function checks for a match in a host list. The most common usage is expected to be </p> <div class="docbook_literallayout"><pre> lss_match_host(sender_host_name, sender_host_address, ...) </pre></div> <p> An empty address field matches an empty item in the host list. If the host name is NULL, the name corresponding to $sender_host_address is automatically looked up if a host name is required to match an item in the list. The return values are as for <span class="docbook_emphasis">lss_match_domain()</span>, but in addition, <span class="docbook_emphasis">lss_match_host()</span> returns ERROR in the case when it had to look up a host name, but the lookup failed. </p> </dd> <dt><span class="docbook_emphasis">void log_write(unsigned int selector, int which, char *format, ...)</span></dt> <dd> <p> This function writes to Exim’s log files. The first argument should be zero (it is concerned with <span class="docbook_option">log_selector</span>). The second argument can be <code class="docbook_literal">LOG_MAIN</code> or <code class="docbook_literal">LOG_REJECT</code> or <code class="docbook_literal">LOG_PANIC</code> or the inclusive “or” of any combination of them. It specifies to which log or logs the message is written. The remaining arguments are a format and relevant insertion arguments. The string should not contain any newlines, not even at the end. </p> </dd> <dt><span class="docbook_emphasis">void receive_add_recipient(uschar *address, int pno)</span></dt> <dd> <p> This function adds an additional recipient to the message. The first argument is the recipient address. If it is unqualified (has no domain), it is qualified with the <span class="docbook_option">qualify_recipient</span> domain. The second argument must always be -1. </p> <p> This function does not allow you to specify a private <span class="docbook_option">errors_to</span> address (as described with the structure of <span class="docbook_option">recipient_item</span> above), because it pre-dates the addition of that field to the structure. However, it is easy to add such a value afterwards. For example: </p> <div class="docbook_literallayout"><pre> receive_add_recipient(US"monitor@mydom.example", -1); recipients_list[recipients_count-1].errors_to = US"postmaster@mydom.example"; </pre></div> </dd> <dt><span class="docbook_emphasis">BOOL receive_remove_recipient(uschar *recipient)</span></dt> <dd> <p> This is a convenience function to remove a named recipient from the list of recipients. It returns true if a recipient was removed, and false if no matching recipient could be found. The argument must be a complete email address. </p> </dd> </dl> <p> </p> <dl> <dt><span class="docbook_emphasis">uschar rfc2047_decode(uschar *string, BOOL lencheck, uschar *target, int zeroval, int *lenptr, uschar **error)</span></dt> <dd> <p> This function decodes strings that are encoded according to RFC 2047. Typically these are the contents of header lines. First, each “encoded word” is decoded from the Q or B encoding into a byte-string. Then, if provided with the name of a charset encoding, and if the <span class="docbook_function">iconv()</span> function is available, an attempt is made to translate the result to the named character set. If this fails, the binary string is returned with an error message. </p> <p> The first argument is the string to be decoded. If <span class="docbook_option">lencheck</span> is TRUE, the maximum MIME word length is enforced. The third argument is the target encoding, or NULL if no translation is wanted. </p> <p> If a binary zero is encountered in the decoded string, it is replaced by the contents of the <span class="docbook_option">zeroval</span> argument. For use with Exim headers, the value must not be 0 because header lines are handled as zero-terminated strings. </p> <p> The function returns the result of processing the string, zero-terminated; if <span class="docbook_option">lenptr</span> is not NULL, the length of the result is set in the variable to which it points. When <span class="docbook_option">zeroval</span> is 0, <span class="docbook_option">lenptr</span> should not be NULL. </p> <p> If an error is encountered, the function returns NULL and uses the <span class="docbook_option">error</span> argument to return an error message. The variable pointed to by <span class="docbook_option">error</span> is set to NULL if there is no error; it may be set non-NULL even when the function returns a non-NULL value if decoding was successful, but there was a problem with translation. </p> </dd> <dt><span class="docbook_emphasis">int smtp_fflush(void)</span></dt> <dd> <p> This function is used in conjunction with <span class="docbook_emphasis">smtp_printf()</span>, as described below. </p> </dd> <dt><span class="docbook_emphasis">void smtp_printf(char *, ...)</span></dt> <dd> <p> The arguments of this function are like <span class="docbook_function">printf()</span>; it writes to the SMTP output stream. You should use this function only when there is an SMTP output stream, that is, when the incoming message is being received via interactive SMTP. This is the case when <span class="docbook_option">smtp_input</span> is TRUE and <span class="docbook_option">smtp_batched_input</span> is FALSE. If you want to test for an incoming message from another host (as opposed to a local process that used the <span class="docbook_option">-bs</span> command line option), you can test the value of <span class="docbook_option">sender_host_address</span>, which is non-NULL when a remote host is involved. </p> <p> If an SMTP TLS connection is established, <span class="docbook_emphasis">smtp_printf()</span> uses the TLS output function, so it can be used for all forms of SMTP connection. </p> <p> Strings that are written by <span class="docbook_emphasis">smtp_printf()</span> from within <span class="docbook_function">local_scan()</span> must start with an appropriate response code: 550 if you are going to return LOCAL_SCAN_REJECT, 451 if you are going to return LOCAL_SCAN_TEMPREJECT, and 250 otherwise. Because you are writing the initial lines of a multi-line response, the code must be followed by a hyphen to indicate that the line is not the final response line. You must also ensure that the lines you write terminate with CRLF. For example: </p> <div class="docbook_literallayout"><pre> smtp_printf("550-this is some extra info\r\n"); return LOCAL_SCAN_REJECT; </pre></div> <p> Note that you can also create multi-line responses by including newlines in the data returned via the <span class="docbook_option">return_text</span> argument. The added value of using <span class="docbook_emphasis">smtp_printf()</span> is that, for instance, you could introduce delays between multiple output lines. </p> <p> The <span class="docbook_emphasis">smtp_printf()</span> function does not return any error indication, because it does not automatically flush pending output, and therefore does not test the state of the stream. (In the main code of Exim, flushing and error detection is done when Exim is ready for the next SMTP input command.) If you want to flush the output and check for an error (for example, the dropping of a TCP/IP connection), you can call <span class="docbook_emphasis">smtp_fflush()</span>, which has no arguments. It flushes the output stream, and returns a non-zero value if there is an error. </p> </dd> <dt><span class="docbook_emphasis">void *store_get(int)</span></dt> <dd> <p> This function accesses Exim’s internal store (memory) manager. It gets a new chunk of memory whose size is given by the argument. Exim bombs out if it ever runs out of memory. See the next section for a discussion of memory handling. </p> </dd> <dt><span class="docbook_emphasis">void *store_get_perm(int)</span></dt> <dd> <p> This function is like <span class="docbook_emphasis">store_get()</span>, but it always gets memory from the permanent pool. See the next section for a discussion of memory handling. </p> </dd> <dt><span class="docbook_emphasis">uschar *string_copy(uschar *string)</span></dt> <dd> <p> See below. </p> </dd> <dt><span class="docbook_emphasis">uschar *string_copyn(uschar *string, int length)</span></dt> <dd> <p> See below. </p> </dd> <dt><span class="docbook_emphasis">uschar *string_sprintf(char *format, ...)</span></dt> <dd> <p> These three functions create strings using Exim’s dynamic memory facilities. The first makes a copy of an entire string. The second copies up to a maximum number of characters, indicated by the second argument. The third uses a format and insertion arguments to create a new string. In each case, the result is a pointer to a new string in the current memory pool. See the next section for more discussion. </p> </dd> </dl> </div> <div class="section"> <h3 id="SECTmemhanloc" class="">8. More about Exim’s memory handling</h3> <p> No function is provided for freeing memory, because that is never needed. The dynamic memory that Exim uses when receiving a message is automatically recycled if another message is received by the same process (this applies only to incoming SMTP connections – other input methods can supply only one message at a time). After receiving the last message, a reception process terminates. </p> <p> Because it is recycled, the normal dynamic memory cannot be used for holding data that must be preserved over a number of incoming messages on the same SMTP connection. However, Exim in fact uses two pools of dynamic memory; the second one is not recycled, and can be used for this purpose. </p> <p> If you want to allocate memory that remains available for subsequent messages in the same SMTP connection, you should set </p> <div class="docbook_literallayout"><pre> store_pool = POOL_PERM </pre></div> <p> before calling the function that does the allocation. There is no need to restore the value if you do not need to; however, if you do want to revert to the normal pool, you can either restore the previous value of <span class="docbook_option">store_pool</span> or set it explicitly to POOL_MAIN. </p> <p> The pool setting applies to all functions that get dynamic memory, including <span class="docbook_emphasis">expand_string()</span>, <span class="docbook_emphasis">store_get()</span>, and the <span class="docbook_emphasis">string_xxx()</span> functions. There is also a convenience function called <span class="docbook_emphasis">store_get_perm()</span> that gets a block of memory from the permanent pool while preserving the value of <span class="docbook_option">store_pool</span>. </p> </div> </div> <a class="previous_page" href="ch41.html"><-previous</a><a class="next_page" href="ch43.html">next-></a> </div></div> <iframe id="branding" name="branding" src="../../../../branding/branding.html" height="0" frameborder="no" scrolling="no"></iframe><div id="footer">Website design by <a href="https://secure.grepular.com/">Mike Cardwell</a>, of <a href="http://cardwellit.com/">Cardwell IT Ltd.</a> </div> <div class="left_bar"></div> <div class="right_bar"></div> <div id="toc"> <ul class="hidden"></ul> <img src="../../../../doc/contents.png" width="16" height="155"> </div> </div> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script><script type="text/javascript" src="../../../../common.js"></script><script type="text/javascript" src="../../../../doc/chapter.js"></script> </body> </html>