summaryrefslogtreecommitdiffstats
path: root/src/postconf/postconf_lookup.c
blob: 3cfa9f3b0473ec9aeba7c92b9ad9d117590a43c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*++
/* NAME
/*	postconf_lookup 3
/* SUMMARY
/*	parameter lookup routines
/* SYNOPSIS
/*	#include <postconf.h>
/*
/*	const char *pcf_lookup_parameter_value(mode, name, local_scope, node)
/*	int	mode;
/*	const char *name;
/*	PCF_MASTER_ENT *local_scope;
/*	PCF_PARAM_NODE *node;
/*
/*	char    *pcf_expand_parameter_value(buf, mode, value, local_scope)
/*	VSTRING *buf;
/*	int	mode;
/*	const char *value;
/*	PCF_MASTER_ENT *local_scope;
/* DESCRIPTION
/*	These functions perform parameter value lookups.  The order
/*	of decreasing precedence is:
/* .IP \(bu
/*	Search name=value parameter settings in master.cf.  These
/*	lookups are disabled with the PCF_SHOW_DEFS flag.
/* .IP \(bu
/*	Search name=value parameter settings in main.cf.  These
/*	lookups are disabled with the PCF_SHOW_DEFS flag.
/* .IP \(bu
/*	Search built-in default parameter settings. These lookups
/*	are disabled with the PCF_SHOW_NONDEF flag.
/* .PP
/*	pcf_lookup_parameter_value() looks up the value for the
/*	named parameter, and returns null if the name was not found.
/*
/*	pcf_expand_parameter_value() expands $name in the specified
/*	parameter value. This function ignores the PCF_SHOW_NONDEF
/*	flag.  The result value is a pointer to storage in a
/*	user-supplied buffer, or in a buffer that is overwritten
/*	with each call.
/*
/*	Arguments:
/* .IP buf
/*	Null buffer pointer, or pointer to user-supplied buffer.
/* .IP mode
/*	Bit-wise OR of zero or one of the following (other flags
/*	are ignored):
/* .RS
/* .IP PCF_SHOW_DEFS
/*	Search built-in default parameter settings only.
/* .IP PCF_SHOW_NONDEF
/*	Search local (master.cf) and global (main.cf) name=value
/*	parameter settings only.
/* .RE
/* .IP name
/*	The name of a parameter to be looked up.
/* .IP value
/*	The parameter value where $name should be expanded.
/* .IP local_scope
/*	Pointer to master.cf entry with local name=value settings,
/*	or a null pointer (i.e. no local parameter lookup).
/* .IP node
/*	Global default value for the named parameter, or a null
/*	pointer (i.e. do the global default lookup anyway).
/* DIAGNOSTICS
/*	Problems are reported to the standard error stream.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*
/*	Wietse Venema
/*	Google, Inc.
/*	111 8th Avenue
/*	New York, NY 10011, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <string.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <vstring.h>
#include <dict.h>
#include <stringops.h>
#include <mac_expand.h>

/* Global library. */

#include <mail_conf.h>

/* Application-specific. */

#include <postconf.h>

#define STR(x) vstring_str(x)

/* pcf_lookup_parameter_value - look up specific parameter value */

const char *pcf_lookup_parameter_value(int mode, const char *name,
				               PCF_MASTER_ENT *local_scope,
				               PCF_PARAM_NODE *node)
{
    const char *value = 0;

#define LOOKUP(dict, name) ((dict) ? dict_get((dict), (name)) : 0)

    /*
     * Local name=value entries in master.cf take precedence over global
     * name=value entries in main.cf. Built-in defaults have the lowest
     * precedence.
     */
    if ((mode & PCF_SHOW_DEFS) != 0
	|| ((local_scope == 0
	     || ((value = LOOKUP(local_scope->ro_params, name)) == 0
		 && (value = LOOKUP(local_scope->all_params, name)) == 0))
	    && (value = dict_lookup(CONFIG_DICT, name)) == 0
	    && (mode & PCF_SHOW_NONDEF) == 0)) {
	if (node != 0 || (node = PCF_PARAM_TABLE_FIND(pcf_param_table, name)) != 0)
	    value = pcf_convert_param_node(PCF_SHOW_DEFS, name, node);
    }
    return (value);
}

 /*
  * Data structure to pass private state while recursively expanding $name in
  * parameter values.
  */
typedef struct {
    int     mode;
    PCF_MASTER_ENT *local_scope;
} PCF_EVAL_CTX;

/* pcf_lookup_parameter_value_wrapper - macro parser call-back routine */

static const char *pcf_lookup_parameter_value_wrapper(const char *key,
						            int unused_type,
						              void *context)
{
    PCF_EVAL_CTX *cp = (PCF_EVAL_CTX *) context;

    return (pcf_lookup_parameter_value(cp->mode, key, cp->local_scope,
				       (PCF_PARAM_NODE *) 0));
}

/* pcf_expand_parameter_value - expand $name in parameter value */

char   *pcf_expand_parameter_value(VSTRING *buf, int mode, const char *value,
				           PCF_MASTER_ENT *local_scope)
{
    const char *myname = "pcf_expand_parameter_value";
    static VSTRING *local_buf;
    int     status;
    PCF_EVAL_CTX eval_ctx;

    /*
     * Initialize.
     */
    if (buf == 0) {
	if (local_buf == 0)
	    local_buf = vstring_alloc(10);
	buf = local_buf;
    }

    /*
     * Expand macros recursively.
     * 
     * When expanding $name in "postconf -n" parameter values, don't limit the
     * search to only non-default parameter values.
     * 
     * When expanding $name in "postconf -d" parameter values, do limit the
     * search to only default parameter values.
     */
#define DONT_FILTER (char *) 0

    eval_ctx.mode = (mode & ~PCF_SHOW_NONDEF);
    eval_ctx.local_scope = local_scope;
    status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER,
		    pcf_lookup_parameter_value_wrapper, (void *) &eval_ctx);
    if (status & MAC_PARSE_ERROR)
	msg_fatal("macro processing error");
    if (msg_verbose > 1) {
	if (strcmp(value, STR(buf)) != 0)
	    msg_info("%s: expand %s -> %s", myname, value, STR(buf));
	else
	    msg_info("%s: const  %s", myname, value);
    }
    return (STR(buf));
}