postconf_lookup.c revision 1.4
1/*	$NetBSD: postconf_lookup.c,v 1.4 2022/10/08 16:12:47 christos Exp $	*/
2
3/*++
4/* NAME
5/*	postconf_lookup 3
6/* SUMMARY
7/*	parameter lookup routines
8/* SYNOPSIS
9/*	#include <postconf.h>
10/*
11/*	const char *pcf_lookup_parameter_value(mode, name, local_scope, node)
12/*	int	mode;
13/*	const char *name;
14/*	PCF_MASTER_ENT *local_scope;
15/*	PCF_PARAM_NODE *node;
16/*
17/*	char    *pcf_expand_parameter_value(buf, mode, value, local_scope)
18/*	VSTRING *buf;
19/*	int	mode;
20/*	const char *value;
21/*	PCF_MASTER_ENT *local_scope;
22/* DESCRIPTION
23/*	These functions perform parameter value lookups.  The order
24/*	of decreasing precedence is:
25/* .IP \(bu
26/*	Search name=value parameter settings in master.cf.  These
27/*	lookups are disabled with the PCF_SHOW_DEFS flag.
28/* .IP \(bu
29/*	Search name=value parameter settings in main.cf.  These
30/*	lookups are disabled with the PCF_SHOW_DEFS flag.
31/* .IP \(bu
32/*	Search built-in default parameter settings. These lookups
33/*	are disabled with the PCF_SHOW_NONDEF flag.
34/* .PP
35/*	pcf_lookup_parameter_value() looks up the value for the
36/*	named parameter, and returns null if the name was not found.
37/*
38/*	pcf_expand_parameter_value() expands $name in the specified
39/*	parameter value. This function ignores the PCF_SHOW_NONDEF
40/*	flag.  The result value is a pointer to storage in a
41/*	user-supplied buffer, or in a buffer that is overwritten
42/*	with each call.
43/*
44/*	Arguments:
45/* .IP buf
46/*	Pointer to user-supplied buffer; must not be null.
47/* .IP mode
48/*	Bit-wise OR of zero or one of the following (other flags
49/*	are ignored):
50/* .RS
51/* .IP PCF_SHOW_DEFS
52/*	Search built-in default parameter settings only.
53/* .IP PCF_SHOW_NONDEF
54/*	Search local (master.cf) and global (main.cf) name=value
55/*	parameter settings only.
56/* .RE
57/* .IP name
58/*	The name of a parameter to be looked up.
59/* .IP value
60/*	The parameter value where $name should be expanded.
61/* .IP local_scope
62/*	Pointer to master.cf entry with local name=value settings,
63/*	or a null pointer (i.e. no local parameter lookup).
64/* .IP node
65/*	Global default value for the named parameter, or a null
66/*	pointer (i.e. do the global default lookup anyway).
67/* DIAGNOSTICS
68/*	Problems are reported to the standard error stream.
69/* LICENSE
70/* .ad
71/* .fi
72/*	The Secure Mailer license must be distributed with this software.
73/* AUTHOR(S)
74/*	Wietse Venema
75/*	IBM T.J. Watson Research
76/*	P.O. Box 704
77/*	Yorktown Heights, NY 10598, USA
78/*
79/*	Wietse Venema
80/*	Google, Inc.
81/*	111 8th Avenue
82/*	New York, NY 10011, USA
83/*--*/
84
85/* System library. */
86
87#include <sys_defs.h>
88#include <string.h>
89
90/* Utility library. */
91
92#include <msg.h>
93#include <mymalloc.h>
94#include <vstring.h>
95#include <dict.h>
96#include <stringops.h>
97#include <mac_expand.h>
98
99/* Global library. */
100
101#include <mail_conf.h>
102
103/* Application-specific. */
104
105#include <postconf.h>
106
107#define STR(x) vstring_str(x)
108
109/* pcf_lookup_parameter_value - look up specific parameter value */
110
111const char *pcf_lookup_parameter_value(int mode, const char *name,
112				               PCF_MASTER_ENT *local_scope,
113				               PCF_PARAM_NODE *node)
114{
115    const char *value = 0;
116
117#define LOOKUP(dict, name) ((dict) ? dict_get((dict), (name)) : 0)
118
119    /*
120     * Local name=value entries in master.cf take precedence over global
121     * name=value entries in main.cf. Built-in defaults have the lowest
122     * precedence.
123     */
124    if ((mode & PCF_SHOW_DEFS) != 0
125	|| ((local_scope == 0
126	     || ((value = LOOKUP(local_scope->ro_params, name)) == 0
127		 && (value = LOOKUP(local_scope->all_params, name)) == 0))
128	    && (value = dict_lookup(CONFIG_DICT, name)) == 0
129	    && (mode & PCF_SHOW_NONDEF) == 0)) {
130	if (node != 0 || (node = PCF_PARAM_TABLE_FIND(pcf_param_table, name)) != 0)
131	    value = pcf_convert_param_node(PCF_SHOW_DEFS, name, node);
132    }
133    return (value);
134}
135
136 /*
137  * Data structure to pass private state while recursively expanding $name in
138  * parameter values.
139  */
140typedef struct {
141    int     mode;
142    PCF_MASTER_ENT *local_scope;
143} PCF_EVAL_CTX;
144
145/* pcf_lookup_parameter_value_wrapper - macro parser call-back routine */
146
147static const char *pcf_lookup_parameter_value_wrapper(const char *key,
148						            int unused_type,
149						              void *context)
150{
151    PCF_EVAL_CTX *cp = (PCF_EVAL_CTX *) context;
152
153    return (pcf_lookup_parameter_value(cp->mode, key, cp->local_scope,
154				       (PCF_PARAM_NODE *) 0));
155}
156
157/* pcf_expand_parameter_value - expand $name in parameter value */
158
159char   *pcf_expand_parameter_value(VSTRING *buf, int mode, const char *value,
160				           PCF_MASTER_ENT *local_scope)
161{
162    const char *myname = "pcf_expand_parameter_value";
163    int     status;
164    PCF_EVAL_CTX eval_ctx;
165
166    /*
167     * Sanity check.
168     */
169    if (buf == 0)
170	msg_panic("%s: null buffer pointer", myname);
171
172    /*
173     * Expand macros recursively.
174     *
175     * When expanding $name in "postconf -n" parameter values, don't limit the
176     * search to only non-default parameter values.
177     *
178     * When expanding $name in "postconf -d" parameter values, do limit the
179     * search to only default parameter values.
180     */
181#define DONT_FILTER (char *) 0
182
183    eval_ctx.mode = (mode & ~PCF_SHOW_NONDEF);
184    eval_ctx.local_scope = local_scope;
185    status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER,
186		    pcf_lookup_parameter_value_wrapper, (void *) &eval_ctx);
187    if (status & MAC_PARSE_ERROR)
188	msg_fatal("macro processing error");
189    if (msg_verbose > 1) {
190	if (strcmp(value, STR(buf)) != 0)
191	    msg_info("%s: expand %s -> %s", myname, value, STR(buf));
192	else
193	    msg_info("%s: const  %s", myname, value);
194    }
195    return (STR(buf));
196}
197