static DICT *proxy_map_find(const char *map_type_name, int request_flags, int *statp) { DICT *dict; #define PROXY_COLON DICT_TYPE_PROXY ":" #define PROXY_COLON_LEN (sizeof(PROXY_COLON) - 1) #define READ_OPEN_FLAGS O_RDONLY #define WRITE_OPEN_FLAGS (O_RDWR | O_CREAT) /* * Canonicalize the map name. If the map is not on the approved list, * deny the request. */ #define PROXY_MAP_FIND_ERROR_RETURN(x) { *statp = (x); return (0); } while (strncmp(map_type_name, PROXY_COLON, PROXY_COLON_LEN) == 0) map_type_name += PROXY_COLON_LEN; if (strchr(map_type_name, ':') == 0) PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_BAD); if (htable_locate(proxy_auth_maps, map_type_name) == 0) { msg_warn("request for unapproved table: \"%s\"", map_type_name); msg_warn("to approve this table for %s access, list %s:%s in %s:%s", proxy_writer == 0 ? "read-only" : "read-write", DICT_TYPE_PROXY, map_type_name, MAIN_CONF_FILE, proxy_writer == 0 ? VAR_PROXY_READ_MAPS : VAR_PROXY_WRITE_MAPS); PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_DENY); } /* * Open one instance of a map for each combination of name+flags. * * Assume that a map instance can be shared among clients with different * paranoia flag settings and with different map lookup flag settings. * * XXX The open() flags are passed implicitly, via the selection of the * service name. For a more sophisticated interface, appropriate subsets * of open() flags should be received directly from the client. */ vstring_sprintf(map_type_name_flags, "%s:%s", map_type_name, dict_flags_str(request_flags & DICT_FLAG_INST_MASK)); if (msg_verbose) msg_info("proxy_map_find: %s", STR(map_type_name_flags)); if ((dict = dict_handle(STR(map_type_name_flags))) == 0) { dict = dict_open(map_type_name, proxy_writer ? WRITE_OPEN_FLAGS : READ_OPEN_FLAGS, request_flags); if (dict == 0) msg_panic("proxy_map_find: dict_open null result"); dict_register(STR(map_type_name_flags), dict); } dict->error = 0; return (dict); }
MAPS *maps_create(const char *title, const char *map_names, int dict_flags) { const char *myname = "maps_create"; char *temp; char *bufp; static char sep[] = CHARS_COMMA_SP; static char parens[] = CHARS_BRACE; MAPS *maps; char *map_type_name; VSTRING *map_type_name_flags; DICT *dict; /* * Initialize. */ maps = (MAPS *) mymalloc(sizeof(*maps)); maps->title = mystrdup(title); maps->argv = argv_alloc(2); maps->error = 0; /* * For each specified type:name pair, either register a new dictionary, * or increment the reference count of an existing one. */ if (*map_names) { bufp = temp = mystrdup(map_names); map_type_name_flags = vstring_alloc(10); #define OPEN_FLAGS O_RDONLY while ((map_type_name = mystrtokq(&bufp, sep, parens)) != 0) { vstring_sprintf(map_type_name_flags, "%s(%o,%s)", map_type_name, OPEN_FLAGS, dict_flags_str(dict_flags)); if ((dict = dict_handle(vstring_str(map_type_name_flags))) == 0) dict = dict_open(map_type_name, OPEN_FLAGS, dict_flags); if ((dict->flags & dict_flags) != dict_flags) msg_panic("%s: map %s has flags 0%o, want flags 0%o", myname, map_type_name, dict->flags, dict_flags); dict_register(vstring_str(map_type_name_flags), dict); argv_add(maps->argv, vstring_str(map_type_name_flags), ARGV_END); } myfree(temp); vstring_free(map_type_name_flags); } return (maps); }
void dict_test(int argc, char **argv) { VSTRING *keybuf = vstring_alloc(1); VSTRING *inbuf = vstring_alloc(1); DICT *dict; char *dict_name; int open_flags; char *bufp; char *cmd; const char *key; const char *value; int ch; int dict_flags = 0; int n; int rc; #define USAGE "verbose|del key|get key|put key=value|first|next|masks|flags" signal(SIGPIPE, SIG_IGN); msg_vstream_init(argv[0], VSTREAM_ERR); while ((ch = GETOPT(argc, argv, "v")) > 0) { switch (ch) { default: usage(argv[0]); case 'v': msg_verbose++; break; } } optind = OPTIND; if (argc - optind < 2) usage(argv[0]); if (strcasecmp(argv[optind + 1], "create") == 0) open_flags = O_CREAT | O_RDWR | O_TRUNC; else if (strcasecmp(argv[optind + 1], "write") == 0) open_flags = O_RDWR; else if (strcasecmp(argv[optind + 1], "read") == 0) open_flags = O_RDONLY; else msg_fatal("unknown access mode: %s", argv[2]); for (n = 2; argv[optind + n]; n++) dict_flags |= dict_flags_mask(argv[optind + 2]); if ((dict_flags & DICT_FLAG_OPEN_LOCK) == 0) dict_flags |= DICT_FLAG_LOCK; if ((dict_flags & (DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE)) == 0) dict_flags |= DICT_FLAG_DUP_REPLACE; vstream_fflush(VSTREAM_OUT); dict_name = argv[optind]; dict_allow_surrogate = 1; dict = dict_open(dict_name, open_flags, dict_flags); dict_register(dict_name, dict); while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { bufp = vstring_str(inbuf); if (!isatty(0)) { vstream_printf("> %s\n", bufp); vstream_fflush(VSTREAM_OUT); } if (*bufp == '#') continue; if ((cmd = mystrtok(&bufp, " ")) == 0) { vstream_printf("usage: %s\n", USAGE); vstream_fflush(VSTREAM_OUT); continue; } if (dict_changed_name()) msg_warn("dictionary has changed"); key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0; value = mystrtok(&bufp, " ="); if (strcmp(cmd, "verbose") == 0 && !key) { msg_verbose++; } else if (strcmp(cmd, "del") == 0 && key && !value) { if ((rc = dict_del(dict, key)) > 0) vstream_printf("%s: not found\n", key); else if (rc < 0) vstream_printf("%s: error\n", key); else vstream_printf("%s: deleted\n", key); } else if (strcmp(cmd, "get") == 0 && key && !value) { if ((value = dict_get(dict, key)) == 0) { vstream_printf("%s: %s\n", key, dict->error ? "error" : "not found"); } else { vstream_printf("%s=%s\n", key, value); } } else if (strcmp(cmd, "put") == 0 && key && value) { if (dict_put(dict, key, value) != 0) vstream_printf("%s: %s\n", key, dict->error ? "error" : "not updated"); else vstream_printf("%s=%s\n", key, value); } else if (strcmp(cmd, "first") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else vstream_printf("%s\n", dict->error ? "error" : "not found"); } else if (strcmp(cmd, "next") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else vstream_printf("%s\n", dict->error ? "error" : "not found"); } else if (strcmp(cmd, "flags") == 0 && !key && !value) { vstream_printf("dict flags %s\n", dict_flags_str(dict->flags)); } else if (strcmp(cmd, "masks") == 0 && !key && !value) { vstream_printf("DICT_FLAG_IMPL_MASK %s\n", dict_flags_str(DICT_FLAG_IMPL_MASK)); vstream_printf("DICT_FLAG_PARANOID %s\n", dict_flags_str(DICT_FLAG_PARANOID)); vstream_printf("DICT_FLAG_RQST_MASK %s\n", dict_flags_str(DICT_FLAG_RQST_MASK)); vstream_printf("DICT_FLAG_INST_MASK %s\n", dict_flags_str(DICT_FLAG_INST_MASK)); } else { vstream_printf("usage: %s\n", USAGE); } vstream_fflush(VSTREAM_OUT); } vstring_free(keybuf); vstring_free(inbuf); dict_close(dict); }
static ARGV *match_list_parse(ARGV *list, char *string, int init_match) { const char *myname = "match_list_parse"; VSTRING *buf = vstring_alloc(10); VSTREAM *fp; const char *delim = " ,\t\r\n"; char *bp = string; char *start; char *item; char *map_type_name_flags; int match; #define OPEN_FLAGS O_RDONLY #define DICT_FLAGS (DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX) #define STR(x) vstring_str(x) /* * /filename contents are expanded in-line. To support !/filename we * prepend the negation operator to each item from the file. */ while ((start = mystrtokq(&bp, delim, "{}")) != 0) { if (*start == '#') { msg_warn("%s: comment at end of line is not supported: %s %s", myname, start, bp); break; } for (match = init_match, item = start; *item == '!'; item++) match = !match; if (*item == 0) msg_fatal("%s: no pattern after '!'", myname); if (*item == '/') { /* /file/name */ if ((fp = vstream_fopen(item, O_RDONLY, 0)) == 0) { vstring_sprintf(buf, "%s:%s", DICT_TYPE_NOFILE, item); /* XXX Should increment existing map refcount. */ if (dict_handle(STR(buf)) == 0) dict_register(STR(buf), dict_surrogate(DICT_TYPE_NOFILE, item, OPEN_FLAGS, DICT_FLAGS, "open file %s: %m", item)); argv_add(list, STR(buf), (char *) 0); } else { while (vstring_fgets(buf, fp)) if (vstring_str(buf)[0] != '#') list = match_list_parse(list, vstring_str(buf), match); if (vstream_fclose(fp)) msg_fatal("%s: read file %s: %m", myname, item); } } else if (MATCH_DICTIONARY(item)) { /* type:table */ vstring_sprintf(buf, "%s%s(%o,%s)", match ? "" : "!", item, OPEN_FLAGS, dict_flags_str(DICT_FLAGS)); map_type_name_flags = STR(buf) + (match == 0); /* XXX Should increment existing map refcount. */ if (dict_handle(map_type_name_flags) == 0) dict_register(map_type_name_flags, dict_open(item, OPEN_FLAGS, DICT_FLAGS)); argv_add(list, STR(buf), (char *) 0); } else { /* other pattern */ argv_add(list, match ? item : STR(vstring_sprintf(buf, "!%s", item)), (char *) 0); } } vstring_free(buf); return (list); }