]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/RCS/replsbr.c,v
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / 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 @