constify
[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 */