X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=uip%2Fscansbr.c;h=232a41906e99d4524e68440a240ff0d50a44914c;hb=e69044f7624abe5cb2cb796d528c0cc5f29515f7;hp=b178e75955a5944a0d226366e0894ae625b9c0a2;hpb=81a21a9a97d8633f6d6231e31fdb6e328d0d3ff2;p=mmh diff --git a/uip/scansbr.c b/uip/scansbr.c index b178e75..232a419 100644 --- a/uip/scansbr.c +++ b/uip/scansbr.c @@ -2,8 +2,6 @@ /* * scansbr.c -- routines to help scan along... * - * $Id$ - * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. @@ -16,18 +14,6 @@ #include #include -#ifdef _FSTDIO -# define _ptr _p /* Gag */ -# define _cnt _w /* Wretch */ -#endif - -#ifdef SCO_5_STDIO -# define _ptr __ptr -# define _cnt __cnt -# define _base __base -# define _filbuf(fp) ((fp)->__cnt = 0, __filbuf(fp)) -#endif - #define MAXSCANL 256 /* longest possible scan line */ /* @@ -40,10 +26,6 @@ #define SBUFSIZ 512 static struct format *fmt; -#ifdef JLR -static struct format *fmt_top; -#endif /* JLR */ - static struct comp *datecomp; /* pntr to "date" comp */ static struct comp *bodycomp; /* pntr to "body" pseudo-comp * * (if referenced) */ @@ -65,28 +47,29 @@ 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 +#else +#define SCAN_CHARWIDTH 1 +#endif int scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, int unseen, char *folder, long size, int noisy) { int i, compnum, encrypted, state; - char *cp, *tmpbuf, **nxtbuf; - char *saved_c_text; + unsigned char *cp, *tmpbuf, *startbody; + char **nxtbuf; + char *saved_c_text = NULL; struct comp *cptr; struct comp **savecomp; - char *scnmsg; - FILE *scnout; + char *scnmsg = NULL; + FILE *scnout = NULL; char name[NAMESZ]; static int rlwidth, slwidth; - -#ifdef RPATHS - char returnpath[BUFSIZ]; - char deliverydate[BUFSIZ]; -#endif + static size_t scanl_size; /* first-time only initialization */ if (!scanl) { @@ -97,32 +80,60 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, width = MAXSCANL; } dat[3] = slwidth = width; - scanl = (char *) mh_xmalloc((size_t) (slwidth + 2) ); + /* Arbitrarily allocate 20 * slwidth to provide room for lots + of escape sequences. */ + scanl_size = SCAN_CHARWIDTH * (20 * slwidth + 2); + scanl = (char *) mh_xmalloc (scanl_size); if (outnum) umask(~m_gmprot()); /* Compile format string */ - ncomps = fmt_compile (nfs, &fmt) + 1; - -#ifdef JLR - fmt_top = fmt; -#endif /* JLR */ - FINDCOMP(bodycomp, "body"); - FINDCOMP(datecomp, "date"); - FINDCOMP(cptr, "folder"); + ncomps = fmt_compile (nfs, &fmt, 1) + 2; + + bodycomp = fmt_findcomp("body"); + datecomp = fmt_findcomp("date"); + cptr = fmt_findcomp("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; + cptr->c_text = getcpy(folder); + if (fmt_addcompentry("encrypted")) { ncomps++; } - FINDCOMP (cptr, "dtimenow"); + cptr = fmt_findcomp("dtimenow"); if (cptr) cptr->c_text = getcpy(dtimenow (0)); + + /* + * In other programs I got rid of this complicated buffer switching, + * but since scan reads lots of messages at once and this complicated + * memory management, I decided to keep it; otherwise there was + * the potential for a lot of malloc() and free()s, and I could + * see the malloc() pool really getting fragmented. Maybe it + * wouldn't be an issue in practice; perhaps this will get + * revisited someday. + * + * So, some notes for what's going on: + * + * nxtbuf is an array of pointers that contains malloc()'d buffers + * to hold our component text. used_buf is an array of struct comp + * pointers that holds pointers to component structures we found while + * processing a message. + * + * We read in the message with m_getfld(), using "tmpbuf" as our + * input buffer. tmpbuf is set at the start of message processing + * to the first buffer in our buffer pool (nxtbuf). + * + * Every time we find a component we care about, we set that component's + * text buffer to the current value of tmpbuf, and then switch tmpbuf + * to the next buffer in our pool. We also add that component to + * our used_buf pool. + * + * When we're done, we go back and zero out all of the component + * text buffer pointers that we saved in used_buf. + * + * Note that this means c_text memory is NOT owned by the fmt_module + * and it's our responsibility to free it. + */ + nxtbuf = compbuffers = (char **) calloc((size_t) ncomps, sizeof(char *)); if (nxtbuf == NULL) adios (NULL, "unable to allocate component buffers"); @@ -142,6 +153,7 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, nxtbuf = compbuffers; savecomp = used_buf; tmpbuf = *nxtbuf++; + startbody = NULL; dat[0] = innum ? innum : outnum; dat[1] = curflg; dat[4] = unseen; @@ -169,19 +181,6 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, } if ((scnout = fopen (scnmsg, "w")) == NULL) adios (scnmsg, "unable to write"); -#ifdef RPATHS - /* - * Add the Return-Path and Delivery-Date - * header fields to message. - */ - if (get_returnpath (returnpath, sizeof(returnpath), - deliverydate, sizeof(deliverydate))) { - FPUTS ("Return-Path: "); - FPUTS (returnpath); - FPUTS ("Delivery-Date: "); - FPUTS (deliverydate); - } -#endif /* RPATHS */ } /* scan - main loop */ @@ -201,23 +200,18 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, * buffer as the component temp buffer (buffer switching * saves an extra copy of the component text). */ - if ((cptr = wantcomp[CHASH(name)])) { - do { - if (!strcasecmp(name, cptr->c_name)) { - if (! cptr->c_text) { - cptr->c_text = tmpbuf; - for (cp = tmpbuf + strlen (tmpbuf) - 1; + if ((cptr = fmt_findcasecomp(name))) { + if (! cptr->c_text) { + cptr->c_text = tmpbuf; + for (cp = tmpbuf + strlen (tmpbuf) - 1; cp >= tmpbuf; cp--) - if (isspace (*cp)) - *cp = 0; - else - break; - *--savecomp = cptr; - tmpbuf = *nxtbuf++; - } - break; - } - } while ((cptr = cptr->c_next)); + if (isspace (*cp)) + *cp = 0; + else + break; + *--savecomp = cptr; + tmpbuf = *nxtbuf++; + } } while (state == FLDPLUS) { @@ -229,42 +223,49 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, case BODY: compnum = -1; + /* + * A slight hack ... if we have less than rlwidth characters + * in the buffer, call m_getfld again. + */ + + if ((i = strlen(tmpbuf)) < rlwidth) { + state = m_getfld (state, name, tmpbuf + i, + rlwidth - i, inb); + } + if (! outnum) { state = FILEEOF; /* stop now if scan cmd */ + if (bodycomp && startbody == NULL) + startbody = tmpbuf; 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. + * The previous code here used to call m_getfld() using + * pointers to the underlying output stdio buffers to + * avoid the extra copy. Tests by Markus Schnalke show + * no noticable performance loss on larger mailboxes + * if we incur an extra copy, and messing around with + * internal stdio buffers is becoming more and more + * unportable as times go on. So from now on just deal + * with the overhead of an extra copy. * - * 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". + * Subtle change - with the previous code tmpbuf wasn't + * used, so we could reuse it for the {body} component. + * Now since we're using tmpbuf as our read buffer we + * need to save the beginning of the body for later. + * See the above (and below) use of startbody. */ body:; + if (bodycomp && startbody == NULL) { + startbody = tmpbuf; + tmpbuf = *nxtbuf++; + } + while (state == BODY) { -#ifdef LINUX_STDIO - if (scnout->_IO_write_ptr == scnout->_IO_write_end) { -#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; -#else - state = m_getfld( state, name, scnout->_ptr, -(scnout->_cnt), inb ); - scnout->_cnt -= msg_count; - scnout->_ptr += msg_count; -#endif + state = m_getfld(state, name, tmpbuf, rlwidth, inb); + FPUTS(tmpbuf); } goto finished; @@ -305,7 +306,7 @@ finished: /* Save and restore buffer so we don't trash our dynamic pool! */ if (bodycomp) { saved_c_text = bodycomp->c_text; - bodycomp->c_text = tmpbuf; + bodycomp->c_text = startbody; } if (size) @@ -337,13 +338,7 @@ finished: } } - fmt_scan (fmt, scanl, slwidth, dat); - -#if 0 - fmt = fmt_scan (fmt, scanl, slwidth, dat); - if (!fmt) - fmt = fmt_top; /* reset for old format files */ -#endif + fmt_scan (fmt, scanl, scanl_size, slwidth, dat); if (bodycomp) bodycomp->c_text = saved_c_text; @@ -351,7 +346,7 @@ finished: if (noisy) fputs (scanl, stdout); - FINDCOMP (cptr, "encrypted"); + cptr = fmt_findcomp ("encrypted"); encrypted = cptr && cptr->c_text; /* return dynamically allocated buffers to pool */ @@ -368,19 +363,6 @@ finished: } -/* - * Cheat: we are loaded with adrparse, which wants a routine called - * OfficialName(). We call adrparse:getm() with the correct arguments - * to prevent OfficialName() from being called. Hence, the following - * is to keep the loader happy. - */ -char * -OfficialName (char *name) -{ - return name; -} - - static int mh_fputs(char *s, FILE *stream) {