global queue_name
[exim.git] / src / src / queue.c
index f411f3629c833f90a2f63cd32a514fd54a76ddc1..c971790927475b39f17e2e647c5fbd33a8fed721 100644 (file)
@@ -1,10 +1,8 @@
-/* $Cambridge: exim/src/src/queue.c,v 1.7 2005/06/16 14:10:13 ph10 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions that operate on the input queue. */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions that operate on the input queue. */
@@ -144,7 +142,8 @@ else i = subdiroffset;
 
 /* Set up prototype for the directory name. */
 
 
 /* Set up prototype for the directory name. */
 
-sprintf(CS buffer, "%s/input", spool_directory);
+snprintf(CS buffer, sizeof(buffer), "%s/input/%s", spool_directory, queue_name);
+buffer[sizeof(buffer) - 3] = 0;
 subptr = Ustrlen(buffer);
 buffer[subptr+2] = 0;               /* terminator for lengthened name */
 
 subptr = Ustrlen(buffer);
 buffer[subptr+2] = 0;               /* terminator for lengthened name */
 
@@ -163,8 +162,8 @@ for (; i <= *subcount; i++)
     buffer[subptr+1] = subdirchar;
     }
 
     buffer[subptr+1] = subdirchar;
     }
 
-  dd = opendir(CS buffer);
-  if (dd == NULL) continue;
+  if (!(dd = opendir(CS buffer)))
+    continue;
 
   /* Now scan the directory. */
 
 
   /* Now scan the directory. */
 
@@ -267,7 +266,8 @@ for (; i <= *subcount; i++)
     if (!split_spool_directory && count <= 2)
       {
       rmdir(CS buffer);
     if (!split_spool_directory && count <= 2)
       {
       rmdir(CS buffer);
-      sprintf(CS big_buffer, "%s/msglog/%c", spool_directory, subdirchar);
+      sprintf(CS big_buffer, "%s/msglog/%s/%c",
+               spool_directory, queue_name, subdirchar);
       rmdir(CS big_buffer);
       }
     if (subdiroffset > 0) break;    /* Single sub-directory */
       rmdir(CS big_buffer);
       }
     if (subdiroffset > 0) break;    /* Single sub-directory */
@@ -453,7 +453,8 @@ for (i  = (queue_run_in_order? -1 : 0);
       load_average = os_getloadavg();
       if (load_average > deliver_queue_load_max)
         {
       load_average = os_getloadavg();
       if (load_average > deliver_queue_load_max)
         {
-        log_write(0, LOG_MAIN, "abandon queue run (load %.2f, max %.2f)",
+        log_write(L_queue_run, LOG_MAIN, "Abandon queue run: %s (load %.2f, max %.2f)",
+          log_detail,
           (double)load_average/1000.0,
           (double)deliver_queue_load_max/1000.0);
         i = subcount;                 /* Don't process other directories */
           (double)load_average/1000.0,
           (double)deliver_queue_load_max/1000.0);
         i = subcount;                 /* Don't process other directories */
@@ -477,8 +478,8 @@ for (i  = (queue_run_in_order? -1 : 0);
     /* Check that the message still exists */
 
     message_subdir[0] = f->dir_uschar;
     /* Check that the message still exists */
 
     message_subdir[0] = f->dir_uschar;
-    sprintf(CS buffer, "%s/input/%s/%s", spool_directory, message_subdir,
-      f->text);
+    snprintf(CS buffer, sizeof(buffer), "%s/input/%s/%s/%s",
+      spool_directory, queue_name, message_subdir, f->text);
     if (Ustat(buffer, &statbuf) < 0) continue;
 
     /* There are some tests that require the reading of the header file. Ensure
     if (Ustat(buffer, &statbuf) < 0) continue;
 
     /* There are some tests that require the reading of the header file. Ensure
@@ -594,7 +595,7 @@ for (i  = (queue_run_in_order? -1 : 0);
     if (queue_run_pipe == 0)
       {
       queue_run_pipe = dup(queue_run_pipe);
     if (queue_run_pipe == 0)
       {
       queue_run_pipe = dup(queue_run_pipe);
-      close(0);
+      (void)close(0);
       }
 
     /* Before forking to deliver the message, ensure any open and cached
       }
 
     /* Before forking to deliver the message, ensure any open and cached
@@ -627,7 +628,7 @@ for (i  = (queue_run_in_order? -1 : 0);
     /* Close the writing end of the synchronizing pipe in this process,
     then wait for the first level process to terminate. */
 
     /* Close the writing end of the synchronizing pipe in this process,
     then wait for the first level process to terminate. */
 
-    close(pfd[pipe_write]);
+    (void)close(pfd[pipe_write]);
     set_process_info("running queue: waiting for %s (%d)", f->text, pid);
     while (wait(&status) != pid);
 
     set_process_info("running queue: waiting for %s (%d)", f->text, pid);
     while (wait(&status) != pid);
 
@@ -651,7 +652,8 @@ for (i  = (queue_run_in_order? -1 : 0);
     the mere fact that read() unblocks is enough. */
 
     set_process_info("running queue: waiting for children of %d", pid);
     the mere fact that read() unblocks is enough. */
 
     set_process_info("running queue: waiting for children of %d", pid);
-    (void)read(pfd[pipe_read], buffer, sizeof(buffer));
+    if (read(pfd[pipe_read], buffer, sizeof(buffer)) > 0)
+      log_write(0, LOG_MAIN|LOG_PANIC, "queue run: unexpected data on pipe");
     (void)close(pfd[pipe_read]);
     set_process_info("running queue");
 
     (void)close(pfd[pipe_read]);
     set_process_info("running queue");
 
@@ -842,8 +844,8 @@ for (; f != NULL; f = f->next)
     FILE *jread;
     struct stat statbuf;
 
     FILE *jread;
     struct stat statbuf;
 
-    sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir,
-      f->text);
+    sprintf(CS big_buffer, "%s/input/%s/%s/%s",
+      spool_directory, queue_name, message_subdir, f->text);
     ptr = Ustrlen(big_buffer)-1;
     big_buffer[ptr] = 'D';
 
     ptr = Ustrlen(big_buffer)-1;
     big_buffer[ptr] = 'D';
 
@@ -873,7 +875,7 @@ for (; f != NULL; f = f->next)
         big_buffer[n-1] = 0;
         tree_add_nonrecipient(big_buffer);
         }
         big_buffer[n-1] = 0;
         tree_add_nonrecipient(big_buffer);
         }
-      fclose(jread);
+      (void)fclose(jread);
       }
     }
 
       }
     }
 
@@ -892,8 +894,8 @@ for (; f != NULL; f = f->next)
     if (save_errno == ERRNO_SPOOLFORMAT)
       {
       struct stat statbuf;
     if (save_errno == ERRNO_SPOOLFORMAT)
       {
       struct stat statbuf;
-      sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir,
-        f->text);
+      sprintf(CS big_buffer, "%s/input/%s/%s/%s",
+        spool_directory, queue_name, message_subdir, f->text);
       if (Ustat(big_buffer, &statbuf) == 0)
         printf("*** spool format error: size=" OFF_T_FMT " ***",
           statbuf.st_size);
       if (Ustat(big_buffer, &statbuf) == 0)
         printf("*** spool format error: size=" OFF_T_FMT " ***",
           statbuf.st_size);
@@ -935,9 +937,9 @@ for (; f != NULL; f = f->next)
 *             Act on a specific message          *
 *************************************************/
 
 *             Act on a specific message          *
 *************************************************/
 
-/* Actions that require a list of addresses make use of
-argv/argc/recipients_arg. Other actions do not. This function does its
-own authority checking.
+/* Actions that require a list of addresses make use of argv/argc/
+recipients_arg. Other actions do not. This function does its own
+authority checking.
 
 Arguments:
   id              id of the message to work on
 
 Arguments:
   id              id of the message to work on
@@ -1004,12 +1006,15 @@ if (action >= MSG_SHOW_BODY)
 
   for (i = 0; i < 2; i++)
     {
 
   for (i = 0; i < 2; i++)
     {
-    message_subdir[0] = (split_spool_directory == (i == 0))? id[5] : 0;
-    sprintf(CS spoolname, "%s/%s/%s/%s%s", spool_directory, subdirectory,
-      message_subdir, id, suffix);
-    fd = Uopen(spoolname, O_RDONLY, 0);
-    if (fd >= 0) break;
-    if (i == 0) continue;
+    message_subdir[0] = split_spool_directory == (i == 0) ? id[5] : 0;
+    snprintf(CS spoolname, sizeof(spoolname), "%s/%s/%s/%s/%s%s",
+             spool_directory, subdirectory, queue_name,
+             message_subdir, id, suffix);
+    if ((fd = Uopen(spoolname, O_RDONLY, 0)) >= 0)
+      break;
+    if (i == 0)
+      continue;
+
     printf("Failed to open %s file for %s%s: %s\n", subdirectory, id, suffix,
       strerror(errno));
     if (action == MSG_SHOW_LOG && !message_logs)
     printf("Failed to open %s file for %s%s: %s\n", subdirectory, id, suffix,
       strerror(errno));
     if (action == MSG_SHOW_LOG && !message_logs)
@@ -1019,9 +1024,9 @@ if (action >= MSG_SHOW_BODY)
     }
 
   while((rc = read(fd, big_buffer, big_buffer_size)) > 0)
     }
 
   while((rc = read(fd, big_buffer, big_buffer_size)) > 0)
-    write(fileno(stdout), big_buffer, rc);
+    rc = write(fileno(stdout), big_buffer, rc);
 
 
-  close(fd);
+  (void)close(fd);
   return TRUE;
   }
 
   return TRUE;
   }
 
@@ -1030,7 +1035,7 @@ other process is working on this message. If the file does not exist, continue
 only if the action is remove and the user is an admin user, to allow for
 tidying up broken states. */
 
 only if the action is remove and the user is an admin user, to allow for
 tidying up broken states. */
 
-if (!spool_open_datafile(id))
+if ((deliver_datafile = spool_open_datafile(id)) < 0)
   {
   if (errno == ENOENT)
     {
   {
   if (errno == ENOENT)
     {
@@ -1064,7 +1069,7 @@ if (spool_read_header(spoolname, TRUE, FALSE) != spool_read_OK)
     printf("Spool format error for %s\n", spoolname);
   if (action != MSG_REMOVE || !admin_user)
     {
     printf("Spool format error for %s\n", spoolname);
   if (action != MSG_REMOVE || !admin_user)
     {
-    close(deliver_datafile);
+    (void)close(deliver_datafile);
     deliver_datafile = -1;
     return FALSE;
     }
     deliver_datafile = -1;
     return FALSE;
     }
@@ -1079,7 +1084,7 @@ why we leave this check until after the headers are read. */
 if (!admin_user && (action != MSG_REMOVE || real_uid != originator_uid))
   {
   printf("Permission denied\n");
 if (!admin_user && (action != MSG_REMOVE || real_uid != originator_uid))
   {
   printf("Permission denied\n");
-  close(deliver_datafile);
+  (void)close(deliver_datafile);
   deliver_datafile = -1;
   return FALSE;
   }
   deliver_datafile = -1;
   return FALSE;
   }
@@ -1092,10 +1097,17 @@ username = (pw != NULL)?
 
 /* Take the necessary action. */
 
 
 /* Take the necessary action. */
 
-printf("Message %s ", id);
+if (action != MSG_SHOW_COPY) printf("Message %s ", id);
 
 switch(action)
   {
 
 switch(action)
   {
+  case MSG_SHOW_COPY:
+  deliver_in_buffer = store_malloc(DELIVER_IN_BUFFER_SIZE);
+  deliver_out_buffer = store_malloc(DELIVER_OUT_BUFFER_SIZE);
+  transport_write_message(NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, 0);
+  break;
+
+
   case MSG_FREEZE:
   if (deliver_freeze)
     {
   case MSG_FREEZE:
   if (deliver_freeze)
     {
@@ -1155,7 +1167,8 @@ switch(action)
   message_subdir[0] = id[5];
   for (j = 0; j < 2; message_subdir[0] = 0, j++)
     {
   message_subdir[0] = id[5];
   for (j = 0; j < 2; message_subdir[0] = 0, j++)
     {
-    sprintf(CS spoolname, "%s/msglog/%s/%s", spool_directory, message_subdir, id);
+    snprintf(CS spoolname, sizeof(spoolname), "%s/msglog/%s/%s/%s",
+      spool_directory, queue_name, message_subdir, id);
     if (Uunlink(spoolname) < 0)
       {
       if (errno != ENOENT)
     if (Uunlink(spoolname) < 0)
       {
       if (errno != ENOENT)
@@ -1169,8 +1182,8 @@ switch(action)
 
     for (i = 0; i < 3; i++)
       {
 
     for (i = 0; i < 3; i++)
       {
-      sprintf(CS spoolname, "%s/input/%s/%s-%c", spool_directory, message_subdir,
-        id, "DHJ"[i]);
+      snprintf(CS spoolname, sizeof(spoolname), "%s/input/%s/%s/%s-%c",
+        spool_directory, queue_name, message_subdir, id, "DHJ"[i]);
       if (Uunlink(spoolname) < 0)
         {
         if (errno != ENOENT)
       if (Uunlink(spoolname) < 0)
         {
         if (errno != ENOENT)
@@ -1267,6 +1280,9 @@ switch(action)
       {
       if (action == MSG_ADD_RECIPIENT)
         {
       {
       if (action == MSG_ADD_RECIPIENT)
         {
+#ifdef SUPPORT_I18N
+       if (string_is_utf8(recipient)) allow_utf8_domains = message_smtputf8 = TRUE;
+#endif
         receive_add_recipient(recipient, -1);
         log_write(0, LOG_MAIN, "recipient <%s> added by %s",
           recipient, username);
         receive_add_recipient(recipient, -1);
         log_write(0, LOG_MAIN, "recipient <%s> added by %s",
           recipient, username);
@@ -1290,6 +1306,9 @@ switch(action)
         }
       else  /* MSG_EDIT_SENDER */
         {
         }
       else  /* MSG_EDIT_SENDER */
         {
+#ifdef SUPPORT_I18N
+       if (string_is_utf8(recipient)) allow_utf8_domains = message_smtputf8 = TRUE;
+#endif
         sender_address = recipient;
         log_write(0, LOG_MAIN, "sender address changed to <%s> by %s",
           recipient, username);
         sender_address = recipient;
         log_write(0, LOG_MAIN, "sender address changed to <%s> by %s",
           recipient, username);
@@ -1314,7 +1333,7 @@ switch(action)
 /* Closing the datafile releases the lock and permits other processes
 to operate on the message (if it still exists). */
 
 /* Closing the datafile releases the lock and permits other processes
 to operate on the message (if it still exists). */
 
-close(deliver_datafile);
+(void)close(deliver_datafile);
 deliver_datafile = -1;
 return yield;
 }
 deliver_datafile = -1;
 return yield;
 }
@@ -1338,7 +1357,8 @@ queue_check_only(void)
 BOOL *set;
 int sep = 0;
 struct stat statbuf;
 BOOL *set;
 int sep = 0;
 struct stat statbuf;
-uschar *s, *ss, *name;
+const uschar *s;
+uschar *ss, *name;
 uschar buffer[1024];
 
 if (queue_only_file == NULL) return;
 uschar buffer[1024];
 
 if (queue_only_file == NULL) return;