regex: updates from neatvi
[neatmail.git] / pn.c
blob09a8ad457b3ab77858d57658660d8ec5e3264afd
1 #include <fcntl.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include "mail.h"
9 #define NHDRS 128
11 static char *hdrs[NHDRS]; /* included headers */
12 static int hdrs_n;
13 static char pn_buf[4096]; /* last line */
14 static char pn_rev; /* push back the last line */
15 static int maxlen = -1; /* body length to include */
16 static char *pn_path; /* input path */
17 static FILE *pn_fp; /* input file */
18 static long pn_pos; /* file position */
19 static int pn_num; /* message number */
21 static char *lnext(void)
23 if (pn_rev) {
24 pn_rev = 0;
25 return pn_buf;
27 pn_pos += strlen(pn_buf);
28 return fgets(pn_buf, sizeof(pn_buf), pn_fp);
31 static void lback(void)
33 pn_rev = 1;
36 static int hdrs_add(char *hdr)
38 if (hdrs_n < NHDRS)
39 hdrs[hdrs_n++] = hdr;
40 return 0;
43 static int hdrs_find(char *ln)
45 int i;
46 for (i = 0; i < hdrs_n; i++)
47 if (startswith(ln, hdrs[i]))
48 return i;
49 return -1;
52 static int from_(char *s)
54 return s && s[0] == 'F' && s[1] == 'r' && s[2] == 'o' &&
55 s[3] == 'm' && s[4] == ' ';
58 static int pn_one(void)
60 char *ln;
61 int hdrout = 0;
62 long beg, body;
63 while ((ln = lnext())) {
64 fputs(ln, stdout);
65 if (ln[0] != '\n')
66 break;
68 if (!ln)
69 return -1;
70 beg = pn_pos;
71 /* read headers */
72 while ((ln = lnext())) {
73 if (from_(ln) || ln[0] == '\n') {
74 lback();
75 break;
77 if (ln[0] != ' ' && ln[0] != '\t')
78 hdrout = hdrs_find(ln) >= 0;
79 if (hdrout)
80 fputs(ln, stdout);
82 body = pn_pos;
83 /* read body */
84 while ((ln = lnext())) {
85 if (from_(ln)) {
86 lback();
87 break;
89 if (maxlen < 0 || pn_pos - body + strlen(ln) < maxlen)
90 fputs(ln, stdout);
92 if (pn_path && maxlen == 0)
93 printf("Neatmail-Source: %d@%s %ld %ld\n", pn_num, pn_path, beg, pn_pos);
94 if (maxlen >= 0 && pn_pos - body >= maxlen)
95 fputs("\n", stdout);
96 return 0;
99 static int pn_proc(char *path)
101 if (path && (pn_fp = fopen(path, "r")) == NULL)
102 return 1;
103 if (path == NULL)
104 pn_fp = stdin;
105 pn_path = path;
106 pn_pos = 0;
107 pn_num = 0;
108 pn_buf[0] = '\0';
109 while (pn_one() == 0)
110 pn_num++;
111 if (path != NULL)
112 fclose(pn_fp);
113 fprintf(stderr, "%s: %d messages\n", path ? path : "stdin", pn_num);
114 return 0;
117 static char *usage =
118 "usage: neatmail pn [options] [imbox] <imbox >ombox\n\n"
119 "options:\n"
120 " -h hdr \tspecify headers to include\n"
121 " -H \tinclude the default set of headers\n"
122 " -s size \tmaximum message body length to include\n";
124 int pn(char *argv[])
126 char *path[16] = {NULL};
127 int path_n = 0;
128 int i;
129 if (!argv[0]) {
130 printf("%s", usage);
131 return 1;
133 for (i = 0; argv[i] && argv[i][0] == '-'; i++) {
134 if (argv[i][1] == 'h') {
135 hdrs_add(argv[i][2] ? argv[i] + 2 : argv[++i]);
136 continue;
138 if (argv[i][1] == 'H') {
139 hdrs_add("From:");
140 hdrs_add("To:");
141 hdrs_add("Cc:");
142 hdrs_add("Bcc:");
143 hdrs_add("Subject:");
144 hdrs_add("Date:");
145 hdrs_add("Message-ID:");
146 hdrs_add("Reply-To:");
147 hdrs_add("In-Reply-To:");
148 hdrs_add("References:");
149 hdrs_add("MIME-Version:");
150 hdrs_add("Content-Type:");
151 hdrs_add("Content-Transfer-Encoding:");
152 hdrs_add("User-Agent:");
153 hdrs_add("X-Mailer:");
154 hdrs_add("Organization:");
155 hdrs_add("Status:");
156 hdrs_add("Neatmail");
157 continue;
159 if (argv[i][1] == 's') {
160 maxlen = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
161 continue;
163 if (argv[i][1] == 'b') {
164 path[path_n++] = argv[i][2] ? argv[i] + 2 : argv[++i];
165 continue;
168 for (; argv[i]; i++)
169 path[path_n++] = argv[i];
170 for (i = 0; i < path_n; i++)
171 if (pn_proc(path[i]) != 0)
172 fprintf(stderr, "pn: cannot open <%s>\n", path[i]);
173 if (path_n == 0)
174 pn_proc(NULL);
175 return 0;