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