Blob


1 #include "common.h"
3 enum {
4 Buffersize = 64*1024
5 };
7 typedef struct Inbuf Inbuf;
8 struct Inbuf
9 {
10 char buf[Buffersize];
11 char *wp;
12 char *rp;
13 int eof;
14 int in;
15 int out;
16 int last;
17 ulong bytes;
18 };
20 static Inbuf*
21 allocinbuf(int in, int out)
22 {
23 Inbuf *b;
25 b = mallocz(sizeof(Inbuf), 1);
26 if(b == nil)
27 sysfatal("reading mailbox: %r");
28 b->rp = b->wp = b->buf;
29 b->in = in;
30 b->out = out;
31 return b;
32 }
34 static int
35 fill(Inbuf *b, int addspace)
36 {
37 int i, n;
39 if(b->eof && b->wp - b->rp == 0)
40 return 0;
42 n = b->rp - b->buf;
43 if(n > 0){
44 i = write(b->out, b->buf, n);
45 if(i != n)
46 return -1;
47 b->last = b->buf[n-1];
48 b->bytes += n;
49 }
50 if(addspace){
51 if(write(b->out, " ", 1) != 1)
52 return -1;
53 b->last = ' ';
54 b->bytes++;
55 }
57 n = b->wp - b->rp;
58 memmove(b->buf, b->rp, n);
59 b->rp = b->buf;
60 b->wp = b->rp + n;
62 i = read(b->in, b->buf+n, sizeof(b->buf)-n);
63 if(i < 0)
64 return -1;
65 b->wp += i;
67 return b->wp - b->rp;
68 }
70 /* code to escape ' '*From' ' at the beginning of a line */
71 int
72 appendfiletombox(int in, int out)
73 {
74 int addspace;
75 int n;
76 char *p;
77 int sol;
78 Inbuf *b;
80 seek(out, 0, 2);
82 b = allocinbuf(in, out);
83 addspace = 0;
84 sol = 1;
86 for(;;){
87 if(b->wp - b->rp < 5){
88 n = fill(b, addspace);
89 addspace = 0;
90 if(n < 0)
91 goto error;
92 if(n == 0)
93 break;
94 if(n < 5){
95 b->rp = b->wp;
96 continue;
97 }
98 }
100 /* state machine looking for ' '*From' ' */
101 if(!sol){
102 p = memchr(b->rp, '\n', b->wp - b->rp);
103 if(p == nil)
104 b->rp = b->wp;
105 else{
106 b->rp = p+1;
107 sol = 1;
109 continue;
110 } else {
111 if(*b->rp == ' ' || strncmp(b->rp, "From ", 5) != 0){
112 b->rp++;
113 continue;
115 addspace = 1;
116 sol = 0;
120 /* mailbox entries always terminate with two newlines */
121 n = b->last == '\n' ? 1 : 2;
122 if(write(out, "\n\n", n) != n)
123 goto error;
124 n += b->bytes;
125 free(b);
126 return n;
127 error:
128 free(b);
129 return -1;
132 int
133 appendfiletofile(int in, int out)
135 int n;
136 Inbuf *b;
138 seek(out, 0, 2);
140 b = allocinbuf(in, out);
141 for(;;){
142 n = fill(b, 0);
143 if(n < 0)
144 goto error;
145 if(n == 0)
146 break;
147 b->rp = b->wp;
149 n = b->bytes;
150 free(b);
151 return n;
152 error:
153 free(b);
154 return -1;