xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_inline.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: dict_inline.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	dict_inline 3
6 /* SUMMARY
7 /*	dictionary manager interface for inline table
8 /* SYNOPSIS
9 /*	#include <dict_inline.h>
10 /*
11 /*	DICT	*dict_inline_open(name, open_flags, dict_flags)
12 /*	const char *name;
13 /*	int	open_flags;
14 /*	int	dict_flags;
15 /* DESCRIPTION
16 /*	dict_inline_open() opens a read-only, in-memory table.
17 /*	Example: "\fBinline:{\fIkey_1=value_1, ..., key_n=value_n\fR}".
18 /*	The longer form with { key = value } allows values that
19 /*	contain whitespace or comma.
20 /* SEE ALSO
21 /*	dict(3) generic dictionary manager
22 /* LICENSE
23 /* .ad
24 /* .fi
25 /*	The Secure Mailer license must be distributed with this software.
26 /* AUTHOR(S)
27 /*	Wietse Venema
28 /*	IBM T.J. Watson Research
29 /*	P.O. Box 704
30 /*	Yorktown Heights, NY 10598, USA
31 /*--*/
32 
33 /* System library. */
34 
35 #include <sys_defs.h>
36 #include <string.h>
37 
38 /* Utility library. */
39 
40 #include <msg.h>
41 #include <mymalloc.h>
42 #include <stringops.h>
43 #include <dict.h>
44 #include <dict_ht.h>
45 #include <dict_inline.h>
46 
47 /* Application-specific. */
48 
49 /* dict_inline_open - open inline table */
50 
51 DICT   *dict_inline_open(const char *name, int open_flags, int dict_flags)
52 {
53     DICT   *dict;
54     char   *cp, *saved_name = 0;
55     size_t  len;
56     char   *nameval, *vname, *value;
57     const char *err = 0;
58     char   *xperr = 0;
59     int     count = 0;
60 
61     /*
62      * Clarity first. Let the optimizer worry about redundant code.
63      */
64 #define DICT_INLINE_RETURN(x) do { \
65 	    DICT *__d = (x); \
66 	    if (saved_name != 0) \
67 		myfree(saved_name); \
68 	    if (xperr != 0) \
69 		myfree(xperr); \
70 	    return (__d); \
71 	} while (0)
72 
73     /*
74      * Sanity checks.
75      */
76     if (open_flags != O_RDONLY)
77 	DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
78 					  open_flags, dict_flags,
79 				  "%s:%s map requires O_RDONLY access mode",
80 					  DICT_TYPE_INLINE, name));
81 
82     /*
83      * UTF-8 syntax check.
84      */
85     if (DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags)
86 	&& allascii(name) == 0
87 	&& valid_utf8_string(name, strlen(name)) == 0)
88 	DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
89 					  open_flags, dict_flags,
90 					  "bad UTF-8 syntax: \"%s:%s\"; "
91 					  "need \"%s:{name=value...}\"",
92 					  DICT_TYPE_INLINE, name,
93 					  DICT_TYPE_INLINE));
94 
95     /*
96      * Parse the table into its constituent name=value pairs.
97      */
98     if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
99 	|| *(cp = saved_name = mystrndup(name + 1, len - 2)) == 0)
100 	DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
101 					  open_flags, dict_flags,
102 					  "bad syntax: \"%s:%s\"; "
103 					  "need \"%s:{name=value...}\"",
104 					  DICT_TYPE_INLINE, name,
105 					  DICT_TYPE_INLINE));
106 
107     /*
108      * Reuse the "internal" dictionary type.
109      */
110     dict = dict_open3(DICT_TYPE_HT, name, open_flags, dict_flags);
111     dict_type_override(dict, DICT_TYPE_INLINE);
112     while ((nameval = mystrtokq(&cp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
113 	if ((nameval[0] != CHARS_BRACE[0]
114 	     || (err = xperr = extpar(&nameval, CHARS_BRACE, EXTPAR_FLAG_STRIP)) == 0)
115 	    && (err = split_nameval(nameval, &vname, &value)) != 0)
116 	    break;
117 
118 	/* No duplicate checks. See comments in dict_thash.c. */
119 	dict->update(dict, vname, value);
120 	count += 1;
121     }
122     if (err != 0 || count == 0) {
123 	dict->close(dict);
124 	DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
125 					  open_flags, dict_flags,
126 					  "%s: \"%s:%s\"; "
127 					  "need \"%s:{name=value...}\"",
128 					  err != 0 ? err : "empty table",
129 					  DICT_TYPE_INLINE, name,
130 					  DICT_TYPE_INLINE));
131     }
132     dict->owner.status = DICT_OWNER_TRUSTED;
133 
134     DICT_INLINE_RETURN(DICT_DEBUG (dict));
135 }
136