]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/sbr/RCS/m_getfld.c,v
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / 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 @