|
|
1.1 root 1: /* replsbr.c - routines to help repl along... */
2:
3: #include "../h/mh.h"
4: #include "../h/addrsbr.h"
5: #include "../h/formatsbr.h"
6: #include <ctype.h>
7: #include <stdio.h>
8:
9:
10: extern short ccto, /* from repl.c */
11: cccc,
12: ccme,
13: format,
14: outputlinelen,
15: querysw;
16: extern char *fcc,
17: *filter,
18: *form;
19:
20: static int dftype;
21:
22: static char *badaddrs = NULL;
23: static char *dfhost;
24:
25: static struct mailname mq;
26:
27:
28: #define SBUFSIZ 256
29: /* buffer size for content part of header
30: * fields. We want this to be large
31: * enough so that we don't do a lot of
32: * extra FLDPLUS calls on m_getfld but
33: * small enough so that we don't snarf
34: * the entire message body when we're
35: * not going to use any of it.
36: */
37:
38: static struct format *fmt;
39:
40: static int ncomps = 0; /* # of interesting components */
41: static char **compbuffers = 0; /* buffers for component text */
42: static struct comp **used_buf = 0; /* stack for comp that use buffers */
43:
44: static int dat[4]; /* aux. data for format routine */
45:
46: static void replfilter();
47: static int insert();
48:
49: /* */
50:
51: /* ARGSUSED */
52:
53: replout(inb, msg, drft)
54: register FILE *inb;
55: char *msg, *drft;
56: {
57: register int state;
58: register int i;
59: register struct comp *cptr;
60: register char *tmpbuf;
61: register char **nxtbuf;
62: register struct comp **savecomp;
63: FILE *out;
64: char name[NAMESZ];
65: char *scanl;
66: int char_read = 0;
67: char *cp;
68: int format_len;
69:
70: (void) umask( ~ m_gmprot() );
71: if ((out = fopen (drft, "w")) == NULL)
72: adios (drft, "unable to create");
73:
74: cp = new_fs (form ? form : replcomps, NULLCP, NULLCP);
75: format_len = strlen (cp);
76: ncomps = fmt_compile (cp, &fmt) + 1;
77: nxtbuf = compbuffers = (char **)calloc((unsigned)ncomps,sizeof(char *));
78: if (nxtbuf == NULL)
79: adios (NULLCP, "unable to allocate component buffers");
80: savecomp = used_buf = (struct comp **)calloc((unsigned)(ncomps+1),
81: sizeof(struct comp *));
82: if (used_buf == NULL)
83: adios (NULLCP, "unable to allocate component buffer stack");
84: savecomp += ncomps+1; *--savecomp = 0;
85: for (i = ncomps; i--; )
86: if ((*nxtbuf++ = malloc( SBUFSIZ )) == NULL)
87: adios (NULLCP, "unable to allocate component buffer");
88:
89: nxtbuf = compbuffers;
90: tmpbuf = *nxtbuf++;
91:
92: /* ignore any components killed by command line switches */
93: if (!ccto) {
94: FINDCOMP (cptr, "to");
95: if (cptr)
96: cptr->c_name = "";
97: }
98: if (!cccc) {
99: FINDCOMP (cptr, "cc");
100: if (cptr)
101: cptr->c_name = "";
102: }
103: /* set up the "fcc" pseudo-component */
104: if (fcc) {
105: FINDCOMP (cptr, "fcc");
106: if (cptr)
107: cptr->c_text = getcpy (fcc);
108: }
109: if (!ccme)
110: (void) ismymbox ((struct mailname *)0); /* XXX */
111:
112: /* pick any interesting stuff out of msg "inb" */
113: for (state = FLD;;) {
114: state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
115: switch (state) {
116: case FLD:
117: case FLDPLUS:
118: /*
119: * if we're interested in this component, save a pointer
120: * to the component text, then start using our next free
121: * buffer as the component temp buffer (buffer switching
122: * saves an extra copy of the component text).
123: */
124: if (cptr = wantcomp[CHASH(name)])
125: do {
126: if (uleq(name, cptr->c_name)) {
127: char_read += msg_count;
128: if (! cptr->c_text) {
129: cptr->c_text = tmpbuf;
130: *--savecomp = cptr;
131: /* Zero pointer to avoid freeing memory twice */
132: nxtbuf--;
133: *nxtbuf = 0;
134: nxtbuf++;
135: tmpbuf = *nxtbuf++;
136: } else {
137: i = strlen (cp = cptr->c_text) - 1;
138: if (cp[i] == '\n')
139: if (cptr->c_type & CT_ADDR) {
140: cp[i] = '\0';
141: cp = add (",\n\t", cp);
142: } else {
143: cp = add ("\t", cp);
144: }
145: cptr->c_text = add (tmpbuf, cp);
146: }
147: while (state == FLDPLUS) {
148: state = m_getfld (state, name, tmpbuf,
149: SBUFSIZ, inb);
150: cptr->c_text = add (tmpbuf, cptr->c_text);
151: char_read += msg_count;
152: }
153: break;
154: }
155: } while (cptr = cptr->c_next);
156:
157: while (state == FLDPLUS)
158: state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
159: break;
160:
161: case LENERR:
162: case FMTERR:
163: case BODY:
164: case FILEEOF:
165: goto finished;
166:
167: default:
168: adios (NULLCP, "m_getfld() returned %d", state);
169: }
170: }
171: /*
172: * format and output the header lines.
173: */
174: finished:
175: /* if there's a "subject" component, strip any "re:"s off it */
176: FINDCOMP (cptr, "subject")
177: if (cptr && (cp = cptr->c_text)) {
178: register char *sp = cp;
179:
180: for (;;) {
181: while (isspace(i = *cp++))
182: ;
183: if ((i | 0x20) != 'r' || (*cp++ | 0x20) != 'e' || *cp++ != ':')
184: break;
185: sp = cp;
186: }
187: if (sp != cptr->c_text) {
188: cp = cptr->c_text;
189: cptr->c_text = getcpy (sp);
190: free (cp);
191: }
192: }
193: i = format_len + char_read + 256;
194: scanl = malloc ((unsigned)i + 2);
195: dat[0] = dat[1] = dat[2] = 0;
196: dat[3] = outputlinelen;
197: (void) fmtscan (fmt, scanl, i, dat);
198: fputs (scanl, out);
199: if (badaddrs) {
200: fputs ("\nrepl: bad addresses:\n", out);
201: fputs ( badaddrs, out);
202: }
203: if (filter)
204: replfilter (inb, out);
205:
206: if (ferror (out))
207: adios (drft, "error writing");
208: (void) fclose (out);
209:
210: /* return dynamically allocated buffers */
211: free (scanl);
212: while ( cptr = *savecomp++ )
213: free (cptr->c_text);
214: for (nxtbuf = compbuffers, i = ncomps; i--; )
215: if (*nxtbuf)
216: free (*nxtbuf++);
217: free ((char *) compbuffers);
218: free ((char *) used_buf);
219: }
220:
221: /* */
222:
223: static char *buf; /* our current working buffer */
224: static char *bufend; /* end of working buffer */
225: static char *last_dst; /* buf ptr at end of last call */
226: static unsigned int bufsiz; /* current size of buf */
227:
228: #define BUFINCR 512 /* how much to expand buf when if fills */
229:
230: #define CPY(s) { cp = (s); while (*dst++ = *cp++) ; --dst; }
231:
232: /* check if there's enough room in buf for str. add more mem if needed */
233:
234: #define CHECKMEM(str) \
235: if ((len = strlen (str) + 1) >= bufend - dst) {\
236: bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\
237: dst -= (unsigned int)buf;\
238: last_dst -= (unsigned int)buf;\
239: buf = realloc (buf, bufsiz);\
240: if (! buf)\
241: adios (NULLCP, "formataddr: couldn't get buffer space");\
242: dst += (unsigned int)buf;\
243: last_dst += (unsigned int)buf;\
244: bufend = buf + bufsiz;\
245: }
246:
247:
248: /* fmtscan will call this routine if the user includes the function
249: * "(formataddr {component})" in a format string. "orig" is the
250: * original contents of the string register. "str" is the address
251: * string to be formatted and concatenated onto orig. This routine
252: * returns a pointer to the concatenated address string.
253: *
254: * We try to not do a lot of malloc/copy/free's (which is why we
255: * don't call "getcpy") but still place no upper limit on the
256: * length of the result string.
257: */
258: char *
259: formataddr(orig, str)
260: char *orig, *str;
261: {
262: register int len;
263: char baddr[BUFSIZ],
264: error[BUFSIZ];
265: register int isgroup;
266: register char *dst;
267: register char *cp;
268: register char *sp;
269: register struct mailname *mp = NULL;
270:
271: /* if we don't have a buffer yet, get one */
272: if (bufsiz == 0) {
273: buf = malloc (BUFINCR);
274: if (! buf)
275: adios (NULLCP, "formataddr: couldn't allocate buffer space");
276: bufsiz = BUFINCR - 6; /* leave some slop */
277: bufend = buf + bufsiz;
278: }
279: /*
280: * If "orig" points to our buffer we can just pick up where we
281: * left off. Otherwise we have to copy orig into our buffer.
282: */
283: if (orig == buf)
284: dst = last_dst;
285: else if (!orig || !*orig) {
286: dst = buf;
287: *dst = '\0';
288: } else {
289: CHECKMEM (orig);
290: CPY (orig);
291: }
292:
293: /* concatenate all the new addresses onto 'buf' */
294: for (isgroup = 0; cp = getname (str); ) {
295: if ((mp = getm (cp, dfhost, dftype, AD_NAME, error)) == NULL) {
296: (void) sprintf (baddr, "\t%s -- %s\n", cp, error);
297: badaddrs = add (baddr, badaddrs);
298: continue;
299: }
300: if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
301: *dst++ = ';';
302: isgroup = 0;
303: }
304: if (insert (mp)) {
305: /* if we get here we're going to add an address */
306: if (dst != buf) {
307: *dst++ = ',';
308: *dst++ = ' ';
309: }
310: if (mp->m_gname) {
311: CHECKMEM (mp->m_gname);
312: CPY (mp->m_gname);
313: isgroup++;
314: }
315: sp = adrformat (mp);
316: CHECKMEM (sp);
317: CPY (sp);
318: }
319: }
320:
321: if (isgroup)
322: *dst++ = ';';
323:
324: *dst = '\0';
325: last_dst = dst;
326: return (buf);
327: }
328: /* */
329:
330: static int
331: insert(np)
332: register struct mailname *np;
333: {
334: char buffer[BUFSIZ];
335: register struct mailname *mp;
336:
337: if (np -> m_mbox == NULL)
338: return 0;
339:
340: for (mp = &mq; mp -> m_next; mp = mp -> m_next) {
341: #ifdef BERK
342: if (uleq (np -> m_mbox, mp -> m_next -> m_mbox))
343: return 0;
344: #else not BERK
345: if (uleq (np -> m_host, mp -> m_next -> m_host)
346: && uleq (np -> m_mbox, mp -> m_next -> m_mbox))
347: return 0;
348: #endif BERK
349: }
350: if (!ccme && ismymbox (np))
351: return 0;
352:
353: if (querysw) {
354: (void) sprintf (buffer, "Reply to %s? ", adrformat (np));
355: if (!gans (buffer, anoyes))
356: return 0;
357: }
358: mp -> m_next = np;
359: #ifdef ISI
360: if (ismymbox (np))
361: ccme = 0;
362: #endif ISI
363: return 1;
364: }
365:
366: /* */
367:
368: static void
369: replfilter(in, out)
370: register FILE *in, *out;
371: {
372: int pid;
373: char *mhl;
374:
375: if (filter == NULL)
376: return;
377:
378: if (access (filter, 04) == NOTOK)
379: adios (filter, "unable to read");
380:
381: mhl = r1bindex (mhlproc, '/');
382:
383: rewind (in);
384: (void) fflush (out);
385:
386: switch (pid = vfork ()) {
387: case NOTOK:
388: adios ("fork", "unable to");
389:
390: case OK:
391: (void) dup2 (fileno (in), fileno (stdin));
392: (void) dup2 (fileno (out), fileno (stdout));
393: closefds (3);
394:
395: execlp (mhlproc, mhl, "-form", filter, "-noclear", NULLCP);
396: fprintf (stderr, "unable to exec ");
397: perror (mhlproc);
398: _exit (-1);
399:
400: default:
401: if (pidXwait (pid, mhl))
402: done (1);
403: (void) fseek (out, 0L, 2);
404: break;
405: }
406: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.