Merge branch 'list_safety'
[exim.git] / src / src / search.c
index 1b8115b5049e5629528c8fd3e44e6527e8067651..15db52aa6aba0ca1716c52e3af09d6fb14787f43 100644 (file)
@@ -1,10 +1,8 @@
-/* $Cambridge: exim/src/src/search.c,v 1.2 2005/01/04 10:00:42 ph10 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* A set of functions to search databases in various formats. An open
@@ -71,7 +69,7 @@ int top = lookup_list_count;
 while (top > bot)
   {
   int mid = (top + bot)/2;
-  int c = Ustrncmp(name, lookup_list[mid].name, len);
+  int c = Ustrncmp(name, lookup_list[mid]->name, len);
 
   /* If c == 0 we have matched the incoming name with the start of the search
   type name. However, some search types are substrings of others (e.g. nis and
@@ -81,9 +79,9 @@ while (top > bot)
   are testing. By leaving c == 0 when the lengths are different, and doing a
   > 0 test below, this all falls out correctly. */
 
-  if (c == 0 && Ustrlen(lookup_list[mid].name) == len)
+  if (c == 0 && Ustrlen(lookup_list[mid]->name) == len)
     {
-    if (lookup_list[mid].find != NULL) return mid;
+    if (lookup_list[mid]->find != NULL) return mid;
     search_error_message  = string_sprintf("lookup type \"%.*s\" is not "
       "available (not in the binary - check buildtime LOOKUP configuration)",
       len, name);
@@ -184,18 +182,26 @@ else if (len >= 1 && ss[len-1]  == '*')
   }
 
 /* Check for the individual search type. Only those that are actually in the
-binary are valid. For query-style types, "partial" is an error. */
+binary are valid. For query-style types, "partial" and default types are
+erroneous. */
 
 stype = search_findtype(ss, len);
-if (pv >= 0 && mac_islookup(stype, lookup_querystyle))
+if (stype >= 0 && mac_islookup(stype, lookup_querystyle))
   {
-  search_error_message = string_sprintf("\"partial\" is not permitted "
-    "for lookup type \"%s\"", ss);
-  return -1;
+  if (pv >= 0)
+    {
+    search_error_message = string_sprintf("\"partial\" is not permitted "
+      "for lookup type \"%s\"", ss);
+    return -1;
+    }
+  if ((*starflags & (SEARCH_STAR|SEARCH_STARAT)) != 0)
+    {
+    search_error_message = string_sprintf("defaults using \"*\" or \"*@\" are "
+      "not permitted for lookup type \"%s\"", ss);
+    return -1;
+    }
   }
 
-/* All is well; pass back the partial type and return the lookup type. */
-
 *ptypeptr = pv;
 return stype;
 }
@@ -229,8 +235,8 @@ if (t->left != NULL) tidyup_subtree(t->left);
 if (t->right != NULL) tidyup_subtree(t->right);
 if (c != NULL &&
     c->handle != NULL &&
-    lookup_list[c->search_type].close != NULL)
-  lookup_list[c->search_type].close(c->handle);
+    lookup_list[c->search_type]->close != NULL)
+  lookup_list[c->search_type]->close(c->handle);
 }
 
 
@@ -262,7 +268,7 @@ open_filecount = 0;
 /* Call the general tidyup entry for any drivers that have one. */
 
 for (i = 0; i < lookup_list_count; i++)
-  if (lookup_list[i].tidy != NULL) (lookup_list[i].tidy)();
+  if (lookup_list[i]->tidy != NULL) (lookup_list[i]->tidy)();
 
 if (search_reset_point != NULL) store_reset(search_reset_point);
 search_reset_point = NULL;
@@ -327,7 +333,7 @@ search_open(uschar *filename, int search_type, int modemask, uid_t *owners,
 void *handle;
 tree_node *t;
 search_cache *c;
-lookup_info *lk = lookup_list + search_type;
+lookup_info *lk = lookup_list[search_type];
 uschar keybuffer[256];
 int old_pool = store_pool;
 
@@ -380,7 +386,7 @@ if (lk->type == lookup_absfile && open_filecount >= lookup_open_max)
       ((search_cache *)(open_bot->data.ptr))->down = NULL;
     else
       open_top = NULL;
-    ((lookup_list + c->search_type)->close)(c->handle);
+    ((lookup_list[c->search_type])->close)(c->handle);
     c->handle = NULL;
     open_filecount--;
     }
@@ -389,7 +395,7 @@ if (lk->type == lookup_absfile && open_filecount >= lookup_open_max)
 /* If opening is successful, call the file-checking function if there is one,
 and if all is still well, enter the open database into the tree. */
 
-handle = lk->open(filename, &search_error_message);
+handle = (lk->open)(filename, &search_error_message);
 if (handle == NULL)
   {
   store_pool = old_pool;
@@ -472,7 +478,7 @@ search_find_defer = FALSE;
 
 DEBUG(D_lookup) debug_printf("internal_search_find: file=\"%s\"\n  "
   "type=%s key=\"%s\"\n", filename,
-  lookup_list[search_type].name, keystring);
+  lookup_list[search_type]->name, keystring);
 
 /* Insurance. If the keystring is empty, just fail. */
 
@@ -503,7 +509,7 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL)
   like FAIL, except that search_find_defer is set so the caller can
   distinguish if necessary. */
 
-  if (lookup_list[search_type].find(c->handle, filename, keystring, keylength,
+  if (lookup_list[search_type]->find(c->handle, filename, keystring, keylength,
       &data, &search_error_message, &do_cache) == DEFER)
     {
     search_find_defer = TRUE;
@@ -614,7 +620,7 @@ DEBUG(D_lookup)
 that opens real files. */
 
 if (open_top != (tree_node *)handle &&
-    lookup_list[t->name[0]-'0'].type == lookup_absfile)
+    lookup_list[t->name[0]-'0']->type == lookup_absfile)
   {
   search_cache *c = (search_cache *)(t->data.ptr);
   tree_node *up = c->up;