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