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