From 4ab286d12be3ccc5f3000673857b4f69b689c69b Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Fri, 3 Feb 2012 12:25:42 +0100 Subject: [PATCH] Major bugfix: inc does not lose data anymore. What have I done in 70b2643e0da8485174480c644ad9785c84f5bff4 ? Producing scan listings and inc'ing mail are too closely related. By removing the body component from scan listings, I also had removed the ability to copy bodies during inc. Hence this commit undos the changes. (And reintroduces the body component in scan listings. :-( ) The code is too much interweaved! --- uip/scansbr.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/uip/scansbr.c b/uip/scansbr.c index 9617237..a43044c 100644 --- a/uip/scansbr.c +++ b/uip/scansbr.c @@ -30,13 +30,16 @@ /* ** 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. +** calls on m_getfld but small enough so that we don't snarf +** the entire message body when we're only going to display 30 +** characters of it. */ #define SBUFSIZ 512 static struct format *fmt; static struct comp *datecomp; /* pntr to "date" comp */ +static struct comp *bodycomp; /* pntr to "body" pseudo-comp (if referenced) */ 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 */ @@ -71,12 +74,13 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, int i, compnum, encrypted, state; unsigned char *cp, *tmpbuf; char **nxtbuf; + char *saved_c_text = NULL; struct comp *cptr; struct comp **savecomp; char *scnmsg = NULL; FILE *scnout = NULL; char name[NAMESZ]; - static int slwidth; + static int rlwidth, slwidth; #ifdef RPATHS char returnpath[BUFSIZ]; @@ -100,6 +104,7 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, /* Compile format string */ ncomps = fmt_compile(nfs, &fmt) + 1; + FINDCOMP(bodycomp, "body"); FINDCOMP(datecomp, "date"); FINDCOMP(cptr, "folder"); if (cptr && folder) @@ -108,7 +113,7 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, if (!cptr) if ((cptr = (struct comp *)calloc(1, sizeof(*cptr)))) { cptr->c_name = "encrypted"; - cptr->c_next = wantcomp[i=CHASH(cptr->c_name)]; + cptr->c_next = wantcomp[i = CHASH(cptr->c_name)]; wantcomp[i] = cptr; ncomps++; } @@ -124,8 +129,9 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, if (used_buf == NULL) adios(NULL, "unable to allocate component buffer stack"); used_buf += ncomps+1; *--used_buf = 0; + rlwidth = bodycomp && (width > SBUFSIZ) ? width : SBUFSIZ; for (i = ncomps; i--; ) - *nxtbuf++ = mh_xmalloc(SBUFSIZ); + *nxtbuf++ = mh_xmalloc(rlwidth); } /* @@ -142,7 +148,7 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, ** Get the first field. If the message is non-empty ** and we're doing an "inc", open the output file. */ - if ((state = m_getfld(FLD, name, tmpbuf, SBUFSIZ, inb)) == FILEEOF) { + if ((state = m_getfld(FLD, name, tmpbuf, rlwidth, inb)) == FILEEOF) { if (ferror(inb)) { advise("read", "unable to"); /* "read error" */ return SCNFAT; @@ -178,7 +184,7 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, /* scan - main loop */ for (compnum = 1; ; - state = m_getfld(state, name, tmpbuf, SBUFSIZ, inb)) { + state = m_getfld(state, name, tmpbuf, rlwidth, inb)) { switch (state) { case FLD: case FLDPLUS: @@ -215,7 +221,7 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, } while (state == FLDPLUS) { - state = m_getfld(state, name, tmpbuf, SBUFSIZ, + state = m_getfld(state, name, tmpbuf, rlwidth, inb); if (outnum) FPUTS(tmpbuf); @@ -223,7 +229,49 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, break; case BODY: - state = FILEEOF; + compnum = -1; + if (! outnum) { + state = FILEEOF; /* stop now if scan cmd */ + goto finished; + } + if (putc('\n', scnout) == EOF) DIEWRERR(); + FPUTS(tmpbuf); + /* + ** performance hack: some people like to run "inc" + ** on things like net.sources or large digests. + ** We do a copy directly into the output buffer + ** rather than going through an intermediate buffer. + ** + ** We need the amount of data m_getfld found & + ** don't want to do a strlen on the long buffer so + ** there's a hack in m_getfld to save the amount + ** of data it returned in the global "msg_count". + */ +body:; + while (state == BODY) { +#ifdef LINUX_STDIO + if (scnout->_IO_write_ptr == scnout->_IO_write_end) { +#elif defined(__DragonFly__) + if (((struct __FILE_public *)scnout)->_w <= 0) { +#else + if (scnout->_cnt <= 0) { +#endif + if (fflush(scnout) == EOF) + DIEWRERR(); + } +#ifdef LINUX_STDIO + state = m_getfld(state, name, scnout->_IO_write_ptr, (long)scnout->_IO_write_ptr-(long)scnout->_IO_write_end , inb); + scnout->_IO_write_ptr += msg_count; +#elif defined(__DragonFly__) + state = m_getfld(state, name, ((struct __FILE_public *)scnout)->_p, -(((struct __FILE_public *)scnout)->_w), inb); + ((struct __FILE_public *)scnout)->_w -= msg_count; + ((struct __FILE_public *)scnout)->_p += msg_count; +#else + state = m_getfld( state, name, scnout->_ptr, -(scnout->_cnt), inb); + scnout->_cnt -= msg_count; + scnout->_ptr += msg_count; +#endif + } goto finished; case LENERR: @@ -236,6 +284,8 @@ scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, FPUTS(name); if (putc('\n', scnout) == EOF) DIEWRERR(); + state = BODY; + goto body; } /* fall through */ @@ -256,6 +306,12 @@ finished: return SCNFAT; } + /* Save and restore buffer so we don't trash our dynamic pool! */ + if (bodycomp) { + saved_c_text = bodycomp->c_text; + bodycomp->c_text = tmpbuf; + } + if (size) dat[2] = size; else if (outnum > 0) { @@ -286,6 +342,9 @@ finished: fmt_scan(fmt, scanl, slwidth, dat); + if (bodycomp) + bodycomp->c_text = saved_c_text; + if (noisy) fputs(scanl, stdout); -- 1.7.10.4