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