tidying
[exim.git] / src / src / queue.c
index b6dff11070a63da6cfc93eb19e6b2fa1035bf925..7648f47ca4b2bc223bc3f482072341ce22956e1f 100644 (file)
 
 
 
+/* Routines with knowlege of spool layout */
+
+static void
+spool_pname_buf(uschar * buf, int len)
+{
+snprintf(CS buf, len, "%s/%s/input", spool_directory, queue_name);
+}
+
+static uschar *
+spool_dname(const uschar * purpose, uschar * subdir)
+{
+return string_sprintf("%s/%s/%s/%s",
+       spool_directory, queue_name, purpose, subdir);
+}
+
+uschar *
+spool_sname(const uschar * purpose, uschar * subdir)
+{
+return string_sprintf("%s%s%s%s%s",
+                   queue_name, *queue_name ? "/" : "",
+                   purpose,
+                   *subdir ? "/" : "", subdir);
+}
+
+uschar *
+spool_fname(const uschar * purpose, uschar * subdir, uschar * fname, uschar * suffix)
+{
+return string_sprintf("%s/%s/%s/%s/%s%s",
+       spool_directory, queue_name, purpose, subdir, fname, suffix);
+}
+
+
+
+
+#ifndef COMPILE_UTILITY
+
 /* The number of nodes to use for the bottom-up merge sort when a list of queue
 items is to be ordered. The code for this sort was contributed as a patch by
 Michael Haardt. */
@@ -142,7 +178,7 @@ else i = subdiroffset;
 
 /* Set up prototype for the directory name. */
 
-snprintf(CS buffer, sizeof(buffer), "%s/input/%s", spool_directory, queue_name);
+spool_pname_buf(buffer, sizeof(buffer));
 buffer[sizeof(buffer) - 3] = 0;
 subptr = Ustrlen(buffer);
 buffer[subptr+2] = 0;               /* terminator for lengthened name */
@@ -162,6 +198,7 @@ for (; i <= *subcount; i++)
     buffer[subptr+1] = subdirchar;
     }
 
+  DEBUG(D_queue_run) debug_printf("looking in %s\n", buffer);
   if (!(dd = opendir(CS buffer)))
     continue;
 
@@ -265,10 +302,11 @@ for (; i <= *subcount; i++)
     {
     if (!split_spool_directory && count <= 2)
       {
+      uschar subdir[2];
+
       rmdir(CS buffer);
-      sprintf(CS big_buffer, "%s/msglog/%s/%c",
-               spool_directory, queue_name, subdirchar);
-      rmdir(CS big_buffer);
+      subdir[0] = subdirchar; subdir[1] = 0;
+      rmdir(CS spool_dname(US"msglog", subdir));
       }
     if (subdiroffset > 0) break;    /* Single sub-directory */
     }
@@ -482,9 +520,8 @@ for (i  = (queue_run_in_order? -1 : 0);
     /* Check that the message still exists */
 
     message_subdir[0] = f->dir_uschar;
-    snprintf(CS buffer, sizeof(buffer), "%s/input/%s/%s/%s",
-      spool_directory, queue_name, message_subdir, f->text);
-    if (Ustat(buffer, &statbuf) < 0) continue;
+    if (Ustat(spool_fname(US"input", message_subdir, f->text, US""), &statbuf) < 0)
+      continue;
 
     /* There are some tests that require the reading of the header file. Ensure
     the store used is scavenged afterwards so that this process doesn't keep
@@ -852,17 +889,16 @@ for (; f != NULL; f = f->next)
     int ptr;
     FILE *jread;
     struct stat statbuf;
+    uschar * fname = spool_fname(US"input", message_subdir, f->text, US"");
 
-    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(fname)-1;
+    fname[ptr] = 'D';
 
     /* Add the data size to the header size; don't count the file name
     at the start of the data file, but add one for the notional blank line
     that precedes the data. */
 
-    if (Ustat(big_buffer, &statbuf) == 0)
+    if (Ustat(fname, &statbuf) == 0)
       size = message_size + statbuf.st_size - SPOOL_DATA_START_OFFSET + 1;
     i = (now - received_time)/60;  /* minutes on queue */
     if (i > 90)
@@ -874,8 +910,8 @@ for (; f != NULL; f = f->next)
 
     /* Collect delivered addresses from any J file */
 
-    big_buffer[ptr] = 'J';
-    jread = Ufopen(big_buffer, "rb");
+    fname[ptr] = 'J';
+    jread = Ufopen(fname, "rb");
     if (jread != NULL)
       {
       while (Ufgets(big_buffer, big_buffer_size, jread) != NULL)
@@ -903,9 +939,9 @@ for (; f != NULL; f = f->next)
     if (save_errno == ERRNO_SPOOLFORMAT)
       {
       struct stat statbuf;
-      sprintf(CS big_buffer, "%s/input/%s/%s/%s",
-        spool_directory, queue_name, message_subdir, f->text);
-      if (Ustat(big_buffer, &statbuf) == 0)
+      uschar * fname = spool_fname(US"input", message_subdir, f->text, US"");
+
+      if (Ustat(fname, &statbuf) == 0)
         printf("*** spool format error: size=" OFF_T_FMT " ***",
           statbuf.st_size);
       else printf("*** spool format error ***");
@@ -970,7 +1006,7 @@ struct passwd *pw;
 uschar *doing = NULL;
 uschar *username;
 uschar *errmsg;
-uschar spoolname[256];
+uschar spoolname[32];
 
 /* Set the global message_id variable, used when re-writing spool files. This
 also causes message ids to be added to log messages. */
@@ -1016,10 +1052,8 @@ if (action >= MSG_SHOW_BODY)
   for (i = 0; i < 2; i++)
     {
     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)
+    if ((fd = Uopen(spool_fname(subdirectory, message_subdir, id, suffix),
+                   O_RDONLY, 0)) >= 0)
       break;
     if (i == 0)
       continue;
@@ -1045,7 +1079,6 @@ only if the action is remove and the user is an admin user, to allow for
 tidying up broken states. */
 
 if ((deliver_datafile = spool_open_datafile(id)) < 0)
-  {
   if (errno == ENOENT)
     {
     yield = FALSE;
@@ -1060,7 +1093,6 @@ if ((deliver_datafile = spool_open_datafile(id)) < 0)
         strerror(errno));
     return FALSE;
     }
-  }
 
 /* Read the spool header file for the message. Again, continue after an
 error only in the case of deleting by an administrator. Setting the third
@@ -1113,7 +1145,7 @@ 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);
+  transport_write_message(1, NULL, 0);
   break;
 
 
@@ -1173,50 +1205,70 @@ switch(action)
   operation, just run everything twice. */
 
   case MSG_REMOVE:
-  message_subdir[0] = id[5];
-  for (j = 0; j < 2; message_subdir[0] = 0, j++)
     {
-    snprintf(CS spoolname, sizeof(spoolname), "%s/msglog/%s/%s/%s",
-      spool_directory, queue_name, message_subdir, id);
-    if (Uunlink(spoolname) < 0)
-      {
-      if (errno != ENOENT)
-        {
-        yield = FALSE;
-        printf("Error while removing %s: %s\n", spoolname,
-          strerror(errno));
-        }
-      }
-    else removed = TRUE;
+    uschar suffix[3];
 
-    for (i = 0; i < 3; i++)
+    suffix[0] = '-';
+    suffix[2] = 0;
+    message_subdir[0] = id[5];
+
+    for (j = 0; j < 2; message_subdir[0] = 0, j++)
       {
-      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)
-          {
-          yield = FALSE;
-          printf("Error while removing %s: %s\n", spoolname,
-            strerror(errno));
-          }
-        }
-      else removed = TRUE;
+      uschar * fname = spool_fname(US"msglog", message_subdir, id, US"");
+
+      DEBUG(D_any) debug_printf(" removing %s", fname);
+      if (Uunlink(fname) < 0)
+       {
+       if (errno != ENOENT)
+         {
+         yield = FALSE;
+         printf("Error while removing %s: %s\n", fname, strerror(errno));
+         }
+       else DEBUG(D_any) debug_printf(" (no file)\n");
+       }
+      else
+       {
+       removed = TRUE;
+       DEBUG(D_any) debug_printf(" (ok)\n");
+       }
+
+      for (i = 0; i < 3; i++)
+       {
+       uschar * fname;
+
+       suffix[1] = (US"DHJ")[i];
+       fname = spool_fname(US"input", message_subdir, id, suffix);
+
+       DEBUG(D_any) debug_printf(" removing %s", fname);
+       if (Uunlink(fname) < 0)
+         {
+         if (errno != ENOENT)
+           {
+           yield = FALSE;
+           printf("Error while removing %s: %s\n", fname, strerror(errno));
+           }
+         else DEBUG(D_any) debug_printf(" (no file)\n");
+         }
+       else
+         {
+         removed = TRUE;
+         DEBUG(D_any) debug_printf(" (done)\n");
+         }
+       }
       }
-    }
 
-  /* In the common case, the datafile is open (and locked), so give the
-  obvious message. Otherwise be more specific. */
+    /* In the common case, the datafile is open (and locked), so give the
+    obvious message. Otherwise be more specific. */
 
-  if (deliver_datafile >= 0) printf("has been removed\n");
-    else printf("has been removed or did not exist\n");
-  if (removed)
-    {
-    log_write(0, LOG_MAIN, "removed by %s", username);
-    log_write(0, LOG_MAIN, "Completed");
+    if (deliver_datafile >= 0) printf("has been removed\n");
+      else printf("has been removed or did not exist\n");
+    if (removed)
+      {
+      log_write(0, LOG_MAIN, "removed by %s", username);
+      log_write(0, LOG_MAIN, "Completed");
+      }
+    break;
     }
-  break;
 
 
   case MSG_MARK_ALL_DELIVERED:
@@ -1326,7 +1378,6 @@ switch(action)
     }
 
   if (yield)
-    {
     if (spool_write_header(id, SW_MODIFYING, &errmsg) >= 0)
       printf("has been modified\n");
     else
@@ -1334,7 +1385,6 @@ switch(action)
       yield = FALSE;
       printf("- while %s: %s\n", doing, errmsg);
       }
-    }
 
   break;
   }
@@ -1342,8 +1392,11 @@ switch(action)
 /* Closing the datafile releases the lock and permits other processes
 to operate on the message (if it still exists). */
 
-(void)close(deliver_datafile);
-deliver_datafile = -1;
+if (deliver_datafile >= 0)
+  {
+  (void)close(deliver_datafile);
+  deliver_datafile = -1;
+  }
 return yield;
 }
 
@@ -1395,4 +1448,6 @@ while ((ss = string_nextinlist(&s, &sep, buffer, sizeof(buffer))) != NULL)
   }
 }
 
+#endif /*!COMPILE_UTILITY*/
+
 /* End of queue.c */