head 1.19; access; symbols; locks; strict; comment @ * @; 1.19 date 95.12.06.23.47.26; author jromine; state Exp; branches; next 1.18; 1.18 date 95.12.06.21.07.03; author jromine; state Exp; branches; next 1.17; 1.17 date 93.09.04.19.31.32; author jromine; state Exp; branches; next 1.16; 1.16 date 93.08.26.22.13.19; author jromine; state Exp; branches; next 1.15; 1.15 date 93.08.25.17.27.35; author jromine; state Exp; branches; next 1.14; 1.14 date 93.02.26.21.59.28; author jromine; state Exp; branches; next 1.13; 1.13 date 92.12.15.00.20.22; author jromine; state Exp; branches; next 1.12; 1.12 date 92.11.04.00.58.58; author jromine; state Exp; branches; next 1.11; 1.11 date 92.02.05.07.26.30; author jromine; state Exp; branches; next 1.10; 1.10 date 91.01.17.15.29.27; author mh; state Exp; branches; next 1.9; 1.9 date 90.11.05.11.38.43; author mh; state Exp; branches; next 1.8; 1.8 date 90.11.05.11.35.20; author mh; state Exp; branches; next 1.7; 1.7 date 90.11.05.11.23.19; author mh; state Exp; branches; next 1.6; 1.6 date 90.04.05.14.59.43; author sources; state Exp; branches; next 1.5; 1.5 date 90.03.12.10.49.00; author sources; state Exp; branches; next 1.4; 1.4 date 90.02.09.10.11.12; author sources; state Exp; branches; next 1.3; 1.3 date 90.02.06.13.29.55; author sources; state Exp; branches; next 1.2; 1.2 date 90.01.30.14.05.59; author sources; state Exp; branches; next 1.1; 1.1 date 90.01.30.11.17.06; author sources; state Exp; branches; next ; desc @@ 1.19 log @fix: off-by-1 error @ text @/* replsbr.c - routines to help repl along... */ #ifndef lint static char ident[] = "@@(#)$Id: replsbr.c,v 1.18 1995/12/06 21:07:03 jromine Exp jromine $"; #endif /* lint */ #include "../h/mh.h" #include "../h/addrsbr.h" #include "../h/formatsbr.h" #include #include #include /* off_t */ #include /* L_SET */ extern short ccto, /* from repl.c */ cccc, ccme, format, outputlinelen, querysw; extern int mime; extern char *fcc, *filter, *form; static int dftype=0; static char *badaddrs = NULL; static char *dfhost=NULL; static struct mailname mq={NULL}; #define SBUFSIZ 256 /* buffer size for content part of header * fields. We want this to be large * enough so that we don't do a lot of * extra FLDPLUS calls on m_getfld but * small enough so that we don't snarf * the entire message body when we're * not going to use any of it. */ static struct format *fmt; static int ncomps = 0; /* # of interesting components */ static char **compbuffers = 0; /* buffers for component text */ static struct comp **used_buf = 0; /* stack for comp that use buffers */ static int dat[5]; /* aux. data for format routine */ static char *addrcomps[] = { "from", "sender", "reply-to", "to", "cc", "bcc", "resent-from", "resent-sender", "resent-reply-to", "resent-to", "resent-cc", "resent-bcc", NULL }; static insert(), replfilter(); /* */ /* ARGSUSED */ replout (inb, msg, drft, mp) register FILE *inb; char *msg; char *drft; struct msgs *mp; { register int state; register int i; register struct comp *cptr; register char *tmpbuf; register char **nxtbuf; register struct comp **savecomp; FILE *out; char name[NAMESZ]; char *scanl; int char_read = 0; char *cp; int format_len; register char **ap; (void) umask( ~ m_gmprot() ); if ((out = fopen (drft, "w")) == NULL) adios (drft, "unable to create"); cp = new_fs (form ? form : replcomps, NULLCP, NULLCP); format_len = strlen (cp); ncomps = fmt_compile (cp, &fmt) + 1; if ((nxtbuf = compbuffers = (char **) calloc((unsigned)ncomps,sizeof(char *))) == (char **)NULL) adios (NULLCP, "unable to allocate component buffers"); if ((savecomp = used_buf = (struct comp **) calloc((unsigned)(ncomps+1),sizeof(struct comp *))) == (struct comp **)NULL) adios (NULLCP, "unable to allocate component buffer stack"); savecomp += ncomps + 1; *--savecomp = (struct comp *)0; /* point at zero'd end minus 1 */ for (i = ncomps; i--; ) if ((*nxtbuf++ = malloc( SBUFSIZ )) == NULL) adios (NULLCP, "unable to allocate component buffer"); nxtbuf = compbuffers; /* point at start */ tmpbuf = *nxtbuf++; for (ap = addrcomps; *ap; ap++) { FINDCOMP (cptr, *ap); if (cptr) cptr -> c_type |= CT_ADDR; } /* ignore any components killed by command line switches */ if (!ccto) { FINDCOMP (cptr, "to"); if (cptr) cptr->c_name = ""; } if (!cccc) { FINDCOMP (cptr, "cc"); if (cptr) cptr->c_name = ""; } /* set up the "fcc" pseudo-component */ if (fcc) { FINDCOMP (cptr, "fcc"); if (cptr) cptr->c_text = getcpy (fcc); } if (cp = getenv("USER")) { FINDCOMP (cptr, "user"); if (cptr) cptr->c_text = getcpy(cp); } if (!ccme) (void) ismymbox ((struct mailname *)0); /* XXX */ /* pick any interesting stuff out of msg "inb" */ for (state = FLD;;) { state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb); switch (state) { case FLD: case FLDPLUS: /* * if we're interested in this component, save a pointer * to the component text, then start using our next free * buffer as the component temp buffer (buffer switching * saves an extra copy of the component text). */ if (cptr = wantcomp[CHASH(name)]) do { if (uleq(name, cptr->c_name)) { char_read += msg_count; if (! cptr->c_text) { cptr->c_text = tmpbuf; *--savecomp = cptr; tmpbuf = *nxtbuf++; } else { i = strlen (cp = cptr->c_text) - 1; if (cp[i] == '\n') if (cptr->c_type & CT_ADDR) { cp[i] = '\0'; cp = add (",\n\t", cp); } else { cp = add ("\t", cp); } cptr->c_text = add (tmpbuf, cp); } while (state == FLDPLUS) { state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb); cptr->c_text = add (tmpbuf, cptr->c_text); char_read += msg_count; } break; } } while (cptr = cptr->c_next); while (state == FLDPLUS) state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb); break; case LENERR: case FMTERR: case BODY: case FILEEOF: goto finished; default: adios (NULLCP, "m_getfld() returned %d", state); } } /* * format and output the header lines. */ finished: /* if there's a "subject" component, strip any "re:"s off it */ FINDCOMP (cptr, "subject") if (cptr && (cp = cptr->c_text)) { register char *sp = cp; for (;;) { while (isspace(*cp)) cp++; if(uprf(cp, "re:")) cp += 3; else break; sp = cp; } if (sp != cptr->c_text) { cp = cptr->c_text; cptr->c_text = getcpy (sp); free (cp); } } i = format_len + char_read + 256; scanl = malloc ((unsigned)i + 2); dat[0] = dat[1] = dat[2] = dat[4] = 0; dat[3] = outputlinelen; (void) fmtscan (fmt, scanl, i, dat); fputs (scanl, out); if (badaddrs) { fputs ("\nrepl: bad addresses:\n", out); fputs ( badaddrs, out); } if (filter) replfilter (inb, out); #ifdef MIME else if (mp && mime) (void) fprintf (out, "#forw [original message] +%s %s\n", mp -> foldpath, m_name (mp -> lowsel)); #endif /* MIME */ if (ferror (out)) adios (drft, "error writing"); (void) fclose (out); /* return dynamically allocated buffers */ free (scanl); for (nxtbuf = compbuffers, i = ncomps; cptr = *savecomp++; nxtbuf++, i--) free (cptr->c_text); /* if not nxtbuf, nxtbuf already freed */ while ( i-- > 0) free (*nxtbuf++); /* free unused nxtbufs */ free ((char *) compbuffers); free ((char *) used_buf); } /* */ static char *buf; /* our current working buffer */ static char *bufend; /* end of working buffer */ static char *last_dst; /* buf ptr at end of last call */ static unsigned int bufsiz=0; /* current size of buf */ #define BUFINCR 512 /* how much to expand buf when if fills */ #define CPY(s) { cp = (s); while (*dst++ = *cp++) ; --dst; } /* check if there's enough room in buf for str. add more mem if needed */ #define CHECKMEM(str) \ if ((len = strlen (str) + 1) >= bufend - dst) {\ int i = dst - buf;\ int n = last_dst - buf;\ bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\ buf = realloc (buf, bufsiz);\ dst = buf + i;\ last_dst = buf + n;\ if (! buf)\ adios (NULLCP, "formataddr: couldn't get buffer space");\ bufend = buf + bufsiz;\ } /* fmtscan will call this routine if the user includes the function * "(formataddr {component})" in a format string. "orig" is the * original contents of the string register. "str" is the address * string to be formatted and concatenated onto orig. This routine * returns a pointer to the concatenated address string. * * We try to not do a lot of malloc/copy/free's (which is why we * don't call "getcpy") but still place no upper limit on the * length of the result string. */ char *formataddr (orig, str) char *orig; char *str; { register int len; char baddr[BUFSIZ], error[BUFSIZ]; register int isgroup; register char *dst; register char *cp; register char *sp; register struct mailname *mp = NULL; /* if we don't have a buffer yet, get one */ if (bufsiz == 0) { buf = malloc (BUFINCR); if (! buf) adios (NULLCP, "formataddr: couldn't allocate buffer space"); last_dst = buf; /* XXX */ bufsiz = BUFINCR - 6; /* leave some slop */ bufend = buf + bufsiz; } /* * If "orig" points to our buffer we can just pick up where we * left off. Otherwise we have to copy orig into our buffer. */ if (orig == buf) dst = last_dst; else if (!orig || !*orig) { dst = buf; *dst = '\0'; } else { dst = last_dst; /* XXX */ CHECKMEM (orig); CPY (orig); } /* concatenate all the new addresses onto 'buf' */ for (isgroup = 0; cp = getname (str); ) { if ((mp = getm (cp, dfhost, dftype, AD_NAME, error)) == NULL) { (void) sprintf (baddr, "\t%s -- %s\n", cp, error); badaddrs = add (baddr, badaddrs); continue; } if (isgroup && (mp->m_gname || !mp->m_ingrp)) { *dst++ = ';'; isgroup = 0; } if (insert (mp)) { /* if we get here we're going to add an address */ if (dst != buf) { *dst++ = ','; *dst++ = ' '; } if (mp->m_gname) { CHECKMEM (mp->m_gname); CPY (mp->m_gname); isgroup++; } sp = adrformat (mp); CHECKMEM (sp); CPY (sp); } } if (isgroup) *dst++ = ';'; *dst = '\0'; last_dst = dst; return (buf); } /* */ static insert (np) register struct mailname *np; { char buffer[BUFSIZ]; register struct mailname *mp; if (np -> m_mbox == NULL) return 0; for (mp = &mq; mp -> m_next; mp = mp -> m_next) { #ifdef BERK if (uleq (np -> m_mbox, mp -> m_next -> m_mbox)) return 0; #else /* not BERK */ if (uleq (np -> m_host, mp -> m_next -> m_host) && uleq (np -> m_mbox, mp -> m_next -> m_mbox)) return 0; #endif /* BERK */ } if (!ccme && ismymbox (np)) return 0; if (querysw) { (void) sprintf (buffer, "Reply to %s? ", adrformat (np)); if (!gans (buffer, anoyes)) return 0; } mp -> m_next = np; #ifdef ISI if (ismymbox (np)) ccme = 0; #endif /* ISI */ return 1; } /* */ static replfilter (in, out) register FILE *in, *out; { int pid; char *mhl; if (filter == NULL) return; if (access (filter, 04) == NOTOK) adios (filter, "unable to read"); mhl = r1bindex (mhlproc, '/'); rewind (in); (void) lseek (fileno(in), (off_t)0, L_SET); (void) fflush (out); switch (pid = vfork ()) { case NOTOK: adios ("fork", "unable to"); case OK: (void) dup2 (fileno (in), fileno (stdin)); (void) dup2 (fileno (out), fileno (stdout)); closefds (3); execlp (mhlproc, mhl, "-form", filter, "-noclear", NULLCP); fprintf (stderr, "unable to exec "); perror (mhlproc); _exit (-1); default: if (pidXwait (pid, mhl)) done (1); (void) fseek (out, 0L, 2); break; } } @ 1.18 log @add repl -mime @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.17 1993/09/04 19:31:32 jromine Exp jromine $"; d274 1 a274 1 if ((len = strlen (str)) >= bufend - dst) {\ @ 1.17 log @use L_SET instead of SEEK_SET (for backward-compatibility) include sys/types.h, sys/file.h for lseek @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.16 1993/08/26 22:13:19 jromine Exp jromine $"; d21 1 d73 1 a73 1 replout (inb, msg, drft) d77 1 d239 6 @ 1.16 log @always lseek after rewind (not only on _FSTDIO systems) @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.15 1993/08/25 17:27:35 jromine Exp jromine $"; d11 2 d416 1 a416 1 (void) lseek (fileno(in), (off_t)0, SEEK_SET); @ 1.15 log @off_t fixes for BSD44 @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.14 1993/02/26 21:59:28 jromine Exp jromine $"; d414 1 a425 4 #ifdef _FSTDIO /* the code assumed that rewind does this. */ (void) lseek (fileno(stdin), (off_t)0, SEEK_SET); #endif @ 1.14 log @_FSTDIO @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.13 1992/12/15 00:20:22 jromine Exp jromine $"; d427 1 a427 1 lseek (fileno(stdin), 0, SEEK_SET); @ 1.13 log @endif sugar @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.12 1992/11/04 00:58:58 jromine Exp jromine $"; d425 4 @ 1.12 log @LOCALE @ text @d3 2 a4 2 static char ident[] = "@@(#)$Id: replsbr.c,v 1.11 1992/02/05 07:26:30 jromine Exp jromine $"; #endif lint d374 1 a374 1 #else not BERK d378 1 a378 1 #endif BERK d392 1 a392 1 #endif ISI @ 1.11 log @put unseen sequence in mh-format @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.10 1991/01/17 15:29:27 mh Exp jromine $"; d209 5 a213 3 while (isspace(i = *cp++)) ; if ((i | 0x20) != 'r' || (*cp++ | 0x20) != 'e' || *cp++ != ':') @ 1.10 log @add pseudo-component {user} = $USER envariable @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.9 90/11/05 11:38:43 mh Exp Locker: mh $"; d47 1 a47 1 static int dat[4]; /* aux. data for format routine */ d223 1 a223 1 dat[0] = dat[1] = dat[2] = 0; @ 1.9 log @jlr @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.8 90/11/05 11:35:20 mh Exp Locker: mh $"; d135 5 @ 1.8 log @fix @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.7 90/11/05 11:23:19 mh Exp Locker: mh $"; d96 4 a99 1 a105 5 if ((nxtbuf = compbuffers = (char **) calloc((unsigned)ncomps,sizeof(char *))) == (char **)NULL) adios (NULLCP, "unable to allocate component buffers"); d109 1 @ 1.7 log @fix free'ing freed buf problem @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: replsbr.c,v 1.6 90/04/05 14:59:43 sources Exp Locker: mh $"; d157 1 a157 1 cptr->c_text = tmpbuf; /* use a buf */ d159 1 a159 1 tmpbuf = *nxtbuf++; /* ready next buf */ @ 1.6 log @add ID @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id:$"; a87 1 struct comp **used_buf_fp; d96 11 a106 2 nxtbuf = compbuffers = (char **)calloc((unsigned)ncomps,sizeof(char *)); if (nxtbuf == NULL) a107 5 used_buf_fp = used_buf = (struct comp **)calloc((unsigned)(ncomps+1),sizeof(struct comp *)); if (used_buf == NULL) adios (NULLCP, "unable to allocate component buffer stack"); used_buf += ncomps+1; *--used_buf = 0; d111 1 a111 3 nxtbuf = compbuffers; savecomp = used_buf; d157 1 a157 1 cptr->c_text = tmpbuf; d159 1 a159 1 tmpbuf = *nxtbuf++; d236 5 a240 4 while ( cptr = *savecomp++ ) free (cptr->c_text); for (nxtbuf = compbuffers, i = ncomps; i--; ) free (*nxtbuf++); d242 1 a242 1 free ((char *) used_buf_fp); @ 1.5 log @dst fix @ text @d2 3 @ 1.4 log @Fixes from Van Jacobson @ text @d294 1 d308 1 @ 1.3 log @ANSI Compilance @ text @d28 2 a29 1 #define SBUFSIZ 256 /* buffer size for content part of header @ 1.2 log @fix freeing incremented malloc pointer bug @ text @d61 1 @ 1.1 log @Initial revision @ text @d83 1 d95 2 a96 1 used_buf = (struct comp **)calloc((unsigned)(ncomps+1),sizeof(struct comp *)); d235 1 a235 1 if (*used_buf) free ((char *) used_buf); @