1/*++ 2/* NAME 3/* mail_addr_map 3 4/* SUMMARY 5/* generic address mapping 6/* SYNOPSIS 7/* #include <mail_addr_map.h> 8/* 9/* ARGV *mail_addr_map(path, address, propagate) 10/* MAPS *path; 11/* const char *address; 12/* int propagate; 13/* DESCRIPTION 14/* mail_addr_map() returns the translation for the named address, 15/* or a null pointer if none is found. The result is in canonical 16/* external (quoted) form. The search is case insensitive. 17/* 18/* When the \fBpropagate\fR argument is non-zero, 19/* address extensions that aren't explicitly matched in the lookup 20/* table are propagated to the result addresses. The caller is 21/* expected to pass the result to argv_free(). 22/* 23/* Lookups are performed by mail_addr_find(). When the result has the 24/* form \fI@otherdomain\fR, the result is the original user in 25/* \fIotherdomain\fR. 26/* 27/* Arguments: 28/* .IP path 29/* Dictionary search path (see maps(3)). 30/* .IP address 31/* The address to be looked up. 32/* DIAGNOSTICS 33/* Warnings: map lookup returns a non-address result. 34/* 35/* The path->error value is non-zero when the lookup 36/* should be tried again. 37/* SEE ALSO 38/* mail_addr_find(3), mail address matching 39/* mail_addr_crunch(3), mail address parsing and rewriting 40/* LICENSE 41/* .ad 42/* .fi 43/* The Secure Mailer license must be distributed with this software. 44/* AUTHOR(S) 45/* Wietse Venema 46/* IBM T.J. Watson Research 47/* P.O. Box 704 48/* Yorktown Heights, NY 10598, USA 49/*--*/ 50 51/* System library. */ 52 53#include <sys_defs.h> 54#include <string.h> 55 56/* Utility library. */ 57 58#include <msg.h> 59#include <vstring.h> 60#include <dict.h> 61#include <argv.h> 62#include <mymalloc.h> 63 64/* Global library. */ 65 66#include <mail_addr_find.h> 67#include <mail_addr_crunch.h> 68#include <mail_addr_map.h> 69 70/* Application-specific. */ 71 72#define STR vstring_str 73#define LEN VSTRING_LEN 74 75/* mail_addr_map - map a canonical address */ 76 77ARGV *mail_addr_map(MAPS *path, const char *address, int propagate) 78{ 79 VSTRING *buffer = 0; 80 const char *myname = "mail_addr_map"; 81 const char *string; 82 char *ratsign; 83 char *extension = 0; 84 ARGV *argv = 0; 85 int i; 86 87 /* 88 * Look up the full address; if no match is found, look up the address 89 * with the extension stripped off, and remember the unmatched extension. 90 */ 91 if ((string = mail_addr_find(path, address, &extension)) != 0) { 92 93 /* 94 * Prepend the original user to @otherdomain, but do not propagate 95 * the unmatched address extension. 96 */ 97 if (*string == '@') { 98 buffer = vstring_alloc(100); 99 if ((ratsign = strrchr(address, '@')) != 0) 100 vstring_strncpy(buffer, address, ratsign - address); 101 else 102 vstring_strcpy(buffer, address); 103 if (extension) 104 vstring_truncate(buffer, LEN(buffer) - strlen(extension)); 105 vstring_strcat(buffer, string); 106 string = STR(buffer); 107 } 108 109 /* 110 * Canonicalize and externalize the result, and propagate the 111 * unmatched extension to each address found. 112 */ 113 argv = mail_addr_crunch(string, propagate ? extension : 0); 114 if (buffer) 115 vstring_free(buffer); 116 if (msg_verbose) 117 for (i = 0; i < argv->argc; i++) 118 msg_info("%s: %s -> %d: %s", myname, address, i, argv->argv[i]); 119 if (argv->argc == 0) { 120 msg_warn("%s lookup of %s returns non-address result \"%s\"", 121 path->title, address, string); 122 argv = argv_free(argv); 123 path->error = DICT_ERR_RETRY; 124 } 125 } 126 127 /* 128 * No match found. 129 */ 130 else { 131 if (msg_verbose) 132 msg_info("%s: %s -> %s", myname, address, 133 path->error ? "(try again)" : "(not found)"); 134 } 135 136 /* 137 * Cleanup. 138 */ 139 if (extension) 140 myfree(extension); 141 142 return (argv); 143} 144 145#ifdef TEST 146 147 /* 148 * Proof-of-concept test program. Read an address from stdin, and spit out 149 * the lookup result. 150 */ 151#include <unistd.h> 152#include <mail_conf.h> 153#include <vstream.h> 154#include <vstring_vstream.h> 155#include <mail_params.h> 156 157int main(int argc, char **argv) 158{ 159 VSTRING *buffer = vstring_alloc(100); 160 MAPS *path; 161 ARGV *result; 162 163 /* 164 * Parse JCL. 165 */ 166 if (argc != 2) 167 msg_fatal("usage: %s database", argv[0]); 168 169 /* 170 * Initialize. 171 */ 172#define UPDATE(dst, src) { myfree(dst); dst = mystrdup(src); } 173 174 mail_conf_read(); 175 msg_verbose = 1; 176 if (chdir(var_queue_dir) < 0) 177 msg_fatal("chdir %s: %m", var_queue_dir); 178 path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 179 while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { 180 msg_info("=== Address extension on, extension propagation on ==="); 181 UPDATE(var_rcpt_delim, "+"); 182 if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) 183 argv_free(result); 184 msg_info("=== Address extension on, extension propagation off ==="); 185 if ((result = mail_addr_map(path, STR(buffer), 0)) != 0) 186 argv_free(result); 187 msg_info("=== Address extension off ==="); 188 UPDATE(var_rcpt_delim, ""); 189 if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) 190 argv_free(result); 191 } 192 vstring_free(buffer); 193 maps_free(path); 194 return (0); 195} 196 197#endif 198