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