summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/tools/mailstream.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/tools/mailstream.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/tools/mailstream.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/kmicromail/libetpan/tools/mailstream.c b/kmicromail/libetpan/tools/mailstream.c
new file mode 100644
index 0000000..0f55e67
--- a/dev/null
+++ b/kmicromail/libetpan/tools/mailstream.c
@@ -0,0 +1,394 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream.h"
37#include "maillock.h"
38#include <string.h>
39#include <stdlib.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42
43#define DEFAULT_NETWORK_TIMEOUT 300
44
45#ifdef LIBETPAN_MAILSTREAM_DEBUG
46
47#define STREAM_DEBUG
48
49#include <stdio.h>
50
51#define LOG_FILE "libetpan-stream-debug.log"
52
53int mailstream_debug = 0;
54
55#define STREAM_LOG_BUF(buf, size) \
56 if (mailstream_debug) { \
57 FILE * f; \
58 mode_t old_mask; \
59 \
60 old_mask = umask(0077); \
61 f = fopen(LOG_FILE, "a"); \
62 umask(old_mask); \
63 if (f != NULL) { \
64 maillock_write_lock(LOG_FILE, fileno(f)); \
65 fwrite((buf), 1, (size), f); \
66 maillock_write_unlock(LOG_FILE, fileno(f)); \
67 fclose(f); \
68 } \
69 }
70
71#define STREAM_LOG(str) \
72 if (mailstream_debug) { \
73 FILE * f; \
74 mode_t old_mask; \
75 \
76 old_mask = umask(0077); \
77 f = fopen(LOG_FILE, "a"); \
78 umask(old_mask); \
79 if (f != NULL) { \
80 maillock_write_lock(LOG_FILE, fileno(f)); \
81 fputs((str), f); \
82 maillock_write_unlock(LOG_FILE, fileno(f)); \
83 fclose(f); \
84 } \
85 }
86
87#else
88
89#define STREAM_LOG_BUF(buf, size) do { } while (0)
90#define STREAM_LOG(buf) do { } while (0)
91
92#endif
93
94
95mailstream * mailstream_new(mailstream_low * low, size_t buffer_size)
96{
97 mailstream * s;
98
99 s = malloc(sizeof(* s));
100 if (s == NULL)
101 goto err;
102
103 s->read_buffer = malloc(buffer_size);
104 if (s->read_buffer == NULL)
105 goto free_s;
106 s->read_buffer_len = 0;
107
108 s->write_buffer = malloc(buffer_size);
109 if (s->write_buffer == NULL)
110 goto free_read_buffer;
111 s->write_buffer_len = 0;
112
113 s->buffer_max_size = buffer_size;
114 s->low = low;
115
116 return s;
117
118 free_read_buffer:
119 free(s->read_buffer);
120 free_s:
121 free(s);
122 err:
123 return NULL;
124}
125
126static size_t write_to_internal_buffer(mailstream * s,
127 const void * buf, size_t count)
128{
129 memcpy(s->write_buffer + s->write_buffer_len, buf, count);
130 s->write_buffer_len += count;
131
132 return count;
133}
134
135static size_t write_direct(mailstream * s, const void * buf, size_t count)
136{
137 size_t left;
138 const char * cur_buf;
139 ssize_t written;
140
141 cur_buf = buf;
142 left = count;
143 while (left > 0) {
144 written = mailstream_low_write(s->low, cur_buf, left);
145
146 if (written == -1) {
147 if (count == left)
148 return -1;
149 else
150 return count - left;
151 }
152
153 cur_buf += written;
154 left -= written;
155 }
156
157 return count;
158}
159
160ssize_t mailstream_write(mailstream * s, const void * buf, size_t count)
161{
162 int r;
163
164 if (s == NULL)
165 return -1;
166
167 if (count + s->write_buffer_len > s->buffer_max_size) {
168 r = mailstream_flush(s);
169 if (r == -1)
170 return -1;
171
172 if (count > s->buffer_max_size)
173 return write_direct(s, buf, count);
174 }
175
176#ifdef STREAM_DEBUG
177 STREAM_LOG(">>>>>>> send >>>>>>\n");
178 STREAM_LOG_BUF(buf, count);
179 STREAM_LOG("\n");
180 STREAM_LOG(">>>>>>> end send >>>>>>\n");
181#endif
182
183 return write_to_internal_buffer(s, buf, count);
184}
185
186int mailstream_flush(mailstream * s)
187{
188 char * cur_buf;
189 size_t left;
190 ssize_t written;
191
192 if (s == NULL)
193 return -1;
194
195 cur_buf = s->write_buffer;
196 left = s->write_buffer_len;
197 while (left > 0) {
198 written = mailstream_low_write(s->low, cur_buf, left);
199
200 if (written == -1)
201 goto move_buffer;
202 cur_buf += written;
203 left -= written;
204 }
205
206 s->write_buffer_len = 0;
207
208 return 0;
209
210 move_buffer:
211 memmove(s->write_buffer, cur_buf, left);
212 s->write_buffer_len = left;
213 return -1;
214}
215
216static ssize_t read_from_internal_buffer(mailstream * s,
217 void * buf, size_t count)
218{
219 if (count >= s->read_buffer_len)
220 count = s->read_buffer_len;
221 if (count != 0)
222 memcpy(buf, s->read_buffer, count);
223
224 s->read_buffer_len -= count;
225 if (s->read_buffer_len != 0)
226 memmove(s->read_buffer, s->read_buffer + count,
227 s->read_buffer_len);
228
229 return count;
230}
231
232static ssize_t read_through_buffer(mailstream * s, void * buf, size_t count)
233{
234 size_t left;
235 char * cur_buf;
236 ssize_t bytes_read;
237
238 cur_buf = buf;
239 left = count;
240
241 while (left > 0) {
242 bytes_read = mailstream_low_read(s->low, cur_buf, left);
243
244 if (bytes_read == -1) {
245 if (count == left)
246 return -1;
247 else
248 return count - left;
249 }
250 else if (bytes_read == 0)
251 return count - left;
252
253 cur_buf += bytes_read;
254 left -= bytes_read;
255 }
256
257 return count;
258}
259
260ssize_t mailstream_read(mailstream * s, void * buf, size_t count)
261{
262 ssize_t read_bytes;
263 char * cur_buf;
264 size_t left;
265
266 if (s == NULL)
267 return -1;
268
269 left = count;
270 cur_buf = buf;
271 read_bytes = read_from_internal_buffer(s, cur_buf, left);
272 cur_buf += read_bytes;
273 left -= read_bytes;
274
275 if (left == 0) {
276#ifdef STREAM_DEBUG
277 STREAM_LOG("<<<<<<< read <<<<<<\n");
278 STREAM_LOG_BUF(buf, read_bytes);
279 STREAM_LOG("\n");
280 STREAM_LOG("<<<<<<< end read <<<<<<\n");
281#endif
282
283 return read_bytes;
284 }
285
286 if (left > s->buffer_max_size) {
287 read_bytes = read_through_buffer(s, cur_buf, left);
288 if (read_bytes == -1) {
289 if (count == left)
290 return -1;
291 else {
292
293#ifdef STREAM_DEBUG
294 STREAM_LOG("<<<<<<< read <<<<<<\n");
295 STREAM_LOG_BUF(buf, count - left);
296 STREAM_LOG("\n");
297 STREAM_LOG("<<<<<<< end read <<<<<<\n");
298#endif
299
300 return count - left;
301 }
302 }
303
304 cur_buf += read_bytes;
305 left -= read_bytes;
306
307#ifdef STREAM_DEBUG
308 STREAM_LOG("<<<<<<< read <<<<<<\n");
309 STREAM_LOG_BUF(buf, count - left);
310 STREAM_LOG("\n");
311 STREAM_LOG("<<<<<<< end read <<<<<<\n");
312#endif
313
314 return count - left;
315 }
316
317 read_bytes = mailstream_low_read(s->low, s->read_buffer, s->buffer_max_size);
318 if (read_bytes == -1) {
319 if (left == count)
320 return -1;
321 else {
322#ifdef STREAM_DEBUG
323 STREAM_LOG("<<<<<<< read <<<<<<\n");
324 STREAM_LOG_BUF(buf, count - left);
325 STREAM_LOG("\n");
326 STREAM_LOG("<<<<<<< end read <<<<<<\n");
327#endif
328
329 return count - left;
330 }
331 }
332 else
333 s->read_buffer_len += read_bytes;
334
335 read_bytes = read_from_internal_buffer(s, cur_buf, left);
336 cur_buf += read_bytes;
337 left -= read_bytes;
338
339#ifdef STREAM_DEBUG
340 STREAM_LOG("<<<<<<< read <<<<<<\n");
341 STREAM_LOG_BUF(buf, count - left);
342 STREAM_LOG("\n");
343 STREAM_LOG("<<<<<<< end read <<<<<<\n");
344#endif
345
346 return count - left;
347}
348
349mailstream_low * mailstream_get_low(mailstream * s)
350{
351 return s->low;
352}
353
354void mailstream_set_low(mailstream * s, mailstream_low * low)
355{
356 s->low = low;
357}
358
359int mailstream_close(mailstream * s)
360{
361 mailstream_low_close(s->low);
362 mailstream_low_free(s->low);
363
364 free(s->read_buffer);
365 free(s->write_buffer);
366
367 free(s);
368
369 return 0;
370}
371
372
373
374ssize_t mailstream_feed_read_buffer(mailstream * s)
375{
376 ssize_t read_bytes;
377
378 if (s == NULL)
379 return -1;
380
381 if (s->read_buffer_len == 0) {
382 read_bytes = mailstream_low_read(s->low, s->read_buffer,
383 s->buffer_max_size);
384 if (read_bytes == -1)
385 return -1;
386 s->read_buffer_len += read_bytes;
387 }
388
389 return s->read_buffer_len;
390}
391
392struct timeval mailstream_network_delay =
393 { .tv_sec = DEFAULT_NETWORK_TIMEOUT, .tv_usec = 0 };
394