Postfix3.3.1
dict_union.c
[詳解]
1 /*++
2 /* NAME
3 /* dict_union 3
4 /* SUMMARY
5 /* dictionary manager interface for union of tables
6 /* SYNOPSIS
7 /* #include <dict_union.h>
8 /*
9 /* DICT *dict_union_open(name, open_flags, dict_flags)
10 /* const char *name;
11 /* int open_flags;
12 /* int dict_flags;
13 /* DESCRIPTION
14 /* dict_union_open() opens a sequence of one or more tables.
15 /* Example: "\fBunionmap:{\fItype_1:name_1, ..., type_n:name_n\fR}".
16 /*
17 /* Each "unionmap:" query is given to each table in the specified
18 /* order. All found results are concatenated, separated by
19 /* comma. The unionmap table produces no result when all
20 /* lookup tables return no result.
21 /*
22 /* The first and last characters of a "unionmap:" table name
23 /* must be '{' and '}'. Within these, individual maps are
24 /* separated with comma or whitespace.
25 /*
26 /* The open_flags and dict_flags arguments are passed on to
27 /* the underlying dictionaries.
28 /* SEE ALSO
29 /* dict(3) generic dictionary manager
30 /* LICENSE
31 /* .ad
32 /* .fi
33 /* The Secure Mailer license must be distributed with this software.
34 /* AUTHOR(S)
35 /* Wietse Venema
36 /* IBM T.J. Watson Research
37 /* P.O. Box 704
38 /* Yorktown Heights, NY 10598, USA
39 /*
40 /* Wietse Venema
41 /* Google, Inc.
42 /* 111 8th Avenue
43 /* New York, NY 10011, USA
44 /*--*/
45 
46 /* System library. */
47 
48 #include <sys_defs.h>
49 #include <string.h>
50 
51 /* Utility library. */
52 
53 #include <msg.h>
54 #include <mymalloc.h>
55 #include <htable.h>
56 #include <dict.h>
57 #include <dict_union.h>
58 #include <stringops.h>
59 #include <vstring.h>
60 
61 /* Application-specific. */
62 
63 typedef struct {
64  DICT dict; /* generic members */
65  ARGV *map_union; /* pipelined tables */
66  VSTRING *re_buf; /* reply buffer */
67 } DICT_UNION;
68 
69 #define STR(x) vstring_str(x)
70 
71 /* dict_union_lookup - search a bunch of tables and combine the results */
72 
73 static const char *dict_union_lookup(DICT *dict, const char *query)
74 {
75  static const char myname[] = "dict_union_lookup";
76  DICT_UNION *dict_union = (DICT_UNION *) dict;
77  DICT *map;
78  char **cpp;
79  char *dict_type_name;
80  const char *result = 0;
81 
82  /*
83  * After Roel van Meer, postfix-users mailing list, Sept 2014.
84  */
85  VSTRING_RESET(dict_union->re_buf);
86  for (cpp = dict_union->map_union->argv; (dict_type_name = *cpp) != 0; cpp++) {
87  if ((map = dict_handle(dict_type_name)) == 0)
88  msg_panic("%s: dictionary \"%s\" not found", myname, dict_type_name);
89  if ((result = dict_get(map, query)) != 0) {
90  if (VSTRING_LEN(dict_union->re_buf) > 0)
91  VSTRING_ADDCH(dict_union->re_buf, ',');
92  vstring_strcat(dict_union->re_buf, result);
93  } else if (map->error != 0) {
94  DICT_ERR_VAL_RETURN(dict, map->error, 0);
95  }
96  }
98  VSTRING_LEN(dict_union->re_buf) > 0 ?
99  STR(dict_union->re_buf) : 0);
100 }
101 
102 /* dict_union_close - disassociate from a bunch of tables */
103 
104 static void dict_union_close(DICT *dict)
105 {
106  DICT_UNION *dict_union = (DICT_UNION *) dict;
107  char **cpp;
108  char *dict_type_name;
109 
110  for (cpp = dict_union->map_union->argv; (dict_type_name = *cpp) != 0; cpp++)
111  dict_unregister(dict_type_name);
112  argv_free(dict_union->map_union);
113  vstring_free(dict_union->re_buf);
114  dict_free(dict);
115 }
116 
117 /* dict_union_open - open a bunch of tables */
118 
119 DICT *dict_union_open(const char *name, int open_flags, int dict_flags)
120 {
121  static const char myname[] = "dict_union_open";
122  DICT_UNION *dict_union;
123  char *saved_name = 0;
124  char *dict_type_name;
125  ARGV *argv = 0;
126  char **cpp;
127  DICT *dict;
128  int match_flags = 0;
129  struct DICT_OWNER aggr_owner;
130  size_t len;
131 
132  /*
133  * Clarity first. Let the optimizer worry about redundant code.
134  */
135 #define DICT_UNION_RETURN(x) do { \
136  if (saved_name != 0) \
137  myfree(saved_name); \
138  if (argv != 0) \
139  argv_free(argv); \
140  return (x); \
141  } while (0)
142 
143  /*
144  * Sanity checks.
145  */
146  if (open_flags != O_RDONLY)
148  open_flags, dict_flags,
149  "%s:%s map requires O_RDONLY access mode",
150  DICT_TYPE_UNION, name));
151 
152  /*
153  * Split the table name into its constituent parts.
154  */
155  if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
156  || *(saved_name = mystrndup(name + 1, len - 2)) == 0
157  || ((argv = argv_splitq(saved_name, CHARS_COMMA_SP, CHARS_BRACE)),
158  (argv->argc == 0)))
160  open_flags, dict_flags,
161  "bad syntax: \"%s:%s\"; "
162  "need \"%s:{type:name...}\"",
163  DICT_TYPE_UNION, name,
164  DICT_TYPE_UNION));
165 
166  /*
167  * The least-trusted table in the set determines the over-all trust
168  * level. The first table determines the pattern-matching flags.
169  */
170  DICT_OWNER_AGGREGATE_INIT(aggr_owner);
171  for (cpp = argv->argv; (dict_type_name = *cpp) != 0; cpp++) {
172  if (msg_verbose)
173  msg_info("%s: %s", myname, dict_type_name);
174  if (strchr(dict_type_name, ':') == 0)
176  open_flags, dict_flags,
177  "bad syntax: \"%s:%s\"; "
178  "need \"%s:{type:name...}\"",
179  DICT_TYPE_UNION, name,
180  DICT_TYPE_UNION));
181  if ((dict = dict_handle(dict_type_name)) == 0)
182  dict = dict_open(dict_type_name, open_flags, dict_flags);
183  dict_register(dict_type_name, dict);
184  DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
185  if (cpp == argv->argv)
186  match_flags = dict->flags & (DICT_FLAG_FIXED | DICT_FLAG_PATTERN);
187  }
188 
189  /*
190  * Bundle up the result.
191  */
192  dict_union =
193  (DICT_UNION *) dict_alloc(DICT_TYPE_UNION, name, sizeof(*dict_union));
194  dict_union->dict.lookup = dict_union_lookup;
195  dict_union->dict.close = dict_union_close;
196  dict_union->dict.flags = dict_flags | match_flags;
197  dict_union->dict.owner = aggr_owner;
198  dict_union->re_buf = vstring_alloc(100);
199  dict_union->map_union = argv;
200  argv = 0;
201  DICT_UNION_RETURN(DICT_DEBUG (&dict_union->dict));
202 }
int msg_verbose
Definition: msg.c:177
VSTRING * re_buf
Definition: dict_union.c:66
#define CHARS_BRACE
Definition: sys_defs.h:1763
void dict_register(const char *dict_name, DICT *dict_info)
Definition: dict.c:312
#define DICT_OWNER_AGGREGATE_UPDATE(dst, src)
Definition: dict.h:63
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
void(* close)(struct DICT *)
Definition: dict.h:87
Definition: argv.h:17
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define DICT_OWNER_AGGREGATE_INIT(dst)
Definition: dict.h:55
#define DICT_FLAG_FIXED
Definition: dict.h:114
int flags
Definition: dict.h:81
#define DICT_UNION_RETURN(x)
char ** argv
Definition: argv.h:20
DICT * dict_open(const char *, int, int)
Definition: dict_open.c:421
#define VSTRING_LEN(vp)
Definition: vstring.h:72
ARGV * map_union
Definition: dict_union.c:65
#define STR(x)
Definition: dict_union.c:69
#define DICT_ERR_NONE
Definition: dict.h:177
void dict_unregister(const char *dict_name)
Definition: dict.c:354
Definition: dict.h:78
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
DICT dict
Definition: dict_union.c:64
ARGV * argv_splitq(const char *, const char *, const char *)
Definition: argv_splitq.c:67
#define dict_get(dp, key)
Definition: dict.h:236
#define VSTRING_RESET(vp)
Definition: vstring.h:77
DICT * dict_handle(const char *dict_name)
Definition: dict.c:333
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int error
Definition: dict.h:94
const char *(* lookup)(struct DICT *, const char *)
Definition: dict.h:82
#define DICT_ERR_VAL_RETURN(dict, err, val)
Definition: dict.h:192
#define DICT_TYPE_UNION
Definition: dict_union.h:22
#define CHARS_COMMA_SP
Definition: sys_defs.h:1761
#define DICT_FLAG_PATTERN
Definition: dict.h:115
void dict_free(DICT *)
Definition: dict_alloc.c:163
char * mystrndup(const char *str, ssize_t len)
Definition: mymalloc.c:242
size_t balpar(const char *string, const char *parens)
Definition: balpar.c:39
DICT * dict_union_open(const char *name, int open_flags, int dict_flags)
Definition: dict_union.c:119
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
ssize_t argc
Definition: argv.h:19
DICT * dict_alloc(const char *, const char *, ssize_t)
Definition: dict_alloc.c:135
DICT_OWNER owner
Definition: dict.h:93
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
Definition: vstring.c:459
DICT * dict_surrogate(const char *dict_type, const char *dict_name, int open_flags, int dict_flags, const char *fmt,...)
void msg_info(const char *fmt,...)
Definition: msg.c:199