SECURITY: length limits on many cmdline options
[exim.git] / src / src / exim.c
index 0b7b87ed58be01ead8750da9a0518d662b2dd2c7..112fa4f3d5f3856dc329977372c7424dc266e121 100644 (file)
@@ -53,7 +53,7 @@ return store_get((int)size, TRUE);
 }
 
 static void
-function_dummy_free(void *block) { block = block; }
+function_dummy_free(void * block) {}
 
 static void *
 function_store_malloc(size_t size)
@@ -62,7 +62,7 @@ return store_malloc((int)size);
 }
 
 static void
-function_store_free(void *block)
+function_store_free(void * block)
 {
 store_free(block);
 }
@@ -279,7 +279,6 @@ Returns:  nothing
 void
 sigalrm_handler(int sig)
 {
-sig = sig;      /* Keep picky compilers happy */
 sigalrm_seen = TRUE;
 os_non_restarting_signal(SIGALRM, sigalrm_handler);
 }
@@ -384,14 +383,20 @@ return 0;
 *************************************************/
 
 #ifdef _POSIX_MONOTONIC_CLOCK
-/* Amount CLOCK_MONOTONIC is behind realtime, at startup. */
+# ifdef CLOCK_BOOTTIME
+#  define EXIM_CLOCKTYPE CLOCK_BOOTTIME
+# else
+#  define EXIM_CLOCKTYPE CLOCK_MONOTONIC
+# endif
+
+/* Amount EXIM_CLOCK is behind realtime, at startup. */
 static struct timespec offset_ts;
 
 static void
 exim_clock_init(void)
 {
 struct timeval tv;
-if (clock_gettime(CLOCK_MONOTONIC, &offset_ts) != 0) return;
+if (clock_gettime(EXIM_CLOCKTYPE, &offset_ts) != 0) return;
 (void)gettimeofday(&tv, NULL);
 offset_ts.tv_sec = tv.tv_sec - offset_ts.tv_sec;
 offset_ts.tv_nsec = tv.tv_usec * 1000 - offset_ts.tv_nsec;
@@ -402,6 +407,29 @@ offset_ts.tv_nsec += 1000*1000*1000;
 #endif
 
 
+void
+exim_gettime(struct timeval * tv)
+{
+#ifdef _POSIX_MONOTONIC_CLOCK
+struct timespec now_ts;
+
+if (clock_gettime(EXIM_CLOCKTYPE, &now_ts) == 0)
+  {
+  now_ts.tv_sec += offset_ts.tv_sec;
+  if ((now_ts.tv_nsec += offset_ts.tv_nsec) >= 1000*1000*1000)
+    {
+    now_ts.tv_sec++;
+    now_ts.tv_nsec -= 1000*1000*1000;
+    }
+  tv->tv_sec = now_ts.tv_sec;
+  tv->tv_usec = now_ts.tv_nsec / 1000;
+  }
+else
+#endif
+  (void)gettimeofday(tv, NULL);
+}
+
+
 /* Exim uses a time + a pid to generate a unique identifier in two places: its
 message IDs, and in file names for maildir deliveries. Because some OS now
 re-use pids within the same second, sub-second times are now being used.
@@ -428,28 +456,9 @@ exim_wait_tick(struct timeval * tgt_tv, int resolution)
 struct timeval now_tv;
 long int now_true_usec;
 
-#ifdef _POSIX_MONOTONIC_CLOCK
-struct timespec now_ts;
-
-if (clock_gettime(CLOCK_MONOTONIC, &now_ts) == 0)
-  {
-  now_ts.tv_sec += offset_ts.tv_sec;
-  if ((now_ts.tv_nsec += offset_ts.tv_nsec) >= 1000*1000*1000)
-    {
-    now_ts.tv_sec++;
-    now_ts.tv_nsec -= 1000*1000*1000;
-    }
-  now_tv.tv_sec = now_ts.tv_sec;
-  now_true_usec = (now_ts.tv_nsec / (resolution * 1000)) * resolution;
-  now_tv.tv_usec = now_true_usec;
-  }
-else
-#endif
-  {
-  (void)gettimeofday(&now_tv, NULL);
-  now_true_usec = now_tv.tv_usec;
-  now_tv.tv_usec = (now_true_usec/resolution) * resolution;
-  }
+exim_gettime(&now_tv);
+now_true_usec = now_tv.tv_usec;
+now_tv.tv_usec = (now_true_usec/resolution) * resolution;
 
 while (exim_tvcmp(&now_tv, tgt_tv) <= 0)
   {
@@ -487,7 +496,7 @@ while (exim_tvcmp(&now_tv, tgt_tv) <= 0)
   /* Be prapared to go around if the kernel does not implement subtick
   granularity (GNU Hurd) */
 
-  (void)gettimeofday(&now_tv, NULL);
+  exim_gettime(&now_tv);
   now_true_usec = now_tv.tv_usec;
   now_tv.tv_usec = (now_true_usec/resolution) * resolution;
   }
@@ -555,7 +564,7 @@ for (int i = 0; i <= 2; i++)
     {
     if (devnull < 0) devnull = open("/dev/null", O_RDWR);
     if (devnull < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
-      string_open_failed(errno, "/dev/null", NULL));
+      string_open_failed("/dev/null", NULL));
     if (devnull != i) (void)dup2(devnull, i);
     }
   }
@@ -751,6 +760,25 @@ vfprintf(stderr, fmt, ap);
 exit(EXIT_FAILURE);
 }
 
+/* fail if a length is too long */
+static void
+exim_len_fail_toolong(int itemlen, int maxlen, const char *description)
+{
+if (itemlen <= maxlen)
+  return;
+fprintf(stderr, "exim: length limit exceeded (%d > %d) for: %s\n",
+        len, maxlen, description)
+exit(EXIT_FAILURE);
+}
+
+/* only pass through the string item back to the caller if it's short enough */
+static const uschar *
+exim_str_fail_toolong(const uschar *item, int maxlen, const char *description)
+{
+exim_len_fail_toolong(Ustrlen(item), maxlen, description);
+return item;
+}
+
 /* exim_chown_failure() called from exim_chown()/exim_fchown() on failure
 of chown()/fchown().  See src/functions.h for more explanation */
 int
@@ -1001,6 +1029,9 @@ g = string_cat(NULL, US"Support for:");
 #ifdef EXPERIMENTAL_DSN_INFO
   g = string_cat(g, US" Experimental_DSN_info");
 #endif
+#ifdef EXPERIMENTAL_ESMTP_LIMITS
+  g = string_cat(g, US" Experimental_ESMTP_Limits");
+#endif
 #ifdef EXPERIMENTAL_QUEUEFILE
   g = string_cat(g, US" Experimental_QUEUEFILE");
 #endif
@@ -1126,6 +1157,9 @@ show_db_version(fp);
 #ifdef SUPPORT_I18N
   utf8_version_report(fp);
 #endif
+#ifdef SUPPORT_DMARC
+  dmarc_version_report(fp);
+#endif
 #ifdef SUPPORT_SPF
   spf_lib_version_report(fp);
 #endif
@@ -1660,6 +1694,8 @@ extern char **environ;
 (void)gettimeofday(&timestamp_startup, NULL);
 #endif
 
+store_init();  /* Initialise the memory allocation susbsystem */
+
 /* If the Exim user and/or group and/or the configuration file owner/group were
 defined by ref:name at build time, we must now find the actual uid/gid values.
 This is a feature to make the lives of binary distributors easier. */
@@ -1729,7 +1765,7 @@ make quite sure. */
 
 setlocale(LC_ALL, "C");
 
-/* Get the offset between CLOCK_MONOTONIC and wallclock */
+/* Get the offset between CLOCK_MONOTONIC/CLOCK_BOOTTIME and wallclock */
 
 #ifdef _POSIX_MONOTONIC_CLOCK
 exim_clock_init();
@@ -2123,10 +2159,10 @@ on the second character (the one after '-'), to save some effort. */
            {
            if (++i >= argc)
              exim_fail("exim: string expected after %s\n", arg);
-           if (Ustrcmp(argrest, "d") == 0) ftest_domain = argv[i];
-           else if (Ustrcmp(argrest, "l") == 0) ftest_localpart = argv[i];
-           else if (Ustrcmp(argrest, "p") == 0) ftest_prefix = argv[i];
-           else if (Ustrcmp(argrest, "s") == 0) ftest_suffix = argv[i];
+           if (Ustrcmp(argrest, "d") == 0) ftest_domain = exim_str_fail_toolong(argv[i], EXIM_DOMAINNAME_MAX, "-bfd");
+           else if (Ustrcmp(argrest, "l") == 0) ftest_localpart = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfl");
+           else if (Ustrcmp(argrest, "p") == 0) ftest_prefix = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfp");
+           else if (Ustrcmp(argrest, "s") == 0) ftest_suffix = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfs");
            else badarg = TRUE;
            }
          break;
@@ -2136,7 +2172,7 @@ on the second character (the one after '-'), to save some effort. */
          if (!*argrest || Ustrcmp(argrest, "c") == 0)
            {
            if (++i >= argc) { badarg = TRUE; break; }
-           sender_host_address = string_copy_taint(argv[i], TRUE);
+           sender_host_address = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-bh"), TRUE);
            host_checking = checking = f.log_testing_mode = TRUE;
            f.host_checking_callout = *argrest == 'c';
            message_logs = FALSE;
@@ -2246,7 +2282,7 @@ on the second character (the one after '-'), to save some effort. */
        case 'P':
 
          /* -bP config: we need to setup here, because later,
-          * when list_options is checked, the config is read already */
+         when list_options is checked, the config is read already */
          if (*argrest)
            badarg = TRUE;
          else if (argv[i+1] && Ustrcmp(argv[i+1], "config") == 0)
@@ -2364,6 +2400,7 @@ on the second character (the one after '-'), to save some effort. */
       int len = Ustrlen(ALT_CONFIG_PREFIX);
       const uschar *list = argrest;
       uschar *filename;
+      /* The argv is untainted, so big_buffer (also untainted) is ok to use */
       while((filename = string_nextinlist(&list, &sep, big_buffer,
              big_buffer_size)))
         if (  (  Ustrlen(filename) < len
@@ -2593,7 +2630,7 @@ on the second character (the one after '-'), to save some effort. */
     case 'F':
     if (!*argrest)
       if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; }
-    originator_name = string_copy_taint(argrest, TRUE);
+    originator_name = string_copy_taint(exim_str_fail_toolong(argrest, EXIM_HUMANNAME_MAX, "-F"), TRUE);
     f.sender_name_forced = TRUE;
     break;
 
@@ -2619,6 +2656,7 @@ on the second character (the one after '-'), to save some effort. */
       uschar *errmess;
       if (!*argrest)
         if (i+1 < argc) argrest = argv[++i]; else { badarg = TRUE; break; }
+      (void) exim_str_fail_toolong(argrest, EXIM_DISPLAYMAIL_MAX, "-f");
       if (!*argrest)
         *(sender_address = store_get(1, FALSE)) = '\0';  /* Ensure writeable memory */
       else
@@ -2715,9 +2753,9 @@ on the second character (the one after '-'), to save some effort. */
       if (msg_action_arg >= 0)
         exim_fail("exim: incompatible arguments\n");
 
-      continue_transport = string_copy_taint(argv[++i], TRUE);
-      continue_hostname = string_copy_taint(argv[++i], TRUE);
-      continue_host_address = string_copy_taint(argv[++i], TRUE);
+      continue_transport = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-C internal transport"), TRUE);
+      continue_hostname = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-C internal hostname"), TRUE);
+      continue_host_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-C internal hostaddr"), TRUE);
       continue_sequence = Uatoi(argv[++i]);
       msg_action = MSG_DELIVER;
       msg_action_arg = ++i;
@@ -2762,13 +2800,15 @@ on the second character (the one after '-'), to save some effort. */
     /* -MCd: for debug, set a process-purpose string */
 
        case 'd': if (++i < argc)
-                   process_purpose = string_copy_taint(argv[i], TRUE);
+                   process_purpose = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCd"), TRUE);
                  else badarg = TRUE;
                  break;
 
-    /* -MCG: set the queue name, to a non-default value */
+    /* -MCG: set the queue name, to a non-default value. Arguably, anything
+       from the commandline should be tainted - but we will need an untainted
+       value for the spoolfile when doing a -odi delivery process. */
 
-       case 'G': if (++i < argc) queue_name = string_copy_taint(argv[i], TRUE);
+       case 'G': if (++i < argc) queue_name = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCG"), FALSE);
                  else badarg = TRUE;
                  break;
 
@@ -2776,11 +2816,42 @@ on the second character (the one after '-'), to save some effort. */
 
        case 'K': smtp_peer_options |= OPTION_CHUNKING; break;
 
+#ifdef EXPERIMENTAL_ESMTP_LIMITS
+    /* -MCL: peer used LIMITS RCPTMAX and/or RCPTDOMAINMAX */
+       case 'L': if (++i < argc) continue_limit_mail = Uatoi(argv[i]);
+                 else badarg = TRUE;
+                 if (++i < argc) continue_limit_rcpt = Uatoi(argv[i]);
+                 else badarg = TRUE;
+                 if (++i < argc) continue_limit_rcptdom = Uatoi(argv[i]);
+                 else badarg = TRUE;
+                 break;
+#endif
+
     /* -MCP: set the smtp_use_pipelining flag; this is useful only when
     it preceded -MC (see above) */
 
        case 'P': smtp_peer_options |= OPTION_PIPE; break;
 
+#ifdef SUPPORT_SOCKS
+    /* -MCp: Socks proxy in use; nearside IP, port, external IP, port */
+       case 'p': proxy_session = TRUE;
+                 if (++i < argc)
+                   {
+                   proxy_local_address = string_copy_taint(argv[i], TRUE);
+                   if (++i < argc)
+                     {
+                     proxy_local_port = Uatoi(argv[i]);
+                     if (++i < argc)
+                       {
+                       proxy_external_address = string_copy_taint(argv[i], TRUE);
+                       if (++i < argc)
+                         {
+                         proxy_external_port = Uatoi(argv[i]);
+                         break;
+                   } } } }
+                 badarg = TRUE;
+                 break;
+#endif
     /* -MCQ: pass on the pid of the queue-running process that started
     this chain of deliveries and the fd of its synchronizing pipe; this
     is useful only when it precedes -MC (see above) */
@@ -2804,19 +2875,31 @@ on the second character (the one after '-'), to save some effort. */
        case 'S': smtp_peer_options |= OPTION_SIZE; break;
 
 #ifndef DISABLE_TLS
+    /* -MCs: used with -MCt; SNI was sent */
+    /* -MCr: ditto, DANE */
+
+       case 'r':
+       case 's': if (++i < argc)
+                   {
+                   continue_proxy_sni = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_HOSTNAME_MAX, "-MCr/-MCs"), TRUE);
+                   if (argrest[1] == 'r') continue_proxy_dane = TRUE;
+                   }
+                 else badarg = TRUE;
+                 break;
+
     /* -MCt: similar to -MCT below but the connection is still open
     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.  */
+    and the TLS cipher. */
 
        case 't': if (++i < argc)
-                   sending_ip_address = string_copy_taint(argv[i], TRUE);
+                   sending_ip_address = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-MCt IP"), TRUE);
                  else badarg = TRUE;
                  if (++i < argc)
                    sending_port = (int)(Uatol(argv[i]));
                  else badarg = TRUE;
                  if (++i < argc)
-                   continue_proxy_cipher = string_copy_taint(argv[i], TRUE);
+                   continue_proxy_cipher = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_CIPHERNAME_MAX, "-MCt cipher"), TRUE);
                  else badarg = TRUE;
                  /*FALLTHROUGH*/
 
@@ -2843,6 +2926,7 @@ on the second character (the one after '-'), to save some effort. */
     following options which are followed by a single message id, and which
     act on that message. Some of them use the "recipient" addresses as well.
        -Mar  add recipient(s)
+       -MG   move to a different queue
        -Mmad mark all recipients delivered
        -Mmd  mark recipients(s) delivered
        -Mes  edit sender
@@ -2878,7 +2962,7 @@ on the second character (the one after '-'), to save some effort. */
    else if (Ustrcmp(argrest, "G") == 0)
       {
       msg_action = MSG_SETQUEUE;
-      queue_name_dest = string_copy_taint(argv[++i], TRUE);
+      queue_name_dest = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-MG"), TRUE);
       }
     else if (Ustrcmp(argrest, "mad") == 0)
       {
@@ -3091,27 +3175,27 @@ on the second character (the one after '-'), to save some effort. */
        /* -oMa: Set sender host address */
 
        if (Ustrcmp(argrest, "a") == 0)
-         sender_host_address = string_copy_taint(argv[++i], TRUE);
+         sender_host_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMa"), TRUE);
 
        /* -oMaa: Set authenticator name */
 
        else if (Ustrcmp(argrest, "aa") == 0)
-         sender_host_authenticated = string_copy_taint(argv[++i], TRUE);
+         sender_host_authenticated = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMaa"), TRUE);
 
        /* -oMas: setting authenticated sender */
 
        else if (Ustrcmp(argrest, "as") == 0)
-         authenticated_sender = string_copy_taint(argv[++i], TRUE);
+         authenticated_sender = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"), TRUE);
 
        /* -oMai: setting authenticated id */
 
        else if (Ustrcmp(argrest, "ai") == 0)
-         authenticated_id = string_copy_taint(argv[++i], TRUE);
+         authenticated_id = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"), TRUE);
 
        /* -oMi: Set incoming interface address */
 
        else if (Ustrcmp(argrest, "i") == 0)
-         interface_address = string_copy_taint(argv[++i], TRUE);
+         interface_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMi"), TRUE);
 
        /* -oMm: Message reference */
 
@@ -3131,19 +3215,19 @@ on the second character (the one after '-'), to save some effort. */
          if (received_protocol)
            exim_fail("received_protocol is set already\n");
          else
-           received_protocol = string_copy_taint(argv[++i], TRUE);
+           received_protocol = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMr"), TRUE);
 
        /* -oMs: Set sender host name */
 
        else if (Ustrcmp(argrest, "s") == 0)
-         sender_host_name = string_copy_taint(argv[++i], TRUE);
+         sender_host_name = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-oMs"), TRUE);
 
        /* -oMt: Set sender ident */
 
        else if (Ustrcmp(argrest, "t") == 0)
          {
          sender_ident_set = TRUE;
-         sender_ident = string_copy_taint(argv[++i], TRUE);
+         sender_ident = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IDENTUSER_MAX, "-oMt"), TRUE);
          }
 
        /* Else a bad argument */
@@ -3193,10 +3277,18 @@ on the second character (the one after '-'), to save some effort. */
        break;
 
       /* -oX <list>: Override local_interfaces and/or default daemon ports */
+      /* Limits: Is there a real limit we want here?  1024 is very arbitrary. */
 
       case 'X':
        if (*argrest) badarg = TRUE;
-       else override_local_interfaces = string_copy_taint(argv[++i], TRUE);
+       else override_local_interfaces = string_copy_taint(exim_str_fail_toolong(argv[++i], 1024, "-oX", TRUE);
+       break;
+
+      /* -oY: Override creation of daemon notifier socket */
+
+      case 'Y':
+       if (*argrest) badarg = TRUE;
+       else notifier_socket = NULL;
        break;
 
       /* Unknown -o argument */
@@ -3237,9 +3329,10 @@ on the second character (the one after '-'), to save some effort. */
         exim_fail("received_protocol is set already\n");
 
       if (!hn)
-        received_protocol = string_copy_taint(argrest, TRUE);
+        received_protocol = string_copy_taint(exim_str_fail_toolong(argrest, EXIM_DRIVERNAME_MAX, "-p<protocol>"), TRUE);
       else
         {
+        (void) exim_str_fail_toolong(argrest, (EXIM_DRIVERNAME_MAX+1+EXIM_HOSTNAME_MAX), "-p<protocol>:<host>");
         received_protocol = string_copyn_taint(argrest, hn - argrest, TRUE);
         sender_host_name = string_copy_taint(hn + 1, TRUE);
         }
@@ -3295,6 +3388,7 @@ on the second character (the one after '-'), to save some effort. */
       {
       int i;
       for (argrest++, i = 0; argrest[i] && argrest[i] != '/'; ) i++;
+      exim_len_fail_toolong(i, EXIM_DRIVERNAME_MAX, "-q*G<name>");
       queue_name = string_copyn(argrest, i);
       argrest += i;
       if (*argrest == '/') argrest++;
@@ -3348,15 +3442,18 @@ on the second character (the one after '-'), to save some effort. */
     /* -R: Set string to match in addresses for forced queue run to
     pick out particular messages. */
 
+    /* Avoid attacks from people providing very long strings, and do so before
+    we make copies. */
+    const char *tainted_selectstr;
     if (*argrest)
-      deliver_selectstring = string_copy_taint(argrest, TRUE);
+      tainted_selectstr = argrest;
     else if (i+1 < argc)
-      deliver_selectstring = string_copy_taint(argv[++i], TRUE);
+      tainted_selectstr = argv[++i];
     else
       exim_fail("exim: string expected after -R\n");
+    deliver_selectstring = string_copy_taint(exim_str_fail_toolong(tainted_selectstr, EXIM_EMAILADDR_MAX, "-R"), TRUE);
     break;
 
-
     /* -r: an obsolete synonym for -f (see above) */
 
 
@@ -3387,12 +3484,14 @@ on the second character (the one after '-'), to save some effort. */
     /* -S: Set string to match in addresses for forced queue run to
     pick out particular messages. */
 
+    const char *tainted_selectstr;
     if (*argrest)
-      deliver_selectstring_sender = string_copy_taint(argrest, TRUE);
+      tainted_selectstr = argrest;
     else if (i+1 < argc)
-      deliver_selectstring_sender = string_copy_taint(argv[++i], TRUE);
+      tainted_selectstr = argv[++i];
     else
       exim_fail("exim: string expected after -S\n");
+    deliver_selectstring_sender = string_copy_taint(exim_str_fail_toolong(tainted_selectstr, EXIM_EMAILADDR_MAX, "-S"), TRUE);
     break;
 
     /* -Tqt is an option that is exclusively for use by the testing suite.
@@ -3474,10 +3573,12 @@ on the second character (the one after '-'), to save some effort. */
         exim_fail("exim: string expected after -X\n");
     break;
 
+    /* -z: a line of text to log */
+
     case 'z':
     if (!*argrest)
       if (++i < argc)
-       log_oneline = string_copy_taint(argv[i], TRUE);
+       log_oneline = string_copy_taint(exim_str_fail_toolong(argv[i], 2048, "-z logtext"), TRUE);
       else
         exim_fail("exim: file name expected after %s\n", argv[i-1]);
     break;
@@ -4102,10 +4203,8 @@ privilege by now. Before the chdir, we try to ensure that the directory exists.
 
 if (Uchdir(spool_directory) != 0)
   {
-  int dummy;
-  (void)directory_make(spool_directory, US"", SPOOL_DIRECTORY_MODE, FALSE);
-  dummy = /* quieten compiler */ Uchdir(spool_directory);
-  dummy = dummy;       /* yet more compiler quietening, sigh */
+  (void) directory_make(spool_directory, US"", SPOOL_DIRECTORY_MODE, FALSE);
+  (void) Uchdir(spool_directory);
   }
 
 /* Handle calls with the -bi option. This is a sendmail option to rebuild *the*
@@ -4116,7 +4215,7 @@ script. */
 
 if (bi_option)
   {
-  (void)fclose(config_file);
+  (void) fclose(config_file);
   if (bi_command && *bi_command)
     {
     int i = 0;
@@ -4751,16 +4850,16 @@ for (i = 0;;)
 configuration specifies something to use. When running in the test harness,
 any setting of unknown_login overrides the actual name. */
 
-if (originator_login == NULL || f.running_in_test_harness)
+if (!originator_login || f.running_in_test_harness)
   {
-  if (unknown_login != NULL)
+  if (unknown_login)
     {
     originator_login = expand_string(unknown_login);
-    if (originator_name == NULL && unknown_username != NULL)
+    if (!originator_name && unknown_username)
       originator_name = expand_string(unknown_username);
-    if (originator_name == NULL) originator_name = US"";
+    if (!originator_name) originator_name = US"";
     }
-  if (originator_login == NULL)
+  if (!originator_login)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Failed to get user name for uid %d",
       (int)real_uid);
   }
@@ -4768,8 +4867,7 @@ if (originator_login == NULL || f.running_in_test_harness)
 /* Ensure that the user name is in a suitable form for use as a "phrase" in an
 RFC822 address.*/
 
-originator_name = string_copy(parse_fix_phrase(originator_name,
-  Ustrlen(originator_name), big_buffer, big_buffer_size));
+originator_name = US parse_fix_phrase(originator_name, Ustrlen(originator_name));
 
 /* If a message is created by this call of Exim, the uid/gid of its originator
 are those of the caller. These values are overridden if an existing message is