]> mj.ucw.cz Git - maildups.git/blob - mparse.c
mparse: Allow to choose the header fields to print
[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 *get_line(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 static int want_header(char *line, char **want, int n_want)
67 {
68   if (!n_want)
69     return 1;
70
71   for (int i=0; i<n_want; i++)
72     {
73       int len = strlen(want[i]);
74       if (!strncasecmp(line, want[i], len))
75         return 1;
76     }
77
78   return 0;
79 }
80
81 enum state {
82   S_INITIAL,
83   S_HEADER,
84   S_BODY,
85 };
86
87 int
88 main(int argc, char **argv)
89 {
90   char *c;
91   enum state state = S_INITIAL;
92   int want = 0;
93
94   while (c = get_line())
95     {
96       // printf("<%s>\n", c);
97       if (state == S_INITIAL || state == S_BODY)
98         {
99           if (!strncmp(c, "From ", 5))
100             {
101               state = S_HEADER;
102               fputs(c, stdout);
103             }
104         }
105       else
106         {
107           if (!*c)
108             {
109               puts("\n");
110               state = S_BODY;
111             }
112           else if (*c == ' ' || *c == '\t')
113             {
114               if (want)
115                 {
116                   while (*c == ' ' || *c == '\t')
117                     c++;
118                   putchar(' ');
119                   fputs(c, stdout);
120                 }
121             }
122           else
123             {
124               want = want_header(c, argv+1, argc-1);
125               if (want)
126                 {
127                   putchar('\n');
128                   fputs(c, stdout);
129                 }
130             }
131         }
132     }
133
134   if (state == S_HEADER)
135     printf("\nX-Warning: Incomplete mail\n\n");
136
137   return 0;
138 }