xref: /netbsd-src/external/ibm-public/postfix/dist/src/postconf/postconf_lookup.c (revision 67b9b338a7386232ac596b5fd0cd5a9cc8a03c71)
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