1/*++ 2/* NAME 3/* postconf_match 3 4/* SUMMARY 5/* pattern-matching support 6/* SYNOPSIS 7/* #include <postconf.h> 8/* 9/* int pcf_parse_field_pattern(field_expr) 10/* char *field_expr; 11/* 12/* const char *pcf_str_field_pattern(field_pattern) 13/* int field_pattern; 14/* 15/* int pcf_is_magic_field_pattern(field_pattern) 16/* int field_pattern; 17/* 18/* ARGV *pcf_parse_service_pattern(service_expr, min_expr, max_expr) 19/* const char *service_expr; 20/* int min_expr; 21/* int max_expr; 22/* 23/* int PCF_IS_MAGIC_SERVICE_PATTERN(service_pattern) 24/* const ARGV *service_pattern; 25/* 26/* int PCF_MATCH_SERVICE_PATTERN(service_pattern, service_name, 27/* service_type) 28/* const ARGV *service_pattern; 29/* const char *service_name; 30/* const char *service_type; 31/* 32/* const char *pcf_str_field_pattern(field_pattern) 33/* int field_pattern; 34/* 35/* int PCF_IS_MAGIC_PARAM_PATTERN(param_pattern) 36/* const char *param_pattern; 37/* 38/* int PCF_MATCH_PARAM_PATTERN(param_pattern, param_name) 39/* const char *param_pattern; 40/* const char *param_name; 41/* DESCRIPTION 42/* pcf_parse_service_pattern() takes an expression and splits 43/* it up on '/' into an array of sub-expressions, This function 44/* returns null if the input does fewer than "min" or more 45/* than "max" sub-expressions. 46/* 47/* PCF_IS_MAGIC_SERVICE_PATTERN() returns non-zero if any of 48/* the service name or service type sub-expressions contains 49/* a matching operator (as opposed to string literals that 50/* only match themselves). This is an unsafe macro that evaluates 51/* its arguments more than once. 52/* 53/* PCF_MATCH_SERVICE_PATTERN() matches a service name and type 54/* from master.cf against the parsed pattern. This is an unsafe 55/* macro that evaluates its arguments more than once. 56/* 57/* pcf_parse_field_pattern() converts a field sub-expression, 58/* and returns the conversion result. 59/* 60/* pcf_str_field_pattern() converts a result from 61/* pcf_parse_field_pattern() into string form. 62/* 63/* pcf_is_magic_field_pattern() returns non-zero if the field 64/* pattern sub-expression contained a matching operator (as 65/* opposed to a string literal that only matches itself). 66/* 67/* PCF_IS_MAGIC_PARAM_PATTERN() returns non-zero if the parameter 68/* sub-expression contains a matching operator (as opposed to 69/* a string literal that only matches itself). This is an 70/* unsafe macro that evaluates its arguments more than once. 71/* 72/* PCF_MATCH_PARAM_PATTERN() matches a parameter name from 73/* master.cf against the parsed pattern. This is an unsafe 74/* macro that evaluates its arguments more than once. 75/* 76/* Arguments 77/* .IP field_expr 78/* A field expression. 79/* .IP service_expr 80/* This argument is split on '/' into its constituent 81/* sub-expressions. 82/* .IP min_expr 83/* The minimum number of sub-expressions in service_expr. 84/* .IP max_expr 85/* The maximum number of sub-expressions in service_expr. 86/* .IP service_name 87/* Service name from master.cf. 88/* .IP service_type 89/* Service type from master.cf. 90/* .IP param_pattern 91/* A parameter name expression. 92/* DIAGNOSTICS 93/* Fatal errors: invalid syntax. 94/* LICENSE 95/* .ad 96/* .fi 97/* The Secure Mailer license must be distributed with this software. 98/* AUTHOR(S) 99/* Wietse Venema 100/* IBM T.J. Watson Research 101/* P.O. Box 704 102/* Yorktown Heights, NY 10598, USA 103/*--*/ 104 105/* System library. */ 106 107#include <sys_defs.h> 108#include <string.h> 109 110/* Utility library. */ 111 112#include <msg.h> 113#include <mymalloc.h> 114#include <vstring.h> 115 116/* Global library. */ 117 118#include <split_at.h> 119 120/* Application-specific. */ 121 122#include <postconf.h> 123 124 /* 125 * Conversion table. Each PCF_MASTER_NAME_XXX name entry must be stored at 126 * table offset PCF_MASTER_FLD_XXX. So don't mess it up. 127 */ 128NAME_CODE pcf_field_name_offset[] = { 129 PCF_MASTER_NAME_SERVICE, PCF_MASTER_FLD_SERVICE, 130 PCF_MASTER_NAME_TYPE, PCF_MASTER_FLD_TYPE, 131 PCF_MASTER_NAME_PRIVATE, PCF_MASTER_FLD_PRIVATE, 132 PCF_MASTER_NAME_UNPRIV, PCF_MASTER_FLD_UNPRIV, 133 PCF_MASTER_NAME_CHROOT, PCF_MASTER_FLD_CHROOT, 134 PCF_MASTER_NAME_WAKEUP, PCF_MASTER_FLD_WAKEUP, 135 PCF_MASTER_NAME_MAXPROC, PCF_MASTER_FLD_MAXPROC, 136 PCF_MASTER_NAME_CMD, PCF_MASTER_FLD_CMD, 137 "*", PCF_MASTER_FLD_WILDC, 138 0, PCF_MASTER_FLD_NONE, 139}; 140 141/* pcf_parse_field_pattern - parse service attribute pattern */ 142 143int pcf_parse_field_pattern(const char *field_name) 144{ 145 int field_pattern; 146 147 if ((field_pattern = name_code(pcf_field_name_offset, 148 NAME_CODE_FLAG_STRICT_CASE, 149 field_name)) == PCF_MASTER_FLD_NONE) 150 msg_fatal("invalid service attribute name: \"%s\"", field_name); 151 return (field_pattern); 152} 153 154/* pcf_parse_service_pattern - parse service pattern */ 155 156ARGV *pcf_parse_service_pattern(const char *pattern, int min_expr, int max_expr) 157{ 158 ARGV *argv; 159 char **cpp; 160 161 /* 162 * Work around argv_split() lameness. 163 */ 164 if (*pattern == '/') 165 return (0); 166 argv = argv_split(pattern, PCF_NAMESP_SEP_STR); 167 if (argv->argc < min_expr || argv->argc > max_expr) { 168 argv_free(argv); 169 return (0); 170 } 171 172 /* 173 * Allow '*' only all by itself. 174 */ 175 for (cpp = argv->argv; *cpp; cpp++) { 176 if (!PCF_MATCH_ANY(*cpp) && strchr(*cpp, PCF_MATCH_WILDC_STR[0]) != 0) { 177 argv_free(argv); 178 return (0); 179 } 180 } 181 182 /* 183 * Provide defaults for missing fields. 184 */ 185 while (argv->argc < max_expr) 186 argv_add(argv, PCF_MATCH_WILDC_STR, ARGV_END); 187 return (argv); 188} 189