1 /* $NetBSD: cleanup_map1n.c,v 1.1.1.1 2009/06/23 10:08:43 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* cleanup_map1n 3 6 /* SUMMARY 7 /* one-to-many address mapping 8 /* SYNOPSIS 9 /* #include <cleanup.h> 10 /* 11 /* ARGV *cleanup_map1n_internal(state, addr, maps, propagate) 12 /* CLEANUP_STATE *state; 13 /* const char *addr; 14 /* MAPS *maps; 15 /* int propagate; 16 /* DESCRIPTION 17 /* This module implements one-to-many table mapping via table lookup. 18 /* Table lookups are done with quoted (externalized) address forms. 19 /* The process is recursive. The recursion terminates when the 20 /* left-hand side appears in its own expansion, or when a maximal 21 /* nesting level is reached. 22 /* 23 /* cleanup_map1n_internal() is the interface for addresses in 24 /* internal (unquoted) form. 25 /* DIAGNOSTICS 26 /* Recoverable errors: the global \fIcleanup_errs\fR flag is updated. 27 /* SEE ALSO 28 /* mail_addr_map(3) address mappings 29 /* mail_addr_find(3) address lookups 30 /* LICENSE 31 /* .ad 32 /* .fi 33 /* The Secure Mailer license must be distributed with this software. 34 /* AUTHOR(S) 35 /* Wietse Venema 36 /* IBM T.J. Watson Research 37 /* P.O. Box 704 38 /* Yorktown Heights, NY 10598, USA 39 /*--*/ 40 41 /* System library. */ 42 43 #include <sys_defs.h> 44 #include <string.h> 45 46 #ifdef STRCASECMP_IN_STRINGS_H 47 #include <strings.h> 48 #endif 49 50 /* Utility library. */ 51 52 #include <mymalloc.h> 53 #include <msg.h> 54 #include <argv.h> 55 #include <vstring.h> 56 #include <dict.h> 57 58 /* Global library. */ 59 60 #include <mail_params.h> 61 #include <mail_addr_map.h> 62 #include <cleanup_user.h> 63 #include <quote_822_local.h> 64 #include <been_here.h> 65 66 /* Application-specific. */ 67 68 #include "cleanup.h" 69 70 /* cleanup_map1n_internal - one-to-many table lookups */ 71 72 ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, 73 MAPS *maps, int propagate) 74 { 75 ARGV *argv; 76 ARGV *lookup; 77 int count; 78 int i; 79 int arg; 80 BH_TABLE *been_here; 81 char *saved_lhs; 82 83 /* 84 * Initialize. 85 */ 86 argv = argv_alloc(1); 87 argv_add(argv, addr, ARGV_END); 88 argv_terminate(argv); 89 been_here = been_here_init(0, BH_FLAG_FOLD); 90 91 /* 92 * Rewrite the address vector in place. With each map lookup result, 93 * split it into separate addresses, then rewrite and flatten each 94 * address, and repeat the process. Beware: argv is being changed, so we 95 * must index the array explicitly, instead of running along it with a 96 * pointer. 97 */ 98 #define UPDATE(ptr,new) { myfree(ptr); ptr = mystrdup(new); } 99 #define STR vstring_str 100 #define RETURN(x) { been_here_free(been_here); return (x); } 101 102 for (arg = 0; arg < argv->argc; arg++) { 103 if (argv->argc > var_virt_expan_limit) { 104 msg_warn("%s: unreasonable %s map expansion size for %s", 105 state->queue_id, maps->title, addr); 106 break; 107 } 108 for (count = 0; /* void */ ; count++) { 109 110 /* 111 * Don't expand an address that already expanded into itself. 112 */ 113 if (been_here_check_fixed(been_here, argv->argv[arg]) != 0) 114 break; 115 if (count >= var_virt_recur_limit) { 116 msg_warn("%s: unreasonable %s map nesting for %s", 117 state->queue_id, maps->title, addr); 118 break; 119 } 120 quote_822_local(state->temp1, argv->argv[arg]); 121 if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) { 122 saved_lhs = mystrdup(argv->argv[arg]); 123 for (i = 0; i < lookup->argc; i++) { 124 unquote_822_local(state->temp1, lookup->argv[i]); 125 if (i == 0) { 126 UPDATE(argv->argv[arg], STR(state->temp1)); 127 } else { 128 argv_add(argv, STR(state->temp1), ARGV_END); 129 argv_terminate(argv); 130 } 131 132 /* 133 * Allow an address to expand into itself once. 134 */ 135 if (strcasecmp(saved_lhs, STR(state->temp1)) == 0) 136 been_here_fixed(been_here, saved_lhs); 137 } 138 myfree(saved_lhs); 139 argv_free(lookup); 140 } else if (dict_errno != 0) { 141 msg_warn("%s: %s map lookup problem for %s", 142 state->queue_id, maps->title, addr); 143 state->errs |= CLEANUP_STAT_WRITE; 144 RETURN(argv); 145 } else { 146 break; 147 } 148 } 149 } 150 RETURN(argv); 151 } 152