int main(int argc, char **argv) { VSTRING *buffer = vstring_alloc(100); MAPS *path; ARGV *result; /* * Parse JCL. */ if (argc != 2) msg_fatal("usage: %s database", argv[0]); /* * Initialize. */ #define UPDATE(dst, src) { myfree(dst); dst = mystrdup(src); } mail_conf_read(); msg_verbose = 1; if (chdir(var_queue_dir) < 0) msg_fatal("chdir %s: %m", var_queue_dir); path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { msg_info("=== Address extension on, extension propagation on ==="); UPDATE(var_rcpt_delim, "+"); if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) argv_free(result); msg_info("=== Address extension on, extension propagation off ==="); if ((result = mail_addr_map(path, STR(buffer), 0)) != 0) argv_free(result); msg_info("=== Address extension off ==="); UPDATE(var_rcpt_delim, ""); if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) argv_free(result); } vstring_free(buffer); maps_free(path); return (0); }
int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr, MAPS *maps, int propagate) { int count; int expand_to_self; ARGV *new_addr; char *saved_addr; int did_rewrite = 0; /* * Produce sensible output even in the face of a recoverable error. This * simplifies error recovery considerably because we can do delayed error * checking in one place, instead of having error handling code all over * the place. */ for (count = 0; count < MAX_RECURSION; count++) { if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) { if (new_addr->argc > 1) msg_warn("%s: multi-valued %s entry for %s", state->queue_id, maps->title, STR(addr)); saved_addr = mystrdup(STR(addr)); did_rewrite |= strcmp(new_addr->argv[0], STR(addr)); vstring_strcpy(addr, new_addr->argv[0]); expand_to_self = !strcasecmp_utf8(saved_addr, STR(addr)); myfree(saved_addr); argv_free(new_addr); if (expand_to_self) return (did_rewrite); } else if (maps->error != 0) { msg_warn("%s: %s map lookup problem for %s -- " "message not accepted, try again later", state->queue_id, maps->title, STR(addr)); state->errs |= CLEANUP_STAT_WRITE; return (did_rewrite); } else { return (did_rewrite); } } msg_warn("%s: unreasonable %s map nesting for %s -- " "message not accepted, try again later", state->queue_id, maps->title, STR(addr)); return (did_rewrite); }
int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate) { const char *myname = "smtp_map11_external"; ARGV *new_addr; const char *result; if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) { if (new_addr->argc > 1) msg_warn("multi-valued %s result for %s", maps->title, STR(addr)); result = new_addr->argv[0]; if (msg_verbose) msg_info("%s: %s -> %s", myname, STR(addr), result); vstring_strcpy(addr, result); argv_free(new_addr); return (1); } else { if (maps->error != 0) msg_fatal("%s map lookup problem for %s", maps->title, STR(addr)); if (msg_verbose) msg_info("%s: %s not found", myname, STR(addr)); return (0); } }
ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, MAPS *maps, int propagate) { ARGV *argv; ARGV *lookup; int count; int i; int arg; BH_TABLE *been_here; char *saved_lhs; /* * Initialize. */ argv = argv_alloc(1); argv_add(argv, addr, ARGV_END); argv_terminate(argv); been_here = been_here_init(0, BH_FLAG_FOLD); /* * Rewrite the address vector in place. With each map lookup result, * split it into separate addresses, then rewrite and flatten each * address, and repeat the process. Beware: argv is being changed, so we * must index the array explicitly, instead of running along it with a * pointer. */ #define UPDATE(ptr,new) do { \ if (ptr) myfree(ptr); ptr = mystrdup(new); \ } while (0) #define STR vstring_str #define RETURN(x) do { \ been_here_free(been_here); return (x); \ } while (0) #define UNEXPAND(argv, addr) do { \ argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \ } while (0) for (arg = 0; arg < argv->argc; arg++) { if (argv->argc > var_virt_expan_limit) { msg_warn("%s: unreasonable %s map expansion size for %s -- " "message not accepted, try again later", state->queue_id, maps->title, addr); state->errs |= CLEANUP_STAT_DEFER; UPDATE(state->reason, "4.6.0 Alias expansion error"); UNEXPAND(argv, addr); RETURN(argv); } for (count = 0; /* void */ ; count++) { /* * Don't expand an address that already expanded into itself. */ if (been_here_check_fixed(been_here, argv->argv[arg]) != 0) break; if (count >= var_virt_recur_limit) { msg_warn("%s: unreasonable %s map nesting for %s -- " "message not accepted, try again later", state->queue_id, maps->title, addr); state->errs |= CLEANUP_STAT_DEFER; UPDATE(state->reason, "4.6.0 Alias expansion error"); UNEXPAND(argv, addr); RETURN(argv); } quote_822_local(state->temp1, argv->argv[arg]); if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) { saved_lhs = mystrdup(argv->argv[arg]); for (i = 0; i < lookup->argc; i++) { unquote_822_local(state->temp1, lookup->argv[i]); if (i == 0) { UPDATE(argv->argv[arg], STR(state->temp1)); } else { argv_add(argv, STR(state->temp1), ARGV_END); argv_terminate(argv); } /* * Allow an address to expand into itself once. */ if (strcasecmp(saved_lhs, STR(state->temp1)) == 0) been_here_fixed(been_here, saved_lhs); } myfree(saved_lhs); argv_free(lookup); } else if (maps->error != 0) { msg_warn("%s: %s map lookup problem for %s -- " "message not accepted, try again later", state->queue_id, maps->title, addr); state->errs |= CLEANUP_STAT_WRITE; UPDATE(state->reason, "4.6.0 Alias expansion error"); UNEXPAND(argv, addr); RETURN(argv); } else { break; } } } RETURN(argv); }