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