diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 2244 |
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; |