Mercurial > masqmail
comparison src/alias.c @ 10:26e34ae9a3e3
changed indention and line wrapping to a more consistent style
author | meillo@marmaro.de |
---|---|
date | Mon, 27 Oct 2008 16:23:10 +0100 |
parents | 08114f7dcc23 |
children | a8f3424347dc |
comparison
equal
deleted
inserted
replaced
9:31cc8a89cb74 | 10:26e34ae9a3e3 |
---|---|
17 */ | 17 */ |
18 | 18 |
19 #include "masqmail.h" | 19 #include "masqmail.h" |
20 #include <fnmatch.h> | 20 #include <fnmatch.h> |
21 | 21 |
22 gboolean addr_is_local(address *addr) | 22 gboolean |
23 addr_is_local(address * addr) | |
23 { | 24 { |
24 GList *dom_node; | 25 GList *dom_node; |
25 GList *addr_node; | 26 GList *addr_node; |
26 address *a; | 27 address *a; |
27 | 28 |
28 foreach(conf.local_hosts, dom_node){ | 29 foreach(conf.local_hosts, dom_node) { |
29 if(addr->domain == NULL) | 30 if (addr->domain == NULL) |
30 return TRUE; | 31 return TRUE; |
31 if(fnmatch(dom_node->data, addr->domain, FNM_CASEFOLD) == 0){ | 32 if (fnmatch(dom_node->data, addr->domain, FNM_CASEFOLD) == 0) { |
32 foreach(conf.not_local_addresses,addr_node){ | 33 foreach(conf.not_local_addresses, addr_node) { |
33 a = create_address_qualified(addr_node->data, TRUE, conf.host_name); | 34 a = create_address_qualified(addr_node->data, TRUE, conf.host_name); |
34 if(addr_isequal(a,addr)){ | 35 if (addr_isequal(a, addr)) { |
35 destroy_address(a); | 36 destroy_address(a); |
36 return FALSE; | 37 return FALSE; |
38 } | |
39 destroy_address(a); | |
40 } | |
41 return TRUE; | |
42 } | |
37 } | 43 } |
38 destroy_address(a); | 44 foreach(conf.local_addresses, addr_node) { |
39 } | 45 a = create_address_qualified(addr_node->data, TRUE, conf.host_name); |
40 return TRUE; | 46 if (addr_isequal(a, addr)) { |
41 } | 47 destroy_address(a); |
42 } | 48 return TRUE; |
43 foreach(conf.local_addresses,addr_node){ | 49 } |
44 a = create_address_qualified(addr_node->data, TRUE, conf.host_name); | 50 destroy_address(a); |
45 if(addr_isequal(a,addr)){ | 51 } |
46 destroy_address(a); | 52 return FALSE; |
47 return TRUE; | |
48 } | |
49 destroy_address(a); | |
50 } | |
51 return FALSE; | |
52 } | 53 } |
53 | 54 |
54 static | 55 static gboolean |
55 gboolean addr_isequal_alias(address *addr1, address *addr2) | 56 addr_isequal_alias(address * addr1, address * addr2) |
56 { | 57 { |
57 return | 58 return (conf.alias_local_cmp(addr1->local_part, addr2->local_part) == 0) |
58 (conf.alias_local_cmp(addr1->local_part, addr2->local_part) == 0) && | 59 && (strcasecmp(addr1->domain, addr2->domain) == 0); |
59 (strcasecmp(addr1->domain, addr2->domain) == 0); | |
60 } | 60 } |
61 | 61 |
62 static | 62 static GList* |
63 GList *parse_list(gchar *line) | 63 parse_list(gchar * line) |
64 { | 64 { |
65 GList *list = NULL; | 65 GList *list = NULL; |
66 gchar buf[256]; | 66 gchar buf[256]; |
67 gchar *p, *q; | 67 gchar *p, *q; |
68 | 68 |
69 p = line; | 69 p = line; |
70 while(*p != 0){ | 70 while (*p != 0) { |
71 q = buf; | 71 q = buf; |
72 while(isspace(*p)) p++; | 72 while (isspace(*p)) |
73 if(*p != '\"'){ | 73 p++; |
74 while(*p && (*p != ',') && (q < buf+255)) | 74 if (*p != '\"') { |
75 *(q++) = *(p++); | 75 while (*p && (*p != ',') && (q < buf + 255)) |
76 *q = 0; | 76 *(q++) = *(p++); |
77 }else{ | 77 *q = 0; |
78 gboolean escape = FALSE; | 78 } else { |
79 p++; | 79 gboolean escape = FALSE; |
80 while(*p && (*p != '\"' || escape) && (q < buf+255)){ | 80 p++; |
81 if((*p == '\\') && !escape) | 81 while (*p && (*p != '\"' || escape) && (q < buf + 255)) { |
82 escape = TRUE; | 82 if ((*p == '\\') && !escape) |
83 else{ | 83 escape = TRUE; |
84 escape = FALSE; | 84 else { |
85 *(q++) = *p; | 85 escape = FALSE; |
86 *(q++) = *p; | |
87 } | |
88 p++; | |
89 } | |
90 *q = 0; | |
91 while (*p && (*p != ',')) | |
92 p++; | |
93 } | |
94 list = g_list_append(list, g_strdup(g_strchomp(buf))); | |
95 if (*p) | |
96 p++; | |
86 } | 97 } |
87 p++; | 98 return list; |
88 } | |
89 *q = 0; | |
90 while(*p && (*p != ',')) p++; | |
91 } | |
92 list = g_list_append(list, g_strdup(g_strchomp(buf))); | |
93 if(*p) p++; | |
94 } | |
95 return list; | |
96 } | 99 } |
97 | 100 |
98 GList *alias_expand(GList *alias_table, GList *rcpt_list, GList *non_rcpt_list) | 101 GList* |
102 alias_expand(GList * alias_table, GList * rcpt_list, GList * non_rcpt_list) | |
99 { | 103 { |
100 GList *done_list = NULL; | 104 GList *done_list = NULL; |
101 GList *rcpt_node = g_list_copy(rcpt_list); | 105 GList *rcpt_node = g_list_copy(rcpt_list); |
102 | 106 |
103 while(rcpt_node != NULL){ | 107 while (rcpt_node != NULL) { |
104 address *addr = (address *)(rcpt_node->data); | 108 address *addr = (address *) (rcpt_node->data); |
105 DEBUG(5) debugf("alias_expand begin: '%s@%s'\n", addr->local_part, addr->domain); | 109 DEBUG(5) debugf("alias_expand begin: '%s@%s'\n", addr->local_part, addr->domain); |
106 // if(addr_is_local(addr) && (addr->local_part[0] != '|') && | 110 /* if(addr_is_local(addr) && (addr->local_part[0] != '|') && */ |
107 if(addr_is_local(addr) && | 111 if (addr_is_local(addr) && !(addr->flags & ADDR_FLAG_NOEXPAND)) { |
108 !(addr->flags & ADDR_FLAG_NOEXPAND)){ | 112 gchar *val; |
109 gchar *val; | |
110 | |
111 /* special handling for postmaster */ | |
112 if(strcasecmp(addr->local_part, "postmaster") == 0) | |
113 val = (gchar *)table_find_func(alias_table, addr->local_part, strcasecmp); | |
114 else | |
115 val = (gchar *)table_find_func(alias_table, addr->local_part, conf.alias_local_cmp); | |
116 | 113 |
117 DEBUG(5) debugf("alias: '%s' is local\n", addr->local_part); | 114 /* special handling for postmaster */ |
118 if(val != NULL){ | 115 if (strcasecmp(addr->local_part, "postmaster") == 0) |
119 GList *val_list = parse_list(val); | 116 val = (gchar *) table_find_func(alias_table, addr->local_part, strcasecmp); |
120 GList *val_node; | 117 else |
121 GList *alias_list = NULL; | 118 val = (gchar *) table_find_func(alias_table, addr->local_part, conf.alias_local_cmp); |
122 | 119 |
123 DEBUG(5) debugf("alias: '%s' -> '%s'\n", addr->local_part, val); | 120 DEBUG(5) debugf("alias: '%s' is local\n", addr->local_part); |
124 foreach(val_list, val_node){ | 121 if (val != NULL) { |
125 gchar *val = (gchar *)(val_node->data); | 122 GList *val_list = parse_list(val); |
126 address *alias_addr; | 123 GList *val_node; |
127 address *addr_parent = NULL; | 124 GList *alias_list = NULL; |
128 | 125 |
129 if(val[0] == '|'){ | 126 DEBUG(5) debugf("alias: '%s' -> '%s'\n", addr->local_part, val); |
130 DEBUG(5) debugf("alias: %s is a pipe address\n", val); | 127 foreach(val_list, val_node) { |
131 alias_addr = create_address_pipe(val); | 128 gchar *val = (gchar *) (val_node->data); |
132 DEBUG(5) debugf("alias_pipe: %s is a pipe address\n", alias_addr->local_part); | 129 address *alias_addr; |
133 }else if(val[0] == '\\'){ | 130 address *addr_parent = NULL; |
134 DEBUG(5) debugf("alias: shall not be expanded: '%s'\n", val); | |
135 alias_addr = create_address_qualified(&(val[1]), TRUE, conf.host_name); | |
136 alias_addr->flags |= ADDR_FLAG_NOEXPAND; | |
137 DEBUG(5) debugf("alias: not expanded: '%s'\n",alias_addr->local_part); | |
138 }else{ | |
139 alias_addr = create_address_qualified(val, TRUE, conf.host_name); | |
140 | 131 |
141 /* search in parents for loops: */ | 132 if (val[0] == '|') { |
142 for(addr_parent = addr; addr_parent; addr_parent = addr_parent->parent){ | 133 DEBUG(5) debugf("alias: %s is a pipe address\n", val); |
143 if(addr_isequal_alias(alias_addr, addr_parent)){ | 134 alias_addr = create_address_pipe(val); |
144 logwrite(LOG_ALERT, "detected alias loop, (ignoring): %s@%s -> %s@%s\n", | 135 DEBUG(5) debugf("alias_pipe: %s is a pipe address\n", alias_addr->local_part); |
145 addr_parent->local_part, addr_parent->domain, | 136 } else if (val[0] == '\\') { |
146 addr->local_part, addr->domain); | 137 DEBUG(5) debugf("alias: shall not be expanded: '%s'\n", val); |
147 break; | 138 alias_addr = create_address_qualified(&(val[1]), TRUE, conf.host_name); |
148 } | 139 alias_addr->flags |= ADDR_FLAG_NOEXPAND; |
149 } | 140 DEBUG(5) debugf("alias: not expanded: '%s'\n", alias_addr->local_part); |
150 } | 141 } else { |
151 if(!addr_parent){ | 142 alias_addr = create_address_qualified(val, TRUE, conf.host_name); |
152 alias_list = g_list_append(alias_list, alias_addr); | 143 |
153 alias_addr->parent = addr; | 144 /* search in parents for loops: */ |
154 } | 145 for (addr_parent = addr; addr_parent; addr_parent = addr_parent->parent) { |
155 g_free(val); | 146 if (addr_isequal_alias (alias_addr, addr_parent)) { |
147 logwrite(LOG_ALERT, | |
148 "detected alias loop, (ignoring): %s@%s -> %s@%s\n", | |
149 addr_parent->local_part, | |
150 addr_parent->domain, | |
151 addr->local_part, addr->domain); | |
152 break; | |
153 } | |
154 } | |
155 } | |
156 if (!addr_parent) { | |
157 alias_list = g_list_append(alias_list, alias_addr); | |
158 alias_addr->parent = addr; | |
159 } | |
160 g_free(val); | |
161 } | |
162 g_list_free(val_list); | |
163 addr->children = g_list_copy(alias_list); | |
164 rcpt_node = g_list_concat(rcpt_node, alias_list); | |
165 } else { | |
166 DEBUG(5) debugf("alias: '%s' is completed\n", addr->local_part); | |
167 done_list = g_list_append(done_list, addr); | |
168 } | |
169 } else { | |
170 DEBUG(5) debugf("alias: '%s@%s' is not local\n", addr->local_part, addr->domain); | |
171 done_list = g_list_append(done_list, addr); | |
172 } | |
173 rcpt_node = g_list_next(rcpt_node); | |
156 } | 174 } |
157 g_list_free(val_list); | |
158 addr->children = g_list_copy(alias_list); | |
159 rcpt_node = g_list_concat(rcpt_node, alias_list); | |
160 }else{ | |
161 DEBUG(5) debugf("alias: '%s' is completed\n", addr->local_part); | |
162 done_list = g_list_append(done_list, addr); | |
163 } | |
164 }else{ | |
165 DEBUG(5) debugf("alias: '%s@%s' is not local\n", addr->local_part, addr->domain); | |
166 done_list = g_list_append(done_list, addr); | |
167 } | |
168 rcpt_node = g_list_next(rcpt_node); | |
169 } | |
170 | 175 |
171 /* delete addresses from done_list if they are in the non_rcpt_list */ | 176 /* delete addresses from done_list if they are in the non_rcpt_list */ |
172 if(non_rcpt_list){ | 177 if (non_rcpt_list) { |
173 GList *rcpt_node_next; | 178 GList *rcpt_node_next; |
174 for(rcpt_node = g_list_first(done_list); | 179 for (rcpt_node = g_list_first(done_list); rcpt_node; rcpt_node = rcpt_node_next) { |
175 rcpt_node; | 180 address *addr = (address *) (rcpt_node->data); |
176 rcpt_node = rcpt_node_next){ | 181 GList *non_node; |
177 address *addr = (address *)(rcpt_node->data); | |
178 GList *non_node; | |
179 | 182 |
180 rcpt_node_next = g_list_next(rcpt_node); | 183 rcpt_node_next = g_list_next(rcpt_node); |
181 | 184 |
182 foreach(non_rcpt_list, non_node){ | 185 foreach(non_rcpt_list, non_node) { |
183 address *non_addr = (address *)(non_node->data); | 186 address *non_addr = (address *) (non_node->data); |
184 if(addr_isequal(addr, non_addr)){ | 187 if (addr_isequal(addr, non_addr)) { |
185 done_list = g_list_remove_link(done_list, rcpt_node); | 188 done_list = g_list_remove_link(done_list, rcpt_node); |
186 g_list_free_1(rcpt_node); | 189 g_list_free_1(rcpt_node); |
187 addr_mark_delivered(addr); /* this address is still in the children lists | 190 addr_mark_delivered(addr); /* this address is still in the children lists of the original address */ |
188 of the original address */ | 191 break; |
189 break; | 192 } |
193 } | |
194 } | |
190 } | 195 } |
191 } | 196 return done_list; |
192 } | |
193 } | |
194 return done_list; | |
195 } | 197 } |