Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / match_service.c
blobda37df79233ce49316f62f41aa6edb4a89f95cb8
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* match_service 3
6 /* SUMMARY
7 /* simple master.cf service name.type pattern matcher
8 /* SYNOPSIS
9 /* #include <match_service.h>
11 /* ARGV *match_service_init(pattern_list)
12 /* const char *pattern_list;
14 /* int match_service_match(list, name_type)
15 /* ARGV *list;
16 /* const char *name_type;
18 /* void match_service_free(list)
19 /* ARGV *list;
20 /* DESCRIPTION
21 /* This module implements pattern matching for Postfix master.cf
22 /* services. This is more precise than using domain_list(3),
23 /* because match_service(3) won't treat a dotted service name
24 /* as a domain hierarchy. Moreover, this module has the advantage
25 /* that it does not drag in all the LDAP, SQL and other map
26 /* lookup client code into programs that don't need it.
28 /* Each pattern is of the form "name.type" or "type", where
29 /* "name" and "type" are the first two fields of a master.cf
30 /* entry. Patterns are separated by whitespace and/or commas.
31 /* Matches are case insensitive. Patterns are matched in the
32 /* specified order, and the matching process stops at the first
33 /* match. In order to reverse the result of a pattern match,
34 /* precede a pattern with an exclamation point (!).
36 /* match_service_init() parses the pattern list. The result
37 /* must be passed to match_service_match() or match_service_free().
39 /* match_service_match() matches one service name.type string
40 /* against the specified pattern list.
42 /* match_service_free() releases storage allocated by
43 /* match_service_init().
44 /* DIAGNOSTICS
45 /* Fatal error: out of memory, malformed pattern.
46 /* Panic: malformed search string.
47 /* SEE ALSO
48 /* domain_list(3) match domain names.
49 /* LICENSE
50 /* .ad
51 /* .fi
52 /* The Secure Mailer license must be distributed with this software.
53 /* AUTHOR(S)
54 /* Wietse Venema
55 /* IBM T.J. Watson Research
56 /* P.O. Box 704
57 /* Yorktown Heights, NY 10598, USA
58 /*--*/
60 /* System library. */
62 #include <sys_defs.h>
63 #include <string.h>
65 #ifdef STRCASECMP_IN_STRINGS_H
66 #include <strings.h>
67 #endif
69 /* Utility library. */
71 #include <msg.h>
72 #include <argv.h>
73 #include <mymalloc.h>
74 #include <stringops.h>
75 #include <match_service.h>
77 /* match_service_init - initialize pattern list */
79 ARGV *match_service_init(const char *patterns)
81 const char *delim = " ,\t\r\n";
82 ARGV *list = argv_alloc(1);
83 char *saved_patterns = mystrdup(patterns);
84 char *bp = saved_patterns;
85 const char *item;
87 while ((item = mystrtok(&bp, delim)) != 0)
88 argv_add(list, item, (char *) 0);
89 argv_terminate(list);
90 myfree(saved_patterns);
91 return (list);
94 /* match_service_match - match service name.type against pattern list */
96 int match_service_match(ARGV *list, const char *name_type)
98 const char *myname = "match_service_match";
99 const char *type;
100 char **cpp;
101 char *pattern;
102 int match;
105 * Quick check for empty list.
107 if (list->argv[0] == 0)
108 return (0);
111 * Sanity check.
113 if ((type = strrchr(name_type, '.')) == 0 || *++type == 0)
114 msg_panic("%s: malformed service: \"%s\"; need \"name.type\" format",
115 myname, name_type);
118 * Iterate over all patterns in the list, stop at the first match.
120 for (cpp = list->argv; (pattern = *cpp) != 0; cpp++) {
121 if (msg_verbose)
122 msg_info("%s: %s ~? %s", myname, name_type, pattern);
123 for (match = 1; *pattern == '!'; pattern++)
124 match = !match;
125 if (strcasecmp(strchr(pattern, '.') ? name_type : type, pattern) == 0) {
126 if (msg_verbose)
127 msg_info("%s: %s: found match", myname, name_type);
128 return (match);
131 if (msg_verbose)
132 msg_info("%s: %s: no match", myname, name_type);
133 return (0);
136 /* match_service_free - release storage */
138 void match_service_free(ARGV *list)
140 argv_free(list);