Intercept chown()/fchown() failure and emit a pointer to the bugreport. Closes 2391
[exim.git] / src / src / exim.c
index 5c9d4ee16a478791ae59968cb097c6aa76231fb0..2dbc41162513504d9c5df13b8815df743b6a0e8d 100644 (file)
@@ -473,8 +473,6 @@ return f;
 }
 
 
-
-
 /*************************************************
 *   Ensure stdin, stdout, and stderr exist       *
 *************************************************/
@@ -687,6 +685,36 @@ vfprintf(stderr, fmt, ap);
 exit(EXIT_FAILURE);
 }
 
+/* exim_chown_failure() called from exim_chown()/exim_fchown() on failure
+of chown()/fchown().  See src/functions.h for more explanation */
+int
+exim_chown_failure(int fd, const uschar *name, uid_t owner, gid_t group)
+{
+#if 1
+log_write(0, LOG_MAIN|LOG_PANIC,
+  __FILE__ ":%d: chown(%s, %d:%d) failed (%s)."
+  " Please contact the authors and refer to https://bugs.exim.org/show_bug.cgi?id=2391",
+  __LINE__, name?name:US"<unknown>", owner, group, strerror(errno));
+#else
+/* I leave this here, commented, in case the "bug"(?) comes up again.
+   It is not an Exim bug, but we can provide a workaround.
+   See Bug 2391
+   HS 2019-04-18 */
+
+int saved_errno = errno;  /* from the preceeding chown call */
+struct stat buf;
+
+if (0 == (fd < 0 ? stat(name, &buf) : fstat(fd, &buf)))
+{
+  if (buf.st_uid == owner && buf.st_gid == group) return 0;
+  log_write(0, LOG_MAIN|LOG_PANIC, "Wrong ownership on %s", name);
+}
+else log_write(0, LOG_MAIN|LOG_PANIC, "Stat failed on %s: %s", name, strerror(errno));
+
+errno = saved_errno;
+return -1;
+#endif
+}
 
 
 /*************************************************
@@ -903,9 +931,6 @@ fprintf(fp, "Support for:");
 #ifdef EXPERIMENTAL_DSN_INFO
   fprintf(fp, " Experimental_DSN_info");
 #endif
-#ifdef EXPERIMENTAL_REQUIRETLS
-  fprintf(fp, " Experimental_REQUIRETLS");
-#endif
 #ifdef EXPERIMENTAL_PIPE_CONNECT
   fprintf(fp, " Experimental_PIPE_CONNECT");
 #endif
@@ -930,6 +955,9 @@ fprintf(fp, "Lookups (built-in):");
 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
   fprintf(fp, " ibase");
 #endif
+#if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
+  fprintf(fp, " json");
+#endif
 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
   fprintf(fp, " ldap ldapdn ldapm");
 #endif
@@ -2683,7 +2711,7 @@ for (i = 1; i < argc; i++)
 
 #ifdef SUPPORT_TLS
     /* -MCt: similar to -MCT below but the connection is still open
-    via a proxy proces which handles the TLS context and coding.
+    via a proxy process which handles the TLS context and coding.
     Require three arguments for the proxied local address and port,
     and the TLS cipher.  */
 
@@ -2707,16 +2735,6 @@ for (i = 1; i < argc; i++)
       break;
       }
 
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
-    /* -MS   set REQUIRETLS on (new) message */
-
-    else if (*argrest == 'S')
-      {
-      tls_requiretls |= REQUIRETLS_MSG;
-      break;
-      }
-#endif
-
     /* -M[x]: various operations on the following list of message ids:
        -M    deliver the messages, ignoring next retry times and thawing
        -Mc   deliver the messages, checking next retry times, no thawing
@@ -3635,7 +3653,7 @@ if (f.running_in_test_harness) smtputf8_advertise_hosts = NULL;
 is a failure. It leaves the configuration file open so that the subsequent
 configuration data for delivery can be read if needed.
 
-NOTE: immediatly after opening the configuration file we change the working
+NOTE: immediately after opening the configuration file we change the working
 directory to "/"! Later we change to $spool_directory. We do it there, because
 during readconf_main() some expansion takes place already. */