54c8b05a00eaf63c1b53c56b6be21d418dc5a330
[mmh] / uip / ali.c
1
2 /*
3  * ali.c -- list nmh mail aliases
4  *
5  * $Id$
6  */
7
8 #include <h/mh.h>
9 #include <h/addrsbr.h>
10 #include <h/aliasbr.h>
11
12 /*
13  * maximum number of names
14  */
15 #define NVEC 50
16
17 static struct swit switches[] = {
18 #define ALIASW                0
19     { "alias aliasfile", 0 },
20 #define NALIASW               1
21     { "noalias", -7 },
22 #define LISTSW                2
23     { "list", 0 },
24 #define NLISTSW               3
25     { "nolist", 0 },
26 #define NORMSW                4
27     { "normalize", 0 },
28 #define NNORMSW               5
29     { "nonormalize", 0 },
30 #define USERSW                6
31     { "user", 0 },
32 #define NUSERSW               7
33     { "nouser", 0 },
34 #define VERSIONSW             8
35     { "version", 0 },
36 #define HELPSW                9
37     { "help", 4 },
38     { NULL, 0 }
39 };
40
41 static int pos = 1;
42
43 extern struct aka *akahead;
44
45 /*
46  * prototypes
47  */
48 void print_aka (char *, int, int);
49 void print_usr (char *, int, int);
50
51
52 int
53 main (int argc, char **argv)
54 {
55     int i, vecp = 0, inverted = 0, list = 0;
56     int noalias = 0, normalize = AD_NHST;
57     char *cp, **ap, **argp, buf[BUFSIZ];
58     char *vec[NVEC], **arguments;
59     struct aka *ak;
60
61 #ifdef LOCALE
62     setlocale(LC_ALL, "");
63 #endif
64     invo_name = r1bindex (argv[0], '/');
65
66     /* read user profile/context */
67     context_read();
68
69     mts_init (invo_name);
70     arguments = getarguments (invo_name, argc, argv, 1);
71     argp = arguments;
72
73     while ((cp = *argp++)) {
74         if (*cp == '-') {
75             switch (smatch (++cp, switches)) {
76                 case AMBIGSW: 
77                     ambigsw (cp, switches);
78                     done (1);
79                 case UNKWNSW: 
80                     adios (NULL, "-%s unknown", cp);
81
82                 case HELPSW: 
83                     snprintf (buf, sizeof(buf), "%s [switches] aliases ...",
84                         invo_name);
85                     print_help (buf, switches, 1);
86                     done (1);
87                 case VERSIONSW:
88                     print_version (invo_name);
89                     done (1);
90
91                 case ALIASW: 
92                     if (!(cp = *argp++) || *cp == '-')
93                         adios (NULL, "missing argument to %s", argp[-2]);
94                     if ((i = alias (cp)) != AK_OK)
95                         adios (NULL, "aliasing error in %s - %s", cp, akerror (i));
96                     continue;
97                 case NALIASW: 
98                     noalias++;
99                     continue;
100
101                 case LISTSW: 
102                     list++;
103                     continue;
104                 case NLISTSW: 
105                     list = 0;
106                     continue;
107
108                 case NORMSW: 
109                     normalize = AD_HOST;
110                     continue;
111                 case NNORMSW: 
112                     normalize = AD_NHST;
113                     continue;
114
115                 case USERSW: 
116                     inverted++;
117                     continue;
118                 case NUSERSW: 
119                     inverted = 0;
120                     continue;
121             }
122         }
123         vec[vecp++] = cp;
124     }
125
126     if (!noalias) {
127         /* allow Aliasfile: profile entry */
128         if ((cp = context_find ("Aliasfile"))) {
129             char *dp = NULL;
130
131             for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++)
132                 if ((i = alias (*ap)) != AK_OK)
133                     adios (NULL, "aliasing error in %s - %s", *ap, akerror (i));
134             if (dp)
135                 free(dp);
136         }
137         alias (AliasFile);
138     }
139
140     /*
141      * If -user is specified
142      */
143     if (inverted) {
144         if (vecp == 0)
145             adios (NULL, "usage: %s -user addresses ...  (you forgot the addresses)",
146                    invo_name);
147
148         for (i = 0; i < vecp; i++)
149             print_usr (vec[i], list, normalize);
150
151         done (0);
152     }
153
154     if (vecp) {
155         /* print specified aliases */
156         for (i = 0; i < vecp; i++)
157             print_aka (akvalue (vec[i]), list, 0);
158     } else {
159         /* print them all */
160         for (ak = akahead; ak; ak = ak->ak_next) {
161             printf ("%s: ", ak->ak_name);
162             pos += strlen (ak->ak_name) + 1;
163             print_aka (akresult (ak), list, pos);
164         }
165     }
166
167     return done (0);
168 }
169
170 void
171 print_aka (char *p, int list, int margin)
172 {
173     char c;
174
175     if (p == NULL) {
176         printf ("<empty>\n");
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                             printf (",\n ");
189                             pos = 2;
190                         } else {
191                             printf (", ");
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 void
211 print_usr (char *s, int list, int norm)
212 {
213     register char *cp, *pp, *vp;
214     register struct aka *ak;
215     register struct mailname *mp, *np;
216
217     if ((pp = getname (s)) == NULL)
218         adios (NULL, "no address in \"%s\"", s);
219     if ((mp = getm (pp, NULL, 0, norm, NULL)) == NULL)
220         adios (NULL, "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, norm, NULL)) == NULL)
229                 continue;
230             if (!strcasecmp (mp->m_host, np->m_host)
231                     && !strcasecmp (mp->m_mbox, 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 #if 0
245     printf ("%s: ", s);
246     print_aka (vp ? vp : s, list, pos += strlen (s) + 1);
247 #else
248     print_aka (vp ? vp : s, list, 0);
249 #endif
250
251     if (vp)
252         free (vp);
253 }