Expansion item ${listquote }. Bug 1066
[exim.git] / src / src / drtables.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
f9ba5e22 5/* Copyright (c) University of Cambridge 1995 - 2018 */
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
b53c265b
JH
38#ifdef AUTH_EXTERNAL
39#include "auths/external.h"
40#endif
41
44bbabb5
PP
42#ifdef AUTH_GSASL
43#include "auths/gsasl_exim.h"
44#endif
45
dde3daac
PP
46#ifdef AUTH_HEIMDAL_GSSAPI
47#include "auths/heimdal_gssapi.h"
48#endif
49
059ec3d9
PH
50#ifdef AUTH_PLAINTEXT
51#include "auths/plaintext.h"
52#endif
53
54#ifdef AUTH_SPA
55#include "auths/spa.h"
56#endif
57
b3ef41c9
JH
58#ifdef AUTH_TLS
59#include "auths/tls.h"
60#endif
61
059ec3d9
PH
62auth_info auths_available[] = {
63
64/* Checking by an expansion condition on plain text */
65
66#ifdef AUTH_CRAM_MD5
67 {
f2ed27cf
JH
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,
25bd12fd
JH
76 .version_report = NULL,
77 .macros_create = NULL,
059ec3d9
PH
78 },
79#endif
80
81#ifdef AUTH_CYRUS_SASL
82 {
f2ed27cf
JH
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,
25bd12fd
JH
91 .version_report = auth_cyrus_sasl_version_report,
92 .macros_create = NULL,
059ec3d9
PH
93 },
94#endif
95
14aa5a05
PH
96#ifdef AUTH_DOVECOT
97 {
f2ed27cf
JH
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,
25bd12fd
JH
106 .version_report = NULL,
107 .macros_create = NULL,
44bbabb5
PP
108 },
109#endif
110
b53c265b
JH
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,
25bd12fd
JH
121 .version_report = NULL,
122 .macros_create = NULL,
b53c265b
JH
123 },
124#endif
125
44bbabb5
PP
126#ifdef AUTH_GSASL
127 {
f2ed27cf
JH
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,
14a806d6 135 .clientcode = auth_gsasl_client,
25bd12fd
JH
136 .version_report = auth_gsasl_version_report,
137 .macros_create = auth_gsasl_macros,
14aa5a05
PH
138 },
139#endif
140
dde3daac
PP
141#ifdef AUTH_HEIMDAL_GSSAPI
142 {
f2ed27cf
JH
143 .driver_name = US"heimdal_gssapi",
144 .options = auth_heimdal_gssapi_options,
7be14582 145 .options_count = &auth_heimdal_gssapi_options_count,
f2ed27cf
JH
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,
25bd12fd
JH
151 .version_report = auth_heimdal_gssapi_version_report,
152 .macros_create = NULL,
dde3daac
PP
153 },
154#endif
155
059ec3d9
PH
156#ifdef AUTH_PLAINTEXT
157 {
f2ed27cf
JH
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,
25bd12fd
JH
166 .version_report = NULL,
167 .macros_create = NULL,
059ec3d9
PH
168 },
169#endif
170
171#ifdef AUTH_SPA
172 {
f2ed27cf
JH
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,
25bd12fd
JH
181 .version_report = NULL,
182 .macros_create = NULL,
059ec3d9
PH
183 },
184#endif
185
b3ef41c9
JH
186#ifdef AUTH_TLS
187 {
f2ed27cf
JH
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,
25bd12fd
JH
196 .version_report = NULL,
197 .macros_create = NULL,
b3ef41c9
JH
198 },
199#endif
200
adf73d37 201 { .driver_name = US"" } /* end marker */
059ec3d9
PH
202};
203
204
205/* Tables of information about which routers and transports are included in the
206exim 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
3369a853
ACK
256#ifdef EXPERIMENTAL_QUEUEFILE
257#include "transports/queuefile.h"
258#endif
259
059ec3d9
PH
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
267router_info routers_available[] = {
268#ifdef ROUTER_ACCEPT
269 {
f2ed27cf
JH
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
059ec3d9
PH
279 },
280#endif
281#ifdef ROUTER_DNSLOOKUP
282 {
f2ed27cf
JH
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
059ec3d9
PH
292 },
293#endif
294#ifdef ROUTER_IPLITERAL
295 {
f2ed27cf
JH
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
059ec3d9
PH
305 },
306#endif
307#ifdef ROUTER_IPLOOKUP
308 {
f2ed27cf
JH
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
059ec3d9
PH
318 },
319#endif
320#ifdef ROUTER_MANUALROUTE
321 {
f2ed27cf
JH
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
059ec3d9
PH
331 },
332#endif
333#ifdef ROUTER_QUERYPROGRAM
334 {
f2ed27cf
JH
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
059ec3d9
PH
344 },
345#endif
346#ifdef ROUTER_REDIRECT
347 {
f2ed27cf
JH
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
059ec3d9
PH
357 },
358#endif
adf73d37 359 { US"" }
059ec3d9
PH
360};
361
362
363
364transport_info transports_available[] = {
365#ifdef TRANSPORT_APPENDFILE
366 {
f2ed27cf
JH
367 .driver_name = US"appendfile",
368 .options = appendfile_transport_options,
369 .options_count = &appendfile_transport_options_count,
370 .options_block = &appendfile_transport_option_defaults, /* private options defaults */
371 .options_len = sizeof(appendfile_transport_options_block),
372 .init = appendfile_transport_init,
373 .code = appendfile_transport_entry,
374 .tidyup = NULL,
375 .closedown = NULL,
376 .local = TRUE
059ec3d9
PH
377 },
378#endif
379#ifdef TRANSPORT_AUTOREPLY
380 {
f2ed27cf
JH
381 .driver_name = US"autoreply",
382 .options = autoreply_transport_options,
383 .options_count = &autoreply_transport_options_count,
384 .options_block = &autoreply_transport_option_defaults,
385 .options_len = sizeof(autoreply_transport_options_block),
386 .init = autoreply_transport_init,
387 .code = autoreply_transport_entry,
388 .tidyup = NULL,
389 .closedown = NULL,
390 .local = TRUE
059ec3d9
PH
391 },
392#endif
393#ifdef TRANSPORT_LMTP
394 {
f2ed27cf
JH
395 .driver_name = US"lmtp",
396 .options = lmtp_transport_options,
397 .options_count = &lmtp_transport_options_count,
398 .options_block = &lmtp_transport_option_defaults,
399 .options_len = sizeof(lmtp_transport_options_block),
400 .init = lmtp_transport_init,
401 .code = lmtp_transport_entry,
402 .tidyup = NULL,
403 .closedown = NULL,
404 .local = TRUE
059ec3d9
PH
405 },
406#endif
407#ifdef TRANSPORT_PIPE
408 {
f2ed27cf
JH
409 .driver_name = US"pipe",
410 .options = pipe_transport_options,
411 .options_count = &pipe_transport_options_count,
412 .options_block = &pipe_transport_option_defaults,
413 .options_len = sizeof(pipe_transport_options_block),
414 .init = pipe_transport_init,
415 .code = pipe_transport_entry,
416 .tidyup = NULL,
417 .closedown = NULL,
418 .local = TRUE
059ec3d9
PH
419 },
420#endif
3369a853
ACK
421#ifdef EXPERIMENTAL_QUEUEFILE
422 {
f2ed27cf
JH
423 .driver_name = US"queuefile",
424 .options = queuefile_transport_options,
425 .options_count = &queuefile_transport_options_count,
426 .options_block = &queuefile_transport_option_defaults,
427 .options_len = sizeof(queuefile_transport_options_block),
428 .init = queuefile_transport_init,
429 .code = queuefile_transport_entry,
430 .tidyup = NULL,
431 .closedown = NULL,
432 .local = TRUE
3369a853
ACK
433 },
434#endif
059ec3d9
PH
435#ifdef TRANSPORT_SMTP
436 {
f2ed27cf
JH
437 .driver_name = US"smtp",
438 .options = smtp_transport_options,
439 .options_count = &smtp_transport_options_count,
440 .options_block = &smtp_transport_option_defaults,
441 .options_len = sizeof(smtp_transport_options_block),
442 .init = smtp_transport_init,
443 .code = smtp_transport_entry,
444 .tidyup = NULL,
445 .closedown = smtp_transport_closedown,
446 .local = FALSE
059ec3d9
PH
447 },
448#endif
adf73d37 449 { US"" }
059ec3d9
PH
450};
451
ab1604ea
JH
452#ifndef MACRO_PREDEF
453
454gstring *
455auth_show_supported(gstring * g)
456{
457g = string_cat(g, US"Authenticators:");
458for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
459 g = string_fmt_append(g, " %s", ai->driver_name);
460return string_cat(g, US"\n");
461}
462
463gstring *
464route_show_supported(gstring * g)
adf73d37 465{
ab1604ea
JH
466g = string_cat(g, US"Routers:");
467for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
468 g = string_fmt_append(g, " %s", rr->driver_name);
469return string_cat(g, US"\n");
470}
471
472gstring *
473transport_show_supported(gstring * g)
474{
475g = string_cat(g, US"Transports:");
adf73d37 476#ifdef TRANSPORT_APPENDFILE
ab1604ea 477 g = string_cat(g, US" appendfile");
adf73d37 478 #ifdef SUPPORT_MAILDIR
ab1604ea 479 g = string_cat(g, US"/maildir"); /* damn these subclasses */
adf73d37
JH
480 #endif
481 #ifdef SUPPORT_MAILSTORE
ab1604ea 482 g = string_cat(g, US"/mailstore");
adf73d37
JH
483 #endif
484 #ifdef SUPPORT_MBX
ab1604ea 485 g = string_cat(g, US"/mbx");
adf73d37
JH
486 #endif
487#endif
488#ifdef TRANSPORT_AUTOREPLY
ab1604ea 489 g = string_cat(g, US" autoreply");
adf73d37
JH
490#endif
491#ifdef TRANSPORT_LMTP
ab1604ea 492 g = string_cat(g, US" lmtp");
adf73d37
JH
493#endif
494#ifdef TRANSPORT_PIPE
ab1604ea 495 g = string_cat(g, US" pipe");
adf73d37
JH
496#endif
497#ifdef EXPERIMENTAL_QUEUEFILE
ab1604ea 498 g = string_cat(g, US" queuefile");
adf73d37
JH
499#endif
500#ifdef TRANSPORT_SMTP
ab1604ea 501 g = string_cat(g, US" smtp");
adf73d37 502#endif
ab1604ea 503return string_cat(g, US"\n");
adf73d37
JH
504}
505
d185889f 506
d185889f 507
e6d225ae
DW
508struct lookupmodulestr
509{
510 void *dl;
511 struct lookup_module_info *info;
512 struct lookupmodulestr *next;
513};
514
515static struct lookupmodulestr *lookupmodules = NULL;
516
96f5fe4c
JH
517static void
518addlookupmodule(void *dl, struct lookup_module_info *info)
e6d225ae 519{
f3ebb786 520struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), FALSE);
96f5fe4c
JH
521
522p->dl = dl;
523p->info = info;
524p->next = lookupmodules;
525lookupmodules = p;
526lookup_list_count += info->lookupcount;
e6d225ae
DW
527}
528
529/* only valid after lookup_list and lookup_list_count are assigned */
96f5fe4c
JH
530static void
531add_lookup_to_list(lookup_info *info)
e6d225ae 532{
96f5fe4c
JH
533/* need to add the lookup to lookup_list, sorted */
534int pos = 0;
535
536/* strategy is to go through the list until we find
537either an empty spot or a name that is higher.
538this can't fail because we have enough space. */
539
540while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
541 pos++;
542
543if (lookup_list[pos])
544 {
545 /* need to insert it, so move all the other items up
546 (last slot is still empty, of course) */
547
d447dbd1 548 memmove(&lookup_list[pos+1], &lookup_list[pos],
96f5fe4c 549 sizeof(lookup_info *) * (lookup_list_count-pos-1));
e6d225ae 550 }
96f5fe4c 551lookup_list[pos] = info;
e6d225ae
DW
552}
553
4d805ee9
PP
554
555/* These need to be at file level for old versions of gcc (2.95.2 reported),
556 * which give parse errors on an extern in function scope. Each entry needs
557 * to also be invoked in init_lookup_list() below */
558
78f72498
JH
559#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
560extern lookup_module_info cdb_lookup_module_info;
4d805ee9 561#endif
78f72498
JH
562#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
563extern lookup_module_info dbmdb_lookup_module_info;
4d805ee9 564#endif
78f72498
JH
565#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
566extern lookup_module_info dnsdb_lookup_module_info;
4d805ee9 567#endif
78f72498
JH
568#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
569extern lookup_module_info dsearch_lookup_module_info;
4d805ee9 570#endif
78f72498
JH
571#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
572extern lookup_module_info ibase_lookup_module_info;
4d805ee9 573#endif
ffc92d69
JH
574#if defined(LOOKUP_JSON)
575extern lookup_module_info json_lookup_module_info;
576#endif
78f72498
JH
577#if defined(LOOKUP_LDAP)
578extern lookup_module_info ldap_lookup_module_info;
de78e2d5 579#endif
78f72498
JH
580#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
581extern lookup_module_info lsearch_lookup_module_info;
4d805ee9 582#endif
78f72498
JH
583#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
584extern lookup_module_info mysql_lookup_module_info;
4d805ee9
PP
585#endif
586#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
587extern lookup_module_info nis_lookup_module_info;
588#endif
78f72498
JH
589#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
590extern lookup_module_info nisplus_lookup_module_info;
4d805ee9 591#endif
78f72498
JH
592#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
593extern lookup_module_info oracle_lookup_module_info;
4d805ee9 594#endif
78f72498
JH
595#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
596extern lookup_module_info passwd_lookup_module_info;
4d805ee9 597#endif
78f72498
JH
598#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
599extern lookup_module_info pgsql_lookup_module_info;
4d805ee9 600#endif
78f72498
JH
601#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
602extern lookup_module_info redis_lookup_module_info;
4d805ee9 603#endif
5bde3efa
ACK
604#if defined(EXPERIMENTAL_LMDB)
605extern lookup_module_info lmdb_lookup_module_info;
606#endif
7952eef9 607#if defined(SUPPORT_SPF)
78f72498 608extern lookup_module_info spf_lookup_module_info;
4d805ee9 609#endif
78f72498
JH
610#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
611extern lookup_module_info sqlite_lookup_module_info;
4d805ee9 612#endif
78f72498
JH
613#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
614extern lookup_module_info testdb_lookup_module_info;
615#endif
616#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
617extern lookup_module_info whoson_lookup_module_info;
4d805ee9
PP
618#endif
619
96f5fe4c
JH
620
621void
622init_lookup_list(void)
e6d225ae 623{
fb2bba55 624#ifdef LOOKUP_MODULE_DIR
2fa25efc
JH
625DIR *dd;
626struct dirent *ent;
627int countmodules = 0;
628int moduleerrors = 0;
fb2bba55 629#endif
2fa25efc
JH
630static BOOL lookup_list_init_done = FALSE;
631rmark reset_point;
e6d225ae 632
2fa25efc
JH
633if (lookup_list_init_done)
634 return;
635reset_point = store_mark();
636lookup_list_init_done = TRUE;
6545de78 637
e6d225ae 638#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
2fa25efc 639addlookupmodule(NULL, &cdb_lookup_module_info);
e6d225ae
DW
640#endif
641
642#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
2fa25efc 643addlookupmodule(NULL, &dbmdb_lookup_module_info);
e6d225ae
DW
644#endif
645
646#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
2fa25efc 647addlookupmodule(NULL, &dnsdb_lookup_module_info);
e6d225ae
DW
648#endif
649
650#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
2fa25efc 651addlookupmodule(NULL, &dsearch_lookup_module_info);
e6d225ae
DW
652#endif
653
654#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
2fa25efc 655addlookupmodule(NULL, &ibase_lookup_module_info);
e6d225ae
DW
656#endif
657
658#ifdef LOOKUP_LDAP
2fa25efc 659addlookupmodule(NULL, &ldap_lookup_module_info);
e6d225ae
DW
660#endif
661
ffc92d69 662#ifdef LOOKUP_JSON
2fa25efc 663addlookupmodule(NULL, &json_lookup_module_info);
ffc92d69
JH
664#endif
665
e6d225ae 666#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
2fa25efc 667addlookupmodule(NULL, &lsearch_lookup_module_info);
e6d225ae
DW
668#endif
669
670#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
2fa25efc 671addlookupmodule(NULL, &mysql_lookup_module_info);
e6d225ae
DW
672#endif
673
674#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
2fa25efc 675addlookupmodule(NULL, &nis_lookup_module_info);
e6d225ae
DW
676#endif
677
678#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
2fa25efc 679addlookupmodule(NULL, &nisplus_lookup_module_info);
e6d225ae
DW
680#endif
681
682#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
2fa25efc 683addlookupmodule(NULL, &oracle_lookup_module_info);
e6d225ae
DW
684#endif
685
686#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
2fa25efc 687addlookupmodule(NULL, &passwd_lookup_module_info);
e6d225ae
DW
688#endif
689
690#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
2fa25efc 691addlookupmodule(NULL, &pgsql_lookup_module_info);
e6d225ae
DW
692#endif
693
de78e2d5 694#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
2fa25efc 695addlookupmodule(NULL, &redis_lookup_module_info);
9bdd29ad
TL
696#endif
697
5bde3efa 698#ifdef EXPERIMENTAL_LMDB
2fa25efc 699addlookupmodule(NULL, &lmdb_lookup_module_info);
5bde3efa
ACK
700#endif
701
7952eef9 702#ifdef SUPPORT_SPF
2fa25efc 703addlookupmodule(NULL, &spf_lookup_module_info);
e6d225ae
DW
704#endif
705
706#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
2fa25efc 707addlookupmodule(NULL, &sqlite_lookup_module_info);
e6d225ae
DW
708#endif
709
710#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
2fa25efc 711addlookupmodule(NULL, &testdb_lookup_module_info);
e6d225ae
DW
712#endif
713
714#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
2fa25efc 715addlookupmodule(NULL, &whoson_lookup_module_info);
e6d225ae
DW
716#endif
717
718#ifdef LOOKUP_MODULE_DIR
54a2a2a9 719if (!(dd = exim_opendir(LOOKUP_MODULE_DIR)))
2fa25efc
JH
720 {
721 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
722 log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
e6d225ae 723 }
2fa25efc
JH
724else
725 {
726 const pcre *regex_islookupmod = regex_must_compile(
727 US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
728
729 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
730 while ((ent = readdir(dd)))
731 {
732 char *name = ent->d_name;
733 int len = (int)strlen(name);
734 if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0)
735 {
736 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
737 void *dl;
738 struct lookup_module_info *info;
739 const char *errormsg;
740
741 /* SRH: am I being paranoid here or what? */
742 if (pathnamelen > big_buffer_size)
743 {
744 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
745 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
746 continue;
747 }
748
749 /* SRH: snprintf here? */
750 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
751
752 if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
753 {
3fc07bd5
AM
754 errormsg = dlerror();
755 fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
756 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
2fa25efc 757 moduleerrors++;
2fa25efc
JH
758 continue;
759 }
760
761 /* FreeBSD nsdispatch() can trigger dlerror() errors about
762 * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
763 * state before calling dlsym(), so that any error afterwards only
764 * comes from dlsym().
765 */
766 errormsg = dlerror();
767
768 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
769 if ((errormsg = dlerror()))
770 {
771 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
3fc07bd5 772 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
2fa25efc
JH
773 dlclose(dl);
774 moduleerrors++;
2fa25efc
JH
775 continue;
776 }
777 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
778 {
779 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
3fc07bd5 780 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
2fa25efc
JH
781 dlclose(dl);
782 moduleerrors++;
2fa25efc
JH
783 continue;
784 }
785
786 addlookupmodule(dl, info);
787 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
788 countmodules++;
e6d225ae
DW
789 }
790 }
2fa25efc
JH
791 store_free((void*)regex_islookupmod);
792 closedir(dd);
e6d225ae
DW
793 }
794
2fa25efc 795DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
e6d225ae
DW
796#endif
797
2fa25efc 798DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
e6d225ae 799
2fa25efc
JH
800lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
801memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
e6d225ae 802
2fa25efc
JH
803/* now add all lookups to the real list */
804for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
805 for (int j = 0; j < p->info->lookupcount; j++)
806 add_lookup_to_list(p->info->lookups[j]);
807store_reset(reset_point);
808/* just to be sure */
809lookupmodules = NULL;
e6d225ae
DW
810}
811
d185889f 812#endif /*!MACRO_PREDEF*/
059ec3d9 813/* End of drtables.c */