1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include "mail.h"
18
19 static mu_assoc_t aliases;
20
21 static void
alias_free(void * data)22 alias_free (void *data)
23 {
24 mu_list_t al = data;
25 util_slist_destroy (&al);
26 }
27
28 static void
alias_print_group(const char * name,mu_list_t al)29 alias_print_group (const char *name, mu_list_t al)
30 {
31 mu_printf ("%s ", name);
32 util_slist_print (al, 0);
33 mu_printf ("\n");
34 }
35
36 static mu_list_t
alias_lookup(const char * name)37 alias_lookup (const char *name)
38 {
39 return mu_assoc_get (aliases, name);
40 }
41
42 static void
alias_print(char * name)43 alias_print (char *name)
44 {
45 if (!name)
46 {
47 mu_iterator_t itr;
48
49 if (!aliases)
50 return;
51
52 mu_assoc_get_iterator (aliases, &itr);
53 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
54 mu_iterator_next (itr))
55 {
56 const char *name;
57 mu_list_t al;
58 if (mu_iterator_current_kv (itr, (const void **)&name, (void**)&al))
59 continue;
60 alias_print_group (name, al);
61 }
62 }
63 else
64 {
65 mu_list_t al;
66
67 al = alias_lookup (name);
68 if (!al)
69 {
70 mu_error (_("\"%s\": not a group"), name);
71 return;
72 }
73 alias_print_group (name, al);
74 }
75 }
76
77 static int
alias_create(const char * name,mu_list_t * al)78 alias_create (const char *name, mu_list_t *al)
79 {
80 int rc;
81 mu_list_t l;
82
83 if (!aliases)
84 {
85 mu_assoc_create (&aliases, 0);
86 mu_assoc_set_destroy_item (aliases, alias_free);
87 }
88 if (mu_assoc_lookup_ref (aliases, name, al))
89 {
90 rc = mu_list_create (&l);
91 if (rc)
92 return rc;
93 mu_assoc_install (aliases, name, l);
94 *al = l;
95 return 0;
96 }
97 return 1;
98 }
99
100 void
alias_destroy(const char * name)101 alias_destroy (const char *name)
102 {
103 mu_assoc_remove (aliases, name);
104 }
105
106
107 static void
recursive_alias_expand(const char * name,mu_list_t exlist,mu_list_t origlist)108 recursive_alias_expand (const char *name, mu_list_t exlist, mu_list_t origlist)
109 {
110 mu_list_t al;
111 mu_iterator_t itr;
112
113 if ((al = alias_lookup (name)) == NULL)
114 {
115 if (mu_list_locate (exlist, (void*)name, NULL) == MU_ERR_NOENT)
116 mu_list_append (exlist, (void*)name);
117 return;
118 }
119
120 mu_list_get_iterator (al, &itr);
121 for (mu_iterator_first (itr);
122 !mu_iterator_is_done (itr);
123 mu_iterator_next (itr))
124 {
125 char *word;
126
127 mu_iterator_current (itr, (void **)&word);
128 if (mu_list_locate (origlist, word, NULL) == MU_ERR_NOENT)
129 {
130 mu_list_push (origlist, word);
131 recursive_alias_expand (word, exlist, origlist);
132 mu_list_pop (origlist, NULL);
133 }
134 }
135 mu_iterator_destroy (&itr);
136 }
137
138 static int
string_comp(const void * item,const void * value)139 string_comp (const void *item, const void *value)
140 {
141 return strcmp (item, value);
142 }
143
144 char *
alias_expand(const char * name)145 alias_expand (const char *name)
146 {
147 mu_list_t al;
148 mu_list_t list;
149
150 if (mailvar_is_true (mailvar_name_recursivealiases))
151 {
152 char *s;
153 mu_list_t origlist;
154
155 int status = mu_list_create (&list);
156 if (status)
157 {
158 mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, status);
159 return NULL;
160 }
161 status = mu_list_create (&origlist);
162 if (status)
163 {
164 mu_list_destroy (&origlist);
165 mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, status);
166 return NULL;
167 }
168 mu_list_set_comparator (list, string_comp);
169 mu_list_set_comparator (origlist, string_comp);
170 recursive_alias_expand (name, list, origlist);
171 s = util_slist_to_string (list, ",");
172 mu_list_destroy (&origlist);
173 mu_list_destroy (&list);
174 return s;
175 }
176
177 if ((al = alias_lookup (name)) == NULL)
178 return NULL;
179 return util_slist_to_string (al, ",");
180 }
181
182
183 struct alias_iterator
184 {
185 mu_iterator_t itr;
186 const char *prefix;
187 int prefixlen;
188 int pos;
189 };
190
191 const char *
alias_iterate_next(alias_iterator_t atr)192 alias_iterate_next (alias_iterator_t atr)
193 {
194 while (!mu_iterator_is_done (atr->itr))
195 {
196 const char *name;
197 mu_list_t al;
198
199 if (mu_iterator_current_kv (atr->itr, (const void **)&name, (void**)&al))
200 continue;
201 mu_iterator_next (atr->itr);
202 if (strlen (name) >= atr->prefixlen
203 && strncmp (name, atr->prefix, atr->prefixlen) == 0)
204 return name;
205 }
206 return NULL;
207 }
208
209 const char *
alias_iterate_first(const char * prefix,alias_iterator_t * pc)210 alias_iterate_first (const char *prefix, alias_iterator_t *pc)
211 {
212 mu_iterator_t itr;
213 alias_iterator_t atr;
214
215 if (!aliases)
216 {
217 *pc = NULL;
218 return NULL;
219 }
220
221 if (mu_assoc_get_iterator (aliases, &itr))
222 return NULL;
223 mu_iterator_first (itr);
224 atr = mu_alloc (sizeof *atr);
225 atr->prefix = prefix;
226 atr->prefixlen = strlen (prefix);
227 atr->pos = 0;
228 atr->itr = itr;
229 *pc = atr;
230
231 return alias_iterate_next (atr);
232 }
233
234 void
alias_iterate_end(alias_iterator_t * pc)235 alias_iterate_end (alias_iterator_t *pc)
236 {
237 mu_iterator_destroy (&(*pc)->itr);
238 free (*pc);
239 *pc = NULL;
240 }
241
242
243
244 /*
245 * a[lias] [alias [address...]]
246 * g[roup] [alias [address...]]
247 */
248
249 int
mail_alias(int argc,char ** argv)250 mail_alias (int argc, char **argv)
251 {
252 if (argc == 1)
253 alias_print (NULL);
254 else if (argc == 2)
255 alias_print (argv[1]);
256 else
257 {
258 mu_list_t al;
259
260 if (alias_create (argv[1], &al))
261 return 1;
262
263 argc--;
264 argv++;
265 while (--argc)
266 util_slist_add (&al, *++argv);
267 }
268 return 0;
269 }
270
271
272