Mercurial > masqmail
comparison src/alias.c @ 387:a408411ff8df
Added a glob-pattern aliasing facility.
One use-case is virtual hosting another catch-all maildrops, but you may
use it as a more flexible aliasing mechanism as well.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Sat, 18 Feb 2012 12:35:12 +0100 |
parents | 028bc124d744 |
children | 68ae9182059c |
comparison
equal
deleted
inserted
replaced
386:13c9e0969054 | 387:a408411ff8df |
---|---|
102 p++; | 102 p++; |
103 } | 103 } |
104 return list; | 104 return list; |
105 } | 105 } |
106 | 106 |
107 static int | |
108 globaliascmp(const char *pattern, const char *addr) | |
109 { | |
110 if (conf.localpartcmp==strcasecmp) { | |
111 return fnmatch(pattern, addr, FNM_CASEFOLD); | |
112 } else if (strncasecmp(addr, "postmaster", 10)==0) { | |
113 /* | |
114 ** postmaster must always be matched caseless | |
115 ** see RFC 822 and RFC 5321 | |
116 */ | |
117 return fnmatch(pattern, addr, FNM_CASEFOLD); | |
118 } else { | |
119 /* case-sensitive */ | |
120 return fnmatch(pattern, addr, 0); | |
121 } | |
122 } | |
123 | |
107 /* | 124 /* |
108 ** addr is assumed to be local and no pipe address nor not-to-expand | 125 ** addr is assumed to be local and no pipe address nor not-to-expand |
109 */ | 126 */ |
110 static GList* | 127 static GList* |
111 expand_one(GList *alias_table, address *addr) | 128 expand_one(GList *alias_table, address *addr, int doglob) |
112 { | 129 { |
113 GList *val_list; | 130 GList *val_list; |
114 GList *val_node; | 131 GList *val_node; |
115 GList *alias_list = NULL; | 132 GList *alias_list = NULL; |
116 GList *alias_node; | 133 GList *alias_node; |
117 gchar *val; | 134 gchar *val; |
118 | 135 |
119 /* expand the local alias */ | 136 /* expand the local alias */ |
120 DEBUG(6) debugf("alias: '%s' is local and will get expanded\n", addr->local_part); | 137 DEBUG(6) debugf("alias: '%s' is local and will get expanded\n", |
121 | 138 doglob ? addr->address : addr->local_part); |
122 if (strcasecmp(addr->local_part, "postmaster") == 0) { | 139 |
140 if (doglob) { | |
141 val = (gchar *) table_find_func(alias_table, addr->address, | |
142 globaliascmp); | |
143 | |
144 } else if (strcasecmp(addr->local_part, "postmaster") == 0) { | |
123 /* | 145 /* |
124 ** postmaster must always be matched caseless | 146 ** postmaster must always be matched caseless |
125 ** see RFC 822 and RFC 5321 | 147 ** see RFC 822 and RFC 5321 |
126 */ | 148 */ |
127 val = (gchar *) table_find_func(alias_table, addr->local_part, strcasecmp); | 149 val = (gchar *) table_find_func(alias_table, addr->local_part, |
150 strcasecmp); | |
128 } else { | 151 } else { |
129 val = (gchar *) table_find_func(alias_table, addr->local_part, conf.localpartcmp); | 152 val = (gchar *) table_find_func(alias_table, addr->local_part, |
153 conf.localpartcmp); | |
130 } | 154 } |
131 if (!val) { | 155 if (!val) { |
132 DEBUG(5) debugf("alias: '%s' is fully expanded, hence completed\n", | 156 DEBUG(5) debugf("alias: '%s' is fully expanded, hence " |
133 addr->local_part); | 157 "completed\n", |
158 doglob ? addr->address : addr->local_part); | |
134 return g_list_append(NULL, addr); | 159 return g_list_append(NULL, addr); |
135 } | 160 } |
136 | 161 |
137 DEBUG(5) debugf("alias: '%s' -> '%s'\n", addr->local_part, val); | 162 DEBUG(5) debugf("alias: '%s' -> '%s'\n", |
163 doglob ? addr->address : addr->local_part, val); | |
138 val_list = parse_list(val); | 164 val_list = parse_list(val); |
139 alias_list = NULL; | 165 alias_list = NULL; |
140 | 166 |
141 foreach(val_list, val_node) { | 167 foreach(val_list, val_node) { |
142 gchar *val = (gchar *) (val_node->data); | 168 gchar *val = (gchar *) (val_node->data); |
147 if (val[0] == '\\') { | 173 if (val[0] == '\\') { |
148 DEBUG(5) debugf("alias: '%s' is marked as final, hence completed\n", val); | 174 DEBUG(5) debugf("alias: '%s' is marked as final, hence completed\n", val); |
149 alias_addr = create_address_qualified(val+1, TRUE, conf.host_name); | 175 alias_addr = create_address_qualified(val+1, TRUE, conf.host_name); |
150 g_free(val); | 176 g_free(val); |
151 DEBUG(6) debugf("alias: address generated: '%s'\n", | 177 DEBUG(6) debugf("alias: address generated: '%s'\n", |
152 alias_addr->local_part); | 178 alias_addr->address); |
153 alias_list = g_list_append(alias_list, alias_addr); | 179 alias_list = g_list_append(alias_list, alias_addr); |
154 continue; | 180 continue; |
155 } | 181 } |
156 | 182 |
157 if (val[0] == '|') { | 183 if (val[0] == '|') { |
166 | 192 |
167 alias_addr = create_address_qualified(val, TRUE, conf.host_name); | 193 alias_addr = create_address_qualified(val, TRUE, conf.host_name); |
168 g_free(val); | 194 g_free(val); |
169 | 195 |
170 if (!addr_is_local(alias_addr)) { | 196 if (!addr_is_local(alias_addr)) { |
171 DEBUG(5) debugf("alias: '%s@%s' is non-local, hence completed\n", | 197 DEBUG(5) debugf("alias: '%s' is non-local, hence completed\n", |
172 alias_addr->local_part, alias_addr->domain); | 198 alias_addr->address); |
173 alias_list = g_list_append(alias_list, alias_addr); | 199 alias_list = g_list_append(alias_list, alias_addr); |
174 continue; | 200 continue; |
175 } | 201 } |
176 | 202 |
177 /* addr is local and to expand at this point */ | 203 /* addr is local and to expand at this point */ |
184 } | 210 } |
185 alias_addr->parent = addr; | 211 alias_addr->parent = addr; |
186 | 212 |
187 /* recurse */ | 213 /* recurse */ |
188 DEBUG(6) debugf("alias: >>\n"); | 214 DEBUG(6) debugf("alias: >>\n"); |
189 alias_node = expand_one(alias_table, alias_addr); | 215 alias_node = expand_one(alias_table, alias_addr, doglob); |
190 DEBUG(6) debugf("alias: <<\n"); | 216 DEBUG(6) debugf("alias: <<\n"); |
191 if (alias_node) { | 217 if (alias_node) { |
192 alias_list = g_list_concat(alias_list, alias_node); | 218 alias_list = g_list_concat(alias_list, alias_node); |
193 } | 219 } |
194 } | 220 } |
197 | 223 |
198 return alias_list; | 224 return alias_list; |
199 } | 225 } |
200 | 226 |
201 GList* | 227 GList* |
202 alias_expand(GList *alias_table, GList *rcpt_list, GList *non_rcpt_list) | 228 alias_expand(GList *alias_table, GList *rcpt_list, GList *non_rcpt_list, |
229 int doglob) | |
203 { | 230 { |
204 GList *rcpt_node = NULL; | 231 GList *rcpt_node = NULL; |
205 GList *alias_list = NULL; | 232 GList *alias_list = NULL; |
206 GList *done_list = NULL; | 233 GList *done_list = NULL; |
207 GList *rcpt_node_next = NULL; | 234 GList *rcpt_node_next = NULL; |
212 rcpt_node=g_list_next(rcpt_node)) { | 239 rcpt_node=g_list_next(rcpt_node)) { |
213 | 240 |
214 addr = (address *) (rcpt_node->data); | 241 addr = (address *) (rcpt_node->data); |
215 if (addr_is_local(addr)) { | 242 if (addr_is_local(addr)) { |
216 DEBUG(5) debugf("alias: (orig rcpt addr) expand local '%s'\n", | 243 DEBUG(5) debugf("alias: (orig rcpt addr) expand local '%s'\n", |
217 addr->local_part); | 244 doglob ? addr->address : addr->local_part); |
218 alias_list = expand_one(alias_table, addr); | 245 alias_list = expand_one(alias_table, addr, doglob); |
219 if (alias_list) { | 246 if (alias_list) { |
220 done_list = g_list_concat(done_list, alias_list); | 247 done_list = g_list_concat(done_list, alias_list); |
221 } | 248 } |
222 } else { | 249 } else { |
223 DEBUG(5) debugf("alias: (orig rcpt addr) don't expand non-local '%s@%s'\n", | 250 DEBUG(5) debugf("alias: (orig rcpt addr) don't expand non-local '%s'\n", |
224 addr->local_part, addr->domain); | 251 addr->address); |
225 done_list = g_list_append(done_list, addr); | 252 done_list = g_list_append(done_list, addr); |
226 } | 253 } |
227 } | 254 } |
228 | 255 |
229 /* we're done if we don't have to remove rcpts */ | 256 /* we're done if we don't have to remove rcpts */ |