static void postmap_body(void *ptr, int unused_rec_type, const char *keybuf, ssize_t unused_len, off_t unused_offset) { POSTMAP_KEY_STATE *state = (POSTMAP_KEY_STATE *) ptr; DICT **dicts = state->dicts; char **maps = state->maps; int map_count = state->map_count; int dict_flags = state->dict_flags; const char *map_name; const char *value; int n; for (n = 0; n < map_count; n++) { if (dicts[n] == 0) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); if ((value = dict_get(dicts[n], keybuf)) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", dicts[n]->type, dicts[n]->name, keybuf); msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", dicts[n]->type, dicts[n]->name); } vstream_printf("%s %s\n", keybuf, value); state->found = 1; break; } if (dicts[n]->error) msg_fatal("table %s:%s: query error: %m", dicts[n]->type, dicts[n]->name); } }
static int postmap_deletes(VSTREAM *in, char **maps, const int map_count, int dict_flags) { int found = 0; VSTRING *keybuf = vstring_alloc(100); DICT **dicts; const char *map_name; int n; int open_flags; /* * Sanity check. */ if (map_count <= 0) msg_panic("postmap_deletes: bad map count"); /* * Open maps ahead of time. */ dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count); for (n = 0; n < map_count; n++) { map_name = split_at(maps[n], ':'); if (map_name && strcmp(maps[n], DICT_TYPE_PROXY) == 0) open_flags = O_RDWR | O_CREAT; /* XXX */ else open_flags = O_RDWR; dicts[n] = (map_name != 0 ? dict_open3(maps[n], map_name, open_flags, dict_flags) : dict_open3(var_db_type, maps[n], open_flags, dict_flags)); } /* * Perform all requests. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { for (n = 0; n < map_count; n++) { found |= (dict_del(dicts[n], STR(keybuf)) == 0); if (dicts[n]->error) msg_fatal("table %s:%s: delete error: %m", dicts[n]->type, dicts[n]->name); } } /* * Cleanup. */ for (n = 0; n < map_count; n++) if (dicts[n]) dict_close(dicts[n]); myfree((void *) dicts); vstring_free(keybuf); return (found); }
static void postmap_seq(const char *map_type, const char *map_name, int dict_flags) { DICT *dict; const char *key; const char *value; int func; if (strcmp(map_type, DICT_TYPE_PROXY) == 0) msg_fatal("can't sequence maps via the proxy service"); dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) { if (dict_seq(dict, func, &key, &value) != 0) break; if (*key == 0) { msg_warn("table %s:%s: empty lookup key value is not allowed", map_type, map_name); } else if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", map_type, map_name, key); msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", map_type, map_name); } vstream_printf("%s %s\n", key, value); } if (dict->error) msg_fatal("table %s:%s: sequence error: %m", dict->type, dict->name); vstream_fflush(VSTREAM_OUT); dict_close(dict); }
DICT *dict_open(const char *dict_spec, int open_flags, int dict_flags) { char *saved_dict_spec = mystrdup(dict_spec); char *dict_name; DICT *dict; if ((dict_name = split_at(saved_dict_spec, ':')) == 0) msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s\"", dict_spec); dict = dict_open3(saved_dict_spec, dict_name, open_flags, dict_flags); myfree(saved_dict_spec); return (dict); }
static int postmap_delete(const char *map_type, const char *map_name, const char *key, int dict_flags) { DICT *dict; int status; int open_flags; if (strcmp(map_type, DICT_TYPE_PROXY) == 0) open_flags = O_RDWR | O_CREAT; /* XXX */ else open_flags = O_RDWR; dict = dict_open3(map_type, map_name, open_flags, dict_flags); status = dict_del(dict, key); if (dict->error) msg_fatal("table %s:%s: delete error: %m", dict->type, dict->name); dict_close(dict); return (status == 0); }
static int postmap_query(const char *map_type, const char *map_name, const char *key, int dict_flags) { DICT *dict; const char *value; dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); if ((value = dict_get(dict, key)) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", map_type, map_name, key); msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", map_type, map_name); } vstream_printf("%s\n", value); } if (dict->error) msg_fatal("table %s:%s: query error: %m", dict->type, dict->name); vstream_fflush(VSTREAM_OUT); dict_close(dict); return (value != 0); }
static int postmap_queries(VSTREAM *in, char **maps, const int map_count, const int postmap_flags, const int dict_flags) { int found = 0; VSTRING *keybuf = vstring_alloc(100); DICT **dicts; const char *map_name; const char *value; int n; /* * Sanity check. */ if (map_count <= 0) msg_panic("postmap_queries: bad map count"); /* * Prepare to open maps lazily. */ dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count); for (n = 0; n < map_count; n++) dicts[n] = 0; /* * Perform all queries. Open maps on the fly, to avoid opening unecessary * maps. */ if ((postmap_flags & POSTMAP_FLAG_HB_KEY) == 0) { while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { for (n = 0; n < map_count; n++) { if (dicts[n] == 0) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); if ((value = dict_get(dicts[n], STR(keybuf))) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", dicts[n]->type, dicts[n]->name, STR(keybuf)); msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", dicts[n]->type, dicts[n]->name); } vstream_printf("%s %s\n", STR(keybuf), value); found = 1; break; } if (dicts[n]->error) msg_fatal("table %s:%s: query error: %m", dicts[n]->type, dicts[n]->name); } } } else { POSTMAP_KEY_STATE key_state; MIME_STATE *mime_state; int mime_errs = 0; /* * Bundle up the request and instantiate a MIME parsing engine. */ key_state.dicts = dicts; key_state.maps = maps; key_state.map_count = map_count; key_state.dict_flags = dict_flags; key_state.header_done = 0; key_state.found = 0; mime_state = mime_state_alloc((postmap_flags & POSTMAP_FLAG_MIME_KEY) ? 0 : MIME_OPT_DISABLE_MIME, (postmap_flags & POSTMAP_FLAG_HEADER_KEY) ? postmap_header : (MIME_STATE_HEAD_OUT) 0, (postmap_flags & POSTMAP_FLAG_FULL_KEY) ? (MIME_STATE_ANY_END) 0 : postmap_head_end, (postmap_flags & POSTMAP_FLAG_BODY_KEY) ? postmap_body : (MIME_STATE_BODY_OUT) 0, (MIME_STATE_ANY_END) 0, (MIME_STATE_ERR_PRINT) 0, (void *) &key_state); /* * Process the input message. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF && key_state.header_done == 0 && mime_errs == 0) mime_errs = mime_state_update(mime_state, REC_TYPE_NORM, STR(keybuf), LEN(keybuf)); /* * Flush the MIME engine output buffer and tidy up loose ends. */ if (mime_errs == 0) mime_errs = mime_state_update(mime_state, REC_TYPE_END, "", 0); if (mime_errs) msg_fatal("message format error: %s", mime_state_detail(mime_errs)->text); mime_state_free(mime_state); found = key_state.found; } if (found) vstream_fflush(VSTREAM_OUT); /* * Cleanup. */ for (n = 0; n < map_count; n++) if (dicts[n]) dict_close(dicts[n]); myfree((void *) dicts); vstring_free(keybuf); return (found); }
static int postalias_queries(VSTREAM *in, char **maps, const int map_count, const int dict_flags) { int found = 0; VSTRING *keybuf = vstring_alloc(100); DICT **dicts; const char *map_name; const char *value; int n; /* * Sanity check. */ if (map_count <= 0) msg_panic("postalias_queries: bad map count"); /* * Prepare to open maps lazily. */ dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count); for (n = 0; n < map_count; n++) dicts[n] = 0; /* * Perform all queries. Open maps on the fly, to avoid opening unecessary * maps. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { for (n = 0; n < map_count; n++) { if (dicts[n] == 0) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); if ((value = dict_get(dicts[n], STR(keybuf))) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", dicts[n]->type, dicts[n]->name, STR(keybuf)); msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", dicts[n]->type, dicts[n]->name); } vstream_printf("%s: %s\n", STR(keybuf), value); found = 1; break; } if (dicts[n]->error) msg_fatal("table %s:%s: query error: %m", dicts[n]->type, dicts[n]->name); } } if (found) vstream_fflush(VSTREAM_OUT); /* * Cleanup. */ for (n = 0; n < map_count; n++) if (dicts[n]) dict_close(dicts[n]); myfree((void *) dicts); vstring_free(keybuf); return (found); }