service-process.c revision 230ef558135f16a66b86cbe3762524eaa9ae9d81
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "common.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "array.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "aqueue.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "ioloop.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "istream.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "ostream.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "write-full.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "base64.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "hash.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "str.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "llist.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "hostpid.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "env-util.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "fd-close-on-exec.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "restrict-access.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "restrict-process-size.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "eacces-error.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "master-service.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "master-service-settings.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "dup2-array.h"
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include "service.h"
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce#include "service-anvil.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "service-log.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "service-process-notify.h"
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include "service-process.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include <grp.h>
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include <pwd.h>
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include <stdlib.h>
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio#include <unistd.h>
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio#include <fcntl.h>
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio#include <syslog.h>
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include <signal.h>
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include <sys/wait.h>
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidênciostatic void
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncioservice_dup_fds(struct service *service)
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce{
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce struct service_listener *const *listeners;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ARRAY_TYPE(dup2) dups;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce unsigned int i, count, n = 0, socket_listener_count, ssl_socket_count;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek /* stdin/stdout is already redirected to /dev/null. Other master fds
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce should have been opened with fd_close_on_exec() so we don't have to
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce worry about them.
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce because the destination fd might be another one's source fd we have
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce to be careful not to overwrite anything. dup() the fd when needed */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek socket_listener_count = 0;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek listeners = array_get(&service->listeners, &count);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek t_array_init(&dups, count + 10);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce switch (service->type) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce case SERVICE_TYPE_LOG:
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce i_assert(n == 0);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce services_log_dup2(&dups, service->list, MASTER_LISTEN_FD_FIRST,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce &socket_listener_count);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce n += socket_listener_count;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek break;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek case SERVICE_TYPE_ANVIL:
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek dup2_append(&dups, service_anvil_global->log_fdpass_fd[0],
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek MASTER_ANVIL_LOG_FDPASS_FD);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek /* nonblocking anvil fd must be the first one. anvil treats it
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce as the master's fd */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce dup2_append(&dups, service_anvil_global->nonblocking_fd[0],
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce MASTER_LISTEN_FD_FIRST + n++);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek dup2_append(&dups, service_anvil_global->blocking_fd[0],
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek MASTER_LISTEN_FD_FIRST + n++);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce socket_listener_count += 2;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce break;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce default:
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce break;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce /* first add non-ssl listeners */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce for (i = 0; i < count; i++) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (listeners[i]->fd != -1 &&
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce (listeners[i]->type != SERVICE_LISTENER_INET ||
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce !listeners[i]->set.inetset.set->ssl)) {
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio dup2_append(&dups, listeners[i]->fd,
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio MASTER_LISTEN_FD_FIRST + n);
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio n++; socket_listener_count++;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce /* then ssl-listeners */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ssl_socket_count = 0;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce for (i = 0; i < count; i++) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (listeners[i]->fd != -1 &&
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek listeners[i]->type == SERVICE_LISTENER_INET &&
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek listeners[i]->set.inetset.set->ssl) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek dup2_append(&dups, listeners[i]->fd,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek MASTER_LISTEN_FD_FIRST + n);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek n++; socket_listener_count++;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek ssl_socket_count++;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (service->login_notify_fd != -1) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce dup2_append(&dups, service->login_notify_fd,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce MASTER_LOGIN_NOTIFY_FD);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce switch (service->type) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek case SERVICE_TYPE_LOG:
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek case SERVICE_TYPE_ANVIL:
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek case SERVICE_TYPE_CONFIG:
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek dup2_append(&dups, null_fd, MASTER_ANVIL_FD);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek break;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce case SERVICE_TYPE_UNKNOWN:
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce case SERVICE_TYPE_LOGIN:
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce dup2_append(&dups, service_anvil_global->blocking_fd[1],
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce MASTER_ANVIL_FD);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce break;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (service->type != SERVICE_TYPE_LOG) {
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio /* set log file to stderr. dup2() here immediately so that
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio we can set up logging to it without causing any log messages
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio to be lost. */
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio i_assert(service->log_fd[1] != -1);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put("LOG_SERVICE=1");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (dup2(service->log_fd[1], STDERR_FILENO) < 0)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce i_fatal("dup2(log fd) failed: %m");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce i_set_failure_internal();
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce } else {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce dup2_append(&dups, null_fd, STDERR_FILENO);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* make sure we don't leak syslog fd. try to do it as late as possible,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce but also before dup2()s in case syslog fd is one of them. */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce closelog();
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (dup2_array(&dups) < 0)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce i_fatal("service(%s): dup2s failed", service->set->name);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(t_strdup_printf("SSL_SOCKET_COUNT=%d", ssl_socket_count));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestatic void
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcedrop_privileges(struct service *service)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct restrict_access_settings rset;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce bool disallow_root;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce unsigned int len;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (service->vsz_limit != 0)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce restrict_process_size(service->vsz_limit/1024, -1U);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce restrict_access_init(&rset);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce rset.uid = service->uid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce rset.gid = service->gid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce rset.privileged_gid = service->privileged_gid;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek rset.chroot_dir = *service->set->chroot == '\0' ? NULL :
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek service->set->chroot;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (rset.chroot_dir != NULL) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* drop trailing / if it exists */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce len = strlen(rset.chroot_dir);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (rset.chroot_dir[len-1] == '/')
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce rset.chroot_dir = t_strndup(rset.chroot_dir, len-1);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce rset.extra_groups = service->extra_gids;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio if (service->set->drop_priv_before_exec) {
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio disallow_root = service->type == SERVICE_TYPE_LOGIN;
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio restrict_access(&rset, NULL, disallow_root);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce } else {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce restrict_access_set_env(&rset);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestatic void
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorceservice_process_setup_environment(struct service *service, unsigned int uid)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce const struct master_service_settings *set = service->list->service_set;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce const char *const *p;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* remove all environment, and put back what we need */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_clean();
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce for (p = service->list->child_process_env; *p != NULL; p++)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(*p);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce switch (service->type) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce case SERVICE_TYPE_CONFIG:
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service->config_file_path, NULL));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce break;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce case SERVICE_TYPE_LOG:
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* give the log's configuration directly, so it won't depend
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce on config process */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put("DOVECONF_ENV=1");
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek env_put(t_strconcat("LOG_PATH=", set->log_path, NULL));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek env_put(t_strconcat("INFO_LOG_PATH=", set->info_log_path, NULL));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek env_put(t_strconcat("DEBUG_LOG_PATH=", set->debug_log_path, NULL));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(t_strconcat("SYSLOG_FACILITY=", set->syslog_facility, NULL));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce break;
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek default:
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek services_get_config_socket_path(service->list), NULL));
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek break;
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek }
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce
a8361f37af31a8a9767056bd27c418c947293f56Fabiano Fidêncio env_put(t_strdup_printf(MASTER_CLIENT_LIMIT_ENV"=%u",
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce service->client_limit));
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio if (service->set->service_count != 0) {
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio env_put(t_strdup_printf(MASTER_SERVICE_COUNT_ENV"=%u",
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek service->set->service_count));
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(t_strdup_printf(MASTER_UID_ENV"=%u", uid));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (!service->set->master_set->version_ignore)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce env_put(MASTER_DOVECOT_VERSION_ENV"="PACKAGE_VERSION);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (*ssl_manual_key_password != '\0' && service->have_inet_listeners) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* manually given SSL password. give it only to services
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce that have inet listeners. */
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek env_put(t_strconcat(MASTER_SSL_KEY_PASSWORD_ENV"=",
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek ssl_manual_key_password, NULL));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozekstatic void service_process_status_timeout(struct service_process *process)
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek{
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek service_error(process->service,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Initial status notification not received in %d "
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek "seconds, killing the process",
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce SERVICE_FIRST_STATUS_TIMEOUT_SECS);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (kill(process->pid, SIGKILL) < 0 && errno != ESRCH) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek service_error(process->service, "kill(%s, SIGKILL) failed: %m",
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek dec2str(process->pid));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce timeout_remove(&process->to_status);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestruct service_process *service_process_create(struct service *service)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek static unsigned int uid_counter = 0;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct service_process *process;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce unsigned int uid = ++uid_counter;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce pid_t pid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce bool process_forked;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek i_assert(service->status_fd[0] != -1);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (service->to_throttle != NULL) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* throttling service, don't create new processes */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce return NULL;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (service->type == SERVICE_TYPE_ANVIL &&
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek service_anvil_global->pid != 0) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce pid = service_anvil_global->pid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce uid = service_anvil_global->uid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process_forked = FALSE;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce } else {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce pid = fork();
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce process_forked = TRUE;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (pid < 0) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce service_error(service, "fork() failed: %m");
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce return NULL;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (pid == 0) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* child */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service_process_setup_environment(service, uid);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service_dup_fds(service);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce drop_privileges(service);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process_exec(service->executable, NULL);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio process = i_new(struct service_process, 1);
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek process->service = service;
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio process->refcount = 1;
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio process->pid = pid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process->uid = uid;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (process_forked) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process->to_status =
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce timeout_add(SERVICE_FIRST_STATUS_TIMEOUT_SECS * 1000,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service_process_status_timeout, process);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process->available_count = service->client_limit;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service->process_count++;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service->process_avail++;
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek DLLIST_PREPEND(&service->processes, process);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek service_list_ref(service->list);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek hash_table_insert(service_pids, &process->pid, process);
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (service->type == SERVICE_TYPE_ANVIL && process_forked)
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek service_anvil_process_created(process);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return process;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozekvoid service_process_destroy(struct service_process *process)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct service *service = process->service;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct service_list *service_list = service->list;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce DLLIST_REMOVE(&service->processes, process);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek hash_table_remove(service_pids, &process->pid);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (process->available_count > 0)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service->process_avail--;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service->process_count--;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce i_assert(service->process_avail <= service->process_count);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (process->to_status != NULL)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce timeout_remove(&process->to_status);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (process->to_idle != NULL)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce timeout_remove(&process->to_idle);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (service->list->log_byes != NULL)
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek service_process_notify_add(service->list->log_byes, process);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process->destroyed = TRUE;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service_process_unref(process);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (service->process_count < service->process_limit &&
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service->type == SERVICE_TYPE_LOGIN)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service_login_notify(service, FALSE);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce service_list_unref(service_list);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcevoid service_process_ref(struct service_process *process)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce i_assert(process->refcount > 0);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce process->refcount++;
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio}
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncioint service_process_unref(struct service_process *process)
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce{
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio i_assert(process->refcount > 0);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce if (--process->refcount > 0)
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return TRUE;
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce i_assert(process->destroyed);
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio i_free(process);
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio return FALSE;
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio}
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidênciostatic const char *
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncioget_exit_status_message(struct service *service, enum fatal_exit_status status)
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio{
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio switch (status) {
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce case FATAL_LOGOPEN:
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return "Can't open log file";
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce case FATAL_LOGWRITE:
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return "Can't write to log file";
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce case FATAL_LOGERROR:
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return "Internal logging error";
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce case FATAL_OUTOFMEM:
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce if (service->vsz_limit == 0)
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return "Out of memory";
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return t_strdup_printf("Out of memory (vsz_limit=%u MB, "
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce "you may need to increase it)",
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce (unsigned int)(service->vsz_limit/1024/1024));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek case FATAL_EXEC:
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return "exec() failed";
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek case FATAL_DEFAULT:
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio return "Fatal failure";
a8361f37af31a8a9767056bd27c418c947293f56Fabiano Fidêncio }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return NULL;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek}
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidênciostatic void
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorcelog_coredump(struct service *service, string_t *str, int status)
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce{
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio#ifdef WCOREDUMP
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio int signum = WTERMSIG(status);
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio if (WCOREDUMP(status)) {
d806427f200dc1ffd44d37724eb40125af5cc8c2Fabiano Fidêncio str_append(str, " (core dumped)");
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce return;
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce }
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio if (signum != SIGABRT && signum != SIGSEGV && signum != SIGBUS)
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio return;
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio /* let's try to figure out why we didn't get a core dump */
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio if (core_dumps_disabled) {
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio str_printfa(str, " (core dumps disabled)");
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio return;
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio }
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio#ifndef HAVE_PR_SET_DUMPABLE
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio if (!service->set->drop_priv_before_exec) {
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio str_append(str, " (core not dumped - set drop_priv_before_exec=yes)");
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio return;
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio }
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio if (*service->set->privileged_group != '\0') {
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio str_append(str, " (core not dumped - privileged_group prevented it)");
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio return;
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio }
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio#else
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio if (!service->set->login_dump_core &&
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio service->type == SERVICE_TYPE_LOGIN) {
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio str_append(str, " (core not dumped - add -D parameter to service executable");
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio return;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio }
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio#endif
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio str_append(str, " (core not dumped)");
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio#endif
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio}
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidênciostatic void
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncioservice_process_get_status_error(string_t *str, struct service_process *process,
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio int status, bool *default_fatal_r)
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio{
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio struct service *service = process->service;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio const char *msg;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio *default_fatal_r = FALSE;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio str_printfa(str, "service(%s): child %s ", service->set->name,
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio dec2str(process->pid));
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio if (WIFSIGNALED(status)) {
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio str_printfa(str, "killed with signal %d", WTERMSIG(status));
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio log_coredump(service, str, status);
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio return;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio }
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio if (!WIFEXITED(status)) {
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio str_printfa(str, "died with status %d", status);
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio return;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio }
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio status = WEXITSTATUS(status);
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio if (status == 0) {
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio str_truncate(str, 0);
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio return;
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio }
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio str_printfa(str, "returned error %d", status);
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio msg = get_exit_status_message(service, status);
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio if (msg != NULL)
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio str_printfa(str, " (%s)", msg);
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio if (status == FATAL_DEFAULT)
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio *default_fatal_r = TRUE;
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio}
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidênciostatic void service_process_log(struct service_process *process,
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio bool default_fatal, const char *str)
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio{
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio const char *data;
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio if (!default_fatal || process->service->log_fd[1] == -1) {
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio i_error("%s", str);
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio return;
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio }
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio /* log it via the log process in charge of handling
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio this process's logging */
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek data = t_strdup_printf("%d %s DEFAULT-FATAL %s\n",
f35f4e4c8bd5b834504c0554552d78db3624706aFabiano Fidêncio process->service->log_process_internal_fd,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce dec2str(process->pid), str);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (write(process->service->list->master_log_fd[1],
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce data, strlen(data)) < 0) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce i_error("write(log process) failed: %m");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce i_error("%s", str);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek}
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcevoid service_process_log_status_error(struct service_process *process,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce int status)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* fast path */
8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1Jakub Hrozek return;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce }
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce T_BEGIN {
a9d46b86993ee8d87fddf0ba50665c0b1b78ebb7Simo Sorce string_t *str = t_str_new(256);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek bool default_fatal;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek service_process_get_status_error(str, process, status,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek &default_fatal);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (str_len(str) > 0)
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek service_process_log(process, default_fatal, str_c(str));
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce } T_END;
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio}
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio