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