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