Annotation of 43BSDReno/contrib/mh/sbr/m_getfld.c, revision 1.1

1.1     ! root        1: /* m_getfld.c - read/parse a message */
        !             2: 
        !             3: #include "../h/mh.h"
        !             4: #include <stdio.h>
        !             5: #include "../zotnet/mts.h"
        !             6: #include <ctype.h>
        !             7: 
        !             8: 
        !             9: /* This module has a long and checkered history.  First, it didn't burst
        !            10:    maildrops correctly because it considered two CTRL-A:s in a row to be
        !            11:    an inter-message delimiter.  It really is four CTRL-A:s followed by a
        !            12:    newline.  Unfortunately, MMDF will convert this delimiter *inside* a
        !            13:    message to a CTRL-B followed by three CTRL-A:s and a newline.  This
        !            14:    caused the old version of m_getfld() to declare eom prematurely.  The
        !            15:    fix was a lot slower than
        !            16: 
        !            17:                c == '\001' && peekc (iob) == '\001'
        !            18: 
        !            19:    but it worked, and to increase generality, UUCP style maildrops could
        !            20:    be parsed as well.  Unfortunately the speed issue finally caught up with
        !            21:    us since this routine is at the very heart of MH.
        !            22: 
        !            23:    To speed things up considerably, the routine Eom() was made an auxilary
        !            24:    function called by the macro eom().  Unless we are bursting a maildrop,
        !            25:    the eom() macro returns FALSE saying we aren't at the end of the
        !            26:    message.
        !            27: 
        !            28:    The next thing to do is to read the mtstailor file and initialize
        !            29:    delimiter[] and delimlen accordingly...
        !            30: 
        !            31:    After mhl was made a built-in in msh, m_getfld() worked just fine
        !            32:    (using m_unknown() at startup).  Until one day: a message which was
        !            33:    the result of a bursting was shown. Then, since the burst boundaries
        !            34:    aren't CTRL-A:s, m_getfld() would blinding plunge on past the boundary.
        !            35:    Very sad.  The solution: introduce m_eomsbr().  This hook gets called
        !            36:    after the end of each line (since testing for eom involves an fseek()).
        !            37:    This worked fine, until one day: a message with no body portion arrived.
        !            38:    Then the
        !            39: 
        !            40:                   while (eom (c = Getc (iob), iob))
        !            41:                        continue;
        !            42: 
        !            43:    loop caused m_getfld() to return FMTERR.  So, that logic was changed to
        !            44:    check for (*eom_action) and act accordingly.
        !            45: 
        !            46:    This worked fine, until one day: someone didn't use four CTRL:A's as
        !            47:    their delimiters.  So, the bullet got bit and we read mts.h and
        !            48:    continue to struggle on.  It's not that bad though, since the only time
        !            49:    the code gets executed is when inc (or msh) calls it, and both of these
        !            50:    have already called mts_init().
        !            51: 
        !            52:    ------------------------
        !            53:    (Written by Van Jacobson for the mh6 m_getfld, January, 1986):
        !            54: 
        !            55:    This routine was accounting for 60% of the cpu time used by most mh
        !            56:    programs.  I spent a bit of time tuning and it now accounts for <10%
        !            57:    of the time used.  Like any heavily tuned routine, it's a bit
        !            58:    complex and you want to be sure you understand everything that it's
        !            59:    doing before you start hacking on it.  Let me try to emphasize
        !            60:    that:  every line in this atrocity depends on every other line,
        !            61:    sometimes in subtle ways.  You should understand it all, in detail,
        !            62:    before trying to change any part.  If you do change it, test the
        !            63:    result thoroughly (I use a hand-constructed test file that exercises
        !            64:    all the ways a header name, header body, header continuation,
        !            65:    header-body separator, body line and body eom can align themselves
        !            66:    with respect to a buffer boundary).  "Minor" bugs in this routine
        !            67:    result in garbaged or lost mail.
        !            68: 
        !            69:    If you hack on this and slow it down, I, my children and my
        !            70:    children's children will curse you.
        !            71: 
        !            72:    This routine gets used on three different types of files: normal,
        !            73:    single msg files, "packed" unix or mmdf mailboxs (when used by inc)
        !            74:    and packed, directoried bulletin board files (when used by msh).
        !            75:    The biggest impact of different file types is in "eom" testing.  The
        !            76:    code has been carefully organized to test for eom at appropriate
        !            77:    times and at no other times (since the check is quite expensive).
        !            78:    I have tried to arrange things so that the eom check need only be
        !            79:    done on entry to this routine.  Since an eom can only occur after a
        !            80:    newline, this is easy to manage for header fields.  For the msg
        !            81:    body, we try to efficiently search the input buffer to see if
        !            82:    contains the eom delimiter.  If it does, we take up to the
        !            83:    delimiter, otherwise we take everything in the buffer.  (The change
        !            84:    to the body eom/copy processing produced the most noticeable
        !            85:    performance difference, particularly for "inc" and "show".)
        !            86: 
        !            87:    There are three qualitatively different things this routine busts
        !            88:    out of a message: field names, field text and msg bodies.  Field
        !            89:    names are typically short (~8 char) and the loop that extracts them
        !            90:    might terminate on a colon, newline or max width.  I considered
        !            91:    using a Vax "scanc" to locate the end of the field followed by a
        !            92:    "bcopy" but the routine call overhead on a Vax is too large for this
        !            93:    to work on short names.  If Berkeley ever makes "inline" part of the
        !            94:    C optimiser (so things like "scanc" turn into inline instructions) a
        !            95:    change here would be worthwhile.
        !            96: 
        !            97:    Field text is typically 60 - 100 characters so there's (barely)
        !            98:    a win in doing a routine call to something that does a "locc"
        !            99:    followed by a "bmove".  About 30% of the fields have continuations
        !           100:    (usually the 822 "received:" lines) and each continuation generates
        !           101:    another routine call.  "Inline" would be a big win here, as well.
        !           102: 
        !           103:    Messages, as of this writing, seem to come in two flavors: small
        !           104:    (~1K) and long (>2K).  Most messages have 400 - 600 bytes of headers
        !           105:    so message bodies average at least a few hundred characters.
        !           106:    Assuming your system uses reasonably sized stdio buffers (1K or
        !           107:    more), this routine should be able to remove the body in large
        !           108:    (>500 byte) chunks.  The makes the cost of a call to "bcopy"
        !           109:    small but there is a premium on checking for the eom in packed
        !           110:    maildrops.  The eom pattern is always a simple string so we can
        !           111:    construct an efficient pattern matcher for it (e.g., a Vax "matchc"
        !           112:    instruction).  Some thought went into recognizing the start of
        !           113:    an eom that has been split across two buffers.
        !           114: 
        !           115:    This routine wants to deal with large chunks of data so, rather
        !           116:    than "getc" into a local buffer, it uses stdio's buffer.  If
        !           117:    you try to use it on a non-buffered file, you'll get what you
        !           118:    deserve.  This routine "knows" that struct FILEs have a _ptr
        !           119:    and a _cnt to describe the current state of the buffer and
        !           120:    it knows that _filbuf ignores the _ptr & _cnt and simply fills
        !           121:    the buffer.  If stdio on your system doesn't work this way, you
        !           122:    may have to make small changes in this routine.
        !           123:    
        !           124:    This routine also "knows" that an EOF indication on a stream is
        !           125:    "sticky" (i.e., you will keep getting EOF until you reposition the
        !           126:    stream).  If your system doesn't work this way it is broken and you
        !           127:    should complain to the vendor.  As a consequence of the sticky
        !           128:    EOF, this routine will never return any kind of EOF status when
        !           129:    there is data in "name" or "buf").
        !           130:   */
        !           131: 
        !           132: 
        !           133: #define Getc(iob)      getc(iob)
        !           134: #define eom(c,iob)     (msg_style != MS_DEFAULT && \
        !           135:                         (((c) == *msg_delim && m_Eom(c,iob)) ||\
        !           136:                          (eom_action && (*eom_action)(c))))
        !           137: 
        !           138: static unsigned char *matchc();
        !           139: static unsigned char *locc();
        !           140: 
        !           141: static unsigned char **pat_map;
        !           142: 
        !           143: int    msg_count = 0;  /* disgusting hack for "inc" so it can
        !           144:                         * know how many characters were stuffed
        !           145:                         * in the buffer on the last call (see
        !           146:                         * comments in uip/scansbr.c) */
        !           147: 
        !           148: int    msg_style = MS_DEFAULT;
        !           149: /*
        !           150:  * The "full" delimiter string for a packed maildrop consists
        !           151:  * of a newline followed by the actual delimiter.  E.g., the
        !           152:  * full string for a Unix maildrop would be: "\n\nFrom ".
        !           153:  * "Fdelim" points to the start of the full string and is used
        !           154:  * in the BODY case of the main routine to search the buffer for
        !           155:  * a possible eom.  Msg_delim points to the first character of
        !           156:  * the actual delim. string (i.e., fdelim+1).  Edelim
        !           157:  * points to the 2nd character of actual delimiter string.  It
        !           158:  * is used in m_Eom because the first character of the string
        !           159:  * has been read and matched before m_Eom is called.
        !           160:  */
        !           161: char   *msg_delim = "";
        !           162: static unsigned char *fdelim;
        !           163: static unsigned char *delimend;
        !           164: static int  fdelimlen;
        !           165: static unsigned char *edelim;
        !           166: static int  edelimlen;
        !           167: 
        !           168: static int  (*eom_action) () = NULL;
        !           169: 
        !           170: /*  */
        !           171: 
        !           172: m_getfld(state, name, buf, bufsz, iob)
        !           173:        int state;
        !           174:        int bufsz;
        !           175:        unsigned char *name, *buf;
        !           176:        register FILE *iob;
        !           177: {
        !           178:     register unsigned char  *cp;
        !           179:     register unsigned char  *bp;
        !           180:     register int    cnt;
        !           181:     register int    c;
        !           182:     register int    i;
        !           183:     register int    j;
        !           184:     register unsigned char  *ep;
        !           185:     register unsigned char  *sp;
        !           186: 
        !           187:     if ((c = Getc(iob)) < 0) {
        !           188:        msg_count = 0;
        !           189:        *buf = 0;
        !           190:        return FILEEOF;
        !           191:     }
        !           192:     if (eom (c, iob)) {
        !           193:        if (! eom_action) {
        !           194:            /* flush null messages */
        !           195:            while ((c = Getc(iob)) >= 0 && eom (c, iob))
        !           196:                ;
        !           197:            if (c >= 0)
        !           198:                (void) ungetc(c, iob);
        !           199:        }
        !           200:        msg_count = 0;
        !           201:        *buf = 0;
        !           202:        return FILEEOF;
        !           203:     }
        !           204: 
        !           205:     switch (state) {
        !           206:        case FLDEOF: 
        !           207:        case BODYEOF: 
        !           208:        case FLD: 
        !           209:            if (c == '\n' || c == '-') {
        !           210:                /* we hit the header/body separator */
        !           211:                while (c != '\n' && (c = Getc(iob)) >= 0)
        !           212:                    ;
        !           213: 
        !           214:                if (c < 0 || (c = Getc(iob)) < 0 || eom (c, iob)) {
        !           215:                    if (! eom_action) {
        !           216:                        /* flush null messages */
        !           217:                        while ((c = Getc(iob)) >= 0 && eom (c, iob))
        !           218:                            ;
        !           219:                        if (c >= 0)
        !           220:                            (void) ungetc(c, iob);
        !           221:                    }
        !           222:                    msg_count = 0;
        !           223:                    *buf = 0;
        !           224:                    return FILEEOF;
        !           225:                }
        !           226:                state = BODY;
        !           227:                goto body;
        !           228:            }
        !           229:            /*
        !           230:             * get the name of this component.  take characters up
        !           231:             * to a ':', a newline or NAMESZ-1 characters, whichever
        !           232:             * comes first.  
        !           233:             */
        !           234:            cp = name; i = NAMESZ - 1;
        !           235:            for (;;) {
        !           236:                bp = sp = (unsigned char *) iob->_ptr - 1;
        !           237:                j = (cnt = iob->_cnt+1) < i ? cnt : i;
        !           238:                while ((c = *bp++) != ':' && c != '\n' && --j >= 0)
        !           239:                    *cp++ = c;
        !           240: 
        !           241:                j = bp - sp;
        !           242:                if ((cnt -= j) <= 0) {
        !           243:                    if (_filbuf(iob) == EOF) {
        !           244:                        *cp = *buf = NULL;
        !           245:                        advise (NULLCP, "eof encountered in field \"%s\"",
        !           246:                                name);
        !           247:                        return FMTERR;
        !           248:                    }
        !           249:                } else {
        !           250:                    iob->_ptr = (char *) bp + 1;
        !           251:                    iob->_cnt = cnt - 1;
        !           252:                }
        !           253:                if (c == ':')
        !           254:                    break;
        !           255: 
        !           256:                /*
        !           257:                 * something went wrong.  possibilities are:
        !           258:                 *  . hit a newline (error)
        !           259:                 *  . got more than namesz chars. (error)
        !           260:                 *  . hit the end of the buffer. (loop)
        !           261:                 */
        !           262:                if (c == '\n') {
        !           263:                    *cp = *buf = NULL;
        !           264:                    advise (NULLCP, "eol encountered in field \"%s\"", name);
        !           265:                    state = FMTERR;
        !           266:                    goto finish;
        !           267:                }
        !           268:                if ((i -= j) <= 0) {
        !           269:                    *cp = *buf = NULL;
        !           270:                    advise (NULLCP, "field name \"%s\" exceeds %d bytes",
        !           271:                            name, NAMESZ - 1);
        !           272:                    state = LENERR;
        !           273:                    goto finish;
        !           274:                }
        !           275:            }
        !           276: 
        !           277:            while (isspace (*--cp) && cp >= name)
        !           278:                ;
        !           279:            *++cp = NULL;
        !           280:            /* fall through */
        !           281: 
        !           282:        case FLDPLUS: 
        !           283:            /*
        !           284:             * get (more of) the text of a field.  take
        !           285:             * characters up to the end of this field (newline
        !           286:             * followed by non-blank) or bufsz-1 characters.
        !           287:             */
        !           288:            cp = buf; i = bufsz-1;
        !           289:            for (;;) {
        !           290:                cnt = iob->_cnt++; bp = (unsigned char *) --iob->_ptr;
        !           291:                c = cnt < i ? cnt : i;
        !           292:                while (ep = locc( c, bp, '\n' )) {
        !           293:                    /*
        !           294:                     * if we hit the end of this field, return.
        !           295:                     */
        !           296:                    if ((j = *++ep) != ' ' && j != '\t') {
        !           297:                        j = ep - (unsigned char *) iob->_ptr;
        !           298:                        (void) bcopy( iob->_ptr, cp, j);
        !           299:                        iob->_ptr = (char *) ep; iob->_cnt -= j;
        !           300:                        cp += j;
        !           301:                        state = FLD;
        !           302:                        goto finish;
        !           303:                    }
        !           304:                    c -= ep - bp; bp = ep;
        !           305:                }
        !           306:                /*
        !           307:                 * end of input or dest buffer - copy what we've found.
        !           308:                 */
        !           309:                c += bp - (unsigned char *) iob->_ptr;
        !           310:                (void) bcopy( iob->_ptr, cp, c);
        !           311:                i -= c; cp += c;
        !           312:                if (i <= 0) {
        !           313:                    /* the dest buffer is full */
        !           314:                    iob->_cnt -= c; iob->_ptr += c;
        !           315:                    state = FLDPLUS;
        !           316:                    break;
        !           317:                }
        !           318:                /* 
        !           319:                 * There's one character left in the input buffer.
        !           320:                 * Copy it & fill the buffer.  If the last char
        !           321:                 * was a newline and the next char is not whitespace,
        !           322:                 * this is the end of the field.  Otherwise loop.
        !           323:                 */
        !           324:                --i;
        !           325:                *cp++ = j = *(iob->_ptr + c);
        !           326:                c = _filbuf(iob);
        !           327:                if (j == '\n' && c != ' ' && c != '\t') {
        !           328:                    if (c != EOF)
        !           329:                        --iob->_ptr, ++iob->_cnt;
        !           330:                    state = FLD;
        !           331:                    break;
        !           332:                }
        !           333:            }
        !           334:            break;
        !           335: 
        !           336:        case BODY: 
        !           337:        body:
        !           338:            /*
        !           339:             * get the message body up to bufsz characters or the
        !           340:             * end of the message.  Sleazy hack: if bufsz is negative
        !           341:             * we assume that we were called to copy directly into
        !           342:             * the output buffer and we don't add an eos.
        !           343:             */
        !           344:            i = (bufsz < 0) ? -bufsz : bufsz-1;
        !           345:            bp = (unsigned char *) --iob->_ptr; cnt = ++iob->_cnt;
        !           346:            c = (cnt < i ? cnt : i);
        !           347:            if (msg_style != MS_DEFAULT && c > 1) {
        !           348:                /*
        !           349:                 * packed maildrop - only take up to the (possible)
        !           350:                 * start of the next message.  This "matchc" should
        !           351:                 * probably be a Boyer-Moore matcher for non-vaxen,
        !           352:                 * particularly since we have the alignment table
        !           353:                 * all built for the end-of-buffer test (next).
        !           354:                 * But our vax timings indicate that the "matchc"
        !           355:                 * instruction is 50% faster than a carefully coded
        !           356:                 * B.M. matcher for most strings.  (So much for elegant
        !           357:                 * algorithms vs. brute force.)  Since I (currently)
        !           358:                 * run MH on a vax, we use the matchc instruction. --vj
        !           359:                 */
        !           360:                if (ep = matchc( fdelimlen, fdelim, c, bp ) )
        !           361:                    c = ep - bp + 1;
        !           362:                else {
        !           363:                    /*
        !           364:                     * There's no delim in the buffer but there may be
        !           365:                     * a partial one at the end.  If so, we want to leave
        !           366:                     * it so the "eom" check on the next call picks it up.
        !           367:                     * Use a modified Boyer-Moore matcher to make this
        !           368:                     * check relatively cheap.  The first "if" figures
        !           369:                     * out what position in the pattern matches the last
        !           370:                     * character in the buffer.  The inner "while" matches
        !           371:                     * the pattern against the buffer, backwards starting
        !           372:                     * at that position.  Note that unless the buffer
        !           373:                     * ends with one of the characters in the pattern
        !           374:                     * (excluding the first and last), we do only one test.
        !           375:                     */
        !           376:                    ep = bp + c - 1;
        !           377:                    if (sp = pat_map[*ep]) {
        !           378:                        do {
        !           379:                            cp = sp;
        !           380:                            while (*--ep == *--cp)
        !           381:                                ;
        !           382:                            if (cp < fdelim) {
        !           383:                                if (ep >= bp)
        !           384:                                    /*
        !           385:                                     * ep < bp means that all the buffer
        !           386:                                     * contains is a prefix of delim.
        !           387:                                     * If this prefix is really a delim, the
        !           388:                                     * m_eom call at entry should have found
        !           389:                                     * it.  Thus it's not a delim and we can
        !           390:                                     * take all of it.
        !           391:                                     */
        !           392:                                    c = (ep - bp) + 2;
        !           393:                                break;
        !           394:                            }
        !           395:                            /* try matching one less char of delim string */
        !           396:                            ep = bp + c - 1;
        !           397:                        } while (--sp > fdelim);
        !           398:                    }
        !           399:                }
        !           400:            }
        !           401:            (void) bcopy( bp, buf, c );
        !           402:            iob->_cnt -= c;
        !           403:            iob->_ptr += c;
        !           404:            if (bufsz < 0) {
        !           405:                msg_count = c;
        !           406:                return (state);
        !           407:            }
        !           408:            cp = buf + c;
        !           409:            break;
        !           410: 
        !           411:        default: 
        !           412:            adios (NULLCP, "m_getfld() called with bogus state of %d", state);
        !           413:     }
        !           414: finish:;
        !           415:     *cp = NULL;
        !           416:     msg_count = cp - buf;
        !           417:     return (state);
        !           418: }
        !           419: 
        !           420: /*  */
        !           421: 
        !           422: #ifdef RPATHS
        !           423: static char  unixbuf[BUFSIZ] = "";
        !           424: #endif RPATHS
        !           425: 
        !           426: void
        !           427: m_unknown(iob)
        !           428:        register FILE *iob;
        !           429: {
        !           430:     register   int c;
        !           431:     register   long pos;
        !           432:     char       text[10];
        !           433:     register    char *cp;
        !           434:     register   char *delimstr;
        !           435: 
        !           436:     msg_style = MS_UNKNOWN;
        !           437: 
        !           438:     /* Figure out what the message delimitter string is for this
        !           439:      * maildrop.  (This used to be part of m_Eom but I didn't like
        !           440:      * the idea of an "if" statement that could only succeed on the
        !           441:      * first call to m_Eom getting executed on each call, i.e., at
        !           442:      * every newline in the message).
        !           443:      *
        !           444:      * If the first line of the maildrop is a Unix "from" line, we say the
        !           445:      * style is UUCP and eat the rest of the line.  Otherwise we say the style
        !           446:      * is MMDF & look for the delimiter string specified when MH was built
        !           447:      * (or from the mtstailor file).
        !           448:      */
        !           449:     pos = ftell (iob);
        !           450:     if (fread (text, sizeof *text, 5, iob) == 5
        !           451:            && strncmp (text, "From ", 5) == 0) {
        !           452:        msg_style = MS_UUCP;
        !           453:        delimstr = "\nFrom ";
        !           454: #ifndef        RPATHS
        !           455:        while ((c = getc (iob)) != '\n' && c >= 0)
        !           456:            ;
        !           457: #else  RPATHS
        !           458:        cp = unixbuf;
        !           459:        while ((c = getc (iob)) != '\n')
        !           460:            *cp++ = c;
        !           461:        *cp = NULL;
        !           462: #endif RPATHS
        !           463:     } else {
        !           464:        /* not a Unix style maildrop */
        !           465:        (void) fseek (iob, pos, 0);
        !           466:        if (mmdlm2 == NULLCP || *mmdlm2 == NULL)
        !           467:            mmdlm2 = "\001\001\001\001\n";
        !           468:        delimstr = mmdlm2;
        !           469:        msg_style = MS_MMDF;
        !           470:     }
        !           471:     c = strlen (delimstr);
        !           472:     fdelim = (unsigned char *)malloc((unsigned)c + 3);
        !           473:     *fdelim++ = '\0';
        !           474:     *fdelim = '\n';
        !           475:     msg_delim = (char *)fdelim+1;
        !           476:     edelim = (unsigned char *)msg_delim+1;
        !           477:     fdelimlen = c + 1;
        !           478:     edelimlen = c - 1;
        !           479:     (void)strcpy(msg_delim, delimstr);
        !           480:     delimend = (unsigned char *)msg_delim + edelimlen;
        !           481:     if (edelimlen <= 1)
        !           482:        adios (NULLCP, "maildrop delimiter must be at least 2 bytes");
        !           483:     /*
        !           484:      * build a Boyer-Moore end-position map for the matcher in m_getfld.
        !           485:      * N.B. - we don't match just the first char (since it's the newline
        !           486:      * separator) or the last char (since the matchc would have found it
        !           487:      * if it was a real delim).
        !           488:      */
        !           489:     pat_map = (unsigned char **) calloc (256, sizeof (unsigned char *));
        !           490: 
        !           491:     for (cp = (char *)fdelim + 1; cp < (char *)delimend; cp++ )
        !           492:        pat_map[*cp] = (unsigned char *)cp;
        !           493: 
        !           494:     if (msg_style == MS_MMDF) {
        !           495:        /* flush extra msg hdrs */
        !           496:        while ((c = Getc(iob)) >= 0 && eom (c, iob))
        !           497:            ;
        !           498:        if (c >= 0)
        !           499:            (void) ungetc(c, iob);
        !           500:     }
        !           501: }
        !           502: 
        !           503: void
        !           504: m_eomsbr(action)
        !           505:        int (*action)();
        !           506: {
        !           507:     if (eom_action = action) {
        !           508:        msg_style = MS_MSH;
        !           509:        *msg_delim = 0;
        !           510:        fdelimlen = 1;
        !           511:        delimend = fdelim;
        !           512:     } else {
        !           513:        msg_style = MS_MMDF;
        !           514:        msg_delim = (char *)fdelim + 1;
        !           515:        fdelimlen = strlen(fdelim);
        !           516:        delimend = (unsigned char *)(msg_delim + edelimlen);
        !           517:     }
        !           518: }
        !           519: 
        !           520: /*  */
        !           521: 
        !           522: /* test for msg delimiter string */
        !           523: 
        !           524: int
        !           525: m_Eom(c, iob)
        !           526:        register int c;
        !           527:        register FILE *iob;
        !           528: {
        !           529:     register long pos = 0L;
        !           530:     register int i;
        !           531:     char    text[10];
        !           532: #ifdef RPATHS
        !           533:     register    char *cp;
        !           534: #endif RPATHS
        !           535: 
        !           536:     pos = ftell (iob);
        !           537:     if ((i = fread (text, sizeof *text, edelimlen, iob)) != edelimlen
        !           538:            || strncmp (text, edelim, edelimlen)) {
        !           539:        if (i == 0 && msg_style == MS_UUCP)
        !           540:            /* the final newline in the (brain damaged) unix-format
        !           541:             * maildrop is part of the delimitter - delete it.
        !           542:             */
        !           543:            return 1;
        !           544: 
        !           545:        (void) fseek (iob, pos, 0);
        !           546:        return 0;
        !           547:     }
        !           548: 
        !           549:     if (msg_style == MS_UUCP) {
        !           550: #ifndef        RPATHS
        !           551:        while ((c = getc (iob)) != '\n')
        !           552:            if (c < 0)
        !           553:                break;
        !           554: #else  RPATHS
        !           555:        cp = unixbuf;
        !           556:        while ((c = getc (iob)) != '\n' && c >= 0)
        !           557:            *cp++ = c;
        !           558:        *cp = NULL;
        !           559: #endif RPATHS
        !           560:     }
        !           561: 
        !           562:     return 1;
        !           563: }
        !           564: 
        !           565: /*  */
        !           566: 
        !           567: #ifdef RPATHS
        !           568: char *
        !           569: unixline()
        !           570: {
        !           571:     register char  *cp,
        !           572:                    *dp,
        !           573:                    *pp;
        !           574:     static char unixfrom[BUFSIZ];
        !           575: 
        !           576:     pp = unixfrom;
        !           577:     if (cp = dp = index (unixbuf, ' ')) {
        !           578:        while (cp = index (cp + 1, 'r'))
        !           579:            if (strncmp (cp, "remote from ", 12) == 0) {
        !           580:                *cp = NULL;
        !           581:                (void) sprintf (pp, "%s!", cp + 12);
        !           582:                pp += strlen (pp);
        !           583:                break;
        !           584:            }
        !           585:        if (cp == NULL)
        !           586:            cp = unixbuf + strlen (unixbuf);
        !           587:        if ((cp -= 25) >= dp)
        !           588:            *cp = NULL;
        !           589:     }
        !           590: 
        !           591:     (void) sprintf (pp, "%s\n", unixbuf);
        !           592:     unixbuf[0] = NULL;
        !           593:     return unixfrom;
        !           594: }
        !           595: #endif RPATHS
        !           596: 
        !           597: /*  */
        !           598: 
        !           599: #if (vax && !lint)
        !           600:        asm(".align 1");
        !           601:        asm("_matchc: .word 0");
        !           602:        asm("   movq 4(ap),r0");
        !           603:        asm("   movq 12(ap),r2");
        !           604:        asm("   matchc  r0,(r1),r2,(r3)");
        !           605:        asm("   beql 1f");
        !           606:        asm("   movl 4(ap),r3");
        !           607:        asm("1: subl3  4(ap),r3,r0");
        !           608:        asm("   ret");
        !           609: #else
        !           610: static unsigned char *
        !           611: matchc( patln, pat, strln, str )
        !           612:        int patln;
        !           613:        char *pat;
        !           614:        int strln;
        !           615:        register char *str;
        !           616: {
        !           617:        register char *es = str + strln - patln;
        !           618:        register char *sp;
        !           619:        register char *pp;
        !           620:        register char *ep = pat + patln;
        !           621:        register char pc = *pat++;
        !           622: 
        !           623:        for(;;) {
        !           624:                while (pc != *str++)
        !           625:                        if (str > es)
        !           626:                                return 0;
        !           627: 
        !           628:                sp = str; pp = pat;
        !           629:                while (pp < ep && *sp++ == *pp++)
        !           630:                        ;
        !           631:                if (pp >= ep) 
        !           632:                        return ((unsigned char *)--str);
        !           633:        }
        !           634: }
        !           635: #endif
        !           636: 
        !           637: /*  */
        !           638: 
        !           639: /*
        !           640:  * Locate character "term" in the next "cnt" characters of "src".
        !           641:  * If found, return its address, otherwise return 0.
        !           642:  */
        !           643: #if (vax && !lint)
        !           644:        asm(".align 1");
        !           645:        asm("_locc: .word 0");
        !           646:        asm("   movq  4(ap),r0");
        !           647:        asm("   locc  12(ap),r0,(r1)");
        !           648:        asm("   beql  1f");
        !           649:        asm("   movl  r1,r0");
        !           650:        asm("1: ret");
        !           651: #else
        !           652: static unsigned char *
        !           653: locc( cnt, src, term )
        !           654:        register int  cnt;
        !           655:        register unsigned char *src;
        !           656:        register unsigned char term;
        !           657: {
        !           658:     while (*src++ != term && --cnt > 0);
        !           659: 
        !           660:     return (cnt > 0 ? --src : (unsigned char *)0);
        !           661: }
        !           662: #endif
        !           663: 
        !           664: /*  */
        !           665: 
        !           666: #if    !defined (BSD42) && !defined (bcopy)
        !           667: int
        !           668: bcmp(b1, b2, length)
        !           669:        register char *b1, *b2;
        !           670: register int   length;
        !           671: {
        !           672:     while (length-- > 0)
        !           673:        if (*b1++ != *b2++)
        !           674:            return 1;
        !           675: 
        !           676:     return 0;
        !           677: }
        !           678: 
        !           679: 
        !           680: bcopy(b1, b2, length)
        !           681:        register char *b1, *b2;
        !           682:        register int length;
        !           683: {
        !           684:     while (length-- > 0)
        !           685:        *b2++ = *b1++;
        !           686: }
        !           687: 
        !           688: 
        !           689: bzero(b, length)
        !           690:        register char *b;
        !           691:        register int length;
        !           692: {
        !           693:     while (length-- > 0)
        !           694:        *b++ = NULL;
        !           695: }
        !           696: #endif not BSD42 or SYS5

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.