aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c2244
1 files changed, 0 insertions, 2244 deletions
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 416916b2..00000000
--- a/src/main.c
+++ /dev/null
@@ -1,2244 +0,0 @@
-/* This file is part of mailfromd.
- Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#define MF_SOURCE_NAME MF_SOURCE_MAIN
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <signal.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
-
-#include <mailutils/mailutils.h>
-#if MAILUTILS_VERSION_NUMBER < 1290
-# include <mailutils/argp.h>
-#else
-# include <mailutils/libargp.h>
-#endif
-#ifdef HAVE_MAILUTILS_SYSLOG_H
-# include <mailutils/syslog.h>
-#endif
-#include "mailfromd.h"
-
-
-/* Configurable options */
-
-int mode = MAILFROMD_DAEMON; /* Default operation mode */
-enum smtp_state test_state = smtp_state_envfrom; /* State for --test mode */
-int need_config = 1;/* Set if the current mode requires reading the
- configuration file */
-char *script_file = DEFAULT_SCRIPT_FILE;
-int script_check; /* Check config file syntax and exit */
-extern int yy_flex_debug; /* Enable tracing the lexical analyzer */
-int script_ydebug; /* Enable tracing the parser */
-int script_dump_tree; /* Dump created config tree to stdout */
-int script_dump_code; /* Dump disassembled code to stdout */
-int script_dump_macros; /* Dump used Sendmail macros */
-int script_dump_xref; /* Dump cross-reference */
-int preprocess_option; /* Only preprocess the sources */
-
-#ifdef DEFAULT_PREPROCESSOR
-# define DEF_EXT_PP DEFAULT_PREPROCESSOR
-#else
-# define DEF_EXT_PP NULL
-#endif
-char *ext_pp = DEF_EXT_PP; /* External preprocessor to use */
-
-int do_transcript; /* Enable session transript */
-int do_trace; /* Enable tracing configuration */
-int mtasim_option; /* mtasim compatibility mode */
-unsigned optimization_level = 1; /* Optimization level */
-int log_to_stderr; /* Use stderr for logging */
-char *portspec; /* Communication socket specification.
- See init_names() */
-int force_remove; /* Remove local communication socket if it already
- exists */
-int foreground; /* Stay in foreground */
-int single_process_option; /* Run in single process mode. */
-unsigned long source_address = INADDR_ANY; /* Source address for TCP
- connections */
-#ifdef USE_SYSLOG_ASYNC
-int use_syslog_async = DEFAULT_SYSLOG_ASYNC;
- /* Use asynchronous syslog implementation */
-#endif
-
-char *syslog_tag; /* Tag to mark syslog entries with. */
-char *mailfromd_state_dir; /* see init_names() */
-char *pidfile; /* see init_names() */
-char *user = DEFAULT_USER; /* Switch to this user privileges after
- startup */
-mu_list_t retain_groups; /* List of group IDs to retain when switching
- to users privileges. */
-
-/* DBM-related options */
-time_t negative_expire_interval = DEFAULT_EXPIRE_INTERVAL/2;
- /* Expire negative cache entries after this
- number of seconds */
-time_t expire_interval = 0; /* When set, overrides all the three above
- intervals */
-int predict_next_option;
-double predict_rate; /* Prediction rate for --list --format=rates*/
-
-int ignore_failed_reads_option; /* Ignore failed reads while compacting or
- expiring */
-int all_option; /* Process all databases */
-char *time_format_string = "%c"; /* String to format the time stamps */
-size_t lock_retry_count_option = 3;
-time_t lock_retry_timeout_option = 1;
-/* DBM-related options end */
-
-int source_info_option; /* Debug messages include source locations */
-int stack_trace_option; /* Print stack traces on runtime errors */
-char *file_option; /* File name for DB management commands */
-struct db_format *format_option;
-
-/* Connect settings */
-time_t connect_timeout = 10;
-
-/* I/O settings */
-time_t io_timeout = 3;
-
-/* Initial response settings */
-time_t response_timeout = 30;
-
-
-/* Logging & debugging */
-
-int
-syslog_printer (int prio, const char *fmt, va_list ap)
-{
-#ifdef USE_SYSLOG_ASYNC
- if (use_syslog_async) {
- vsyslog_async (prio, fmt, ap);
- } else
-#endif
- {
-#if HAVE_VSYSLOG
- vsyslog (prio, fmt, ap);
-#else
- char buf[128];
- vsnprintf (buf, sizeof buf, fmt, ap);
- syslog (prio, "%s", buf);
-#endif
- }
- return 0;
-}
-
-#ifdef USE_SYSLOG_ASYNC
-void
-mf_gacopyz_syslog_async_log_printer(int level, char *fmt, va_list ap)
-{
- switch (level) {
- case SMI_LOG_DEBUG:
- level = LOG_DEBUG;
- break;
- case SMI_LOG_INFO:
- level = LOG_INFO;
- break;
- case SMI_LOG_WARN:
- level = LOG_WARNING;
- break;
- case SMI_LOG_ERR:
- level = LOG_ERR;
- break;
-
- case SMI_LOG_FATAL:
- default:
- level = LOG_EMERG;
- }
- vsyslog_async(level, fmt, ap);
-}
-#endif
-
-int
-syslog_error_printer (const char *fmt, va_list ap)
-{
- return syslog_printer(LOG_ERR, fmt, ap);
-}
-
-int
-stderr_error_printer (const char *fmt, va_list ap)
-{
- fprintf(stderr, "%s: ", program_invocation_short_name);
- vfprintf(stderr, fmt, ap);
- fputc ('\n', stderr);
- return 0;
-}
-
-void
-vlogmsg(int prio, const char *fmt, va_list ap)
-{
- if (log_to_stderr) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- } else
- syslog_printer(prio, fmt, ap);
-}
-
-void
-logmsg(int prio, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogmsg(prio, fmt, ap);
- va_end(ap);
-}
-
-void
-trace(const char *fmt, ...)
-{
- if (do_trace) {
- va_list ap;
- va_start(ap, fmt);
- vlogmsg(LOG_INFO, fmt, ap);
- va_end(ap);
- }
-}
-
-void
-debug_log(char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogmsg(LOG_DEBUG, fmt, ap);
- va_end(ap);
-}
-
-void
-log_status(sfsistat status, SMFICTX *ctx)
-{
- int lev;
- debug_module_level(NULL, &lev);
- if (lev >= 1 && status != SMFIS_CONTINUE) {
- const char *str = sfsistat_str(status);
- if (str)
- logmsg(LOG_INFO,
- "%s%s", mailfromd_msgid(ctx), str);
- else
- logmsg(LOG_INFO,
- "%sstatus %d",
- mailfromd_msgid(ctx), status);
- }
-}
-
-static void
-mf_error_on_locus(mu_debug_t err, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
-#if MAILUTILS_VERSION_NUMBER >= 1290
- if (err) {
- mu_debug_vprintf(err, 0, fmt, ap);
- mu_debug_printf(err, 0, "\n");
- } else
-#endif
- mu_verror(fmt, ap);
- va_end(ap);
-}
-
-
-/* Sendmail class file support */
-
-static mu_list_t domain_list;
-
-int
-compare_string(const void *item, const void *value)
-{
- return strcmp(item, value);
-}
-
-/* Read domains from sendmail-style domain file NAME and store them in
- DOMAIN_LIST */
-int
-read_domain_file(mu_debug_t err, char *name)
-{
- FILE *fp;
- char buf[256];
- char *p;
-
- fp = fopen(name, "r");
- if (!fp) {
- mf_error_on_locus(err, _("Cannot open file `%s': %s"),
- name, mu_strerror(errno));
- return 1;
- }
-
- if (!domain_list) {
- mu_list_create(&domain_list);
- mu_list_set_comparator(domain_list, compare_string);
- }
-
- while (p = fgets(buf, sizeof buf, fp)) {
- char *q;
-
- while (*p && isspace(*p))
- p++;
- if (*p == '#')
- continue;
-
- for (q = p + strlen(p) - 1; q > p && isspace(*q); q--)
- *q = 0;
-
- if (*p == 0)
- continue;
-
- mu_list_append(domain_list, strdup(p));
- }
-
- fclose(fp);
- return 0;
-}
-
-/* Return true if we relay domain NAME */
-int
-relayed_domain_p(char *name)
-{
- char *p = name;
-
- while (p) {
- if (mu_list_locate(domain_list, p, NULL) == 0) {
- debug2(10,"%s is in relayed domain %s",
- name, p);
- return 1;
- }
- p = strchr(p, '.');
- if (p)
- p++;
- }
- return 0;
-}
-
-/* Return true if CLIENT represents a host we relay. CLIENT is a dotted-quad
- IP address. */
-int
-host_in_relayed_domain_p(char *client)
-{
- int rc;
- char *hbuf;
-
- if (mu_list_is_empty(domain_list))
- return 0;
-
- if (resolve_ipstr(client, &hbuf))
- return 0;
- rc = relayed_domain_p(hbuf);
- free(hbuf);
- return rc;
-}
-
-
-/* ************************************************************************
- Configuration directives and options.
-
- This is rather complicated. Mailfromd can take its configurable values
- from the following locations (in that order):
-
- 1. From the mailutils configuration file suite, $sysconfdir/mailutils.rc
- and/or any files included herein;
- 2. From #pragma statements in the filter script file,
- $sysconfdir/mailfromd.rc;
- 3. From command line options;
-
- Versions prior to 4.2.90 supported only [2] and [3]. Generally speaking,
- [2] was needed because Mailutils versions prior to 1.2.90 lacked proper
- configuration file support. With the advent of it, [2] became obsolete
- and will probably be removed in some point in the future.
-
- For the time being, however, I need to support all flavors of options,
- because it is reasonable to assume that many of the installers still have
- MU 1.2 or prior, with which [1] is not available.
-
- Technically speaking, [1] is supported by mu_app_init, whenever compiled
- with newer Mailutils, [2] is supported by the "option handling" code below,
- and [3] is handled by argp machinery (called either from mu_app_init, for
- MU >=1.2.90, or from mu_argp_parse, for older Mailutils versions).
-
- There are some functions common to [1] and [2], these are defined in this
- section.
- ************************************************************************ */
-
-static int
-gid_comp(const void *item, const void *data)
-{
- return (gid_t) item != (gid_t) data;
-}
-
-static int
-mf_option_group(mu_debug_t err, char *arg)
-{
- struct group *group = getgrnam(arg);
- if (group) {
- if (!retain_groups) {
- int rc = mu_list_create(&retain_groups);
- if (rc) {
- mf_error_on_locus(err,
- _("Cannot create list: %s"),
- mu_strerror(rc));
- return 1;
- }
- mu_list_set_comparator(retain_groups, gid_comp);
- }
- mu_list_append(retain_groups, (void*)group->gr_gid);
- } else {
- mf_error_on_locus(err, _("Unknown group: %s"), arg);
- return 1;
- }
- return 0;
-}
-
-static int
-mf_option_mailfrom(mu_debug_t err, char *arg)
-{
- int rc;
- mu_address_t addr;
-
- rc = mu_address_create(&addr, arg);
- if (rc) {
- mf_error_on_locus(err, _("Cannot create address `%s': %s"),
- arg, mu_strerror(rc));
- return 1;
- }
- mu_address_destroy(&addr);
- defer_initialize_variable("mailfrom_address", arg);
- return 0;
-}
-
-static int
-mf_option_state_directory(mu_debug_t err, char *arg)
-{
- struct stat st;
- if (stat(arg, &st)) {
- mf_error_on_locus(err, _("Cannot stat file `%s': %s"),
- arg,
- mu_strerror(errno));
- return 1;
- }
- if (!S_ISDIR(st.st_mode)) {
- mf_error_on_locus(err, _("`%s' is not a directory"), arg);
- return 1;
- }
- if (arg[0] != '/') {
- mf_error_on_locus(err,
- _("State directory `%s' is not an absolute file name"),
- arg);
- return 1;
- }
- mailfromd_state_dir = xstrdup(arg);
- return 0;
-}
-
-static int
-mf_option_source_ip(mu_debug_t err, char *arg, unsigned long *pval)
-{
- unsigned long address = inet_addr(arg);
- if (address == INADDR_NONE) {
- struct hostent *phe = gethostbyname(arg);
- if (!phe) {
- mf_error_on_locus(err, _("Cannot resolve `%s'"),
- arg);
- return 1;
- }
- address = *(((unsigned long **) phe->h_addr_list)[0]);
- }
- *pval = address;
- return 0;
-}
-
-
-/* Option handling.
-
- There are two classes of options: those that can be set using #pragma
- directive in the configuration file, and those that can be used only in
- command line.
-
- The latter are handled as usual. The former are processed in two stages:
- first, upon processing command line, their command line settings are
- verified and stored in struct option_cache below. Then, configuration
- file is parsed. Any valid `#pragma option' directives found there overwrite
- values in option_cache. Finally, process_options() is called that scans the
- cache and actually sets any options found there. */
-
-static int option_string(char *opt, void **pval, char *newval);
-
-static int
-option_ehlo(char *opt, void **pval, char *newval)
-{
- if (get_locus()->file)
- parse_warning(
- "`#pragma option ehlo' is deprecated, consider using "
- "`set ehlo_domain \"%s\"' instead",
- (char*) newval);
- else
- parse_warning(
- "option --ehlo is deprecated, consider using "
- "`-v ehlo_domain=\"%s\"' instead",
- (char*) newval);
- return option_string(opt, pval, newval);
-}
-
-static void
-set_ehlo(void *value)
-{
- defer_initialize_variable("ehlo_domain", value);
-}
-
-static int
-option_mailfrom(char *opt, void **pval, char *newval)
-{
- int rc;
- mu_address_t addr;
-
- /* FIXME-MU: compensate for mailutils deficiency */
- if (newval[0] == 0)
- newval = DEFAULT_FROM_ADDRESS;
- if (get_locus()->file)
- parse_warning(
- "`#pragma option mailfrom' is deprecated, consider using "
- "`set mailfrom_address \"%s\"' instead",
- (char*) newval);
- else
- parse_warning(
- "option --mailfrom is deprecated, consider using "
- "`-v mailfrom_address=\"%s\"' instead",
- (char*) newval);
-
- rc = mu_address_create(&addr, newval);
- if (rc) {
- mu_error(_("Cannot create address `%s': %s"),
- newval, mu_strerror(rc));
- return 1;
- }
- mu_address_destroy(&addr);
- return option_string(opt, pval, newval);
-}
-
-static void
-set_mailfrom(void *value)
-{
- int rc;
- mu_address_t addr;
-
- /* FIXME-MU: compensate for mailutils deficiency */
- if (*(char*)value == 0)
- value = DEFAULT_FROM_ADDRESS;
-
- rc = mu_address_create(&addr, value);
- if (rc) {
- mu_error(_("Cannot create address `%s': %s"),
- (char*)value, mu_strerror(rc));
- return;
- }
- mu_address_destroy(&addr);
- defer_initialize_variable("mailfrom_address", value);
-}
-
-
-/* Other options */
-
-static void
-set_debug(void *value)
-{
- debug_parse_spec(value);
-}
-
-static void
-set_positive_expire(void *value)
-{
- cache_format->expire_interval = *(time_t*) value;
- free(value);
-}
-
-static void
-set_negative_expire(void *value)
-{
- negative_expire_interval = *(time_t*) value;
- free(value);
-}
-
-static void
-set_expire(void *value)
-{
- expire_interval = *(time_t*) value;
- free(value);
-}
-
-static void
-set_rates_expire(void *value)
-{
- rate_format->expire_interval = *(time_t*) value;
- free(value);
-}
-
-static void
-set_port(void *value)
-{
- portspec = value;
-}
-
-static void
-set_user(void *value)
-{
- user = value;
-}
-
-static void
-set_milter_timeout(void *value)
-{
- time_t to = *(time_t*) value;
- free(value);
- if (smfi_settimeout(to) == MI_FAILURE) {
- mu_error(_("Invalid milter timeout: %lu"), (unsigned long) to);
- exit(EX_USAGE);
- }
-}
-
-static void
-set_pidfile(void *value)
-{
- pidfile = value;
-}
-
-static void
-set_io_timeout(void *value)
-{
- io_timeout = *(time_t*) value;
- free(value);
-}
-
-static void
-set_connect_timeout(void *value)
-{
- connect_timeout = *(time_t*) value;
- free(value);
-}
-
-static void
-set_response_timeout(void *value)
-{
- response_timeout = *(time_t*) value;
- free(value);
-}
-
-static int
-load_relay_file(void *item, void *data)
-{
- read_domain_file(NULL, item);
- return 0;
-}
-
-static void
-set_relay(void *value)
-{
- mu_list_do(value, load_relay_file, NULL);
-}
-
-static void
-set_source(void *value)
-{
- source_address = *(unsigned long*)value;
-}
-
-static void
-set_group(void *value)
-{
- /* do nothing */
-}
-
-void
-set_source_info(void *value)
-{
- source_info_option = (int) value;
-}
-
-void
-set_stack_trace(void *value)
-{
- stack_trace_option = (int) value;
-}
-
-static void
-set_lock_retry_count(void *value)
-{
- lock_retry_count_option = strtoul(value, NULL, 0);
-}
-
-static void
-set_lock_retry_timeout(void *value)
-{
- lock_retry_timeout_option = *(time_t*) value;
- free(value);
-}
-
-static int
-option_string(char *opt, void **pval, char *newval)
-{
- if (*pval)
- free(*pval);
- *pval = strdup(newval);
- return 0;
-}
-
-static int
-option_number(char *opt, void **pval, char *newval)
-{
- char *p;
-
- strtoul(newval, &p, 10);
- if (*p) {
- errno = EINVAL;
- return 1;
- }
- return option_string(opt, pval, newval);
-}
-
-static int
-option_boolean(char *opt, void **pval, char *newval)
-{
- int val;
-
- if (strcmp (newval, "yes") == 0
- || strcmp (newval, "true") == 0
- || strcmp (newval, "t") == 0)
- val = 1;
- else if (strcmp (newval, "no") == 0
- || strcmp (newval, "false") == 0
- || strcmp (newval, "nil") == 0)
- val = 0;
- else {
- char *p;
-
- val = strtoul(newval, &p, 10);
- if (*p) {
- errno = EINVAL;
- return 1;
- }
- }
-
- *pval = (void*) val;
- return 0;
-}
-
-static int
-option_debug(char *opt, void **pval, char *newval)
-{
- return option_string(opt, pval, newval);
-}
-
-static int
-option_time(char *opt, void **pval, char *newval)
-{
- time_t interval;
- const char *endp;
- if (parse_time_interval(newval, &interval, &endp)) {
- mu_error(_("%s: unrecognized time format (near `%s')"),
- opt, endp);
- return 1;
- }
- if (!*pval)
- *pval = xmalloc(sizeof(time_t));
- *(time_t*) *pval = interval;
- return 0;
-}
-
-static int
-option_pidfile(char *opt, void **pval, char *newval)
-{
- if (newval[0] != '/') {
- mu_error(_("Invalid pidfile name: must be absolute"));
- return 1;
- }
- return option_string(opt, pval, newval);
-}
-
-static int
-option_relay(char *opt, void **pval, char *newval)
-{
- if (!*pval)
- mu_list_create((mu_list_t*)pval);
- mu_list_append(*pval, strdup(newval));
- return 0;
-}
-
-static int
-option_source(char *opt, void **pval, char *newval)
-{
- unsigned long address;
-
- if (mf_option_source_ip(NULL, newval, &address))
- return 1;
-
- if (*pval == 0)
- *pval = xmalloc (sizeof address);
- *(unsigned long*)*pval = address;
- return 0;
-}
-
-static int
-option_group(char *opt, void **pval, char *newval)
-{
- return mf_option_group(NULL, newval);
-}
-
-void
-set_state_directory(void *value)
-{
- /* nothing */
-}
-
-int
-option_state_directory(char *opt, void **pval, char *newval)
-{
- return mf_option_state_directory(NULL, newval);
-}
-
-struct option_cache {
- char *name;
- void *value;
- int (*handler)(char *opt, void **pval, char *newval);
- void (*set)(void *value);
- int cumulative;
-} option_cache[] = {
- { "ehlo", NULL, option_ehlo, set_ehlo },
- { "debug", NULL, option_debug, set_debug },
- { "source-info", NULL, option_boolean, set_source_info },
- { "stack-trace", NULL, option_boolean, set_stack_trace },
- { "expire-interval", NULL, option_time, set_expire },
- { "positive-expire-interval", NULL, option_time, set_positive_expire },
- { "negative-expire-interval", NULL, option_time, set_negative_expire },
- { "rates-expire-interval", NULL, option_time, set_rates_expire },
- { "port", NULL, option_string, set_port }, /* FIXME: option_port */
- { "user", NULL, option_string, set_user },
- { "group", NULL, option_group, set_group },
- { "milter-timeout", NULL, option_time, set_milter_timeout },
- { "pidfile", NULL, option_pidfile, set_pidfile },
- { "mailfrom", NULL, option_mailfrom, set_mailfrom },
- { "timeout", NULL, option_time, set_io_timeout },
- { "io-timeout", NULL, option_time, set_io_timeout },
- { "connect-timeout", NULL, option_time, set_connect_timeout },
- { "initial-response-timeout", NULL, option_time,
- set_response_timeout },
- { "relay", NULL, option_relay, set_relay, 1 },
- { "source", NULL, option_source, set_source },
- { "lock-retry-count", NULL, option_number, set_lock_retry_count },
- { "lock-retry-timeout", NULL, option_time, set_lock_retry_timeout },
- { "state-directory", NULL, option_state_directory, set_state_directory },
- { NULL }
-};
-
-static struct option_cache *
-find_option(char *name)
-{
- struct option_cache *p;
-
- for (p = option_cache; p->name; p++)
- if (strcmp(p->name, name) == 0)
- return p;
- return NULL;
-}
-
-int
-set_option(char *name, char *value, int override)
-{
- struct option_cache *p = find_option(name);
- if (!p) {
- errno = ENOENT;
- return 1;
- }
- if (!p->cumulative && !override && p->value)
- return 0;
- return p->handler(name, &p->value, value);
-}
-
-void
-process_options()
-{
- struct option_cache *p;
-
- for (p = option_cache; p->name; p++)
- if (p->value && p->set)
- p->set(p->value);
-}
-
-
-/* Command line parsing */
-
-const char *program_version = "mailfromd (" PACKAGE_STRING ")";
-static char doc[] = N_("mailfromd -- a general purpose milter daemon");
-static char args_doc[] = "[var=value...][SCRIPT]";
-
-enum mailfromd_option {
- OPTION_ALL = 256,
- OPTION_COMPACT,
- OPTION_CONFIG_FILE,
- OPTION_DAEMON,
- OPTION_DELETE,
- OPTION_DOMAIN_FILE,
- OPTION_DUMP_CODE,
- OPTION_DUMP_GRAMMAR_TRACE,
- OPTION_DUMP_LEX_TRACE,
- OPTION_DUMP_MACROS,
- OPTION_DUMP_TREE,
- OPTION_DUMP_XREF,
- OPTION_EXPIRE,
- OPTION_FOREGROUND,
- OPTION_GACOPYZ_LOG,
- OPTION_IGNORE_FAILED_READS,
- OPTION_LINT,
- OPTION_LOG_TAG,
- OPTION_LIST,
- OPTION_LOCK_RETRY_COUNT,
- OPTION_LOCK_RETRY_TIMEOUT,
- OPTION_MILTER_TIMEOUT,
- OPTION_MTASIM,
- OPTION_NO_PREPROCESSOR,
- OPTION_NO_SYSLOG_ASYNC,
- OPTION_PIDFILE,
- OPTION_POSTMASTER_EMAIL,
- OPTION_PREDICT_NEXT,
- OPTION_PREPROCESSOR,
- OPTION_SHOW_DEFAULTS,
- OPTION_SINGLE_PROCESS,
- OPTION_STACK_TRACE,
- OPTION_STATE_DIRECTORY,
- OPTION_SOURCE_INFO,
- OPTION_SYSLOG,
- OPTION_SYSLOG_ASYNC,
- OPTION_TIME_FORMAT,
- OPTION_TIMEOUT,
- OPTION_TRACE,
- OPTION_TRACE_PROGRAM,
-};
-
-static struct argp_option options[] = {
-#define GRP 0
- { NULL, 0, NULL, 0,
- N_("Operation modifiers"), GRP },
- { "delete", OPTION_DELETE, NULL, 0,
- N_("Delete given entries from the database"), GRP+1 },
- { "list", OPTION_LIST, NULL, 0,
- N_("List given database (default cache)"), GRP+1 },
- { "expire", OPTION_EXPIRE, NULL, 0,
- N_("Delete expired entries from the database"), GRP+1 },
- { "compact", OPTION_COMPACT, NULL, 0,
- N_("Compact the database"), GRP+1 },
- { "test", 't', N_("HANDLER"), OPTION_ARG_OPTIONAL,
- N_("Run in test mode"), GRP+1 },
- { "lint", OPTION_LINT, NULL, 0,
- N_("Check syntax and exit"), GRP+1 },
- { "syntax-check", 0, NULL, OPTION_ALIAS, NULL, GRP+1 },
- { "show-defaults", OPTION_SHOW_DEFAULTS, NULL, 0,
- N_("Show compilation defaults"), GRP+1 },
- { "daemon", OPTION_DAEMON, NULL, 0,
- N_("Run in daemon mode (default)"), GRP+1 },
-
- { NULL, 'E', NULL, 0,
- N_("Preprocess source files and exit"), GRP+1 },
- /* Reserved for future use: */
- { "compile", 'c', NULL, OPTION_HIDDEN,
- N_("Compile files"), GRP+1 },
- { "load", 'l', N_("FILE"), OPTION_HIDDEN,
- N_("Load library"), GRP+1 },
- { "load-dir", 'L', N_("DIR"), OPTION_HIDDEN,
- N_("Add DIR to the load path"), GRP+1 },
-
-#undef GRP
-#define GRP 15
- { NULL, 0, NULL, 0,
- N_("Database management options"), GRP },
- { "file", 'f', N_("FILE"), 0,
- N_("DB file name to operate upon"),
- GRP+1 },
- { "format", 'H', N_("FORMAT"), 0,
- N_("Format of the DB file to operate upon"), GRP+1 },
- { "ignore-failed-reads", OPTION_IGNORE_FAILED_READS, NULL, 0,
- N_("Ignore failed reads while compacting the database"), GRP+1 },
- { "predict", OPTION_PREDICT_NEXT, N_("RATE"), 0,
- N_("Predict when the user will be able to send next message"),
- GRP+1 },
- { "lock-retry-count", OPTION_LOCK_RETRY_COUNT, N_("NUMBER"), 0,
- N_("Set maximum number of attempts to acquire the lock"), GRP+1 },
- { "lock-retry-timeout", OPTION_LOCK_RETRY_TIMEOUT, N_("TIME"), 0,
- N_("Set timeout for acquiring the lockfile"), GRP+1 },
- { "expire-interval", 'e', N_("NUMBER"), 0,
- N_("Set database expiration interval to NUMBER seconds"), GRP+1 },
- { "all", OPTION_ALL, NULL, 0,
- N_("With --compact or --expire: apply the operation to all "
- "available databases"), GRP+1 },
- { "time-format", OPTION_TIME_FORMAT, N_("FMT"), 0,
- N_("Output timestamps using given format (default \"%c\")"), GRP+1 },
-
-#undef GRP
-#define GRP 20
- { NULL, 0, NULL, 0,
- N_("General options"), GRP },
- { "state-directory", OPTION_STATE_DIRECTORY, N_("DIR"), 0,
- N_("Set new program state directory"), GRP+1 },
- { "config-file", OPTION_CONFIG_FILE, N_("FILE"), OPTION_HIDDEN,
- N_("Read configuration from FILE"), GRP+1 },
- { "include", 'I', N_("DIR"), 0,
- N_("Add the directory DIR to the list of directories to be "
- "searched for header files"), GRP+1 },
- { "port", 'p', N_("STRING"), 0,
- N_("Set communication socket"), GRP+1 },
- { "remove", 'r', NULL, 0,
- N_("Force removing local socket file, if it already exists"),
- GRP+1 },
- { "foreground", OPTION_FOREGROUND, NULL, 0,
- N_("Stay in foreground"), GRP+1 },
- { "mtasim", OPTION_MTASIM, NULL, 0,
- N_("Run in mtasim compatibility mode"), GRP+1 },
- { "single-process", OPTION_SINGLE_PROCESS, NULL, 0,
- N_("Run in single-process mode"), GRP+1 },
- { "pidfile", OPTION_PIDFILE, N_("FILE"), 0,
- N_("Set pidfile name"), GRP+1 },
- { "user", 'u', N_("NAME"), 0,
- N_("Switch to this user privileges after startup"), GRP+1 },
- { "group", 'g', N_("NAME"), 0,
- N_("Retain the supplementary group NAME when switching to user "
- "privileges"),
- GRP+1 },
- { "source", 'S', N_("ADDRESS"), 0,
- N_("Set source address for TCP connections"), GRP+1 },
- { "optimize", 'O', N_("LEVEL"), OPTION_ARG_OPTIONAL,
- N_("Set code optimization level"), GRP+1 },
- { "variable", 'v', N_("VAR=VALUE"), 0,
- N_("Assign VALUE to VAR"), GRP+1 },
- { "relayed-domain-file", OPTION_DOMAIN_FILE, N_("FILE"), 0,
- N_("Read relayed domains from FILE"), GRP+1 },
- { "preprocessor", OPTION_PREPROCESSOR, N_("COMMAND"), 0,
- N_("Use command as external preprocessor"), GRP+1 },
- { "no-preprocessor", OPTION_NO_PREPROCESSOR, NULL, 0,
- N_("Disable the use of external preprocessor"), GRP+1 },
-#undef GRP
-
-#undef GRP
-#define GRP 30
- { NULL, 0, NULL, 0,
- N_("Timeout control"), GRP },
- { "milter-timeout", OPTION_MILTER_TIMEOUT, N_("TIME"), 0,
- N_("Set MTA connection timeout"), GRP+1 },
- { "timeout", OPTION_TIMEOUT, N_("TIME"), 0,
- N_("Set I/O operation timeout"), GRP+1 },
-
-#undef GRP
-#define GRP 40
- { NULL, 0, NULL, 0,
- N_("Informational and debugging options"), GRP },
- { "transcript", 'X', NULL, 0,
- N_("Enable transcript of SMTP sessions"), GRP+1 },
- { "trace", OPTION_TRACE, NULL, 0,
- N_("Trace executed actions"), GRP+1 },
- { "trace-program", OPTION_TRACE_PROGRAM, N_("MODULES"),
- OPTION_ARG_OPTIONAL,
- N_("Enable filter program tracing"), GRP+1 },
- { "debug", 'd', N_("LEVEL"), 0,
- N_("Set debugging level"), GRP+1 },
- { "dump-code", OPTION_DUMP_CODE, NULL, 0,
- N_("Dump disassembled code"), GRP+1 },
- { "dump-grammar-trace", OPTION_DUMP_GRAMMAR_TRACE, NULL, 0,
- N_("Dump grammar traces"), GRP+1 },
- { "dump-lex-trace", OPTION_DUMP_LEX_TRACE, NULL, 0,
- N_("Dump lexical analyzer traces"), GRP+1 },
- { "dump-tree", OPTION_DUMP_TREE, NULL, 0,
- N_("Dump parser tree"), GRP+1 },
- { "dump-macros", OPTION_DUMP_MACROS, NULL, 0,
- N_("Show used Sendmail macros"), GRP+1 },
- { "xref", OPTION_DUMP_XREF, NULL, 0,
- N_("Produce a cross-reference listing"), GRP+1 },
- { "dump-xref", 0, NULL, OPTION_ALIAS, NULL, GRP+1 },
- { "gacopyz-log", OPTION_GACOPYZ_LOG, N_("LEVEL"), 0,
- N_("Set Gacopyz log level"), GRP+1 },
- { "stderr", 's', NULL, 0,
- N_("Log to stderr"), GRP+1 },
- { "syslog", OPTION_SYSLOG, NULL, 0,
- N_("Log to syslog (default)"), GRP+1 },
-#ifdef USE_SYSLOG_ASYNC
- { "syslog-async", OPTION_SYSLOG_ASYNC, NULL, 0,
- N_("Use asynchronous syslog"), GRP+1 },
- { "no-syslog-async", OPTION_NO_SYSLOG_ASYNC, NULL, 0,
- N_("Use system syslog"), GRP+1 },
-#endif
- { "log-tag", OPTION_LOG_TAG, N_("STRING"), 0,
- N_("Set the identifier used in syslog messages to STRING"), GRP+1 },
- { "source-info", OPTION_SOURCE_INFO, NULL, 0,
- N_("Debug messages include source information"), GRP+1 },
- { "stack-trace", OPTION_STACK_TRACE, NULL, 0,
- N_("Enable stack traces on runtime errors"), GRP+1 },
-#undef GRP
-
- /*DEPRECATED OPTIONS*/
- { "domain", 'D', N_("STRING"), OPTION_HIDDEN, "", 1 },
- { "ehlo", 0, NULL, OPTION_ALIAS|OPTION_HIDDEN, NULL, 1 },
- { "postmaster-email", OPTION_POSTMASTER_EMAIL, N_("EMAIL"),
- OPTION_HIDDEN, "", 1 },
- { "mailfrom", 0, NULL, OPTION_ALIAS|OPTION_HIDDEN, NULL, 1 },
-
-#if 0
-/* This entry is to pacify `make check-docs'. The options below
- are defined in libmailutils.
- */
- { "log-facility", }
- { "mailer", }
-#endif
- { NULL }
-};
-
-static int
-validate_options()
-{
- if (all_option &&
- !(mode == MAILFROMD_COMPACT || mode == MAILFROMD_EXPIRE)) {
- mu_error(_("--all is meaningful only with --expire or --compact option"));
- return 1;
- }
- if (all_option && format_option)
- mu_error(_("--format is incompatible with --all"));
- return 0;
-}
-
-
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key) {
- case 'D':
- set_option("ehlo", arg, 1);
- break;
-
- case 'd':
- set_option("debug", arg, 1);
- break;
-
- case 'E':
- preprocess_option = 1;
- break;
-
- case 'e':
- set_option("expire-interval", arg, 1);
- break;
-
- case 'f':
- file_option = arg;
- break;
-
- case 'H':
- format_option = db_format_lookup(arg);
- if (format_option == NULL)
- argp_error(state, _("Unknown database format: %s"),
- arg);
- break;
-
- case 'I':
- add_include_dir(arg);
- break;
-
- case OPTION_ALL:
- all_option = 1;
- break;
-
- case OPTION_CONFIG_FILE:
- /*DEPRECATION*/
- mu_error("Warning: --config-file is obsolete; give the filter script name as an argument");
- script_file = arg;
- break;
-
- case OPTION_IGNORE_FAILED_READS:
- ignore_failed_reads_option = 1;
- break;
-
- case OPTION_LOCK_RETRY_COUNT:
- set_option("lock-retry-count", arg, 1);
- break;
-
- case OPTION_LOCK_RETRY_TIMEOUT:
- set_option("lock-retry-timeout", arg, 1);
- break;
-
- case OPTION_PREDICT_NEXT:
- format_option = db_format_lookup("rate");
- if (convert_rate(arg, &predict_rate) == 0)
- predict_next_option = 1;
- mode = MAILFROMD_LIST;
- break;
-
- case OPTION_PREPROCESSOR:
- ext_pp = arg;
- break;
-
- case OPTION_NO_PREPROCESSOR:
- ext_pp = NULL;
- break;
-
- case OPTION_TIME_FORMAT:
- time_format_string = arg;
- break;
-
- case 'c':
- case 'l':
- case 'L':
- argp_error(state,
- _("The option `-%c' is not yet implemented"),
- key);
- break;
-
- case OPTION_LOG_TAG:
- syslog_tag = arg;
- break;
-
- case OPTION_LINT:
- log_to_stderr = 1;</