chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[inn-innduct.git] / doc / hook-perl
diff --git a/doc/hook-perl b/doc/hook-perl
deleted file mode 100644 (file)
index b2e33d8..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-INN Perl Filtering and Authentication Support
-
-    This is $Revision: 7880 $ dated $Date: 2008-06-07 14:46:49 +0200 (Sat,
-    07 Jun 2008) $.
-
-    This file documents INN's built-in support for Perl filtering and reader
-    authentication.  The code is based very heavily on work by Christophe
-    Wolfhugel <wolf@pasteur.fr>, and his work was in turn inspired by the
-    existing TCL support.  Please send any bug reports to inn-bugs@isc.org,
-    not to Christophe, as the code has been modified heavily since he
-    originally wrote it.
-
-    The Perl filtering support is described in more detail below. 
-    Basically, it allows you to supply a Perl function that is invoked on
-    every article received by innd from a peer (the innd filter) or by nnrpd
-    from a reader (the nnrpd filter).  This function can decide whether to
-    accept or reject the article, and can optionally do other, more
-    complicated processing (such as add history entries, cancel articles,
-    spool local posts into a holding area, or even modify the headers of
-    locally submitted posts).  The Perl authentication hooks allow you to
-    replace or supplement the readers.conf mechanism used by nnrpd.
-
-    For Perl filtering support, you need to have Perl version 5.004 or
-    newer.  Earlier versions of Perl will fail with a link error at
-    compilation time.  http://language.perl.com/info/software.html should
-    have the latest Perl version.
-
-    To enable Perl support, you have to specify --with-perl when you run
-    configure.  See INSTALL for more information.
-
-The innd Perl Filter
-
-    When innd starts, it first loads the file _PATH_PERL_STARTUP_INND
-    (defined in include/paths.h, by default startup_innd.pl) and then loads
-    the file _PATH_PERL_FILTER_INND (also defined in include/paths.h, by
-    default filter_innd.pl).  Both of these files must be located in the
-    directory specified by pathfilter in inn.conf
-    (/usr/local/news/bin/filter by default).  The default directory for
-    filter code can be specified at configure time by giving the flag
-    --with-filter-dir to configure.
-
-    INN doesn't care what Perl functions you define in which files.  The
-    only thing that's different about the two files is when they're loaded. 
-    startup_innd.pl is loaded only once, when innd first starts, and is
-    never reloaded as long as innd is running.  Any modifications to that
-    file won't be noticed by innd; only stopping and restarting innd can
-    cause it to be reloaded.
-
-    filter_innd.pl, on the other hand, can be reloaded on command (with
-    "ctlinnd reload filter.perl 'reason'").  Whenever filter_innd.pl is
-    loaded, including the first time at innd startup, the Perl function
-    filter_before_reload() is called before it's reloaded and the function
-    filter_after_reload() is called after it's reloaded (if the functions
-    exist).  Additionally, any code in either startup_innd.pl or
-    filter_innd.pl at the top level (in other words, not inside a sub { })
-    is automatically executed by Perl when the files are loaded.
-
-    This allows one to do things like write out filter statistics whenever
-    the filter is reloaded, load a cache into memory, flush cached data to
-    disk, or other similar operations that should only happen at particular
-    times or with manual intervention.  Remember, any code not inside
-    functions in startup_innd.pl is executed when that file is loaded, and
-    it's loaded only once when innd first starts.  That makes it the ideal
-    place to put initialization code that should only run once, or code to
-    load data that was preserved on disk across a stop and restart of innd
-    (perhaps using filter_mode() -- see below).
-
-    As mentioned above, "ctlinnd reload filter.perl 'reason'" (or "ctlinnd
-    reload all 'reason'") will cause filter_innd.pl to be reloaded.  If the
-    function filter_art() is defined after the file has been reloaded,
-    filtering is turned on.  Otherwise, filtering is turned off.  (Note that
-    due to the way Perl stores functions, once you've defined filter_art(),
-    you can't undefine it just by deleting it from the file and reloading
-    the filter.  You'll need to replace it with an empty sub.)
-
-    The Perl function filter_art() is the heart of a Perl filter.  Whenever
-    an article is received from a peer, via either IHAVE or TAKETHIS,
-    filter_art() is called if Perl filtering is turned on.  It receives no
-    arguments, and should return a single scalar value.  That value should
-    be the empty string to indicate that INN should accept the article, or
-    some rejection message to indicate that the article should be rejected.
-
-    filter_art() has access to a global hash named %hdr, which contains all
-    of the standard headers present in the article and their values.  The
-    standard headers are:
-
-        Also-Control, Approved, Bytes, Cancel-Key, Cancel-Lock,
-        Content-Base, Content-Disposition, Content-Transfer-Encoding,
-        Content-Type, Control, Date, Date-Received, Distribution, Expires,
-        Face, Followup-To, From, In-Reply-To, Injection-Date, Injection-Info,
-        Keywords, Lines, List-ID, Message-ID, MIME-Version, Newsgroups,
-        NNTP-Posting-Date, NNTP-Posting-Host, Organization, Originator,
-        Path, Posted, Posting-Version, Received, References, Relay-Version,
-        Reply-To, Sender, Subject, Supersedes, User-Agent,
-        X-Auth, X-Canceled-By, X-Cancelled-By, X-Complaints-To, X-Face,
-        X-HTTP-UserAgent, X-HTTP-Via, X-Mailer, X-Modbot, X-Modtrace,
-        X-Newsposter, X-Newsreader, X-No-Archive, X-Original-Message-ID,
-        X-Original-Trace, X-Originating-IP, X-PGP-Key, X-PGP-Sig,
-        X-Poster-Trace, X-Postfilter, X-Proxy-User, X-Submissions-To,
-        X-Trace, X-Usenet-Provider, Xref.
-
-    Note that all the above headers are as they arrived, not modified by
-    your INN (especially, the Xref: header, if present, is the one of the
-    remote site which sent you the article, and not yours).
-
-    For example, the Newsgroups: header of the article is accessible inside
-    the Perl filter as $hdr{'Newsgroups'}.  In addition, $hdr{'__BODY__'}
-    will contain the full body of the article and $hdr{'__LINES__'} will
-    contain the number of lines in the body of the article.
-
-    The contents of the %hdr hash for a typical article may therefore look
-    something like this:
-
-        %hdr = (Subject      => 'MAKE MONEY FAST!!', 
-            From         => 'Joe Spamer <him@example.com>',
-            Date         => '10 Sep 1996 15:32:28 UTC',
-            Newsgroups   => 'alt.test',
-            Path         => 'news.example.com!not-for-mail',
-            Organization => 'Spammers Anonymous',
-            Lines        => '5',
-            Distribution => 'usa',
-            'Message-ID' => '<6.20232.842369548@example.com>',
-            __BODY__     => 'Send five dollars to the ISC, c/o ...',
-            __LINES__    => 5
-        );
-
-    Note that the value of $hdr{Lines} is the contents of the Lines: header
-    of the article and may bear no resemblence to the actual length of the
-    article.  $hdr{__LINES__} is the line count calculated by INN, and is
-    guaranteed to be accurate.
-
-    The %hdr hash should not be modified inside filter_art().  Instead, if
-    any of the contents need to be modified temporarily during filtering
-    (smashing case, for example), copy them into a seperate variable first
-    and perform the modifications on the copy.  Currently, $hdr{__BODY__} is
-    the only data that will cause your filter to die if you modify it, but
-    in the future other keys may also contain live data.  Modifying live INN
-    data in Perl will hopefully only cause a fatal exception in your Perl
-    code that disables Perl filtering until you fix it, but it's possible
-    for it to cause article munging or even core dumps in INN.  So always,
-    always make a copy first.
-
-    As mentioned above, if filter_art() returns the empty string (''), the
-    article is accepted.  Note that this must be the empty string, not 0 or
-    undef.  Otherwise, the article is rejected, and whatever scalar
-    filter_art() returns (typically a string) will be taken as the reason
-    why the article was rejected.  This reason will be returned to the
-    remote peer as well as logged to the news logs.  (innreport, in its
-    nightly report, will summarize the number of articles rejected by the
-    Perl filter and include a count of how many articles were rejected with
-    each reason string.)
-
-    One other type of filtering is also supported.  If Perl filtering is
-    turned on and the Perl function filter_messageid() is defined, that
-    function will be called for each message ID received from a peer (via
-    either CHECK or IHAVE).  The function receives a single argument, the
-    message ID, and like filter_art() should return an empty string to
-    accept the article or an error string to refuse the article.  This
-    function is called before any history lookups and for every article
-    offered to innd with CHECK or IHAVE (before the actual article is sent).
-    Accordingly, the message ID is the only information it has about the
-    article (the %hdr hash will be empty).  This code would sit in a
-    performance-critical hot path in a typical server, and therefore should
-    be as fast as possible, but it can do things like refuse articles from
-    certain hosts or cancels for already rejected articles (if they follow
-    the $alz convention) without having to take the network bandwidth hit of
-    accepting the entire article first.
-
-    Note that you cannot rely on filter_messageid() being called for every
-    incoming article; articles sent via TAKETHIS without an earlier CHECK
-    will never pass through filter_messageid() and will only go through
-    filter_art().
-
-    Finally, whenever ctlinnd throttle, ctlinnd pause, or ctlinnd go is run,
-    the Perl function filter_mode() is called if it exists.  It receives no
-    arguments and returns no value, but it has access to a global hash %mode
-    that contains three values:
-
-        Mode       The current server mode (throttled, paused, or running)
-        NewMode    The new mode the server is going to
-        reason     The reason that was given to ctlinnd
-
-    One possible use for this function is to save filter state across a
-    restart of innd.  There isn't any Perl function which is called when INN
-    shuts down, but using filter_mode() the Perl filter can dump it's state
-    to disk whenever INN is throttled.  Then, if the news administrator
-    follows the strongly recommended shutdown procedure of throttling the
-    server before shutting it down, the filter state will be safely saved to
-    disk and can be reloaded when innd restarts (possibly by
-    startup_innd.pl).
-
-    The state of the Perl interpretor in which all of these Perl functions
-    run is preserved over the lifetime of innd.  In other words, it's
-    permissible for the Perl code to create its own global Perl variables,
-    data structures, saved state, and the like, and all of that will be
-    available to filter_art() and filter_messageid() each time they're
-    called.  The only variable INN fiddles with (or pays any attention to at
-    all) is %hdr, which is cleared after each call to filter_art().
-
-    Perl filtering can be turned off with "ctlinnd perl n" and back on again
-    with "ctlinnd perl y".  Perl filtering is turned off automatically if
-    loading of the filter fails or if the filter code returns any sort of a
-    fatal error (either due to Perl itself or due to a "die" in the Perl
-    code).
-
-Supported innd Callbacks
-
-    innd makes seven functions available to any of its embedded Perl code. 
-    Those are:
-
-    INN::addhist(*messageid*, *arrival*, *articledate*, *expire*, *paths*)
-        Adds *messageid* to the history database.  All of the arguments
-        except the first one are optional; the times default to the current
-        time and the paths field defaults to the empty string.  (For those
-        unfamiliar with the fields of a history(5) database entry, the
-        *arrival* is normally the time at which the server accepts the
-        article, the *articledate* is from the Date header of the article,
-        the *expire* is from the Expires header of the article, and the
-        *paths* field is the storage API token.  All three times as measured
-        as a time_t since the epoch.)  Returns true on success, false
-        otherwise.
-
-    INN::article(*messageid*)
-        Returns the full article (as a simple string) identified by
-        *messageid*, or undef if it isn't found.  Each line will end with a
-        simple \n, but leading periods may still be doubled if the article
-        is stored in wire format.
-
-    INN::cancel(*messageid*)
-        Cancels *messageid*.  (This is equivalent to "ctlinnd cancel"; it
-        cancels the message on the local server, but doesn't post a cancel
-        message or do anything else that affects anything other than the
-        local server.) Returns true on success, false otherwise.
-
-    INN::filesfor(*messageid*)
-        Returns the *paths* field of the history entry for the given
-        *messageid*.  This will be the storage API token for the message. 
-        If *messageid* isn't found in the history database, returns undef.
-
-    INN::havehist(*messageid*)
-        Looks up *messageid* in the history database and returns true if
-        it's found, false otherwise.
-
-    INN::head(*messageid*)
-        Returns the header (as a simple string) of the article identified by
-        *messageid*, or undef if it isn't found.  Each line will end with a
-        simple \n (in other words, regardless of the format of article
-        storage, the returned string won't be in wire format).
-
-    INN::newsgroup(*newsgroup*)
-        Returns the status of *newsgroup* (the last field of the active file
-        entry for that newsgroup).  See active(5) for a description of the
-        possible values and their meanings (the most common are "y" for an
-        unmoderated group and "m" for a moderated group).  If *newsgroup*
-        isn't in the active file, returns undef.
-
-    These functions can only be used from inside the innd Perl filter;
-    they're not available in the nnrpd filter.
-
-Common Callbacks
-
-    The following additional function is available from inside filters
-    embedded in innd, and is also available from filters embedded in nnrpd
-    (see below):
-
-    INN::syslog(level, message)
-        Logs a message via syslog(2).  This is quite a bit more reliable and
-        portable than trying to use Sys::Syslog from inside the Perl filter.
-        Only the first character of the level argument matters; the valid
-        letters are the first letters of ALERT, CRIT, ERR, WARNING, NOTICE,
-        INFO, and DEBUG (case-insensitive) and specify the priority at which
-        the message is logged.  If a level that doesn't match any of those
-        levels is given, the default priority level is LOG_NOTICE.  The
-        second argument is the message to log; it will be prefixed by
-        "filter: " and logged to syslog with facility LOG_NEWS.
-
-The nnrpd Posting Filter
-
-    Whenever Perl support is needed in nnrpd, it first loads the file
-    _PATH_PERL_FILTER_NNRPD (defined in include/paths.h, by default
-    filter_nnrpd.pl).  This file must be located in the directory specified
-    by pathfilter in inn.conf (/usr/local/news/bin/filter by default).  The
-    default directory for filter code can be specified at configure time by
-    giving the flag --with-filter-dir to configure.
-
-    If filter_nnrpd.pl loads successfully and defines the Perl function
-    filter_post(), Perl filtering is turned on.  Otherwise, it's turned off.
-    If filter_post() ever returns a fatal error (either from Perl or from a
-    "die" in the Perl code), Perl filtering is turned off for the life of
-    that nnrpd process and any further posts made during that session won't
-    go through the filter.
-
-    While Perl filtering is on, every article received by nnrpd via the POST
-    command is passed to the filter_post() Perl function before it is passed
-    to INN (or mailed to the moderator of a moderated newsgroup).  If
-    filter_post() returns an empty string (''), the article is accepted and
-    normal processing of it continues.  Otherwise, the article is rejected
-    and the string returned by filter_post() is returned to the client as
-    the error message (with some exceptions; see below).
-
-    filter_post() has access to a global hash %hdr, which contains all of
-    the headers of the article.  (Unlike the innd Perl filter, %hdr for the
-    nnrpd Perl filter contains *all* of the headers, not just the standard
-    ones.  If any of the headers are duplicated, though, %hdr will contain
-    only the value of the last occurance of the header.  nnrpd will reject
-    the article before the filter runs if any of the standard headers are
-    duplicated.)  It also has access to the full body of the article in the
-    variable $body, and if the poster authenticated via AUTHINFO (or if
-    either Perl authentication or a readers.conf authentication method is
-    used and produces user information), it has access to the authenticated
-    username of the poster in the variable $user.
-
-    Unlike the innd Perl filter, the nnrpd Perl filter can modify the %hdr
-    hash.  In fact, if the Perl variable $modify_headers is set to true
-    after filter_post() returns, the contents of the %hdr hash will be
-    written back to the article replacing the original headers. 
-    filter_post() can therefore make any modifications it wishes to the
-    headers and those modifications will be reflected in the article as it's
-    finally posted.  The article body cannot be modified in this way; any
-    changes to $body will just be ignored.
-
-    Be careful when using the ability to modify headers.  filter_post() runs
-    after all the normal consistency checks on the headers and after server
-    supplied headers (like Message-ID: and Date:) are filled in.  Deleting
-    required headers or modifying headers that need to follow a strict
-    format can result in nnrpd trying to post nonsense articles (which will
-    probably then be rejected by innd).  If $modify_headers is set,
-    *everything* in the %hdr hash is taken to be article headers and added
-    to the article.
-
-    If filter_post() returns something other than the empty string, this
-    message is normally returned to the client as an error.  There are two
-    exceptions:  If the string returned begins with "DROP", the post will be
-    silently discarded and success returned to the client.  If the string
-    begins with "SPOOL", success is returned to the client, but the post is
-    saved in a directory named "spam" under the directory specified by
-    pathincoming in inn.conf (in a directory named "spam/mod" if the post is
-    to a moderated group).  This is intended to allow manual inspection of
-    the suspect messages; if they should be posted, they can be manually
-    moved out of the subdirectory to the directory specified by pathincoming
-    in inn.conf, where they can be posted by running "rnews -U".  If you use
-    this functionality, make sure those directories exist.
-
-Changes to Perl Authentication Support for nnrpd
-
-    The old authentication functionality has been combined with the new
-    readers.conf mechanism by Erik Klavon <erik@eriq.org>; bug reports
-    should however go to inn-bugs@isc.org, not Erik.
-
-    The remainder of this section is an introduction to the new mechanism
-    (which uses the perl_auth: and perl_access: readers.conf parameters)
-    with porting/migration suggestions for people familiar with the old
-    mechanism (identifiable by the nnrpperlauth: parameter in inn.conf).
-
-    Other people should skip this section.
-
-    The perl_auth parameter allows the use of Perl to authenticate a user. 
-    Scripts (like those from the old mechanism) are listed in readers.conf
-    using perl_auth in the same manner other authenticators are using auth:
-
-        perl_auth: "/path/to/script/auth1.pl"
-
-    The file given as argument to perl_auth should contain the same
-    procedures as before. The global hash %attributes remains the same,
-    except for the removal of the "type" entry which is no longer needed in
-    this modification and the addition of several new entries (port,
-    intipaddr, intport) described below. The return array now only contains
-    either two or three elements, the first of which is the NNTP return
-    code. The second is an error string which is passed to the client if the
-    error code indicates that the authentication attempt has failed. This
-    allows a specific error message to be generated by the perl script in
-    place of "Authentication failed". An optional third return element if
-    present will be used to match the connection with the users: parameter
-    in access groups and will also be the username logged. If this element
-    is absent, the username supplied by the client during authentication
-    will be used as was the previous behavior.
-
-    The perl_access parameter (described below) is also new; it allows the
-    dynamic generation of an access group for an incoming connection using a
-    Perl script.  If a connection matches an auth group which has a
-    perl_access parameter, all access groups in readers.conf are ignored;
-    instead the procedure described below is used to generate an access
-    group.  This concept is due to Jeffrey M. Vinocur.
-
-    The new functionality should provide all of the existing capabilities of
-    the Perl hook, in combination with the flexibility of readers.conf and
-    the use of other authentication and resolving programs.  To use Perl
-    authentication code that predates the readers.conf mechanism, you would
-    need to modify the code slightly (see below for the new specification)
-    and supply a simple readers.conf file.  If you don't want to modify your
-    code, the samples directory has nnrpd_auth_wrapper.pl and
-    nnrpd_access_wrapper.pl which should allow you to use your old code
-    without needing to change it.
-
-    However, before trying to use your old Perl code, you may want to
-    consider replacing it entirely with non-Perl authentication.  (With
-    readers.conf and the regular authenticator and resolver programs, much
-    of what once required Perl can be done directly.)  Even if the
-    functionality is not available directly, you may wish to write a new
-    authenticator or resolver (which can be done in whatever language you
-    prefer to work in).
-
-Perl Authentication Support for nnrpd
-
-    Support for authentication via Perl is provided in nnrpd by the
-    inclusion of a perl_auth: parameter in a readers.conf auth group.
-    perl_auth: works exactly like the auth: parameter in readers.conf,
-    except that it calls the script given as argument using the Perl hook
-    rather then treating it as an external program.
-
-    If the processing of readers.conf requires that a perl_auth: statement
-    be used for authentication, Perl is loaded (if it has yet to be) and the
-    file given as argument to the perl_auth: parameter is loaded as well. If
-    a Perl function auth_init() is defined by that file, it is called
-    immediately after the file is loaded.  It takes no arguments and returns
-    nothing.
-
-    Provided the file loads without errors, auth_init() (if present) runs
-    without fatal errors, and a Perl function authenticate() is defined,
-    authenticate() will then be called. authenticate() takes no arguments,
-    but it has access to a global hash %attributes which contains
-    information about the connection as follows: $attributes{hostname} will
-    contain the hostname (or the IP address if it doesn't resolve) of the
-    client machine, $attributes{ipaddress} will contain its IP address (as a
-    string), $attributes{port} will contain the client port (as an integer),
-    $attributes{interface} contains the hostname of the interface the client
-    connected on, $attributes{intipaddr} contains the IP address (as a
-    string) of the interface the client connected on, $attributes{intport}
-    contains the port (as an integer) on the interface the client connected
-    on, $attributes{username} will contain the provided username and
-    $attributes{password} the password.
-
-    authenticate() should return a two or three element array.  The first
-    element is the NNTP response code to return to the client, the second
-    element is an error string which is passed to the client if the response
-    code indicates that the authentication attempt has failed. An optional
-    third return element if present will be used to match the connection
-    with the users: parameter in access groups and will also be the username
-    logged. If this element is absent, the username supplied by the client
-    during authentication will be used for matching and logging.
-
-    The NNTP response code should probably be either 281 (authentication
-    successful) or 502 (authentication unsuccessful).  If the code returned
-    is anything other than 281, nnrpd will print an authentication error
-    message and drop the connection and exit.
-
-    If authenticate() dies (either due to a Perl error or due to calling
-    die), or if it returns anything other than the two or three element
-    array described above, an internal error will be reported to the client,
-    the exact error will be logged to syslog, and nnrpd will drop the
-    connection and exit.
-
-Dynamic Generation of Access Groups
-
-    A Perl script may be used to dynamically generate an access group which
-    is then used to determine the access rights of the client. This occurs
-    whenever the perl_access: is specified in an auth group which has
-    successfully matched the client. Only one perl_access: statement is
-    allowed in an auth group. This parameter should not be mixed with a
-    python_access: statement in the same auth group.
-
-    When a perl_access: parameter is encountered, Perl is loaded (if it has
-    yet to be) and the file given as argument is loaded as well. Provided
-    the file loads without errors, and a Perl function access() is defined,
-    access() will then be called. access() takes no arguments, but it has
-    access to a global hash %attributes which contains information about the
-    connection as follows: $attributes{hostname} will contain the hostname
-    (or the IP address if it doesn't resolve) of the client machine,
-    $attributes{ipaddress} will contain its IP address (as a string),
-    $attributes{port} will contain the client port (as an integer),
-    $attributes{interface} contains the hostname of the interface the client
-    connected on, $attributes{intipaddr} contains the IP address (as a
-    string) of the interface the client connected on, $attributes{intport}
-    contains the port (as an integer) on the interface the client connected
-    on, $attributes{username} will contain the provided username and domain
-    (in username@domain form).
-
-    access() returns a hash, containing the desired access parameters and
-    values.  Here is an untested example showing how to dynamically generate
-    a list of newsgroups based on the client's username and domain.
-
-         my %hosts = ( "example.com" => "example.*", "isc.org" => "isc.*" );
-
-         sub access {
-            %return_hash = (
-               "max_rate" => "10000",
-               "addnntppostinghost" => "true",
-         #     ...
-            );
-            if( defined $attributes{username} &&
-                $attributes{username} =~ /.*@(.*)/ )
-            {
-               $return_hash{"virtualhost"} = "true";
-               $return_hash{"path"} = $1;
-               $return_hash{"newsgroups"} = $hosts{$1};
-            } else {
-               $return_hash{"read"} = "*";
-               $return_hash{"post"} = "local.*"
-            }
-            return %return_hash;
-         }
-
-    Note that both the keys and values are quoted strings. These values are
-    to be returned to a C program and must be quoted strings. For values
-    containing one or more spaces, it is not necessary to include extra
-    quotes inside the string.
-
-    While you may include the users: parameter in a dynamically generated
-    access group, some care should be taken (unless your pattern is just *
-    which is equivalent to leaving the parameter out). The group created
-    with the values returned from the Perl script is the only one considered
-    when nnrpd attempts to find an access group matching the connection. If
-    a users: parameter is included and it doesn't match the connection, then
-    the client will be denied access since there are no other access groups
-    which could match the connection.
-
-    If access() dies (either due to a Perl error or due to calling die), or
-    if it returns anything other than a hash as described above, an internal
-    error will be reported to the client, the exact error will be logged to
-    syslog, and nnrpd will drop the connection and exit.
-
-Notes on Writing Embedded Perl
-
-    All Perl evaluation is done inside an implicit eval block, so calling
-    die in Perl code will not kill the innd or nnrpd process.  Neither will
-    Perl errors (such as syntax errors).  However, such errors will have
-    negative effects (fatal errors in the innd or nnrpd filter will cause
-    filtering to be disabled, and fatal errors in the nnrpd authentication
-    code will cause the client connection to be terminated).
-
-    Calling exit directly, however, *will* kill the innd or nnrpd process,
-    so don't do that.  Similarly, you probably don't want to call fork (or
-    any other function that results in a fork such as system,
-    IPC::Open3::open3(), or any use of backticks) since there are possibly
-    unflushed buffers that could get flushed twice, lots of open state that
-    may not get closed properly, and innumerable other potential problems. 
-    In general, be aware that all Perl code is running inside a large and
-    complicated C program, and Perl code that impacts the process as a whole
-    is best avoided.
-
-    You can use print and warn inside Perl code to send output to STDOUT or
-    STDERR, but you probably shouldn't.  Instead, open a log file and print
-    to it instead (or, in the innd filter, use INN::syslog() to write
-    messages via syslog like the rest of INN).  If you write to STDOUT or
-    STDERR, where that data will go depends on where the filter is running;
-    inside innd, it will go to the news log or the errlog, and inside nnrpd
-    it will probably go nowhere but could go to the client.  The nnrpd
-    filter takes some steps to try to keep output from going across the
-    network connection to the client (which would probably result in a very
-    confused client), but best not to take the chance.
-
-    For similar reasons, try to make your Perl code -w clean, since Perl
-    warnings are written to STDERR.  (INN won't run your code under -w, but
-    better safe than sorry, and some versions of Perl have some mandatory
-    warnings you can't turn off.)
-
-    You *can* use modules in your Perl code, just like you would in an
-    ordinary Perl script.  You can even use modules that dynamically load C
-    code.  Just make sure that none of the modules you use go off behind
-    your back to do any of the things above that are best avoided.
-
-    Whenever you make any modifications to the Perl code, and particularly
-    before starting INN or reloading filter.perl with new code, you should
-    run perl -wc on the file.  This will at least make sure you don't have
-    any glaring syntax errors.  Remember, if there are errors in your code,
-    filtering will be disabled, which could mean that posts you really
-    wanted to reject will leak through and authentication of readers may be
-    totally broken.
-
-    The samples directory has example startup_innd.pl, filter_innd.pl,
-    filter_nnrpd.pl, and nnrpd_auth.pl files that contain some simplistic
-    examples.  Look them over as a starting point when writing your own.
-
-Available Packages
-
-    This is an unofficial list of known filtering packages at the time of
-    publication.  This is not an endorsement of these filters by the ISC or
-    the INN developers, but is included as assistance in locating packages
-    which make use of this filter mechanism.
-
-      CleanFeed               Jeremy Nixon <jeremy@exit109.com>
-      <URL:http://www.exit109.com/~jeremy/news/cleanfeed.html>
-            A spam filter catching excessive multi-posting and a host of
-            other things.  Uses filter_innd.pl exclusively, requires the MD5
-            Perl module.  Probably the most popular and widely-used Perl
-            filter around.
-
-      Usenet II Filter        Edward S. Marshall <emarshal@xnet.com>
-      <URL:http://www.xnet.com/~emarshal/inn/filter_nnrpd.pl>
-            Checks for "soundness" according to Usenet II guidelines in the
-            net.* hierarchy.  Designed to use filter_nnrpd.pl.
-
-      News Gizmo              Aidan Cully <aidan@panix.com>
-      <URL:http://www.panix.com/gizmo/>
-            A posting filter for helping a site enforce Usenet-II soundness,
-            and for quotaing the number of messages any user can post to
-            Usenet daily.