X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fscansbr.c;h=1c68bc26d53afbfa4bfe8297f4b5a9ec40a3543d;hp=9617237a3a92791536758f70e090cb4bf4a7b3a1;hb=51d0e643f8daeb2db8de0a3d31d7d7f038b48380;hpb=70b2643e0da8485174480c644ad9785c84f5bff4 diff --git a/uip/scansbr.c b/uip/scansbr.c index 9617237..1c68bc2 100644 --- a/uip/scansbr.c +++ b/uip/scansbr.c @@ -30,25 +30,28 @@ /* ** 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 */ +static char **compbuffers = NULL; /* buffers for component text */ +static struct comp **used_buf = NULL; /* stack for comp that use buffers */ static int dat[5]; /* aux. data for format routine */ -char *scanl = 0; /* text of most recent scanline */ +char *scanl = NULL; /* text of most recent scanline */ #define DIEWRERR() adios(scnmsg, "write error on") #define FPUTS(buf) {\ - if (mh_fputs(buf,scnout) == EOF)\ + if (fputs(buf,scnout) == EOF)\ DIEWRERR();\ } @@ -56,7 +59,6 @@ char *scanl = 0; /* text of most recent scanline */ ** prototypes */ int sc_width(void); /* from termsbr.c */ -static int mh_fputs(char *, FILE *); #ifdef MULTIBYTE_SUPPORT #define SCAN_CHARWIDTH MB_CUR_MAX @@ -66,17 +68,18 @@ static int mh_fputs(char *, FILE *); int scan(FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, - int unseen, char *folder, long size, int noisy) + int unseen, int noisy) { - int i, compnum, encrypted, state; + int i, compnum, 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,21 +103,8 @@ 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) - cptr->c_text = folder; - FINDCOMP(cptr, "encrypted"); - if (!cptr) - if ((cptr = (struct comp *)calloc(1, sizeof(*cptr)))) { - cptr->c_name = "encrypted"; - cptr->c_next = wantcomp[i=CHASH(cptr->c_name)]; - wantcomp[i] = cptr; - ncomps++; - } - FINDCOMP(cptr, "dtimenow"); - if (cptr) - cptr->c_text = getcpy(dtimenow(0)); nxtbuf = compbuffers = (char **) calloc((size_t) ncomps, sizeof(char *)); if (nxtbuf == NULL) @@ -124,8 +114,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 +133,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 +169,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 +206,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 +214,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 +269,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,19 +291,23 @@ finished: return SCNFAT; } - if (size) - dat[2] = size; - else if (outnum > 0) { + /* 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 (outnum > 0) { dat[2] = ftell(scnout); if (dat[2] == EOF) DIEWRERR(); } - if ((datecomp && !datecomp->c_text) || (!size && !outnum)) { + if ((datecomp && !datecomp->c_text) || !outnum) { struct stat st; fstat(fileno(inb), &st); - if (!size && !outnum) + if (!outnum) dat[2] = st.st_size; if (datecomp) { if (! datecomp->c_text) { @@ -286,12 +325,12 @@ finished: fmt_scan(fmt, scanl, slwidth, dat); + if (bodycomp) + bodycomp->c_text = saved_c_text; + if (noisy) fputs(scanl, stdout); - FINDCOMP(cptr, "encrypted"); - encrypted = cptr && cptr->c_text; - /* return dynamically allocated buffers to pool */ while ((cptr = *savecomp++)) { *--nxtbuf = cptr->c_text; @@ -302,16 +341,5 @@ finished: if (outnum && (ferror(scnout) || fclose(scnout) == EOF)) DIEWRERR(); - return (state != FILEEOF ? SCNERR : encrypted ? SCNENC : SCNMSG); -} - -static int -mh_fputs(char *s, FILE *stream) -{ - char c; - - while ((c = *s++)) - if (putc(c,stream) == EOF ) - return(EOF); - return (0); + return (state != FILEEOF ? SCNERR : SCNMSG); }