635c01be475e75894f4c2611a2979ba099731e62
[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 /* 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],
550           &lookup_list[pos],
551           sizeof(lookup_info *) * (lookup_list_count-pos-1));
552   }
553 lookup_list[pos] = info;
554 }
555
556
557 /* These need to be at file level for old versions of gcc (2.95.2 reported),
558  * which give parse errors on an extern in function scope.  Each entry needs
559  * to also be invoked in init_lookup_list() below  */
560
561 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
562 extern lookup_module_info cdb_lookup_module_info;
563 #endif
564 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
565 extern lookup_module_info dbmdb_lookup_module_info;
566 #endif
567 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
568 extern lookup_module_info dnsdb_lookup_module_info;
569 #endif
570 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
571 extern lookup_module_info dsearch_lookup_module_info;
572 #endif
573 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
574 extern lookup_module_info ibase_lookup_module_info;
575 #endif
576 #if defined(LOOKUP_JSON)
577 extern lookup_module_info json_lookup_module_info;
578 #endif
579 #if defined(LOOKUP_LDAP)
580 extern lookup_module_info ldap_lookup_module_info;
581 #endif
582 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
583 extern lookup_module_info lsearch_lookup_module_info;
584 #endif
585 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
586 extern lookup_module_info mysql_lookup_module_info;
587 #endif
588 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
589 extern lookup_module_info nis_lookup_module_info;
590 #endif
591 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
592 extern lookup_module_info nisplus_lookup_module_info;
593 #endif
594 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
595 extern lookup_module_info oracle_lookup_module_info;
596 #endif
597 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
598 extern lookup_module_info passwd_lookup_module_info;
599 #endif
600 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
601 extern lookup_module_info pgsql_lookup_module_info;
602 #endif
603 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
604 extern lookup_module_info redis_lookup_module_info;
605 #endif
606 #if defined(EXPERIMENTAL_LMDB)
607 extern lookup_module_info lmdb_lookup_module_info;
608 #endif
609 #if defined(SUPPORT_SPF)
610 extern lookup_module_info spf_lookup_module_info;
611 #endif
612 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
613 extern lookup_module_info sqlite_lookup_module_info;
614 #endif
615 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
616 extern lookup_module_info testdb_lookup_module_info;
617 #endif
618 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
619 extern lookup_module_info whoson_lookup_module_info;
620 #endif
621
622
623 void
624 init_lookup_list(void)
625 {
626 #ifdef LOOKUP_MODULE_DIR
627   DIR *dd;
628   struct dirent *ent;
629   int countmodules = 0;
630   int moduleerrors = 0;
631 #endif
632   static BOOL lookup_list_init_done = FALSE;
633   rmark reset_point;
634
635   if (lookup_list_init_done)
636     return;
637   reset_point = store_mark();
638   lookup_list_init_done = TRUE;
639
640 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
641   addlookupmodule(NULL, &cdb_lookup_module_info);
642 #endif
643
644 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
645   addlookupmodule(NULL, &dbmdb_lookup_module_info);
646 #endif
647
648 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
649   addlookupmodule(NULL, &dnsdb_lookup_module_info);
650 #endif
651
652 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
653   addlookupmodule(NULL, &dsearch_lookup_module_info);
654 #endif
655
656 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
657   addlookupmodule(NULL, &ibase_lookup_module_info);
658 #endif
659
660 #ifdef LOOKUP_LDAP
661   addlookupmodule(NULL, &ldap_lookup_module_info);
662 #endif
663
664 #ifdef LOOKUP_JSON
665   addlookupmodule(NULL, &json_lookup_module_info);
666 #endif
667
668 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
669   addlookupmodule(NULL, &lsearch_lookup_module_info);
670 #endif
671
672 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
673   addlookupmodule(NULL, &mysql_lookup_module_info);
674 #endif
675
676 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
677   addlookupmodule(NULL, &nis_lookup_module_info);
678 #endif
679
680 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
681   addlookupmodule(NULL, &nisplus_lookup_module_info);
682 #endif
683
684 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
685   addlookupmodule(NULL, &oracle_lookup_module_info);
686 #endif
687
688 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
689   addlookupmodule(NULL, &passwd_lookup_module_info);
690 #endif
691
692 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
693   addlookupmodule(NULL, &pgsql_lookup_module_info);
694 #endif
695
696 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
697   addlookupmodule(NULL, &redis_lookup_module_info);
698 #endif
699
700 #ifdef EXPERIMENTAL_LMDB
701   addlookupmodule(NULL, &lmdb_lookup_module_info);
702 #endif
703
704 #ifdef SUPPORT_SPF
705   addlookupmodule(NULL, &spf_lookup_module_info);
706 #endif
707
708 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
709   addlookupmodule(NULL, &sqlite_lookup_module_info);
710 #endif
711
712 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
713   addlookupmodule(NULL, &testdb_lookup_module_info);
714 #endif
715
716 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
717   addlookupmodule(NULL, &whoson_lookup_module_info);
718 #endif
719
720 #ifdef LOOKUP_MODULE_DIR
721   dd = opendir(LOOKUP_MODULE_DIR);
722   if (dd == NULL) {
723     DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
724     log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
725   }
726   else {
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)) != NULL) {
732       char *name = ent->d_name;
733       int len = (int)strlen(name);
734       if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
735         int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
736         void *dl;
737         struct lookup_module_info *info;
738         const char *errormsg;
739
740         /* SRH: am I being paranoid here or what? */
741         if (pathnamelen > big_buffer_size) {
742           fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
743           log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
744           continue;
745         }
746
747         /* SRH: snprintf here? */
748         sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
749
750         dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
751         if (dl == NULL) {
752           fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
753           moduleerrors++;
754           log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
755           continue;
756         }
757
758         /* FreeBSD nsdispatch() can trigger dlerror() errors about
759          * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
760          * state before calling dlsym(), so that any error afterwards only
761          * comes from dlsym().
762          */
763         errormsg = dlerror();
764
765         info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
766         if ((errormsg = dlerror()) != NULL) {
767           fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
768           dlclose(dl);
769           moduleerrors++;
770           log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
771           continue;
772         }
773         if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
774           fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
775           dlclose(dl);
776           moduleerrors++;
777           log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
778           continue;
779         }
780
781         addlookupmodule(dl, info);
782         DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
783         countmodules++;
784       }
785     }
786     store_free((void*)regex_islookupmod);
787     closedir(dd);
788   }
789
790   DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
791 #endif
792
793   DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
794
795   lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
796   memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
797
798   /* now add all lookups to the real list */
799   for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
800     for (int j = 0; j < p->info->lookupcount; j++)
801       add_lookup_to_list(p->info->lookups[j]);
802   store_reset(reset_point);
803   /* just to be sure */
804   lookupmodules = NULL;
805 }
806
807 #endif  /*!MACRO_PREDEF*/
808 /* End of drtables.c */