]> diplodocus.org Git - nmh/blob - sbr/fmt_addr.c
Fix stupid accidental dependence on a bash quirk in previous
[nmh] / sbr / fmt_addr.c
1
2 /*
3 * fmt_addr.c -- format an address field (from fmt_scan)
4 *
5 * $Id$
6 *
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
10 */
11
12 #include <h/mh.h>
13 #include <h/addrsbr.h>
14 #include <h/fmt_scan.h>
15
16 static char *buf; /* our current working buffer */
17 static char *bufend; /* end of working buffer */
18 static char *last_dst; /* buf ptr at end of last call */
19 static unsigned int bufsiz; /* current size of buf */
20
21 #define BUFINCR 512 /* how much to expand buf when if fills */
22
23 #define CPY(s) { cp = (s); while ((*dst++ = *cp++)) ; --dst; }
24
25 /* check if there's enough room in buf for str. add more mem if needed */
26 #define CHECKMEM(str) \
27 if ((len = strlen (str)) >= bufend - dst) {\
28 int i = dst - buf;\
29 int n = last_dst - buf;\
30 bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\
31 buf = realloc (buf, bufsiz);\
32 dst = buf + i;\
33 last_dst = buf + n;\
34 if (! buf)\
35 adios (NULL, "formataddr: couldn't get buffer space");\
36 bufend = buf + bufsiz;\
37 }
38
39
40 /* fmt_scan will call this routine if the user includes the function
41 * "(formataddr {component})" in a format string. "orig" is the
42 * original contents of the string register. "str" is the address
43 * string to be formatted and concatenated onto orig. This routine
44 * returns a pointer to the concatenated address string.
45 *
46 * We try to not do a lot of malloc/copy/free's (which is why we
47 * don't call "getcpy") but still place no upper limit on the
48 * length of the result string.
49 *
50 * This routine is placed in a separate library so it can be
51 * overridden by particular programs (e.g., "replsbr").
52 */
53
54 char *
55 formataddr (char *orig, char *str)
56 {
57 register int len;
58 register int isgroup;
59 register char *dst;
60 register char *cp;
61 register char *sp;
62 register struct mailname *mp = NULL;
63
64 /* if we don't have a buffer yet, get one */
65 if (bufsiz == 0) {
66 buf = malloc (BUFINCR);
67 if (! buf)
68 adios (NULL, "formataddr: couldn't allocate buffer space");
69 last_dst = buf; /* XXX */
70 bufsiz = BUFINCR - 6; /* leave some slop */
71 bufend = buf + bufsiz;
72 }
73 /*
74 * If "orig" points to our buffer we can just pick up where we
75 * left off. Otherwise we have to copy orig into our buffer.
76 */
77 if (orig == buf)
78 dst = last_dst;
79 else if (!orig || !*orig) {
80 dst = buf;
81 *dst = '\0';
82 } else {
83 dst = last_dst; /* XXX */
84 CHECKMEM (orig);
85 CPY (orig);
86 }
87
88 /* concatenate all the new addresses onto 'buf' */
89 for (isgroup = 0; (cp = getname (str)); ) {
90 if ((mp = getm (cp, NULL, 0, fmt_norm, NULL)) == NULL)
91 continue;
92
93 if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
94 *dst++ = ';';
95 isgroup = 0;
96 }
97 /* if we get here we're going to add an address */
98 if (dst != buf) {
99 *dst++ = ',';
100 *dst++ = ' ';
101 }
102 if (mp->m_gname) {
103 CHECKMEM (mp->m_gname);
104 CPY (mp->m_gname);
105 isgroup++;
106 }
107 sp = adrformat (mp);
108 CHECKMEM (sp);
109 CPY (sp);
110 mnfree (mp);
111 }
112
113 if (isgroup)
114 *dst++ = ';';
115
116 *dst = '\0';
117 last_dst = dst;
118 return (buf);
119 }