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); }
void mkmap_close(MKMAP *mkmap) { /* * Close the database. */ dict_close(mkmap->dict); /* * Do whatever special processing is needed after closing the database, * such as releasing a global exclusive lock on the database file. * Individual Postfix dict modules implement locking only for individual * record operations, because most Postfix applications don't need global * exclusive locks. */ if (mkmap->after_close) mkmap->after_close(mkmap); /* * Resume signal delivery. */ if (mkmap->multi_writer == 0) sigresume(); /* * Cleanup. */ myfree((char *) mkmap); }
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); }
void dict_cache_close(DICT_CACHE *cp) { /* * Destroy the DICT_CACHE object. */ dict_cache_control(cp, DICT_CACHE_CTL_INTERVAL, 0, DICT_CACHE_CTL_END); dict_close(cp->db); if (cp->saved_curr_key) myfree(cp->saved_curr_key); if (cp->saved_curr_val) myfree(cp->saved_curr_val); myfree((char *) cp); }
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); }
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); }
int main(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 = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE; int n; 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++) { if (strcasecmp(argv[optind + 2], "fold") == 0) dict_flags |= DICT_FLAG_FOLD_ANY; else if (strcasecmp(argv[optind + 2], "sync") == 0) dict_flags |= DICT_FLAG_SYNC_UPDATE; else usage(argv[0]); } dict_name = argv[optind]; 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: del key|get key|put key=value|first|next\n"); 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, "del") == 0 && key && !value) { if (dict_del(dict, key)) vstream_printf("%s: not found\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_errno == DICT_ERR_RETRY ? "soft error" : "not found"); } else { vstream_printf("%s=%s\n", key, value); } } else if (strcmp(cmd, "put") == 0 && key && value) { dict_put(dict, key, value); 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_errno == DICT_ERR_RETRY ? "soft 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_errno == DICT_ERR_RETRY ? "soft error" : "not found"); } else { vstream_printf("usage: del key|get key|put key=value|first|next\n"); } vstream_fflush(VSTREAM_OUT); } vstring_free(keybuf); vstring_free(inbuf); dict_close(dict); return (0); }
int main(int argc, char** argv) { int c; char* p; uid_t uid, gid, client_gid, root_gid; struct passwd* pw; struct group* gr; struct stat st; int localsocket = 1; /* * compilerwarnung: "client_gid may be used uninitialized" * sowas will man ja nun wirklich nicht ... */ uid = gid = client_gid = root_gid = 0; while ((c = getopt(argc, argv, "bc:d:hfg:k:m:n:s:t:u:vx")) > 0) { switch (c) { case 'b': /* break contentheader */ logmsg(LOG_INFO, "option -b is ignored for compatibily reasons, you may remove it safely"); break; case 'c': /* clientgroup */ opt_clientgroup = optarg; if ((gr = getgrnam(opt_clientgroup)) == NULL) { logmsg(LOG_ERR, "unknown clientgroup: getgrnam(%s) failed", opt_group); exit(EX_DATAERR); } client_gid = gr->gr_gid; break; case 'd': /* Loglevel */ opt_loglevel = (int) strtoul(optarg, &p, 10); if (p != NULL && *p != '\0') { printf("debug-level is not valid integer: %s\n", optarg); exit(EX_DATAERR); } p = NULL; if (opt_loglevel < 0 || opt_loglevel > 7) { printf("loglevel out of range 0..7: %i\n", opt_loglevel); exit(EX_DATAERR); } break; case 'f': /* signer from header, not from envelope */ opt_signerfromheader = 1; break; case 'g': /* group */ opt_group = optarg; if ((gr = getgrnam(opt_group)) == NULL) { printf("unknown group: getgrnam(%s) failed", opt_group); exit(EX_DATAERR); } break; case 'k': /* keepdir */ opt_keepdir = optarg; if (stat(opt_keepdir, &st) < 0) { printf("directory to keep data: %s: %s", opt_keepdir, strerror(errno)); exit(EX_DATAERR); } if (!S_ISDIR(st.st_mode)) { printf("directory to keep data: %s is not a directory", opt_keepdir); exit(EX_DATAERR); } /* Zugriffsrechte werden spaeter geprueft, wenn zur richtigen uid gewechselt wurde */ break; case '?': /* help */ case 'h': usage(); exit(EX_OK); case 'm': /* Signingtable cdbfilename */ opt_signingtable = optarg; break; case 'n': /* Modetable cdbfilename */ opt_modetable = optarg; break; case 's': /* Miltersocket */ opt_miltersocket = optarg; break; case 't': /* Timeout */ opt_timeout = (int) strtoul(optarg, &p, 10); if (p != NULL && *p != '\0') { printf("timeout is not valid integer: %s\n", optarg); exit(EX_DATAERR); } p = NULL; if (opt_timeout < 0 ) { printf("negative milter connection timeout: %i\n", opt_timeout); exit(EX_DATAERR); } break; case 'u': /* user */ opt_user = optarg; /* get passwd/group entries for opt_user and opt_group */ if ((pw = getpwnam(opt_user)) == NULL) { logmsg(LOG_ERR, "unknown user: getpwnam(%s) failed", opt_user); exit(EX_DATAERR); } break; case 'v': /* Version */ version(); exit(EX_OK); case 'x': /* add X-Header */ opt_addxheader = (int) !opt_addxheader; break; default: usage(); exit(EX_USAGE); } } /* open syslog an say helo */ openlog(STR_PROGNAME, LOG_PID, LOG_MAIL); logmsg(LOG_NOTICE, "starting %s %s listening on %s, loglevel %i", STR_PROGNAME, STR_PROGVERSION, opt_miltersocket, opt_loglevel); /* force a new processgroup */ if ((setsid() == -1)) logmsg(LOG_DEBUG, "ignoring that setsid() failed"); if (opt_timeout > 0 && smfi_settimeout(opt_timeout) != MI_SUCCESS) { logmsg(LOG_ERR, "could not set milter timeout"); exit(EX_SOFTWARE); } logmsg(LOG_INFO, "miltertimeout set to %i", opt_timeout); if (smfi_setconn(opt_miltersocket) != MI_SUCCESS) { logmsg(LOG_ERR, "could not set milter socket"); exit(EX_SOFTWARE); } if (smfi_register(callbacks) != MI_SUCCESS) { logmsg(LOG_ERR, "could not register milter"); exit(EX_SOFTWARE); } /* * User- und Gruppennamen stehen nun fest. Testen, ob es diese gibt * und uid / gid ermitteln */ if ((pw = getpwnam(opt_user)) == NULL) { logmsg(LOG_ERR, "unknown user: getpwnam(%s) failed", opt_user); exit(EX_DATAERR); } uid = pw->pw_uid; if ((gr = getgrnam(opt_group)) == NULL) { logmsg(LOG_ERR, "unknown group: getgrnam(%s) failed", opt_group); exit(EX_SOFTWARE); } gid = gr->gr_gid; /* wenn nicht als Parameter angegeben, gehört ein Unix-Socket erstmal der gleichen Gruppe */ if (opt_clientgroup == NULL) client_gid = gid; /* wenn inet in optarg gefunden wird *und* das auch noch direkt am Anfang * dann ist's kein lokaler socket */ if (((p = strstr(opt_miltersocket, "inet")) != NULL) && opt_miltersocket == p) localsocket = 0; if (localsocket == 1) { /* den Socket oeffnen */ if (smfi_opensocket(REMOVE_EXISTING_SOCKETS) != MI_SUCCESS) { logmsg(LOG_ERR, "could not open milter socket %s", opt_miltersocket); exit(EX_SOFTWARE); } /* testen, ob's den Socket nun gibt */ p = opt_miltersocket + strlen("local:"); if (stat(p, &st) < 0) { p = opt_miltersocket + strlen("unix:"); if (stat(p, &st) < 0) { logmsg(LOG_ERR, "miltersocket does not exist: %m", strerror(errno)); exit(EX_DATAERR); } } /* gid der Gruppe root */ if ((gr = getgrnam("root")) == NULL) { logmsg(LOG_ERR, "unknown rootgroup: getgrnam(root) failed"); exit(EX_SOFTWARE); } root_gid = gr->gr_gid; /* clientgroup muss != root und != opt_group sein */ if ((client_gid == gid) || (client_gid == root_gid)) { logmsg(LOG_ERR, "clientgroup %s must be neither %s nor %s", opt_clientgroup, "root", opt_group); exit(EX_DATAERR); } /* nun die Rechte setzen */ if (chown(p, uid, client_gid) != 0) { logmsg(LOG_ERR, "chown(%s, %i, %i) failed: %m", p, uid, client_gid, strerror(errno)); exit(EX_SOFTWARE); } if (chmod(p, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) { logmsg(LOG_ERR, "chmod(%s, 0660) failed: %m", p, strerror(errno)); exit(EX_SOFTWARE); } logmsg(LOG_INFO, "changed socket %s to owner/group: %i/%i, mode: 0660", opt_miltersocket, uid, client_gid); } /* gid/uid setzen */ if (setgid(gid) != 0) { logmsg(LOG_ERR, "setgid(%i) failed: %s", gr->gr_gid, strerror(errno)); exit(EX_SOFTWARE); } if (setuid(uid) != 0) { logmsg(LOG_ERR, "setuid(%i) failed: %s", pw->pw_uid, strerror(errno)); exit(EX_SOFTWARE); } /* aktuelle uid/gid pruefen und loggen */ uid = getuid(); gid = getgid(); if (uid == 0 || gid == 0) { logmsg(LOG_ERR, "too much priveleges, %s will not start under root", STR_PROGNAME); exit(EX_DATAERR); } logmsg(LOG_INFO, "running as uid: %i, gid: %i", (int) uid, (int) gid); if (opt_keepdir != NULL) { if (S_IRWXO & st.st_mode) { logmsg(LOG_ERR, "directory to keep data: %s: permissions too open: remove any access for other", opt_keepdir); exit(EX_DATAERR); } if (access(opt_keepdir, R_OK) < 0 && errno == EACCES) { logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no read access", opt_keepdir); exit(EX_DATAERR); } if (access(opt_keepdir, W_OK) < 0 && errno == EACCES) { logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no write access", opt_keepdir); exit(EX_DATAERR); } if (access(opt_keepdir, X_OK) < 0 && errno == EACCES) { logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no execute access", opt_keepdir); exit(EX_DATAERR); } logmsg(LOG_INFO, "directory to keep data: %s", opt_keepdir); } dict_open(opt_signingtable, &dict_signingtable); if (opt_modetable) dict_open(opt_modetable, &dict_modetable); /* initialize OpenSSL */ SSL_library_init(); OpenSSL_add_all_algorithms(); /* get meaningful error messages */ SSL_load_error_strings(); ERR_load_crypto_strings(); /* Statistik initialisieren */ init_stats(); /* Signal-Handler fuer SIGALRM */ signal(SIGALRM, sig_handler); /* Run milter */ if ((c = smfi_main()) != MI_SUCCESS) logmsg(LOG_ERR, "Milter startup failed"); else logmsg(LOG_NOTICE, "stopping %s %s listening on %s", STR_PROGNAME, STR_PROGVERSION, opt_miltersocket); dict_close(&dict_signingtable); if (opt_modetable) dict_close(&dict_modetable); /* cleanup OpenSSL */ ERR_free_strings(); EVP_cleanup(); output_stats(); #ifdef DMALLOC dmalloc_log_stats(); dmalloc_log_unfreed(); dmalloc_shutdown(); #endif exit(c); }
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); }