]> mj.ucw.cz Git - maildups.git/blob - mparse.c
9c31851f9cc4d3584ede9fd0f730e9b60595195f
[maildups.git] / mparse.c
1 /*
2  *      Mailbox Parser (so far very primitive)
3  *
4  *      (c) 2010 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11
12 #include "util.h"
13
14 const char progname[] = "mparse";
15
16 #define BUFSIZE 65536
17
18 static char buf[BUFSIZE];
19 static char *bpos=buf, *bend=buf;
20
21 static char *getline(void)
22 {
23   if (!bpos)
24     return NULL;
25
26   for (;;)
27     {
28       int remains = bend - bpos;
29       if (remains)
30         {
31           char *nl = memchr(bpos, '\n', remains);
32           if (nl)
33             {
34               char *p = bpos;
35               if (nl > p && nl[-1] == '\r')
36                 nl[-1] = 0;
37               *nl++ = 0;
38               bpos = nl;
39               return p;
40             }
41           memmove(buf, bpos, remains);
42         }
43       bpos = buf;
44       bend = buf + remains;
45
46       int space = BUFSIZE - remains;
47       if (!space)
48         die("Line too long");
49       int len = read(0, bend, space);
50       if (len < 0)
51         die("Read error: %m");
52       if (!len)
53         {
54           bpos = NULL;
55           if (bend > buf)
56             {
57               *bend = 0;
58               return buf;
59             }
60           return NULL;
61         }
62       bend = bend + len;
63     }
64 }
65
66 enum state {
67   S_INITIAL,
68   S_HEADER,
69   S_BODY,
70 };
71
72 int
73 main(int argc UNUSED, char **argv UNUSED)
74 {
75   char *c;
76   enum state state = S_INITIAL;
77
78   while (c = getline())
79     {
80       // printf("<%s>\n", c);
81       if (state == S_INITIAL || state == S_BODY)
82         {
83           if (!strncmp(c, "From ", 5))
84             {
85               state = S_HEADER;
86               fputs(c, stdout);
87             }
88         }
89       else
90         {
91           if (!*c)
92             {
93               puts("\n");
94               state = S_BODY;
95             }
96           else if (*c == ' ' || *c == '\t')
97             {
98               while (*c == ' ' || *c == '\t')
99                 c++;
100               putchar(' ');
101               fputs(c, stdout);
102             }
103           else
104             {
105               putchar('\n');
106               fputs(c, stdout);
107             }
108         }
109     }
110
111   if (state == S_HEADER)
112     printf("\nX-Warning: Incomplete mail\n\n");
113
114   return 0;
115 }