tidying
[exim.git] / src / src / match.c
index a877aef3b65d87a08fc56480a5d94c07031d71b8..2cb4993599188aa1a5349199e2bae27218d534e4 100644 (file)
@@ -2,10 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* Functions for matching strings */
 
@@ -430,9 +430,9 @@ int yield = OK;
 unsigned int * original_cache_bits = *cache_ptr;
 BOOL include_unknown = FALSE, ignore_unknown = FALSE,
       include_defer = FALSE, ignore_defer = FALSE;
-const uschar *list;
-uschar *sss;
-uschar *ot = NULL;
+const uschar * list;
+uschar * sss;
+uschar * ot = NULL;
 BOOL textonly_re;
 
 /* Save time by not scanning for the option name when we don't need it. */
@@ -514,6 +514,11 @@ HDEBUG(D_any) if (!ot)
   gstring_release_unused(g);
   ot = string_from_gstring(g);
   }
+HDEBUG(D_lists)
+  {
+  debug_printf_indent("%s\n", ot);
+  expand_level++;
+  }
 
 /* Now scan the list and process each item in turn, until one of them matches,
 or we hit an error. */
@@ -522,6 +527,8 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
   {
   uschar * ss = sss;
 
+  HDEBUG(D_lists) debug_printf_indent("list element: %s\n", ss);
+
   /* Address lists may contain +caseful, to restore caseful matching of the
   local part. We have to know the layout of the control block, unfortunately.
   The lower cased address is in a temporary buffer, so we just copy the local
@@ -592,7 +599,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
   if (*ss == '!')
     {
     yield = FAIL;
-    while (isspace((*(++ss))));
+    while (isspace(*++ss)) ;
     }
   else
     yield = OK;
@@ -605,14 +612,15 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
     {
     if (*ss == '+' && anchorptr)
       {
-      int bits = 0;
-      int offset = 0;
-      int shift = 0;
-      unsigned int *use_cache_bits = original_cache_bits;
-      uschar *cached = US"";
-      namedlist_block *nb;
+      int bits = 0, offset = 0, shift = 0;
+      unsigned int * use_cache_bits = original_cache_bits;
+      uschar * cached = US"";
+      namedlist_block * nb;
       tree_node * t;
 
+      DEBUG(D_lists)
+       { debug_printf_indent(" start sublist %s\n", ss+1); expand_level += 2; }
+
       if (!(t = tree_search(*anchorptr, ss+1)))
        {
         log_write(0, LOG_MAIN|LOG_PANIC, "unknown named%s list \"%s\"",
@@ -621,7 +629,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
           type == MCL_ADDRESS ?   " address" :
           type == MCL_LOCALPART ? " local part" : "",
           ss);
-       return DEFER;
+       goto DEFER_RETURN;
        }
       nb = t->data.ptr;
 
@@ -645,8 +653,12 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
 
       if (bits == 0)
         {
-        switch (match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits,
-                func, arg, type, name, valueptr))
+        int res = match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits,
+                func, arg, type, name, valueptr);
+       DEBUG(D_lists)
+         { expand_level -= 2; debug_printf_indent(" end sublist %s\n", ss+1); }
+
+        switch (res)
           {
           case OK:   bits = 1; break;
           case FAIL: bits = 3; break;
@@ -695,8 +707,12 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
 
       else
         {
-        DEBUG(D_lists) debug_printf_indent("cached %s match for %s\n",
-          (bits & (-bits)) == bits ? "yes" : "no", ss);
+        DEBUG(D_lists)
+         {
+         expand_level -= 2;
+         debug_printf_indent("cached %s match for %s\n",
+           (bits & (-bits)) == bits ? "yes" : "no", ss);
+         }
 
         cached = US" - cached";
         if (valueptr)
@@ -720,7 +736,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
         {
         HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\"%s)\n", ot,
           yield == OK ? "yes" : "no", sss, cached);
-        return yield;
+       goto YIELD_RETURN;
         }
       }
 
@@ -734,7 +750,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
         case OK:
          HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\")\n", ot,
            (yield == OK)? "yes" : "no", sss);
-         return yield;
+         goto YIELD_RETURN;
 
         case DEFER:
          if (!error)
@@ -809,15 +825,14 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
 
     while (Ufgets(filebuffer, sizeof(filebuffer), f) != NULL)
       {
-      uschar *error;
-      uschar *sss = filebuffer;
+      uschar * error, * sss = filebuffer;
 
       while ((ss = Ustrchr(sss, '#')) != NULL)
         {
         if ((type != MCL_ADDRESS && type != MCL_LOCALPART) ||
               ss == filebuffer || isspace(ss[-1]))
           {
-          *ss = 0;
+          *ss = '\0';
           break;
           }
         sss = ss + 1;
@@ -825,20 +840,19 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
 
       ss = filebuffer + Ustrlen(filebuffer);           /* trailing space */
       while (ss > filebuffer && isspace(ss[-1])) ss--;
-      *ss = 0;
+      *ss = '\0';
 
       ss = filebuffer;
-      while (isspace(*ss)) ss++;                       /* leading space */
-
-      if (!*ss) continue;                              /* ignore empty */
+      if (!Uskip_whitespace(&ss))                      /* leading space */
+       continue;                                       /* ignore empty */
 
       file_yield = yield;                              /* positive yield */
       sss = ss;                                                /* for debugging */
 
       if (*ss == '!')                                  /* negation */
         {
-        file_yield = (file_yield == OK)? FAIL : OK;
-        while (isspace((*(++ss))));
+        file_yield = file_yield == OK ? FAIL : OK;
+        while (isspace(*++ss)) ;
         }
 
       switch ((func)(arg, ss, valueptr, &error))
@@ -852,7 +866,8 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
          Copy it to allocated memory now we know it matched. */
 
          if (valueptr) *valueptr = string_copy(ss);
-         return file_yield;
+         yield = file_yield;
+         goto YIELD_RETURN;
 
         case DEFER:
          if (!error)
@@ -864,21 +879,24 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
            break;
            }
          (void)fclose(f);
-         if (include_defer)
-           {
-           log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
-           return OK;
-           }
-         goto DEFER_RETURN;
+         if (!include_defer)
+           goto DEFER_RETURN;
+         log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
+         goto OK_RETURN;
+
+        /* The ERROR return occurs when checking hosts, when either a forward
+        or reverse lookup has failed. It can also occur in a match_ip list if a
+        non-IP address item is encountered. The error string gives details of
+        which it was. */
 
-        case ERROR:            /* host name lookup failed - this can only */
-         if (ignore_unknown)   /* be for an incoming host (not outgoing) */
+        case ERROR:
+         if (ignore_unknown)
            {
            HDEBUG(D_lists) debug_printf_indent("%s: item ignored by +ignore_unknown\n",
              error);
            }
          else
-          {
+           {
            HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot,
              include_unknown? "yes":"no", error);
            (void)fclose(f);
@@ -886,10 +904,10 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
              {
              if (LOGGING(unknown_in_list))
                log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
-             return FAIL;
+             goto FAIL_RETURN;
              }
            log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
-           return OK;
+           goto OK_RETURN;
            }
         }
       }
@@ -905,14 +923,33 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
 /* End of list reached: if the last item was negated yield OK, else FAIL. */
 
 HDEBUG(D_lists)
-  debug_printf_indent("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
-return yield == OK ? FAIL : OK;
+  HDEBUG(D_lists)
+    {
+    expand_level--;
+    debug_printf_indent("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
+    }
+  return yield == OK ? FAIL : OK;
 
 /* Something deferred */
 
 DEFER_RETURN:
-HDEBUG(D_lists) debug_printf("%s list match deferred for %s\n", ot, sss);
-return DEFER;
+  HDEBUG(D_lists)
+    {
+    expand_level--;
+    debug_printf_indent("%s list match deferred for %s\n", ot, sss);
+    }
+  return DEFER;
+
+FAIL_RETURN:
+  yield = FAIL;
+  goto YIELD_RETURN;
+
+OK_RETURN:
+  yield = OK;
+
+YIELD_RETURN:
+  HDEBUG(D_lists) expand_level--;
+  return yield;
 }
 
 
@@ -934,6 +971,7 @@ Arguments:
   s              string to search for
   listptr        ptr to ptr to colon separated list of patterns, or NULL
   sep            a separator value for the list (see string_nextinlist())
+                or zero for auto
   anchorptr      ptr to tree for named items, or NULL if no named items
   cache_bits     ptr to cache_bits for ditto, or NULL if not caching
   type           MCL_DOMAIN when matching a domain list
@@ -1117,7 +1155,7 @@ if (pattern[0] == '@' && pattern[1] == '@')
       if (*ss == '!')
         {
         local_yield = FAIL;
-        while (isspace((*(++ss))));
+        while (isspace(*++ss)) ;
         }
       else local_yield = OK;