1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2020 - 2023 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
15 /* This module contains tables that define the lookup methods and drivers
16 that are actually included in the binary. Its contents are controlled by
17 various macros in config.h that ultimately come from Local/Makefile. They are
18 all described in src/EDITME. */
21 lookup_info **lookup_list;
22 int lookup_list_count = 0;
24 /* Table of information about all possible authentication mechanisms. All
25 entries are always present if any mechanism is declared, but the functions are
26 set to NULL for those that are not compiled into the binary. */
29 #include "auths/cram_md5.h"
32 #ifdef AUTH_CYRUS_SASL
33 #include "auths/cyrus_sasl.h"
37 #include "auths/dovecot.h"
41 #include "auths/external.h"
45 #include "auths/gsasl_exim.h"
48 #ifdef AUTH_HEIMDAL_GSSAPI
49 #include "auths/heimdal_gssapi.h"
53 #include "auths/plaintext.h"
57 #include "auths/spa.h"
61 #include "auths/tls.h"
64 auth_info auths_available[] = {
66 /* Checking by an expansion condition on plain text */
70 .driver_name = US"cram_md5", /* lookup name */
71 .options = auth_cram_md5_options,
72 .options_count = &auth_cram_md5_options_count,
73 .options_block = &auth_cram_md5_option_defaults,
74 .options_len = sizeof(auth_cram_md5_options_block),
75 .init = auth_cram_md5_init,
76 .servercode = auth_cram_md5_server,
77 .clientcode = auth_cram_md5_client,
78 .version_report = NULL,
79 .macros_create = NULL,
83 #ifdef AUTH_CYRUS_SASL
85 .driver_name = US"cyrus_sasl",
86 .options = auth_cyrus_sasl_options,
87 .options_count = &auth_cyrus_sasl_options_count,
88 .options_block = &auth_cyrus_sasl_option_defaults,
89 .options_len = sizeof(auth_cyrus_sasl_options_block),
90 .init = auth_cyrus_sasl_init,
91 .servercode = auth_cyrus_sasl_server,
93 .version_report = auth_cyrus_sasl_version_report,
94 .macros_create = NULL,
100 .driver_name = US"dovecot",
101 .options = auth_dovecot_options,
102 .options_count = &auth_dovecot_options_count,
103 .options_block = &auth_dovecot_option_defaults,
104 .options_len = sizeof(auth_dovecot_options_block),
105 .init = auth_dovecot_init,
106 .servercode = auth_dovecot_server,
108 .version_report = NULL,
109 .macros_create = NULL,
115 .driver_name = US"external",
116 .options = auth_external_options,
117 .options_count = &auth_external_options_count,
118 .options_block = &auth_external_option_defaults,
119 .options_len = sizeof(auth_external_options_block),
120 .init = auth_external_init,
121 .servercode = auth_external_server,
122 .clientcode = auth_external_client,
123 .version_report = NULL,
124 .macros_create = NULL,
130 .driver_name = US"gsasl",
131 .options = auth_gsasl_options,
132 .options_count = &auth_gsasl_options_count,
133 .options_block = &auth_gsasl_option_defaults,
134 .options_len = sizeof(auth_gsasl_options_block),
135 .init = auth_gsasl_init,
136 .servercode = auth_gsasl_server,
137 .clientcode = auth_gsasl_client,
138 .version_report = auth_gsasl_version_report,
139 .macros_create = auth_gsasl_macros,
143 #ifdef AUTH_HEIMDAL_GSSAPI
145 .driver_name = US"heimdal_gssapi",
146 .options = auth_heimdal_gssapi_options,
147 .options_count = &auth_heimdal_gssapi_options_count,
148 .options_block = &auth_heimdal_gssapi_option_defaults,
149 .options_len = sizeof(auth_heimdal_gssapi_options_block),
150 .init = auth_heimdal_gssapi_init,
151 .servercode = auth_heimdal_gssapi_server,
153 .version_report = auth_heimdal_gssapi_version_report,
154 .macros_create = NULL,
158 #ifdef AUTH_PLAINTEXT
160 .driver_name = US"plaintext",
161 .options = auth_plaintext_options,
162 .options_count = &auth_plaintext_options_count,
163 .options_block = &auth_plaintext_option_defaults,
164 .options_len = sizeof(auth_plaintext_options_block),
165 .init = auth_plaintext_init,
166 .servercode = auth_plaintext_server,
167 .clientcode = auth_plaintext_client,
168 .version_report = NULL,
169 .macros_create = NULL,
175 .driver_name = US"spa",
176 .options = auth_spa_options,
177 .options_count = &auth_spa_options_count,
178 .options_block = &auth_spa_option_defaults,
179 .options_len = sizeof(auth_spa_options_block),
180 .init = auth_spa_init,
181 .servercode = auth_spa_server,
182 .clientcode = auth_spa_client,
183 .version_report = NULL,
184 .macros_create = NULL,
190 .driver_name = US"tls",
191 .options = auth_tls_options,
192 .options_count = &auth_tls_options_count,
193 .options_block = &auth_tls_option_defaults,
194 .options_len = sizeof(auth_tls_options_block),
195 .init = auth_tls_init,
196 .servercode = auth_tls_server,
198 .version_report = NULL,
199 .macros_create = NULL,
203 { .driver_name = US"" } /* end marker */
207 /* Tables of information about which routers and transports are included in the
210 /* Pull in the necessary header files */
212 #include "routers/rf_functions.h"
215 # include "routers/accept.h"
218 #ifdef ROUTER_DNSLOOKUP
219 # include "routers/dnslookup.h"
222 #ifdef ROUTER_MANUALROUTE
223 # include "routers/manualroute.h"
226 #ifdef ROUTER_IPLITERAL
227 # include "routers/ipliteral.h"
230 #ifdef ROUTER_IPLOOKUP
231 # include "routers/iplookup.h"
234 #ifdef ROUTER_QUERYPROGRAM
235 # include "routers/queryprogram.h"
238 #ifdef ROUTER_REDIRECT
239 # include "routers/redirect.h"
242 #ifdef TRANSPORT_APPENDFILE
243 # include "transports/appendfile.h"
246 #ifdef TRANSPORT_AUTOREPLY
247 # include "transports/autoreply.h"
250 #ifdef TRANSPORT_LMTP
251 # include "transports/lmtp.h"
254 #ifdef TRANSPORT_PIPE
255 # include "transports/pipe.h"
258 #ifdef EXPERIMENTAL_QUEUEFILE
259 # include "transports/queuefile.h"
262 #ifdef TRANSPORT_SMTP
263 # include "transports/smtp.h"
267 /* Now set up the structures, terminated by an entry with a null name. */
269 router_info routers_available[] = {
273 .driver_name = US"accept",
274 .options = accept_router_options,
275 .options_count = &accept_router_options_count,
276 .options_block = &accept_router_option_defaults,
277 .options_len = sizeof(accept_router_options_block),
278 .init = accept_router_init,
280 .code = accept_router_entry,
281 .tidyup = NULL, /* no tidyup entry */
282 .ri_flags = ri_yestransport
285 #ifdef ROUTER_DNSLOOKUP
288 .driver_name = US"dnslookup",
289 .options = dnslookup_router_options,
290 .options_count = &dnslookup_router_options_count,
291 .options_block = &dnslookup_router_option_defaults,
292 .options_len = sizeof(dnslookup_router_options_block),
293 .init = dnslookup_router_init,
295 .code = dnslookup_router_entry,
296 .tidyup = NULL, /* no tidyup entry */
297 .ri_flags = ri_yestransport
300 #ifdef ROUTER_IPLITERAL
303 .driver_name = US"ipliteral",
304 .options = ipliteral_router_options,
305 .options_count = &ipliteral_router_options_count,
306 .options_block = &ipliteral_router_option_defaults,
307 .options_len = sizeof(ipliteral_router_options_block),
308 .init = ipliteral_router_init,
310 .code = ipliteral_router_entry,
311 .tidyup = NULL, /* no tidyup entry */
312 .ri_flags = ri_yestransport
315 #ifdef ROUTER_IPLOOKUP
318 .driver_name = US"iplookup",
319 .options = iplookup_router_options,
320 .options_count = &iplookup_router_options_count,
321 .options_block = &iplookup_router_option_defaults,
322 .options_len = sizeof(iplookup_router_options_block),
323 .init = iplookup_router_init,
325 .code = iplookup_router_entry,
326 .tidyup = NULL, /* no tidyup entry */
327 .ri_flags = ri_notransport
330 #ifdef ROUTER_MANUALROUTE
333 .driver_name = US"manualroute",
334 .options = manualroute_router_options,
335 .options_count = &manualroute_router_options_count,
336 .options_block = &manualroute_router_option_defaults,
337 .options_len = sizeof(manualroute_router_options_block),
338 .init = manualroute_router_init,
340 .code = manualroute_router_entry,
341 .tidyup = NULL, /* no tidyup entry */
345 #ifdef ROUTER_QUERYPROGRAM
348 .driver_name = US"queryprogram",
349 .options = queryprogram_router_options,
350 .options_count = &queryprogram_router_options_count,
351 .options_block = &queryprogram_router_option_defaults,
352 .options_len = sizeof(queryprogram_router_options_block),
353 .init = queryprogram_router_init,
355 .code = queryprogram_router_entry,
356 .tidyup = NULL, /* no tidyup entry */
360 #ifdef ROUTER_REDIRECT
363 .driver_name = US"redirect",
364 .options = redirect_router_options,
365 .options_count = &redirect_router_options_count,
366 .options_block = &redirect_router_option_defaults,
367 .options_len = sizeof(redirect_router_options_block),
368 .init = redirect_router_init,
370 .code = redirect_router_entry,
371 .tidyup = NULL, /* no tidyup entry */
372 .ri_flags = ri_notransport
380 transport_info transports_available[] = {
381 #ifdef TRANSPORT_APPENDFILE
384 .driver_name = US"appendfile",
385 .options = appendfile_transport_options,
386 .options_count = &appendfile_transport_options_count,
387 .options_block = &appendfile_transport_option_defaults, /* private options defaults */
388 .options_len = sizeof(appendfile_transport_options_block),
389 .init = appendfile_transport_init,
391 .code = appendfile_transport_entry,
397 #ifdef TRANSPORT_AUTOREPLY
400 .driver_name = US"autoreply",
401 .options = autoreply_transport_options,
402 .options_count = &autoreply_transport_options_count,
403 .options_block = &autoreply_transport_option_defaults,
404 .options_len = sizeof(autoreply_transport_options_block),
405 .init = autoreply_transport_init,
407 .code = autoreply_transport_entry,
413 #ifdef TRANSPORT_LMTP
416 .driver_name = US"lmtp",
417 .options = lmtp_transport_options,
418 .options_count = &lmtp_transport_options_count,
419 .options_block = &lmtp_transport_option_defaults,
420 .options_len = sizeof(lmtp_transport_options_block),
421 .init = lmtp_transport_init,
423 .code = lmtp_transport_entry,
429 #ifdef TRANSPORT_PIPE
432 .driver_name = US"pipe",
433 .options = pipe_transport_options,
434 .options_count = &pipe_transport_options_count,
435 .options_block = &pipe_transport_option_defaults,
436 .options_len = sizeof(pipe_transport_options_block),
437 .init = pipe_transport_init,
439 .code = pipe_transport_entry,
445 #ifdef EXPERIMENTAL_QUEUEFILE
448 .driver_name = US"queuefile",
449 .options = queuefile_transport_options,
450 .options_count = &queuefile_transport_options_count,
451 .options_block = &queuefile_transport_option_defaults,
452 .options_len = sizeof(queuefile_transport_options_block),
453 .init = queuefile_transport_init,
455 .code = queuefile_transport_entry,
461 #ifdef TRANSPORT_SMTP
464 .driver_name = US"smtp",
465 .options = smtp_transport_options,
466 .options_count = &smtp_transport_options_count,
467 .options_block = &smtp_transport_option_defaults,
468 .options_len = sizeof(smtp_transport_options_block),
469 .init = smtp_transport_init,
471 .code = smtp_transport_entry,
473 .closedown = smtp_transport_closedown,
483 auth_show_supported(gstring * g)
485 g = string_cat(g, US"Authenticators:");
486 for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
487 g = string_fmt_append(g, " %s", ai->driver_name);
488 return string_cat(g, US"\n");
492 route_show_supported(gstring * g)
494 g = string_cat(g, US"Routers:");
495 for (router_info * rr = routers_available; rr->drinfo.driver_name[0]; rr++)
496 g = string_fmt_append(g, " %s", rr->drinfo.driver_name);
497 return string_cat(g, US"\n");
501 transport_show_supported(gstring * g)
503 g = string_cat(g, US"Transports:");
504 #ifdef TRANSPORT_APPENDFILE
505 g = string_cat(g, US" appendfile");
506 #ifdef SUPPORT_MAILDIR
507 g = string_cat(g, US"/maildir"); /* damn these subclasses */
509 #ifdef SUPPORT_MAILSTORE
510 g = string_cat(g, US"/mailstore");
513 g = string_cat(g, US"/mbx");
516 #ifdef TRANSPORT_AUTOREPLY
517 g = string_cat(g, US" autoreply");
519 #ifdef TRANSPORT_LMTP
520 g = string_cat(g, US" lmtp");
522 #ifdef TRANSPORT_PIPE
523 g = string_cat(g, US" pipe");
525 #ifdef EXPERIMENTAL_QUEUEFILE
526 g = string_cat(g, US" queuefile");
528 #ifdef TRANSPORT_SMTP
529 g = string_cat(g, US" smtp");
531 return string_cat(g, US"\n");
536 struct lookupmodulestr
539 struct lookup_module_info *info;
540 struct lookupmodulestr *next;
543 static struct lookupmodulestr *lookupmodules = NULL;
546 addlookupmodule(void *dl, struct lookup_module_info *info)
548 struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), GET_UNTAINTED);
552 p->next = lookupmodules;
554 lookup_list_count += info->lookupcount;
557 /* only valid after lookup_list and lookup_list_count are assigned */
559 add_lookup_to_list(lookup_info *info)
561 /* need to add the lookup to lookup_list, sorted */
564 /* strategy is to go through the list until we find
565 either an empty spot or a name that is higher.
566 this can't fail because we have enough space. */
568 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
571 if (lookup_list[pos])
573 /* need to insert it, so move all the other items up
574 (last slot is still empty, of course) */
576 memmove(&lookup_list[pos+1], &lookup_list[pos],
577 sizeof(lookup_info *) * (lookup_list_count-pos-1));
579 lookup_list[pos] = info;
583 /* These need to be at file level for old versions of gcc (2.95.2 reported),
584 which give parse errors on an extern in function scope. Each entry needs
585 to also be invoked in init_lookup_list() below */
587 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
588 extern lookup_module_info cdb_lookup_module_info;
590 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
591 extern lookup_module_info dbmdb_lookup_module_info;
593 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
594 extern lookup_module_info dnsdb_lookup_module_info;
596 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
597 extern lookup_module_info dsearch_lookup_module_info;
599 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
600 extern lookup_module_info ibase_lookup_module_info;
602 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
603 extern lookup_module_info json_lookup_module_info;
605 #if defined(LOOKUP_LDAP)
606 extern lookup_module_info ldap_lookup_module_info;
608 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
609 extern lookup_module_info lsearch_lookup_module_info;
611 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
612 extern lookup_module_info mysql_lookup_module_info;
614 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
615 extern lookup_module_info nis_lookup_module_info;
617 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
618 extern lookup_module_info nisplus_lookup_module_info;
620 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
621 extern lookup_module_info oracle_lookup_module_info;
623 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
624 extern lookup_module_info passwd_lookup_module_info;
626 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
627 extern lookup_module_info pgsql_lookup_module_info;
629 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
630 extern lookup_module_info redis_lookup_module_info;
632 #if defined(LOOKUP_LMDB)
633 extern lookup_module_info lmdb_lookup_module_info;
635 #if defined(SUPPORT_SPF)
636 extern lookup_module_info spf_lookup_module_info;
638 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
639 extern lookup_module_info sqlite_lookup_module_info;
641 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
642 extern lookup_module_info testdb_lookup_module_info;
644 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
645 extern lookup_module_info whoson_lookup_module_info;
648 extern lookup_module_info readsock_lookup_module_info;
652 init_lookup_list(void)
654 #ifdef LOOKUP_MODULE_DIR
657 int countmodules = 0;
658 int moduleerrors = 0;
660 static BOOL lookup_list_init_done = FALSE;
663 if (lookup_list_init_done)
665 reset_point = store_mark();
666 lookup_list_init_done = TRUE;
668 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
669 addlookupmodule(NULL, &cdb_lookup_module_info);
672 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
673 addlookupmodule(NULL, &dbmdb_lookup_module_info);
676 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
677 addlookupmodule(NULL, &dnsdb_lookup_module_info);
680 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
681 addlookupmodule(NULL, &dsearch_lookup_module_info);
684 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
685 addlookupmodule(NULL, &ibase_lookup_module_info);
689 addlookupmodule(NULL, &ldap_lookup_module_info);
692 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
693 addlookupmodule(NULL, &json_lookup_module_info);
696 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
697 addlookupmodule(NULL, &lsearch_lookup_module_info);
700 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
701 addlookupmodule(NULL, &mysql_lookup_module_info);
704 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
705 addlookupmodule(NULL, &nis_lookup_module_info);
708 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
709 addlookupmodule(NULL, &nisplus_lookup_module_info);
712 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
713 addlookupmodule(NULL, &oracle_lookup_module_info);
716 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
717 addlookupmodule(NULL, &passwd_lookup_module_info);
720 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
721 addlookupmodule(NULL, &pgsql_lookup_module_info);
724 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
725 addlookupmodule(NULL, &redis_lookup_module_info);
729 addlookupmodule(NULL, &lmdb_lookup_module_info);
733 addlookupmodule(NULL, &spf_lookup_module_info);
736 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
737 addlookupmodule(NULL, &sqlite_lookup_module_info);
740 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
741 addlookupmodule(NULL, &testdb_lookup_module_info);
744 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
745 addlookupmodule(NULL, &whoson_lookup_module_info);
748 addlookupmodule(NULL, &readsock_lookup_module_info);
750 #ifdef LOOKUP_MODULE_DIR
751 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
753 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
754 log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
758 const pcre2_code * regex_islookupmod = regex_must_compile(
759 US"\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
761 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
762 while ((ent = readdir(dd)))
764 char * name = ent->d_name;
765 int len = (int)strlen(name);
766 if (regex_match(regex_islookupmod, US name, len, NULL))
768 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
770 struct lookup_module_info *info;
771 const char *errormsg;
773 /* SRH: am I being paranoid here or what? */
774 if (pathnamelen > big_buffer_size)
776 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
777 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
781 /* SRH: snprintf here? */
782 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
784 if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
786 errormsg = dlerror();
787 fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
788 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
793 /* FreeBSD nsdispatch() can trigger dlerror() errors about
794 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
795 state before calling dlsym(), so that any error afterwards only comes
798 errormsg = dlerror();
800 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
801 if ((errormsg = dlerror()))
803 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
804 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
809 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
811 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
812 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
818 addlookupmodule(dl, info);
819 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
823 store_free((void*)regex_islookupmod);
827 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
830 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
832 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
833 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
835 /* now add all lookups to the real list */
836 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
837 for (int j = 0; j < p->info->lookupcount; j++)
838 add_lookup_to_list(p->info->lookups[j]);
839 store_reset(reset_point);
840 /* just to be sure */
841 lookupmodules = NULL;
844 #endif /*!MACRO_PREDEF*/
845 /* End of drtables.c */