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 */