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