diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pies.c | 46 | ||||
-rw-r--r-- | src/pies.h | 6 | ||||
-rw-r--r-- | src/progman.c | 121 |
3 files changed, 135 insertions, 38 deletions
@@ -36,6 +36,11 @@ unsigned long shutdown_timeout = 5; pies_acl_t pies_acl; limits_record_t pies_limits; int force_option; +char *mailer_program = "/usr/sbin/sendmail"; +char *mailer_command_line = "/usr/sbin/sendmail -oi -t"; +int mailer_argc; +char **mailer_argv; + /* Logging */ @@ -1164,6 +1169,18 @@ struct grecs_keyword pies_keywords[] = { grecs_type_string, &meta1_queue_dir, 0, NULL, }, + {"mailer-program", + NULL, + N_("Full path to the mailer binary."), + grecs_type_string, &mailer_program, 0, + NULL + }, + {"mailer-command-line", + NULL, + N_("Mailer command line (without recipient addresses)."), + grecs_type_string, &mailer_command_line, 0, + NULL + }, {NULL} }; @@ -1258,6 +1275,7 @@ parse_opt (int key, char *arg, struct argp_state *state) switch (key) { case 't': + log_to_stderr = 1; lint_mode = 1; break; @@ -1274,6 +1292,7 @@ parse_opt (int key, char *arg, struct argp_state *state) exit (0); case OPT_FOREGROUND: + log_to_stderr = 1; foreground = 1; break; @@ -1670,6 +1689,28 @@ remove_pidfile (char *name) logmsg (LOG_ERR, _("cannot unlink pidfile `%s': %s"), name, strerror (errno)); } + + +static void +set_mailer_argcv () +{ + int i; + struct wordsplit ws; + + if (wordsplit (mailer_command_line, &ws, WRDSF_DEFFLAGS)) + { + logmsg (LOG_CRIT, _("cannot parse mailer command line: %s"), + strerror (errno)); + exit (EX_CONFIG); + } + mailer_argc = ws.ws_wordc; + mailer_argv = xcalloc (mailer_argc + 1, sizeof (mailer_argv[0])); + for (i = 0; i < mailer_argc; i++) + mailer_argv[i] = xstrdup (ws.ws_wordv[i]); + mailer_argv[i] = NULL; + wordsplit_free (&ws); +} + const char version_etc_copyright[] = /* Do *not* mark this string for translation. %s is a copyright @@ -1716,7 +1757,8 @@ main (int argc, char **argv) mf_proctitle_init (argc, argv, environ); /* Set default logging */ - log_setup (!stderr_closed_p ()); + log_to_stderr = !stderr_closed_p (); + log_setup (log_to_stderr); config_init (); argp_program_version_hook = version; if (argp_parse (&argp, argc, argv, 0, &index, NULL)) @@ -1728,6 +1770,8 @@ main (int argc, char **argv) if (grecs_parse (conffile)) exit (EX_CONFIG); + set_mailer_argcv (); + if (lint_mode) { progman_build_depmap (); @@ -169,8 +169,12 @@ extern char *log_tag; extern int log_facility; extern unsigned long shutdown_timeout; extern struct component default_component; -pies_acl_t pies_acl; +extern pies_acl_t pies_acl; extern limits_record_t pies_limits; +extern char *mailer_program; +extern char *mailer_command_line; +extern int mailer_argc; +extern char **mailer_argv; void register_prog (struct component *comp); size_t progman_running_count (void); diff --git a/src/progman.c b/src/progman.c index 3211d9a..b85a797 100644 --- a/src/progman.c +++ b/src/progman.c @@ -163,6 +163,23 @@ unlink_prog (struct prog *pp) void destroy_prog (struct prog **pp) { + struct prog *p = *pp; + switch (p->type) + { + case TYPE_COMPONENT: + break; + + case TYPE_RETR: + { + struct prog *master = p->v.r.master; + if (p == master->v.p.redir[0]) + master->v.p.redir[0] = NULL; + else if (p == master->v.p.redir[1]) + master->v.p.redir[1] = NULL; + else + logmsg (LOG_NOTICE, _("orphan redirector: %s"), p->tag); + } + } unlink_prog (*pp); free (*pp); *pp = NULL; @@ -1350,13 +1367,13 @@ wait_for_child (pid_t pid) void send_msg (char *rcpts, const char *msg_text) { - int i; - pid_t pid; + int i, j, k; + pid_t child_pid, grand_child_pid; struct wordsplit ws; int p[2]; size_t size; - ws.ws_offs = 3; /* sendmail -oi -t */ + ws.ws_offs = mailer_argc; ws.ws_delim = ","; if (wordsplit (rcpts, &ws, WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM | WRDSF_DOOFFS)) @@ -1367,12 +1384,21 @@ send_msg (char *rcpts, const char *msg_text) return; } - ws.ws_wordv[0] = "/usr/sbin/sendmail"; /* FIXME: path */ - ws.ws_wordv[1] = "-oi"; - ws.ws_wordv[2] = "-t"; - for (i = 0; i < ws.ws_wordc; i++) + debug (1, (_("sending notification to %s"), rcpts)); + + /* Copy mailer arguments */ + for (i = 0; i < mailer_argc; i++) + ws.ws_wordv[i] = mailer_argv[i]; + /* j - number of the recipient; + i - index of the ws_wordv being converted; + k - index of the ws_wordv to store the converted value to. + + Normally i == k, unless there are some invalid ws_wordv's, + in which case i > k. + */ + for (j = 0, k = i; j < ws.ws_wordc; j++, i++) { - char *arg = ws.ws_wordv[3 + i]; + char *arg = ws.ws_wordv[i]; size_t len; while (*arg && c_isblank (*arg)) @@ -1380,36 +1406,38 @@ send_msg (char *rcpts, const char *msg_text) len = strlen (arg); if (len > 0) { - while (len > 0 && c_isblank(arg[len - 1])) + while (len > 0 && c_isblank (arg[len - 1])) len--; } if (len == 0) - continue; //FIXME + continue; if (arg[0] == '<' && arg[len-1] == '>') { arg++; len -= 2; } if (len == 0) - continue; //FIXME - memmove (ws.ws_wordv[3 + i], arg, len); - ws.ws_wordv[3 + i][len] = 0; + continue; + memmove (ws.ws_wordv[k], arg, len); + ws.ws_wordv[k][len] = 0; + k++; } - + ws.ws_wordv[k] = NULL; + /* Fork a child: */ - pid = fork (); - if (pid <= 0) + child_pid = fork (); + if (child_pid != 0) wordsplit_free (&ws); - if (pid < 0) + if (child_pid < 0) { logmsg (LOG_ERR, _("cannot send mail: fork failed: %s"), strerror (errno)); return; } - if (pid == 0) - //FIXME: SIGCHLD Handler? */ + if (child_pid) + /*FIXME: SIGCHLD Handler? */ return; /* Child process */ @@ -1425,18 +1453,15 @@ send_msg (char *rcpts, const char *msg_text) exit (EX_OSERR); } - pid = fork (); - if (pid <= 0) - wordsplit_free (&ws); - - if (pid < 0) + grand_child_pid = fork (); + if (grand_child_pid < 0) { logmsg (LOG_ERR, _("cannot send mail: fork failed: %s"), strerror (errno)); return; } - if (pid) + if (grand_child_pid == 0) { /* Grand-child */ /* =========== */ @@ -1444,7 +1469,7 @@ send_msg (char *rcpts, const char *msg_text) close (0); close (p[1]); dup2 (p[0], 0); - execv (ws.ws_wordv[0], ws.ws_wordv); + execv (mailer_program, ws.ws_wordv); exit (127); } @@ -1466,7 +1491,7 @@ send_msg (char *rcpts, const char *msg_text) } close (p[1]); - exit (wait_for_child (pid)); + exit (wait_for_child (grand_child_pid)); } static const char default_termination_message[] = @@ -1485,9 +1510,11 @@ notify (const char *tag, int status, struct action *act) { "version", PACKAGE_VERSION }, #define COMPONENT_IDX 3 { "component", NULL }, -#define RETCODE_IDX 4 +#define TERMINATION_IDX 4 + { "termination", NULL }, +#define RETCODE_IDX 5 { "retcode", NULL }, -#define PROGRAM_NAME_IDX 5 +#define PROGRAM_NAME_IDX 6 { "program-name", NULL }, { NULL } }; @@ -1496,7 +1523,21 @@ notify (const char *tag, int status, struct action *act) char buf[INT_BUFSIZE_BOUND (uintmax_t)]; mdef[COMPONENT_IDX].value = (char*) tag; - mdef[RETCODE_IDX].value = umaxtostr (status, buf); + if (WIFEXITED (status)) + { + mdef[TERMINATION_IDX].value = _("exited with code"); + mdef[RETCODE_IDX].value = umaxtostr (WEXITSTATUS (status), buf); + } + else if (WIFSIGNALED (status)) + { + mdef[TERMINATION_IDX].value = _("caught signal"); + mdef[RETCODE_IDX].value = umaxtostr (WTERMSIG (status), buf); + } + else + { + mdef[TERMINATION_IDX].value = "UNKNOWN"; + mdef[RETCODE_IDX].value = "UNKNOWN"; + } mdef[PROGRAM_NAME_IDX].value = (char*) program_name; msg_text = meta_expand_string (act->message ? act->message : default_termination_message, @@ -1614,11 +1655,21 @@ progman_cleanup (int expect_term) act = default_component.act_head; if (WIFEXITED (status)) - retcode = WEXITSTATUS (status); + { + retcode = WEXITSTATUS (status); + debug (1, (_("%s: terminated with code %d"), + prog->tag, retcode)); + } else if (WIFSIGNALED (status)) - retcode = STATUS_SIG_BIT | WTERMSIG (status); + { + retcode = STATUS_SIG_BIT | WTERMSIG (status); + debug (1, (_("%s: terminated on signal %d"), + prog->tag, retcode)); + } else { + debug (1, (_("%s: unrecognized termination status"), + prog->tag)); /* Enforce default action: */ act = NULL; } @@ -1639,10 +1690,8 @@ progman_cleanup (int expect_term) break; case action_disable: - logmsg (LOG_NOTICE, - _("disabling component %s: " - "exited with code %d"), - prog->tag, status); + logmsg (LOG_NOTICE, _("disabling component %s"), + prog->tag); prog->v.p.status = status_disabled; } if (act->addr) |