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