~ubuntu-branches/ubuntu/trusty/dovecot/trusty-updates

« back to all changes in this revision

Viewing changes to src/lib-master/master-service.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (1.15.3) (96.1.1 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20140108093549-814nkqdcxfbvgktg
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2005-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "lib-signals.h"
15
15
#include "syslog-util.h"
16
16
#include "master-instance.h"
17
17
#include "master-login.h"
 
18
#include "master-service-ssl.h"
18
19
#include "master-service-private.h"
19
20
#include "master-service-settings.h"
20
21
 
133
134
        lib_init();
134
135
        /* Set a logging prefix temporarily. This will be ignored once the log
135
136
           is properly initialized */
136
 
        i_set_failure_prefix(t_strdup_printf("%s(init): ", name));
 
137
        i_set_failure_prefix("%s(init): ", name);
137
138
 
138
139
        /* ignore these signals as early as possible */
 
140
        lib_signals_init();
139
141
        lib_signals_ignore(SIGPIPE, TRUE);
140
142
        lib_signals_ignore(SIGALRM, FALSE);
141
143
 
149
151
        service->argv = *argv;
150
152
        service->name = i_strdup(name);
151
153
        /* keep getopt_str first in case it contains "+" */
152
 
        service->getopt_str = getopt_str == NULL ?
 
154
        service->getopt_str = *getopt_str == '\0' ?
153
155
                i_strdup(master_service_getopt_string()) :
154
156
                i_strconcat(getopt_str, master_service_getopt_string(), NULL);
155
157
        service->flags = flags;
156
158
        service->ioloop = io_loop_create();
157
 
        service->service_count_left = (unsigned int)-1;
 
159
        service->service_count_left = UINT_MAX;
158
160
        service->config_fd = -1;
159
161
 
160
162
        service->config_path = i_strdup(getenv(MASTER_CONFIG_FILE_ENV));
182
184
                service->listener_names_count =
183
185
                        str_array_length((void *)service->listener_names);
184
186
        }
 
187
        service->want_ssl_settings = service->ssl_socket_count > 0 ||
 
188
                (flags & MASTER_SERVICE_FLAG_USE_SSL_SETTINGS) != 0;
185
189
 
186
190
        /* set up some kind of logging until we know exactly how and where
187
191
           we want to log */
188
192
        if (getenv("LOG_SERVICE") != NULL)
189
193
                i_set_failure_internal();
190
 
        if (getenv("USER") != NULL) {
191
 
                i_set_failure_prefix(t_strdup_printf("%s(%s): ",
192
 
                                                     name, getenv("USER")));
193
 
        } else {
194
 
                i_set_failure_prefix(t_strdup_printf("%s: ", name));
195
 
        }
 
194
        if (getenv("USER") != NULL)
 
195
                i_set_failure_prefix("%s(%s): ", name, getenv("USER"));
 
196
        else
 
197
                i_set_failure_prefix("%s: ", name);
196
198
 
197
199
        if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
198
200
                /* initialize master_status structure */
215
217
                    count > 0)
216
218
                        service->process_limit = count;
217
219
 
 
220
                value = getenv(MASTER_PROCESS_MIN_AVAIL_ENV);
 
221
                if (value != NULL && str_to_uint(value, &count) == 0 &&
 
222
                    count > 0)
 
223
                        service->process_min_avail = count;
 
224
 
218
225
                /* set the default service count */
219
226
                value = getenv(MASTER_SERVICE_COUNT_ENV);
220
227
                if (value != NULL && str_to_uint(value, &count) == 0 &&
229
236
                master_service_set_client_limit(service, 1);
230
237
                master_service_set_service_count(service, 1);
231
238
        }
 
239
        if ((flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0) {
 
240
                /* since we're going to keep the config socket open anyway,
 
241
                   open it now so we can read settings even after privileges
 
242
                   are dropped. */
 
243
                master_service_config_socket_try_open(service);
 
244
        }
232
245
 
233
246
        master_service_verify_version_string(service);
234
247
        return service;
260
273
        if (getenv("LOG_SERVICE") != NULL && !service->log_directly) {
261
274
                /* logging via log service */
262
275
                i_set_failure_internal();
263
 
                i_set_failure_prefix(prefix);
 
276
                i_set_failure_prefix("%s", prefix);
264
277
                return;
265
278
        }
266
279
 
285
298
                                          &facility))
286
299
                        facility = LOG_MAIL;
287
300
                i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
288
 
                i_set_failure_prefix(prefix);
 
301
                i_set_failure_prefix("%s", prefix);
289
302
 
290
303
                if (strcmp(service->set->log_path, "syslog") != 0) {
291
304
                        /* set error handlers back to file */
292
 
                        i_set_fatal_handler(NULL);
293
 
                        i_set_error_handler(NULL);
 
305
                        i_set_fatal_handler(default_fatal_handler);
 
306
                        i_set_error_handler(default_error_handler);
294
307
                }
295
308
        }
296
309
 
332
345
{
333
346
        struct master_instance_list *list;
334
347
        const struct master_instance *inst;
335
 
        const char *path;
 
348
        const char *instance_path, *path;
336
349
 
337
 
        list = master_instance_list_init(MASTER_INSTANCE_PATH);
 
350
        /* note that we don't have any settings yet. we're just finding out
 
351
           which dovecot.conf we even want to read! so we must use the
 
352
           hardcoded state_dir path. */
 
353
        instance_path = t_strconcat(PKG_STATEDIR"/"MASTER_INSTANCE_FNAME, NULL);
 
354
        list = master_instance_list_init(instance_path);
338
355
        inst = master_instance_list_find_by_name(list, name);
339
356
        if (inst != NULL) {
340
357
                path = t_strdup_printf("%s/dovecot.conf", inst->base_dir);
359
376
                if (!get_instance_config(arg, &path))
360
377
                        i_fatal("Unknown instance name: %s", arg);
361
378
                service->config_path = i_strdup(path);
362
 
                service->keep_environment = TRUE;
 
379
                service->config_path_is_default = FALSE;
363
380
                break;
364
381
        case 'k':
365
382
                service->keep_environment = TRUE;
398
415
        }
399
416
}
400
417
 
401
 
static void master_status_error(void *context)
 
418
static void master_status_error(struct master_service *service)
402
419
{
403
 
        struct master_service *service = context;
404
 
 
405
420
        /* status fd is a write-only pipe, so if we're here it means the
406
421
           master wants us to die (or died itself). don't die until all
407
422
           service connections are finished. */
420
435
        struct stat st;
421
436
 
422
437
        /* set default signal handlers */
423
 
        lib_signals_init();
424
438
        if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0)
425
439
                sigint_flags |= LIBSIG_FLAG_RESTART;
426
440
        lib_signals_set_handler(SIGINT, sigint_flags, sig_die, service);
439
453
                                                  master_status_error, service);
440
454
        }
441
455
        master_service_io_listeners_add(service);
 
456
        if (service->want_ssl_settings &&
 
457
            (service->flags & MASTER_SERVICE_FLAG_NO_SSL_INIT) == 0)
 
458
                master_service_ssl_ctx_init(service);
442
459
 
443
460
        if ((service->flags & MASTER_SERVICE_FLAG_STD_CLIENT) != 0) {
444
461
                /* we already have a connection to be served */
485
502
        return service->process_limit;
486
503
}
487
504
 
 
505
unsigned int master_service_get_process_min_avail(struct master_service *service)
 
506
{
 
507
        return service->process_min_avail;
 
508
}
 
509
 
488
510
unsigned int master_service_get_idle_kill_secs(struct master_service *service)
489
511
{
490
512
        return service->idle_kill_secs;
584
606
        return service->killed;
585
607
}
586
608
 
 
609
bool master_service_is_master_stopped(struct master_service *service)
 
610
{
 
611
        return service->io_status_error == NULL;
 
612
}
 
613
 
587
614
void master_service_anvil_send(struct master_service *service, const char *cmd)
588
615
{
589
616
        ssize_t ret;
630
657
                service->total_available_count--;
631
658
                service->service_count_left--;
632
659
        } else {
633
 
                if (service->service_count_left != (unsigned int)-1)
 
660
                if (service->service_count_left != UINT_MAX)
634
661
                        service->service_count_left--;
635
662
 
636
663
                i_assert(service->master_status.available_count <
712
739
        *_service = NULL;
713
740
 
714
741
        master_service_io_listeners_remove(service);
 
742
        master_service_ssl_ctx_deinit(service);
715
743
 
716
744
        master_service_close_config_fd(service);
717
745
        if (service->to_die != NULL)
732
760
                pool_unref(&service->set_pool);
733
761
        }
734
762
        lib_signals_deinit();
 
763
        /* run atexit callbacks before destroying ioloop */
 
764
        lib_atexit_run();
735
765
        io_loop_destroy(&service->ioloop);
736
766
 
737
767
        if (service->listener_names != NULL)
807
837
                if (close(conn.fd) < 0)
808
838
                        i_error("close(service connection) failed: %m");
809
839
                master_service_client_connection_destroyed(service);
810
 
        }
811
 
        if (conn.fifo) {
 
840
        } else if (conn.fifo) {
812
841
                /* reading FIFOs stays open forever, don't count them
813
842
                   as real clients */
814
843
                master_service_client_connection_destroyed(service);
815
844
        }
 
845
        if (service->master_status.available_count == 0 &&
 
846
            service->service_count_left == 1) {
 
847
                /* we're not going to accept any more connections after this.
 
848
                   go ahead and close the connection early. don't do this
 
849
                   before calling callback, because it may want to access
 
850
                   the listen_fd (e.g. to check socket permissions). */
 
851
                i_assert(service->listeners != NULL);
 
852
                master_service_io_listeners_remove(service);
 
853
                master_service_io_listeners_close(service);
 
854
        }
816
855
}
817
856
 
818
857
static void io_listeners_init(struct master_service *service)
870
909
        }
871
910
}
872
911
 
 
912
void master_service_ssl_io_listeners_remove(struct master_service *service)
 
913
{
 
914
        unsigned int i;
 
915
 
 
916
        if (service->listeners != NULL) {
 
917
                for (i = 0; i < service->socket_count; i++) {
 
918
                        if (service->listeners[i].io != NULL &&
 
919
                            service->listeners[i].ssl)
 
920
                                io_remove(&service->listeners[i].io);
 
921
                }
 
922
        }
 
923
}
 
924
 
873
925
static void master_service_io_listeners_close(struct master_service *service)
874
926
{
875
927
        unsigned int i;
883
935
                                        i_error("close(listener %d) failed: %m",
884
936
                                                service->listeners[i].fd);
885
937
                                }
 
938
                                service->listeners[i].fd = -1;
886
939
                        }
887
940
                }
888
941
        } else {
982
1035
bool version_string_verify(const char *line, const char *service_name,
983
1036
                           unsigned major_version)
984
1037
{
 
1038
        unsigned int minor_version;
 
1039
 
 
1040
        return version_string_verify_full(line, service_name,
 
1041
                                          major_version, &minor_version);
 
1042
}
 
1043
 
 
1044
bool version_string_verify_full(const char *line, const char *service_name,
 
1045
                                unsigned major_version,
 
1046
                                unsigned int *minor_version_r)
 
1047
{
985
1048
        unsigned int service_name_len = strlen(service_name);
986
1049
        bool ret;
987
1050
 
995
1058
        line += service_name_len + 1;
996
1059
 
997
1060
        T_BEGIN {
998
 
                ret = str_uint_equals(t_strcut(line, '\t'), major_version);
 
1061
                const char *p = strchr(line, '\t');
 
1062
 
 
1063
                if (p == NULL)
 
1064
                        ret = FALSE;
 
1065
                else {
 
1066
                        ret = str_uint_equals(t_strdup_until(line, p),
 
1067
                                              major_version);
 
1068
                        if (str_to_uint(p+1, minor_version_r) < 0)
 
1069
                                ret = FALSE;
 
1070
                }
999
1071
        } T_END;
1000
1072
        return ret;
1001
1073
}