diff options
-rw-r--r-- | lib/libmf.h | 1 | ||||
-rw-r--r-- | lib/server.c | 78 | ||||
-rw-r--r-- | src/calloutd.c | 2 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/srvcfg.c | 13 |
5 files changed, 97 insertions, 5 deletions
diff --git a/lib/libmf.h b/lib/libmf.h index 79a01287..55adb595 100644 --- a/lib/libmf.h +++ b/lib/libmf.h @@ -277,6 +277,7 @@ extern void mf_server_log_setup(void); extern mode_t mf_server_umask; extern char *mf_server_user; extern mu_list_t mf_server_retain_groups; +extern char *mf_server_lint_option; void mf_server_check_pidfile(const char *name); void mf_server_save_cmdline(int argc, char **argv); diff --git a/lib/server.c b/lib/server.c index 9a0c326c..eda9cacd 100644 --- a/lib/server.c +++ b/lib/server.c @@ -20,6 +20,7 @@ #include <sys/types.h> #include <sys/stat.h> +#include <sys/wait.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> @@ -31,6 +32,7 @@ #include <mailutils/errno.h> #include <mailutils/daemon.h> #include <mailutils/util.h> +#include <mailutils/stream.h> #include "libmf.h" #include "srvman.h" @@ -86,6 +88,7 @@ mf_server_write_pidfile(const char *name) static int x_argc; /* A copy of argc and ... */ static char **x_argv; /* ... argv */ static int restart; /* Set to 1 if restart is requested */ +char *mf_server_lint_option; void mf_server_save_cmdline(int argc, char **argv) @@ -122,7 +125,6 @@ static RETSIGTYPE sig_restart(int sig) { restart = 1; - mfd_srvman_stop(); } /* Umask for creating new files */ @@ -155,6 +157,74 @@ priv_setup() } } +static int +run_lint() +{ + pid_t pid; + int p[2]; + + if (!mf_server_lint_option) + return 0; + + if (pipe(p)) { + mu_error(_("pipe: %s"), mu_strerror(errno)); + return -1; + } + pid = fork(); + if (pid == -1) { + mu_error(_("fork: %s"), mu_strerror(errno)); + close(p[0]); + close(p[1]); + return -1; + } + + if (pid) { + mu_stream_t instream; + int rc, status; + + close(p[1]); + rc = mu_stdio_stream_create(&instream, p[0], MU_STREAM_READ); + if (rc) { + mu_error(_("cannot open input stream: %s"), + mu_strerror (rc)); + return -1; + } + rc = mu_stream_copy(mu_strerr, instream, 0, NULL); + mu_stream_close(instream); + mu_stream_destroy(&instream); + waitpid(pid, &status, 0); + return !(WIFEXITED(status) && WEXITSTATUS(status) == 0); + } + + /* Child process */ + + /* Prepare arguments */ + x_argv = xrealloc(x_argv, (x_argc + 3) * sizeof(x_argv[0])); + x_argv[x_argc] = "--stderr"; + x_argv[x_argc + 1] = mf_server_lint_option; + x_argv[x_argc + 2] = NULL; + + close(2); + dup2(p[1], 2); + close(p[0]); + close_fds_above(2); + execv(x_argv[0], x_argv); + abort(); +} + +static int +server_idle_hook(void *data) +{ + if (restart) { + if (run_lint()) { + mu_error(_("syntax check failed; restart cancelled")); + restart = 0; + } else + return 1; + } + return 0; +} + void mf_server_start(const char *program, const char *dir, const char *pidfile, int flags) @@ -202,6 +272,7 @@ mf_server_start(const char *program, const char *dir, const char *pidfile, mu_error(_("%s started"), program); + srvman_param.idle_hook = server_idle_hook; if (mfd_srvman_open()) exit(EX_UNAVAILABLE); mfd_srvman_run(NULL); @@ -215,7 +286,10 @@ mf_server_start(const char *program, const char *dir, const char *pidfile, mu_daemon_remove_pidfile(); mu_onexit_run(); logger_close(); - close_fds_above(1); + if (logger_flags(LOGF_STDERR)) + close_fds_above(2); + else + close_fds_above(1); execv(x_argv[0], x_argv); mf_server_log_setup(); mu_error(_("cannot restart: %s"), mu_strerror(errno)); diff --git a/src/calloutd.c b/src/calloutd.c index d82f936a..cd054125 100644 --- a/src/calloutd.c +++ b/src/calloutd.c @@ -121,6 +121,7 @@ main(int argc, char **argv) argp_program_version_hook = version; /* Set default logging */ mu_log_facility = DEFAULT_LOG_FACILITY; + mu_stdstream_setup(MU_STDSTREAM_RESET_NONE); mf_srvcfg_log_setup(stderr_closed_p() ? "syslog" : "stderr"); libcallout_init(); @@ -142,6 +143,7 @@ main(int argc, char **argv) exit(EX_CONFIG); mf_srvcfg_flush(); + mf_server_lint_option = "--config-lint"; mf_server_start("calloutd", mailfromd_state_dir, pidfile, server_flags); exit(0); @@ -1166,6 +1166,7 @@ main(int argc, char **argv) int index; prog_counter_t entry_point; struct arguments args; + int stderr_is_closed = stderr_closed_p(); mf_init_nls(); mf_proctitle_init(argc, argv, environ); @@ -1179,11 +1180,11 @@ main(int argc, char **argv) yy_flex_debug = 0; /* Set default logging */ - mu_set_program_name (argv[0]); + mu_set_program_name(argv[0]); mu_log_tag = (char*)mu_program_name; mu_log_facility = DEFAULT_LOG_FACILITY; - mu_stdstream_setup (); - mf_srvcfg_log_setup(stderr_closed_p() ? "syslog" : "stderr"); + mu_stdstream_setup(MU_STDSTREAM_RESET_NONE); + mf_srvcfg_log_setup(stderr_is_closed ? "syslog" : "stderr"); debug_init(modnames); libcallout_init(); @@ -1329,6 +1330,7 @@ main(int argc, char **argv) server_flags |= MF_SERVER_NORESTART; } open_strecho(1); + mf_server_lint_option = "--lint"; mf_server_start("mailfromd", mailfromd_state_dir, pidfile, server_flags); break; diff --git a/src/srvcfg.c b/src/srvcfg.c index 96145330..0afb7f6a 100644 --- a/src/srvcfg.c +++ b/src/srvcfg.c @@ -740,10 +740,23 @@ srv_parse_opt(int key, char *arg, struct argp_state *state) break; case OPTION_SYSLOG: + /* This option is handled twice. First, it must take + effect immediately, so that any eventual startup + errors end up being reported to syslog: */ + mf_srvcfg_log_setup("syslog"); + /* Second, it is entered to the optcache in order for + it to override any logging settings read from the + configuration file. */ mf_optcache_set_option("logger", "syslog"); break; case OPTION_STDERR: + /* In the contrast to --syslog, this option takes effect + only after the configuration file has been parsed. + This is so because --stderr is the default behavior, + so that any configuration file errors are reported to + stderr anyway (unless it is closed, in which case they + are redirected to syslog). */ mf_optcache_set_option("logger", "stderr"); break; |