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