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