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