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