postconf_dbms.c revision 1.1
1/* $NetBSD: postconf_dbms.c,v 1.1 2013/01/02 18:59:03 tron Exp $ */ 2 3/*++ 4/* NAME 5/* postconf_dbms 3 6/* SUMMARY 7/* legacy support for database-defined main.cf parameter names 8/* SYNOPSIS 9/* #include <postconf.h> 10/* 11/* void register_dbms_parameters(param_value, flag_parameter, 12/* local_scope) 13/* const char *param_value; 14/* const char *(flag_parameter) (const char *, int, char *); 15/* PC_MASTER_ENT *local_scope; 16/* DESCRIPTION 17/* This module implements legacy support for database configuration 18/* where main.cf parameter names are generated by prepending 19/* the database name to a database-defined suffix. 20/* 21/* Arguments: 22/* .IP param_value 23/* A parameter value to be searched for "type:table" strings. 24/* When a database type is found that supports legacy-style 25/* configuration, the table name is combined with each of the 26/* database-defined suffixes to generate candidate parameter 27/* names for that database type. 28/* .IP flag_parameter 29/* A function that takes as arguments a candidate parameter 30/* name, an unused value, and a local namespace pointer. The 31/* function will flag the parameter as "used" if it has a 32/* "name=value" entry in the local or global namespace. 33/* .IP local_scope 34/* The local namespace. 35/* DIAGNOSTICS 36/* No explicit diagnostics. 37/* LICENSE 38/* .ad 39/* .fi 40/* The Secure Mailer license must be distributed with this software. 41/* AUTHOR(S) 42/* Wietse Venema 43/* IBM T.J. Watson Research 44/* P.O. Box 704 45/* Yorktown Heights, NY 10598, USA 46/*--*/ 47 48/* System library. */ 49 50#include <sys_defs.h> 51#include <string.h> 52 53/* Utility library. */ 54 55#include <stringops.h> 56#include <split_at.h> 57#include <mac_expand.h> 58#include <dict.h> 59 60/* Global library. */ 61 62#include <mail_conf.h> 63#include <dict_proxy.h> 64#include <dict_ldap.h> 65#include <dict_mysql.h> 66#include <dict_pgsql.h> 67#include <dict_sqlite.h> 68#include <dict_memcache.h> 69 70/* Application-specific. */ 71 72#include <postconf.h> 73 74 /* 75 * SLMs. 76 */ 77#define STR(x) vstring_str(x) 78 79#ifdef LEGACY_DBMS_SUPPORT 80 81 /* 82 * The legacy database interface automagically instantiates a list of 83 * parameters by prepending the table name to database-specific suffixes. 84 */ 85 86/* See ldap_table(5). */ 87 88static const char *ldap_suffixes[] = { 89 "bind", "bind_dn", "bind_pw", "cache", "cache_expiry", "cache_size", 90 "chase_referrals", "debuglevel", "dereference", "domain", 91 "expansion_limit", "leaf_result_attribute", "query_filter", 92 "recursion_limit", "result_attribute", "result_format", "scope", 93 "search_base", "server_host", "server_port", "size_limit", 94 "special_result_attribute", "terminal_result_attribute", 95 "timeout", "version", 0, 96}; 97 98/* See mysql_table(5). */ 99 100static const char *mysql_suffixes[] = { 101 "additional_conditions", "dbname", "domain", "expansion_limit", 102 "hosts", "password", "query", "result_format", "select_field", 103 "table", "user", "where_field", 0, 104}; 105 106/* See pgsql_table(5). */ 107 108static const char *pgsql_suffixes[] = { 109 "additional_conditions", "dbname", "domain", "expansion_limit", 110 "hosts", "password", "query", "result_format", "select_field", 111 "select_function", "table", "user", "where_field", 0, 112}; 113 114/* See sqlite_table(5). */ 115 116static const char *sqlite_suffixes[] = { 117 "additional_conditions", "dbpath", "domain", "expansion_limit", 118 "query", "result_format", "select_field", "table", "where_field", 119 0, 120}; 121 122/* See memcache_table(5). */ 123 124static const char *memcache_suffixes[] = { 125 "backup", "data_size_limit", "domain", "flags", "key_format", 126 "line_size_limit", "max_try", "memcache", "retry_pause", 127 "timeout", "ttl", 0, 128}; 129 130 /* 131 * Bundle up the database types and their suffix lists. 132 */ 133typedef struct { 134 const char *db_type; 135 const char **db_suffixes; 136} PC_DBMS_INFO; 137 138static const PC_DBMS_INFO dbms_info[] = { 139 DICT_TYPE_LDAP, ldap_suffixes, 140 DICT_TYPE_MYSQL, mysql_suffixes, 141 DICT_TYPE_PGSQL, pgsql_suffixes, 142 DICT_TYPE_SQLITE, sqlite_suffixes, 143 DICT_TYPE_MEMCACHE, memcache_suffixes, 144 0, 145}; 146 147/* register_dbms_parameters_cb - mac_expand() call-back */ 148 149static const char *register_dbms_parameters_cb(const char *mac_name, 150 int unused_mode, 151 char *context) 152{ 153 PC_MASTER_ENT *local_scope = (PC_MASTER_ENT *) context; 154 const char *mac_val; 155 156 /* 157 * Local namespace "name=value" settings are always explicit. They have 158 * precedence over global namespace "name=value" settings which are 159 * either explicit or defined by their default value. 160 */ 161 if (local_scope == 0 162 || (mac_val = dict_get(local_scope->all_params, mac_name)) == 0) 163 mac_val = mail_conf_lookup(mac_name); 164 return (mac_val); 165} 166 167/* register_dbms_parameters - look for database_type:prefix_name */ 168 169void register_dbms_parameters(const char *param_value, 170 const char *(flag_parameter) (const char *, int, char *), 171 PC_MASTER_ENT *local_scope) 172{ 173 const PC_DBMS_INFO *dp; 174 char *bufp; 175 char *db_type; 176 char *prefix; 177 static VSTRING *buffer = 0; 178 static VSTRING *candidate = 0; 179 const char **cpp; 180 181 /* 182 * Emulate Postfix parameter value expansion, prepending the appropriate 183 * local (master.cf "-o name-value") namespace to the global (main.cf 184 * "name=value") namespace. 185 * 186 * XXX This does not examine both sides of conditional macro expansion, and 187 * may expand the "wrong" conditional macros. This is the best we can do 188 * for legacy database configuration support. 189 */ 190#define NO_SCAN_FILTER ((char *) 0) 191 192 (void) mac_expand(buffer ? buffer : (buffer = vstring_alloc(100)), 193 param_value, MAC_EXP_FLAG_RECURSE, NO_SCAN_FILTER, 194 register_dbms_parameters_cb, (char *) local_scope); 195 196 /* 197 * Naive parsing. We don't really know if the parameter specifies free 198 * text or a list of databases. 199 */ 200 bufp = STR(buffer); 201 while ((db_type = mystrtok(&bufp, " ,\t\r\n")) != 0) { 202 203 /* 204 * Skip over "proxy:" indirections. 205 */ 206 while ((prefix = split_at(db_type, ':')) != 0 207 && strcmp(db_type, DICT_TYPE_PROXY) == 0) 208 db_type = prefix; 209 210 /* 211 * Look for database:prefix where the prefix is not a pathname and 212 * the database is a known type. Synthesize candidate parameter names 213 * from the user-defined prefix and from the database-defined suffix 214 * list, and see if those parameters have a "name=value" entry in the 215 * local or global namespace. 216 */ 217 if (prefix != 0 && *prefix != '/' && *prefix != '.') { 218 for (dp = dbms_info; dp->db_type != 0; dp++) { 219 if (strcmp(db_type, dp->db_type) == 0) { 220 for (cpp = dp->db_suffixes; *cpp; cpp++) { 221 vstring_sprintf(candidate ? candidate : 222 (candidate = vstring_alloc(30)), 223 "%s_%s", prefix, *cpp); 224 flag_parameter(STR(candidate), 0, (char *) local_scope); 225 } 226 break; 227 } 228 } 229 } 230 } 231} 232 233#endif 234