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