Unbreak no-TLS build
[exim.git] / src / src / daemon.c
index 067bb3329bbc6fc26b006b50cd49c13cc32ea6e6..78a4d8ec2ba137fc3d24188ca224a555e8b3d8b3 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with running Exim as a daemon */
@@ -58,7 +59,6 @@ Returns:  nothing
 static void
 sighup_handler(int sig)
 {
-sig = sig;    /* Keep picky compilers happy */
 sighup_seen = TRUE;
 signal(SIGHUP, sighup_handler);
 }
@@ -82,7 +82,6 @@ Returns:  nothing
 static void
 main_sigchld_handler(int sig)
 {
-sig = sig;    /* Keep picky compilers happy */
 os_non_restarting_signal(SIGCHLD, SIG_DFL);
 sigchld_seen = TRUE;
 }
@@ -126,6 +125,18 @@ if (smtp_out) smtp_printf("421 %s\r\n", FALSE, smtp_msg);
 
 
 
+/*************************************************
+*************************************************/
+
+static void
+close_daemon_sockets(int daemon_notifier_fd,
+  int * listen_sockets, int listen_socket_count)
+{
+if (daemon_notifier_fd >= 0) (void) close(daemon_notifier_fd);
+for (int i = 0; i < listen_socket_count; i++) (void) close(listen_sockets[i]);
+}
+
+
 /*************************************************
 *            Handle a connected SMTP call        *
 *************************************************/
@@ -265,10 +276,10 @@ to provide host-specific limits according to $sender_host address, but because
 this is in the daemon mainline, only fast expansions (such as inline address
 checks) should be used. The documentation is full of warnings. */
 
-if (smtp_accept_max_per_host != NULL)
+if (smtp_accept_max_per_host)
   {
   uschar *expanded = expand_string(smtp_accept_max_per_host);
-  if (expanded == NULL)
+  if (!expanded)
     {
     if (!f.expand_string_forcedfail)
       log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
@@ -280,7 +291,7 @@ if (smtp_accept_max_per_host != NULL)
     uschar *s = expanded;
     while (isdigit(*s))
       max_for_this_host = max_for_this_host * 10 + *s++ - '0';
-    if (*s != 0)
+    if (*s)
       log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
         "for %s contains non-digit: %s", whofrom->s, expanded);
     }
@@ -290,8 +301,7 @@ if (smtp_accept_max_per_host != NULL)
 per host_address checks. Note that at this stage smtp_accept_count contains the
 count of *other* connections, not including this one. */
 
-if ((max_for_this_host > 0) &&
-    (smtp_accept_count >= max_for_this_host))
+if (max_for_this_host > 0 && smtp_accept_count >= max_for_this_host)
   {
   int host_accept_count = 0;
   int other_host_count = 0;    /* keep a count of non matches to optimise */
@@ -308,8 +318,8 @@ if ((max_for_this_host > 0) &&
       early, either by hitting the target, or finding there are not enough
       connections left to make the target. */
 
-      if ((host_accept_count >= max_for_this_host) ||
-         ((smtp_accept_count - other_host_count) < max_for_this_host))
+      if (  host_accept_count >= max_for_this_host
+         || smtp_accept_count - other_host_count < max_for_this_host)
        break;
       }
 
@@ -323,6 +333,7 @@ if ((max_for_this_host > 0) &&
     log_write(L_connection_reject,
               LOG_MAIN, "Connection from %s refused: too many connections "
       "from that IP address", whofrom->s);
+    search_tidyup();
     goto ERROR_RETURN;
     }
   }
@@ -355,13 +366,12 @@ if (LOGGING(smtp_connection))
 expansion above did a lookup. */
 
 search_tidyup();
-pid = fork();
+pid = exim_fork(US"daemon-accept");
 
 /* Handle the child process */
 
 if (pid == 0)
   {
-  int i;
   int queue_only_reason = 0;
   int old_pool = store_pool;
   int save_debug_selector = debug_selector;
@@ -424,7 +434,7 @@ if (pid == 0)
   extensive comment before the reception loop in exim.c for a fuller
   explanation of this logic. */
 
-  for (i = 0; i < listen_socket_count; i++) (void)close(listen_sockets[i]);
+  close_daemon_sockets(daemon_notifier_fd, listen_sockets, listen_socket_count);
 
   /* Set FD_CLOEXEC on the SMTP socket. We don't want any rogue child processes
   to be able to communicate with them, under any circumstances. */
@@ -651,7 +661,7 @@ if (pid == 0)
 
       mac_smtp_fflush();
 
-      if ((dpid = fork()) == 0)
+      if ((dpid = exim_fork(US"daemon-accept-delivery")) == 0)
         {
         (void)fclose(smtp_in);
         (void)fclose(smtp_out);
@@ -940,9 +950,8 @@ if ((f = Ufopen(pid_file_path, "rb")))
   }
 else
   DEBUG(D_any)
-    debug_printf("%s\n", string_open_failed(errno, "pid file %s",
-      pid_file_path));
-exim_exit(EXIT_SUCCESS, US"pid file remover");
+    debug_printf("%s\n", string_open_failed("pid file %s", pid_file_path));
+exim_exit(EXIT_SUCCESS);
 }
 
 
@@ -954,13 +963,17 @@ daemon_die(void)
 {
 int pid;
 
+#if !defined(DISABLE_TLS) && (defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT))
+tls_watch_invalidate();
+#endif
+
 if (daemon_notifier_fd >= 0)
   {
   close(daemon_notifier_fd);
   daemon_notifier_fd = -1;
 #ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
     {
-    uschar * s = string_sprintf("%s/%s", spool_directory, NOTIFIER_SOCKET_NAME);
+    uschar * s = expand_string(notifier_socket);
     DEBUG(D_any) debug_printf("unlinking notifier socket %s\n", s);
     Uunlink(s);
     }
@@ -969,7 +982,7 @@ if (daemon_notifier_fd >= 0)
 
 if (f.running_in_test_harness || write_pid)
   {
-  if ((pid = fork()) == 0)
+  if ((pid = exim_fork(US"daemon-del-pidfile")) == 0)
     {
     if (override_pid_file_path)
       (void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, FALSE, 3,
@@ -982,7 +995,7 @@ if (f.running_in_test_harness || write_pid)
   if (pid > 0)
     child_close(pid, 1);
   }
-exim_exit(EXIT_SUCCESS, US"daemon");
+exim_exit(EXIT_SUCCESS);
 }
 
 
@@ -998,7 +1011,19 @@ const uschar * where;
 struct sockaddr_un sa_un = {.sun_family = AF_UNIX};
 int len;
 
-DEBUG(D_any) debug_printf("creating notifier socket ");
+if (!notifier_socket || !*notifier_socket)
+  {
+  DEBUG(D_any) debug_printf("-oY used so not creating notifier socket\n");
+  return;
+  }
+if (override_local_interfaces && !override_pid_file_path)
+  {
+  DEBUG(D_any)
+    debug_printf("-oX used without -oP so not creating notifier socket\n");
+  return;
+  }
+
+DEBUG(D_any) debug_printf("creating notifier socket\n");
 
 #ifdef SOCK_CLOEXEC
 if ((fd = socket(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
@@ -1012,13 +1037,14 @@ if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0)
 #ifdef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
 sa_un.sun_path[0] = 0; /* Abstract local socket addr - Linux-specific? */
 len = offsetof(struct sockaddr_un, sun_path) + 1
-  + snprintf(sa_un.sun_path+1, sizeof(sa_un.sun_path)-1, "%s", NOTIFIER_SOCKET_NAME);
-DEBUG(D_any) debug_printf("@%s\n", sa_un.sun_path+1);
+  + snprintf(sa_un.sun_path+1, sizeof(sa_un.sun_path)-1, "%s",
+             expand_string(notifier_socket));
+DEBUG(D_any) debug_printf(" @%s\n", sa_un.sun_path+1);
 #else                  /* filesystem-visible and persistent; will neeed removal */
 len = offsetof(struct sockaddr_un, sun_path)
-  + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path), "%s/%s", 
-               spool_directory, NOTIFIER_SOCKET_NAME);
-DEBUG(D_any) debug_printf("%s\n", sa_un.sun_path);
+  + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path), "%s", 
+             expand_string(notifier_socket));
+DEBUG(D_any) debug_printf(" %s\n", sa_un.sun_path);
 #endif
 
 if (bind(fd, (const struct sockaddr *)&sa_un, len) < 0)
@@ -1056,20 +1082,15 @@ daemon_notification(void)
 {
 uschar buf[256], cbuf[256];
 struct sockaddr_un sa_un;
-struct iovec iov = {.iov_base = (void *)buf,   /* ? cast needed for Solaris compiler */
-                   .iov_len = sizeof(buf)-1
-                  };
+struct iovec iov = {.iov_base = buf, .iov_len = sizeof(buf)-1};
 struct msghdr msg = { .msg_name = &sa_un,
                      .msg_namelen = sizeof(sa_un),
                      .msg_iov = &iov,
                      .msg_iovlen = 1,
-#if !defined(__sun)
                      .msg_control = cbuf,
                      .msg_controllen = sizeof(cbuf)
-#endif
                    };
 ssize_t sz;
-struct cmsghdr * cp;
 
 buf[sizeof(buf)-1] = 0;
 if ((sz = recvmsg(daemon_notifier_fd, &msg, 0)) <= 0) return FALSE;
@@ -1123,14 +1144,14 @@ for (struct cmsghdr * cp = CMSG_FIRSTHDR(&msg);
 buf[sz] = 0;
 switch (buf[0])
   {
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
   case NOTIFY_MSG_QRUN:
     /* this should be a message_id */
     DEBUG(D_queue_run)
       debug_printf("%s: qrunner trigger: %s\n", __FUNCTION__, buf+1);
     memcpy(queuerun_msgid, buf+1, MESSAGE_ID_LENGTH+1);
     return TRUE;
-#endif /*EXPERIMENTAL_QUEUE_RAMP*/
+#endif
 
   case NOTIFY_QUEUE_SIZE_REQ:
     {
@@ -1184,6 +1205,8 @@ ip_address_item *addresses = NULL;
 time_t last_connection_time = (time_t)0;
 int local_queue_run_max = atoi(CS expand_string(queue_run_max));
 
+process_purpose = US"daemon";
+
 /* If any debugging options are set, turn on the D_pid bit so that all
 debugging lines get the pid added. */
 
@@ -1335,7 +1358,7 @@ if (f.daemon_listen && !f.inetd_wait_mode)
 
     list = override_local_interfaces;
     sep = 0;
-    while ((s = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)))
+    while ((s = string_nextinlist(&list, &sep, NULL, 0)))
       {
       uschar joinstr[4];
       gstring ** gp = Ustrpbrk(s, ".:") ? &new_local_interfaces : &new_smtp_port;
@@ -1373,13 +1396,13 @@ if (f.daemon_listen && !f.inetd_wait_mode)
 
   list = daemon_smtp_port;
   sep = 0;
-  while ((s = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)))
+  while ((s = string_nextinlist(&list, &sep, NULL, 0)))
     pct++;
   default_smtp_port = store_get((pct+1) * sizeof(int), FALSE);
   list = daemon_smtp_port;
   sep = 0;
   for (pct = 0;
-       (s = string_nextinlist(&list, &sep, big_buffer, big_buffer_size));
+       (s = string_nextinlist(&list, &sep, NULL, 0));
        pct++)
     {
     if (isdigit(*s))
@@ -1585,7 +1608,7 @@ if (f.background_daemon)
 
   if (getppid() != 1)
     {
-    pid_t pid = fork();
+    pid_t pid = exim_fork(US"daemon");
     if (pid < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
       "fork() failed when starting daemon: %s", strerror(errno));
     if (pid > 0) exit(EXIT_SUCCESS);      /* in parent process, just exit */
@@ -1807,8 +1830,7 @@ if (f.running_in_test_harness || write_pid)
     }
   else
     DEBUG(D_any)
-      debug_printf("%s\n", string_open_failed(errno, "pid file %s",
-        pid_file_path));
+      debug_printf("%s\n", string_open_failed("pid file %s", pid_file_path));
   }
 
 /* Set up the handler for SIGHUP, which causes a restart of the daemon. */
@@ -1883,7 +1905,8 @@ else if (f.daemon_listen)
   ip_address_item * ipa;
   uschar * p;
   uschar * qinfo = queue_interval > 0
-    ? string_sprintf("-q%s", readconf_printtime(queue_interval))
+    ? string_sprintf("-q%s%s",
+       f.queue_2stage ? "q" : "", readconf_printtime(queue_interval))
     : US"no queue runs";
 
   /* Build a list of listening addresses in big_buffer, but limit it to 10
@@ -2020,6 +2043,9 @@ malware_init();
 #ifdef SUPPORT_SPF
 spf_init();
 #endif
+#ifndef DISABLE_TLS
+tls_daemon_init();
+#endif
 
 /* Close the log so it can be renamed and moved. In the few cases below where
 this long-running process writes to the log (always exceptional conditions), it
@@ -2102,7 +2128,7 @@ for (;;)
     else
       {
       DEBUG(D_any) debug_printf("%s received\n",
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
        *queuerun_msgid ? "qrun notification" :
 #endif
        "SIGALRM");
@@ -2111,14 +2137,11 @@ for (;;)
       have enough queue runners on the go. If we are not running as root, a
       re-exec is required. */
 
-      if (queue_interval > 0 &&
-         (local_queue_run_max <= 0 || queue_run_count < local_queue_run_max))
+      if (  queue_interval > 0
+         && (local_queue_run_max <= 0 || queue_run_count < local_queue_run_max))
         {
-        if ((pid = fork()) == 0)
+        if ((pid = exim_fork(US"queue-runner")) == 0)
           {
-          DEBUG(D_any) debug_printf("Starting queue-runner: pid %d\n",
-            (int)getpid());
-
           /* Disable debugging if it's required only for the daemon process. We
           leave the above message, because it ties up with the "child ended"
           debugging messages. */
@@ -2127,10 +2150,8 @@ for (;;)
 
           /* Close any open listening sockets in the child */
 
-         if (daemon_notifier_fd >= 0)
-           (void) close(daemon_notifier_fd);
-          for (int sk = 0; sk < listen_socket_count; sk++)
-            (void) close(listen_sockets[sk]);
+         close_daemon_sockets(daemon_notifier_fd,
+           listen_sockets, listen_socket_count);
 
           /* Reset SIGHUP and SIGCHLD in the child in both cases. */
 
@@ -2152,7 +2173,7 @@ for (;;)
             *p++ = '-';
             *p++ = 'q';
             if (  f.queue_2stage
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
               && !*queuerun_msgid
 #endif
               ) *p++ = 'q';
@@ -2164,9 +2185,10 @@ for (;;)
            extra[0] = *queue_name
              ? string_sprintf("%sG%s", opt, queue_name) : opt;
 
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
            if (*queuerun_msgid)
              {
+             log_write(0, LOG_MAIN, "notify triggered queue run");
              extra[extracount++] = queuerun_msgid;     /* Trigger only the */
              extra[extracount++] = queuerun_msgid;     /* one message      */
              }
@@ -2198,9 +2220,10 @@ for (;;)
 
           /* No need to re-exec; SIGALRM remains set to the default handler */
 
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
          if (*queuerun_msgid)
            {
+           log_write(0, LOG_MAIN, "notify triggered queue run");
            f.queue_2stage = FALSE;
            queue_run(queuerun_msgid, queuerun_msgid, FALSE);
            }
@@ -2233,7 +2256,7 @@ for (;;)
       /* Reset the alarm clock */
 
       sigalrm_seen = FALSE;
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
       if (*queuerun_msgid)
        *queuerun_msgid = 0;
       else
@@ -2261,8 +2284,18 @@ for (;;)
     fd_set select_listen;
 
     FD_ZERO(&select_listen);
+#ifndef DISABLE_TLS
+    if (tls_watch_fd >= 0)
+      {
+      FD_SET(tls_watch_fd, &select_listen);
+      if (tls_watch_fd > max_socket) max_socket = tls_watch_fd;
+      }
+#endif
     if (daemon_notifier_fd >= 0)
+      {
       FD_SET(daemon_notifier_fd, &select_listen);
+      if (daemon_notifier_fd > max_socket) max_socket = daemon_notifier_fd;
+      }
     for (int sk = 0; sk < listen_socket_count; sk++)
       {
       FD_SET(listen_sockets[sk], &select_listen);
@@ -2305,8 +2338,8 @@ for (;;)
     errno = select_errno;
 
 #ifndef DISABLE_TLS
-    /* Create or rotate any required keys */
-    tls_daemon_init();
+    /* Create or rotate any required keys; handle (delayed) filewatch event */
+    tls_daemon_tick();
 #endif
 
     /* Loop for all the sockets that are currently ready to go. If select
@@ -2319,6 +2352,15 @@ for (;;)
 
       if (!select_failed)
        {
+#if !defined(DISABLE_TLS) && (defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT))
+       if (tls_watch_fd >= 0 && FD_ISSET(tls_watch_fd, &select_listen))
+         {
+         FD_CLR(tls_watch_fd, &select_listen);
+          tls_watch_trigger_time = time(NULL); /* Set up delayed event */
+         tls_watch_discard_event(tls_watch_fd);
+         break;        /* to top of daemon loop */
+         }
+#endif
        if (  daemon_notifier_fd >= 0
           && FD_ISSET(daemon_notifier_fd, &select_listen))
          {
@@ -2438,8 +2480,8 @@ for (;;)
     {
     log_write(0, LOG_MAIN, "pid %d: SIGHUP received: re-exec daemon",
       getpid());
-    for (int sk = 0; sk < listen_socket_count; sk++)
-      (void)close(listen_sockets[sk]);
+    close_daemon_sockets(daemon_notifier_fd,
+      listen_sockets, listen_socket_count);
     ALARM_CLR(0);
     signal(SIGHUP, SIG_IGN);
     sighup_argv[0] = exim_path;