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