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
pcf_lookup_parameter_value(int mode,const char * name,PCF_MASTER_ENT * local_scope,PCF_PARAM_NODE * node)111 const 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 */
140 typedef 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
pcf_lookup_parameter_value_wrapper(const char * key,int unused_type,void * context)147 static 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
pcf_expand_parameter_value(VSTRING * buf,int mode,const char * value,PCF_MASTER_ENT * local_scope)159 char *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