1 /* $NetBSD: dict_inline.c,v 1.4 2022/10/08 16:12:50 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 /* Wietse Venema 33 /* Google, Inc. 34 /* 111 8th Avenue 35 /* New York, NY 10011, USA 36 /*--*/ 37 38 /* System library. */ 39 40 #include <sys_defs.h> 41 #include <string.h> 42 43 /* Utility library. */ 44 45 #include <msg.h> 46 #include <mymalloc.h> 47 #include <stringops.h> 48 #include <dict.h> 49 #include <dict_ht.h> 50 #include <dict_inline.h> 51 52 /* Application-specific. */ 53 54 /* dict_inline_open - open inline table */ 55 56 DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) 57 { 58 DICT *dict; 59 char *cp, *saved_name = 0; 60 size_t len; 61 char *nameval, *vname, *value; 62 const char *err = 0; 63 char *free_me = 0; 64 int count = 0; 65 66 /* 67 * Clarity first. Let the optimizer worry about redundant code. 68 */ 69 #define DICT_INLINE_RETURN(x) do { \ 70 DICT *__d = (x); \ 71 if (saved_name != 0) \ 72 myfree(saved_name); \ 73 if (free_me != 0) \ 74 myfree(free_me); \ 75 return (__d); \ 76 } while (0) 77 78 /* 79 * Sanity checks. 80 */ 81 if (open_flags != O_RDONLY) 82 DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, 83 open_flags, dict_flags, 84 "%s:%s map requires O_RDONLY access mode", 85 DICT_TYPE_INLINE, name)); 86 87 /* 88 * UTF-8 syntax check. 89 */ 90 if (DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags) 91 && allascii(name) == 0 92 && valid_utf8_string(name, strlen(name)) == 0) 93 DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, 94 open_flags, dict_flags, 95 "bad UTF-8 syntax: \"%s:%s\"; " 96 "need \"%s:{name=value...}\"", 97 DICT_TYPE_INLINE, name, 98 DICT_TYPE_INLINE)); 99 100 /* 101 * Parse the table into its constituent name=value pairs. 102 */ 103 if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0 104 || *(cp = saved_name = mystrndup(name + 1, len - 2)) == 0) 105 DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, 106 open_flags, dict_flags, 107 "bad syntax: \"%s:%s\"; " 108 "need \"%s:{name=value...}\"", 109 DICT_TYPE_INLINE, name, 110 DICT_TYPE_INLINE)); 111 112 /* 113 * Reuse the "internal" dictionary type. 114 */ 115 dict = dict_open3(DICT_TYPE_HT, name, open_flags, dict_flags); 116 dict_type_override(dict, DICT_TYPE_INLINE); 117 while ((nameval = mystrtokq(&cp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { 118 if (nameval[0] == CHARS_BRACE[0]) 119 err = free_me = extpar(&nameval, CHARS_BRACE, EXTPAR_FLAG_STRIP); 120 if (err != 0 || (err = split_qnameval(nameval, &vname, &value)) != 0) 121 break; 122 123 if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) != 0) { 124 VSTRING *base64_buf; 125 126 if ((base64_buf = dict_file_to_b64(dict, value)) == 0) { 127 err = free_me = dict_file_get_error(dict); 128 break; 129 } 130 value = vstring_str(base64_buf); 131 } 132 /* No duplicate checks. See comments in dict_thash.c. */ 133 dict->update(dict, vname, value); 134 count += 1; 135 } 136 if (err != 0 || count == 0) { 137 dict->close(dict); 138 DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, 139 open_flags, dict_flags, 140 "%s: \"%s:%s\"; " 141 "need \"%s:{name=%s...}\"", 142 err != 0 ? err : "empty table", 143 DICT_TYPE_INLINE, name, 144 DICT_TYPE_INLINE, 145 (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ? 146 "filename" : "value")); 147 } 148 dict->owner.status = DICT_OWNER_TRUSTED; 149 150 dict_file_purge_buffers(dict); 151 DICT_INLINE_RETURN(DICT_DEBUG (dict)); 152 } 153