Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / replsbr.c,v
1 head    1.19;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.19
9 date    95.12.06.23.47.26;      author jromine; state Exp;
10 branches;
11 next    1.18;
12
13 1.18
14 date    95.12.06.21.07.03;      author jromine; state Exp;
15 branches;
16 next    1.17;
17
18 1.17
19 date    93.09.04.19.31.32;      author jromine; state Exp;
20 branches;
21 next    1.16;
22
23 1.16
24 date    93.08.26.22.13.19;      author jromine; state Exp;
25 branches;
26 next    1.15;
27
28 1.15
29 date    93.08.25.17.27.35;      author jromine; state Exp;
30 branches;
31 next    1.14;
32
33 1.14
34 date    93.02.26.21.59.28;      author jromine; state Exp;
35 branches;
36 next    1.13;
37
38 1.13
39 date    92.12.15.00.20.22;      author jromine; state Exp;
40 branches;
41 next    1.12;
42
43 1.12
44 date    92.11.04.00.58.58;      author jromine; state Exp;
45 branches;
46 next    1.11;
47
48 1.11
49 date    92.02.05.07.26.30;      author jromine; state Exp;
50 branches;
51 next    1.10;
52
53 1.10
54 date    91.01.17.15.29.27;      author mh;      state Exp;
55 branches;
56 next    1.9;
57
58 1.9
59 date    90.11.05.11.38.43;      author mh;      state Exp;
60 branches;
61 next    1.8;
62
63 1.8
64 date    90.11.05.11.35.20;      author mh;      state Exp;
65 branches;
66 next    1.7;
67
68 1.7
69 date    90.11.05.11.23.19;      author mh;      state Exp;
70 branches;
71 next    1.6;
72
73 1.6
74 date    90.04.05.14.59.43;      author sources; state Exp;
75 branches;
76 next    1.5;
77
78 1.5
79 date    90.03.12.10.49.00;      author sources; state Exp;
80 branches;
81 next    1.4;
82
83 1.4
84 date    90.02.09.10.11.12;      author sources; state Exp;
85 branches;
86 next    1.3;
87
88 1.3
89 date    90.02.06.13.29.55;      author sources; state Exp;
90 branches;
91 next    1.2;
92
93 1.2
94 date    90.01.30.14.05.59;      author sources; state Exp;
95 branches;
96 next    1.1;
97
98 1.1
99 date    90.01.30.11.17.06;      author sources; state Exp;
100 branches;
101 next    ;
102
103
104 desc
105 @@
106
107
108 1.19
109 log
110 @fix: off-by-1 error
111 @
112 text
113 @/* replsbr.c - routines to help repl along... */
114 #ifndef lint
115 static char ident[] = "@@(#)$Id: replsbr.c,v 1.18 1995/12/06 21:07:03 jromine Exp jromine $";
116 #endif  /* lint */
117
118 #include "../h/mh.h"
119 #include "../h/addrsbr.h"
120 #include "../h/formatsbr.h"
121 #include <ctype.h>
122 #include <stdio.h>
123 #include <sys/types.h>          /* off_t */
124 #include <sys/file.h>           /* L_SET */
125
126
127 extern short    ccto,           /* from repl.c */
128                 cccc,
129                 ccme,
130                 format,
131                 outputlinelen,
132                 querysw;
133 extern int      mime;
134 extern char *fcc,
135             *filter,
136             *form;
137
138 static int   dftype=0;
139
140 static char *badaddrs = NULL;
141 static char *dfhost=NULL;
142
143 static struct mailname  mq={NULL};
144
145
146 #define SBUFSIZ 256             
147                                 /* buffer size for content part of header
148                                  * fields.  We want this to be large
149                                  * enough so that we don't do a lot of
150                                  * extra FLDPLUS calls on m_getfld but
151                                  * small enough so that we don't snarf
152                                  * the entire message body when we're
153                                  * not going to use any of it.
154                                  */
155
156 static struct format *fmt;
157
158 static int      ncomps = 0;             /* # of interesting components */
159 static char     **compbuffers = 0;      /* buffers for component text */
160 static struct comp **used_buf = 0;      /* stack for comp that use buffers */
161
162 static int dat[5];                      /* aux. data for format routine */
163
164 static char *addrcomps[] = {
165     "from",
166     "sender",
167     "reply-to",
168     "to",
169     "cc",
170     "bcc",
171     "resent-from",
172     "resent-sender",
173     "resent-reply-to",
174     "resent-to",
175     "resent-cc",
176     "resent-bcc",
177     NULL
178 };
179
180 static  insert(), replfilter();
181 /* \f */
182
183 /* ARGSUSED */
184
185 replout (inb, msg, drft, mp)
186     register FILE *inb;
187     char    *msg;
188     char    *drft;
189     struct msgs *mp;
190 {
191     register int  state;
192     register int  i;
193     register struct comp *cptr;
194     register char *tmpbuf;
195     register char **nxtbuf;
196     register struct comp **savecomp;
197     FILE    *out;
198     char    name[NAMESZ];
199     char    *scanl;
200     int     char_read = 0;
201     char    *cp;
202     int      format_len;
203     register char **ap;
204
205     (void) umask( ~ m_gmprot() );
206     if ((out = fopen (drft, "w")) == NULL)
207         adios (drft, "unable to create");
208
209     cp = new_fs (form ? form : replcomps, NULLCP, NULLCP);
210     format_len = strlen (cp);
211     ncomps = fmt_compile (cp, &fmt) + 1;
212     if ((nxtbuf = compbuffers = (char **)
213             calloc((unsigned)ncomps,sizeof(char *))) 
214             == (char **)NULL)
215         adios (NULLCP, "unable to allocate component buffers");
216     if ((savecomp = used_buf = (struct comp **)
217             calloc((unsigned)(ncomps+1),sizeof(struct comp *)))
218             == (struct comp **)NULL)
219         adios (NULLCP, "unable to allocate component buffer stack");
220     savecomp += ncomps + 1;
221     *--savecomp = (struct comp *)0;     /* point at zero'd end minus 1 */
222     for (i = ncomps; i--; )
223         if ((*nxtbuf++ = malloc( SBUFSIZ )) == NULL)
224             adios (NULLCP, "unable to allocate component buffer");
225
226     nxtbuf = compbuffers;               /* point at start */
227     tmpbuf = *nxtbuf++;
228
229     for (ap = addrcomps; *ap; ap++) {
230         FINDCOMP (cptr, *ap);
231         if (cptr)
232             cptr -> c_type |= CT_ADDR;
233     }
234
235     /* ignore any components killed by command line switches */
236     if (!ccto) {
237         FINDCOMP (cptr, "to");
238         if (cptr)
239             cptr->c_name = "";
240     }
241     if (!cccc) {
242         FINDCOMP (cptr, "cc");
243         if (cptr)
244             cptr->c_name = "";
245     }
246     /* set up the "fcc" pseudo-component */
247     if (fcc) {
248         FINDCOMP (cptr, "fcc");
249         if (cptr)
250             cptr->c_text = getcpy (fcc);
251     }
252     if (cp = getenv("USER")) {
253         FINDCOMP (cptr, "user");
254         if (cptr)
255             cptr->c_text = getcpy(cp);
256     }
257     if (!ccme)
258         (void) ismymbox ((struct mailname *)0); /* XXX */
259
260     /* pick any interesting stuff out of msg "inb" */
261     for (state = FLD;;) {
262         state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
263         switch (state) {
264             case FLD: 
265             case FLDPLUS: 
266                 /*
267                  * if we're interested in this component, save a pointer
268                  * to the component text, then start using our next free
269                  * buffer as the component temp buffer (buffer switching
270                  * saves an extra copy of the component text).
271                  */
272                 if (cptr = wantcomp[CHASH(name)])
273                     do {
274                         if (uleq(name, cptr->c_name)) {
275                             char_read += msg_count;
276                             if (! cptr->c_text) {
277                                 cptr->c_text = tmpbuf;
278                                 *--savecomp = cptr;
279                                 tmpbuf = *nxtbuf++;
280                             } else {
281                                 i = strlen (cp = cptr->c_text) - 1;
282                                 if (cp[i] == '\n')
283                                     if (cptr->c_type & CT_ADDR) {
284                                         cp[i] = '\0';
285                                         cp = add (",\n\t", cp);
286                                     } else {
287                                         cp = add ("\t", cp);
288                                     }
289                                 cptr->c_text = add (tmpbuf, cp);
290                             }
291                             while (state == FLDPLUS) {
292                                 state = m_getfld (state, name, tmpbuf,
293                                                   SBUFSIZ, inb);
294                                 cptr->c_text = add (tmpbuf, cptr->c_text);
295                                 char_read += msg_count;
296                             }
297                             break;
298                         }
299                     } while (cptr = cptr->c_next);
300
301                 while (state == FLDPLUS)
302                     state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
303                 break;
304
305             case LENERR: 
306             case FMTERR: 
307             case BODY: 
308             case FILEEOF:
309                 goto finished;
310
311             default: 
312                 adios (NULLCP, "m_getfld() returned %d", state);
313         }
314     }
315     /*
316      * format and output the header lines.
317      */
318 finished:
319     /* if there's a "subject" component, strip any "re:"s off it */
320     FINDCOMP (cptr, "subject")
321     if (cptr && (cp = cptr->c_text)) {
322         register char *sp = cp;
323
324         for (;;) {
325             while (isspace(*cp))
326                 cp++;
327             if(uprf(cp, "re:"))
328                 cp += 3;
329             else
330                 break;
331             sp = cp;
332         }
333         if (sp != cptr->c_text) {
334             cp = cptr->c_text;
335             cptr->c_text = getcpy (sp);
336             free (cp);
337         }
338     }
339     i = format_len + char_read + 256;
340     scanl = malloc ((unsigned)i + 2);
341     dat[0] = dat[1] = dat[2] = dat[4] = 0;
342     dat[3] = outputlinelen;
343     (void) fmtscan (fmt, scanl, i, dat);
344     fputs (scanl, out);
345     if (badaddrs) {
346         fputs ("\nrepl: bad addresses:\n", out);
347         fputs ( badaddrs, out);
348     }
349     if (filter)
350         replfilter (inb, out);
351 #ifdef  MIME
352     else
353         if (mp && mime)
354             (void) fprintf (out, "#forw [original message] +%s %s\n",
355                             mp -> foldpath, m_name (mp -> lowsel));
356 #endif  /* MIME */
357
358     if (ferror (out))
359         adios (drft, "error writing");
360     (void) fclose (out);
361
362     /* return dynamically allocated buffers */
363     free (scanl);
364     for (nxtbuf = compbuffers, i = ncomps;
365             cptr = *savecomp++; nxtbuf++, i--)
366         free (cptr->c_text);    /* if not nxtbuf, nxtbuf already freed */
367     while ( i-- > 0)
368         free (*nxtbuf++);       /* free unused nxtbufs */
369     free ((char *) compbuffers);
370     free ((char *) used_buf);
371 }
372
373 /* \f */
374
375 static char *buf;               /* our current working buffer */
376 static char *bufend;            /* end of working buffer */
377 static char *last_dst;          /* buf ptr at end of last call */
378 static unsigned int bufsiz=0;   /* current size of buf */
379
380 #define BUFINCR 512             /* how much to expand buf when if fills */
381
382 #define CPY(s) { cp = (s); while (*dst++ = *cp++) ; --dst; }
383
384 /* check if there's enough room in buf for str.  add more mem if needed */
385 #define CHECKMEM(str) \
386             if ((len = strlen (str) + 1) >= bufend - dst) {\
387                 int i = dst - buf;\
388                 int n = last_dst - buf;\
389                 bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\
390                 buf = realloc (buf, bufsiz);\
391                 dst = buf + i;\
392                 last_dst = buf + n;\
393                 if (! buf)\
394                     adios (NULLCP, "formataddr: couldn't get buffer space");\
395                 bufend = buf + bufsiz;\
396             }
397
398
399 /* fmtscan will call this routine if the user includes the function
400  * "(formataddr {component})" in a format string.  "orig" is the
401  * original contents of the string register.  "str" is the address
402  * string to be formatted and concatenated onto orig.  This routine
403  * returns a pointer to the concatenated address string.
404  *
405  * We try to not do a lot of malloc/copy/free's (which is why we
406  * don't call "getcpy") but still place no upper limit on the
407  * length of the result string.
408  */
409 char *formataddr (orig, str)
410     char *orig;
411     char *str;
412 {
413     register int  len;
414     char    baddr[BUFSIZ],
415             error[BUFSIZ];
416     register int  isgroup;
417     register char  *dst;
418     register char  *cp;
419     register char  *sp;
420     register struct mailname *mp = NULL;
421
422     /* if we don't have a buffer yet, get one */
423     if (bufsiz == 0) {
424         buf = malloc (BUFINCR);
425         if (! buf)
426             adios (NULLCP, "formataddr: couldn't allocate buffer space");
427         last_dst = buf;         /* XXX */
428         bufsiz = BUFINCR - 6;  /* leave some slop */
429         bufend = buf + bufsiz;
430     }
431     /*
432      * If "orig" points to our buffer we can just pick up where we
433      * left off.  Otherwise we have to copy orig into our buffer.
434      */
435     if (orig == buf)
436         dst = last_dst;
437     else if (!orig || !*orig) {
438         dst = buf;
439         *dst = '\0';
440     } else {
441         dst = last_dst;         /* XXX */
442         CHECKMEM (orig);
443         CPY (orig);
444     }
445
446     /* concatenate all the new addresses onto 'buf' */
447     for (isgroup = 0; cp = getname (str); ) {
448         if ((mp = getm (cp, dfhost, dftype, AD_NAME, error)) == NULL) {
449             (void) sprintf (baddr, "\t%s -- %s\n", cp, error);
450             badaddrs = add (baddr, badaddrs);
451             continue;
452         }
453         if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
454             *dst++ = ';';
455             isgroup = 0;
456         }
457         if (insert (mp)) {
458             /* if we get here we're going to add an address */
459             if (dst != buf) {
460                 *dst++ = ',';
461                 *dst++ = ' ';
462             }
463             if (mp->m_gname) {
464                 CHECKMEM (mp->m_gname);
465                 CPY (mp->m_gname);
466                 isgroup++;
467             }
468             sp = adrformat (mp);
469             CHECKMEM (sp);
470             CPY (sp);
471         }
472     }
473
474     if (isgroup)
475         *dst++ = ';';
476
477     *dst = '\0';
478     last_dst = dst;
479     return (buf);
480 }
481 /* \f */
482
483 static  insert (np)
484 register struct mailname *np;
485 {
486     char    buffer[BUFSIZ];
487     register struct mailname *mp;
488
489     if (np -> m_mbox == NULL)
490         return 0;
491
492     for (mp = &mq; mp -> m_next; mp = mp -> m_next) {
493 #ifdef BERK
494         if (uleq (np -> m_mbox, mp -> m_next -> m_mbox))
495             return 0;
496 #else   /* not BERK */
497         if (uleq (np -> m_host, mp -> m_next -> m_host)
498                 && uleq (np -> m_mbox, mp -> m_next -> m_mbox))
499             return 0;
500 #endif  /* BERK */
501     }
502     if (!ccme && ismymbox (np))
503         return 0;
504
505     if (querysw) {
506         (void) sprintf (buffer, "Reply to %s? ", adrformat (np));
507         if (!gans (buffer, anoyes))
508         return 0;
509     }
510     mp -> m_next = np;
511 #ifdef  ISI
512     if (ismymbox (np))
513         ccme = 0;
514 #endif  /* ISI */
515     return 1;
516 }
517
518 /* \f */
519
520 static  replfilter (in, out)
521 register FILE *in,
522               *out;
523 {
524     int     pid;
525     char   *mhl;
526
527     if (filter == NULL)
528         return;
529
530     if (access (filter, 04) == NOTOK)
531         adios (filter, "unable to read");
532
533     mhl = r1bindex (mhlproc, '/');
534
535     rewind (in);
536     (void) lseek (fileno(in), (off_t)0, L_SET);
537     (void) fflush (out);
538
539     switch (pid = vfork ()) {
540         case NOTOK: 
541             adios ("fork", "unable to");
542
543         case OK: 
544             (void) dup2 (fileno (in), fileno (stdin));
545             (void) dup2 (fileno (out), fileno (stdout));
546             closefds (3);
547
548             execlp (mhlproc, mhl, "-form", filter, "-noclear", NULLCP);
549             fprintf (stderr, "unable to exec ");
550             perror (mhlproc);
551             _exit (-1);
552
553         default: 
554             if (pidXwait (pid, mhl))
555                 done (1);
556             (void) fseek (out, 0L, 2);
557             break;
558     }
559 }
560 @
561
562
563 1.18
564 log
565 @add repl -mime
566 @
567 text
568 @d3 1
569 a3 1
570 static char ident[] = "@@(#)$Id: replsbr.c,v 1.17 1993/09/04 19:31:32 jromine Exp jromine $";
571 d274 1
572 a274 1
573             if ((len = strlen (str)) >= bufend - dst) {\
574 @
575
576
577 1.17
578 log
579 @use L_SET instead of SEEK_SET (for backward-compatibility)
580 include sys/types.h, sys/file.h for lseek
581 @
582 text
583 @d3 1
584 a3 1
585 static char ident[] = "@@(#)$Id: replsbr.c,v 1.16 1993/08/26 22:13:19 jromine Exp jromine $";
586 d21 1
587 d73 1
588 a73 1
589 replout (inb, msg, drft)
590 d77 1
591 d239 6
592 @
593
594
595 1.16
596 log
597 @always lseek after rewind (not only on _FSTDIO systems)
598 @
599 text
600 @d3 1
601 a3 1
602 static char ident[] = "@@(#)$Id: replsbr.c,v 1.15 1993/08/25 17:27:35 jromine Exp jromine $";
603 d11 2
604 d416 1
605 a416 1
606     (void) lseek (fileno(in), (off_t)0, SEEK_SET);
607 @
608
609
610 1.15
611 log
612 @off_t fixes for BSD44
613 @
614 text
615 @d3 1
616 a3 1
617 static char ident[] = "@@(#)$Id: replsbr.c,v 1.14 1993/02/26 21:59:28 jromine Exp jromine $";
618 d414 1
619 a425 4
620 #ifdef _FSTDIO
621             /* <sigh> the code assumed that rewind does this. */
622             (void) lseek (fileno(stdin), (off_t)0, SEEK_SET);
623 #endif
624 @
625
626
627 1.14
628 log
629 @_FSTDIO
630 @
631 text
632 @d3 1
633 a3 1
634 static char ident[] = "@@(#)$Id: replsbr.c,v 1.13 1992/12/15 00:20:22 jromine Exp jromine $";
635 d427 1
636 a427 1
637             lseek (fileno(stdin), 0, SEEK_SET);
638 @
639
640
641 1.13
642 log
643 @endif sugar
644 @
645 text
646 @d3 1
647 a3 1
648 static char ident[] = "@@(#)$Id: replsbr.c,v 1.12 1992/11/04 00:58:58 jromine Exp jromine $";
649 d425 4
650 @
651
652
653 1.12
654 log
655 @LOCALE
656 @
657 text
658 @d3 2
659 a4 2
660 static char ident[] = "@@(#)$Id: replsbr.c,v 1.11 1992/02/05 07:26:30 jromine Exp jromine $";
661 #endif  lint
662 d374 1
663 a374 1
664 #else not BERK
665 d378 1
666 a378 1
667 #endif BERK
668 d392 1
669 a392 1
670 #endif  ISI
671 @
672
673
674 1.11
675 log
676 @put unseen sequence in mh-format
677 @
678 text
679 @d3 1
680 a3 1
681 static char ident[] = "@@(#)$Id: replsbr.c,v 1.10 1991/01/17 15:29:27 mh Exp jromine $";
682 d209 5
683 a213 3
684             while (isspace(i = *cp++))
685                 ;
686             if ((i | 0x20) != 'r' || (*cp++ | 0x20) != 'e' || *cp++ != ':')
687 @
688
689
690 1.10
691 log
692 @add pseudo-component {user} = $USER envariable
693 @
694 text
695 @d3 1
696 a3 1
697 static char ident[] = "@@(#)$Id: replsbr.c,v 1.9 90/11/05 11:38:43 mh Exp Locker: mh $";
698 d47 1
699 a47 1
700 static int dat[4];                      /* aux. data for format routine */
701 d223 1
702 a223 1
703     dat[0] = dat[1] = dat[2] = 0;
704 @
705
706
707 1.9
708 log
709 @jlr
710 @
711 text
712 @d3 1
713 a3 1
714 static char ident[] = "@@(#)$Id: replsbr.c,v 1.8 90/11/05 11:35:20 mh Exp Locker: mh $";
715 d135 5
716 @
717
718
719 1.8
720 log
721 @fix
722 @
723 text
724 @d3 1
725 a3 1
726 static char ident[] = "@@(#)$Id: replsbr.c,v 1.7 90/11/05 11:23:19 mh Exp Locker: mh $";
727 d96 4
728 a99 1
729
730 a105 5
731
732     if ((nxtbuf = compbuffers = (char **)
733             calloc((unsigned)ncomps,sizeof(char *))) 
734             == (char **)NULL)
735         adios (NULLCP, "unable to allocate component buffers");
736 d109 1
737 @
738
739
740 1.7
741 log
742 @fix free'ing freed buf problem
743 @
744 text
745 @d3 1
746 a3 1
747 static char ident[] = "@@(#)$Id: replsbr.c,v 1.6 90/04/05 14:59:43 sources Exp Locker: mh $";
748 d157 1
749 a157 1
750                                 cptr->c_text = tmpbuf;  /* use a buf */
751 d159 1
752 a159 1
753                                 tmpbuf = *nxtbuf++;     /* ready next buf */
754 @
755
756
757 1.6
758 log
759 @add ID
760 @
761 text
762 @d3 1
763 a3 1
764 static char ident[] = "@@(#)$Id:$";
765 a87 1
766     struct comp **used_buf_fp;
767 d96 11
768 a106 2
769     nxtbuf = compbuffers = (char **)calloc((unsigned)ncomps,sizeof(char *));
770     if (nxtbuf == NULL)
771 a107 5
772     used_buf_fp = used_buf =
773         (struct comp **)calloc((unsigned)(ncomps+1),sizeof(struct comp *));
774     if (used_buf == NULL)
775         adios (NULLCP, "unable to allocate component buffer stack");
776     used_buf += ncomps+1; *--used_buf = 0;
777 d111 1
778 a111 3
779
780     nxtbuf = compbuffers;
781     savecomp = used_buf;
782 d157 1
783 a157 1
784                                 cptr->c_text = tmpbuf;
785 d159 1
786 a159 1
787                                 tmpbuf = *nxtbuf++;
788 d236 5
789 a240 4
790     while ( cptr = *savecomp++ )
791         free (cptr->c_text);
792     for (nxtbuf = compbuffers, i = ncomps; i--; )
793         free (*nxtbuf++);
794 d242 1
795 a242 1
796     free ((char *) used_buf_fp);
797 @
798
799
800 1.5
801 log
802 @dst fix
803 @
804 text
805 @d2 3
806 @
807
808
809 1.4
810 log
811 @Fixes from Van Jacobson
812 @
813 text
814 @d294 1
815 d308 1
816 @
817
818
819 1.3
820 log
821 @ANSI Compilance
822 @
823 text
824 @d28 2
825 a29 1
826 #define SBUFSIZ 256             /* buffer size for content part of header
827 @
828
829
830 1.2
831 log
832 @fix freeing incremented malloc pointer bug
833 @
834 text
835 @d61 1
836 @
837
838
839 1.1
840 log
841 @Initial revision
842 @
843 text
844 @d83 1
845 d95 2
846 a96 1
847     used_buf = (struct comp **)calloc((unsigned)(ncomps+1),sizeof(struct comp *));
848 d235 1
849 a235 1
850     if (*used_buf) free ((char *) used_buf);
851 @