Annotation of 43BSDReno/contrib/mh/sbr/m_getfld.c, revision 1.1.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.