]> diplodocus.org Git - nmh/blob - uip/ali.c
Use va_copy() to get a copy of va_list, instead of using original.
[nmh] / uip / ali.c
1 /* ali.c -- list nmh mail aliases
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <h/mh.h>
9 #include <h/addrsbr.h>
10 #include <h/aliasbr.h>
11 #include <h/mts.h>
12 #include "h/done.h"
13 #include <h/utils.h>
14
15 #define ALI_SWITCHES \
16 X("alias aliasfile", 0, ALIASW) \
17 X("noalias", 0, NALIASW) \
18 X("list", 0, LISTSW) \
19 X("nolist", 0, NLISTSW) \
20 X("user", 0, USERSW) \
21 X("nouser", 0, NUSERSW) \
22 X("version", 0, VERSIONSW) \
23 X("help", 0, HELPSW) \
24
25 #define X(sw, minchars, id) id,
26 DEFINE_SWITCH_ENUM(ALI);
27 #undef X
28
29 #define X(sw, minchars, id) { sw, minchars, id },
30 DEFINE_SWITCH_ARRAY(ALI, switches);
31 #undef X
32
33 static int pos = 1;
34
35 extern struct aka *akahead;
36
37 /*
38 * prototypes
39 */
40 static void print_aka (char *, bool, int);
41 static void print_usr (char *, bool);
42
43
44 int
45 main (int argc, char **argv)
46 {
47 int i, vecp = 0;
48 bool inverted, list, noalias;
49 char *cp, **ap, **argp, buf[BUFSIZ];
50 /* Really only need to allocate for argc-1, but must allocate at least 1,
51 so go ahead and allocate for argc char pointers. */
52 char **vec = mh_xmalloc (argc * sizeof (char *)), **arguments;
53 struct aka *ak;
54
55 if (nmh_init(argv[0], true, true)) { return 1; }
56
57 mts_init ();
58 arguments = getarguments (invo_name, argc, argv, 1);
59 argp = arguments;
60
61 inverted = list = noalias = false;
62 while ((cp = *argp++)) {
63 if (*cp == '-') {
64 switch (smatch (++cp, switches)) {
65 case AMBIGSW:
66 ambigsw (cp, switches);
67 done (1);
68 case UNKWNSW:
69 die("-%s unknown", cp);
70
71 case HELPSW:
72 snprintf (buf, sizeof(buf), "%s [switches] aliases ...",
73 invo_name);
74 print_help (buf, switches, 1);
75 done (0);
76 case VERSIONSW:
77 print_version (invo_name);
78 done (0);
79
80 case ALIASW:
81 if (!(cp = *argp++) || *cp == '-')
82 die("missing argument to %s", argp[-2]);
83 if ((i = alias (cp)) != AK_OK)
84 die("aliasing error in %s - %s", cp, akerror (i));
85 continue;
86 case NALIASW:
87 noalias = true;
88 continue;
89
90 case LISTSW:
91 list = true;
92 continue;
93 case NLISTSW:
94 list = false;
95 continue;
96
97 case USERSW:
98 inverted = true;
99 continue;
100 case NUSERSW:
101 inverted = false;
102 continue;
103 }
104 }
105
106 if (vecp < argc) {
107 vec[vecp++] = cp;
108 } else {
109 /* Should never happen, but try to protect against code changes
110 that could allow it. */
111 die("too many arguments");
112 }
113 }
114
115 if (!noalias) {
116 /* allow Aliasfile: profile entry */
117 if ((cp = context_find ("Aliasfile"))) {
118 char *dp = NULL;
119
120 for (ap = brkstring(dp = mh_xstrdup(cp), " ", "\n"); ap && *ap; ap++)
121 if ((i = alias (*ap)) != AK_OK)
122 die("aliasing error in %s - %s", *ap, akerror (i));
123 free(dp);
124 }
125 alias (AliasFile);
126 }
127
128 /*
129 * If -user is specified
130 */
131 if (inverted) {
132 if (vecp == 0)
133 die("usage: %s -user addresses ... (you forgot the addresses)",
134 invo_name);
135
136 for (i = 0; i < vecp; i++)
137 print_usr (vec[i], list);
138 } else {
139 if (vecp) {
140 /* print specified aliases */
141 for (i = 0; i < vecp; i++)
142 print_aka (akvalue (vec[i]), list, 0);
143 } else {
144 /* print them all */
145 for (ak = akahead; ak; ak = ak->ak_next) {
146 char *res;
147
148 printf ("%s: ", ak->ak_name);
149 pos += strlen (ak->ak_name) + 1;
150 res = akresult(ak);
151 print_aka(res, list, pos);
152 free(res);
153 }
154 }
155 }
156
157 free (vec);
158 done (0);
159 return 1;
160 }
161
162 static void
163 print_aka (char *p, bool list, int margin)
164 {
165 char c;
166
167 if (p == NULL) {
168 puts("<empty>");
169 return;
170 }
171
172 while ((c = *p++)) {
173 switch (c) {
174 case ',':
175 if (*p) {
176 if (list)
177 printf ("\n%*s", margin, "");
178 else {
179 if (pos >= 68) {
180 fputs(",\n ", stdout);
181 pos = 2;
182 } else {
183 fputs(", ", stdout);
184 pos += 2;
185 }
186 }
187 }
188
189 case 0:
190 break;
191
192 default:
193 pos++;
194 putchar (c);
195 }
196 }
197
198 putchar ('\n');
199 pos = 1;
200 }
201
202 static void
203 print_usr (char *s, bool list)
204 {
205 char *cp, *pp, *vp;
206 struct aka *ak;
207 struct mailname *mp, *np;
208
209 if ((pp = getname (s)) == NULL)
210 die("no address in \"%s\"", s);
211 if ((mp = getm (pp, NULL, 0, NULL, 0)) == NULL)
212 die("bad address \"%s\"", s);
213 while (getname (""))
214 continue;
215
216 vp = NULL;
217 for (ak = akahead; ak; ak = ak->ak_next) {
218 pp = akresult (ak);
219 while ((cp = getname (pp))) {
220 if ((np = getm (cp, NULL, 0, NULL, 0)) == NULL)
221 continue;
222 if (!strcasecmp (FENDNULL(mp->m_host),
223 FENDNULL(np->m_host)) &&
224 !strcasecmp (FENDNULL(mp->m_mbox),
225 FENDNULL(np->m_mbox))) {
226 vp = vp ? add (ak->ak_name, add (",", vp))
227 : getcpy (ak->ak_name);
228 mnfree (np);
229 while (getname (""))
230 continue;
231 break;
232 }
233 mnfree (np);
234 }
235 }
236 mnfree (mp);
237
238 print_aka (vp ? vp : s, list, 0);
239
240 free(vp);
241 }