summaryrefslogtreecommitdiffstats
path: root/src/postconf/postconf_match.c
blob: 53709a4bba2d6f5e4572d947b1153b5e30fdad2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*++
/* NAME
/*	postconf_match 3
/* SUMMARY
/*	pattern-matching support
/* SYNOPSIS
/*	#include <postconf.h>
/*
/*	int	pcf_parse_field_pattern(field_expr)
/*	char	*field_expr;
/*
/*	const char *pcf_str_field_pattern(field_pattern)
/*	int	field_pattern;
/*
/*	int	pcf_is_magic_field_pattern(field_pattern)
/*	int	field_pattern;
/*
/*	ARGV	*pcf_parse_service_pattern(service_expr, min_expr, max_expr)
/*	const char *service_expr;
/*	int	min_expr;
/*	int	max_expr;
/*
/*	int	PCF_IS_MAGIC_SERVICE_PATTERN(service_pattern)
/*	const ARGV *service_pattern;
/*
/*	int	PCF_MATCH_SERVICE_PATTERN(service_pattern, service_name,
/*					service_type)
/*	const ARGV *service_pattern;
/*	const char *service_name;
/*	const char *service_type;
/*
/*	const char *pcf_str_field_pattern(field_pattern)
/*	int	field_pattern;
/*
/*	int	PCF_IS_MAGIC_PARAM_PATTERN(param_pattern)
/*	const char *param_pattern;
/*
/*	int	PCF_MATCH_PARAM_PATTERN(param_pattern, param_name)
/*	const char *param_pattern;
/*	const char *param_name;
/* DESCRIPTION
/*	pcf_parse_service_pattern() takes an expression and splits
/*	it up on '/' into an array of sub-expressions, This function
/*	returns null if the input does fewer than "min" or more
/*	than "max" sub-expressions.
/*
/*	PCF_IS_MAGIC_SERVICE_PATTERN() returns non-zero if any of
/*	the service name or service type sub-expressions contains
/*	a matching operator (as opposed to string literals that
/*	only match themselves). This is an unsafe macro that evaluates
/*	its arguments more than once.
/*
/*	PCF_MATCH_SERVICE_PATTERN() matches a service name and type
/*	from master.cf against the parsed pattern. This is an unsafe
/*	macro that evaluates its arguments more than once.
/*
/*	pcf_parse_field_pattern() converts a field sub-expression,
/*	and returns the conversion result.
/*
/*	pcf_str_field_pattern() converts a result from
/*	pcf_parse_field_pattern() into string form.
/*
/*	pcf_is_magic_field_pattern() returns non-zero if the field
/*	pattern sub-expression contained a matching operator (as
/*	opposed to a string literal that only matches itself).
/*
/*	PCF_IS_MAGIC_PARAM_PATTERN() returns non-zero if the parameter
/*	sub-expression contains a matching operator (as opposed to
/*	a string literal that only matches itself). This is an
/*	unsafe macro that evaluates its arguments more than once.
/*
/*	PCF_MATCH_PARAM_PATTERN() matches a parameter name from
/*	master.cf against the parsed pattern. This is an unsafe
/*	macro that evaluates its arguments more than once.
/*
/*	Arguments
/* .IP field_expr
/*	A field expression.
/* .IP service_expr
/*	This argument is split on '/' into its constituent
/*	sub-expressions.
/* .IP min_expr
/*	The minimum number of sub-expressions in service_expr.
/* .IP max_expr
/*	The maximum number of sub-expressions in service_expr.
/* .IP service_name
/*	Service name from master.cf.
/* .IP service_type
/*	Service type from master.cf.
/* .IP param_pattern
/*	A parameter name expression.
/* DIAGNOSTICS
/*	Fatal errors: invalid syntax.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <string.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <vstring.h>

/* Global library. */

#include <split_at.h>

/* Application-specific. */

#include <postconf.h>

 /*
  * Conversion table. Each PCF_MASTER_NAME_XXX name entry must be stored at
  * table offset PCF_MASTER_FLD_XXX. So don't mess it up.
  */
NAME_CODE pcf_field_name_offset[] = {
    PCF_MASTER_NAME_SERVICE, PCF_MASTER_FLD_SERVICE,
    PCF_MASTER_NAME_TYPE, PCF_MASTER_FLD_TYPE,
    PCF_MASTER_NAME_PRIVATE, PCF_MASTER_FLD_PRIVATE,
    PCF_MASTER_NAME_UNPRIV, PCF_MASTER_FLD_UNPRIV,
    PCF_MASTER_NAME_CHROOT, PCF_MASTER_FLD_CHROOT,
    PCF_MASTER_NAME_WAKEUP, PCF_MASTER_FLD_WAKEUP,
    PCF_MASTER_NAME_MAXPROC, PCF_MASTER_FLD_MAXPROC,
    PCF_MASTER_NAME_CMD, PCF_MASTER_FLD_CMD,
    "*", PCF_MASTER_FLD_WILDC,
    0, PCF_MASTER_FLD_NONE,
};

/* pcf_parse_field_pattern - parse service attribute pattern */

int     pcf_parse_field_pattern(const char *field_name)
{
    int     field_pattern;

    if ((field_pattern = name_code(pcf_field_name_offset,
				   NAME_CODE_FLAG_STRICT_CASE,
				   field_name)) == PCF_MASTER_FLD_NONE)
	msg_fatal("invalid service attribute name: \"%s\"", field_name);
    return (field_pattern);
}

/* pcf_parse_service_pattern - parse service pattern */

ARGV   *pcf_parse_service_pattern(const char *pattern, int min_expr, int max_expr)
{
    ARGV   *argv;
    char  **cpp;

    /*
     * Work around argv_split() lameness.
     */
    if (*pattern == '/')
	return (0);
    argv = argv_split(pattern, PCF_NAMESP_SEP_STR);
    if (argv->argc < min_expr || argv->argc > max_expr) {
	argv_free(argv);
	return (0);
    }

    /*
     * Allow '*' only all by itself.
     */
    for (cpp = argv->argv; *cpp; cpp++) {
	if (!PCF_MATCH_ANY(*cpp) && strchr(*cpp, PCF_MATCH_WILDC_STR[0]) != 0) {
	    argv_free(argv);
	    return (0);
	}
    }

    /*
     * Provide defaults for missing fields.
     */
    while (argv->argc < max_expr)
	argv_add(argv, PCF_MATCH_WILDC_STR, ARGV_END);
    return (argv);
}