1 /* replsbr.c - routines to help repl along... */
3 static char ident[] = "@(#)$Id: replsbr.c,v 1.19 1995/12/06 23:47:26 jromine Exp $";
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
11 #include <sys/types.h> /* off_t */
12 #include <sys/file.h> /* L_SET */
15 extern short ccto, /* from repl.c */
28 static char *badaddrs = NULL;
29 static char *dfhost=NULL;
31 static struct mailname mq={NULL};
35 /* buffer size for content part of header
36 * fields. We want this to be large
37 * enough so that we don't do a lot of
38 * extra FLDPLUS calls on m_getfld but
39 * small enough so that we don't snarf
40 * the entire message body when we're
41 * not going to use any of it.
44 static struct format *fmt;
46 static int ncomps = 0; /* # of interesting components */
47 static char **compbuffers = 0; /* buffers for component text */
48 static struct comp **used_buf = 0; /* stack for comp that use buffers */
50 static int dat[5]; /* aux. data for format routine */
52 static char *addrcomps[] = {
68 static insert(), replfilter();
73 replout (inb, msg, drft, mp)
81 register struct comp *cptr;
82 register char *tmpbuf;
83 register char **nxtbuf;
84 register struct comp **savecomp;
93 (void) umask( ~ m_gmprot() );
94 if ((out = fopen (drft, "w")) == NULL)
95 adios (drft, "unable to create");
97 cp = new_fs (form ? form : replcomps, NULLCP, NULLCP);
98 format_len = strlen (cp);
99 ncomps = fmt_compile (cp, &fmt) + 1;
100 if ((nxtbuf = compbuffers = (char **)
101 calloc((unsigned)ncomps,sizeof(char *)))
103 adios (NULLCP, "unable to allocate component buffers");
104 if ((savecomp = used_buf = (struct comp **)
105 calloc((unsigned)(ncomps+1),sizeof(struct comp *)))
106 == (struct comp **)NULL)
107 adios (NULLCP, "unable to allocate component buffer stack");
108 savecomp += ncomps + 1;
109 *--savecomp = (struct comp *)0; /* point at zero'd end minus 1 */
110 for (i = ncomps; i--; )
111 if ((*nxtbuf++ = malloc( SBUFSIZ )) == NULL)
112 adios (NULLCP, "unable to allocate component buffer");
114 nxtbuf = compbuffers; /* point at start */
117 for (ap = addrcomps; *ap; ap++) {
118 FINDCOMP (cptr, *ap);
120 cptr -> c_type |= CT_ADDR;
123 /* ignore any components killed by command line switches */
125 FINDCOMP (cptr, "to");
130 FINDCOMP (cptr, "cc");
134 /* set up the "fcc" pseudo-component */
136 FINDCOMP (cptr, "fcc");
138 cptr->c_text = getcpy (fcc);
140 if (cp = getenv("USER")) {
141 FINDCOMP (cptr, "user");
143 cptr->c_text = getcpy(cp);
146 (void) ismymbox ((struct mailname *)0); /* XXX */
148 /* pick any interesting stuff out of msg "inb" */
149 for (state = FLD;;) {
150 state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
155 * if we're interested in this component, save a pointer
156 * to the component text, then start using our next free
157 * buffer as the component temp buffer (buffer switching
158 * saves an extra copy of the component text).
160 if (cptr = wantcomp[CHASH(name)])
162 if (uleq(name, cptr->c_name)) {
163 char_read += msg_count;
164 if (! cptr->c_text) {
165 cptr->c_text = tmpbuf;
169 i = strlen (cp = cptr->c_text) - 1;
171 if (cptr->c_type & CT_ADDR) {
173 cp = add (",\n\t", cp);
177 cptr->c_text = add (tmpbuf, cp);
179 while (state == FLDPLUS) {
180 state = m_getfld (state, name, tmpbuf,
182 cptr->c_text = add (tmpbuf, cptr->c_text);
183 char_read += msg_count;
187 } while (cptr = cptr->c_next);
189 while (state == FLDPLUS)
190 state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
200 adios (NULLCP, "m_getfld() returned %d", state);
204 * format and output the header lines.
207 /* if there's a "subject" component, strip any "re:"s off it */
208 FINDCOMP (cptr, "subject")
209 if (cptr && (cp = cptr->c_text)) {
210 register char *sp = cp;
221 if (sp != cptr->c_text) {
223 cptr->c_text = getcpy (sp);
227 i = format_len + char_read + 256;
228 scanl = malloc ((unsigned)i + 2);
229 dat[0] = dat[1] = dat[2] = dat[4] = 0;
230 dat[3] = outputlinelen;
231 (void) fmtscan (fmt, scanl, i, dat);
234 fputs ("\nrepl: bad addresses:\n", out);
235 fputs ( badaddrs, out);
238 replfilter (inb, out);
242 (void) fprintf (out, "#forw [original message] +%s %s\n",
243 mp -> foldpath, m_name (mp -> lowsel));
247 adios (drft, "error writing");
250 /* return dynamically allocated buffers */
252 for (nxtbuf = compbuffers, i = ncomps;
253 cptr = *savecomp++; nxtbuf++, i--)
254 free (cptr->c_text); /* if not nxtbuf, nxtbuf already freed */
256 free (*nxtbuf++); /* free unused nxtbufs */
257 free ((char *) compbuffers);
258 free ((char *) used_buf);
263 static char *buf; /* our current working buffer */
264 static char *bufend; /* end of working buffer */
265 static char *last_dst; /* buf ptr at end of last call */
266 static unsigned int bufsiz=0; /* current size of buf */
268 #define BUFINCR 512 /* how much to expand buf when if fills */
270 #define CPY(s) { cp = (s); while (*dst++ = *cp++) ; --dst; }
272 /* check if there's enough room in buf for str. add more mem if needed */
273 #define CHECKMEM(str) \
274 if ((len = strlen (str) + 1) >= bufend - dst) {\
276 int n = last_dst - buf;\
277 bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\
278 buf = realloc (buf, bufsiz);\
282 adios (NULLCP, "formataddr: couldn't get buffer space");\
283 bufend = buf + bufsiz;\
287 /* fmtscan will call this routine if the user includes the function
288 * "(formataddr {component})" in a format string. "orig" is the
289 * original contents of the string register. "str" is the address
290 * string to be formatted and concatenated onto orig. This routine
291 * returns a pointer to the concatenated address string.
293 * We try to not do a lot of malloc/copy/free's (which is why we
294 * don't call "getcpy") but still place no upper limit on the
295 * length of the result string.
297 char *formataddr (orig, str)
304 register int isgroup;
308 register struct mailname *mp = NULL;
310 /* if we don't have a buffer yet, get one */
312 buf = malloc (BUFINCR);
314 adios (NULLCP, "formataddr: couldn't allocate buffer space");
315 last_dst = buf; /* XXX */
316 bufsiz = BUFINCR - 6; /* leave some slop */
317 bufend = buf + bufsiz;
320 * If "orig" points to our buffer we can just pick up where we
321 * left off. Otherwise we have to copy orig into our buffer.
325 else if (!orig || !*orig) {
329 dst = last_dst; /* XXX */
334 /* concatenate all the new addresses onto 'buf' */
335 for (isgroup = 0; cp = getname (str); ) {
336 if ((mp = getm (cp, dfhost, dftype, AD_NAME, error)) == NULL) {
337 (void) sprintf (baddr, "\t%s -- %s\n", cp, error);
338 badaddrs = add (baddr, badaddrs);
341 if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
346 /* if we get here we're going to add an address */
352 CHECKMEM (mp->m_gname);
372 register struct mailname *np;
375 register struct mailname *mp;
377 if (np -> m_mbox == NULL)
380 for (mp = &mq; mp -> m_next; mp = mp -> m_next) {
382 if (uleq (np -> m_mbox, mp -> m_next -> m_mbox))
385 if (uleq (np -> m_host, mp -> m_next -> m_host)
386 && uleq (np -> m_mbox, mp -> m_next -> m_mbox))
390 if (!ccme && ismymbox (np))
394 (void) sprintf (buffer, "Reply to %s? ", adrformat (np));
395 if (!gans (buffer, anoyes))
408 static replfilter (in, out)
418 if (access (filter, 04) == NOTOK)
419 adios (filter, "unable to read");
421 mhl = r1bindex (mhlproc, '/');
424 (void) lseek (fileno(in), (off_t)0, L_SET);
427 switch (pid = vfork ()) {
429 adios ("fork", "unable to");
432 (void) dup2 (fileno (in), fileno (stdin));
433 (void) dup2 (fileno (out), fileno (stdout));
436 execlp (mhlproc, mhl, "-form", filter, "-noclear", NULLCP);
437 fprintf (stderr, "unable to exec ");
442 if (pidXwait (pid, mhl))
444 (void) fseek (out, 0L, 2);