/*++ /* NAME /* mail_addr_map 3 /* SUMMARY /* generic address mapping /* SYNOPSIS /* #include /* /* ARGV *mail_addr_map(path, address, propagate) /* MAPS *path; /* const char *address; /* int propagate; /* DESCRIPTION /* mail_addr_map() returns the translation for the named address, /* or a null pointer if none is found. The result is in canonical /* external (quoted) form. The search is case insensitive. /* /* When the \fBpropagate\fR argument is non-zero, /* address extensions that aren't explicitly matched in the lookup /* table are propagated to the result addresses. The caller is /* expected to pass the result to argv_free(). /* /* Lookups are performed by mail_addr_find(). When the result has the /* form \fI@otherdomain\fR, the result is the original user in /* \fIotherdomain\fR. /* /* Arguments: /* .IP path /* Dictionary search path (see maps(3)). /* .IP address /* The address to be looked up. /* DIAGNOSTICS /* The global \fIdict_errno\fR is non-zero when the lookup /* should be tried again. /* SEE ALSO /* mail_addr_find(3), mail address matching /* mail_addr_crunch(3), mail address parsing and rewriting /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include /* Utility library. */ #include #include #include #include #include /* Global library. */ #include #include #include /* Application-specific. */ #define STR vstring_str #define LEN VSTRING_LEN /* mail_addr_map - map a canonical address */ ARGV *mail_addr_map(MAPS *path, const char *address, int propagate) { VSTRING *buffer = 0; char *myname = "mail_addr_map"; const char *string; char *ratsign; char *extension = 0; ARGV *argv = 0; int i; /* * Look up the full address; if no match is found, look up the address * with the extension stripped off, and remember the unmatched extension. */ if ((string = mail_addr_find(path, address, &extension)) != 0) { /* * Prepend the original user to @otherdomain, but do not propagate * the unmatched address extension. */ if (*string == '@') { buffer = vstring_alloc(100); if ((ratsign = strrchr(address, '@')) != 0) vstring_strncpy(buffer, address, ratsign - address); else vstring_strcpy(buffer, address); if (extension) vstring_truncate(buffer, LEN(buffer) - strlen(extension)); vstring_strcat(buffer, string); string = STR(buffer); } /* * Canonicalize and externalize the result, and propagate the * unmatched extension to each address found. */ argv = mail_addr_crunch(string, propagate ? extension : 0); if (buffer) vstring_free(buffer); if (msg_verbose) for (i = 0; i < argv->argc; i++) msg_info("%s: %s -> %d: %s", myname, address, i, argv->argv[i]); } /* * No match found. */ else { if (msg_verbose) msg_info("%s: %s -> %s", myname, address, dict_errno ? "(try again)" : "(not found)"); } /* * Cleanup. */ if (extension) myfree(extension); return (argv); } #ifdef TEST /* * Proof-of-concept test program. Read an address from stdin, and spit out * the lookup result. */ #include #include #include #include #include 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); 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); } #endif