diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-01-04 21:49:12 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-01-04 21:49:12 +0000 |
commit | c060b5fddd1ae0a06089df418c4cb4393b2de615 (patch) | |
tree | 447b37dc4cd4b709ea950297499f68f6089d27d0 /pop3d/pop3d.c | |
parent | c51fa40b04c2b6cc8c0ef0693b8b2df89ac3119c (diff) | |
download | mailutils-c060b5fddd1ae0a06089df418c4cb4393b2de615.tar.gz mailutils-c060b5fddd1ae0a06089df418c4cb4393b2de615.tar.bz2 |
* TODO, NEWS: Update.
* mailbox/msrv.c: New file.
* mailbox/Makefile.am: Add msrv.c.
* include/mailutils/server.h (mu_tcp_server_conn_fp): Take
sockaddr as argument
(mu_tcp_server_create,mu_tcp_server_get_sockaddr): Likewise.
(mu_m_server_*): New prototypes.
* include/mailutils/types.hin (mu_m_server_t): New type.
* mailbox/acl.c: Fix debugging output.
(mu_sockaddr_to_str, mu_sockaddr_to_astr): New functions.
* mailbox/tcpsrv.c: Handle AF_INET and AF_UNIX sockets.
* examples/echosrv.c: Update mu_tcp_server_* calls.
* examples/config/Makefile.am: Remove comsat.conf and
mailutils.rc.
* imap4d/imap4d.c, imap4d/imap4d.h, imap4d/signal.c,
maidag/lmtp.c, maidag/maidag.c, maidag/maidag.h, pop3d/extra.c,
pop3d/pop3d.c, pop3d/pop3d.h, pop3d/signal.c: Rewrite using
m-server.
* include/mailutils/cfg.h (mu_offsetof): Bug fix.
* mailbox/cfg_driver.c (dup_container): Bugfix. Offset was not
copied.
(mu_cfg_section_add_params): If identifier starts with a dot, it
is hidden, i.e. its substatements are copied directly into the
parent structure.
* mailbox/cfg_lexer.c (isword): Take care of opening braces.
(default_lexer): Several fixes.
* mailbox/cfg_parser.y (mu_cfg_parse): Initialize debugging level
from global settings.
(_scan_tree_helper): Ensure debugging object has correct locus
information before calling the section parser.
(mu_cfg_scan_tree): If no debugging object is supplied, use the
one from diag.c
* mailbox/daemon.c (mu_daemon_create_pidfile): Return a meaningful
error code.
* mailbox/debug.c (mu_debug_create): Initialize printer to NULL.
(mu_debug_vprintf): If printer is NULL, use
mu_debug_default_printer.
(mu_debug_check_level): Bugfix.
* mailbox/server.c: Minor indentation fix.
* mailbox/syslog.c (mu_diag_syslog_printer): Chop off \r as well.
* mailbox/folder.c (mu_folder_create_from_record): Bugfixes.
* include/mailutils/debug.hm4 (mu_sockaddr_to_str)
(mu_sockaddr_to_astr): New functions.
* include/mailutils/.cvsignore: Add debug.h
* po/POTFILES.in: Update.
Diffstat (limited to 'pop3d/pop3d.c')
-rw-r--r-- | pop3d/pop3d.c | 413 |
1 files changed, 145 insertions, 268 deletions
diff --git a/pop3d/pop3d.c b/pop3d/pop3d.c index 7c85a1e24..9ec6703cc 100644 --- a/pop3d/pop3d.c +++ b/pop3d/pop3d.c @@ -1,6 +1,6 @@ /* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2007 Free Software Foundation, Inc. + 2005, 2007, 2008 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,15 +27,9 @@ int state; char *username; char *md5shared; -struct mu_gocs_daemon default_gocs_daemon = { - MODE_INTERACTIVE, /* Start in interactive (inetd) mode */ - 20, /* Default maximum number of children */ - 110, /* Standard POP3 port */ - 600, /* Idle timeout */ - 0, /* No transcript by default */ - NULL /* No PID file by default */ -}; - +mu_m_server_t server; +unsigned int idle_timeout; +int pop3d_transcript; int debug_mode; #ifdef WITH_TLS @@ -45,8 +39,6 @@ int tls_done; int initial_state = AUTHORIZATION; -/* Number of child processes. */ -size_t children; /* Should all the messages be undeleted on startup */ int undelete_on_startup; #ifdef ENABLE_LOGIN_DELAY @@ -58,11 +50,6 @@ char *login_stat_file = LOGIN_STAT_FILE; unsigned expire = EXPIRE_NEVER; /* Expire messages after this number of days */ int expire_on_exit = 0; /* Delete expired messages on exit */ -mu_acl_t pop3d_acl; - -static int pop3d_mainloop (int fd, FILE *, FILE *); -static void pop3d_daemon_init (void); -static void pop3d_daemon (unsigned int, unsigned int); static error_t pop3d_parse_opt (int key, char *arg, struct argp_state *astate); const char *program_version = "pop3d (" PACKAGE_STRING ")"; @@ -75,9 +62,17 @@ static char doc[] = N_("GNU pop3d -- the POP3 daemon"); #define OPT_TLS_REQUIRED 261 #define OPT_BULLETIN_SOURCE 262 #define OPT_BULLETIN_DB 263 +#define OPT_FOREGROUND 264 static struct argp_option options[] = { #define GRP 0 + { "foreground", OPT_FOREGROUND, 0, 0, N_("Remain in foreground."), GRP+1}, + { "inetd", 'i', 0, 0, N_("Run in inetd mode"), GRP+1}, + { "daemon", 'd', N_("NUMBER"), OPTION_ARG_OPTIONAL, + N_("Runs in daemon mode with a maximum of NUMBER children"), GRP+1 }, +#undef GRP + +#define GRP 5 {"undelete", 'u', NULL, OPTION_HIDDEN, N_("Undelete all messages on startup"), GRP+1}, {"expire", OPT_EXPIRE, N_("DAYS"), OPTION_HIDDEN, @@ -161,7 +156,8 @@ static struct mu_cfg_param pop3d_cfg_param[] = { N_("Set the bulletin database file name."), N_("file") }, #endif - { "acl", mu_cfg_section, }, + { ".server", mu_cfg_section, NULL, 0, NULL, + N_("Server configuration.") }, TCP_WRAPPERS_CONFIG { NULL } }; @@ -176,7 +172,6 @@ static struct argp argp = { }; static const char *pop3d_argp_capa[] = { - "daemon", "auth", "common", "debug", @@ -194,6 +189,20 @@ pop3d_parse_opt (int key, char *arg, struct argp_state *astate) switch (key) { + case 'd': + mu_argp_node_list_new (&lst, "mode", "daemon"); + if (arg) + mu_argp_node_list_new (&lst, "max-children", arg); + break; + + case 'i': + mu_argp_node_list_new (&lst, "mode", "inetd"); + break; + + case OPT_FOREGROUND: + mu_argp_node_list_new (&lst, "foreground", "yes"); + break; + case 'u': mu_argp_node_list_new (&lst, "undelete", "yes"); break; @@ -246,153 +255,6 @@ pop3d_parse_opt (int key, char *arg, struct argp_state *astate) return 0; } - -int -main (int argc, char **argv) -{ - struct group *gr; - int status = OK; - - /* Native Language Support */ - mu_init_nls (); - - MU_AUTH_REGISTER_ALL_MODULES(); - /* Register the desired formats. */ - mu_register_local_mbox_formats (); - -#ifdef WITH_TLS - mu_gocs_register ("tls", mu_tls_module_init); -#endif /* WITH_TLS */ - mu_tcpwrapper_cfg_init (); - mu_acl_cfg_init (); - - mu_gocs_daemon = default_gocs_daemon; - mu_argp_init (program_version, NULL); - if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param, - argc, argv, 0, NULL, &pop3d_acl)) - exit (1); - - if (expire == 0) - expire_on_exit = 1; - -#ifdef USE_LIBPAM - if (!mu_pam_service) - mu_pam_service = "gnu-pop3d"; -#endif - - if (mu_gocs_daemon.mode == MODE_INTERACTIVE && isatty (0)) - { - /* If input is a tty, switch to debug mode */ - debug_mode = 1; - } - else - { - gr = getgrnam ("mail"); - if (gr == NULL) - { - perror (_("Error getting mail group")); - exit (EXIT_FAILURE); - } - - if (setgid (gr->gr_gid) == -1) - { - perror (_("Error setting mail group")); - exit (EXIT_FAILURE); - } - } - - /* Set the signal handlers. */ - signal (SIGINT, pop3d_signal); - signal (SIGQUIT, pop3d_signal); - signal (SIGILL, pop3d_signal); - signal (SIGBUS, pop3d_signal); - signal (SIGFPE, pop3d_signal); - signal (SIGSEGV, pop3d_signal); - signal (SIGTERM, pop3d_signal); - signal (SIGSTOP, pop3d_signal); - signal (SIGPIPE, pop3d_signal); - signal (SIGABRT, pop3d_signal); - - if (mu_gocs_daemon.mode == MODE_DAEMON) - pop3d_daemon_init (); - else - { - /* Make sure we are in the root directory. */ - chdir ("/"); - } - - /* Set up for syslog. */ - openlog ("gnu-pop3d", LOG_PID, log_facility); - /* Redirect any stdout error from the library to syslog, they - should not go to the client. */ - { - mu_debug_t debug; - - mu_diag_get_debug (&debug); - mu_debug_set_print (debug, mu_diag_syslog_printer, NULL); - - /* FIXME: this should be done automatically by cfg */ - if (pop3d_acl) - { - mu_acl_get_debug (pop3d_acl, &debug); - mu_debug_set_print (debug, mu_debug_syslog_printer, NULL); - } - } - - umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ - - if (mu_gocs_daemon.pidfile) - { - mu_daemon_create_pidfile (mu_gocs_daemon.pidfile); - } - - /* Check TLS environment, i.e. cert and key files */ -#ifdef WITH_TLS - tls_available = mu_check_tls_environment (); - if (tls_available) - tls_available = mu_init_tls_libs (); -#endif /* WITH_TLS */ - - /* Actually run the daemon. */ - if (mu_gocs_daemon.mode == MODE_DAEMON) - pop3d_daemon (mu_gocs_daemon.maxchildren, mu_gocs_daemon.port); - /* exit (EXIT_SUCCESS) -- no way out of daemon except a signal. */ - else - status = pop3d_mainloop (fileno (stdin), stdin, stdout); - - /* Close the syslog connection and exit. */ - closelog (); - return (OK != status); -} - -/* Sets things up for daemon mode. */ -static void -pop3d_daemon_init (void) -{ - extern int daemon (int, int); - - /* Become a daemon. Take care to close inherited fds and to hold - first three one, in, out, err */ - if (daemon (0, 0) < 0) - { - perror (_("Failed to become a daemon:")); - exit (EXIT_FAILURE); - } - - /* SIGCHLD is not ignore but rather use to do some simple load balancing. */ -#ifdef HAVE_SIGACTION - { - struct sigaction act; - act.sa_handler = pop3d_sigchld; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - sigaction (SIGCHLD, &act, NULL); - } -#else - signal (SIGCHLD, pop3d_sigchld); -#endif -} - int pop3d_get_client_address (int fd, struct sockaddr_in *pcs) { @@ -424,7 +286,7 @@ pop3d_get_client_address (int fd, struct sockaddr_in *pcs) fd -- socket descriptor (for diagnostics) infile -- input stream outfile -- output stream */ -static int +int pop3d_mainloop (int fd, FILE *infile, FILE *outfile) { int status = OK; @@ -433,44 +295,13 @@ pop3d_mainloop (int fd, FILE *infile, FILE *outfile) if (pop3d_get_client_address (fd, &cs) == 0) { - if (pop3d_acl) - { - mu_acl_result_t res; - int rc = mu_acl_check_sockaddr (pop3d_acl, - (struct sockaddr*) &cs, - sizeof (cs), - &res); - if (rc) - { - mu_error (_("Access from %s blocked: cannot check ACLs: %s"), - inet_ntoa (cs.sin_addr), mu_strerror (rc)); - return 1; - } - switch (res) - { - case mu_acl_result_undefined: - mu_diag_output (MU_DIAG_INFO, - _("%s: undefined ACL result; access allowed"), - inet_ntoa (cs.sin_addr)); - break; - - case mu_acl_result_accept: - break; - - case mu_acl_result_deny: - mu_error (_("Access from %s blocked."), - inet_ntoa (cs.sin_addr)); - return 1; - } - } - if (!mu_tcpwrapper_access (fd)) { mu_error (_("Access from %s blocked."), inet_ntoa (cs.sin_addr)); return 1; } } - else if (!debug_mode && (mu_tcp_wrapper_enable || pop3d_acl)) + else if (!debug_mode && mu_tcp_wrapper_enable) { mu_error (_("Rejecting connection from unknown address")); return 1; @@ -630,85 +461,131 @@ pop3d_mainloop (int fd, FILE *infile, FILE *outfile) return (status != OK); } -/* Runs GNU POP3 in standalone daemon mode. This opens and binds to a port - (default 110) then executes a pop3d_mainloop() upon accepting a connection. - It starts maxchildren child processes to listen to and accept socket - connections. */ -static void -pop3d_daemon (unsigned int maxchildren, unsigned int port) +int +pop3d_connection (int fd, void *data, time_t timeout, int transcript) +{ + idle_timeout = timeout; + pop3d_transcript = transcript; + pop3d_mainloop (fd, fdopen (fd, "r"), fdopen (fd, "w")); + return 0; +} + +int +main (int argc, char **argv) { - struct sockaddr_in server, client; - pid_t pid; - int listenfd, connfd; - size_t size; + struct group *gr; + int status = OK; - listenfd = socket (PF_INET, SOCK_STREAM, 0); - if (listenfd == -1) + /* Native Language Support */ + mu_init_nls (); + + MU_AUTH_REGISTER_ALL_MODULES(); + /* Register the desired formats. */ + mu_register_local_mbox_formats (); + +#ifdef WITH_TLS + mu_gocs_register ("tls", mu_tls_module_init); +#endif /* WITH_TLS */ + mu_tcpwrapper_cfg_init (); + mu_acl_cfg_init (); + mu_m_server_cfg_init (); + + mu_argp_init (program_version, NULL); + + mu_m_server_create (&server, "GNU pop3d"); + mu_m_server_set_conn (server, pop3d_connection); + mu_m_server_set_mode (server, MODE_INTERACTIVE); + mu_m_server_set_max_children (server, 20); + /* FIXME mu_m_server_set_pidfile (); */ + mu_m_server_set_default_port (server, 110); + mu_m_server_set_timeout (server, 600); + + if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param, + argc, argv, 0, NULL, server)) + exit (1); + + if (expire == 0) + expire_on_exit = 1; + +#ifdef USE_LIBPAM + if (!mu_pam_service) + mu_pam_service = "gnu-pop3d"; +#endif + + if (mu_m_server_mode (server) == MODE_INTERACTIVE && isatty (0)) { - mu_diag_output (MU_DIAG_ERROR, "socket: %s", strerror(errno)); - exit (EXIT_FAILURE); + /* If input is a tty, switch to debug mode */ + debug_mode = 1; } - size = 1; /* Use size here to avoid making a new variable. */ - setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size)); - size = sizeof (server); - memset (&server, 0, size); - server.sin_family = AF_INET; - server.sin_addr.s_addr = htonl (INADDR_ANY); - server.sin_port = htons (port); - - if (bind (listenfd, (struct sockaddr *)&server, size) == -1) + else { - mu_diag_output (MU_DIAG_ERROR, "bind: %s", strerror (errno)); - exit (EXIT_FAILURE); - } + gr = getgrnam ("mail"); + if (gr == NULL) + { + perror (_("Error getting mail group")); + exit (EXIT_FAILURE); + } - if (listen (listenfd, 128) == -1) - { - mu_diag_output (MU_DIAG_ERROR, "listen: %s", strerror (errno)); - exit (EXIT_FAILURE); + if (setgid (gr->gr_gid) == -1) + { + perror (_("Error setting mail group")); + exit (EXIT_FAILURE); + } } - mu_diag_output (MU_DIAG_INFO, _("GNU pop3d started")); + /* Set the signal handlers. */ + signal (SIGINT, pop3d_signal); + signal (SIGQUIT, pop3d_signal); + signal (SIGILL, pop3d_signal); + signal (SIGBUS, pop3d_signal); + signal (SIGFPE, pop3d_signal); + signal (SIGSEGV, pop3d_signal); + signal (SIGTERM, pop3d_signal); + signal (SIGSTOP, pop3d_signal); + signal (SIGPIPE, pop3d_signal); + signal (SIGABRT, pop3d_signal); - for (;;) + /* Set up for syslog. */ + openlog ("gnu-pop3d", LOG_PID, log_facility); + /* Redirect any stdout error from the library to syslog, they + should not go to the client. */ + { + mu_debug_t debug; + + mu_diag_get_debug (&debug); + mu_debug_set_print (debug, mu_diag_syslog_printer, NULL); + + mu_debug_default_printer = mu_debug_syslog_printer; + } + + umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ + + /* Check TLS environment, i.e. cert and key files */ +#ifdef WITH_TLS + tls_available = mu_check_tls_environment (); + if (tls_available) + tls_available = mu_init_tls_libs (); +#endif /* WITH_TLS */ + + /* Actually run the daemon. */ + if (mu_m_server_mode (server) == MODE_DAEMON) { - process_cleanup (); - if (children > maxchildren) - { - mu_diag_output (MU_DIAG_ERROR, _("too many children (%s)"), - mu_umaxtostr (0, children)); - pause (); - continue; - } - connfd = accept (listenfd, (struct sockaddr *)&client, - (socklen_t *) &size); - if (connfd == -1) - { - if (errno == EINTR) - continue; - mu_diag_output (MU_DIAG_ERROR, "accept: %s", strerror (errno)); - continue; - /*exit (EXIT_FAILURE);*/ - } - - pid = fork (); - if (pid == -1) - mu_diag_output (MU_DIAG_ERROR, "fork: %s", strerror (errno)); - else if (pid == 0) /* Child. */ - { - int status; - - close (listenfd); - status = pop3d_mainloop (connfd, - fdopen (connfd, "r"), fdopen (connfd, "w")); - closelog (); - exit (status); - } - else - { - ++children; - } - close (connfd); + mu_m_server_begin (server); + status = mu_m_server_run (server); + mu_m_server_end (server); + mu_m_server_destroy (&server); + } + else + { + /* Make sure we are in the root directory. */ + chdir ("/"); + status = pop3d_mainloop (fileno (stdin), stdin, stdout); } + + if (status) + mu_error (_("Main loop status: %s"), mu_strerror (status)); + /* Close the syslog connection and exit. */ + closelog (); + return (OK != status); } |