constification
[exim.git] / src / src / exim.c
index de25b325659b27fd2753770d04561f19fde8d8cf..bedac628b0a852d3494194ea962b8c48188700d5 100644 (file)
@@ -279,6 +279,8 @@ if (US info->si_addr < US 4096)
   log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (null pointer indirection)");
 else
   log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (maybe attempt to write to immutable memory)");
+if (process_info_len > 0)
+  log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (%.*s)", process_info_len, process_info);
 signal(SIGSEGV, SIG_DFL);
 kill(getpid(), sig);
 }
@@ -287,6 +289,8 @@ kill(getpid(), sig);
 segv_handler(int sig)
 {
 log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (maybe attempt to write to immutable memory)");
+if (process_info_len > 0)
+  log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (%.*s)", process_info_len, process_info);
 signal(SIGSEGV, SIG_DFL);
 kill(getpid(), sig);
 }
@@ -735,7 +739,7 @@ Returns:     nothing; bombs out on failure
 */
 
 void
-exim_setugid(uid_t uid, gid_t gid, BOOL igflag, uschar *msg)
+exim_setugid(uid_t uid, gid_t gid, BOOL igflag, const uschar * msg)
 {
 uid_t euid = geteuid();
 gid_t egid = getegid();
@@ -944,7 +948,7 @@ else
   int rc = verify_address(deliver_make_addr(address,TRUE), stdout, flags, -1,
     -1, -1, NULL, NULL, NULL);
   if (rc == FAIL) *exit_value = 2;
-    else if (rc == DEFER && *exit_value == 0) *exit_value = 1;
+  else if (rc == DEFER && *exit_value == 0) *exit_value = 1;
   }
 }
 
@@ -955,54 +959,66 @@ else
 *************************************************/
 
 static void
-show_db_version(FILE * f)
+show_string(BOOL is_stdout, gstring * g)
+{
+const uschar * s = string_from_gstring(g);
+if (s)
+  if (is_stdout) fputs(CCS s, stdout);
+  else debug_printf("%s", s);
+}
+
+
+static gstring *
+show_db_version(gstring * g)
 {
 #ifdef DB_VERSION_STRING
 DEBUG(D_any)
   {
-  fprintf(f, "Library version: BDB: Compile: %s\n", DB_VERSION_STRING);
-  fprintf(f, "                      Runtime: %s\n",
+  g = string_fmt_append(g, "Library version: BDB: Compile: %s\n", DB_VERSION_STRING);
+  g = string_fmt_append(g, "                      Runtime: %s\n",
     db_version(NULL, NULL, NULL));
   }
 else
-  fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING);
+  g = string_fmt_append(g, "Berkeley DB: %s\n", DB_VERSION_STRING);
 
 #elif defined(BTREEVERSION) && defined(HASHVERSION)
-  #ifdef USE_DB
-  fprintf(f, "Probably Berkeley DB version 1.8x (native mode)\n");
-  #else
-  fprintf(f, "Probably Berkeley DB version 1.8x (compatibility mode)\n");
-  #endif
+ifdef USE_DB
+  g = string_cat(g, US"Probably Berkeley DB version 1.8x (native mode)\n");
+else
+  g = string_cat(g, US"Probably Berkeley DB version 1.8x (compatibility mode)\n");
+endif
 
 #elif defined(_DBM_RDONLY) || defined(dbm_dirfno)
-fprintf(f, "Probably ndbm\n");
+g = string_cat(g, US"Probably ndbm\n");
 #elif defined(USE_TDB)
-fprintf(f, "Using tdb\n");
+g = string_cat(g, US"Using tdb\n");
 #else
-  #ifdef USE_GDBM
-  fprintf(f, "Probably GDBM (native mode)\n");
-  #else
-  fprintf(f, "Probably GDBM (compatibility mode)\n");
-  #endif
+ifdef USE_GDBM
+  g = string_cat(g, US"Probably GDBM (native mode)\n");
+else
+  g = string_cat(g, US"Probably GDBM (compatibility mode)\n");
+endif
 #endif
+return g;
 }
 
 
 /* This function is called for -bV/--version and for -d to output the optional
 features of the current Exim binary.
 
-Arguments:  a FILE for printing
+Arguments:  BOOL, true for stdout else debug channel
 Returns:    nothing
 */
 
 static void
-show_whats_supported(FILE * fp)
+show_whats_supported(BOOL is_stdout)
 {
 rmark reset_point = store_mark();
-gstring * g;
-DEBUG(D_any) {} else show_db_version(fp);
+gstring * g = NULL;
 
-g = string_cat(NULL, US"Support for:");
+DEBUG(D_any) {} else g = show_db_version(g);
+
+g = string_cat(g, US"Support for:");
 #ifdef SUPPORT_CRYPTEQ
   g = string_cat(g, US" crypteq");
 #endif
@@ -1109,9 +1125,6 @@ g = string_cat(NULL, US"Support for:");
 #ifdef EXPERIMENTAL_QUEUEFILE
   g = string_cat(g, US" Experimental_QUEUEFILE");
 #endif
-#if defined(EXPERIMENTAL_SRS_ALT)
-  g = string_cat(g, US" Experimental_SRS");
-#endif
 g = string_cat(g, US"\n");
 
 g = string_cat(g, US"Lookups (built-in):");
@@ -1181,6 +1194,7 @@ g = transport_show_supported(g);
 #ifdef WITH_CONTENT_SCAN
 g = malware_show_supported(g);
 #endif
+show_string(is_stdout, g); g = NULL;
 
 if (fixed_never_users[0] > 0)
   {
@@ -1192,19 +1206,19 @@ if (fixed_never_users[0] > 0)
   }
 
 g = string_fmt_append(g, "Configure owner: %d:%d\n", config_uid, config_gid);
-fputs(CS string_from_gstring(g), fp);
 
-fprintf(fp, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t));
+g = string_fmt_append(g, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t));
 
 /* Everything else is details which are only worth reporting when debugging.
 Perhaps the tls_version_report should move into this too. */
-DEBUG(D_any) do {
+DEBUG(D_any)
+  {
 
 /* clang defines __GNUC__ (at least, for me) so test for it first */
 #if defined(__clang__)
-  fprintf(fp, "Compiler: CLang [%s]\n", __clang_version__);
+  g = string_fmt_append(g, "Compiler: CLang [%s]\n", __clang_version__);
 #elif defined(__GNUC__)
-  fprintf(fp, "Compiler: GCC [%s]\n",
+  g = string_fmt_append(g, "Compiler: GCC [%s]\n",
 # ifdef __VERSION__
       __VERSION__
 # else
@@ -1212,35 +1226,38 @@ DEBUG(D_any) do {
 # endif
       );
 #else
-  fprintf(fp, "Compiler: <unknown>\n");
+  g = string_cat(g, US"Compiler: <unknown>\n");
 #endif
 
 #if defined(__GLIBC__) && !defined(__UCLIBC__)
-  fprintf(fp, "Library version: Glibc: Compile: %d.%d\n",
+  g = string_fmt_append(g, "Library version: Glibc: Compile: %d.%d\n",
                __GLIBC__, __GLIBC_MINOR__);
   if (__GLIBC_PREREQ(2, 1))
-    fprintf(fp, "                        Runtime: %s\n",
+    g = string_fmt_append(g, "                        Runtime: %s\n",
                gnu_get_libc_version());
 #endif
 
-show_db_version(fp);
+g = show_db_version(g);
 
 #ifndef DISABLE_TLS
-  tls_version_report(fp);
+  g = tls_version_report(g);
 #endif
 #ifdef SUPPORT_I18N
-  utf8_version_report(fp);
+  g = utf8_version_report(g);
 #endif
 #ifdef SUPPORT_DMARC
-  dmarc_version_report(fp);
+  g = dmarc_version_report(g);
 #endif
 #ifdef SUPPORT_SPF
-  spf_lib_version_report(fp);
+  g = spf_lib_version_report(g);
 #endif
 
-  for (auth_info * authi = auths_available; *authi->driver_name != '\0'; ++authi)
-    if (authi->version_report)
-      (*authi->version_report)(fp);
+show_string(is_stdout, g);
+g = NULL;
+
+for (auth_info * authi = auths_available; *authi->driver_name != '\0'; ++authi)
+  if (authi->version_report)
+    g = (*authi->version_report)(g);
 
   /* PCRE_PRERELEASE is either defined and empty or a bare sequence of
   characters; unless it's an ancient version of PCRE in which case it
@@ -1253,7 +1270,7 @@ show_db_version(fp);
   {
   uschar buf[24];
   pcre2_config(PCRE2_CONFIG_VERSION, buf);
-  fprintf(fp, "Library version: PCRE2: Compile: %d.%d%s\n"
+  g = string_fmt_append(g, "Library version: PCRE2: Compile: %d.%d%s\n"
               "                        Runtime: %s\n",
           PCRE2_MAJOR, PCRE2_MINOR,
           EXPAND_AND_QUOTE(PCRE2_PRERELEASE) "",
@@ -1262,23 +1279,29 @@ show_db_version(fp);
 #undef QUOTE
 #undef EXPAND_AND_QUOTE
 
-  init_lookup_list();
-  for (int i = 0; i < lookup_list_count; i++)
-    if (lookup_list[i]->version_report)
-      lookup_list[i]->version_report(fp);
+show_string(is_stdout, g);
+g = NULL;
+
+init_lookup_list();
+for (int i = 0; i < lookup_list_count; i++)
+  if (lookup_list[i]->version_report)
+    g = lookup_list[i]->version_report(g);
+show_string(is_stdout, g);
+g = NULL;
 
 #ifdef WHITELIST_D_MACROS
-  fprintf(fp, "WHITELIST_D_MACROS: \"%s\"\n", WHITELIST_D_MACROS);
+  g = string_fmt_append(g, "WHITELIST_D_MACROS: \"%s\"\n", WHITELIST_D_MACROS);
 #else
-  fprintf(fp, "WHITELIST_D_MACROS unset\n");
+  g = string_cat(g, US"WHITELIST_D_MACROS unset\n");
 #endif
 #ifdef TRUSTED_CONFIG_LIST
-  fprintf(fp, "TRUSTED_CONFIG_LIST: \"%s\"\n", TRUSTED_CONFIG_LIST);
+  g = string_fmt_append(g, "TRUSTED_CONFIG_LIST: \"%s\"\n", TRUSTED_CONFIG_LIST);
 #else
-  fprintf(fp, "TRUSTED_CONFIG_LIST unset\n");
+  g = string_cat(g, US"TRUSTED_CONFIG_LIST unset\n");
 #endif
+  }
 
-} while (0);
+show_string(is_stdout, g);
 store_reset(reset_point);
 }
 
@@ -1690,7 +1713,7 @@ int  i, rv;
 int  list_queue_option = 0;
 int  msg_action = 0;
 int  msg_action_arg = -1;
-int  namelen = (argv[0] == NULL)? 0 : Ustrlen(argv[0]);
+int  namelen = argv[0] ? Ustrlen(argv[0]) : 0;
 int  queue_only_reason = 0;
 #ifdef EXIM_PERL
 int  perl_start_option = 0;
@@ -1834,6 +1857,7 @@ if (f.running_in_test_harness)
   debug_store = TRUE;
 
 /* Protect against abusive argv[0] */
+if (!argv[0] || !argc) exim_fail("exim: executable name required\n");
 exim_str_fail_toolong(argv[0], PATH_MAX, "argv[0]");
 
 /* The C standard says that the equivalent of setlocale(LC_ALL, "C") is obeyed
@@ -2440,7 +2464,7 @@ on the second character (the one after '-'), to save some effort. */
              version_cnumber, version_date);
            printf("%s\n", CS version_copyright);
            version_printed = TRUE;
-           show_whats_supported(stdout);
+           show_whats_supported(TRUE);
            f.log_testing_mode = TRUE;
            }
          else badarg = TRUE;
@@ -2635,21 +2659,36 @@ on the second character (the one after '-'), to save some effort. */
     #endif
     break;
 
-    /* -d: Set debug level (see also -v below) or set the drop_cr option.
-    The latter is now a no-op, retained for compatibility only. If -dd is used,
-    debugging subprocesses of the daemon is disabled. */
-
     case 'd':
+
+    /* -dropcr: Set this option.  Now a no-op, retained for compatibility only. */
+
     if (Ustrcmp(argrest, "ropcr") == 0)
       {
       /* drop_cr = TRUE; */
       }
 
-    /* Use an intermediate variable so that we don't set debugging while
-    decoding the debugging bits. */
+    /* -dp: Set up a debug pretrigger buffer with given size. */
+
+    else if (Ustrcmp(argrest, "p") == 0)
+      if (++i >= argc)
+       badarg = TRUE;
+      else
+       debug_pretrigger_setup(argv[i]);
+
+    /* -dt: Set a debug trigger selector */
+
+    else if (Ustrncmp(argrest, "t=", 2) == 0)
+      dtrigger_selector = (unsigned int) Ustrtol(argrest + 2, NULL, 0);
+
+    /* -d: Set debug level (see also -v below).
+    If -dd is used, debugging subprocesses of the daemon is disabled. */
 
     else
       {
+      /* Use an intermediate variable so that we don't set debugging while
+      decoding the debugging bits. */
+
       unsigned int selector = D_default;
       debug_selector = 0;
       debug_file = NULL;
@@ -3753,7 +3792,7 @@ if (debug_selector != 0)
       version_string, (long int)real_uid, (long int)real_gid, (int)getpid(),
       debug_selector);
     if (!version_printed)
-      show_whats_supported(stderr);
+      show_whats_supported(FALSE);
     }
   }