Avoid repeated string-copy building command-string for rspamd
[exim.git] / src / src / drtables.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
80fea873 5/* Copyright (c) University of Cambridge 1995 - 2016 */
059ec3d9
PH
6/* See the file NOTICE for conditions of use and distribution. */
7
8
9#include "exim.h"
10
e6d225ae 11#include <string.h>
059ec3d9
PH
12
13/* This module contains tables that define the lookup methods and drivers
14that are actually included in the binary. Its contents are controlled by
15various macros in config.h that ultimately come from Local/Makefile. They are
16all described in src/EDITME. */
17
18
e6d225ae
DW
19lookup_info **lookup_list;
20int lookup_list_count = 0;
059ec3d9 21
4c04137d 22/* Table of information about all possible authentication mechanisms. All
059ec3d9
PH
23entries are always present if any mechanism is declared, but the functions are
24set 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
14aa5a05
PH
34#ifdef AUTH_DOVECOT
35#include "auths/dovecot.h"
36#endif
37
44bbabb5
PP
38#ifdef AUTH_GSASL
39#include "auths/gsasl_exim.h"
40#endif
41
dde3daac
PP
42#ifdef AUTH_HEIMDAL_GSSAPI
43#include "auths/heimdal_gssapi.h"
44#endif
45
059ec3d9
PH
46#ifdef AUTH_PLAINTEXT
47#include "auths/plaintext.h"
48#endif
49
50#ifdef AUTH_SPA
51#include "auths/spa.h"
52#endif
53
b3ef41c9
JH
54#ifdef AUTH_TLS
55#include "auths/tls.h"
56#endif
57
059ec3d9
PH
58auth_info auths_available[] = {
59
60/* Checking by an expansion condition on plain text */
61
62#ifdef AUTH_CRAM_MD5
63 {
f2ed27cf
JH
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
059ec3d9
PH
73 },
74#endif
75
76#ifdef AUTH_CYRUS_SASL
77 {
f2ed27cf
JH
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
059ec3d9
PH
87 },
88#endif
89
14aa5a05
PH
90#ifdef AUTH_DOVECOT
91 {
f2ed27cf
JH
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
44bbabb5
PP
101 },
102#endif
103
104#ifdef AUTH_GSASL
105 {
f2ed27cf
JH
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
14aa5a05
PH
115 },
116#endif
117
dde3daac
PP
118#ifdef AUTH_HEIMDAL_GSSAPI
119 {
f2ed27cf
JH
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
dde3daac
PP
129 },
130#endif
131
059ec3d9
PH
132#ifdef AUTH_PLAINTEXT
133 {
f2ed27cf
JH
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
059ec3d9
PH
143 },
144#endif
145
146#ifdef AUTH_SPA
147 {
f2ed27cf
JH
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
059ec3d9
PH
157 },
158#endif
159
b3ef41c9
JH
160#ifdef AUTH_TLS
161 {
f2ed27cf
JH
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
b3ef41c9
JH
171 },
172#endif
173
f2ed27cf 174{ .driver_name = US"" } /* end marker */
059ec3d9
PH
175};
176
177
178/* Tables of information about which routers and transports are included in the
179exim binary. */
180
181/* Pull in the necessary header files */
182
183#include "routers/rf_functions.h"
184
185#ifdef ROUTER_ACCEPT
186#include "routers/accept.h"
187#endif
188
189#ifdef ROUTER_DNSLOOKUP
190#include "routers/dnslookup.h"
191#endif
192
193#ifdef ROUTER_MANUALROUTE
194#include "routers/manualroute.h"
195#endif
196
197#ifdef ROUTER_IPLITERAL
198#include "routers/ipliteral.h"
199#endif
200
201#ifdef ROUTER_IPLOOKUP
202#include "routers/iplookup.h"
203#endif
204
205#ifdef ROUTER_QUERYPROGRAM
206#include "routers/queryprogram.h"
207#endif
208
209#ifdef ROUTER_REDIRECT
210#include "routers/redirect.h"
211#endif
212
213#ifdef TRANSPORT_APPENDFILE
214#include "transports/appendfile.h"
215#endif
216
217#ifdef TRANSPORT_AUTOREPLY
218#include "transports/autoreply.h"
219#endif
220
221#ifdef TRANSPORT_LMTP
222#include "transports/lmtp.h"
223#endif
224
225#ifdef TRANSPORT_PIPE
226#include "transports/pipe.h"
227#endif
228
3369a853
ACK
229#ifdef EXPERIMENTAL_QUEUEFILE
230#include "transports/queuefile.h"
231#endif
232
059ec3d9
PH
233#ifdef TRANSPORT_SMTP
234#include "transports/smtp.h"
235#endif
236
237
238/* Now set up the structures, terminated by an entry with a null name. */
239
240router_info routers_available[] = {
241#ifdef ROUTER_ACCEPT
242 {
f2ed27cf
JH
243 .driver_name = US"accept",
244 .options = accept_router_options,
245 .options_count = &accept_router_options_count,
246 .options_block = &accept_router_option_defaults,
247 .options_len = sizeof(accept_router_options_block),
248 .init = accept_router_init,
249 .code = accept_router_entry,
250 .tidyup = NULL, /* no tidyup entry */
251 .ri_flags = ri_yestransport
059ec3d9
PH
252 },
253#endif
254#ifdef ROUTER_DNSLOOKUP
255 {
f2ed27cf
JH
256 .driver_name = US"dnslookup",
257 .options = dnslookup_router_options,
258 .options_count = &dnslookup_router_options_count,
259 .options_block = &dnslookup_router_option_defaults,
260 .options_len = sizeof(dnslookup_router_options_block),
261 .init = dnslookup_router_init,
262 .code = dnslookup_router_entry,
263 .tidyup = NULL, /* no tidyup entry */
264 .ri_flags = ri_yestransport
059ec3d9
PH
265 },
266#endif
267#ifdef ROUTER_IPLITERAL
268 {
f2ed27cf
JH
269 .driver_name = US"ipliteral",
270 .options = ipliteral_router_options,
271 .options_count = &ipliteral_router_options_count,
272 .options_block = &ipliteral_router_option_defaults,
273 .options_len = sizeof(ipliteral_router_options_block),
274 .init = ipliteral_router_init,
275 .code = ipliteral_router_entry,
276 .tidyup = NULL, /* no tidyup entry */
277 .ri_flags = ri_yestransport
059ec3d9
PH
278 },
279#endif
280#ifdef ROUTER_IPLOOKUP
281 {
f2ed27cf
JH
282 .driver_name = US"iplookup",
283 .options = iplookup_router_options,
284 .options_count = &iplookup_router_options_count,
285 .options_block = &iplookup_router_option_defaults,
286 .options_len = sizeof(iplookup_router_options_block),
287 .init = iplookup_router_init,
288 .code = iplookup_router_entry,
289 .tidyup = NULL, /* no tidyup entry */
290 .ri_flags = ri_notransport
059ec3d9
PH
291 },
292#endif
293#ifdef ROUTER_MANUALROUTE
294 {
f2ed27cf
JH
295 .driver_name = US"manualroute",
296 .options = manualroute_router_options,
297 .options_count = &manualroute_router_options_count,
298 .options_block = &manualroute_router_option_defaults,
299 .options_len = sizeof(manualroute_router_options_block),
300 .init = manualroute_router_init,
301 .code = manualroute_router_entry,
302 .tidyup = NULL, /* no tidyup entry */
303 .ri_flags = 0
059ec3d9
PH
304 },
305#endif
306#ifdef ROUTER_QUERYPROGRAM
307 {
f2ed27cf
JH
308 .driver_name = US"queryprogram",
309 .options = queryprogram_router_options,
310 .options_count = &queryprogram_router_options_count,
311 .options_block = &queryprogram_router_option_defaults,
312 .options_len = sizeof(queryprogram_router_options_block),
313 .init = queryprogram_router_init,
314 .code = queryprogram_router_entry,
315 .tidyup = NULL, /* no tidyup entry */
316 .ri_flags = 0
059ec3d9
PH
317 },
318#endif
319#ifdef ROUTER_REDIRECT
320 {
f2ed27cf
JH
321 .driver_name = US"redirect",
322 .options = redirect_router_options,
323 .options_count = &redirect_router_options_count,
324 .options_block = &redirect_router_option_defaults,
325 .options_len = sizeof(redirect_router_options_block),
326 .init = redirect_router_init,
327 .code = redirect_router_entry,
328 .tidyup = NULL, /* no tidyup entry */
329 .ri_flags = ri_notransport
059ec3d9
PH
330 },
331#endif
f2ed27cf 332{ US"" }
059ec3d9
PH
333};
334
335
336
337transport_info transports_available[] = {
338#ifdef TRANSPORT_APPENDFILE
339 {
f2ed27cf
JH
340 .driver_name = US"appendfile",
341 .options = appendfile_transport_options,
342 .options_count = &appendfile_transport_options_count,
343 .options_block = &appendfile_transport_option_defaults, /* private options defaults */
344 .options_len = sizeof(appendfile_transport_options_block),
345 .init = appendfile_transport_init,
346 .code = appendfile_transport_entry,
347 .tidyup = NULL,
348 .closedown = NULL,
349 .local = TRUE
059ec3d9
PH
350 },
351#endif
352#ifdef TRANSPORT_AUTOREPLY
353 {
f2ed27cf
JH
354 .driver_name = US"autoreply",
355 .options = autoreply_transport_options,
356 .options_count = &autoreply_transport_options_count,
357 .options_block = &autoreply_transport_option_defaults,
358 .options_len = sizeof(autoreply_transport_options_block),
359 .init = autoreply_transport_init,
360 .code = autoreply_transport_entry,
361 .tidyup = NULL,
362 .closedown = NULL,
363 .local = TRUE
059ec3d9
PH
364 },
365#endif
366#ifdef TRANSPORT_LMTP
367 {
f2ed27cf
JH
368 .driver_name = US"lmtp",
369 .options = lmtp_transport_options,
370 .options_count = &lmtp_transport_options_count,
371 .options_block = &lmtp_transport_option_defaults,
372 .options_len = sizeof(lmtp_transport_options_block),
373 .init = lmtp_transport_init,
374 .code = lmtp_transport_entry,
375 .tidyup = NULL,
376 .closedown = NULL,
377 .local = TRUE
059ec3d9
PH
378 },
379#endif
380#ifdef TRANSPORT_PIPE
381 {
f2ed27cf
JH
382 .driver_name = US"pipe",
383 .options = pipe_transport_options,
384 .options_count = &pipe_transport_options_count,
385 .options_block = &pipe_transport_option_defaults,
386 .options_len = sizeof(pipe_transport_options_block),
387 .init = pipe_transport_init,
388 .code = pipe_transport_entry,
389 .tidyup = NULL,
390 .closedown = NULL,
391 .local = TRUE
059ec3d9
PH
392 },
393#endif
3369a853
ACK
394#ifdef EXPERIMENTAL_QUEUEFILE
395 {
f2ed27cf
JH
396 .driver_name = US"queuefile",
397 .options = queuefile_transport_options,
398 .options_count = &queuefile_transport_options_count,
399 .options_block = &queuefile_transport_option_defaults,
400 .options_len = sizeof(queuefile_transport_options_block),
401 .init = queuefile_transport_init,
402 .code = queuefile_transport_entry,
403 .tidyup = NULL,
404 .closedown = NULL,
405 .local = TRUE
3369a853
ACK
406 },
407#endif
059ec3d9
PH
408#ifdef TRANSPORT_SMTP
409 {
f2ed27cf
JH
410 .driver_name = US"smtp",
411 .options = smtp_transport_options,
412 .options_count = &smtp_transport_options_count,
413 .options_block = &smtp_transport_option_defaults,
414 .options_len = sizeof(smtp_transport_options_block),
415 .init = smtp_transport_init,
416 .code = smtp_transport_entry,
417 .tidyup = NULL,
418 .closedown = smtp_transport_closedown,
419 .local = FALSE
059ec3d9
PH
420 },
421#endif
f2ed27cf 422{ US"" }
059ec3d9
PH
423};
424
d185889f
JH
425
426#ifndef MACRO_PREDEF
427
e6d225ae
DW
428struct lookupmodulestr
429{
430 void *dl;
431 struct lookup_module_info *info;
432 struct lookupmodulestr *next;
433};
434
435static struct lookupmodulestr *lookupmodules = NULL;
436
96f5fe4c
JH
437static void
438addlookupmodule(void *dl, struct lookup_module_info *info)
e6d225ae 439{
96f5fe4c
JH
440struct lookupmodulestr *p = store_malloc(sizeof(struct lookupmodulestr));
441
442p->dl = dl;
443p->info = info;
444p->next = lookupmodules;
445lookupmodules = p;
446lookup_list_count += info->lookupcount;
e6d225ae
DW
447}
448
449/* only valid after lookup_list and lookup_list_count are assigned */
96f5fe4c
JH
450static void
451add_lookup_to_list(lookup_info *info)
e6d225ae 452{
96f5fe4c
JH
453/* need to add the lookup to lookup_list, sorted */
454int pos = 0;
455
456/* strategy is to go through the list until we find
457either an empty spot or a name that is higher.
458this can't fail because we have enough space. */
459
460while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
461 pos++;
462
463if (lookup_list[pos])
464 {
465 /* need to insert it, so move all the other items up
466 (last slot is still empty, of course) */
467
468 memmove(&lookup_list[pos+1],
469 &lookup_list[pos],
470 sizeof(lookup_info *) * (lookup_list_count-pos-1));
e6d225ae 471 }
96f5fe4c 472lookup_list[pos] = info;
e6d225ae
DW
473}
474
4d805ee9
PP
475
476/* These need to be at file level for old versions of gcc (2.95.2 reported),
477 * which give parse errors on an extern in function scope. Each entry needs
478 * to also be invoked in init_lookup_list() below */
479
78f72498
JH
480#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
481extern lookup_module_info cdb_lookup_module_info;
4d805ee9 482#endif
78f72498
JH
483#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
484extern lookup_module_info dbmdb_lookup_module_info;
4d805ee9 485#endif
78f72498
JH
486#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
487extern lookup_module_info dnsdb_lookup_module_info;
4d805ee9 488#endif
78f72498
JH
489#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
490extern lookup_module_info dsearch_lookup_module_info;
4d805ee9 491#endif
78f72498
JH
492#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
493extern lookup_module_info ibase_lookup_module_info;
4d805ee9 494#endif
78f72498
JH
495#if defined(LOOKUP_LDAP)
496extern lookup_module_info ldap_lookup_module_info;
de78e2d5 497#endif
78f72498
JH
498#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
499extern lookup_module_info lsearch_lookup_module_info;
4d805ee9 500#endif
78f72498
JH
501#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
502extern lookup_module_info mysql_lookup_module_info;
4d805ee9
PP
503#endif
504#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
505extern lookup_module_info nis_lookup_module_info;
506#endif
78f72498
JH
507#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
508extern lookup_module_info nisplus_lookup_module_info;
4d805ee9 509#endif
78f72498
JH
510#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
511extern lookup_module_info oracle_lookup_module_info;
4d805ee9 512#endif
78f72498
JH
513#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
514extern lookup_module_info passwd_lookup_module_info;
4d805ee9 515#endif
78f72498
JH
516#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
517extern lookup_module_info pgsql_lookup_module_info;
4d805ee9 518#endif
78f72498
JH
519#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
520extern lookup_module_info redis_lookup_module_info;
4d805ee9 521#endif
5bde3efa
ACK
522#if defined(EXPERIMENTAL_LMDB)
523extern lookup_module_info lmdb_lookup_module_info;
524#endif
78f72498
JH
525#if defined(EXPERIMENTAL_SPF)
526extern lookup_module_info spf_lookup_module_info;
4d805ee9 527#endif
78f72498
JH
528#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
529extern lookup_module_info sqlite_lookup_module_info;
4d805ee9 530#endif
78f72498
JH
531#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
532extern lookup_module_info testdb_lookup_module_info;
533#endif
534#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
535extern lookup_module_info whoson_lookup_module_info;
4d805ee9
PP
536#endif
537
96f5fe4c
JH
538
539void
540init_lookup_list(void)
e6d225ae 541{
fb2bba55 542#ifdef LOOKUP_MODULE_DIR
e6d225ae
DW
543 DIR *dd;
544 struct dirent *ent;
e6d225ae
DW
545 int countmodules = 0;
546 int moduleerrors = 0;
fb2bba55 547#endif
e6d225ae 548 struct lookupmodulestr *p;
cab0c277
JH
549 static BOOL lookup_list_init_done = FALSE;
550
e6d225ae 551
6545de78
PP
552 if (lookup_list_init_done)
553 return;
cab0c277 554 lookup_list_init_done = TRUE;
6545de78 555
e6d225ae 556#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
e6d225ae
DW
557 addlookupmodule(NULL, &cdb_lookup_module_info);
558#endif
559
560#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
e6d225ae
DW
561 addlookupmodule(NULL, &dbmdb_lookup_module_info);
562#endif
563
564#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
e6d225ae
DW
565 addlookupmodule(NULL, &dnsdb_lookup_module_info);
566#endif
567
568#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
e6d225ae
DW
569 addlookupmodule(NULL, &dsearch_lookup_module_info);
570#endif
571
572#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
e6d225ae
DW
573 addlookupmodule(NULL, &ibase_lookup_module_info);
574#endif
575
576#ifdef LOOKUP_LDAP
e6d225ae
DW
577 addlookupmodule(NULL, &ldap_lookup_module_info);
578#endif
579
580#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
e6d225ae
DW
581 addlookupmodule(NULL, &lsearch_lookup_module_info);
582#endif
583
584#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
e6d225ae
DW
585 addlookupmodule(NULL, &mysql_lookup_module_info);
586#endif
587
588#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
e6d225ae
DW
589 addlookupmodule(NULL, &nis_lookup_module_info);
590#endif
591
592#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
e6d225ae
DW
593 addlookupmodule(NULL, &nisplus_lookup_module_info);
594#endif
595
596#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
e6d225ae
DW
597 addlookupmodule(NULL, &oracle_lookup_module_info);
598#endif
599
600#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
e6d225ae
DW
601 addlookupmodule(NULL, &passwd_lookup_module_info);
602#endif
603
604#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
e6d225ae
DW
605 addlookupmodule(NULL, &pgsql_lookup_module_info);
606#endif
607
de78e2d5 608#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
9bdd29ad
TL
609 addlookupmodule(NULL, &redis_lookup_module_info);
610#endif
611
5bde3efa
ACK
612#ifdef EXPERIMENTAL_LMDB
613 addlookupmodule(NULL, &lmdb_lookup_module_info);
614#endif
615
e6d225ae 616#ifdef EXPERIMENTAL_SPF
e6d225ae
DW
617 addlookupmodule(NULL, &spf_lookup_module_info);
618#endif
619
620#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
e6d225ae
DW
621 addlookupmodule(NULL, &sqlite_lookup_module_info);
622#endif
623
624#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
e6d225ae
DW
625 addlookupmodule(NULL, &testdb_lookup_module_info);
626#endif
627
628#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
e6d225ae
DW
629 addlookupmodule(NULL, &whoson_lookup_module_info);
630#endif
631
632#ifdef LOOKUP_MODULE_DIR
633 dd = opendir(LOOKUP_MODULE_DIR);
634 if (dd == NULL) {
1594a79a 635 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
e6d225ae
DW
636 log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
637 }
638 else {
f322340b
JH
639 const pcre *regex_islookupmod = regex_must_compile(
640 US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
641
1594a79a 642 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
e6d225ae
DW
643 while ((ent = readdir(dd)) != NULL) {
644 char *name = ent->d_name;
645 int len = (int)strlen(name);
646 if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
647 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
648 void *dl;
649 struct lookup_module_info *info;
1ba28e2b 650 const char *errormsg;
e6d225ae
DW
651
652 /* SRH: am I being paranoid here or what? */
653 if (pathnamelen > big_buffer_size) {
654 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
655 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
656 continue;
657 }
658
659 /* SRH: snprintf here? */
660 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
661
662 dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
663 if (dl == NULL) {
664 fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
665 moduleerrors++;
666 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
667 continue;
668 }
669
56e0c4ce
PP
670 /* FreeBSD nsdispatch() can trigger dlerror() errors about
671 * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
672 * state before calling dlsym(), so that any error afterwards only
673 * comes from dlsym().
674 */
675 errormsg = dlerror();
676
e6d225ae
DW
677 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
678 if ((errormsg = dlerror()) != NULL) {
679 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
680 dlclose(dl);
681 moduleerrors++;
682 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
683 continue;
684 }
685 if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
686 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
687 dlclose(dl);
688 moduleerrors++;
689 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
690 continue;
691 }
692
693 addlookupmodule(dl, info);
1594a79a 694 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
e6d225ae
DW
695 countmodules++;
696 }
697 }
f322340b 698 store_free((void*)regex_islookupmod);
e6d225ae
DW
699 closedir(dd);
700 }
701
1594a79a 702 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
e6d225ae
DW
703#endif
704
1594a79a 705 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
e6d225ae
DW
706
707 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
708 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
709
710 /* now add all lookups to the real list */
711 p = lookupmodules;
712 while (p) {
713 int j;
714 struct lookupmodulestr *pnext;
715
716 for (j = 0; j < p->info->lookupcount; j++)
717 add_lookup_to_list(p->info->lookups[j]);
718
719 pnext = p->next;
720 store_free(p);
721 p = pnext;
722 }
723 /* just to be sure */
724 lookupmodules = NULL;
725}
726
d185889f 727#endif /*!MACRO_PREDEF*/
059ec3d9 728/* End of drtables.c */