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