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