home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / communic / pcmail / daemon / ms_parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  4.4 KB  |  163 lines

  1. /*++
  2.  
  3. /* NAME
  4.  
  5. /*      ms_parse 3
  6.  
  7. /* SUMMARY
  8.  
  9. /*      message parser
  10.  
  11. /* PROJECT
  12.  
  13. /*      pc-mail
  14.  
  15. /* PACKAGE
  16.  
  17. /*    nfs
  18.  
  19. /* SYNOPSIS
  20.  
  21. /*    #include "ms_parse.h"
  22.  
  23. /*
  24.  
  25. /*    int ms_parse(context, line)
  26.  
  27. /*    int context;
  28.  
  29. /*    char *line;
  30.  
  31. /*
  32.  
  33. /*    int hscanf(line, prefix, format, result)
  34.  
  35. /*    char *line;
  36.  
  37. /*    char *prefix;
  38.  
  39. /*    char *format;
  40.  
  41. /*    char *result;
  42.  
  43. /* DESCRIPTION
  44.  
  45. /*    The routines in this module recognize
  46.  
  47. /*    the context in which successive lines of text occur within an
  48.  
  49. /*    e-mail message, or extract specific information from header
  50.  
  51. /*    lines.
  52.  
  53. /*
  54.  
  55. /*    The expected format of an e-mail message is: UUCP header lines,
  56.  
  57. /*    RFC822-like header lines, message body. Each of these sections
  58.  
  59. /*    may be missing from the message. A header line is a line that
  60.  
  61. /*    has no blanks before the first colon appearing on that line.
  62.  
  63. /*
  64.  
  65. /*    ms_parse() determines the context in which a line of text was found:
  66.  
  67. /*
  68.  
  69. /* .nf
  70.  
  71.     MS_UUCP        UUCP-style From_ line
  72.  
  73.     MS_HEADER    RFC822-like header line
  74.  
  75.     MS_CONT        Continued header line
  76.  
  77.     MS_BODY        Line within message body
  78.  
  79. /* .fi
  80.  
  81. /*
  82.  
  83. /*    The context argument should have the value MS_UUCP in the initial
  84.  
  85. /*    call of ms_parse(). Upon successive calls the value should be equal
  86.  
  87. /*    to the last value returned by ms_parse().
  88.  
  89. /*
  90.  
  91. /*    hscanf() compares the beginning of a line with the specified prefix
  92.  
  93. /*    (ignoring case differences), and if the comparison succeeds, it
  94.  
  95. /*    invokes sscanf() on the remainder of that line. A zero return value
  96.  
  97. /*    means that no information was extracted with sscanf.
  98.  
  99. /* AUTHOR(S)
  100.  
  101. /*      W.Z. Venema
  102.  
  103. /*      Eindhoven University of Technology
  104.  
  105. /*      Department of Mathematics and Computer Science
  106.  
  107. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  108.  
  109. /* CREATION DATE
  110.  
  111. /*    Sat Dec  9 18:50:35 MET 1989
  112.  
  113. /* LAST MODIFICATION
  114.  
  115. /*    1/6/90 19:45:16
  116.  
  117. /* VERSION/RELEASE
  118.  
  119. /*    1.7
  120.  
  121. /*--*/
  122.  
  123.  
  124.  
  125. #include <stdio.h>
  126.  
  127. #include <ctype.h>
  128.  
  129.  
  130.  
  131. #include "ms_parse.h"
  132.  
  133.  
  134.  
  135. extern char *strchr();
  136.  
  137.  
  138.  
  139. /* forward declarations */
  140.  
  141.  
  142.  
  143. static int isheader();
  144.  
  145. static int istrncmp();
  146.  
  147.  
  148.  
  149. /* hscanf - match header and extract info from remainder of header line */
  150.  
  151.  
  152.  
  153. int     hscanf(line, pre, fmt, ptr)
  154.  
  155. char   *line;
  156.  
  157. char   *pre;
  158.  
  159. char   *fmt;
  160.  
  161. char   *ptr;
  162.  
  163. {
  164.  
  165.     int     len = strlen(pre);
  166.  
  167.  
  168.  
  169.     return (istrncmp(pre, line, len) == 0 && sscanf(line + len, fmt, ptr) == 1);
  170.  
  171. }
  172.  
  173.  
  174.  
  175. /* ms_parse - parse one message line */
  176.  
  177.  
  178.  
  179. int     ms_parse(context, line)
  180.  
  181. register int context;
  182.  
  183. register char *line;
  184.  
  185. {
  186.  
  187.  
  188.  
  189.     /*
  190.  
  191.      * A message may begin with UUCP header lines ("From blablabla",
  192.  
  193.      * sometimes escaped with a ">" character), followed by RFC822-like
  194.  
  195.      * header lines (lines that start with a word + colon, or continuation
  196.  
  197.      * lines that start with whitespace), followed by the remainder of the
  198.  
  199.      * message. Header and body are usually separated by an empty line (on
  200.  
  201.      * systems that can handle that) but the we do not require this.
  202.  
  203.      */
  204.  
  205.  
  206.  
  207.     switch (context) {
  208.  
  209.     case MS_UUCP:
  210.  
  211.     if (line[0] == '>' || strncmp(line, "From ", 5) == 0)
  212.  
  213.         return (MS_UUCP);
  214.  
  215.     if (isspace(line[0]))
  216.  
  217.         return (MS_BODY);
  218.  
  219.     /* FALLTHROUGH */
  220.  
  221.     case MS_HEADER:
  222.  
  223.     case MS_CONT:
  224.  
  225.     if (isspace(line[0]))
  226.  
  227.         return (MS_CONT);
  228.  
  229.     if (isheader(line))
  230.  
  231.         return (MS_HEADER);
  232.  
  233.     /* FALLTHROUGH */
  234.  
  235.     case MS_BODY:
  236.  
  237.     return (MS_BODY);
  238.  
  239.     }
  240.  
  241.     /* NOTREACHED */
  242.  
  243. }
  244.  
  245.  
  246.  
  247. /* isheader - does this line look like a header? */
  248.  
  249.  
  250.  
  251. static int isheader(buf)
  252.  
  253. char   *buf;
  254.  
  255. {
  256.  
  257.     static char blanks[] = " \t\f";
  258.  
  259.     char   *cp;
  260.  
  261.     char   *blk;
  262.  
  263.     char   *colon;
  264.  
  265.  
  266.  
  267.     /*
  268.  
  269.      * A header line has no blanks before the first colon. Which means that a
  270.  
  271.      * line that starts with a colon character is treated as header line.
  272.  
  273.      * This turns out to be what many sendmail implementations do, too.
  274.  
  275.      */
  276.  
  277.  
  278.  
  279.     if ((colon = strchr(buf, ':')) == 0) {    /* check for colon */
  280.  
  281.     return (0);
  282.  
  283.     } else {                    /* find preceding blanks */
  284.  
  285.     for (cp = blanks; *cp; cp++)
  286.  
  287.         if ((blk = strchr(buf, *cp)) != 0 && blk < colon)
  288.  
  289.         return (0);
  290.  
  291.     }
  292.  
  293.     return (1);
  294.  
  295. }
  296.  
  297.  
  298.  
  299. #define    low(x)    ((isascii(x) && isupper(x)) ? tolower(x) : (x))
  300.  
  301.  
  302.  
  303. /* istrncmp - case-insensitive strncmp */
  304.  
  305.  
  306.  
  307. static int istrncmp(s1, s2, len)
  308.  
  309. char   *s1;
  310.  
  311. char   *s2;
  312.  
  313. int     len;
  314.  
  315. {
  316.  
  317.     while (len > 0 && *s1 && *s2 && low(*s1) == low(*s2))
  318.  
  319.     len--, s1++, s2++;
  320.  
  321.     return (len > 0 ? low(*s1) - low(*s2) : 0);
  322.  
  323. }
  324.  
  325.