OSSP CVS Repository

ossp - Check-in [2081]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 2081
Date: 2002-Apr-18 15:31:27 (local)
2002-Apr-18 13:31:27 (UTC)
User:thl
Branch:
Comment: updated documentation, aligned and sorted source;
Tickets:
Inspections:
Files:
ossp-pkg/lmtp2nntp/lmtp2nntp.pod      1.36 -> 1.37     220 inserted, 113 deleted
ossp-pkg/lmtp2nntp/lmtp2nntp_config.c      1.69 -> 1.70     48 inserted, 2 deleted
ossp-pkg/lmtp2nntp/lmtp2nntp_option.c      1.17 -> 1.18     29 inserted, 29 deleted

ossp-pkg/lmtp2nntp/lmtp2nntp.pod 1.36 -> 1.37

--- lmtp2nntp.pod        2002/01/31 15:13:16     1.36
+++ lmtp2nntp.pod        2002/04/18 13:31:27     1.37
@@ -33,119 +33,138 @@
 =head1 SYNOPSIS
 
 B<lmtp2nntp>
-[B<-C> I<childsmax>]
-[B<-D>]
-[B<-K>]
-[B<-P> I<pidfile>]
-[B<-V>]
-[B<-a> I<addr>/I<mask>[,I<addr>/I<mask>[,...]]
-[B<-b> I<addr>[I<:port>]|C<->|I<path>[:perms]]
-[B<-c> I<addr>[I<:port>]]
-[B<-d> I<addr>[I<:port>][,I<addr>[I<:port>], ...]]
-[B<-g> I<groupmode>]
-[B<-h> I<header>:<value>]
-[B<-l> I<level>[:I<logfile>]]
-[B<-m> I<mailfrom>]
-[B<-n> I<nodename>]
-[B<-o> I<operationmode>]
-[B<-r> I<restrictheader>]
-[B<-s> I<size>]
-[B<-t> I<name>=I<sec>[,I<name>=I<sec>[,...]]
-[B<-u> I<uid>]
-[B<-v>]
-I<newsgroup> [I<newsgroup> ...]
+[B<--childsmax|-C> I<childsmax>]
+[B<--daemonize|-D>]
+[B<--kill|-K>]
+[B<--pidfile|-P> I<filename>]
+[B<--acl|-a> I<addr>/I<mask> (LMTP daemon ACL)]
+[B<--bind|-b> I<addr>[I<:port>]|C<->|I<path[:perms]> (LMTP daemon bind)]
+[B<--client|-c> I<addr>[I<:port>] (NNTP client bind)]
+[B<--destination|-d> I<addr>[I<:port>] (NNTP client destination)]
+[B<--groupmode|-g> I<groupmode>]
+[B<--headerrule|-h> [I<pri>]:[I<regex>]:I<header>:[I<val>]]
+[B<--include|-i> I<configfile>]
+[B<--l2spec|-l> I<l2spec>]
+[B<--mailfrom|-m> I<regex>]
+[B<--nodename|-n> I<name>]
+[B<--operationmode|-o> I<abc/a.d.e|post|feed>]
+[B<--restrictheader|-r> I<regex>]
+[B<--size|-s> I<bytes>]
+[B<--testfile|-t> I<filename>]
+[B<--timeoutlmtp> I<sec>]
+[B<--timeoutlmtpaccept> I<sec>]
+[B<--timeoutlmtpread> I<sec>]
+[B<--timeoutlmtpwrite> I<sec>]
+[B<--timeoutnntp> I<sec>]
+[B<--timeoutnntpconnect> I<sec>]
+[B<--timeoutnntpread> I<sec>]
+[B<--timeoutnntpwrite> I<sec>]
+[B<--user|-u> I<uid|name>]
+[B<--version|-v>]
+I<--newsgroup> I<newsgroup|wildmat> [I<newsgroup> ...]
 
 =head1 DESCRIPTION
 
 The B<OSSP lmtp2nntp> program is an LMTP service for use in conjunction
 with an MTA (like Sendmail), providing a reliable real-time mail to news
-gateway. Input messages get their headers slightly reformatted to match
-Usenet news article format. The article is then posted or feeded into
+gateway. Input messages get their headers reformatted according to configurable rewrite rules.
+The article is then posted or feeded into
 a remote NNTP service (like INN). Delivery must take place immediately
 or the transaction fails. B<OSSP lmtp2nntp> relies on the queuing
 capabilities of the MTA in order to provide a fully reliable service.
-For this the program returns proper delivery status notification which
+The program returns proper delivery status notification which
 indicates successful completed action, persistent transient failure or
 permanent failure.
 
+Configuration files can be specified to reduce the complexity of command
+lines. Their content has a simple "command WHITESPACE argument" syntax
+where commands and their arguments map exactly to the long options, with
+dashes omitted.  There is no artifical difference between using command
+line and using configuration files. The only practical impact is that
+the shell expands metacharacters while those have no special meaning
+inside the configuration file.  However, shell style line concatenation
+through BACKSLASH and comments through HASH are supported.
+
+Options belong to one of the three classes SINGLE, FLAG or MULTI. Any
+option can be specified more than once. Those belonging to SINGLE and
+FLAG class can appear multiple times but only the last occurrence in
+terms of parsing sequence counts while those belonging to MULTI class
+handle their arguments as a array. SINGLE and MULTI require an argument,
+FLAG does not allow an argument.
+
 The following command line options and arguments are available:
 
 =over 4
 
-=item B<-C> I<childsmax>
+=item B<--childsmax|-C> I<childsmax>
 
-Childs the daemon spawns at maximum. Default is 10.
+Childs the daemon spawns at max. Default is 10. SINGLE.
 
-=item B<-D>
+=item B<--daemonize|-D>
 
-Daemonize program and detach from current terminal.
+Daemonize and detach from current terminal. FLAG.
 
-=item B<-K>
+=item B<--kill|-K>
 
-Kill the daemon. After processing this option the program is terminated so
+Kill a previously run daemon. After processing this option the program is terminated so
 this option effectivly renders most other options invalid not including
 specification of a pidfile and logging. The pid must be listed in pidfile.
+FLAG.
 
-=item B<-P> I<pidfile>
+=item B<--pidfile|-P> I<filename>
 
-Pidfile to remember the process ID when running as or killing the daemon. Care
+Pidfile holding the process ID. Written when daemonizing. Read when killing a previously run daemon. Care
 must be taken when using relative path names as daemonizing changes the
-current working directory to '/'.
-
-=item B<-V>
-
-Very verbose logging. This means logging is unbuffered.
+current working directory to '/' before the file is opened. SINGLE.
 
-=item B<-a> I<addr>/I<mask>[,I<addr>/I<mask>[,...]] (LMTP daemon ACL)
+=item B<--acl|-a> I<addr>/I<mask> (LMTP daemon ACL)
 
 Access control list specifying TCP INET addresses and masks where incoming
-LMTP connections are accepted from. This option can be specified more than
-once and it is possible to specify more than one addr/ mask per option as a
-comma-separated list. Omitting a mask defaults to a host comparison. The mask
+LMTP connections are accepted from.
+Omitting a mask defaults to a host comparison. The mask
 is a CIDR style bitmask where /0 means no comparison and enforces a match.
-Omitting the wholly option defaults to 0.0.0.0/0 which allows access from
-everywhere.  It is possible to specify both inclusive and exclusive addresses,
+Omitting the wholly option defaults to 0.0.0.0/0 and [::] which allows access from
+any IPv4 or IPv6 host.  It is possible to specify both inclusive and exclusive addresses,
 the latter have to prefixed with an exclamation mark. In order to pass the ACL
 a client must match any inclusion and not match any exclusion. If you specify
-exclusions only a fake inclusion of 0.0.0.0/0 is appended internally.  Any
-addr can be a name to be resolved first.
+exclusions only, a fake inclusion of 0.0.0.0/0 and [::] is appended internally.  Any
+addr can be a name which will be resolved on program launch time. MULTI.
 
-FIXME should we resolv on startup only or for every access or using dns ttl
-
-=item B<-b> I<addr>[I<:port>]|C<->|I<path[:perms]> (LMTP daemon bind)
+=item B<--bind|-b> I<addr>[I<:port>]|C<->|I<path[:perms]> (LMTP daemon bind)
 
 Bind address accepting incoming LMTP connections. Supported are "C<->" for
 stdio, I<path>[:perms] for Unix Domain socket with optional chmod-like
 permissions and I<addr>[I<:port>] for TCP INET socket. Omitting this option
 defaults to stdio. The path for a UNIX domain socket must start with a slash.
-The addr can be a name to be resolved first.
+The addr can be a name which will be resolved on program launch time.
+SINGLE.
 
-=item B<-c> I<addr>[I<:port>] (NNTP client bind)
+=item B<--client|-c> I<addr>[I<:port>] (NNTP client bind)
 
 Client connections for outgoing NNTP communication bind to this address. If an
 address is specified but port is omitted the kernel chooses an ephemeral port.
-If you want to specify a port but no address replace address with all zeroes.
-If completely omitted, 0.0.0.0:0 is assumed which causes the kernel to choose
+If you want to specify a port but no address then replace address with all zeroes.
+If completely omitted, no assumptions are made which causes the kernel to choose
 an address based on routing information and an ephemeral port.  The addr can
-be a name to be resolved first.
+be a name which will be resolved on program launch time. SINGLE.
 
-=item B<-d> I<addr>[I<:port>][,I<addr>[I<:port>], ...] (NNTP client peer)
+=item B<--destination|-d> I<addr>[I<:port>] (NNTP client destination)
 
 Destination hostname or address and optional TCP port of a NNTP service.
 Unless a port is specified, getserbyname(nntp) is queried with fallback to
-119/tcp. If C<-d> option is ommited, the environment variable C<NNTPSERVER> is
-read, if this is undefined or empty C<news> is used and if this doesn't
-resolve, C<localhost> is assumed.  This option can be specified more than once
-and it is possible to specify more than one host/ port per option as a
-comma-separated list.  Any addr can be a name to be resolved first.  It is
+119/tcp. If C<-d> option is ommited, 
+C<news> is used and if this doesn't
+resolve, C<localhost> is assumed.  
+Any addr can be a name which will be resolved on program launch time. It is
 assumed that multiple servers are used to increase the reliability of the news
 system and to speed up distribution by posting the same article to more than
 one server.  In regard to this program they must provide the same groups and
-talk to each other. 
+talk to each other. MULTI.
 
-=item B<-g> I<groupmode>
+=item B<--groupmode|-g> I<groupmode>
 
-Possible values for I<groupmode> are C<arg> (default), C<envelope> and
+Groupmode configures news group(s).
+Possible values are C<arg> (default), C<envelope> and
 C<header>. In C<arg> mode, the C<newsgroup>s specified as command line
 arguments are ultimate destinations for the received messages.  Addresses from
 envelope and headers are ignored.  In C<envelope> mode the newsgroup(s) are
@@ -154,39 +173,98 @@
 C<envelope> and C<header> mode groups must still be specified as command line
 arguments. However, in these modes the command line arguments are filters
 representing allowed groups. Filters can be specified as wildmat's.
+MULTI.
 
-=item B<-h> I<header>:<value>
+=item B<--headerrule|-h> [I<pri>]:[I<regex>]:I<header>:[I<val>]
 
-Header with value to to be inserted into message before delivery.  This option
-can be specified more than once.  Useful for specifiying an moderator Email
-address to all outgoing news messages by applying an "Approved:" header.
-
-=item B<-l> I<level>[:I<logfile>]
-
-The level measures the degree and importance of output and can be any of
-PANIC, CRITICAL, ERROR, WARNING, NOTICE, INFO, TRACE or DEBUG. The recommended
-level for daily operations is NOTICE. The default name for logfile is
-"logfile".  This program is using the logging library (l2) which is currently
-under development. An early access snapshot with limited functionality has
-been included.  Currently the common denominator of usage between lmtp2nntp
-and l2 is to use logging into a file only. Note that this will change soon as
-during integration of l2 into lmtp2nntp logging channels for local syslog and
-a SMTP client were already finished and IRC and NNTP clients are under
-development.
+Header rewriting rule. A message received by the LMTP server is split
+into header and body. The header is further split into a list where the
+headernames are uniqe keys to access single- or multivalues. The values
+are kept in sequence as they appeared in the original message. The
+gateway processes each rule in priority order. Small I<pri> numbers are
+processed first. The default prioriy is 500.  Each rule can modify a
+header and thus change the input of the remaining rules.  If a I<regex>
+is given, the rule processes all currently existing headers that match
+the regular expression. A new header I<header> with I<val> will be
+created.  With no I<regex> given, a new header with name I<header> and
+data I<val> is created.  In both cases, the new header will replace an
+existing header with the same name. Also, if the name or value ever
+becomes empty, the header is removed.  Omitting I<regex> and nothing
+found to replace, the new header will be appended. Processed headers
+will always be single-valued.  Omitting the I<val> means the (matching)
+I<header>(s) will be deleted.  The headderrules support PCRE (Perl
+compatible reguar expression) and if a I<regex> was used, the matching
+elements are available to I<header> and I<value> as "DOLLAR NUMBER".
+The I<value> is also processed through a variable expansion library
+which has access to all command line options, many internal variables
+and all currently existing headers. The expansion allows powerful
+constructs like joining multivalues into a single value.  MULTI.
+
+Functional diagram:
+
+    for each rule
+        if rule has regex
+            for each header
+                if regex matches
+                    create new header
+                    expanding regex references into header name
+                    if headername is empty
+                        delete header
+                    if headervalue is empty
+                        delete header
+                    expanding regex references into header value
+                    expanding variables into header value
+                    if headervalue is empty
+                        delete header
+                    replace existing header //FIXME text above
+        else
+            create new header
+            if headervalue is empty
+                delete header
+            expanding variables into header value
+            replace existing or append new header
+
+Further reading:
+
+- regular expressions see 'pcre' manual page
+- variable expansion see 'lib_var/var.pod' and 'lib_var/var_play'
+
+Variables:
+
+The variables use a hierarchical name space scheme. All options are
+available through '${option.I<optionname>}'. For options of class MULTI
+this yields the first element. Other elements can be accessed through
+'${option.I<optionname>[I<index>]}'. All headers can be accessed through
+'${msg.header.I<headername>}' and again, indexes are supported for
+multivalued headers.  FIXME functions
+
+=item B<--include|-i> I<configfile>
+
+Include a configuration file. There is no artifical limitation on the
+number and levels of configuration files supported. However, no attempt
+is made to prevent recursion. Order of inclusion matters for SINGLE and
+FLAG option classes. MULTI.
+
+=item B<--l2spec|-l> I<l2spec>
+
+L2 channel tree specification.  The full functionality of lib_l2 is
+exposed to the user, see 'lib_l2/l2.pod' when it becomes available and
+have a look at the example configuration file in the meantime. SINGLE.
 
-=item B<-m> I<mailfrom>
+=item B<--mailfrom|-m> I<regex>
 
-"MAIL From:" filter to limit sender addresses. If ommitted, anyone can send
+"Mail From:" envelope restriction to limit sender addresses. If ommitted, anyone can send
 mail. The value to be compared includes the angle brackets. Use a PCRE (Perl
-compatible reguar expression) for I<mailfrom>.
+compatible reguar expression) for I<mailfrom>. SINGLE.
 
-=item B<-n> I<nodename>
+=item B<--nodename|-n> I<name>
 
 Own FQDN used in LMTP and NNTP protocols. This overrides the nodename returned
-by uname(3).
-
-=item B<-o> I<operationmode>
+by uname(3). SINGLE.
 
+=item B<--operationmode|-o> I<abc/a.d.e|post|feed>
+     
+Set fake status or operationmode.
 Possible values for I<operationmode> are C<post>, C<feed> or a string in
 "LLL/D.D.D" format used to fake a LMTP return code.  In C<post> mode articles
 are sent to the NNTP server(s) using POST command. Before posting, a duplicate
@@ -198,47 +276,76 @@
 Delivery not authorized, message refused".  This is useful for debugging LMTP
 setups without engaging NNTP.  Fake mode makes it possible to run without any
 B<-d> option. However, if B<-d> option is given the NNTP client tries to
-connect but it's return codes are ignored.
+connect but it's return codes are ignored. SINGLE.
 
-=item B<-r> I<restrictheader>
+=item B<--restrictheader|-r> I<regex>
 
-Restricted headers. Messages with a matching restrictheader are rejected.  If
-ommitted no restrictions apply. Matching is done before -h headers are
-appended. Use a PCRE (Perl compatible reguar expression) for
-I<restrictheader>.
+Restrict messages by header. Messages with a matching restrictheader are rejected.  If
+ommitted no restrictions apply. Matching is done before headers are
+rewritten. Use a PCRE (Perl compatible reguar expression) for
+I<regex>. SINGLE.
 
-=item B<-s> I<size>
+=item B<--size|-s> I<bytes>
 
 Size limitation on message in bytes. Default is 8388608 (8M).
 
-=item B<-t> I<name>=I<sec>[,I<name>=I<sec>[,...]
+=item B<--testfile|-t> I<filename>
+
+Testfile for headerrule. Allows debugging without LMTP or NNTP activity.
+The file must be in RFC822 E-Mail format. Use this option for debugging
+only, it disables both the mail server and news client.
+
+=item B<--timeoutlmtp> I<sec>        
+
+LMTP server default timeout. Sets timeout for accept, read and write at
+once.  Setting sec to zero means to wait infinite.  Note that all LMTP
+timeouts only apply to socket operations, stdio always waits infinite.
+SINGLE.
+
+=item B<--timeoutlmtpaccept> I<sec>
+
+LMTP server accept timeout.  Default is 0.SINGLE.
+
+=item B<--timeoutlmtpread> I<sec>
+
+LMTP server read timeout. Default is 10. SINGLE.
+
+=item B<--timeoutlmtpwrite> I<sec>
+
+LMTP server write timeout. Default is 10. SINGLE.
+
+=item B<--timeoutnntp> I<sec>
+
+NNTP client default timeout. Sets timeout for connect, read and write at
+once.  Setting sec to zero means to wait infinite.  SINGLE.
+
+=item B<--timeoutnntpconnect> I<sec>
+
+NNTP client connect timeout. Default is 360. SINGLE.
+
+=item B<--timeoutnntpread> I<sec>
+
+NNTP client read timeout. Default is 60. SINGLE.
 
-Timeout for various actions. Possible names are C<lmtp> for any LMTP and
-C<nntp> for any NNTP actions. More granular actions can be specified according
-to the following table, which also lists the system defaults.  Setting sec to
-zero means to wait infinite. Note that LMTP timeouts only apply to socket
-operations, stdio always waits infinite.
+=item B<--timeoutnntpwrite> I<sec>
 
-    lmtp:accept  = 0
-    lmtp:read    = 10
-    lmtp:write   = 10
-    nntp:connect = 360
-    nntp:read    = 60
-    nntp:write   = 60
+NNTP client write timeout. Default is 60. SINGLE.
 
-=item B<-u> I<uid>
+=item B<--user|-u> I<uid|name>
 
-UID or login name to resolve to a UID to be set for program execution.
+User identity to be set for program execution. SINGLE.
 
-=item B<-v>
+=item B<--version|-v>
 
-Print version information.
+Version information is printed, then program exits. FLAG.
 
-=item I<newsgroup> [I<newsgroup> ...]
+=item I<--newsgroup> I<newsgroup|wildmat> [I<newsgroup> ...]
+=item I<newsgroup|wildmat> [I<newsgroup> ...]
 
-Newsgroup to post the message to or filter, depending on groupmode.  Multiple
-groups can be specified.  Crosspostings succeed if delivery to I<any> group
-succeeds.
+Newsgroup name or match. Depending on groupmode, this is a newsgroup to
+post or feed the message to or it is a wildmat filter.
+Crosspostings succeed if delivery to I<any> group
+succeeds. MULTI.
 
 =back
 


ossp-pkg/lmtp2nntp/lmtp2nntp_config.c 1.69 -> 1.70

--- lmtp2nntp_config.c   2002/03/13 16:22:09     1.69
+++ lmtp2nntp_config.c   2002/04/18 13:31:27     1.70
@@ -1263,6 +1263,48 @@
     return rc;
 }
 
+static var_rc_t operate_cb(
+    var_t *var, void *ctx,
+    const char  *op_ptr, size_t op_len,
+    const char  *arg_ptr, size_t arg_len,
+    const char  *val_ptr, size_t val_len,
+    char **out_ptr, size_t *out_len, size_t *out_size)
+{
+    int i;
+
+    if (val_ptr == NULL) {
+        *out_ptr = "";
+        *out_len = 0;
+        *out_size = 0;
+        return VAR_OK;
+    }
+    if (op_len == 6 && strncmp(op_ptr, "return", 6) == 0) {
+        *out_ptr = malloc(arg_len);
+        *out_len = arg_len;
+        *out_size = arg_len;
+        memcpy(*out_ptr, arg_ptr, arg_len);
+        return VAR_OK;
+    }
+    else if (op_len == 5 && strncmp(op_ptr, "upper", 5) == 0) {
+        *out_ptr = malloc(val_len);
+        *out_len = val_len;
+        *out_size = val_len;
+        for (i = 0; i < val_len; i++)
+            (*out_ptr)[i] = (char)toupper((int)(val_ptr[i]));
+        return VAR_OK;
+    }
+    else if (op_len == 5 && strncmp(op_ptr, "lower", 5) == 0) {
+        *out_ptr = malloc(val_len);
+        *out_len = val_len;
+        *out_size = val_len;
+        for (i = 0; i < val_len; i++)
+            (*out_ptr)[i] = (char)tolower((int)(val_ptr[i]));
+        return VAR_OK;
+    }
+    else 
+        return VAR_ERR_UNDEFINED_OPERATION;
+}
+
 void msg_headermatrixbuildup(msg_t *msg)
 {
     ex_t ex;
@@ -1405,6 +1447,10 @@
         logbook(ctx->l2, L2_LEVEL_ERROR, "configure regex callback failed with %s (%d)", var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
         throw(0,0,0);
     }
+    if ((rc = var_config(ctx->config_varregex, VAR_CONFIG_CB_OPERATION, operate_cb, NULL)) != VAR_OK) {
+        logbook(ctx->l2, L2_LEVEL_ERROR, "configure operate callback failed with %s (%d)", var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+        throw(0,0,0);
+    }
     for (hrI = ctx->option_firstheaderrule; hrI != NULL; hrI = hrI->next) { /* for each rule */
         { //FIXME debug code block
             int i;
@@ -1476,7 +1522,7 @@
                             logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
                             cp = res_ptr;
                         }
-                        /* expanding header and other variables into header value */
+                        /* expanding variables into header value */
                         if (hrI->val != NULL) {
                             var_rc_t var_rc;
                             char *res_ptr;
@@ -1515,7 +1561,7 @@
             }
             else {
                 /*FIXME clean up data.m */
-                /* expanding header and other variables into header value */
+                /* expanding variables into header value */
                 var_rc_t var_rc;
                 char *res_ptr;
                 logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding variables in header value '%s'", hrI->val);


ossp-pkg/lmtp2nntp/lmtp2nntp_option.c 1.17 -> 1.18

--- lmtp2nntp_option.c   2002/03/07 16:03:56     1.17
+++ lmtp2nntp_option.c   2002/04/18 13:31:27     1.18
@@ -548,35 +548,35 @@
         return OPTION_ERR_ARG;
 
     try {
-        option_register(o, "childsmax",          'C', OPT_SINGLE,  "10",        "childs to spawn at max",            "childsmax",                  &stdsyntax, "m/\\d+/" ); //"m/[0-9]+/" );
-        option_register(o, "daemonize",          'D', OPT_FLAG,    NULL,        "detach from terminal",              NULL,                         &stdsyntax, NULL );
-        option_register(o, "kill",               'K', OPT_FLAG,    NULL,        "kill a previously run daemon",      NULL,                         &stdsyntax, NULL );
-        option_register(o, "pidfile",            'P', OPT_SINGLE,  NULL,        "file containing pid",               "pidfile",                    &stdsyntax, "m/.*/" );
-        option_register(o, "acl",                'a', OPT_MULTI,   NULL,        "LMTP server access control list",   "addr[/mask]",                &stdsyntax, "m/.*/" );
-        option_register(o, "bind",               'b', OPT_SINGLE,  NULL,        "LMTP server bind",                  "addr[:port]|-|path[:perms]", &stdsyntax, "m/.*/" );
-        option_register(o, "client",             'c', OPT_SINGLE,  NULL,        "NNTP client bind",                  "addr[:port]",                &stdsyntax, "m/.*/" );
-        option_register(o, "destination",        'd', OPT_MULTI,   NULL,        "NNTP client destination",           "addr[:port]",                &stdsyntax, "m/.*/" );
-        option_register(o, "groupmode",          'g', OPT_SINGLE,  "arg",       "arg|envelope|header",               "groupmode",                  &stdsyntax, "m/.*/" ); //"m/(arg|envelope|header)/" );
-        option_register(o, "headerrule",         'h', OPT_MULTI,   NULL,        "header rewriting rule",             "[pri]:[regex]:header:[val]", &stdsyntax, "m/^[0-9]*:.*:.+:.*$/" );
-        option_register(o, "include",            'i', OPT_MULTI,   NULL,        "configfile to include",             "configfile",                 &includeit, "m/.*/" );
-        option_register(o, "timeoutlmtp",        NUL, OPT_SINGLE,  NULL,        "LMTP server default timeout",       "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutlmtpaccept",  NUL, OPT_SINGLE,  "0",         "LMTP server accept timeout",        "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutlmtpread",    NUL, OPT_SINGLE,  "10",        "LMTP server read timeout",          "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutlmtpwrite",   NUL, OPT_SINGLE,  "10",        "LMTP server write timeout",         "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutnntp",        NUL, OPT_SINGLE,  NULL,        "NNTP client default timeout",       "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE,  "360",       "NNTP client connect timeout",       "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutnntpread",    NUL, OPT_SINGLE,  "60",        "NNTP client read timeout",          "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "timeoutnntpwrite",   NUL, OPT_SINGLE,  "60",        "NNTP client write timeout",         "sec",                        &stdsyntax, "m/.*/" );
-        option_register(o, "l2spec",             'l', OPT_SINGLE,  NULL,        "L2 channel tree specification",     "l2spec",                     &stdsyntax, "m/.*/" );
-        option_register(o, "mailfrom",           'm', OPT_SINGLE,  NULL,        "mail from envelope restriction",    "regex",                      &stdsyntax, "m/.*/" );
-        option_register(o, "nodename",           'n', OPT_SINGLE,  NULL,        "nodename",                          "name",                       &stdsyntax, "m/.*/" );
-        option_register(o, "operationmode",      'o', OPT_SINGLE,  "553/5.7.1", "fakestatus or operationmode",       "abc/a.d.e|post|feed",        &stdsyntax, "m/.*/" ); //"m/([0-9]{3}\\/[0-9]\\.[0-9]\\.[0-9]|post|feed)/" ); /* 553 = Requested action not taken: mailbox name not allowed, 5.7.1 =  Delivery not authorized, message refused */
-        option_register(o, "restrictheader",     'r', OPT_SINGLE,  NULL,        "header restriction",                "regex",                      &stdsyntax, "m/.*/" );
-        option_register(o, "size",               's', OPT_SINGLE,  "8388608",   "maximum message size",              "bytes",                      &stdsyntax, "m/.*/" ); //"m/[0-9]+/" );
-        option_register(o, "testfile",           't', OPT_MULTI,   NULL,        "testfile for headerrule",           "testfile",                   &stdsyntax, "m/.*/" );
-        option_register(o, "user",               'u', OPT_SINGLE,  NULL,        "user",                              "uid|name",                   &stdsyntax, "m/.*/" );
-        option_register(o, "version",            'v', OPT_FLAG,    NULL,        "print version",                     NULL,                         &stdsyntax, NULL );
-        option_register(o, "newsgroup",          NUL, OPT_MULTI,   NULL,        "article destination",               "newsgroup",                  &stdsyntax, "m/.*/" );
+        option_register(o, "childsmax",          'C', OPT_SINGLE,  "10",        "Childs the daemon spawns at max.",   "childsmax",                  &stdsyntax, "m/\\d+/" ); //"m/[0-9]+/" );
+        option_register(o, "daemonize",          'D', OPT_FLAG,    NULL,        "Daemonize and detach from terminal", NULL,                         &stdsyntax, NULL );
+        option_register(o, "kill",               'K', OPT_FLAG,    NULL,        "Kill a previously run daemon",       NULL,                         &stdsyntax, NULL );
+        option_register(o, "pidfile",            'P', OPT_SINGLE,  NULL,        "Pidfile holding the process ID",     "filename",                   &stdsyntax, "m/.*/" );
+        option_register(o, "acl",                'a', OPT_MULTI,   NULL,        "LMTP daemon access control list",    "addr[/mask]",                &stdsyntax, "m/.*/" );
+        option_register(o, "bind",               'b', OPT_SINGLE,  NULL,        "LMTP daemon bind",                   "addr[:port]|-|path[:perms]", &stdsyntax, "m/.*/" );
+        option_register(o, "client",             'c', OPT_SINGLE,  NULL,        "NNTP client bind",                   "addr[:port]",                &stdsyntax, "m/.*/" );
+        option_register(o, "destination",        'd', OPT_MULTI,   NULL,        "NNTP client destination",            "addr[:port]",                &stdsyntax, "m/.*/" );
+        option_register(o, "groupmode",          'g', OPT_SINGLE,  "arg",       "Groupmode configures news group(s)", "arg|envelope|header",        &stdsyntax, "m/.*/" ); //"m/(arg|envelope|header)/" );
+        option_register(o, "headerrule",         'h', OPT_MULTI,   NULL,        "Header rewriting rule",              "[pri]:[regex]:header:[val]", &stdsyntax, "m/^[0-9]*:.*:.+:.*$/" );
+        option_register(o, "include",            'i', OPT_MULTI,   NULL,        "Include a configuration file",       "configfile",                 &includeit, "m/.*/" );
+        option_register(o, "l2spec",             'l', OPT_SINGLE,  NULL,        "L2 channel tree specification",      "l2spec",                     &stdsyntax, "m/.*/" );
+        option_register(o, "mailfrom",           'm', OPT_SINGLE,  NULL,        "Mail from envelope restriction",     "regex",                      &stdsyntax, "m/.*/" );
+        option_register(o, "nodename",           'n', OPT_SINGLE,  NULL,        "System nodename",                    "name",                       &stdsyntax, "m/.*/" );
+        option_register(o, "operationmode",      'o', OPT_SINGLE,  "553/5.7.1", "Set fake status or operationmode",   "abc/a.d.e|post|feed",        &stdsyntax, "m/.*/" ); //"m/([0-9]{3}\\/[0-9]\\.[0-9]\\.[0-9]|post|feed)/" ); /* 553 = Requested action not taken: mailbox name not allowed, 5.7.1 =  Delivery not authorized, message refused */
+        option_register(o, "restrictheader",     'r', OPT_SINGLE,  NULL,        "Restrict messages by header",        "regex",                      &stdsyntax, "m/.*/" );
+        option_register(o, "size",               's', OPT_SINGLE,  "8388608",   "Size limitation on message",         "bytes",                      &stdsyntax, "m/.*/" ); //"m/[0-9]+/" );
+        option_register(o, "testfile",           't', OPT_MULTI,   NULL,        "Testfile for headerrule",            "filename",                   &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutlmtp",        NUL, OPT_SINGLE,  NULL,        "LMTP server default timeout",        "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutlmtpaccept",  NUL, OPT_SINGLE,  "0",         "LMTP server accept timeout",         "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutlmtpread",    NUL, OPT_SINGLE,  "10",        "LMTP server read timeout",           "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutlmtpwrite",   NUL, OPT_SINGLE,  "10",        "LMTP server write timeout",          "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutnntp",        NUL, OPT_SINGLE,  NULL,        "NNTP client default timeout",        "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE,  "360",       "NNTP client connect timeout",        "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutnntpread",    NUL, OPT_SINGLE,  "60",        "NNTP client read timeout",           "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "timeoutnntpwrite",   NUL, OPT_SINGLE,  "60",        "NNTP client write timeout",          "sec",                        &stdsyntax, "m/.*/" );
+        option_register(o, "user",               'u', OPT_SINGLE,  NULL,        "User identity",                      "uid|name",                   &stdsyntax, "m/.*/" );
+        option_register(o, "version",            'v', OPT_FLAG,    NULL,        "Version information",                NULL,                         &stdsyntax, NULL    );
+        option_register(o, "newsgroup",          NUL, OPT_MULTI,   NULL,        "Newsgroup name or match",            "newsgroup|wildmat",          &stdsyntax, "m/.*/" );
     }
     catch(ex) {
         if (ex.ex_class == option_create)

CVSTrac 2.0.1