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