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