Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / mail_addr_find.c
blobee60a1ba5c10530b0bf9f47313cf8cad299c8916
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* mail_addr_find 3
6 /* SUMMARY
7 /* generic address-based lookup
8 /* SYNOPSIS
9 /* #include <mail_addr_find.h>
11 /* const char *mail_addr_find(maps, address, extension)
12 /* MAPS *maps;
13 /* const char *address;
14 /* char **extension;
15 /* DESCRIPTION
16 /* mail_addr_find() searches the specified maps for an entry with as
17 /* key the specified address, and derivations from that address.
18 /* It is up to the caller to specify its case sensitivity
19 /* preferences when it opens the maps.
20 /* The result is overwritten upon each call.
22 /* An address that is in the form \fIuser\fR matches itself.
24 /* Given an address of the form \fIuser@domain\fR, the following
25 /* lookups are done in the given order until one returns a result:
26 /* .IP user@domain
27 /* Look up the entire address.
28 /* .IP user
29 /* Look up \fIuser\fR when \fIdomain\fR is equal to $myorigin,
30 /* when \fIdomain\fR matches $mydestination, or when it matches
31 /* $inet_interfaces or $proxy_interfaces.
32 /* .IP @domain
33 /* Look for an entry that matches the domain specified in \fIaddress\fR.
34 /* .PP
35 /* With address extension enabled, the table lookup order is:
36 /* \fIuser+extension\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR,
37 /* \fIuser+extension\fR, \fIuser\fR, and @\fIdomain\fR.
38 /* .PP
39 /* Arguments:
40 /* .IP maps
41 /* Dictionary search path (see maps(3)).
42 /* .IP address
43 /* The address to be looked up.
44 /* .IP extension
45 /* A null pointer, or the address of a pointer that is set to
46 /* the address of a dynamic memory copy of the address extension
47 /* that had to be chopped off in order to match the lookup tables.
48 /* The copy includes the recipient address delimiter.
49 /* The caller is expected to pass the copy to myfree().
50 /* DIAGNOSTICS
51 /* The global \fIdict_errno\fR is non-zero when the lookup
52 /* should be tried again.
53 /* SEE ALSO
54 /* maps(3), multi-dictionary search
55 /* resolve_local(3), recognize local system
56 /* LICENSE
57 /* .ad
58 /* .fi
59 /* The Secure Mailer license must be distributed with this software.
60 /* AUTHOR(S)
61 /* Wietse Venema
62 /* IBM T.J. Watson Research
63 /* P.O. Box 704
64 /* Yorktown Heights, NY 10598, USA
65 /*--*/
67 /* System library. */
69 #include <sys_defs.h>
70 #include <string.h>
72 #ifdef STRCASECMP_IN_STRINGS_H
73 #include <strings.h>
74 #endif
76 /* Utility library. */
78 #include <msg.h>
79 #include <dict.h>
80 #include <stringops.h>
81 #include <mymalloc.h>
82 #include <vstring.h>
84 /* Global library. */
86 #include <mail_params.h>
87 #include <strip_addr.h>
88 #include <mail_addr_find.h>
89 #include <resolve_local.h>
91 /* Application-specific. */
93 #define STR vstring_str
95 /* mail_addr_find - map a canonical address */
97 const char *mail_addr_find(MAPS *path, const char *address, char **extp)
99 const char *myname = "mail_addr_find";
100 const char *result;
101 char *ratsign = 0;
102 char *full_key;
103 char *bare_key;
104 char *saved_ext;
107 * Initialize.
109 full_key = mystrdup(address);
110 if (*var_rcpt_delim == 0) {
111 bare_key = saved_ext = 0;
112 } else {
113 bare_key = strip_addr(full_key, &saved_ext, *var_rcpt_delim);
117 * Try user+foo@domain and user@domain.
119 * Specify what keys are partial or full, to avoid matching partial
120 * addresses with regular expressions.
122 #define FULL 0
123 #define PARTIAL DICT_FLAG_FIXED
125 if ((result = maps_find(path, full_key, FULL)) == 0 && dict_errno == 0
126 && bare_key != 0 && (result = maps_find(path, bare_key, PARTIAL)) != 0
127 && extp != 0) {
128 *extp = saved_ext;
129 saved_ext = 0;
133 * Try user+foo@$myorigin, user+foo@$mydestination or
134 * user+foo@[${proxy,inet}_interfaces]. Then try with +foo stripped off.
136 if (result == 0 && dict_errno == 0
137 && (ratsign = strrchr(full_key, '@')) != 0
138 && (strcasecmp(ratsign + 1, var_myorigin) == 0
139 || resolve_local(ratsign + 1))) {
140 *ratsign = 0;
141 result = maps_find(path, full_key, PARTIAL);
142 if (result == 0 && dict_errno == 0 && bare_key != 0) {
143 if ((ratsign = strrchr(bare_key, '@')) == 0)
144 msg_panic("%s: bare key botch", myname);
145 *ratsign = 0;
146 if ((result = maps_find(path, bare_key, PARTIAL)) != 0 && extp != 0) {
147 *extp = saved_ext;
148 saved_ext = 0;
151 *ratsign = '@';
155 * Try @domain.
157 if (result == 0 && dict_errno == 0 && ratsign)
158 result = maps_find(path, ratsign, PARTIAL);
161 * Clean up.
163 if (msg_verbose)
164 msg_info("%s: %s -> %s", myname, address,
165 result ? result :
166 dict_errno ? "(try again)" :
167 "(not found)");
168 myfree(full_key);
169 if (bare_key)
170 myfree(bare_key);
171 if (saved_ext)
172 myfree(saved_ext);
174 return (result);
177 #ifdef TEST
180 * Proof-of-concept test program. Read an address from stdin, and spit out
181 * the lookup result.
183 #include <vstream.h>
184 #include <vstring_vstream.h>
185 #include <mail_conf.h>
187 int main(int argc, char **argv)
189 VSTRING *buffer = vstring_alloc(100);
190 MAPS *path;
191 const char *result;
192 char *extent;
195 * Parse JCL.
197 if (argc != 2)
198 msg_fatal("usage: %s database", argv[0]);
199 msg_verbose = 1;
202 * Initialize.
204 mail_conf_read();
205 path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
206 while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
207 extent = 0;
208 result = mail_addr_find(path, STR(buffer), &extent);
209 vstream_printf("%s -> %s (%s)\n", STR(buffer), result ? result :
210 dict_errno ? "(try again)" :
211 "(not found)", extent ? extent : "null extension");
212 vstream_fflush(VSTREAM_OUT);
213 if (extent)
214 myfree(extent);
216 vstring_free(buffer);
218 maps_free(path);
219 return (0);
222 #endif