aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libmf.h1
-rw-r--r--lib/server.c78
-rw-r--r--src/calloutd.c2
-rw-r--r--src/main.c8
-rw-r--r--src/srvcfg.c13
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);
diff --git a/src/main.c b/src/main.c
index 090be692..cc0852df 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;

Return to:

Send suggestions and report system problems to the System administrator.