Support old-format message_id spoolfiles for mailq / -bp. Bug 3050
[exim.git] / src / src / queue.c
index d01cde655d6b0dfdd126684c3c33c585b8a093e8..2c3d014f5638405404e06bacd0f2d7f73fcb4129 100644 (file)
@@ -54,8 +54,13 @@ queue_filename **append = &first;
 while (a && b)
   {
   int d;
-  if ((d = Ustrncmp(a->text, b->text, 6)) == 0)
-    d = Ustrcmp(a->text + 14, b->text + 14);
+  if ((d = Ustrncmp(a->text, b->text, MESSAGE_ID_TIME_LEN)) == 0)
+    {
+    BOOL a_old = is_old_message_id(a->text), b_old = is_old_message_id(b->text);
+    /* Do not worry over the sub-second sorting wrt. old vs. new */
+    d = Ustrcmp(a->text + (a_old ? 6+1+6+1 : MESSAGE_ID_TIME_LEN + 1 + MESSAGE_ID_PID_LEN + 1),
+               b->text + (b_old ? 6+1+6+1 : MESSAGE_ID_TIME_LEN + 1 + MESSAGE_ID_PID_LEN + 1));
+    }
   if (d < 0)
     {
     *append = a;
@@ -188,9 +193,9 @@ for (; i <= *subcount; i++)
 
   /* Now scan the directory. */
 
-  for (struct dirent *ent; ent = readdir(dd); )
+  for (struct dirent * ent; ent = readdir(dd); )
     {
-    uschar *name = US ent->d_name;
+    uschar * name = US ent->d_name;
     int len = Ustrlen(name);
 
     /* Count entries */
@@ -209,14 +214,15 @@ for (; i <= *subcount; i++)
 
     /* Otherwise, if it is a header spool file, add it to the list */
 
-    if (len == SPOOL_NAME_LENGTH &&
-        Ustrcmp(name + SPOOL_NAME_LENGTH - 2, "-H") == 0)
+    if (  (len == SPOOL_NAME_LENGTH || len == SPOOL_NAME_LENGTH_OLD)
+       && Ustrcmp(name + len - 2, "-H") == 0
+       )
       if (pcount)
        (*pcount)++;
       else
        {
        queue_filename * next =
-         store_get(sizeof(queue_filename) + Ustrlen(name), name);
+         store_get(sizeof(queue_filename) + len, name);
        Ustrcpy(next->text, name);
        next->dir_uschar = subdirchar;
 
@@ -348,7 +354,7 @@ Returns:     nothing
 */
 
 void
-queue_run(qrunner * q, uschar * start_id, uschar * stop_id, BOOL recurse)
+queue_run(qrunner * q, const uschar * start_id, const uschar * stop_id, BOOL recurse)
 {
 BOOL force_delivery = q->queue_run_force
   || deliver_selectstring || deliver_selectstring_sender;
@@ -579,7 +585,7 @@ for (int i = queue_run_in_order ? -1 : 0;
       else if (  deliver_selectstring_sender
              && !(f.deliver_selectstring_sender_regex
                  ? regex_match(selectstring_regex_sender, sender_address, -1, NULL)
-                 : (strstric(sender_address, deliver_selectstring_sender, FALSE)
+                 : (strstric_c(sender_address, deliver_selectstring_sender, FALSE)
                      != NULL)
              )   )
         {
@@ -595,10 +601,10 @@ for (int i = queue_run_in_order ? -1 : 0;
         int i;
         for (i = 0; i < recipients_count; i++)
           {
-          uschar *address = recipients_list[i].address;
+          const uschar * address = recipients_list[i].address;
           if (  (f.deliver_selectstring_regex
                ? regex_match(selectstring_regex, address, -1, NULL)
-                : (strstric(address, deliver_selectstring, FALSE) != NULL)
+                : (strstric_c(address, deliver_selectstring, FALSE) != NULL)
                )
              && tree_search(tree_nonrecipients, address) == NULL
             )
@@ -657,8 +663,8 @@ for (int i = queue_run_in_order ? -1 : 0;
     /* Now deliver the message; get the id by cutting the -H off the file
     name. The return of the process is zero if a delivery was attempted. */
 
+    fq->text[Ustrlen(fq->text)-2] = 0;
     set_process_info("running queue: %s", fq->text);
-    fq->text[SPOOL_NAME_LENGTH-2] = 0;
 #ifdef MEASURE_TIMING
     report_time_since(&timestamp_startup, US"queue msg selected");
 #endif
@@ -807,7 +813,7 @@ if (!recurse)
 
 
 void
-single_queue_run(qrunner * q, uschar * start_id, uschar * stop_id)
+single_queue_run(qrunner * q, const uschar * start_id, const uschar * stop_id)
 {
 DEBUG(D_queue_run) debug_printf("Single queue run%s%s%s%s\n",
   start_id ? US" starting at " : US"",
@@ -913,7 +919,7 @@ Returns:      nothing
 */
 
 void
-queue_list(int option, uschar **list, int count)
+queue_list(int option, const uschar ** list, int count)
 {
 int subcount;
 int now = (int)time(NULL);
@@ -942,21 +948,27 @@ if (count > 0)
 
 else
   qf = queue_get_spool_list(
-          -1,             /* entire queue */
-          subdirs,        /* for holding sub list */
-          &subcount,      /* for subcount */
-          option >= 8,   /* randomize if required */
-         NULL);          /* don't just count */
+          -1,                          /* entire queue */
+          subdirs,                     /* for holding sub list */
+          &subcount,                   /* for subcount */
+          option >= QL_UNSORTED,       /* randomize if required */
+         NULL);                        /* don't just count */
 
-if (option >= 8) option -= 8;
+option &= ~QL_UNSORTED;
 
 /* Now scan the chain and print information, resetting store used
 each time. */
 
-for (;
-    qf && (reset_point = store_mark());
-    spool_clear_header_globals(), store_reset(reset_point), qf = qf->next
-    )
+if (option == QL_MSGID_ONLY)   /* Print only the message IDs from the chain */
+  for (; qf; qf = qf->next)
+    fprintf(stdout, "%.*s\n",
+      is_old_message_id(qf->text) ? MESSAGE_ID_LENGTH_OLD : MESSAGE_ID_LENGTH,
+      qf->text);
+
+else for (;
+         qf && (reset_point = store_mark());
+         spool_clear_header_globals(), store_reset(reset_point), qf = qf->next
+        )
   {
   int rc, save_errno;
   int size = 0;
@@ -986,7 +998,7 @@ for (;
     that precedes the data. */
 
     if (Ustat(fname, &statbuf) == 0)
-      size = message_size + statbuf.st_size - SPOOL_DATA_START_OFFSET + 1;
+      size = message_size + statbuf.st_size - spool_data_start_offset(qf->text) + 1;
     i = (now - received_time.tv_sec)/60;  /* minutes on queue */
     if (i > 90)
       {
@@ -1010,8 +1022,10 @@ for (;
       }
     }
 
-  fprintf(stdout, "%s ", string_format_size(size, big_buffer));
-  for (int i = 0; i < 16; i++) fputc(qf->text[i], stdout);
+  fprintf(stdout, "%s %.*s",
+    string_format_size(size, big_buffer),
+    is_old_message_id(qf->text) ? MESSAGE_ID_LENGTH_OLD : MESSAGE_ID_LENGTH,
+    qf->text);
 
   if (env_read && sender_address)
     {
@@ -1048,14 +1062,14 @@ for (;
     {
     for (int i = 0; i < recipients_count; i++)
       {
-      tree_node *delivered =
+      tree_node * delivered =
         tree_search(tree_nonrecipients, recipients_list[i].address);
-      if (!delivered || option != 1)
+      if (!delivered || option != QL_UNDELIVERED_ONLY)
         printf("        %s %s\n",
          delivered ? "D" : " ", recipients_list[i].address);
       if (delivered) delivered->data.val = TRUE;
       }
-    if (option == 2 && tree_nonrecipients)
+    if (option == QL_PLUS_GENERATED && tree_nonrecipients)
       queue_list_extras(tree_nonrecipients);
     printf("\n");
     }
@@ -1083,7 +1097,8 @@ Returns:          FALSE if there was any problem
 */
 
 BOOL
-queue_action(uschar *id, int action, uschar **argv, int argc, int recipients_arg)
+queue_action(const uschar * id, int action, const uschar ** argv, int argc,
+  int recipients_arg)
 {
 BOOL yield = TRUE;
 BOOL removed = FALSE;
@@ -1152,7 +1167,7 @@ if (action >= MSG_SHOW_BODY)
     }
 
   while((rc = read(fd, big_buffer, big_buffer_size)) > 0)
-    rc = write(fileno(stdout), big_buffer, rc);
+    rc = write(fileno(stdout), big_buffer, rc);                        /*XXX why not fwrite() ? */
 
   (void)close(fd);
   return TRUE;
@@ -1295,11 +1310,9 @@ switch(action)
 
   case MSG_REMOVE:
     {
-    uschar suffix[3];
+    uschar suffix[3] = { [0]='-', [2]=0 };
 
-    suffix[0] = '-';
-    suffix[2] = 0;
-    message_subdir[0] = id[5];
+    message_subdir[0] = id[MESSAGE_ID_TIME_LEN - 1];
 
     for (int j = 0; j < 2; message_subdir[0] = 0, j++)
       {
@@ -1360,9 +1373,10 @@ switch(action)
          tree_search(tree_nonrecipients, recipients_list[i].address);
        if (!delivered)
          {
-         uschar * save_local = deliver_localpart;
+         const uschar * save_local = deliver_localpart;
          const uschar * save_domain = deliver_domain;
-         uschar * addr = recipients_list[i].address, * errmsg = NULL;
+         const uschar * addr = recipients_list[i].address;
+         uschar * errmsg = NULL;
          int start, end, dom;
 
          if (!parse_extract_address(addr, &errmsg, &start, &end, &dom, TRUE))