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