1/*++
2/* NAME
3/*	postconf_node 3
4/* SUMMARY
5/*	low-level parameter node support
6/* SYNOPSIS
7/*	#include <postconf.h>
8/*
9/*	PCF_PARAM_TABLE *PCF_PARAM_TABLE_CREATE(size)
10/*	ssize_t	size;
11/*
12/*	PCF_PARAM_INFO **PCF_PARAM_TABLE_LIST(table)
13/*	PCF_PARAM_TABLE *table;
14/*
15/*	const char *PCF_PARAM_INFO_NAME(info)
16/*	PCF_PARAM_INFO *info;
17/*
18/*	PCF_PARAM_NODE *PCF_PARAM_INFO_NODE(info)
19/*	PCF_PARAM_INFO *info;
20/*
21/*	PCF_PARAM_NODE *PCF_PARAM_TABLE_FIND(table, name)
22/*	PCF_PARAM_TABLE *table;
23/*	const char *name;
24/*
25/*	PCF_PARAM_INFO *PCF_PARAM_TABLE_LOCATE(table, name)
26/*	PCF_PARAM_TABLE *table;
27/*	const char *name;
28/*
29/*	PCF_PARAM_INFO *PCF_PARAM_TABLE_ENTER(table, name, flags,
30/*						param_data, convert_fn)
31/*	PCF_PARAM_TABLE *table;
32/*	const char *name;
33/*	int	flags;
34/*	char	*param_data;
35/*	const char *(*convert_fn)(char *);
36/*
37/*	PCF_PARAM_NODE *pcf_make_param_node(flags, param_data, convert_fn)
38/*	int	flags;
39/*	char	*param_data;
40/*	const char *(*convert_fn) (char *);
41/*
42/*	const char *pcf_convert_param_node(mode, name, node)
43/*	int	mode;
44/*	const char *name;
45/*	PCF_PARAM_NODE *node;
46/*
47/*	VSTRING *pcf_param_string_buf;
48/*
49/*	PCF_RAW_PARAMETER(node)
50/*	const PCF_PARAM_NODE *node;
51/* DESCRIPTION
52/*	This module maintains data structures (PCF_PARAM_NODE) with
53/*	information about known-legitimate parameters.  These data
54/*	structures are stored in a hash table.
55/*
56/*	The PCF_PARAM_MUMBLE() macros are wrappers around the
57/*	htable(3) module. Their sole purpose is to encapsulate all
58/*	the pointer casting from and to (PCF_PARAM_NODE *). Apart
59/*	from that, the macros have no features worth discussing.
60/*
61/*	pcf_make_param_node() creates a node for the global parameter
62/*	table. This node provides a parameter default value, and a
63/*	function that converts the default value to string.
64/*
65/*	pcf_convert_param_node() produces a string representation
66/*	for a global parameter default value.
67/*
68/*	PCF_RAW_PARAMETER() returns non-zero if the specified
69/*	parameter node represents a "raw parameter". The value of
70/*	such parameters must not be scanned for macro names.  Some
71/*	"raw parameter" values contain "$" without macros, such as
72/*	the smtpd_expansion_filter "safe character" set; and some
73/*	contain $name from a private name space, such as forward_path.
74/*	Some "raw parameter" values in postscreen(8) are safe to
75/*	expand by one level.  Support for that may be added later.
76/*
77/*	pcf_param_string_buf is a buffer that is initialized on the
78/*	fly and that parameter-to-string conversion functions may
79/*	use for temporary result storage.
80/*
81/*	Arguments:
82/* .IP size
83/*	The initial size of the hash table.
84/* .IP table
85/*	A hash table for storage of "valid parameter" information.
86/* .IP info
87/*	A data structure with a name component and a PCF_PARAM_NODE
88/*	component. Use PCF_PARAM_INFO_NAME() and PCF_PARAM_INFO_NODE()
89/*	to access these components.
90/* .IP name
91/*	The name of a "valid parameter".
92/* .IP flags
93/*	PCF_PARAM_FLAG_RAW for a "raw parameter", PCF_PARAM_FLAG_NONE
94/*	otherwise. See the PCF_RAW_PARAMETER() discussion above for
95/*	discussion of "raw parameter" values.
96/* .IP param_data
97/*	Information about the parameter value.  Specify PCF_PARAM_NO_DATA
98/*	if this is not applicable.
99/* .IP convert_fn
100/*	The function that will be invoked to produce a string
101/*	representation of the information in param_data. The function
102/*	receives the param_data value as argument.
103/* .IP mode
104/*	For now, the PCF_SHOW_DEFS flag is required.
105/* .IP name
106/*	The name of the parameter whose value is requested.  This
107/*	is used for diagnostics.
108/* .IP node
109/*	The (flags, param_data, convert_fn) information that needs
110/*	to be converted to a string representation of the default
111/*	value.
112/* DIAGNOSTICS
113/*	Problems are reported to the standard error stream.
114/* LICENSE
115/* .ad
116/* .fi
117/*	The Secure Mailer license must be distributed with this software.
118/* AUTHOR(S)
119/*	Wietse Venema
120/*	IBM T.J. Watson Research
121/*	P.O. Box 704
122/*	Yorktown Heights, NY 10598, USA
123/*--*/
124
125
126/* System library. */
127
128#include <sys_defs.h>
129
130/* Utility library. */
131
132#include <msg.h>
133#include <mymalloc.h>
134#include <vstring.h>
135
136/* Application-specific. */
137
138#include <postconf.h>
139
140VSTRING *pcf_param_string_buf;
141
142/* pcf_make_param_node - make node for global parameter table */
143
144PCF_PARAM_NODE *pcf_make_param_node(int flags, char *param_data,
145				         const char *(*convert_fn) (char *))
146{
147    PCF_PARAM_NODE *node;
148
149    node = (PCF_PARAM_NODE *) mymalloc(sizeof(*node));
150    node->flags = flags;
151    node->param_data = param_data;
152    node->convert_fn = convert_fn;
153    return (node);
154}
155
156/* pcf_convert_param_node - get default parameter value */
157
158const char *pcf_convert_param_node(int mode, const char *name, PCF_PARAM_NODE *node)
159{
160    const char *myname = "pcf_convert_param_node";
161    const char *value;
162
163    /*
164     * One-off initialization.
165     */
166    if (pcf_param_string_buf == 0)
167	pcf_param_string_buf = vstring_alloc(100);
168
169    /*
170     * Sanity check. A null value indicates that a parameter does not have
171     * the requested value. At this time, the only requested value can be the
172     * default value, and a null pointer value makes no sense here.
173     */
174    if ((mode & PCF_SHOW_DEFS) == 0)
175	msg_panic("%s: request for non-default value of parameter %s",
176		  myname, name);
177    if ((value = node->convert_fn(node->param_data)) == 0)
178	msg_panic("%s: parameter %s has null pointer default value",
179		  myname, name);
180
181    /*
182     * Return the parameter default value.
183     */
184    return (value);
185}
186