Postfix3.3.1
match_service.c
[詳解]
1 /*++
2 /* NAME
3 /* match_service 3
4 /* SUMMARY
5 /* simple master.cf service name.type pattern matcher
6 /* SYNOPSIS
7 /* #include <match_service.h>
8 /*
9 /* ARGV *match_service_init(pattern_list)
10 /* const char *pattern_list;
11 /*
12 /* ARGV *match_service_init_argv(pattern_list)
13 /* char **pattern_list;
14 /*
15 /* int match_service_match(list, name_type)
16 /* ARGV *list;
17 /* const char *name_type;
18 /*
19 /* void match_service_free(list)
20 /* ARGV *list;
21 /* DESCRIPTION
22 /* This module implements pattern matching for Postfix master.cf
23 /* services. This is more precise than using domain_list(3),
24 /* because match_service(3) won't treat a dotted service name
25 /* as a domain hierarchy. Moreover, this module has the advantage
26 /* that it does not drag in all the LDAP, SQL and other map
27 /* lookup client code into programs that don't need it.
28 /*
29 /* Each pattern is of the form "name/type" or "type", where
30 /* "name" and "type" are the first two fields of a master.cf
31 /* entry. Patterns are separated by whitespace and/or commas.
32 /* Matches are case insensitive. Patterns are matched in the
33 /* specified order, and the matching process stops at the first
34 /* match. In order to reverse the result of a pattern match,
35 /* precede a pattern with an exclamation point (!).
36 /*
37 /* For backwards compatibility, the form name.type is still
38 /* supported.
39 /*
40 /* match_service_init() parses the pattern list. The result
41 /* must be passed to match_service_match() or match_service_free().
42 /*
43 /* match_service_init_argv() provides an alternate interface
44 /* for pre-parsed strings.
45 /*
46 /* match_service_match() matches one service name.type string
47 /* against the specified pattern list.
48 /*
49 /* match_service_free() releases storage allocated by
50 /* match_service_init().
51 /* DIAGNOSTICS
52 /* Fatal error: out of memory, malformed pattern.
53 /* Panic: malformed search string.
54 /* SEE ALSO
55 /* domain_list(3) match domain names.
56 /* LICENSE
57 /* .ad
58 /* .fi
59 /* The Secure Mailer license must be distributed with this software.
60 /* AUTHOR(S)
61 /* Wietse Venema
62 /* IBM T.J. Watson Research
63 /* P.O. Box 704
64 /* Yorktown Heights, NY 10598, USA
65 /*--*/
66 
67 /* System library. */
68 
69 #include <sys_defs.h>
70 #include <string.h>
71 
72 #ifdef STRCASECMP_IN_STRINGS_H
73 #include <strings.h>
74 #endif
75 
76 /* Utility library. */
77 
78 #include <msg.h>
79 #include <argv.h>
80 #include <mymalloc.h>
81 #include <stringops.h>
82 #include <match_service.h>
83 
84 /* match_service_compat - backwards compatibility */
85 
86 static void match_service_compat(ARGV *argv)
87 {
88  char **cpp;
89  char *cp;
90 
91  for (cpp = argv->argv; *cpp; cpp++) {
92  if (strrchr(*cpp, '/') == 0 && (cp = strrchr(*cpp, '.')) != 0)
93  *cp = '/';
94  }
95 }
96 
97 /* match_service_init - initialize pattern list */
98 
99 ARGV *match_service_init(const char *patterns)
100 {
101  const char *delim = CHARS_COMMA_SP;
102  ARGV *list = argv_alloc(1);
103  char *saved_patterns = mystrdup(patterns);
104  char *bp = saved_patterns;
105  const char *item;
106 
107  while ((item = mystrtok(&bp, delim)) != 0)
108  argv_add(list, item, (char *) 0);
109  argv_terminate(list);
110  myfree(saved_patterns);
111  match_service_compat(list);
112  return (list);
113 }
114 
115 /* match_service_init_argv - impedance adapter */
116 
117 ARGV *match_service_init_argv(char **patterns)
118 {
119  ARGV *list = argv_alloc(1);
120  char **cpp;
121 
122  for (cpp = patterns; *cpp; cpp++)
123  argv_add(list, *cpp, (char *) 0);
124  argv_terminate(list);
125  match_service_compat(list);
126  return (list);
127 }
128 
129 /* match_service_match - match service name.type against pattern list */
130 
131 int match_service_match(ARGV *list, const char *name_type)
132 {
133  const char *myname = "match_service_match";
134  const char *type;
135  char **cpp;
136  char *pattern;
137  int match;
138 
139  /*
140  * Quick check for empty list.
141  */
142  if (list->argv[0] == 0)
143  return (0);
144 
145  /*
146  * Sanity check.
147  */
148  if ((type = strrchr(name_type, '/')) == 0 || *++type == 0)
149  msg_panic("%s: malformed service: \"%s\"; need \"name/type\" format",
150  myname, name_type);
151 
152  /*
153  * Iterate over all patterns in the list, stop at the first match.
154  */
155  for (cpp = list->argv; (pattern = *cpp) != 0; cpp++) {
156  if (msg_verbose)
157  msg_info("%s: %s ~? %s", myname, name_type, pattern);
158  for (match = 1; *pattern == '!'; pattern++)
159  match = !match;
160  if (strcasecmp(strchr(pattern, '/') ? name_type : type, pattern) == 0) {
161  if (msg_verbose)
162  msg_info("%s: %s: found match", myname, name_type);
163  return (match);
164  }
165  }
166  if (msg_verbose)
167  msg_info("%s: %s: no match", myname, name_type);
168  return (0);
169 }
170 
171 /* match_service_free - release storage */
172 
174 {
175  argv_free(list);
176 }
int msg_verbose
Definition: msg.c:177
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
ARGV * match_service_init(const char *patterns)
Definition: match_service.c:99
Definition: argv.h:17
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
int match_service_match(ARGV *list, const char *name_type)
char ** argv
Definition: argv.h:20
void argv_add(ARGV *argvp,...)
Definition: argv.c:197
char * mystrtok(char **src, const char *sep)
Definition: mystrtok.c:54
ARGV * argv_alloc(ssize_t len)
Definition: argv.c:149
void match_service_free(ARGV *list)
#define CHARS_COMMA_SP
Definition: sys_defs.h:1761
ARGV * match_service_init_argv(char **patterns)
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:41
void argv_terminate(ARGV *argvp)
Definition: argv.c:242
void msg_info(const char *fmt,...)
Definition: msg.c:199