Defend against symlink attack by another process running as exim
[users/jgh/exim.git] / src / src / drtables.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2016 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8
9 #include "exim.h"
10
11 #include <string.h>
12
13 /* This module contains tables that define the lookup methods and drivers
14 that are actually included in the binary. Its contents are controlled by
15 various macros in config.h that ultimately come from Local/Makefile. They are
16 all described in src/EDITME. */
17
18
19 lookup_info **lookup_list;
20 int lookup_list_count = 0;
21
22 static int lookup_list_init_done = 0;
23
24 /* Table of information about all possible authentication mechamisms. All
25 entries are always present if any mechanism is declared, but the functions are
26 set to NULL for those that are not compiled into the binary. */
27
28 #ifdef AUTH_CRAM_MD5
29 #include "auths/cram_md5.h"
30 #endif
31
32 #ifdef AUTH_CYRUS_SASL
33 #include "auths/cyrus_sasl.h"
34 #endif
35
36 #ifdef AUTH_DOVECOT
37 #include "auths/dovecot.h"
38 #endif
39
40 #ifdef AUTH_GSASL
41 #include "auths/gsasl_exim.h"
42 #endif
43
44 #ifdef AUTH_HEIMDAL_GSSAPI
45 #include "auths/heimdal_gssapi.h"
46 #endif
47
48 #ifdef AUTH_PLAINTEXT
49 #include "auths/plaintext.h"
50 #endif
51
52 #ifdef AUTH_SPA
53 #include "auths/spa.h"
54 #endif
55
56 #ifdef AUTH_TLS
57 #include "auths/tls.h"
58 #endif
59
60 auth_info auths_available[] = {
61
62 /* Checking by an expansion condition on plain text */
63
64 #ifdef AUTH_CRAM_MD5
65   {
66   US"cram_md5",                              /* lookup name */
67   auth_cram_md5_options,
68   &auth_cram_md5_options_count,
69   &auth_cram_md5_option_defaults,
70   sizeof(auth_cram_md5_options_block),
71   auth_cram_md5_init,                        /* init function */
72   auth_cram_md5_server,                      /* server function */
73   auth_cram_md5_client,                      /* client function */
74   NULL                                       /* diagnostic function */
75   },
76 #endif
77
78 #ifdef AUTH_CYRUS_SASL
79   {
80   US"cyrus_sasl",           /* lookup name */
81   auth_cyrus_sasl_options,
82   &auth_cyrus_sasl_options_count,
83   &auth_cyrus_sasl_option_defaults,
84   sizeof(auth_cyrus_sasl_options_block),
85   auth_cyrus_sasl_init,                      /* init function */
86   auth_cyrus_sasl_server,                    /* server function */
87   NULL,                                      /* client function */
88   auth_cyrus_sasl_version_report             /* diagnostic function */
89   },
90 #endif
91
92 #ifdef AUTH_DOVECOT
93   {
94   US"dovecot",                                /* lookup name */
95   auth_dovecot_options,
96   &auth_dovecot_options_count,
97   &auth_dovecot_option_defaults,
98   sizeof(auth_dovecot_options_block),
99   auth_dovecot_init,                          /* init function */
100   auth_dovecot_server,                        /* server function */
101   NULL,                                       /* client function */
102   NULL                                        /* diagnostic function */
103   },
104 #endif
105
106 #ifdef AUTH_GSASL
107   {
108   US"gsasl",                                  /* lookup name */
109   auth_gsasl_options,
110   &auth_gsasl_options_count,
111   &auth_gsasl_option_defaults,
112   sizeof(auth_gsasl_options_block),
113   auth_gsasl_init,                            /* init function */
114   auth_gsasl_server,                          /* server function */
115   NULL,                                       /* client function */
116   auth_gsasl_version_report                   /* diagnostic function */
117   },
118 #endif
119
120 #ifdef AUTH_HEIMDAL_GSSAPI
121   {
122   US"heimdal_gssapi",                         /* lookup name */
123   auth_heimdal_gssapi_options,
124   &auth_heimdal_gssapi_options_count,
125   &auth_heimdal_gssapi_option_defaults,
126   sizeof(auth_heimdal_gssapi_options_block),
127   auth_heimdal_gssapi_init,                   /* init function */
128   auth_heimdal_gssapi_server,                 /* server function */
129   NULL,                                       /* client function */
130   auth_heimdal_gssapi_version_report          /* diagnostic function */
131   },
132 #endif
133
134 #ifdef AUTH_PLAINTEXT
135   {
136   US"plaintext",                             /* lookup name */
137   auth_plaintext_options,
138   &auth_plaintext_options_count,
139   &auth_plaintext_option_defaults,
140   sizeof(auth_plaintext_options_block),
141   auth_plaintext_init,                       /* init function */
142   auth_plaintext_server,                     /* server function */
143   auth_plaintext_client,                     /* client function */
144   NULL                                       /* diagnostic function */
145   },
146 #endif
147
148 #ifdef AUTH_SPA
149   {
150   US"spa",                                   /* lookup name */
151   auth_spa_options,
152   &auth_spa_options_count,
153   &auth_spa_option_defaults,
154   sizeof(auth_spa_options_block),
155   auth_spa_init,                             /* init function */
156   auth_spa_server,                           /* server function */
157   auth_spa_client,                           /* client function */
158   NULL                                       /* diagnostic function */
159   },
160 #endif
161
162 #ifdef AUTH_TLS
163   {
164   US"tls",                                   /* lookup name */
165   auth_tls_options,
166   &auth_tls_options_count,
167   &auth_tls_option_defaults,
168   sizeof(auth_tls_options_block),
169   auth_tls_init,                             /* init function */
170   auth_tls_server,                           /* server function */
171   NULL,                                      /* client function */
172   NULL                                       /* diagnostic function */
173   },
174 #endif
175
176 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL  }
177 };
178
179
180 /* Tables of information about which routers and transports are included in the
181 exim binary. */
182
183 /* Pull in the necessary header files */
184
185 #include "routers/rf_functions.h"
186
187 #ifdef ROUTER_ACCEPT
188 #include "routers/accept.h"
189 #endif
190
191 #ifdef ROUTER_DNSLOOKUP
192 #include "routers/dnslookup.h"
193 #endif
194
195 #ifdef ROUTER_MANUALROUTE
196 #include "routers/manualroute.h"
197 #endif
198
199 #ifdef ROUTER_IPLITERAL
200 #include "routers/ipliteral.h"
201 #endif
202
203 #ifdef ROUTER_IPLOOKUP
204 #include "routers/iplookup.h"
205 #endif
206
207 #ifdef ROUTER_QUERYPROGRAM
208 #include "routers/queryprogram.h"
209 #endif
210
211 #ifdef ROUTER_REDIRECT
212 #include "routers/redirect.h"
213 #endif
214
215 #ifdef TRANSPORT_APPENDFILE
216 #include "transports/appendfile.h"
217 #endif
218
219 #ifdef TRANSPORT_AUTOREPLY
220 #include "transports/autoreply.h"
221 #endif
222
223 #ifdef TRANSPORT_LMTP
224 #include "transports/lmtp.h"
225 #endif
226
227 #ifdef TRANSPORT_PIPE
228 #include "transports/pipe.h"
229 #endif
230
231 #ifdef TRANSPORT_SMTP
232 #include "transports/smtp.h"
233 #endif
234
235
236 /* Now set up the structures, terminated by an entry with a null name. */
237
238 router_info routers_available[] = {
239 #ifdef ROUTER_ACCEPT
240   {
241   US"accept",
242   accept_router_options,
243   &accept_router_options_count,
244   &accept_router_option_defaults,
245   sizeof(accept_router_options_block),
246   accept_router_init,
247   accept_router_entry,
248   NULL,     /* no tidyup entry */
249   ri_yestransport
250   },
251 #endif
252 #ifdef ROUTER_DNSLOOKUP
253   {
254   US"dnslookup",
255   dnslookup_router_options,
256   &dnslookup_router_options_count,
257   &dnslookup_router_option_defaults,
258   sizeof(dnslookup_router_options_block),
259   dnslookup_router_init,
260   dnslookup_router_entry,
261   NULL,     /* no tidyup entry */
262   ri_yestransport
263   },
264 #endif
265 #ifdef ROUTER_IPLITERAL
266   {
267   US"ipliteral",
268   ipliteral_router_options,
269   &ipliteral_router_options_count,
270   &ipliteral_router_option_defaults,
271   sizeof(ipliteral_router_options_block),
272   ipliteral_router_init,
273   ipliteral_router_entry,
274   NULL,     /* no tidyup entry */
275   ri_yestransport
276   },
277 #endif
278 #ifdef ROUTER_IPLOOKUP
279   {
280   US"iplookup",
281   iplookup_router_options,
282   &iplookup_router_options_count,
283   &iplookup_router_option_defaults,
284   sizeof(iplookup_router_options_block),
285   iplookup_router_init,
286   iplookup_router_entry,
287   NULL,     /* no tidyup entry */
288   ri_notransport
289   },
290 #endif
291 #ifdef ROUTER_MANUALROUTE
292   {
293   US"manualroute",
294   manualroute_router_options,
295   &manualroute_router_options_count,
296   &manualroute_router_option_defaults,
297   sizeof(manualroute_router_options_block),
298   manualroute_router_init,
299   manualroute_router_entry,
300   NULL,     /* no tidyup entry */
301   0
302   },
303 #endif
304 #ifdef ROUTER_QUERYPROGRAM
305   {
306   US"queryprogram",
307   queryprogram_router_options,
308   &queryprogram_router_options_count,
309   &queryprogram_router_option_defaults,
310   sizeof(queryprogram_router_options_block),
311   queryprogram_router_init,
312   queryprogram_router_entry,
313   NULL,     /* no tidyup entry */
314   0
315   },
316 #endif
317 #ifdef ROUTER_REDIRECT
318   {
319   US"redirect",
320   redirect_router_options,
321   &redirect_router_options_count,
322   &redirect_router_option_defaults,
323   sizeof(redirect_router_options_block),
324   redirect_router_init,
325   redirect_router_entry,
326   NULL,     /* no tidyup entry */
327   ri_notransport
328   },
329 #endif
330 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
331 };
332
333
334
335 transport_info transports_available[] = {
336 #ifdef TRANSPORT_APPENDFILE
337   {
338   US"appendfile",                              /* driver name */
339   appendfile_transport_options,                /* local options table */
340   &appendfile_transport_options_count,         /* number of entries */
341   &appendfile_transport_option_defaults,       /* private options defaults */
342   sizeof(appendfile_transport_options_block),  /* size of private block */
343   appendfile_transport_init,                   /* init entry point */
344   appendfile_transport_entry,                  /* main entry point */
345   NULL,                                        /* no tidyup entry */
346   NULL,                                        /* no closedown entry */
347   TRUE,                                        /* local flag */
348   },
349 #endif
350 #ifdef TRANSPORT_AUTOREPLY
351   {
352   US"autoreply",                               /* driver name */
353   autoreply_transport_options,                 /* local options table */
354   &autoreply_transport_options_count,          /* number of entries */
355   &autoreply_transport_option_defaults,        /* private options defaults */
356   sizeof(autoreply_transport_options_block),   /* size of private block */
357   autoreply_transport_init,                    /* init entry point */
358   autoreply_transport_entry,                   /* main entry point */
359   NULL,                                        /* no tidyup entry */
360   NULL,                                        /* no closedown entry */
361   TRUE                                         /* local flag */
362   },
363 #endif
364 #ifdef TRANSPORT_LMTP
365   {
366   US"lmtp",                                    /* driver name */
367   lmtp_transport_options,                      /* local options table */
368   &lmtp_transport_options_count,               /* number of entries */
369   &lmtp_transport_option_defaults,             /* private options defaults */
370   sizeof(lmtp_transport_options_block),        /* size of private block */
371   lmtp_transport_init,                         /* init entry point */
372   lmtp_transport_entry,                        /* main entry point */
373   NULL,                                        /* no tidyup entry */
374   NULL,                                        /* no closedown entry */
375   TRUE                                         /* local flag */
376   },
377 #endif
378 #ifdef TRANSPORT_PIPE
379   {
380   US"pipe",                                    /* driver name */
381   pipe_transport_options,                      /* local options table */
382   &pipe_transport_options_count,               /* number of entries */
383   &pipe_transport_option_defaults,             /* private options defaults */
384   sizeof(pipe_transport_options_block),        /* size of private block */
385   pipe_transport_init,                         /* init entry point */
386   pipe_transport_entry,                        /* main entry point */
387   NULL,                                        /* no tidyup entry */
388   NULL,                                        /* no closedown entry */
389   TRUE                                         /* local flag */
390   },
391 #endif
392 #ifdef TRANSPORT_SMTP
393   {
394   US"smtp",                                    /* driver name */
395   smtp_transport_options,                      /* local options table */
396   &smtp_transport_options_count,               /* number of entries */
397   &smtp_transport_option_defaults,             /* private options defaults */
398   sizeof(smtp_transport_options_block),        /* size of private block */
399   smtp_transport_init,                         /* init entry point */
400   smtp_transport_entry,                        /* main entry point */
401   NULL,                                        /* no tidyup entry */
402   smtp_transport_closedown,                    /* close down passed channel */
403   FALSE                                        /* local flag */
404   },
405 #endif
406 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, FALSE }
407 };
408
409 struct lookupmodulestr
410 {
411   void *dl;
412   struct lookup_module_info *info;
413   struct lookupmodulestr *next;
414 };
415
416 static struct lookupmodulestr *lookupmodules = NULL;
417
418 static void
419 addlookupmodule(void *dl, struct lookup_module_info *info)
420 {
421 struct lookupmodulestr *p = store_malloc(sizeof(struct lookupmodulestr));
422
423 p->dl = dl;
424 p->info = info;
425 p->next = lookupmodules;
426 lookupmodules = p;
427 lookup_list_count += info->lookupcount;
428 }
429
430 /* only valid after lookup_list and lookup_list_count are assigned */
431 static void
432 add_lookup_to_list(lookup_info *info)
433 {
434 /* need to add the lookup to lookup_list, sorted */
435 int pos = 0;
436
437 /* strategy is to go through the list until we find
438 either an empty spot or a name that is higher.
439 this can't fail because we have enough space. */
440
441 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
442   pos++;
443
444 if (lookup_list[pos])
445   {
446   /* need to insert it, so move all the other items up
447   (last slot is still empty, of course) */
448
449   memmove(&lookup_list[pos+1],
450           &lookup_list[pos],
451           sizeof(lookup_info *) * (lookup_list_count-pos-1));
452   }
453 lookup_list[pos] = info;
454 }
455
456
457 /* These need to be at file level for old versions of gcc (2.95.2 reported),
458  * which give parse errors on an extern in function scope.  Each entry needs
459  * to also be invoked in init_lookup_list() below  */
460
461 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
462 extern lookup_module_info cdb_lookup_module_info;
463 #endif
464 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
465 extern lookup_module_info dbmdb_lookup_module_info;
466 #endif
467 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
468 extern lookup_module_info dnsdb_lookup_module_info;
469 #endif
470 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
471 extern lookup_module_info dsearch_lookup_module_info;
472 #endif
473 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
474 extern lookup_module_info ibase_lookup_module_info;
475 #endif
476 #if defined(LOOKUP_LDAP)
477 extern lookup_module_info ldap_lookup_module_info;
478 #endif
479 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
480 extern lookup_module_info lsearch_lookup_module_info;
481 #endif
482 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
483 extern lookup_module_info mysql_lookup_module_info;
484 #endif
485 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
486 extern lookup_module_info nis_lookup_module_info;
487 #endif
488 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
489 extern lookup_module_info nisplus_lookup_module_info;
490 #endif
491 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
492 extern lookup_module_info oracle_lookup_module_info;
493 #endif
494 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
495 extern lookup_module_info passwd_lookup_module_info;
496 #endif
497 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
498 extern lookup_module_info pgsql_lookup_module_info;
499 #endif
500 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
501 extern lookup_module_info redis_lookup_module_info;
502 #endif
503 #if defined(EXPERIMENTAL_LMDB)
504 extern lookup_module_info lmdb_lookup_module_info;
505 #endif
506 #if defined(EXPERIMENTAL_SPF)
507 extern lookup_module_info spf_lookup_module_info;
508 #endif
509 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
510 extern lookup_module_info sqlite_lookup_module_info;
511 #endif
512 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
513 extern lookup_module_info testdb_lookup_module_info;
514 #endif
515 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
516 extern lookup_module_info whoson_lookup_module_info;
517 #endif
518
519
520 void
521 init_lookup_list(void)
522 {
523 #ifdef LOOKUP_MODULE_DIR
524   DIR *dd;
525   struct dirent *ent;
526   int countmodules = 0;
527   int moduleerrors = 0;
528 #endif
529   struct lookupmodulestr *p;
530
531   if (lookup_list_init_done)
532     return;
533   lookup_list_init_done = 1;
534
535 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
536   addlookupmodule(NULL, &cdb_lookup_module_info);
537 #endif
538
539 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
540   addlookupmodule(NULL, &dbmdb_lookup_module_info);
541 #endif
542
543 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
544   addlookupmodule(NULL, &dnsdb_lookup_module_info);
545 #endif
546
547 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
548   addlookupmodule(NULL, &dsearch_lookup_module_info);
549 #endif
550
551 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
552   addlookupmodule(NULL, &ibase_lookup_module_info);
553 #endif
554
555 #ifdef LOOKUP_LDAP
556   addlookupmodule(NULL, &ldap_lookup_module_info);
557 #endif
558
559 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
560   addlookupmodule(NULL, &lsearch_lookup_module_info);
561 #endif
562
563 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
564   addlookupmodule(NULL, &mysql_lookup_module_info);
565 #endif
566
567 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
568   addlookupmodule(NULL, &nis_lookup_module_info);
569 #endif
570
571 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
572   addlookupmodule(NULL, &nisplus_lookup_module_info);
573 #endif
574
575 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
576   addlookupmodule(NULL, &oracle_lookup_module_info);
577 #endif
578
579 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
580   addlookupmodule(NULL, &passwd_lookup_module_info);
581 #endif
582
583 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
584   addlookupmodule(NULL, &pgsql_lookup_module_info);
585 #endif
586
587 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
588   addlookupmodule(NULL, &redis_lookup_module_info);
589 #endif
590
591 #ifdef EXPERIMENTAL_LMDB
592   addlookupmodule(NULL, &lmdb_lookup_module_info);
593 #endif
594
595 #ifdef EXPERIMENTAL_SPF
596   addlookupmodule(NULL, &spf_lookup_module_info);
597 #endif
598
599 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
600   addlookupmodule(NULL, &sqlite_lookup_module_info);
601 #endif
602
603 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
604   addlookupmodule(NULL, &testdb_lookup_module_info);
605 #endif
606
607 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
608   addlookupmodule(NULL, &whoson_lookup_module_info);
609 #endif
610
611 #ifdef LOOKUP_MODULE_DIR
612   dd = opendir(LOOKUP_MODULE_DIR);
613   if (dd == NULL) {
614     DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
615     log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
616   }
617   else {
618     const pcre *regex_islookupmod = regex_must_compile(
619       US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
620
621     DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
622     while ((ent = readdir(dd)) != NULL) {
623       char *name = ent->d_name;
624       int len = (int)strlen(name);
625       if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
626         int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
627         void *dl;
628         struct lookup_module_info *info;
629         const char *errormsg;
630
631         /* SRH: am I being paranoid here or what? */
632         if (pathnamelen > big_buffer_size) {
633           fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
634           log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
635           continue;
636         }
637
638         /* SRH: snprintf here? */
639         sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
640
641         dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
642         if (dl == NULL) {
643           fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
644           moduleerrors++;
645           log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
646           continue;
647         }
648
649         /* FreeBSD nsdispatch() can trigger dlerror() errors about
650          * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
651          * state before calling dlsym(), so that any error afterwards only
652          * comes from dlsym().
653          */
654         errormsg = dlerror();
655
656         info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
657         if ((errormsg = dlerror()) != NULL) {
658           fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
659           dlclose(dl);
660           moduleerrors++;
661           log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
662           continue;
663         }
664         if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
665           fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
666           dlclose(dl);
667           moduleerrors++;
668           log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
669           continue;
670         }
671
672         addlookupmodule(dl, info);
673         DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
674         countmodules++;
675       }
676     }
677     store_free((void*)regex_islookupmod);
678     closedir(dd);
679   }
680
681   DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
682 #endif
683
684   DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
685
686   lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
687   memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
688
689   /* now add all lookups to the real list */
690   p = lookupmodules;
691   while (p) {
692     int j;
693     struct lookupmodulestr *pnext;
694
695     for (j = 0; j < p->info->lookupcount; j++)
696       add_lookup_to_list(p->info->lookups[j]);
697
698     pnext = p->next;
699     store_free(p);
700     p = pnext;
701   }
702   /* just to be sure */
703   lookupmodules = NULL;
704 }
705
706 /* End of drtables.c */