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