]>
diplodocus.org Git - nmh/blob - uip/aliasbr.c
1 /* aliasbr.c -- new aliasing mechanism
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.
9 #include "sbr/concat.h"
10 #include "sbr/vfgets.h"
11 #include "sbr/getcpy.h"
12 #include "h/aliasbr.h"
13 #include "h/addrsbr.h"
20 struct aka
*akahead
= NULL
;
21 struct aka
*akatail
= NULL
;
26 static char *akval (struct aka
*, char *);
27 static bool aleq (char *, char *) PURE
;
28 static char *scanp (char *) PURE
;
29 static char *getp (char *);
30 static char *seekp (char *, char *, char **);
31 static int addfile (struct aka
*, char *);
32 static char *getalias (char *);
33 static void add_aka (struct aka
*, char *);
34 static struct aka
*akalloc (char *);
37 /* Do mh alias substitution on 's' and return the results. */
47 v
= akval (akahead
, s
);
62 akresult (struct aka
*ak
)
64 char *cp
= NULL
, *dp
, *pp
;
67 for (ad
= ak
->ak_addr
; ad
; ad
= ad
->ad_next
) {
68 pp
= ad
->ad_local
? akval (ak
->ak_next
, ad
->ad_text
)
69 : getcpy (ad
->ad_text
);
73 cp
= concat (cp
, ",", pp
, NULL
);
82 akvis
= ak
->ak_visible
;
88 akval (struct aka
*ak
, char *s
)
93 /* It'd be tempting to check for a trailing semicolon and remove
94 it. But that would break the EXMH alias parser on what would
95 then be valid expressions:
96 http://lists.gnu.org/archive/html/nmh-workers/2012-10/msg00039.html
99 for (; ak
; ak
= ak
->ak_next
) {
100 if (aleq (s
, ak
->ak_name
)) {
101 return akresult (ak
);
104 if (strchr (s
, ':')) {
105 /* The first address in a blind list will contain the
106 alias name, so try to match, but just with just the
107 address (not including the list name). If there's a
108 match, then replace the alias part with its
111 char *name
= getname (s
);
115 /* s is of the form "Blind list: address". If address
116 is an alias, expand it. */
117 struct mailname
*mp
= getm (name
, NULL
, 0, NULL
, 0);
119 if (mp
&& mp
->m_ingrp
) {
120 char *gname
= mh_xstrdup(FENDNULL(mp
->m_gname
));
122 /* FIXME: gname must be true; add() never returns NULL.
123 * Is some other test required? */
124 if (gname
&& aleq (name
, ak
->ak_name
)) {
126 cp
= concat (gname
, akresult (ak
), NULL
);
134 /* Need to flush getname after use. */
135 while (getname ("")) continue;
143 return mh_xstrdup(s
);
148 aleq (char *string
, char *aliasent
)
152 while ((c
= *string
++)) {
153 if (*aliasent
== '*')
155 if (tolower((unsigned char)c
) != tolower((unsigned char)*aliasent
))
160 return *aliasent
== 0 || *aliasent
== '*';
170 struct aka
*ak
= NULL
;
174 && !has_prefix(file
, "./") && !has_prefix(file
, "../"))
175 file
= etcpath (file
);
176 if ((fp
= fopen (file
, "r")) == NULL
) {
181 while (vfgets (fp
, &ap
) == OK
) {
183 switch (*(pp
= scanp (bp
))) {
184 case '<': /* recurse a level */
185 if (!*(cp
= getp (pp
+ 1))) {
186 akerrst
= "'<' without alias-file";
190 if ((i
= alias (cp
)) != AK_OK
) {
195 case ':': /* comment */
203 if (!*(cp
= seekp (pp
, &lc
, &ap
))) {
207 if (!(ak
= akalloc (cp
))) {
213 ak
->ak_visible
= false;
217 ak
->ak_visible
= true;
225 switch (*(pp
= scanp (ap
))) {
230 case '<': /* read values from file */
231 if (!*(cp
= getp (pp
+ 1))) {
235 if (!addfile (ak
, cp
)) {
242 while ((cp
= getalias (pp
)))
256 static char buffer
[BUFSIZ
];
260 snprintf (buffer
, sizeof(buffer
), "unable to read '%s'", akerrst
);
264 snprintf (buffer
, sizeof(buffer
), "error in line '%s'", akerrst
);
268 snprintf (buffer
, sizeof(buffer
), "out of memory while on '%s'", akerrst
);
272 snprintf (buffer
, sizeof(buffer
), "unknown error (%d)", i
);
283 while (isspace ((unsigned char) *p
))
292 char *cp
= scanp (p
);
295 while (!isspace ((unsigned char) *cp
) && *cp
)
304 seekp (char *p
, char *c
, char **a
)
309 while (!isspace ((unsigned char) *cp
) && *cp
&& *cp
!= ':' && *cp
!= ';')
320 addfile (struct aka
*ak
, char *file
)
326 if (!(fp
= fopen (etcpath (file
), "r"))) {
331 while (fgets (buffer
, sizeof buffer
, fp
))
332 while ((cp
= getalias (buffer
)))
341 getalias (char *addrs
)
344 static char *cp
= NULL
;
351 /* Remove leading any space from the address. */
352 for (pp
= cp
; isspace ((unsigned char) *pp
); pp
++)
356 /* Find the end of the address. */
357 for (qp
= pp
; *qp
!= 0 && *qp
!= ','; qp
++)
359 /* Set cp to point to the remainder of the addresses. */
362 for (cp
= qp
, qp
--; qp
> pp
; qp
--)
364 if (isspace ((unsigned char) *qp
))
375 add_aka (struct aka
*ak
, char *pp
)
379 for (ad
= ak
->ak_addr
, ld
= NULL
; ad
; ld
= ad
, ad
= ad
->ad_next
)
380 if (!strcmp (pp
, ad
->ad_text
))
384 ad
->ad_text
= mh_xstrdup(pp
);
385 ad
->ad_local
= strchr(pp
, '@') == NULL
&& strchr(pp
, '!') == NULL
;
400 p
->ak_name
= getcpy (id
);
401 p
->ak_visible
= false;
405 akatail
->ak_next
= p
;