1/* $NetBSD$ */ 2 3/*++ 4/* NAME 5/* mail_addr_crunch 3 6/* SUMMARY 7/* parse and canonicalize addresses, apply address extension 8/* SYNOPSIS 9/* #include <mail_addr_crunch.h> 10/* 11/* ARGV *mail_addr_crunch(string, extension) 12/* const char *string; 13/* const char *extension; 14/* DESCRIPTION 15/* mail_addr_crunch() parses a string with zero or more addresses, 16/* rewrites each address to canonical form, and optionally applies 17/* an address extension to each resulting address. Input and result 18/* are in external (quoted) format. The caller is expected to pass 19/* the result to argv_free(). 20/* 21/* Arguments: 22/* .IP string 23/* A string with zero or more addresses in RFC 822 (external) format. 24/* .IP extension 25/* A null pointer, or an address extension (including the recipient 26/* address delimiter) that is propagated to all result addresses. 27/* DIAGNOSTICS 28/* Fatal error: out of memory. 29/* SEE ALSO 30/* tok822_parse(3), address parser 31/* canon_addr(3), address canonicalization 32/* LICENSE 33/* .ad 34/* .fi 35/* The Secure Mailer license must be distributed with this software. 36/* AUTHOR(S) 37/* Wietse Venema 38/* IBM T.J. Watson Research 39/* P.O. Box 704 40/* Yorktown Heights, NY 10598, USA 41/*--*/ 42 43/* System library. */ 44 45#include <sys_defs.h> 46#include <string.h> 47 48/* Utility library. */ 49 50#include <mymalloc.h> 51#include <argv.h> 52#include <vstring.h> 53 54/* Global library. */ 55 56#include <tok822.h> 57#include <canon_addr.h> 58#include <mail_addr_crunch.h> 59 60/* mail_addr_crunch - break string into addresses, optionally add extension */ 61 62ARGV *mail_addr_crunch(const char *string, const char *extension) 63{ 64 VSTRING *extern_addr = vstring_alloc(100); 65 VSTRING *canon_addr = vstring_alloc(100); 66 ARGV *argv = argv_alloc(1); 67 TOK822 *tree; 68 TOK822 **addr_list; 69 TOK822 **tpp; 70 char *ratsign; 71 ssize_t extlen; 72 73 if (extension) 74 extlen = strlen(extension); 75 76#define STR(x) vstring_str(x) 77 78 /* 79 * Parse the string, rewrite each address to canonical form, and convert 80 * the result to external (quoted) form. Optionally apply the extension 81 * to each address found. 82 * 83 * XXX Workaround for the null address. This works for envelopes but 84 * produces ugly results for message headers. 85 */ 86 if (*string == 0 || strcmp(string, "<>") == 0) 87 string = "\"\""; 88 tree = tok822_parse(string); 89 addr_list = tok822_grep(tree, TOK822_ADDR); 90 for (tpp = addr_list; *tpp; tpp++) { 91 tok822_externalize(extern_addr, tpp[0]->head, TOK822_STR_DEFL); 92 canon_addr_external(canon_addr, STR(extern_addr)); 93 if (extension) { 94 VSTRING_SPACE(canon_addr, extlen + 1); 95 if ((ratsign = strrchr(STR(canon_addr), '@')) == 0) { 96 vstring_strcat(canon_addr, extension); 97 } else { 98 memmove(ratsign + extlen, ratsign, strlen(ratsign) + 1); 99 memcpy(ratsign, extension, extlen); 100 VSTRING_SKIP(canon_addr); 101 } 102 } 103 argv_add(argv, STR(canon_addr), ARGV_END); 104 } 105 argv_terminate(argv); 106 myfree((char *) addr_list); 107 tok822_free_tree(tree); 108 vstring_free(canon_addr); 109 vstring_free(extern_addr); 110 return (argv); 111} 112 113#ifdef TEST 114 115 /* 116 * Stand-alone test program, sort of interactive. 117 */ 118#include <stdlib.h> 119#include <unistd.h> 120#include <msg.h> 121#include <vstream.h> 122#include <vstring_vstream.h> 123#include <mail_conf.h> 124#include <mail_params.h> 125 126int main(int unused_argc, char **unused_argv) 127{ 128 VSTRING *extension = vstring_alloc(1); 129 VSTRING *buf = vstring_alloc(1); 130 ARGV *argv; 131 char **cpp; 132 133 mail_conf_read(); 134 if (chdir(var_queue_dir) < 0) 135 msg_fatal("chdir %s: %m", var_queue_dir); 136 137 vstream_printf("extension: (CR for none): "); 138 vstream_fflush(VSTREAM_OUT); 139 if (vstring_get_nonl(extension, VSTREAM_IN) == VSTREAM_EOF) 140 exit(0); 141 142 vstream_printf("print strings to be translated, one per line\n"); 143 vstream_fflush(VSTREAM_OUT); 144 while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { 145 argv = mail_addr_crunch(STR(buf), VSTRING_LEN(extension) ? STR(extension) : 0); 146 for (cpp = argv->argv; *cpp; cpp++) 147 vstream_printf(" %s\n", *cpp); 148 vstream_fflush(VSTREAM_OUT); 149 } 150 return (0); 151} 152 153#endif 154