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