xref: /netbsd-src/external/ibm-public/postfix/dist/src/postconf/postconf_lookup.c (revision 80d9064ac03cbb6a4174695f0d5b237c8766d3d0)
1 /*	$NetBSD: postconf_lookup.c,v 1.1.1.2 2014/07/06 19:27:53 tron 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 /*	Null buffer pointer, or pointer to user-supplied buffer.
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 
80 /* System library. */
81 
82 #include <sys_defs.h>
83 #include <string.h>
84 
85 /* Utility library. */
86 
87 #include <msg.h>
88 #include <mymalloc.h>
89 #include <vstring.h>
90 #include <dict.h>
91 #include <stringops.h>
92 #include <mac_expand.h>
93 
94 /* Global library. */
95 
96 #include <mail_conf.h>
97 
98 /* Application-specific. */
99 
100 #include <postconf.h>
101 
102 #define STR(x) vstring_str(x)
103 
104 /* pcf_lookup_parameter_value - look up specific parameter value */
105 
106 const char *pcf_lookup_parameter_value(int mode, const char *name,
107 				               PCF_MASTER_ENT *local_scope,
108 				               PCF_PARAM_NODE *node)
109 {
110     const char *value = 0;
111 
112     /*
113      * Local name=value entries in master.cf take precedence over global
114      * name=value entries in main.cf. Built-in defaults have the lowest
115      * precedence.
116      */
117     if ((mode & PCF_SHOW_DEFS) != 0
118 	|| ((local_scope == 0 || local_scope->all_params == 0
119 	     || (value = dict_get(local_scope->all_params, name)) == 0)
120 	    && (value = dict_lookup(CONFIG_DICT, name)) == 0
121 	    && (mode & PCF_SHOW_NONDEF) == 0)) {
122 	if (node != 0 || (node = PCF_PARAM_TABLE_FIND(pcf_param_table, name)) != 0)
123 	    value = pcf_convert_param_node(PCF_SHOW_DEFS, name, node);
124     }
125     return (value);
126 }
127 
128  /*
129   * Data structure to pass private state while recursively expanding $name in
130   * parameter values.
131   */
132 typedef struct {
133     int     mode;
134     PCF_MASTER_ENT *local_scope;
135 } PCF_EVAL_CTX;
136 
137 /* pcf_lookup_parameter_value_wrapper - macro parser call-back routine */
138 
139 static const char *pcf_lookup_parameter_value_wrapper(const char *key,
140 						            int unused_type,
141 						              char *context)
142 {
143     PCF_EVAL_CTX *cp = (PCF_EVAL_CTX *) context;
144 
145     return (pcf_lookup_parameter_value(cp->mode, key, cp->local_scope,
146 				       (PCF_PARAM_NODE *) 0));
147 }
148 
149 /* pcf_expand_parameter_value - expand $name in parameter value */
150 
151 char   *pcf_expand_parameter_value(VSTRING *buf, int mode, const char *value,
152 				           PCF_MASTER_ENT *local_scope)
153 {
154     const char *myname = "pcf_expand_parameter_value";
155     static VSTRING *local_buf;
156     int     status;
157     PCF_EVAL_CTX eval_ctx;
158 
159     /*
160      * Initialize.
161      */
162     if (buf == 0) {
163 	if (local_buf == 0)
164 	    local_buf = vstring_alloc(10);
165 	buf = local_buf;
166     }
167 
168     /*
169      * Expand macros recursively.
170      *
171      * When expanding $name in "postconf -n" parameter values, don't limit the
172      * search to only non-default parameter values.
173      *
174      * When expanding $name in "postconf -d" parameter values, do limit the
175      * search to only default parameter values.
176      */
177 #define DONT_FILTER (char *) 0
178 
179     eval_ctx.mode = (mode & ~PCF_SHOW_NONDEF);
180     eval_ctx.local_scope = local_scope;
181     status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER,
182 		    pcf_lookup_parameter_value_wrapper, (char *) &eval_ctx);
183     if (status & MAC_PARSE_ERROR)
184 	msg_fatal("macro processing error");
185     if (msg_verbose > 1) {
186 	if (strcmp(value, STR(buf)) != 0)
187 	    msg_info("%s: expand %s -> %s", myname, value, STR(buf));
188 	else
189 	    msg_info("%s: const  %s", myname, value);
190     }
191     return (STR(buf));
192 }
193