xref: /netbsd-src/external/ibm-public/postfix/dist/src/postconf/postconf_match.c (revision 16d67a18c4cbb2d3cb426b01120f4938ca6dbbf9)
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 
pcf_parse_field_pattern(const char * field_name)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 
pcf_parse_service_pattern(const char * pattern,int min_expr,int max_expr)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