service.c revision 7f6762146f515f9ccbab0876a7747df2fbd4a11e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen#define SERVICE_LOGIN_NOTIFY_MIN_INTERVAL_SECS 2
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenvoid service_error(struct service *service, const char *format, ...)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen i_error("service(%s): %s", service->set->name,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenservice_create_file_listener(struct service *service,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen const char **error_r)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen l = p_new(service->list->pool, struct service_listener, 1);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen if (get_uidgid(set->user, &l->set.fileset.uid, &gid, error_r) < 0)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen if (get_gid(set->group, &l->set.fileset.gid, error_r) < 0)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenresolve_ip(const char *address, struct ip_addr *ip_r, const char **error_r)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen if (address == NULL || strcmp(address, "*") == 0) {
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* IPv4 any */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* IPv6 any */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* Return the first IP if there happens to be multiple. */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen ret = net_gethostbyname(address, &ip_list, &ips_count);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen *error_r = t_strdup_printf("Can't resolve address %s: %s",
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen *error_r = t_strdup_printf("No IPs for address: %s", address);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen *error_r = t_strdup_printf("Multiple IPs for address: %s",
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenservice_create_one_inet_listener(struct service *service,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen l = p_new(service->list->pool, struct service_listener, 1);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen l->inet_address = p_strdup(service->list->pool, address);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen if (resolve_ip(address, &l->set.inetset.ip, error_r) < 0)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen *error_r = t_strdup_printf("Invalid port: %u", set->port);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenservice_create_inet_listeners(struct service *service,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen const char **error_r)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen static struct service_listener *l;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen bool ssl_disabled = strcmp(service->set->master_set->ssl, "no") == 0;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* disabled */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* use the default listen address */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen l = service_create_one_inet_listener(service, set, *tmp,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenstatic struct service *
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenservice_create(pool_t pool, const struct service_settings *set,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen struct service_list *service_list, const char **error_r)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen struct file_listener_settings *const *unix_listeners;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen struct file_listener_settings *const *fifo_listeners;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen struct inet_listener_settings *const *inet_listeners;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen const char *const *tmp;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen unsigned int i, unix_count, fifo_count, inet_count;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen service->client_limit = set->client_limit != 0 ? set->client_limit :
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen service->vsz_limit = set->vsz_limit != (uoff_t)-1 ? set->vsz_limit :
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* unlimited */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* use default */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* default gid to user's primary group */
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen if (get_uidgid(set->user, &service->uid, &service->gid, error_r) < 0)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen if (get_gid(set->group, &service->gid, error_r) < 0)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen if (get_gid(set->privileged_group, &service->privileged_gid,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen service->extra_gids = p_strdup(pool, str_c(str));
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen p_strconcat(pool, set->master_set->libexec_dir, "/",
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* set these later, so if something fails we don't have to worry about
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen closing them */
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen service->status_fd[0] = service_anvil_global->status_fd[0];
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen service->status_fd[1] = service_anvil_global->status_fd[1];
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen unix_listeners = array_get(&set->unix_listeners, &unix_count);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen fifo_listeners = array_get(&set->unix_listeners, &fifo_count);
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen inet_listeners = array_get(&set->inet_listeners, &inet_count);
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen if (unix_count == 0 && service->type == SERVICE_TYPE_CONFIG) {
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen *error_r = "Service must have unix listeners";
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen for (i = 0; i < unix_count; i++) {
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen /* disabled */
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen l = service_create_file_listener(service, SERVICE_LISTENER_UNIX,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen for (i = 0; i < fifo_count; i++) {
795aeec896095aa8f08cc5d3282c88cc0921bff6Timo Sirainen /* disabled */
4394b73cacaf2c31a9b601f66b6e26a1c8f114b4Timo Sirainen l = service_create_file_listener(service, SERVICE_LISTENER_UNIX,
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen for (i = 0; i < inet_count; i++) {
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen if (service_create_inet_listeners(service, inet_listeners[i],
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen if (access(t_strcut(service->executable, ' '), X_OK) < 0) {
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen *error_r = t_strdup_printf("access(%s) failed: %m",
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainenstatic unsigned int pid_hash(const void *p)
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen return (unsigned int)*pid;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenstatic int pid_hash_cmp(const void *p1, const void *p2)
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainenservice_lookup(struct service_list *service_list, const char *name)
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen array_foreach(&service_list->services, services) {
return NULL;
struct service *
return service;
return NULL;
char *const *proto;
return TRUE;
return TRUE;
return FALSE;
const char *const *child_process_env,
const char *error;
unsigned int i, count;
for (i = 0; i < count; i++) {
case SERVICE_TYPE_LOG:
case SERVICE_TYPE_CONFIG:
case SERVICE_TYPE_ANVIL:
int diff;
service);
bool sigterm_log;
int sig;
unsigned int count;
unsigned int secs)
void service_pids_init(void)
void service_pids_deinit(void)