Updated docs/README-ATTACHMENTS, mainly to reflect that no setup is
[mmh] / docs / historical / mh-6.8.5 / sbr / RCS / m_getfld.c,v
1 head    1.15;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.15
9 date    93.02.26.21.57.14;      author jromine; state Exp;
10 branches;
11 next    1.14;
12
13 1.14
14 date    92.10.31.07.44.56;      author jromine; state Exp;
15 branches;
16 next    1.13;
17
18 1.13
19 date    92.10.28.22.56.27;      author jromine; state Exp;
20 branches;
21 next    1.12;
22
23 1.12
24 date    92.05.12.21.49.37;      author jromine; state Exp;
25 branches;
26 next    1.11;
27
28 1.11
29 date    92.02.12.05.07.25;      author jromine; state Exp;
30 branches;
31 next    1.10;
32
33 1.10
34 date    92.01.31.21.54.32;      author jromine; state Exp;
35 branches;
36 next    1.9;
37
38 1.9
39 date    92.01.24.18.03.41;      author jromine; state Exp;
40 branches;
41 next    1.8;
42
43 1.8
44 date    90.04.18.13.48.12;      author sources; state Exp;
45 branches;
46 next    1.7;
47
48 1.7
49 date    90.04.05.15.31.37;      author sources; state Exp;
50 branches;
51 next    1.6;
52
53 1.6
54 date    90.04.05.14.46.02;      author sources; state Exp;
55 branches;
56 next    1.5;
57
58 1.5
59 date    90.04.02.14.39.47;      author sources; state Exp;
60 branches;
61 next    1.4;
62
63 1.4
64 date    90.03.12.10.12.38;      author sources; state Exp;
65 branches;
66 next    1.3;
67
68 1.3
69 date    90.02.08.16.11.03;      author sources; state Exp;
70 branches;
71 next    1.2;
72
73 1.2
74 date    90.02.05.15.06.23;      author sources; state Exp;
75 branches;
76 next    1.1;
77
78 1.1
79 date    90.02.05.15.05.52;      author sources; state Exp;
80 branches;
81 next    ;
82
83
84 desc
85 @@
86
87
88 1.15
89 log
90 @386BSD/BSD44
91 @
92 text
93 @/* m_getfld.c - read/parse a message */
94 #ifndef lint
95 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.14 1992/10/31 07:44:56 jromine Exp jromine $";
96 #endif /* lint */
97
98 #include "../h/mh.h"
99 #include <stdio.h>
100 #include "../zotnet/mts.h"
101 #include <ctype.h>
102
103
104 /* This module has a long and checkered history.  First, it didn't burst
105    maildrops correctly because it considered two CTRL-A:s in a row to be
106    an inter-message delimiter.  It really is four CTRL-A:s followed by a
107    newline.  Unfortunately, MMDF will convert this delimiter *inside* a
108    message to a CTRL-B followed by three CTRL-A:s and a newline.  This
109    caused the old version of m_getfld() to declare eom prematurely.  The
110    fix was a lot slower than
111
112                 c == '\001' && peekc (iob) == '\001'
113
114    but it worked, and to increase generality, UUCP style maildrops could
115    be parsed as well.  Unfortunately the speed issue finally caught up with
116    us since this routine is at the very heart of MH.
117
118    To speed things up considerably, the routine Eom() was made an auxilary
119    function called by the macro eom().  Unless we are bursting a maildrop,
120    the eom() macro returns FALSE saying we aren't at the end of the
121    message.
122
123    The next thing to do is to read the mtstailor file and initialize
124    delimiter[] and delimlen accordingly...
125
126    After mhl was made a built-in in msh, m_getfld() worked just fine
127    (using m_unknown() at startup).  Until one day: a message which was
128    the result of a bursting was shown. Then, since the burst boundaries
129    aren't CTRL-A:s, m_getfld() would blinding plunge on past the boundary.
130    Very sad.  The solution: introduce m_eomsbr().  This hook gets called
131    after the end of each line (since testing for eom involves an fseek()).
132    This worked fine, until one day: a message with no body portion arrived.
133    Then the
134
135                    while (eom (c = Getc (iob), iob))
136                         continue;
137
138    loop caused m_getfld() to return FMTERR.  So, that logic was changed to
139    check for (*eom_action) and act accordingly.
140
141    This worked fine, until one day: someone didn't use four CTRL:A's as
142    their delimiters.  So, the bullet got bit and we read mts.h and
143    continue to struggle on.  It's not that bad though, since the only time
144    the code gets executed is when inc (or msh) calls it, and both of these
145    have already called mts_init().
146
147    ------------------------
148    (Written by Van Jacobson for the mh6 m_getfld, January, 1986):
149
150    This routine was accounting for 60% of the cpu time used by most mh
151    programs.  I spent a bit of time tuning and it now accounts for <10%
152    of the time used.  Like any heavily tuned routine, it's a bit
153    complex and you want to be sure you understand everything that it's
154    doing before you start hacking on it.  Let me try to emphasize
155    that:  every line in this atrocity depends on every other line,
156    sometimes in subtle ways.  You should understand it all, in detail,
157    before trying to change any part.  If you do change it, test the
158    result thoroughly (I use a hand-constructed test file that exercises
159    all the ways a header name, header body, header continuation,
160    header-body separator, body line and body eom can align themselves
161    with respect to a buffer boundary).  "Minor" bugs in this routine
162    result in garbaged or lost mail.
163
164    If you hack on this and slow it down, I, my children and my
165    children's children will curse you.
166
167    This routine gets used on three different types of files: normal,
168    single msg files, "packed" unix or mmdf mailboxs (when used by inc)
169    and packed, directoried bulletin board files (when used by msh).
170    The biggest impact of different file types is in "eom" testing.  The
171    code has been carefully organized to test for eom at appropriate
172    times and at no other times (since the check is quite expensive).
173    I have tried to arrange things so that the eom check need only be
174    done on entry to this routine.  Since an eom can only occur after a
175    newline, this is easy to manage for header fields.  For the msg
176    body, we try to efficiently search the input buffer to see if
177    contains the eom delimiter.  If it does, we take up to the
178    delimiter, otherwise we take everything in the buffer.  (The change
179    to the body eom/copy processing produced the most noticeable
180    performance difference, particularly for "inc" and "show".)
181
182    There are three qualitatively different things this routine busts
183    out of a message: field names, field text and msg bodies.  Field
184    names are typically short (~8 char) and the loop that extracts them
185    might terminate on a colon, newline or max width.  I considered
186    using a Vax "scanc" to locate the end of the field followed by a
187    "bcopy" but the routine call overhead on a Vax is too large for this
188    to work on short names.  If Berkeley ever makes "inline" part of the
189    C optimiser (so things like "scanc" turn into inline instructions) a
190    change here would be worthwhile.
191
192    Field text is typically 60 - 100 characters so there's (barely)
193    a win in doing a routine call to something that does a "locc"
194    followed by a "bmove".  About 30% of the fields have continuations
195    (usually the 822 "received:" lines) and each continuation generates
196    another routine call.  "Inline" would be a big win here, as well.
197
198    Messages, as of this writing, seem to come in two flavors: small
199    (~1K) and long (>2K).  Most messages have 400 - 600 bytes of headers
200    so message bodies average at least a few hundred characters.
201    Assuming your system uses reasonably sized stdio buffers (1K or
202    more), this routine should be able to remove the body in large
203    (>500 byte) chunks.  The makes the cost of a call to "bcopy"
204    small but there is a premium on checking for the eom in packed
205    maildrops.  The eom pattern is always a simple string so we can
206    construct an efficient pattern matcher for it (e.g., a Vax "matchc"
207    instruction).  Some thought went into recognizing the start of
208    an eom that has been split across two buffers.
209
210    This routine wants to deal with large chunks of data so, rather
211    than "getc" into a local buffer, it uses stdio's buffer.  If
212    you try to use it on a non-buffered file, you'll get what you
213    deserve.  This routine "knows" that struct FILEs have a _ptr
214    and a _cnt to describe the current state of the buffer and
215    it knows that _filbuf ignores the _ptr & _cnt and simply fills
216    the buffer.  If stdio on your system doesn't work this way, you
217    may have to make small changes in this routine.
218    
219    This routine also "knows" that an EOF indication on a stream is
220    "sticky" (i.e., you will keep getting EOF until you reposition the
221    stream).  If your system doesn't work this way it is broken and you
222    should complain to the vendor.  As a consequence of the sticky
223    EOF, this routine will never return any kind of EOF status when
224    there is data in "name" or "buf").
225   */
226
227
228 #define Getc(iob)       getc(iob)
229 #define eom(c,iob)      (msg_style != MS_DEFAULT && \
230                          (((c) == *msg_delim && m_Eom(c,iob)) ||\
231                           (eom_action && (*eom_action)(c))))
232
233 static unsigned char *matchc();
234 static unsigned char *locc();
235
236 static unsigned char **pat_map;
237
238 extern int msg_count;   /* defined in sbr/m_msgdef.c = 0
239                          * disgusting hack for "inc" so it can 
240                          * know how many characters were stuffed
241                          * in the buffer on the last call (see
242                          * comments in uip/scansbr.c) */
243
244 extern int msg_style;   /* defined in sbr/m_msgdef.c = MS_DEFAULT */
245 /*
246  * The "full" delimiter string for a packed maildrop consists
247  * of a newline followed by the actual delimiter.  E.g., the
248  * full string for a Unix maildrop would be: "\n\nFrom ".
249  * "Fdelim" points to the start of the full string and is used
250  * in the BODY case of the main routine to search the buffer for
251  * a possible eom.  Msg_delim points to the first character of
252  * the actual delim. string (i.e., fdelim+1).  Edelim
253  * points to the 2nd character of actual delimiter string.  It
254  * is used in m_Eom because the first character of the string
255  * has been read and matched before m_Eom is called.
256  */
257 extern char *msg_delim; /*  defined in sbr/m_msgdef.c = "" */
258 static unsigned char *fdelim;
259 static unsigned char *delimend;
260 static int  fdelimlen;
261 static unsigned char *edelim;
262 static int  edelimlen;
263
264 static int  (*eom_action) () = NULL;
265
266 #ifdef _FSTDIO
267 #define _ptr    _p              /* Gag */
268 #define _cnt    _r              /* Retch */
269 #define _filbuf __srget         /* Puke */
270 #endif
271
272 /* \f */
273
274 m_getfld (state, name, buf, bufsz, iob)
275 int             state;
276 int             bufsz;
277 unsigned char   *name,
278                 *buf;
279 register FILE   *iob;
280 {
281     register unsigned char  *cp;
282     register unsigned char  *bp;
283     register unsigned char  *ep;
284     register unsigned char  *sp;
285     register int    cnt;
286     register int    c;
287     register int    i;
288     register int    j;
289
290     if ((c = Getc(iob)) < 0) {
291         msg_count = 0;
292         *buf = 0;
293         return FILEEOF;
294     }
295     if (eom (c, iob)) {
296         if (! eom_action) {
297             /* flush null messages */
298             while ((c = Getc(iob)) >= 0 && eom (c, iob))
299                 ;
300             if (c >= 0)
301                 (void) ungetc(c, iob);
302         }
303         msg_count = 0;
304         *buf = 0;
305         return FILEEOF;
306     }
307
308     switch (state) {
309         case FLDEOF: 
310         case BODYEOF: 
311         case FLD: 
312             if (c == '\n' || c == '-') {
313                 /* we hit the header/body separator */
314                 while (c != '\n' && (c = Getc(iob)) >= 0)
315                     ;
316
317                 if (c < 0 || (c = Getc(iob)) < 0 || eom (c, iob)) {
318                     if (! eom_action) {
319                         /* flush null messages */
320                         while ((c = Getc(iob)) >= 0 && eom (c, iob))
321                             ;
322                         if (c >= 0)
323                             (void) ungetc(c, iob);
324                     }
325                     msg_count = 0;
326                     *buf = 0;
327                     return FILEEOF;
328                 }
329                 state = BODY;
330                 goto body;
331             }
332             /*
333              * get the name of this component.  take characters up
334              * to a ':', a newline or NAMESZ-1 characters, whichever
335              * comes first.  
336              */
337             cp = name; i = NAMESZ - 1;
338             for (;;) {
339                 bp = sp = (unsigned char *) iob->_ptr - 1;
340                 j = (cnt = iob->_cnt+1) < i ? cnt : i;
341                 while ((c = *bp++) != ':' && c != '\n' && --j >= 0)
342                     *cp++ = c;
343
344                 j = bp - sp;
345                 if ((cnt -= j) <= 0) {
346                     if (_filbuf(iob) == EOF) {
347                         *cp = *buf = 0;
348                         advise (NULLCP, "eof encountered in field \"%s\"",
349                                 name);
350                         return FMTERR;
351                     }
352                 } else {
353                     iob->_ptr = bp + 1;
354                     iob->_cnt = cnt - 1;
355                 }
356                 if (c == ':')
357                     break;
358
359                 /*
360                  * something went wrong.  possibilities are:
361                  *  . hit a newline (error)
362                  *  . got more than namesz chars. (error)
363                  *  . hit the end of the buffer. (loop)
364                  */
365                 if (c == '\n') {
366                     *cp = *buf = 0;
367                     advise (NULLCP, "eol encountered in field \"%s\"", name);
368                     state = FMTERR;
369                     goto finish;
370                 }
371                 if ((i -= j) <= 0) {
372                     *cp = *buf = 0;
373                     advise (NULLCP, "field name \"%s\" exceeds %d bytes",
374                             name, NAMESZ - 1);
375                     state = LENERR;
376                     goto finish;
377                 }
378             }
379
380             while (isspace (*--cp) && cp >= name)
381                 ;
382             *++cp = 0;
383             /* fall through */
384
385         case FLDPLUS: 
386             /*
387              * get (more of) the text of a field.  take
388              * characters up to the end of this field (newline
389              * followed by non-blank) or bufsz-1 characters.
390              */
391             cp = buf; i = bufsz-1;
392             for (;;) {
393                 cnt = iob->_cnt++; bp = (unsigned char *) --iob->_ptr;
394                 c = cnt < i ? cnt : i;
395                 while (ep = locc( c, bp, '\n' )) {
396                     /*
397                      * if we hit the end of this field, return.
398                      */
399                     if ((j = *++ep) != ' ' && j != '\t') {
400                         j = ep - (unsigned char *) iob->_ptr;
401                         (void) bcopy( iob->_ptr, cp, j);
402                         iob->_ptr = ep; iob->_cnt -= j;
403                         cp += j;
404                         state = FLD;
405                         goto finish;
406                     }
407                     c -= ep - bp; bp = ep;
408                 }
409                 /*
410                  * end of input or dest buffer - copy what we've found.
411                  */
412                 c += bp - (unsigned char *) iob->_ptr;
413                 (void) bcopy( iob->_ptr, cp, c);
414                 i -= c; cp += c;
415                 if (i <= 0) {
416                     /* the dest buffer is full */
417                     iob->_cnt -= c; iob->_ptr += c;
418                     state = FLDPLUS;
419                     break;
420                 }
421                 /* 
422                  * There's one character left in the input buffer.
423                  * Copy it & fill the buffer.  If the last char
424                  * was a newline and the next char is not whitespace,
425                  * this is the end of the field.  Otherwise loop.
426                  */
427                 --i;
428                 *cp++ = j = *(iob->_ptr + c);
429                 c = _filbuf(iob);
430                 if ((j == '\0' || j == '\n') && c != ' ' && c != '\t') {
431                     if (c != EOF)
432                         --iob->_ptr, ++iob->_cnt;
433                     state = FLD;
434                     break;
435                 }
436             }
437             break;
438
439         case BODY: 
440         body:
441             /*
442              * get the message body up to bufsz characters or the
443              * end of the message.  Sleazy hack: if bufsz is negative
444              * we assume that we were called to copy directly into
445              * the output buffer and we don't add an eos.
446              */
447             i = (bufsz < 0) ? -bufsz : bufsz-1;
448             bp = (unsigned char *) --iob->_ptr; cnt = ++iob->_cnt;
449             c = (cnt < i ? cnt : i);
450             if (msg_style != MS_DEFAULT && c > 1) {
451                 /*
452                  * packed maildrop - only take up to the (possible)
453                  * start of the next message.  This "matchc" should
454                  * probably be a Boyer-Moore matcher for non-vaxen,
455                  * particularly since we have the alignment table
456                  * all built for the end-of-buffer test (next).
457                  * But our vax timings indicate that the "matchc"
458                  * instruction is 50% faster than a carefully coded
459                  * B.M. matcher for most strings.  (So much for elegant
460                  * algorithms vs. brute force.)  Since I (currently)
461                  * run MH on a vax, we use the matchc instruction. --vj
462                  */
463                 if (ep = matchc( fdelimlen, fdelim, c, bp ) )
464                     c = ep - bp + 1;
465                 else {
466                     /*
467                      * There's no delim in the buffer but there may be
468                      * a partial one at the end.  If so, we want to leave
469                      * it so the "eom" check on the next call picks it up.
470                      * Use a modified Boyer-Moore matcher to make this
471                      * check relatively cheap.  The first "if" figures
472                      * out what position in the pattern matches the last
473                      * character in the buffer.  The inner "while" matches
474                      * the pattern against the buffer, backwards starting
475                      * at that position.  Note that unless the buffer
476                      * ends with one of the characters in the pattern
477                      * (excluding the first and last), we do only one test.
478                      */
479                     ep = bp + c - 1;
480                     if (sp = pat_map[*ep]) {
481                         do {
482                             cp = sp;
483                             while (*--ep == *--cp)
484                             ;
485                             if (cp < fdelim) {
486                                 if (ep >= bp)
487                                     /*
488                                      * ep < bp means that all the buffer
489                                      * contains is a prefix of delim.
490                                      * If this prefix is really a delim, the
491                                      * m_eom call at entry should have found
492                                      * it.  Thus it's not a delim and we can
493                                      * take all of it.
494                                      */
495                                     c = (ep - bp) + 2;
496                             break;
497                         }
498                             /* try matching one less char of delim string */
499                             ep = bp + c - 1;
500                         } while (--sp > fdelim);
501                     }
502                 }
503             }
504             (void) bcopy( bp, buf, c );
505             iob->_cnt -= c;
506             iob->_ptr += c;
507             if (bufsz < 0) {
508                 msg_count = c;
509                 return (state);
510             }
511             cp = buf + c;
512             break;
513
514         default: 
515             adios (NULLCP, "m_getfld() called with bogus state of %d", state);
516     }
517 finish:;
518     *cp = 0;
519     msg_count = cp - buf;
520     return (state);
521 }
522
523 /* \f */
524
525 #ifdef  RPATHS
526 static char  unixbuf[BUFSIZ] = "";
527 #endif /* RPATHS */
528
529 void
530 m_unknown(iob)
531         register FILE *iob;
532 {
533     register    int c;
534     register    long pos;
535     char        text[10];
536     register    char *cp;
537     register    char *delimstr;
538
539     msg_style = MS_UNKNOWN;
540
541     /* Figure out what the message delimitter string is for this
542      * maildrop.  (This used to be part of m_Eom but I didn't like
543      * the idea of an "if" statement that could only succeed on the
544      * first call to m_Eom getting executed on each call, i.e., at
545      * every newline in the message).
546      *
547      * If the first line of the maildrop is a Unix "from" line, we say the
548      * style is UUCP and eat the rest of the line.  Otherwise we say the style
549      * is MMDF & look for the delimiter string specified when MH was built
550      * (or from the mtstailor file).
551      */
552     pos = ftell (iob);
553     if (fread (text, sizeof *text, 5, iob) == 5
554             && strncmp (text, "From ", 5) == 0) {
555         msg_style = MS_UUCP;
556         delimstr = "\nFrom ";
557 #ifndef RPATHS
558         while ((c = getc (iob)) != '\n' && c >= 0)
559             ;
560 #else /* RPATHS */
561         cp = unixbuf;
562         while ((c = getc (iob)) != '\n')
563             *cp++ = c;
564         *cp = 0;
565 #endif /* RPATHS */
566     } else {
567         /* not a Unix style maildrop */
568         (void) fseek (iob, pos, 0);
569         if (mmdlm2 == NULLCP || *mmdlm2 == 0)
570             mmdlm2 = "\001\001\001\001\n";
571         delimstr = mmdlm2;
572         msg_style = MS_MMDF;
573     }
574     c = strlen (delimstr);
575     fdelim = (unsigned char *)malloc((unsigned)c + 3);
576     *fdelim++ = '\0';
577     *fdelim = '\n';
578     msg_delim = (char *)fdelim+1;
579     edelim = (unsigned char *)msg_delim+1;
580     fdelimlen = c + 1;
581     edelimlen = c - 1;
582     (void)strcpy(msg_delim, delimstr);
583     delimend = (unsigned char *)msg_delim + edelimlen;
584     if (edelimlen <= 1)
585         adios (NULLCP, "maildrop delimiter must be at least 2 bytes");
586     /*
587      * build a Boyer-Moore end-position map for the matcher in m_getfld.
588      * N.B. - we don't match just the first char (since it's the newline
589      * separator) or the last char (since the matchc would have found it
590      * if it was a real delim).
591      */
592     pat_map = (unsigned char **) calloc (256, sizeof (unsigned char *));
593
594     for (cp = (char *)fdelim + 1; cp < (char *)delimend; cp++ )
595         pat_map[*cp] = (unsigned char *)cp;
596
597     if (msg_style == MS_MMDF) {
598         /* flush extra msg hdrs */
599         while ((c = Getc(iob)) >= 0 && eom (c, iob))
600             ;
601         if (c >= 0)
602             (void) ungetc(c, iob);
603     }
604 }
605
606
607 void m_eomsbr (action)
608 int     (*action) ();
609 {
610     if (eom_action = action) {
611         msg_style = MS_MSH;
612         *msg_delim = 0;
613         fdelimlen = 1;
614         delimend = fdelim;
615     } else {
616         msg_style = MS_MMDF;
617         msg_delim = (char *)fdelim + 1;
618         fdelimlen = strlen((char *)fdelim);
619         delimend = (unsigned char *)(msg_delim + edelimlen);
620     }
621 }
622
623 /* \f */
624
625 /* test for msg delimiter string */
626
627 int  m_Eom (c, iob)
628 register int     c;
629 register FILE   *iob;
630 {
631     register long pos = 0L;
632     register int i;
633     char    text[10];
634 #ifdef  RPATHS
635     register    char *cp;
636 #endif /* RPATHS */
637
638     pos = ftell (iob);
639     if ((i = fread (text, sizeof *text, edelimlen, iob)) != edelimlen
640             || strncmp (text, (char *)edelim, edelimlen)) {
641         if (i == 0 && msg_style == MS_UUCP)
642             /* the final newline in the (brain damaged) unix-format
643              * maildrop is part of the delimitter - delete it.
644              */
645             return 1;
646
647 #ifdef  notdef
648         (void) fseek (iob, pos, 0);
649 #else
650         (void) fseek (iob, (long)(pos-1), 0);
651         (void) getc (iob);              /* should be OK */
652 #endif /* !notdef */
653         return 0;
654     }
655
656     if (msg_style == MS_UUCP) {
657 #ifndef RPATHS
658         while ((c = getc (iob)) != '\n')
659             if (c < 0)
660                 break;
661 #else /* RPATHS */
662         cp = unixbuf;
663         while ((c = getc (iob)) != '\n' && c >= 0)
664             *cp++ = c;
665         *cp = 0;
666 #endif /* RPATHS */
667     }
668
669     return 1;
670 }
671
672 /* \f */
673
674 #ifdef  RPATHS
675 char   *unixline () {
676     register char  *cp,
677                    *dp,
678                    *pp;
679     static char unixfrom[BUFSIZ];
680
681     pp = unixfrom;
682     if (cp = dp = index (unixbuf, ' ')) {
683         while (cp = index (cp + 1, 'r'))
684             if (strncmp (cp, "remote from ", 12) == 0) {
685                 *cp = 0;
686                 (void) sprintf (pp, "%s!", cp + 12);
687                 pp += strlen (pp);
688                 break;
689             }
690         if (cp == NULL)
691             cp = unixbuf + strlen (unixbuf);
692         if ((cp -= 25) >= dp)
693             *cp = 0;
694     }
695
696     (void) sprintf (pp, "%s\n", unixbuf);
697     unixbuf[0] = 0;
698     return unixfrom;
699 }
700 #endif /* RPATHS */
701
702 /* \f */
703
704 #if (vax && !lint)
705         asm(".align 1");
706         asm("_matchc: .word 0");
707         asm("   movq 4(ap),r0");
708         asm("   movq 12(ap),r2");
709         asm("   matchc  r0,(r1),r2,(r3)");
710         asm("   beql 1f");
711         asm("   movl 4(ap),r3");
712         asm("1: subl3  4(ap),r3,r0");
713         asm("   ret");
714 #else
715 static unsigned char *
716 matchc( patln, pat, strln, str )
717         int patln;
718         char *pat;
719         int strln;
720         register char *str;
721 {
722         register char *es = str + strln - patln;
723         register char *sp;
724         register char *pp;
725         register char *ep = pat + patln;
726         register char pc = *pat++;
727
728         for(;;) {
729                 while (pc != *str++)
730                         if (str > es)
731                                 return 0;
732
733                 sp = str; pp = pat;
734                 while (pp < ep && *sp++ == *pp)
735                         pp++;
736                 if (pp >= ep) 
737                         return ((unsigned char *)--str);
738         }
739 }
740 #endif
741
742 /* \f */
743
744 /*
745  * Locate character "term" in the next "cnt" characters of "src".
746  * If found, return its address, otherwise return 0.
747  */
748 #if (vax && !lint)
749         asm(".align 1");
750         asm("_locc: .word 0");
751         asm("   movq  4(ap),r0");
752         asm("   locc  12(ap),r0,(r1)");
753         asm("   beql  1f");
754         asm("   movl  r1,r0");
755         asm("1: ret");
756 #else
757 static unsigned char *
758 locc( cnt, src, term )
759         register int  cnt;
760         register unsigned char *src;
761         register unsigned char term;
762 {
763     while (*src++ != term && --cnt > 0);
764
765     return (cnt > 0 ? --src : (unsigned char *)0);
766 }
767 #endif
768
769 /* \f */
770
771 #if     !defined (BSD42) && !defined (bcopy)
772 int     bcmp (b1, b2, length)
773 register char *b1,
774               *b2;
775 register int   length;
776 {
777     while (length-- > 0)
778         if (*b1++ != *b2++)
779             return 1;
780
781     return 0;
782 }
783
784
785 bcopy (b1, b2, length)
786 register char *b1,
787               *b2;
788 register int   length;
789 {
790     while (length-- > 0)
791         *b2++ = *b1++;
792 }
793
794
795 bzero (b, length)
796 register char *b;
797 register int   length;
798 {
799     while (length-- > 0)
800         *b++ = 0;
801 }
802 #endif /* not BSD42 */
803 @
804
805
806 1.14
807 log
808 @fix NULL inc bug
809 @
810 text
811 @d3 1
812 a3 1
813 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.13 1992/10/28 22:56:27 jromine Exp jromine $";
814 d173 6
815 @
816
817
818 1.13
819 log
820 @possible fix for no-newline in .mh_profile problem.
821 @
822 text
823 @d3 1
824 a3 1
825 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.12 1992/05/12 21:49:37 jromine Exp jromine $";
826 d549 1
827 a549 1
828 #ifndef safe
829 d554 1
830 a554 1
831 #endif /* !safe */
832 @
833
834
835 1.12
836 log
837 @fix ifdefs
838 @
839 text
840 @d3 1
841 a3 1
842 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.11 1992/02/12 05:07:25 jromine Exp jromine $";
843 d332 1
844 a332 1
845                 if (j == '\n' && c != ' ' && c != '\t') {
846 @
847
848
849 1.11
850 log
851 @second try at fseek() fix
852 @
853 text
854 @d3 2
855 a4 2
856 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.10 1992/01/31 21:54:32 jromine Exp jromine $";
857 #endif  lint
858 d429 1
859 a429 1
860 #endif  RPATHS
861 d462 1
862 a462 1
863 #else   RPATHS
864 d467 1
865 a467 1
866 #endif  RPATHS
867 d520 1
868 a520 1
869         fdelimlen = strlen(fdelim);
870 d538 1
871 a538 1
872 #endif  RPATHS
873 d542 1
874 a542 1
875             || strncmp (text, edelim, edelimlen)) {
876 d563 1
877 a563 1
878 #else   RPATHS
879 d568 1
880 a568 1
881 #endif  RPATHS
882 d602 1
883 a602 1
884 #endif  RPATHS
885 d704 1
886 a704 1
887 #endif  not BSD42
888 @
889
890
891 1.10
892 log
893 @kerberos
894 @
895 text
896 @d3 1
897 a3 1
898 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.9 1992/01/24 18:03:41 jromine Exp jromine $";
899 d549 3
900 a551 1
901 #ifdef notdef
902 d553 2
903 a554 5
904         if (iob->_cnt <= 0)
905             _filbuf(iob);
906 #else
907         (void) fseek (iob, pos, 0);
908 #endif /* !notdef */
909 @
910
911
912 1.9
913 log
914 @move msg_count, msg_style & msg_delim to m_msgdef.c for
915 shared libraries
916 @
917 text
918 @d3 1
919 a3 1
920 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.8 1990/04/18 13:48:12 sources Exp jromine $";
921 d249 1
922 a249 1
923                         *cp = *buf = NULL;
924 d268 1
925 a268 1
926                     *cp = *buf = NULL;
927 d274 1
928 a274 1
929                     *cp = *buf = NULL;
930 d284 1
931 a284 1
932             *++cp = NULL;
933 d420 1
934 a420 1
935     *cp = NULL;
936 d466 1
937 a466 1
938         *cp = NULL;
939 d471 1
940 a471 1
941         if (mmdlm2 == NULLCP || *mmdlm2 == NULL)
942 d568 1
943 a568 1
944         *cp = NULL;
945 d588 1
946 a588 1
947                 *cp = NULL;
948 d596 1
949 a596 1
950             *cp = NULL;
951 d600 1
952 a600 1
953     unixbuf[0] = NULL;
954 d703 1
955 a703 1
956         *b++ = NULL;
957 @
958
959
960 1.8
961 log
962 @back out RAND fix -- under #ifdef notdef
963 @
964 text
965 @d3 1
966 a3 1
967 static char ident[] = "@@(#)$Id: m_getfld.c,v 1.7 90/04/05 15:31:37 sources Exp Locker: sources $";
968 d146 2
969 a147 1
970 int     msg_count = 0;  /* disgusting hack for "inc" so it can
971 d152 1
972 a152 1
973 int     msg_style = MS_DEFAULT;
974 d165 1
975 a165 1
976 char    *msg_delim = "";
977 @
978
979
980 1.7
981 log
982 @add ID
983 @
984 text
985 @d3 1
986 a3 1
987 static char ident[] = "@@(#)$Id:$";
988 d548 1
989 d552 3
990 @
991
992
993 1.6
994 log
995 @add ID
996 @
997 text
998 @d3 1
999 a3 1
1000 static char ident[] = "$Id:";
1001 @
1002
1003
1004 1.5
1005 log
1006 @RAND fixes
1007 @
1008 text
1009 @d2 3
1010 @
1011
1012
1013 1.4
1014 log
1015 @cast iob->_ptr as unsigned char *.  This stuff is really yukky!
1016 @
1017 text
1018 @d545 3
1019 a547 1
1020         (void) fseek (iob, pos, 0);
1021 d629 2
1022 a630 2
1023                 while (pp < ep && *sp++ == *pp++)
1024                         ;
1025 @
1026
1027
1028 1.3
1029 log
1030 @Fixes from Van Jacobson
1031 @
1032 text
1033 @d237 1
1034 a237 1
1035                 bp = sp = iob->_ptr - 1;
1036 d291 1
1037 a291 1
1038                 cnt = iob->_cnt++; bp = --iob->_ptr;
1039 d298 1
1040 a298 1
1041                         j = ep - iob->_ptr;
1042 d310 1
1043 a310 1
1044                 c += bp - iob->_ptr;
1045 d346 1
1046 a346 1
1047             bp = --iob->_ptr; cnt = ++iob->_cnt;
1048 @
1049
1050
1051 1.2
1052 log
1053 @*** empty log message ***
1054 @
1055 text
1056 @d138 2
1057 a139 2
1058 static char *matchc();
1059 static char *locc();
1060 d141 1
1061 a141 1
1062 static char **pat_map;
1063 d162 2
1064 a163 2
1065 static char *fdelim;
1066 static char *delimend;
1067 d165 1
1068 a165 1
1069 static char *edelim;
1070 d175 1
1071 a175 1
1072 char            *name,
1073 d179 1
1074 a179 6
1075     register char  *cp;
1076 #ifndef SYS5
1077     register char  *bp;
1078     register char  *ep;
1079     register char  *sp;
1080 #else   SYS5
1081 a182 1
1082 #endif  SYS5
1083 a292 1
1084 #ifndef SYS5
1085 a293 3
1086 #else   SYS5
1087                 while (ep = (unsigned char *) locc( c, bp, '\n' )) {
1088 #endif  SYS5
1089 a360 1
1090 #ifndef SYS5
1091 a361 3
1092 #else   SYS5
1093                 if (ep = (unsigned char *) matchc( fdelimlen, fdelim, c, bp ) )
1094 #endif  SYS5
1095 d369 1
1096 a369 1
1097                      * check relatively cheap.  The first "while" figures
1098 a376 2
1099 #ifndef SYS5
1100                     sp = delimend;
1101 d378 4
1102 a381 9
1103                     while ((cp = pat_map[*ep]) < sp) {
1104                         ep = bp + c - 1; sp = cp;
1105 #else   SYS5
1106                     sp = (unsigned char *) delimend;
1107                     ep = bp + c - 1;
1108                     while ((cp = pat_map[*ep]) < (char *) sp) {
1109                         ep = bp + c - 1; sp = (unsigned char *) cp;
1110 #endif  SYS5
1111                         while (*--ep == *--cp && cp > fdelim)
1112 d383 11
1113 a393 3
1114                         if (cp == fdelim) {
1115                             if (*ep == *cp && ep > bp)
1116                                 c = (ep - bp) + 1;
1117 d396 3
1118 d427 3
1119 a429 2
1120 void m_unknown (iob)
1121 register FILE *iob;
1122 d435 1
1123 d454 1
1124 a454 1
1125         fdelim = "\n\nFrom ";
1126 d469 1
1127 a469 3
1128         fdelim = (char *)malloc((unsigned)strlen(mmdlm2)+2);
1129         *fdelim = '\n';
1130         (void)strcpy(fdelim+1, mmdlm2);
1131 d472 10
1132 a481 5
1133     fdelimlen = strlen(fdelim);
1134     msg_delim = fdelim+1;
1135     edelim = msg_delim+1;
1136     edelimlen = fdelimlen-2;
1137     delimend = msg_delim + edelimlen;
1138 d490 1
1139 a490 3
1140     pat_map = (char **) malloc( 256 * sizeof (char *));
1141     for (c = 256; c--; )
1142         pat_map[c] = delimend + 1;
1143 d492 2
1144 a493 2
1145     for (cp = fdelim + 1; cp < delimend; cp++ )
1146         pat_map[*cp] = cp;
1147 d515 3
1148 a517 3
1149         msg_delim = fdelim + 1;
1150         fdelimlen = strlen (fdelim);
1151         delimend = msg_delim + edelimlen;
1152 d608 1
1153 a608 1
1154 static char *
1155 d630 1
1156 a630 1
1157                         return (--str);
1158 d650 1
1159 a650 1
1160 static char *
1161 d653 2
1162 a654 2
1163         register char *src;
1164         register char term;
1165 d658 1
1166 a658 1
1167     return (cnt > 0 ? --src : NULLCP);
1168 d695 1
1169 a695 1
1170 #endif  not BSD42 or SYS5
1171 @
1172
1173
1174 1.1
1175 log
1176 @Initial revision
1177 @
1178 text
1179 @d299 1
1180 d301 3
1181 d371 1
1182 d373 3
1183 d391 1
1184 d396 6
1185 @