Add comments as to why smtp_log_no_mail() is not called when
[exim.git] / src / src / daemon.c
index fade1a8d845f544f6508ff702efffb4bb61d1578..1e639453cd1fc51fe39c520ee37fdf292d9da776 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/daemon.c,v 1.14 2006/02/07 11:19:00 ph10 Exp $ */
+/* $Cambridge: exim/src/src/daemon.c,v 1.21 2007/01/17 11:29:39 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with running Exim as a daemon */
@@ -186,13 +186,14 @@ if (smtp_in == NULL)
   goto ERROR_RETURN;
   }
 
-/* Get the data for the local interface address. */
+/* Get the data for the local interface address. Panic for most errors, but
+"connection reset by peer" just means the connection went away. */
 
 if (getsockname(accept_socket, (struct sockaddr *)(&interface_sockaddr),
      &ifsize) < 0)
   {
-  log_write(0, LOG_MAIN|LOG_PANIC, "getsockname() failed: %s",
-    strerror(errno));
+  log_write(0, LOG_MAIN | ((errno == ECONNRESET)? 0 : LOG_PANIC),
+    "getsockname() failed: %s", strerror(errno));
   smtp_printf("421 Local problem: getsockname() failed; please try again later\r\n");
   goto ERROR_RETURN;
   }
@@ -467,7 +468,12 @@ if (pid == 0)
   /* Handle the start of the SMTP session, then loop, accepting incoming
   messages from the SMTP connection. The end will come at the QUIT command,
   when smtp_setup_msg() returns 0. A break in the connection causes the
-  process to die (see accept.c). */
+  process to die (see accept.c).
+
+  NOTE: We do *not* call smtp_log_no_mail() if smtp_start_session() fails,
+  because a log line has already been written for all its failure exists
+  (usually "connection refused: <reason>") and writing another one is
+  unnecessary clutter. */
 
   if (!smtp_start_session())
     {
@@ -499,6 +505,7 @@ if (pid == 0)
       if (!ok)                            /* Connection was dropped */
         {
         mac_smtp_fflush();
+        smtp_log_no_mail();               /* Log no mail if configured */
         _exit(EXIT_SUCCESS);
         }
       if (message_id[0] == 0) continue;   /* No message was accepted */
@@ -507,6 +514,7 @@ if (pid == 0)
       {
       mac_smtp_fflush();
       search_tidyup();
+      smtp_log_no_mail();                 /* Log no mail if configured */
       _exit((rc == 0)? EXIT_SUCCESS : EXIT_FAILURE);
       }
 
@@ -680,13 +688,14 @@ ERROR_RETURN:
 /* Close the streams associated with the socket which will also close the
 socket fds in this process. We can't do anything if fclose() fails, but
 logging brings it to someone's attention. However, "connection reset by peer"
-isn't really a problem, so skip that one. If the streams don't exist, something
-went wrong while setting things up. Make sure the socket descriptors are
-closed, in order to drop the connection. */
+isn't really a problem, so skip that one. On Solaris, a dropped connection can
+manifest itself as a broken pipe, so drop that one too. If the streams don't
+exist, something went wrong while setting things up. Make sure the socket
+descriptors are closed, in order to drop the connection. */
 
 if (smtp_out != NULL)
   {
-  if (fclose(smtp_out) != 0 && errno != ECONNRESET)
+  if (fclose(smtp_out) != 0 && errno != ECONNRESET && errno != EPIPE)
     log_write(0, LOG_MAIN|LOG_PANIC, "daemon: fclose(smtp_out) failed: %s",
       strerror(errno));
   smtp_out = NULL;
@@ -695,7 +704,7 @@ else (void)close(accept_socket);
 
 if (smtp_in != NULL)
   {
-  if (fclose(smtp_in) != 0 && errno != ECONNRESET)
+  if (fclose(smtp_in) != 0 && errno != ECONNRESET && errno != EPIPE)
     log_write(0, LOG_MAIN|LOG_PANIC, "daemon: fclose(smtp_in) failed: %s",
       strerror(errno));
   smtp_in = NULL;
@@ -1414,11 +1423,10 @@ if (running_in_test_harness || write_pid)
   if (pid_file_path[0] == 0)
     pid_file_path = string_sprintf("%s/exim-daemon.pid", spool_directory);
 
-  f = Ufopen(pid_file_path, "wb");
+  f = modefopen(pid_file_path, "wb", 0644);
   if (f != NULL)
     {
     (void)fprintf(f, "%d\n", (int)getpid());
-    (void)fchmod(fileno(f), 0644);
     (void)fclose(f);
     DEBUG(D_any) debug_printf("pid written to %s\n", pid_file_path);
     }
@@ -1628,6 +1636,8 @@ for (;;)
           {
           uschar opt[8];
           uschar *p = opt;
+          uschar *extra[4];
+          int extracount = 1;
 
           signal(SIGALRM, SIG_DFL);
           *p++ = '-';
@@ -1638,8 +1648,29 @@ for (;;)
           if (deliver_force_thaw) *p++ = 'f';
           if (queue_run_local) *p++ = 'l';
           *p = 0;
+          extra[0] = opt;
+
+          /* If -R or -S were on the original command line, ensure they get
+          passed on. */
+
+          if (deliver_selectstring != NULL)
+            {
+            extra[extracount++] = deliver_selectstring_regex? US"-Rr" : US"-R";
+            extra[extracount++] = deliver_selectstring;
+            }
+
+          if (deliver_selectstring_sender != NULL)
+            {
+            extra[extracount++] = deliver_selectstring_sender_regex?
+              US"-Sr" : US"-S";
+            extra[extracount++] = deliver_selectstring_sender;
+            }
+
+          /* Overlay this process with a new execution. */
+
+          (void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, TRUE, extracount,
+            extra[0], extra[1], extra[2], extra[3], extra[4]);
 
-          (void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, TRUE, 1, opt);
           /* Control never returns here. */
           }