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