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