Commit 637f4ca5 637f4ca5d9481742b04b5642e8bd57db1895a9e3 by Alain Magloire

For the new mailbox, one of the short coming with the old stream_t

	object was that select() was not cover, meaning it was not possible
	to check if a stream was {read,write} ready.  The old was to get
	the fd (stream_get_fd()) and do the select.  Providing,
	stream_is_readready (stream_t, int timeout);
	stream_is_writeready (stream_t, int timeout);
	stream_is_exceptionpending (stream_t, int timeout);
	stream_is_open (stream_t);
	Takes care of it.  It will work specially for tcp stream.

	* mailbox2/stream.c: New functions for the select calls:
	(stream_is_readready): New function.
	(stream_is_writeready): New function.(stream_t, int timeout);
	(stream_is_exceptionpending): New function.
	(stream_is_open): New function.
	* mailbox2/bstream.c (_bs_readline): Bug was truncating the string
	to early.
	(_bs_is_readready): New file.
	(_bs_is_writeready): New file.
	(_bs_is_exceptionpending): New file.
	(_bs_is_open): New file.
	* mailbox2/fstream.c: stubs for the select functions.
	* mailbox2/memstream.c: stubs for the select functions.
	* mailbox2/mapstream.c: stubs for the select functions.
	* mailbox2/tcpstream.c: stubs for the select functions.
	* mailbox2/include/mailutils/stream.h: Adjust the prototypes
	* mailbox2/include/mailutils/sys/stream.h: Adjust the prototypes

	It is better not to put threading (Pthread) code in the low level
	API.  But instead in mailbox_t framework, where it can be control.
	* mailbox2/include/mailutils/pop3.h: Adjust the prototypes.
	* mailbox2/pop3/*.c: Remove threading code.
1 parent b51239c0
...@@ -27,7 +27,7 @@ libmailbox_la_SOURCES = \ ...@@ -27,7 +27,7 @@ libmailbox_la_SOURCES = \
27 md5-rsa.c \ 27 md5-rsa.c \
28 memstream.c \ 28 memstream.c \
29 message.c \ 29 message.c \
30 mstream.c \ 30 mapstream.c \
31 mutil.c \ 31 mutil.c \
32 observable.c \ 32 observable.c \
33 observer.c \ 33 observer.c \
......
...@@ -268,9 +268,7 @@ _bs_readline (stream_t stream, char *buf, size_t count, size_t *pnread) ...@@ -268,9 +268,7 @@ _bs_readline (stream_t stream, char *buf, size_t count, size_t *pnread)
268 bs->rbuffer.ptr = nl; 268 bs->rbuffer.ptr = nl;
269 memcpy (s, p, len); 269 memcpy (s, p, len);
270 total += len; 270 total += len;
271 s[len] = '\0'; 271 s += len;
272 if (pnread)
273 *pnread = total;
274 break; 272 break;
275 } 273 }
276 bs->rbuffer.count -= len; 274 bs->rbuffer.count -= len;
...@@ -371,6 +369,38 @@ _bs_tell (stream_t stream, off_t *off) ...@@ -371,6 +369,38 @@ _bs_tell (stream_t stream, off_t *off)
371 return stream_tell (bs->stream, off); 369 return stream_tell (bs->stream, off);
372 } 370 }
373 371
372 static int
373 _bs_is_readready (stream_t stream, int timeout)
374 {
375 struct _bs *bs = (struct _bs *)stream;
376 /* Drain our buffer first. */
377 if (bs->rbuffer.count > 0)
378 return 1;
379 return stream_is_readready (bs->stream, timeout);
380 }
381
382 static int
383 _bs_is_writeready (stream_t stream, int timeout)
384 {
385 struct _bs *bs = (struct _bs *)stream;
386 return stream_is_writeready (bs->stream, timeout);
387 }
388
389 static int
390 _bs_is_exceptionpending (stream_t stream, int timeout)
391 {
392 struct _bs *bs = (struct _bs *)stream;
393 return stream_is_exceptionpending (bs->stream, timeout);
394 }
395
396 static int
397 _bs_is_open (stream_t stream)
398 {
399 struct _bs *bs = (struct _bs *)stream;
400 return stream_is_open (bs->stream);
401 }
402
403
374 static struct _stream_vtable _bs_vtable = 404 static struct _stream_vtable _bs_vtable =
375 { 405 {
376 _bs_add_ref, 406 _bs_add_ref,
...@@ -394,6 +424,12 @@ static struct _stream_vtable _bs_vtable = ...@@ -394,6 +424,12 @@ static struct _stream_vtable _bs_vtable =
394 _bs_get_fd, 424 _bs_get_fd,
395 _bs_get_flags, 425 _bs_get_flags,
396 _bs_get_state, 426 _bs_get_state,
427
428 _bs_is_readready,
429 _bs_is_writeready,
430 _bs_is_exceptionpending,
431
432 _bs_is_open
397 }; 433 };
398 434
399 int 435 int
......
...@@ -247,6 +247,36 @@ _fs_get_state (stream_t stream, enum stream_state *state) ...@@ -247,6 +247,36 @@ _fs_get_state (stream_t stream, enum stream_state *state)
247 } 247 }
248 248
249 static int 249 static int
250 _fs_is_open (stream_t stream)
251 {
252 struct _fs *fs = (struct _fs *)stream;
253 return (fs->file) ? 1 : 0;
254 }
255
256 static int
257 _fs_is_readready (stream_t stream, int timeout)
258 {
259 (void)timeout;
260 return _fs_is_open (stream);
261 }
262
263 static int
264 _fs_is_writeready (stream_t stream, int timeout)
265 {
266 (void)timeout;
267 return _fs_is_open (stream);
268 }
269
270 static int
271 _fs_is_exceptionpending (stream_t stream, int timeout)
272 {
273 (void)stream;
274 (void)timeout;
275 return 0;
276 }
277
278
279 static int
250 _fs_close (stream_t stream) 280 _fs_close (stream_t stream)
251 { 281 {
252 struct _fs *fs = (struct _fs *)stream; 282 struct _fs *fs = (struct _fs *)stream;
...@@ -385,7 +415,13 @@ static struct _stream_vtable _fs_vtable = ...@@ -385,7 +415,13 @@ static struct _stream_vtable _fs_vtable =
385 415
386 _fs_get_fd, 416 _fs_get_fd,
387 _fs_get_flags, 417 _fs_get_flags,
388 _fs_get_state 418 _fs_get_state,
419
420 _fs_is_readready,
421 _fs_is_writeready,
422 _fs_is_exceptionpending,
423
424 _fs_is_open
389 }; 425 };
390 426
391 int 427 int
......
...@@ -36,51 +36,49 @@ extern "C" { ...@@ -36,51 +36,49 @@ extern "C" {
36 struct _pop3; 36 struct _pop3;
37 typedef struct _pop3* pop3_t; 37 typedef struct _pop3* pop3_t;
38 38
39 struct pop3_list_item 39 extern int pop3_create __P ((pop3_t *));
40 { 40 extern int pop3_destroy __P ((pop3_t));
41 unsigned int msgno; 41
42 unsigned int size; 42 extern int pop3_connect __P ((pop3_t, const char *, unsigned int));
43 }; 43 extern int pop3_disconnect __P ((pop3_t));
44 44
45 struct pop3_uidl_item 45 extern int pop3_set_carrier __P ((pop3_t, stream_t));
46 { 46 extern int pop3_get_carrier __P ((pop3_t, stream_t *));
47 unsigned int msgno; 47
48 char *uidl; 48 extern int pop3_set_timeout __P ((pop3_t, int));
49 }; 49 extern int pop3_get_timeout __P ((pop3_t, int *));
50 50
51 extern int pop3_create __P ((pop3_t *)); 51 extern int pop3_apop __P ((pop3_t, const char *, const char *));
52 extern void pop3_destroy __P ((pop3_t)); 52
53 53 extern int pop3_capa __P ((pop3_t, iterator_t *));
54 extern int pop3_connect __P ((pop3_t, const char *, unsigned int)); 54 extern int pop3_capa_current __P ((iterator_t, char **));
55 extern int pop3_disconnect __P ((pop3_t)); 55
56 56 extern int pop3_dele __P ((pop3_t, unsigned int));
57 extern int pop3_set_stream __P ((pop3_t, stream_t)); 57
58 extern int pop3_get_stream __P ((pop3_t, stream_t *)); 58 extern int pop3_list __P ((pop3_t, unsigned int, size_t *));
59 59 extern int pop3_list_all __P ((pop3_t, iterator_t *));
60 extern int pop3_set_timeout __P ((pop3_t, unsigned int)); 60 extern int pop3_list_current __P ((iterator_t, unsigned int *, size_t *));
61 extern int pop3_get_timeout __P ((pop3_t, unsigned int *)); 61
62 62 extern int pop3_noop __P ((pop3_t));
63 extern int pop3_apop __P ((pop3_t, const char *, const char *)); 63 extern int pop3_pass __P ((pop3_t, const char *));
64 extern int pop3_capa __P ((pop3_t, iterator_t *)); 64 extern int pop3_quit __P ((pop3_t));
65 extern int pop3_dele __P ((pop3_t, unsigned int)); 65 extern int pop3_retr __P ((pop3_t, unsigned int, stream_t *));
66 extern int pop3_list __P ((pop3_t, unsigned int, size_t *)); 66 extern int pop3_rset __P ((pop3_t));
67 extern int pop3_list_all __P ((pop3_t, iterator_t *)); 67 extern int pop3_stat __P ((pop3_t, unsigned int *, size_t *));
68 extern int pop3_noop __P ((pop3_t)); 68 extern int pop3_top __P ((pop3_t, unsigned int,
69 extern int pop3_pass __P ((pop3_t, const char *)); 69 unsigned int, stream_t *));
70 extern int pop3_quit __P ((pop3_t)); 70
71 extern int pop3_retr __P ((pop3_t, unsigned int, stream_t *)); 71 extern int pop3_uidl __P ((pop3_t, unsigned int, char **));
72 extern int pop3_rset __P ((pop3_t)); 72 extern int pop3_uidl_all __P ((pop3_t, iterator_t *));
73 extern int pop3_stat __P ((pop3_t, unsigned int *, size_t *)); 73 extern int pop3_uidl_current __P ((iterator_t, unsigned int *, char **));
74 extern int pop3_top __P ((pop3_t, unsigned int, unsigned int, stream_t *)); 74
75 extern int pop3_uidl __P ((pop3_t, unsigned int, char **)); 75 extern int pop3_user __P ((pop3_t, const char *));
76 extern int pop3_uidl_all __P ((pop3_t, iterator_t *)); 76
77 extern int pop3_user __P ((pop3_t, const char *)); 77 extern int pop3_readline __P ((pop3_t, char *, size_t, size_t *));
78 78 extern int pop3_response __P ((pop3_t, char *, size_t, size_t *));
79 extern int pop3_readline __P ((pop3_t, char *, size_t, size_t *)); 79 extern int pop3_writeline __P ((pop3_t, const char *, ...));
80 extern int pop3_response __P ((pop3_t, char *, size_t, size_t *)); 80 extern int pop3_sendline __P ((pop3_t, const char *));
81 extern int pop3_writeline __P ((pop3_t, const char *, ...)); 81 extern int pop3_send __P ((pop3_t));
82 extern int pop3_sendline __P ((pop3_t, const char *));
83 extern int pop3_send __P ((pop3_t));
84 82
85 #ifdef __cplusplus 83 #ifdef __cplusplus
86 } 84 }
......
...@@ -72,6 +72,12 @@ extern int stream_get_fd __P ((stream_t , int *)); ...@@ -72,6 +72,12 @@ extern int stream_get_fd __P ((stream_t , int *));
72 extern int stream_get_flags __P ((stream_t, int *)); 72 extern int stream_get_flags __P ((stream_t, int *));
73 extern int stream_get_state __P ((stream_t, enum stream_state *)); 73 extern int stream_get_state __P ((stream_t, enum stream_state *));
74 74
75 extern int stream_is_readready __P ((stream_t, int));
76 extern int stream_is_writeready __P ((stream_t, int));
77 extern int stream_is_exceptionpending __P ((stream_t, int));
78
79 extern int stream_is_open __P ((stream_t));
80
75 /* Misc. */ 81 /* Misc. */
76 extern int stream_file_create __P ((stream_t *)); 82 extern int stream_file_create __P ((stream_t *));
77 extern int stream_mapfile_create __P ((stream_t *)); 83 extern int stream_mapfile_create __P ((stream_t *));
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
23 #include <mailutils/pop3.h> 23 #include <mailutils/pop3.h>
24 #include <mailutils/sys/stream.h> 24 #include <mailutils/sys/stream.h>
25 #include <mailutils/sys/iterator.h> 25 #include <mailutils/sys/iterator.h>
26 #include <mailutils/monitor.h>
27 #include <mailutils/error.h> 26 #include <mailutils/error.h>
27 #include <mailutils/monitor.h>
28 28
29 #ifdef DMALLOC 29 #ifdef DMALLOC
30 # include <dmalloc.h> 30 # include <dmalloc.h>
...@@ -61,7 +61,7 @@ struct p_iterator ...@@ -61,7 +61,7 @@ struct p_iterator
61 pop3_t pop3; 61 pop3_t pop3;
62 unsigned int ref; 62 unsigned int ref;
63 int done; 63 int done;
64 void *item; 64 char *item;
65 monitor_t lock; 65 monitor_t lock;
66 }; 66 };
67 67
...@@ -103,13 +103,11 @@ struct _pop3 ...@@ -103,13 +103,11 @@ struct _pop3
103 unsigned timeout; /* Default is 10 minutes. */ 103 unsigned timeout; /* Default is 10 minutes. */
104 104
105 enum pop3_state state; 105 enum pop3_state state;
106 stream_t stream; /* TCP Connection. */ 106 stream_t carrier; /* TCP Connection. */
107 monitor_t lock;
108 }; 107 };
109 108
110 extern int pop3_iterator_create __P ((pop3_t, iterator_t *)); 109 extern int pop3_iterator_create __P ((pop3_t, iterator_t *));
111 extern int pop3_stream_create __P ((pop3_t, stream_t *)); 110 extern int pop3_stream_create __P ((pop3_t, stream_t *));
112 extern void pop3_cleanup __P ((void *));
113 111
114 /* Check for non recoverable error. */ 112 /* Check for non recoverable error. */
115 #define POP3_CHECK_EAGAIN(pop3, status) \ 113 #define POP3_CHECK_EAGAIN(pop3, status) \
......
...@@ -47,6 +47,12 @@ struct _stream_vtable ...@@ -47,6 +47,12 @@ struct _stream_vtable
47 int (*get_fd) __P ((stream_t , int *)); 47 int (*get_fd) __P ((stream_t , int *));
48 int (*get_flags) __P ((stream_t, int *)); 48 int (*get_flags) __P ((stream_t, int *));
49 int (*get_state) __P ((stream_t, enum stream_state *)); 49 int (*get_state) __P ((stream_t, enum stream_state *));
50
51 int (*is_readready) __P ((stream_t, int));
52 int (*is_writeready) __P ((stream_t, int));
53 int (*is_exceptionpending) __P ((stream_t, int));
54
55 int (*is_open) __P ((stream_t));
50 }; 56 };
51 57
52 struct _stream 58 struct _stream
......
...@@ -238,6 +238,38 @@ _memory_tell (stream_t stream, off_t *off) ...@@ -238,6 +238,38 @@ _memory_tell (stream_t stream, off_t *off)
238 } 238 }
239 239
240 static int 240 static int
241 _memory_is_open (stream_t stream)
242 {
243 (void)stream;
244 return 1;
245 }
246
247 static int
248 _memory_is_readready (stream_t stream, int timeout)
249 {
250 (void)stream;
251 (void)timeout;
252 return 1;
253 }
254
255 static int
256 _memory_is_writeready (stream_t stream, int timeout)
257 {
258 (void)stream;
259 (void)timeout;
260 return 1;
261 }
262
263 static int
264 _memory_is_exceptionpending (stream_t stream, int timeout)
265 {
266 (void)stream;
267 (void)timeout;
268 return 0;
269 }
270
271
272 static int
241 _memory_open (stream_t stream, const char *filename, int port, int flags) 273 _memory_open (stream_t stream, const char *filename, int port, int flags)
242 { 274 {
243 struct _memory_stream *mem = (struct _memory_stream *)stream; 275 struct _memory_stream *mem = (struct _memory_stream *)stream;
...@@ -278,7 +310,13 @@ static struct _stream_vtable _mem_vtable = ...@@ -278,7 +310,13 @@ static struct _stream_vtable _mem_vtable =
278 310
279 _memory_get_fd, 311 _memory_get_fd,
280 _memory_get_flags, 312 _memory_get_flags,
281 _memory_get_state 313 _memory_get_state,
314
315 _memory_is_readready,
316 _memory_is_writeready,
317 _memory_is_exceptionpending,
318
319 _memory_is_open
282 }; 320 };
283 321
284 int 322 int
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31
32 #include <mailutils/sys/mstream.h>
33 #include <mailutils/error.h>
34
35 #ifdef _POSIX_MAPPED_FILES
36 #include <sys/mman.h>
37
38 #ifndef MAP_FAILED
39 # define MAP_FAILED (void*)-1
40 #endif
41
42 static int
43 _ms_add_ref (stream_t stream)
44 {
45 int status;
46 struct _ms *ms = (struct _ms *)stream;
47 monitor_lock (ms->lock);
48 status = ++ms->ref;
49 monitor_unlock (ms->lock);
50 return status;
51 }
52
53 static int
54 _ms_destroy (stream_t stream)
55 {
56 struct _ms *ms = (struct _ms *)stream;
57
58 if (ms->ptr != MAP_FAILED)
59 {
60 if (ms->ptr)
61 munmap (ms->ptr, ms->size);
62 if (ms->fd != -1)
63 close (ms->fd);
64 monitor_destroy (ms->lock);
65 }
66 free (ms);
67 return 0;
68 }
69
70 static int
71 _ms_release (stream_t stream)
72 {
73 int status;
74 struct _ms *ms = (struct _ms *)stream;
75 monitor_lock (ms->lock);
76 status = --ms->ref;
77 if (status <= 0)
78 {
79 monitor_unlock (ms->lock);
80 _ms_destroy (stream);
81 return 0;
82 }
83 monitor_unlock (ms->lock);
84 return status;
85 }
86
87 static int
88 _ms_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
89 {
90 struct _ms *ms = (struct _ms *)stream;
91 size_t n = 0;
92
93 monitor_lock (ms->lock);
94 if (ms->ptr != MAP_FAILED && ms->ptr)
95 {
96 if (ms->offset < (off_t)ms->size)
97 {
98 n = ((ms->offset + osize) > ms->size) ?
99 ms->size - ms->offset : osize;
100 memcpy (optr, ms->ptr + ms->offset, n);
101 ms->offset += n;
102 }
103 }
104 monitor_unlock (ms->lock);
105
106 if (nbytes)
107 *nbytes = n;
108 return 0;
109 }
110
111 static int
112 _ms_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes)
113 {
114 struct _ms *ms = (struct _ms *)stream;
115 size_t n = 0;
116
117 monitor_lock (ms->lock);
118 if (ms->ptr != MAP_FAILED && ms->ptr)
119 {
120 if (ms->offset < (off_t)ms->size)
121 {
122 /* Save space for the null byte. */
123 char *nl;
124 osize--;
125 nl = memchr (ms->ptr + ms->offset, '\n', ms->size - ms->offset);
126 n = (nl) ? nl - (ms->ptr + ms->offset) + 1 : ms->size - ms->offset;
127 n = (n > osize) ? osize : n;
128 memcpy (optr, ms->ptr + ms->offset, n);
129 optr[n] = '\0';
130 ms->offset += n;
131 }
132 }
133 monitor_unlock (ms->lock);
134
135 if (nbytes)
136 *nbytes = n;
137 return 0;
138 }
139
140 static int
141 _ms_write (stream_t stream, const void *iptr, size_t isize, size_t *nbytes)
142 {
143 struct _ms *ms = (struct _ms *)stream;
144 int err = 0;
145 size_t n = 0;
146
147 monitor_lock (ms->lock);
148 if (ms->mflags & PROT_WRITE)
149 {
150 /* Bigger we have to remmap. */
151 if (ms->size < (ms->offset + isize))
152 {
153 if (ms->ptr != MAP_FAILED && munmap (ms->ptr, ms->size) == 0)
154 {
155 ms->ptr = MAP_FAILED;
156 if (ftruncate (ms->fd, ms->offset + isize) == 0)
157 {
158 ms->ptr = mmap (0, ms->offset + isize, ms->mflags,
159 MAP_SHARED, ms->fd, 0);
160 if (ms->ptr != MAP_FAILED)
161 ms->size = ms->offset + isize;
162 }
163 }
164 }
165
166 if (ms->ptr != MAP_FAILED)
167 {
168 if (isize > 0)
169 memcpy (ms->ptr + ms->offset, iptr, isize);
170 ms->offset += isize;
171 n = isize;
172 }
173 else
174 err = MU_ERROR_IO;
175 }
176 else
177 err = MU_ERROR_IO;
178 monitor_unlock (ms->lock);
179
180 if (nbytes)
181 *nbytes = n;
182 return err;
183 }
184
185 static int
186 _ms_truncate (stream_t stream, off_t len)
187 {
188 struct _ms *ms = (struct _ms *)stream;
189 int err = 0;
190
191 monitor_lock (ms->lock);
192 if (ms->ptr != MAP_FAILED)
193 {
194 /* Remap. */
195 if (ms->ptr && munmap (ms->ptr, ms->size) == 0)
196 {
197 if (ftruncate (ms->fd, len) == 0)
198 {
199 ms->ptr = (len) ?
200 mmap (0, len, ms->mflags, MAP_SHARED, ms->fd, 0) : NULL;
201 if (ms->ptr != MAP_FAILED)
202 {
203 ms->size = len;
204 }
205 else
206 err = errno;
207 }
208 else
209 err = errno;
210 }
211 }
212 monitor_unlock (ms->lock);
213 return err;
214 }
215
216 static int
217 _ms_get_size (stream_t stream, off_t *psize)
218 {
219 struct _ms *ms = (struct _ms *)stream;
220 struct stat stbuf;
221 int err = 0;
222
223 monitor_lock (ms->lock);
224 stbuf.st_size = 0;
225 if (ms->ptr != MAP_FAILED)
226 {
227 if (ms->ptr)
228 msync (ms->ptr, ms->size, MS_SYNC);
229
230 if (fstat(ms->fd, &stbuf) == 0)
231 {
232 /* Remap. */
233 if (ms->size != (size_t)stbuf.st_size)
234 {
235 if (ms->ptr && munmap (ms->ptr, ms->size) == 0)
236 {
237 if (ms->size)
238 {
239 ms->ptr = mmap (0, ms->size, ms->mflags , MAP_SHARED,
240 ms->fd, 0);
241 if (ms->ptr != MAP_FAILED)
242 ms->size = stbuf.st_size;
243 else
244 err = errno;
245 }
246 else
247 ms->ptr = NULL;
248 }
249 else
250 err = errno;
251 }
252 }
253 }
254 monitor_unlock (ms->lock);
255 if (psize)
256 *psize = stbuf.st_size;
257 return err;
258 }
259
260 static int
261 _ms_flush (stream_t stream)
262 {
263 int err = 0;
264 struct _ms *ms = (struct _ms *)stream;
265 monitor_lock (ms->lock);
266 if (ms->ptr != MAP_FAILED && ms->ptr != NULL)
267 err = msync (ms->ptr, ms->size, MS_SYNC);
268 monitor_unlock (ms->lock);
269 return 0;
270 }
271
272 static int
273 _ms_get_fd (stream_t stream, int *pfd)
274 {
275 struct _ms *ms = (struct _ms *)stream;
276 if (pfd)
277 *pfd = ms->fd;
278 return 0;
279 }
280
281 static int
282 _ms_get_flags (stream_t stream, int *flags)
283 {
284 struct _ms *ms = (struct _ms *)stream;
285 if (flags == NULL)
286 return MU_ERROR_INVALID_PARAMETER;
287 *flags = ms->flags;
288 return 0;
289 }
290
291 static int
292 _ms_get_state (stream_t stream, enum stream_state *state)
293 {
294 (void)stream;
295 if (state == NULL)
296 return MU_ERROR_INVALID_PARAMETER;
297 *state = MU_STREAM_NO_STATE;
298 return 0;
299 }
300
301 static int
302 _ms_seek (stream_t stream, off_t off, enum stream_whence whence)
303 {
304 struct _ms *ms = (struct _ms *)stream;
305 off_t noff = ms->offset;
306 int err = 0;
307 if (whence == MU_STREAM_WHENCE_SET)
308 noff = off;
309 else if (whence == MU_STREAM_WHENCE_CUR)
310 noff += off;
311 else if (whence == MU_STREAM_WHENCE_END)
312 noff = ms->size + off;
313 else
314 noff = -1; /* error. */
315 if (noff >= 0)
316 {
317 if (noff > ms->offset)
318 _ms_truncate (stream, noff);
319 ms->offset = noff;
320 }
321 else
322 err = MU_ERROR_INVALID_PARAMETER;
323 return err;
324 }
325
326 static int
327 _ms_tell (stream_t stream, off_t *off)
328 {
329 struct _ms *ms = (struct _ms *)stream;
330 if (off == NULL)
331 return MU_ERROR_INVALID_PARAMETER;
332 *off = ms->offset;
333 return 0;
334 }
335
336 static int
337 _ms_close (stream_t stream)
338 {
339 struct _ms *ms = (struct _ms *)stream;
340 int err = 0;
341 monitor_lock (ms->lock);
342 if (ms->ptr != MAP_FAILED)
343 {
344 if (ms->ptr && munmap (ms->ptr, ms->size) != 0)
345 err = errno;
346 ms->ptr = MAP_FAILED;
347 }
348 if (ms->fd != -1)
349 if (close (ms->fd) != 0)
350 err = errno;
351 ms->fd = -1;
352 monitor_unlock (ms->lock);
353 return err;
354 }
355
356 static int
357 _ms_open (stream_t stream, const char *filename, int port, int flags)
358 {
359 struct _ms *ms = (struct _ms *)stream;
360 int mflag, flg;
361 struct stat st;
362
363 (void)port; /* Ignored. */
364
365 /* Close any previous file. */
366 if (ms->ptr != MAP_FAILED)
367 {
368 if (ms->ptr)
369 munmap (ms->ptr, ms->size);
370 ms->ptr = MAP_FAILED;
371 }
372 if (ms->fd != -1)
373 {
374 close (ms->fd);
375 ms->fd = -1;
376 }
377 /* Map the flags to the system equivalent */
378 if ((flags & MU_STREAM_WRITE) && (flags & MU_STREAM_READ))
379 return EINVAL;
380 else if (flags & MU_STREAM_WRITE)
381 {
382 mflag = PROT_WRITE;
383 flg = O_WRONLY;
384 }
385 else if (flags & MU_STREAM_RDWR)
386 {
387 mflag = PROT_READ | PROT_WRITE;
388 flg = O_RDWR;
389 }
390 else if (flags & MU_STREAM_CREAT)
391 return ENOSYS;
392 else /* default */
393 {
394 mflag = PROT_READ;
395 flg = O_RDONLY;
396 }
397
398 ms->fd = open (filename, flg);
399 if (ms->fd < 0)
400 return errno;
401 if (fstat (ms->fd, &st) != 0)
402 {
403 int err = errno;
404 close (ms->fd);
405 return err;
406 }
407 ms->size = st.st_size;
408 if (ms->size)
409 {
410 ms->ptr = mmap (0, ms->size, mflag , MAP_SHARED, ms->fd, 0);
411 if (ms->ptr == MAP_FAILED)
412 {
413 int err = errno;
414 close (ms->fd);
415 ms->ptr = MAP_FAILED;
416 return err;
417 }
418 }
419 else
420 ms->ptr = NULL;
421 ms->mflags = mflag;
422 ms->flags = flags;
423 return 0;
424 }
425
426 static struct _stream_vtable _ms_vtable =
427 {
428 _ms_add_ref,
429 _ms_release,
430 _ms_destroy,
431
432 _ms_open,
433 _ms_close,
434
435 _ms_read,
436 _ms_readline,
437 _ms_write,
438
439 _ms_seek,
440 _ms_tell,
441
442 _ms_get_size,
443 _ms_truncate,
444 _ms_flush,
445
446 _ms_get_fd,
447 _ms_get_flags,
448 _ms_get_state,
449 };
450
451 #endif /* _POSIX_MAPPED_FILES */
452
453 int
454 stream_mapfile_create (stream_t *pstream)
455 {
456 #ifndef _POSIX_MAPPED_FILES
457 return ENOSYS;
458 #else
459 struct _ms *ms;
460
461 if (pstream == NULL)
462 return MU_ERROR_INVALID_PARAMETER;
463
464 ms = calloc (1, sizeof *ms);
465 if (ms == NULL)
466 return MU_ERROR_NO_MEMORY;
467
468 ms->base.vtable = &_ms_vtable;
469 ms->ref = 1;
470 ms->fd = -1;
471 ms->offset = -1;
472 ms->flags = 0;
473 ms->mflags = 0;
474 monitor_create (&(ms->lock));
475 *pstream = &ms->base;
476
477 return 0;
478 #endif /* _POSIX_MAPPED_FILES */
479 }
...@@ -25,20 +25,19 @@ ...@@ -25,20 +25,19 @@
25 #ifdef HAVE_STRINGS_H 25 #ifdef HAVE_STRINGS_H
26 #include <strings.h> 26 #include <strings.h>
27 #endif 27 #endif
28 #include <string.h>
29 #include <time.h> 28 #include <time.h>
30 #include <pwd.h> 29 #include <pwd.h>
31 #include <unistd.h> 30 #include <unistd.h>
31 #include <string.h>
32 32
33 #include <mailutils/mutil.h> 33 #include <mailutils/mutil.h>
34 34 #include <mailutils/list.h>
35 #ifdef HAVE_MYSQL 35 #include <mailutils/iterator.h>
36 #include "../MySql/MySql.h"
37 #endif
38 36
39 /* convert a sequence of hex characters into an integer */ 37 /* convert a sequence of hex characters into an integer */
40 38
41 unsigned long mu_hex2ul(char hex) 39 unsigned long
40 mu_hex2ul (char hex)
42 { 41 {
43 if (hex >= '0' && hex <= '9') 42 if (hex >= '0' && hex <= '9')
44 return hex - '0'; 43 return hex - '0';
...@@ -52,21 +51,22 @@ unsigned long mu_hex2ul(char hex) ...@@ -52,21 +51,22 @@ unsigned long mu_hex2ul(char hex)
52 return -1; 51 return -1;
53 } 52 }
54 53
55 size_t mu_hexstr2ul(unsigned long* ul, const char* hex, size_t len) 54 size_t
55 mu_hexstr2ul (unsigned long *ul, const char *hex, size_t len)
56 { 56 {
57 size_t r; 57 size_t r;
58 58
59 *ul = 0; 59 *ul = 0;
60 60
61 for (r = 0; r < len; r++) 61 for (r = 0; r < len; r++)
62 { 62 {
63 unsigned long v = mu_hex2ul(hex[r]); 63 unsigned long v = mu_hex2ul (hex[r]);
64 64
65 if (v == (unsigned long)-1) 65 if (v == (unsigned long)-1)
66 return r; 66 return r;
67 67
68 *ul = *ul * 16 + v; 68 *ul = *ul * 16 + v;
69 } 69 }
70 return r; 70 return r;
71 } 71 }
72 72
...@@ -86,18 +86,18 @@ mu_tm2time (struct tm *timeptr, mu_timezone* tz) ...@@ -86,18 +86,18 @@ mu_tm2time (struct tm *timeptr, mu_timezone* tz)
86 { 86 {
87 int offset = tz ? tz->utc_offset : 0; 87 int offset = tz ? tz->utc_offset : 0;
88 88
89 return mktime(timeptr) + mu_utc_offset() - offset; 89 return mktime (timeptr) + mu_utc_offset () - offset;
90 } 90 }
91 91
92 /* Convert time 0 at UTC to our localtime, that tells us the offset 92 /* Convert time 0 at UTC to our localtime, that tells us the offset
93 of our current timezone from UTC. */ 93 of our current timezone from UTC. */
94 time_t 94 time_t
95 mu_utc_offset(void) 95 mu_utc_offset (void)
96 { 96 {
97 time_t t = 0; 97 time_t t = 0;
98 struct tm* tm = gmtime(&t); 98 struct tm* tm = gmtime (&t);
99 99
100 return - mktime(tm); 100 return - mktime (tm);
101 } 101 }
102 102
103 static const char *months[] = 103 static const char *months[] =
...@@ -246,7 +246,6 @@ mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz) ...@@ -246,7 +246,6 @@ mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz)
246 return 0; 246 return 0;
247 } 247 }
248 248
249
250 char * 249 char *
251 mu_get_homedir (void) 250 mu_get_homedir (void)
252 { 251 {
...@@ -255,7 +254,7 @@ mu_get_homedir (void) ...@@ -255,7 +254,7 @@ mu_get_homedir (void)
255 { 254 {
256 struct passwd *pwd; 255 struct passwd *pwd;
257 256
258 pwd = getpwuid(getuid()); 257 pwd = getpwuid (getuid ());
259 if (!pwd) 258 if (!pwd)
260 return NULL; 259 return NULL;
261 homedir = pwd->pw_dir; 260 homedir = pwd->pw_dir;
...@@ -298,11 +297,7 @@ mu_tilde_expansion (const char *ref, const char *delim, const char *homedir) ...@@ -298,11 +297,7 @@ mu_tilde_expansion (const char *ref, const char *delim, const char *homedir)
298 name = calloc (s - p + 1, 1); 297 name = calloc (s - p + 1, 1);
299 memcpy (name, p, s - p); 298 memcpy (name, p, s - p);
300 name [s - p] = '\0'; 299 name [s - p] = '\0';
301 pw = getpwnam (name); 300 pw = mu_getpwnam (name);
302 #ifdef HAVE_MYSQL
303 if (!pw)
304 pw = getMpwnam(name);
305 #endif /* HAVE_MYSQL */
306 free (name); 301 free (name);
307 if (pw) 302 if (pw)
308 { 303 {
...@@ -333,3 +328,80 @@ util_cpystr (char *dst, const char *src, size_t size) ...@@ -333,3 +328,80 @@ util_cpystr (char *dst, const char *src, size_t size)
333 dst[len] = '\0'; 328 dst[len] = '\0';
334 return len; 329 return len;
335 } 330 }
331
332 static list_t _app_getpwnam = NULL;
333
334 void
335 mu_register_getpwnam (struct passwd *(*fun) __P((const char *)))
336 {
337 if (!_app_getpwnam && list_create (&_app_getpwnam))
338 return;
339 list_append (_app_getpwnam, fun);
340 }
341
342 struct passwd *
343 mu_getpwnam (const char *name)
344 {
345 struct passwd *p;
346 iterator_t itr;
347
348 p = getpwnam (name);
349
350 if (!p && iterator_create (&itr, _app_getpwnam) == 0)
351 {
352 struct passwd *(*fun) __P((const char *));
353 for (iterator_first (itr); !p && !iterator_is_done (itr);
354 iterator_next (itr))
355 {
356 iterator_current (itr, (void **)&fun);
357 p = (*fun) (name);
358 }
359
360 iterator_destroy (&itr);
361 }
362 return p;
363 }
364
365 int mu_virtual_domain;
366
367 #ifdef USE_VIRTUAL_DOMAINS
368
369 struct passwd *
370 getpwnam_virtual (const char *u)
371 {
372 struct passwd *pw = NULL;
373 FILE *pfile;
374 size_t i = 0, len = strlen (u), delim = 0;
375 char *filename;
376
377 mu_virtual_domain = 0;
378 for (i = 0; i < len && delim == 0; i++)
379 if (u[i] == '!' || u[i] == ':' || u[i] == '@')
380 delim = i;
381
382 if (delim == 0)
383 return NULL;
384
385 filename = malloc (strlen (SITE_VIRTUAL_PWDDIR) +
386 strlen (&u[delim + 1]) + 2 /* slash and null byte */);
387 if (filename == NULL)
388 return NULL;
389
390 sprintf (filename, "%s/%s", SITE_VIRTUAL_PWDDIR, &u[delim + 1]);
391 pfile = fopen (filename, "r");
392 free (filename);
393
394 if (pfile)
395 while ((pw = fgetpwent (pfile)) != NULL)
396 {
397 if (strlen (pw->pw_name) == delim && !strncmp (u, pw->pw_name, delim))
398 {
399 mu_virtual_domain = 1;
400 break;
401 }
402 }
403
404 return pw;
405 }
406
407 #endif
......
...@@ -10,6 +10,7 @@ lib_LTLIBRARIES = libpop3.la ...@@ -10,6 +10,7 @@ lib_LTLIBRARIES = libpop3.la
10 libmailbox_la_SOURCES = \ 10 libmailbox_la_SOURCES = \
11 pop3_apop.c \ 11 pop3_apop.c \
12 pop3_capa.c \ 12 pop3_capa.c \
13 pop3_carrier.c \
13 pop3_cleanup.c \ 14 pop3_cleanup.c \
14 pop3_connect.c \ 15 pop3_connect.c \
15 pop3_create.c \ 16 pop3_create.c \
......
...@@ -29,12 +29,16 @@ ...@@ -29,12 +29,16 @@
29 APOP name digest 29 APOP name digest
30 a string identifying a mailbox and a MD5 digest string (both required) 30 a string identifying a mailbox and a MD5 digest string (both required)
31 */ 31 */
32 static int 32 int
33 pop3_apop0 (pop3_t pop3, const char *user, const char *secret) 33 pop3_apop (pop3_t pop3, const char *user, const char *secret)
34 { 34 {
35 int status; 35 int status;
36 36
37 /* The server did not offer a time stamp in the greeting, bailout early. */ 37 /* Sanity checks. */
38 if (pop3 == NULL || user == NULL || secret == NULL)
39 return MU_ERROR_INVALID_PARAMETER;
40
41 /* The server did not offer a timestamp in the greeting, bailout early. */
38 if (pop3->timestamp == NULL) 42 if (pop3->timestamp == NULL)
39 return MU_ERROR_NOT_SUPPORTED; 43 return MU_ERROR_NOT_SUPPORTED;
40 44
...@@ -49,9 +53,6 @@ pop3_apop0 (pop3_t pop3, const char *user, const char *secret) ...@@ -49,9 +53,6 @@ pop3_apop0 (pop3_t pop3, const char *user, const char *secret)
49 char *tmp; 53 char *tmp;
50 size_t n; 54 size_t n;
51 55
52 if (user == NULL || secret == NULL)
53 return MU_ERROR_INVALID_PARAMETER;
54
55 MD5Init (&md5context); 56 MD5Init (&md5context);
56 MD5Update (&md5context, (unsigned char *)pop3->timestamp, 57 MD5Update (&md5context, (unsigned char *)pop3->timestamp,
57 strlen (pop3->timestamp)); 58 strlen (pop3->timestamp));
...@@ -90,19 +91,3 @@ pop3_apop0 (pop3_t pop3, const char *user, const char *secret) ...@@ -90,19 +91,3 @@ pop3_apop0 (pop3_t pop3, const char *user, const char *secret)
90 91
91 return status; 92 return status;
92 } 93 }
93
94 int
95 pop3_apop (pop3_t pop3, const char *user, const char *secret)
96 {
97 int status;
98
99 if (pop3 == NULL)
100 return MU_ERROR_INVALID_PARAMETER;
101
102 monitor_lock (pop3->lock);
103 monitor_cleanup_push (pop3_cleanup, pop3);
104 status = pop3_apop0 (pop3, user, secret);
105 monitor_unlock (pop3->lock);
106 monitor_cleanup_pop (0);
107 return status;
108 }
......
...@@ -24,11 +24,14 @@ ...@@ -24,11 +24,14 @@
24 #include <stddef.h> 24 #include <stddef.h>
25 #include <mailutils/sys/pop3.h> 25 #include <mailutils/sys/pop3.h>
26 26
27 static int 27 int
28 pop3_capa0 (pop3_t pop3, iterator_t *piterator) 28 pop3_capa (pop3_t pop3, iterator_t *piterator)
29 { 29 {
30 int status; 30 int status;
31 31
32 if (pop3 == NULL || piterator == NULL)
33 return MU_ERROR_INVALID_PARAMETER;
34
32 switch (pop3->state) 35 switch (pop3->state)
33 { 36 {
34 case POP3_NO_STATE: 37 case POP3_NO_STATE:
...@@ -64,19 +67,3 @@ pop3_capa0 (pop3_t pop3, iterator_t *piterator) ...@@ -64,19 +67,3 @@ pop3_capa0 (pop3_t pop3, iterator_t *piterator)
64 67
65 return status; 68 return status;
66 } 69 }
67
68 int
69 pop3_capa (pop3_t pop3, iterator_t *piterator)
70 {
71 int status;
72
73 if (pop3 == NULL || piterator == NULL)
74 return MU_ERROR_INVALID_PARAMETER;
75
76 monitor_lock (pop3->lock);
77 monitor_cleanup_push (pop3_cleanup, pop3);
78 status = pop3_capa0 (pop3, piterator);
79 monitor_unlock (pop3->lock);
80 monitor_cleanup_pop (0);
81 return status;
82 }
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <string.h>
23 #ifdef HAVE_STRINGS_H
24 # include <strings.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <mailutils/sys/pop3.h>
29
30 int
31 pop3_set_carrier (pop3_t pop3, stream_t carrier)
32 {
33 /* Sanity checks. */
34 if (pop3 == NULL)
35 return MU_ERROR_INVALID_PARAMETER;
36
37 if (pop3->carrier)
38 {
39 stream_close (pop3->carrier);
40 stream_release (pop3->carrier);
41 }
42 pop3->carrier = carrier;
43 return 0;
44 }
45
46 int
47 pop3_get_carrier (pop3_t pop3, stream_t *pcarrier)
48 {
49 /* Sanity checks. */
50 if (pop3 == NULL || pcarrier == NULL)
51 return MU_ERROR_INVALID_PARAMETER;
52
53 if (pop3->carrier == NULL)
54 {
55 stream_t carrier = NULL;
56 int status = stream_tcp_create (&carrier);
57 if (status != 0)
58 return status;
59 status = stream_buffer_create (&(pop3->carrier), carrier, 1024);
60 if (status != 0)
61 {
62 stream_release (carrier);
63 return status;
64 }
65 }
66 /* Incremente the ref count, since we are exposing it. */
67 stream_add_ref (pop3->carrier);
68 *pcarrier = pop3->carrier;
69 return 0;
70 }
...@@ -33,11 +33,15 @@ static int pop3_sleep (int seconds); ...@@ -33,11 +33,15 @@ static int pop3_sleep (int seconds);
33 33
34 /* Open the connection to the server. The server sends an affirmative greeting 34 /* Open the connection to the server. The server sends an affirmative greeting
35 that may contain a timestamp for APOP. */ 35 that may contain a timestamp for APOP. */
36 static int 36 int
37 pop3_connect0 (pop3_t pop3, const char *host, unsigned int port) 37 pop3_connect (pop3_t pop3, const char *host, unsigned int port)
38 { 38 {
39 int status; 39 int status;
40 40
41 /* Sanity checks. */
42 if (pop3 == NULL || host == NULL)
43 return MU_ERROR_INVALID_PARAMETER;
44
41 /* Default is 110. */ 45 /* Default is 110. */
42 if (!port) 46 if (!port)
43 port = 110; 47 port = 110;
...@@ -46,15 +50,18 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port) ...@@ -46,15 +50,18 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
46 switch (pop3->state) 50 switch (pop3->state)
47 { 51 {
48 default: 52 default:
49 /* __Fallthrough__, they want to clear an error. */ 53 /* FALLTHROUGH */
54 /* If pop3 was in an error state going through here should clear it. */
55
50 case POP3_NO_STATE: 56 case POP3_NO_STATE:
51 /* Create the networking stack. */ 57 /* Create the networking stack. */
52 if (pop3->stream == NULL) 58 if (pop3->carrier == NULL)
53 { 59 {
54 status = stream_tcp_create (&(pop3->stream)); 60 stream_t carrier;
61 status = pop3_get_carrier (pop3, &carrier);
55 POP3_CHECK_ERROR (pop3, status); 62 POP3_CHECK_ERROR (pop3, status);
56 /* Using the awkward stream_t buffering. */ 63 /* A add_ref was done part of pop3_get_carrier(). */
57 /*stream_setbufsiz (pop3->stream, 1024); */ 64 stream_release (carrier);
58 } 65 }
59 else 66 else
60 { 67 {
...@@ -65,8 +72,8 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port) ...@@ -65,8 +72,8 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
65 to read a new message, closing the connection and immediately 72 to read a new message, closing the connection and immediately
66 contacting the server again, and he'll end up having 73 contacting the server again, and he'll end up having
67 "-ERR Mail Lock busy" or something similar. To prevent this race 74 "-ERR Mail Lock busy" or something similar. To prevent this race
68 condition we sleep 2 seconds. This really obvious for in 75 condition we sleep 2 seconds. This is really obvious for in
69 environment where QPopper is use, the user as a big mailbox. */ 76 environment where QPopper is use and the user as a big mailbox. */
70 pop3_disconnect (pop3); 77 pop3_disconnect (pop3);
71 pop3_sleep (2); 78 pop3_sleep (2);
72 } 79 }
...@@ -74,7 +81,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port) ...@@ -74,7 +81,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
74 81
75 case POP3_CONNECT: 82 case POP3_CONNECT:
76 /* Establish the connection. */ 83 /* Establish the connection. */
77 status = stream_open (pop3->stream, host, port, 84 status = stream_open (pop3->carrier, host, port,
78 MU_STREAM_READ|MU_STREAM_WRITE); 85 MU_STREAM_READ|MU_STREAM_WRITE);
79 POP3_CHECK_EAGAIN (pop3, status); 86 POP3_CHECK_EAGAIN (pop3, status);
80 pop3->acknowledge = 0; 87 pop3->acknowledge = 0;
...@@ -89,7 +96,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port) ...@@ -89,7 +96,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
89 POP3_CHECK_EAGAIN (pop3, status); 96 POP3_CHECK_EAGAIN (pop3, status);
90 if (strncasecmp (pop3->ack.buf, "+OK", 3) != 0) 97 if (strncasecmp (pop3->ack.buf, "+OK", 3) != 0)
91 { 98 {
92 stream_close (pop3->stream); 99 stream_close (pop3->carrier);
93 pop3->state = POP3_NO_STATE; 100 pop3->state = POP3_NO_STATE;
94 return MU_ERROR_OPERATION_DENIED; 101 return MU_ERROR_OPERATION_DENIED;
95 } 102 }
...@@ -106,7 +113,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port) ...@@ -106,7 +113,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
106 pop3->timestamp = calloc (len + 1, 1); 113 pop3->timestamp = calloc (len + 1, 1);
107 if (pop3->timestamp == NULL) 114 if (pop3->timestamp == NULL)
108 { 115 {
109 stream_close (pop3->stream); 116 stream_close (pop3->carrier);
110 POP3_CHECK_ERROR (pop3, MU_ERROR_NO_MEMORY); 117 POP3_CHECK_ERROR (pop3, MU_ERROR_NO_MEMORY);
111 } 118 }
112 /* Do not copy the surrounding '<>'. */ 119 /* Do not copy the surrounding '<>'. */
...@@ -130,21 +137,3 @@ pop3_sleep (int seconds) ...@@ -130,21 +137,3 @@ pop3_sleep (int seconds)
130 tval.tv_usec = 0; 137 tval.tv_usec = 0;
131 return select (1, NULL, NULL, NULL, &tval); 138 return select (1, NULL, NULL, NULL, &tval);
132 } 139 }
133
134 int
135 pop3_connect (pop3_t pop3, const char *host, unsigned int port)
136 {
137 int status;
138
139 /* Sanity checks. */
140 if (pop3 == NULL || host == NULL)
141 return MU_ERROR_INVALID_PARAMETER;
142
143 monitor_lock (pop3->lock);
144 monitor_cleanup_push (pop3_cleanup, pop3);
145 status = pop3_connect0 (pop3, host, port);
146 monitor_unlock (pop3->lock);
147 monitor_cleanup_pop (0);
148 return status;
149
150 }
......
...@@ -24,11 +24,13 @@ ...@@ -24,11 +24,13 @@
24 #include <mailutils/sys/pop3.h> 24 #include <mailutils/sys/pop3.h>
25 25
26 /* Initialise a pop3_t handle. */ 26 /* Initialise a pop3_t handle. */
27
27 int 28 int
28 pop3_create (pop3_t *ppop3) 29 pop3_create (pop3_t *ppop3)
29 { 30 {
30 pop3_t pop3; 31 pop3_t pop3;
31 32
33 /* Sanity check. */
32 if (ppop3 == NULL) 34 if (ppop3 == NULL)
33 return MU_ERROR_INVALID_PARAMETER; 35 return MU_ERROR_INVALID_PARAMETER;
34 36
...@@ -36,32 +38,33 @@ pop3_create (pop3_t *ppop3) ...@@ -36,32 +38,33 @@ pop3_create (pop3_t *ppop3)
36 if (pop3 == NULL) 38 if (pop3 == NULL)
37 return MU_ERROR_NO_MEMORY; 39 return MU_ERROR_NO_MEMORY;
38 40
41 /* Reserve space for the ack(nowledgement) response. */
39 /* According to RFC 2449: The maximum length of the first line of a 42 /* According to RFC 2449: The maximum length of the first line of a
40 command response (including the initial greeting) is unchanged at 43 command response (including the initial greeting) is unchanged at
41 512 octets (including the terminating CRLF). */ 44 512 octets (including the terminating CRLF). */
42 pop3->ack.len = 512; 45 pop3->ack.len = 512;
43 pop3->ack.ptr = pop3->ack.buf = calloc (pop3->ack.len, 1); 46 pop3->ack.buf = calloc (pop3->ack.len, 1);
44 if (pop3->ack.buf == NULL) 47 if (pop3->ack.buf == NULL)
45 { 48 {
46 pop3_destroy (pop3); 49 pop3_destroy (pop3);
47 return MU_ERROR_NO_MEMORY; 50 return MU_ERROR_NO_MEMORY;
48 } 51 }
52 pop3->ack.ptr = pop3->ack.buf;
49 53
50 /* RFC 2449 recommands 255, but we grow it as needed. */ 54 /* RFC 2449 recommands 255, but we grow it as needed. */
51 pop3->io.len = 255; 55 pop3->io.len = 255;
52 pop3->io.ptr = pop3->io.buf = calloc (pop3->io.len, 1); 56 pop3->io.buf = calloc (pop3->io.len, 1);
53 if (pop3->io.buf == NULL) 57 if (pop3->io.buf == NULL)
54 { 58 {
55 pop3_destroy (pop3); 59 pop3_destroy (pop3);
56 return MU_ERROR_NO_MEMORY; 60 return MU_ERROR_NO_MEMORY;
57 } 61 }
62 pop3->io.ptr = pop3->io.buf;
58 63
59 pop3->state = POP3_NO_STATE; /* Init with no state. */ 64 pop3->state = POP3_NO_STATE; /* Init with no state. */
60 pop3->timeout = 10 * 60; /* The default Timeout is 10 minutes. */ 65 pop3->timeout = (10 * 60) * 100; /* The default Timeout is 10 minutes. */
61 pop3->acknowledge = 0; /* No Ack received. */ 66 pop3->acknowledge = 0; /* No Ack received. */
62 67
63 monitor_create (&(pop3->lock));
64
65 *ppop3 = pop3; 68 *ppop3 = pop3;
66 return 0; /* Okdoke. */ 69 return 0; /* Okdoke. */
67 } 70 }
......
...@@ -26,11 +26,14 @@ ...@@ -26,11 +26,14 @@
26 26
27 #include <mailutils/sys/pop3.h> 27 #include <mailutils/sys/pop3.h>
28 28
29 static int 29 int
30 pop3_dele0 (pop3_t pop3, unsigned msgno) 30 pop3_dele (pop3_t pop3, unsigned msgno)
31 { 31 {
32 int status; 32 int status;
33 33
34 if (pop3 == NULL || msgno == 0)
35 return MU_ERROR_INVALID_PARAMETER;
36
34 switch (pop3->state) 37 switch (pop3->state)
35 { 38 {
36 case POP3_NO_STATE: 39 case POP3_NO_STATE:
...@@ -61,19 +64,3 @@ pop3_dele0 (pop3_t pop3, unsigned msgno) ...@@ -61,19 +64,3 @@ pop3_dele0 (pop3_t pop3, unsigned msgno)
61 } 64 }
62 return status; 65 return status;
63 } 66 }
64
65 int
66 pop3_dele (pop3_t pop3, unsigned msgno)
67 {
68 int status;
69
70 if (pop3 == NULL || msgno == 0)
71 return MU_ERROR_INVALID_PARAMETER;
72
73 monitor_lock (pop3->lock);
74 monitor_cleanup_push (pop3_cleanup, pop3);
75 status = pop3_dele0 (pop3, msgno);
76 monitor_unlock (pop3->lock);
77 monitor_cleanup_pop (0);
78 return status;
79 }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 #include <mailutils/sys/pop3.h> 23 #include <mailutils/sys/pop3.h>
24 #include <stdlib.h> 24 #include <stdlib.h>
25 25
26 void 26 int
27 pop3_destroy (pop3_t pop3) 27 pop3_destroy (pop3_t pop3)
28 { 28 {
29 if (pop3) 29 if (pop3)
...@@ -37,8 +37,7 @@ pop3_destroy (pop3_t pop3) ...@@ -37,8 +37,7 @@ pop3_destroy (pop3_t pop3)
37 if (pop3->timestamp) 37 if (pop3->timestamp)
38 free (pop3->timestamp); 38 free (pop3->timestamp);
39 39
40 monitor_destroy (pop3->lock);
41
42 free (pop3); 40 free (pop3);
43 } 41 }
42 return 0;
44 } 43 }
......
...@@ -23,10 +23,14 @@ ...@@ -23,10 +23,14 @@
23 #include <stdlib.h> 23 #include <stdlib.h>
24 #include <string.h> 24 #include <string.h>
25 25
26 /* Sudden death. */ 26 int
27 static int 27 pop3_disconnect (pop3_t pop3)
28 pop3_disconnect0 (pop3_t pop3)
29 { 28 {
29
30 /* Sanity checks. */
31 if (pop3 == NULL)
32 return MU_ERROR_INVALID_PARAMETER;
33
30 /* We can keep some of the fields, if they decide to pop3_open() again but 34 /* We can keep some of the fields, if they decide to pop3_open() again but
31 clear the states. */ 35 clear the states. */
32 pop3->state = POP3_NO_STATE; 36 pop3->state = POP3_NO_STATE;
...@@ -40,24 +44,7 @@ pop3_disconnect0 (pop3_t pop3) ...@@ -40,24 +44,7 @@ pop3_disconnect0 (pop3_t pop3)
40 free (pop3->timestamp); 44 free (pop3->timestamp);
41 pop3->timestamp = NULL; 45 pop3->timestamp = NULL;
42 } 46 }
43 if (pop3->stream) 47 if (pop3->carrier)
44 return stream_close (pop3->stream); 48 return stream_close (pop3->carrier);
45 return 0; 49 return 0;
46 } 50 }
47
48 int
49 pop3_disconnect (pop3_t pop3)
50 {
51 int status;
52
53 /* Sanity checks. */
54 if (pop3 == NULL)
55 return MU_ERROR_INVALID_PARAMETER;
56
57 monitor_lock (pop3->lock);
58 monitor_cleanup_push (pop3_cleanup, pop3);
59 status = pop3_disconnect0 (pop3);
60 monitor_unlock (pop3->lock);
61 monitor_cleanup_pop (0);
62 return status;
63 }
......
...@@ -123,7 +123,6 @@ p_destroy (iterator_t iterator) ...@@ -123,7 +123,6 @@ p_destroy (iterator_t iterator)
123 return 0; 123 return 0;
124 } 124 }
125 125
126
127 static int 126 static int
128 p_first (iterator_t iterator) 127 p_first (iterator_t iterator)
129 { 128 {
...@@ -149,108 +148,20 @@ p_next (iterator_t iterator) ...@@ -149,108 +148,20 @@ p_next (iterator_t iterator)
149 { 148 {
150 if (n) 149 if (n)
151 { 150 {
152 switch (p_iterator->pop3->state) 151 char *buf;
152 buf = calloc (n + 1, 1);
153 if (buf)
153 { 154 {
154 case POP3_CAPA_RX: 155 /* Consume. */
155 { 156 pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
156 char *buf; 157 if (buf[n - 1] == '\n')
157 buf = calloc (n + 1, 1); 158 buf[n - 1] = '\0';
158 if (buf) 159 if (p_iterator->item)
159 { 160 free (p_iterator->item);
160 /* Consume. */ 161 p_iterator->item = buf;
161 pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
162 if (buf[n - 1] == '\n')
163 buf[n - 1] = '\0';
164 if (p_iterator->item)
165 free (p_iterator->item);
166 p_iterator->item = buf;
167 }
168 else
169 status = MU_ERROR_NO_MEMORY;
170 break;
171 }
172
173 case POP3_UIDL_RX:
174 {
175 struct pop3_uidl_item *pitem;
176 char *buf = calloc (n + 1, 1);
177 if (buf)
178 {
179 if (p_iterator->item)
180 {
181 pitem = p_iterator->item;
182 if (pitem->uidl)
183 free (pitem->uidl);
184 free (pitem);
185 }
186 p_iterator->item = calloc (1, sizeof *pitem);
187 pitem = p_iterator->item;
188 if (pitem)
189 {
190 unsigned msgno;
191 char *space;
192 /* Consume. */
193 pop3_readline (p_iterator->pop3, buf,
194 n + 1, NULL);
195 msgno = 0;
196 /* The format is:
197 msgno uidlsttring */
198 space = strchr (buf, ' ');
199 if (space)
200 {
201 *space++ = '\0';
202 msgno = strtoul (buf, NULL, 10);
203 }
204 if (space && space[strlen (space) - 1] == '\n')
205 space[strlen (space) - 1] = '\0';
206 if (space == NULL)
207 space = (char *)"";
208 pitem->msgno = msgno;
209 pitem->uidl = strdup (space);
210 }
211 else
212 status = MU_ERROR_NO_MEMORY;
213 free (buf);
214 }
215 else
216 status = MU_ERROR_NO_MEMORY;
217 break;
218 }
219
220 case POP3_LIST_RX:
221 {
222 struct pop3_list_item *pitem;
223 char *buf = calloc (n + 1, 1);
224
225 if (buf)
226 {
227 if (p_iterator->item)
228 free (p_iterator->item);
229 pitem = calloc (1, sizeof *pitem);
230 p_iterator->item = pitem;
231 if (pitem)
232 {
233 unsigned msgno;
234 size_t size;
235 /* Consume. */
236 pop3_readline (p_iterator->pop3, buf,
237 n + 1, NULL);
238 size = msgno = 0;
239 sscanf (buf, "%d %d", &msgno, &size);
240 pitem->msgno = msgno;
241 pitem->size = size;
242 }
243 else
244 status = MU_ERROR_NO_MEMORY;
245 free (buf);
246 }
247 else
248 status = MU_ERROR_NO_MEMORY;
249 break;
250 }
251
252 default:
253 } 162 }
163 else
164 status = MU_ERROR_NO_MEMORY;
254 } 165 }
255 else 166 else
256 { 167 {
...@@ -287,21 +198,9 @@ p_current (iterator_t iterator, void *item) ...@@ -287,21 +198,9 @@ p_current (iterator_t iterator, void *item)
287 monitor_lock (p_iterator->lock); 198 monitor_lock (p_iterator->lock);
288 if (item) 199 if (item)
289 { 200 {
290 switch (p_iterator->pop3->state) 201 *((char **)item) = p_iterator->item;
291 { 202 p_iterator->item = NULL;
292 case POP3_CAPA_RX:
293 case POP3_UIDL_RX:
294 *((char **)item) = p_iterator->item;
295 break;
296
297 case POP3_LIST_RX:
298 *((struct pop3_list_item **)item) = p_iterator->item;
299 break;
300
301 default:
302 }
303 } 203 }
304 p_iterator->item = NULL;
305 monitor_unlock (p_iterator->lock); 204 monitor_unlock (p_iterator->lock);
306 } 205 }
307 return 0; 206 return 0;
......
...@@ -28,11 +28,14 @@ ...@@ -28,11 +28,14 @@
28 #include <stdio.h> 28 #include <stdio.h>
29 #include <mailutils/sys/pop3.h> 29 #include <mailutils/sys/pop3.h>
30 30
31 static int 31 int
32 pop3_list0 (pop3_t pop3, unsigned msgno, size_t *psize) 32 pop3_list (pop3_t pop3, unsigned int msgno, size_t *psize)
33 { 33 {
34 int status; 34 int status;
35 35
36 if (pop3 == NULL || msgno == 0 || psize == NULL)
37 return MU_ERROR_INVALID_PARAMETER;
38
36 switch (pop3->state) 39 switch (pop3->state)
37 { 40 {
38 case POP3_NO_STATE: 41 case POP3_NO_STATE:
...@@ -70,18 +73,3 @@ pop3_list0 (pop3_t pop3, unsigned msgno, size_t *psize) ...@@ -70,18 +73,3 @@ pop3_list0 (pop3_t pop3, unsigned msgno, size_t *psize)
70 73
71 return status; 74 return status;
72 } 75 }
73
74 int
75 pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
76 {
77 int status;
78 if (pop3 == NULL)
79 return MU_ERROR_INVALID_PARAMETER;
80
81 monitor_lock (pop3->lock);
82 monitor_cleanup_push (pop3_cleanup, pop3);
83 status = pop3_list0 (pop3, msgno, psize);
84 monitor_unlock (pop3->lock);
85 monitor_cleanup_pop (0);
86 return status;
87 }
......
...@@ -25,19 +25,21 @@ ...@@ -25,19 +25,21 @@
25 # include <strings.h> 25 # include <strings.h>
26 #endif 26 #endif
27 27
28 #include <stdio.h>
28 #include <stdlib.h> 29 #include <stdlib.h>
29 #include <mailutils/sys/pop3.h> 30 #include <mailutils/sys/pop3.h>
30 31
31 static int 32 int
32 pop3_list_all0 (pop3_t pop3, iterator_t *piterator) 33 pop3_list_all (pop3_t pop3, iterator_t *piterator)
33 { 34 {
34 int status; 35 int status;
35 36
37 if (pop3 == NULL || piterator == NULL)
38 return MU_ERROR_INVALID_PARAMETER;
39
36 switch (pop3->state) 40 switch (pop3->state)
37 { 41 {
38 case POP3_NO_STATE: 42 case POP3_NO_STATE:
39 if (piterator == NULL)
40 return MU_ERROR_INVALID_PARAMETER;
41 status = pop3_writeline (pop3, "LIST\r\n"); 43 status = pop3_writeline (pop3, "LIST\r\n");
42 POP3_CHECK_ERROR (pop3, status); 44 POP3_CHECK_ERROR (pop3, status);
43 pop3->state = POP3_LIST; 45 pop3->state = POP3_LIST;
...@@ -72,17 +74,21 @@ pop3_list_all0 (pop3_t pop3, iterator_t *piterator) ...@@ -72,17 +74,21 @@ pop3_list_all0 (pop3_t pop3, iterator_t *piterator)
72 } 74 }
73 75
74 int 76 int
75 pop3_list_all (pop3_t pop3, iterator_t *piterator) 77 pop3_list_current (iterator_t iterator, unsigned int *pno, size_t *plen)
76 { 78 {
77 int status; 79 char *buf;
78 80 int status = iterator_current (iterator, (void *)&buf);
79 if (pop3 == NULL) 81 if (status == 0)
80 return MU_ERROR_INVALID_PARAMETER; 82 {
81 83 size_t size;
82 monitor_lock (pop3->lock); 84 unsigned int msgno;
83 monitor_cleanup_push (pop3_cleanup, pop3); 85 size = msgno = 0;
84 status = pop3_list_all0 (pop3, piterator); 86 sscanf (buf, "%d %d", &msgno, &size);
85 monitor_unlock (pop3->lock); 87 if (pno)
86 monitor_cleanup_pop (0); 88 *pno = msgno;
89 if (plen)
90 *plen = size;
91 free (buf);
92 }
87 return status; 93 return status;
88 } 94 }
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_noop0 (pop3_t pop3) 31 pop3_noop (pop3_t pop3)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
35 switch (pop3->state) 38 switch (pop3->state)
36 { 39 {
37 case POP3_NO_STATE: 40 case POP3_NO_STATE:
...@@ -63,20 +66,3 @@ pop3_noop0 (pop3_t pop3) ...@@ -63,20 +66,3 @@ pop3_noop0 (pop3_t pop3)
63 66
64 return status; 67 return status;
65 } 68 }
66
67
68 int
69 pop3_noop (pop3_t pop3)
70 {
71 int status;
72
73 if (pop3 == NULL)
74 return MU_ERROR_INVALID_PARAMETER;
75
76 monitor_lock (pop3->lock);
77 monitor_cleanup_push (pop3_cleanup, pop3);
78 status = pop3_noop0 (pop3);
79 monitor_unlock (pop3->lock);
80 monitor_cleanup_pop (0);
81 return status;
82 }
......
...@@ -27,16 +27,17 @@ ...@@ -27,16 +27,17 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_pass0 (pop3_t pop3, const char *passwd) 31 pop3_pass (pop3_t pop3, const char *passwd)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL || passwd == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
35 switch (pop3->state) 38 switch (pop3->state)
36 { 39 {
37 case POP3_NO_STATE: 40 case POP3_NO_STATE:
38 if (passwd == NULL)
39 return MU_ERROR_INVALID_PARAMETER;
40 status = pop3_writeline (pop3, "PASS %s\r\n", passwd); 41 status = pop3_writeline (pop3, "PASS %s\r\n", passwd);
41 POP3_CHECK_ERROR (pop3, status); 42 POP3_CHECK_ERROR (pop3, status);
42 pop3->state = POP3_PASS; 43 pop3->state = POP3_PASS;
...@@ -65,19 +66,3 @@ pop3_pass0 (pop3_t pop3, const char *passwd) ...@@ -65,19 +66,3 @@ pop3_pass0 (pop3_t pop3, const char *passwd)
65 66
66 return status; 67 return status;
67 } 68 }
68
69 int
70 pop3_pass (pop3_t pop3, const char *passwd)
71 {
72 int status;
73
74 if (pop3 == NULL)
75 return MU_ERROR_INVALID_PARAMETER;
76
77 monitor_lock (pop3->lock);
78 monitor_cleanup_push (pop3_cleanup, pop3);
79 status = pop3_pass0 (pop3, passwd);
80 monitor_unlock (pop3->lock);
81 monitor_cleanup_pop (0);
82 return status;
83 }
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_quit0 (pop3_t pop3) 31 pop3_quit (pop3_t pop3)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
35 switch (pop3->state) 38 switch (pop3->state)
36 { 39 {
37 case POP3_NO_STATE: 40 case POP3_NO_STATE:
...@@ -58,19 +61,3 @@ pop3_quit0 (pop3_t pop3) ...@@ -58,19 +61,3 @@ pop3_quit0 (pop3_t pop3)
58 61
59 return status; 62 return status;
60 } 63 }
61
62 int
63 pop3_quit (pop3_t pop3)
64 {
65 int status;
66
67 if (pop3 == NULL)
68 return MU_ERROR_INVALID_PARAMETER;
69
70 monitor_lock (pop3->lock);
71 monitor_cleanup_push (pop3_cleanup, pop3);
72 status = pop3_quit0 (pop3);
73 monitor_unlock (pop3->lock);
74 monitor_cleanup_pop (0);
75 return status;
76 }
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
19 # include <config.h> 19 # include <config.h>
20 #endif 20 #endif
21 21
22 #include <stdio.h>
22 #include <stdlib.h> 23 #include <stdlib.h>
23 #include <string.h> 24 #include <string.h>
24 #include <sys/time.h>
25 #include <sys/types.h> 25 #include <sys/types.h>
26 #include <unistd.h> 26 #include <unistd.h>
27 #include <mailutils/sys/pop3.h> 27 #include <mailutils/sys/pop3.h>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
29 29
30 /* Read a complete line from the pop server. Transform CRLF to LF, remove 30 /* Read a complete line from the pop server. Transform CRLF to LF, remove
31 the stuff byte termination octet ".", put a null in the buffer 31 the stuff byte termination octet ".", put a null in the buffer
32 when done. */ 32 when done. And Do a select() (stream_is_readready()) for the timeout. */
33 static int 33 static int
34 pop3_getline (pop3_t pop3) 34 pop3_getline (pop3_t pop3)
35 { 35 {
...@@ -44,38 +44,12 @@ pop3_getline (pop3_t pop3) ...@@ -44,38 +44,12 @@ pop3_getline (pop3_t pop3)
44 since on linux tv is modified when error. */ 44 since on linux tv is modified when error. */
45 if (pop3->timeout) 45 if (pop3->timeout)
46 { 46 {
47 /* Heavy hand but continue if select trip on a signal. */ 47 int ready = stream_is_readready (pop3->carrier, pop3->timeout);
48 for (;;) 48 if (ready == 0)
49 { 49 return MU_ERROR_TIMEOUT;
50 int fd = -1;
51 struct timeval tv;
52 fd_set rfds;
53
54 status = stream_get_fd (pop3->stream, &fd);
55 if (status != 0)
56 return status;
57
58 if (fd == -1)
59 return MU_ERROR_IO;
60
61 FD_ZERO (&rfds);
62 FD_SET (fd, &rfds);
63 tv.tv_sec = pop3->timeout;
64 tv.tv_usec = 0;
65 status = select (fd + 1, &rfds, NULL, NULL, &tv);
66 if (status == 0)
67 return MU_ERROR_TIMEOUT;
68 else if (status == -1)
69 {
70 if (errno == EINTR)
71 continue;
72 return MU_ERROR_IO;
73 }
74 break;
75 }
76 } 50 }
77 51
78 status = stream_readline (pop3->stream, pop3->io.buf + total, 52 status = stream_readline (pop3->carrier, pop3->io.buf + total,
79 pop3->io.len - total, &n); 53 pop3->io.len - total, &n);
80 if (status != 0) 54 if (status != 0)
81 return status; 55 return status;
...@@ -90,7 +64,7 @@ pop3_getline (pop3_t pop3) ...@@ -90,7 +64,7 @@ pop3_getline (pop3_t pop3)
90 if (pop3->io.nl == NULL) /* Do we have a full line. */ 64 if (pop3->io.nl == NULL) /* Do we have a full line. */
91 { 65 {
92 /* Allocate a bigger buffer ? */ 66 /* Allocate a bigger buffer ? */
93 if (total >= pop3->io.len -1) 67 if (total >= pop3->io.len - 1)
94 { 68 {
95 pop3->io.len *= 2; 69 pop3->io.len *= 2;
96 pop3->io.buf = realloc (pop3->io.buf, pop3->io.len + 1); 70 pop3->io.buf = realloc (pop3->io.buf, pop3->io.len + 1);
...@@ -134,6 +108,11 @@ pop3_getline (pop3_t pop3) ...@@ -134,6 +108,11 @@ pop3_getline (pop3_t pop3)
134 return status; 108 return status;
135 } /* if need to fill up. */ 109 } /* if need to fill up. */
136 110
111 /* Call pop3_getline() for the dirty work, and consume i.e. put
112 in the user buffer only buflen. If buflen == 0 or buffer == NULL
113 nothing is consume, the data is save for another call to pop3_readline()
114 with a buffer != NULL.
115 */
137 int 116 int
138 pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread) 117 pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
139 { 118 {
...@@ -142,7 +121,7 @@ pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread) ...@@ -142,7 +121,7 @@ pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
142 int status; 121 int status;
143 122
144 /* Do we need to fill up? Yes if no NL or the buffer is empty. */ 123 /* Do we need to fill up? Yes if no NL or the buffer is empty. */
145 if (pop3->stream && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf)) 124 if (pop3->carrier && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf))
146 { 125 {
147 status = pop3_getline (pop3); 126 status = pop3_getline (pop3);
148 if (status != 0) 127 if (status != 0)
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_retr0 (pop3_t pop3, unsigned msgno, stream_t *pstream) 31 pop3_retr (pop3_t pop3, unsigned int msgno, stream_t *pstream)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL || msgno == 0 || pstream == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
35 switch (pop3->state) 38 switch (pop3->state)
36 { 39 {
37 case POP3_NO_STATE: 40 case POP3_NO_STATE:
...@@ -67,19 +70,3 @@ pop3_retr0 (pop3_t pop3, unsigned msgno, stream_t *pstream) ...@@ -67,19 +70,3 @@ pop3_retr0 (pop3_t pop3, unsigned msgno, stream_t *pstream)
67 70
68 return status; 71 return status;
69 } 72 }
70
71 int
72 pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
73 {
74 int status;
75
76 if (pop3 == NULL || pstream == NULL)
77 return MU_ERROR_INVALID_PARAMETER;
78
79 monitor_lock (pop3->lock);
80 monitor_cleanup_push (pop3_cleanup, pop3);
81 status = pop3_retr0 (pop3, msgno, pstream);
82 monitor_unlock (pop3->lock);
83 monitor_cleanup_pop (0);
84 return status;
85 }
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_rset0 (pop3_t pop3) 31 pop3_rset (pop3_t pop3)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
35 switch (pop3->state) 38 switch (pop3->state)
36 { 39 {
37 case POP3_NO_STATE: 40 case POP3_NO_STATE:
...@@ -63,19 +66,3 @@ pop3_rset0 (pop3_t pop3) ...@@ -63,19 +66,3 @@ pop3_rset0 (pop3_t pop3)
63 66
64 return status; 67 return status;
65 } 68 }
66
67 int
68 pop3_rset (pop3_t pop3)
69 {
70 int status;
71
72 if (pop3 == NULL)
73 return MU_ERROR_INVALID_PARAMETER;
74
75 monitor_lock (pop3->lock);
76 monitor_cleanup_push (pop3_cleanup, pop3);
77 status = pop3_rset0 (pop3);
78 monitor_unlock (pop3->lock);
79 monitor_cleanup_pop (0);
80 return status;
81 }
......
...@@ -40,7 +40,7 @@ int ...@@ -40,7 +40,7 @@ int
40 pop3_send (pop3_t pop3) 40 pop3_send (pop3_t pop3)
41 { 41 {
42 int status = 0; 42 int status = 0;
43 if (pop3->stream && (pop3->io.ptr > pop3->io.buf)) 43 if (pop3->carrier && (pop3->io.ptr > pop3->io.buf))
44 { 44 {
45 size_t n = 0; 45 size_t n = 0;
46 size_t len = pop3->io.ptr - pop3->io.buf; 46 size_t len = pop3->io.ptr - pop3->io.buf;
...@@ -49,34 +49,12 @@ pop3_send (pop3_t pop3) ...@@ -49,34 +49,12 @@ pop3_send (pop3_t pop3)
49 since on linux tv is modified when error. */ 49 since on linux tv is modified when error. */
50 if (pop3->timeout) 50 if (pop3->timeout)
51 { 51 {
52 for (;;) 52 int ready = stream_is_writeready (pop3->carrier, pop3->timeout);
53 { 53 if (ready == 0)
54 int fd = -1; 54 return MU_ERROR_TIMEOUT;
55 struct timeval tv;
56 fd_set wfds;
57 status = stream_get_fd (pop3->stream, &fd);
58 if (status != 0)
59 return status;
60
61 FD_ZERO (&wfds);
62 FD_SET (fd, &wfds);
63 tv.tv_sec = pop3->timeout;
64 tv.tv_usec = 0;
65
66 status = select (fd + 1, NULL, &wfds, NULL, &tv);
67 if (status == 0)
68 return MU_ERROR_TIMEOUT;
69 else if (status == -1)
70 {
71 if (errno == EINTR)
72 continue;
73 return MU_ERROR_IO;
74 }
75 break;
76 }
77 } 55 }
78 56
79 status = stream_write (pop3->stream, pop3->io.buf, len, &n); 57 status = stream_write (pop3->carrier, pop3->io.buf, len, &n);
80 if (n) 58 if (n)
81 { 59 {
82 /* Consume what we sent. */ 60 /* Consume what we sent. */
......
...@@ -28,16 +28,17 @@ ...@@ -28,16 +28,17 @@
28 28
29 #include <mailutils/sys/pop3.h> 29 #include <mailutils/sys/pop3.h>
30 30
31 static int 31 int
32 pop3_stat0 (pop3_t pop3, unsigned *msg_count, size_t *size) 32 pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
33 { 33 {
34 int status; 34 int status;
35 35
36 if (pop3 == NULL || msg_count == NULL || size == NULL)
37 return MU_ERROR_INVALID_PARAMETER;
38
36 switch (pop3->state) 39 switch (pop3->state)
37 { 40 {
38 case POP3_NO_STATE: 41 case POP3_NO_STATE:
39 if (msg_count == NULL || size == NULL)
40 return MU_ERROR_INVALID_PARAMETER;
41 status = pop3_writeline (pop3, "STAT\r\n"); 42 status = pop3_writeline (pop3, "STAT\r\n");
42 POP3_CHECK_ERROR (pop3, status); 43 POP3_CHECK_ERROR (pop3, status);
43 pop3->state = POP3_STAT; 44 pop3->state = POP3_STAT;
...@@ -71,19 +72,3 @@ pop3_stat0 (pop3_t pop3, unsigned *msg_count, size_t *size) ...@@ -71,19 +72,3 @@ pop3_stat0 (pop3_t pop3, unsigned *msg_count, size_t *size)
71 72
72 return status; 73 return status;
73 } 74 }
74
75 int
76 pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
77 {
78 int status;
79
80 if (pop3 == NULL)
81 return MU_ERROR_INVALID_PARAMETER;
82
83 monitor_lock (pop3->lock);
84 monitor_cleanup_push (pop3_cleanup, pop3);
85 status = pop3_stat0 (pop3, msg_count, size);
86 monitor_unlock (pop3->lock);
87 monitor_cleanup_pop (0);
88 return status;
89 }
......
...@@ -27,37 +27,6 @@ ...@@ -27,37 +27,6 @@
27 #include <stdlib.h> 27 #include <stdlib.h>
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 int
31 pop3_set_stream (pop3_t pop3, stream_t stream)
32 {
33 /* Sanity checks. */
34 if (pop3 == NULL)
35 return MU_ERROR_INVALID_PARAMETER;
36
37 /* If the stream was set before we will leak. But do what they say. */
38 pop3->stream = stream;
39 return 0;
40 }
41
42 int
43 pop3_get_stream (pop3_t pop3, stream_t *pstream)
44 {
45 /* Sanity checks. */
46 if (pop3 == NULL || pstream == NULL)
47 return MU_ERROR_INVALID_PARAMETER;
48
49 if (pop3->stream == NULL)
50 {
51 stream_t stream = NULL;
52 int status = stream_tcp_create (&stream);
53 if (status)
54 return status;
55 stream_buffer_create (&(pop3->stream), stream, 1024);
56 }
57 *pstream = pop3->stream;
58 return 0;
59 }
60
61 /* Implementation of the stream for TOP and RETR. */ 30 /* Implementation of the stream for TOP and RETR. */
62 static int p_add_ref __P ((stream_t)); 31 static int p_add_ref __P ((stream_t));
63 static int p_release __P ((stream_t)); 32 static int p_release __P ((stream_t));
...@@ -81,6 +50,12 @@ static int p_get_fd __P ((stream_t, int *)); ...@@ -81,6 +50,12 @@ static int p_get_fd __P ((stream_t, int *));
81 static int p_get_flags __P ((stream_t, int *)); 50 static int p_get_flags __P ((stream_t, int *));
82 static int p_get_state __P ((stream_t, enum stream_state *)); 51 static int p_get_state __P ((stream_t, enum stream_state *));
83 52
53 static int p_is_readready __P ((stream_t, int timeout));
54 static int p_is_writeready __P ((stream_t, int timeout));
55 static int p_is_exceptionpending __P ((stream_t, int timeout));
56
57 static int p_is_open __P ((stream_t));
58
84 static struct _stream_vtable p_s_vtable = 59 static struct _stream_vtable p_s_vtable =
85 { 60 {
86 p_add_ref, 61 p_add_ref,
...@@ -104,6 +79,12 @@ static struct _stream_vtable p_s_vtable = ...@@ -104,6 +79,12 @@ static struct _stream_vtable p_s_vtable =
104 p_get_fd, 79 p_get_fd,
105 p_get_flags, 80 p_get_flags,
106 p_get_state, 81 p_get_state,
82
83 p_is_readready,
84 p_is_writeready,
85 p_is_exceptionpending,
86
87 p_is_open
107 }; 88 };
108 89
109 int 90 int
...@@ -207,10 +188,9 @@ p_read (stream_t stream, void *buf, size_t buflen, size_t *pn) ...@@ -207,10 +188,9 @@ p_read (stream_t stream, void *buf, size_t buflen, size_t *pn)
207 size_t nread = 0; 188 size_t nread = 0;
208 189
209 /* The pop3_readline () function will always read one less to 190 /* The pop3_readline () function will always read one less to
210 be able to terminate the buffer, this will cause serious grief 191 be able to null terminate the buffer, this will cause
211 for stream_read() where it is legitimate to have a buffer of 192 serious grief for stream_read() where it is legitimate to
212 1 char. So we must catch it here or change the behaviour of 193 have a buffer of 1 char. So we must catch it here. */
213 XXX_readline. */
214 if (buflen == 1) 194 if (buflen == 1)
215 { 195 {
216 char buffer[2]; 196 char buffer[2];
...@@ -271,61 +251,89 @@ static int ...@@ -271,61 +251,89 @@ static int
271 p_write (stream_t stream, const void *buf, size_t buflen, size_t *pn) 251 p_write (stream_t stream, const void *buf, size_t buflen, size_t *pn)
272 { 252 {
273 struct p_stream *p_stream = (struct p_stream *)stream; 253 struct p_stream *p_stream = (struct p_stream *)stream;
274 return stream_write (p_stream->pop3->stream, buf, buflen, pn); 254 return stream_write (p_stream->pop3->carrier, buf, buflen, pn);
275 } 255 }
276 256
277 static int 257 static int
278 p_seek (stream_t stream, off_t offset, enum stream_whence whence) 258 p_seek (stream_t stream, off_t offset, enum stream_whence whence)
279 { 259 {
280 struct p_stream *p_stream = (struct p_stream *)stream; 260 struct p_stream *p_stream = (struct p_stream *)stream;
281 return stream_seek (p_stream->pop3->stream, offset, whence); 261 return stream_seek (p_stream->pop3->carrier, offset, whence);
282 } 262 }
283 263
284 static int 264 static int
285 p_tell (stream_t stream, off_t *offset) 265 p_tell (stream_t stream, off_t *offset)
286 { 266 {
287 struct p_stream *p_stream = (struct p_stream *)stream; 267 struct p_stream *p_stream = (struct p_stream *)stream;
288 return stream_tell (p_stream->pop3->stream, offset); 268 return stream_tell (p_stream->pop3->carrier, offset);
289 } 269 }
290 270
291 static int 271 static int
292 p_get_size (stream_t stream, off_t *size) 272 p_get_size (stream_t stream, off_t *size)
293 { 273 {
294 struct p_stream *p_stream = (struct p_stream *)stream; 274 struct p_stream *p_stream = (struct p_stream *)stream;
295 return stream_get_size (p_stream->pop3->stream, size); 275 return stream_get_size (p_stream->pop3->carrier, size);
296 } 276 }
297 277
298 static int 278 static int
299 p_truncate (stream_t stream, off_t size) 279 p_truncate (stream_t stream, off_t size)
300 { 280 {
301 struct p_stream *p_stream = (struct p_stream *)stream; 281 struct p_stream *p_stream = (struct p_stream *)stream;
302 return stream_truncate (p_stream->pop3->stream, size); 282 return stream_truncate (p_stream->pop3->carrier, size);
303 } 283 }
304 284
305 static int 285 static int
306 p_flush (stream_t stream) 286 p_flush (stream_t stream)
307 { 287 {
308 struct p_stream *p_stream = (struct p_stream *)stream; 288 struct p_stream *p_stream = (struct p_stream *)stream;
309 return stream_flush (p_stream->pop3->stream); 289 return stream_flush (p_stream->pop3->carrier);
310 } 290 }
311 291
312 static int 292 static int
313 p_get_fd (stream_t stream, int *fd) 293 p_get_fd (stream_t stream, int *fd)
314 { 294 {
315 struct p_stream *p_stream = (struct p_stream *)stream; 295 struct p_stream *p_stream = (struct p_stream *)stream;
316 return stream_get_fd (p_stream->pop3->stream, fd); 296 return stream_get_fd (p_stream->pop3->carrier, fd);
317 } 297 }
318 298
319 static int 299 static int
320 p_get_flags (stream_t stream, int *flags) 300 p_get_flags (stream_t stream, int *flags)
321 { 301 {
322 struct p_stream *p_stream = (struct p_stream *)stream; 302 struct p_stream *p_stream = (struct p_stream *)stream;
323 return stream_get_flags (p_stream->pop3->stream, flags); 303 return stream_get_flags (p_stream->pop3->carrier, flags);
324 } 304 }
325 305
326 static int 306 static int
327 p_get_state (stream_t stream, enum stream_state *state) 307 p_get_state (stream_t stream, enum stream_state *state)
328 { 308 {
329 struct p_stream *p_stream = (struct p_stream *)stream; 309 struct p_stream *p_stream = (struct p_stream *)stream;
330 return stream_get_state (p_stream->pop3->stream, state); 310 return stream_get_state (p_stream->pop3->carrier, state);
311 }
312
313 static int
314 p_is_readready (stream_t stream, int timeout)
315 {
316 struct p_stream *p_stream = (struct p_stream *)stream;
317 return stream_is_readready (p_stream->pop3->carrier, timeout);
318 }
319
320 static int
321 p_is_writeready (stream_t stream, int timeout)
322 {
323 struct p_stream *p_stream = (struct p_stream *)stream;
324 return stream_is_writeready (p_stream->pop3->carrier, timeout);
325 }
326
327 static int
328 p_is_exceptionpending (stream_t stream, int timeout)
329 {
330 struct p_stream *p_stream = (struct p_stream *)stream;
331 return stream_is_exceptionpending (p_stream->pop3->carrier, timeout);
332 }
333
334 static int
335 p_is_open (stream_t stream)
336 {
337 struct p_stream *p_stream = (struct p_stream *)stream;
338 return stream_is_open (p_stream->pop3->carrier);
331 } 339 }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 #include <stdlib.h> 23 #include <stdlib.h>
24 24
25 int 25 int
26 pop3_set_timeout (pop3_t pop3, unsigned int timeout) 26 pop3_set_timeout (pop3_t pop3, int timeout)
27 { 27 {
28 /* Sanity checks. */ 28 /* Sanity checks. */
29 if (pop3 == NULL) 29 if (pop3 == NULL)
...@@ -34,7 +34,7 @@ pop3_set_timeout (pop3_t pop3, unsigned int timeout) ...@@ -34,7 +34,7 @@ pop3_set_timeout (pop3_t pop3, unsigned int timeout)
34 } 34 }
35 35
36 int 36 int
37 pop3_get_timeout (pop3_t pop3, unsigned int *ptimeout) 37 pop3_get_timeout (pop3_t pop3, int *ptimeout)
38 { 38 {
39 /* Sanity checks. */ 39 /* Sanity checks. */
40 if (pop3 == NULL || ptimeout == NULL) 40 if (pop3 == NULL || ptimeout == NULL)
......
...@@ -27,16 +27,18 @@ ...@@ -27,16 +27,18 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_top0 (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream) 31 pop3_top (pop3_t pop3, unsigned msgno, unsigned int lines, stream_t *pstream)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL || msgno == 0 || pstream == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
38
35 switch (pop3->state) 39 switch (pop3->state)
36 { 40 {
37 case POP3_NO_STATE: 41 case POP3_NO_STATE:
38 if (pstream == NULL)
39 return MU_ERROR_INVALID_PARAMETER;
40 status = pop3_writeline (pop3, "TOP %d %d\r\n", msgno, lines); 42 status = pop3_writeline (pop3, "TOP %d %d\r\n", msgno, lines);
41 POP3_CHECK_ERROR (pop3, status); 43 POP3_CHECK_ERROR (pop3, status);
42 pop3->state = POP3_TOP; 44 pop3->state = POP3_TOP;
...@@ -69,19 +71,3 @@ pop3_top0 (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream) ...@@ -69,19 +71,3 @@ pop3_top0 (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
69 71
70 return status; 72 return status;
71 } 73 }
72
73 int
74 pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
75 {
76 int status;
77
78 if (pop3 == NULL)
79 return MU_ERROR_INVALID_PARAMETER;
80
81 monitor_lock (pop3->lock);
82 monitor_cleanup_push (pop3_cleanup, pop3);
83 status = pop3_top0 (pop3, msgno, lines, pstream);
84 monitor_unlock (pop3->lock);
85 monitor_cleanup_pop (0);
86 return status;
87 }
......
...@@ -28,16 +28,17 @@ ...@@ -28,16 +28,17 @@
28 #include <stdlib.h> 28 #include <stdlib.h>
29 #include <mailutils/sys/pop3.h> 29 #include <mailutils/sys/pop3.h>
30 30
31 static int 31 int
32 pop3_uidl0 (pop3_t pop3, unsigned msgno, char **uidl) 32 pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
33 { 33 {
34 int status; 34 int status;
35 35
36 if (pop3 == NULL || uidl == NULL)
37 return MU_ERROR_INVALID_PARAMETER;
38
36 switch (pop3->state) 39 switch (pop3->state)
37 { 40 {
38 case POP3_NO_STATE: 41 case POP3_NO_STATE:
39 if (uidl == NULL)
40 return MU_ERROR_INVALID_PARAMETER;
41 status = pop3_writeline (pop3, "UIDL %d\r\n", msgno); 42 status = pop3_writeline (pop3, "UIDL %d\r\n", msgno);
42 POP3_CHECK_ERROR (pop3, status); 43 POP3_CHECK_ERROR (pop3, status);
43 pop3->state = POP3_UIDL; 44 pop3->state = POP3_UIDL;
...@@ -98,19 +99,3 @@ pop3_uidl0 (pop3_t pop3, unsigned msgno, char **uidl) ...@@ -98,19 +99,3 @@ pop3_uidl0 (pop3_t pop3, unsigned msgno, char **uidl)
98 99
99 return status; 100 return status;
100 } 101 }
101
102 int
103 pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
104 {
105 int status;
106
107 if (pop3 == NULL)
108 return MU_ERROR_INVALID_PARAMETER;
109
110 monitor_lock (pop3->lock);
111 monitor_cleanup_push (pop3_cleanup, pop3);
112 status = pop3_uidl0 (pop3, msgno, uidl);
113 monitor_unlock (pop3->lock);
114 monitor_cleanup_pop (0);
115 return status;
116 }
......
...@@ -28,16 +28,17 @@ ...@@ -28,16 +28,17 @@
28 #include <stdlib.h> 28 #include <stdlib.h>
29 #include <mailutils/sys/pop3.h> 29 #include <mailutils/sys/pop3.h>
30 30
31 static int 31 int
32 pop3_uidl_all0 (pop3_t pop3, iterator_t *piterator) 32 pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
33 { 33 {
34 int status; 34 int status;
35 35
36 if (pop3 == NULL || piterator == NULL)
37 return MU_ERROR_INVALID_PARAMETER;
38
36 switch (pop3->state) 39 switch (pop3->state)
37 { 40 {
38 case POP3_NO_STATE: 41 case POP3_NO_STATE:
39 if (piterator == NULL)
40 return MU_ERROR_INVALID_PARAMETER;
41 status = pop3_writeline (pop3, "UIDL\r\n"); 42 status = pop3_writeline (pop3, "UIDL\r\n");
42 POP3_CHECK_ERROR (pop3, status); 43 POP3_CHECK_ERROR (pop3, status);
43 pop3->state = POP3_UIDL; 44 pop3->state = POP3_UIDL;
...@@ -72,17 +73,30 @@ pop3_uidl_all0 (pop3_t pop3, iterator_t *piterator) ...@@ -72,17 +73,30 @@ pop3_uidl_all0 (pop3_t pop3, iterator_t *piterator)
72 } 73 }
73 74
74 int 75 int
75 pop3_uidl_all (pop3_t pop3, iterator_t *piterator) 76 pop3_uidl_current (iterator_t iterator, unsigned int *pno, char **puidl)
76 { 77 {
77 int status; 78 char *buf;
78 79 int status = iterator_current (iterator, (void *)&buf);
79 if (pop3 == NULL) 80 if (status == 0)
80 return MU_ERROR_INVALID_PARAMETER; 81 {
81 82 char *space;
82 monitor_lock (pop3->lock); 83 unsigned int msgno = 0;
83 monitor_cleanup_push (pop3_cleanup, pop3); 84 /* The format is: msgno uidlstring */
84 status = pop3_uidl_all0 (pop3, piterator); 85 space = strchr (buf, ' ');
85 monitor_unlock (pop3->lock); 86 if (space)
86 monitor_cleanup_pop (0); 87 {
88 *space++ = '\0';
89 msgno = strtoul (buf, NULL, 10);
90 }
91 if (space && space[strlen (space) - 1] == '\n')
92 space[strlen (space) - 1] = '\0';
93 if (space == NULL)
94 space = (char *)"";
95 if (pno)
96 *pno = msgno;
97 if (puidl)
98 *puidl = strdup (space);
99 free (buf);
100 }
87 return status; 101 return status;
88 } 102 }
......
...@@ -27,16 +27,17 @@ ...@@ -27,16 +27,17 @@
27 27
28 #include <mailutils/sys/pop3.h> 28 #include <mailutils/sys/pop3.h>
29 29
30 static int 30 int
31 pop3_user0 (pop3_t pop3, const char *user) 31 pop3_user (pop3_t pop3, const char *user)
32 { 32 {
33 int status; 33 int status;
34 34
35 if (pop3 == NULL || user == NULL)
36 return MU_ERROR_INVALID_PARAMETER;
37
35 switch (pop3->state) 38 switch (pop3->state)
36 { 39 {
37 case POP3_NO_STATE: 40 case POP3_NO_STATE:
38 if (user == NULL)
39 return MU_ERROR_INVALID_PARAMETER;
40 status = pop3_writeline (pop3, "USER %s\r\n", user); 41 status = pop3_writeline (pop3, "USER %s\r\n", user);
41 POP3_CHECK_ERROR (pop3, status); 42 POP3_CHECK_ERROR (pop3, status);
42 pop3->state = POP3_USER; 43 pop3->state = POP3_USER;
...@@ -65,19 +66,3 @@ pop3_user0 (pop3_t pop3, const char *user) ...@@ -65,19 +66,3 @@ pop3_user0 (pop3_t pop3, const char *user)
65 66
66 return status; 67 return status;
67 } 68 }
68
69 int
70 pop3_user (pop3_t pop3, const char *user)
71 {
72 int status;
73
74 if (pop3 == NULL)
75 return MU_ERROR_INVALID_PARAMETER;
76
77 monitor_lock (pop3->lock);
78 monitor_cleanup_push (pop3_cleanup, pop3);
79 status = pop3_user0 (pop3, user);
80 monitor_unlock (pop3->lock);
81 monitor_cleanup_pop (0);
82 return status;
83 }
......
...@@ -32,6 +32,7 @@ typedef struct { ...@@ -32,6 +32,7 @@ typedef struct {
32 32
33 /* The names of functions that actually do the manipulation. */ 33 /* The names of functions that actually do the manipulation. */
34 int com_apop (char *); 34 int com_apop (char *);
35 int com_capa (char *);
35 int com_disconnect (char *); 36 int com_disconnect (char *);
36 int com_dele (char *); 37 int com_dele (char *);
37 int com_exit (char *); 38 int com_exit (char *);
...@@ -61,6 +62,7 @@ void sig_int (int); ...@@ -61,6 +62,7 @@ void sig_int (int);
61 62
62 COMMAND commands[] = { 63 COMMAND commands[] = {
63 { "apop", com_apop, "Authenticate with APOP: APOP user secret" }, 64 { "apop", com_apop, "Authenticate with APOP: APOP user secret" },
65 { "capa", com_capa, "List capabilities: capa" },
64 { "disconnect", com_disconnect, "Close connection: disconnect" }, 66 { "disconnect", com_disconnect, "Close connection: disconnect" },
65 { "dele", com_dele, "Mark message: DELE msgno" }, 67 { "dele", com_dele, "Mark message: DELE msgno" },
66 { "exit", com_exit, "exit program" }, 68 { "exit", com_exit, "exit program" },
...@@ -333,6 +335,29 @@ com_apop (char *arg) ...@@ -333,6 +335,29 @@ com_apop (char *arg)
333 } 335 }
334 336
335 int 337 int
338 com_capa (char *arg)
339 {
340 iterator_t iterator;
341 int status = pop3_capa (pop3, &iterator);
342 (void)arg;
343 print_response ();
344 if (status == 0)
345 {
346 for (iterator_first (iterator);
347 !iterator_is_done (iterator);
348 iterator_next (iterator))
349 {
350 char *capa = (char *)"";
351 iterator_current (iterator, &capa);
352 printf ("Capa: %s\n", capa);
353 free (capa);
354 }
355 iterator_destroy (iterator);
356 }
357 return status;
358 }
359
360 int
336 com_uidl (char *arg) 361 com_uidl (char *arg)
337 { 362 {
338 if (arg == NULL || *arg == '\0') 363 if (arg == NULL || *arg == '\0')
...@@ -346,10 +371,11 @@ com_uidl (char *arg) ...@@ -346,10 +371,11 @@ com_uidl (char *arg)
346 !iterator_is_done (uidl_iterator); 371 !iterator_is_done (uidl_iterator);
347 iterator_next (uidl_iterator)) 372 iterator_next (uidl_iterator))
348 { 373 {
349 struct pop3_uidl_item *pl; 374 unsigned int msgno = 0;
350 iterator_current (uidl_iterator, (void *)&pl); 375 char *uidl = (char *)"";
351 printf ("Msg: %d UIDL: %s\n", pl->msgno, pl->uidl); 376 pop3_uidl_current (uidl_iterator, &msgno, &uidl);
352 free (pl); 377 printf ("Msg: %d UIDL: %s\n", msgno, uidl);
378 free (uidl);
353 } 379 }
354 iterator_destroy (uidl_iterator); 380 iterator_destroy (uidl_iterator);
355 } 381 }
...@@ -380,10 +406,10 @@ com_list (char *arg) ...@@ -380,10 +406,10 @@ com_list (char *arg)
380 !iterator_is_done (list_iterator); 406 !iterator_is_done (list_iterator);
381 iterator_next (list_iterator)) 407 iterator_next (list_iterator))
382 { 408 {
383 struct pop3_list_item *pl; 409 unsigned int msgno = 0;
384 iterator_current (list_iterator, (void *)&pl); 410 size_t size = 0;
385 printf ("Msg: %d Size: %d\n", pl->msgno, pl->size); 411 pop3_list_current (list_iterator, &msgno, &size);
386 free (pl); 412 printf ("Msg: %d Size: %d\n", msgno, size);
387 } 413 }
388 iterator_destroy (list_iterator); 414 iterator_destroy (list_iterator);
389 } 415 }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
24 #include <mailutils/sys/stream.h> 24 #include <mailutils/sys/stream.h>
25 25
26 int 26 int
27 (stream_add_ref) (stream_t stream) 27 stream_add_ref (stream_t stream)
28 { 28 {
29 if (stream == NULL || stream->vtable == NULL 29 if (stream == NULL || stream->vtable == NULL
30 || stream->vtable->add_ref == NULL) 30 || stream->vtable->add_ref == NULL)
...@@ -33,7 +33,7 @@ int ...@@ -33,7 +33,7 @@ int
33 } 33 }
34 34
35 int 35 int
36 (stream_release) (stream_t stream) 36 stream_release (stream_t stream)
37 { 37 {
38 if (stream == NULL || stream->vtable == NULL 38 if (stream == NULL || stream->vtable == NULL
39 || stream->vtable->release == NULL) 39 || stream->vtable->release == NULL)
...@@ -42,7 +42,7 @@ int ...@@ -42,7 +42,7 @@ int
42 } 42 }
43 43
44 int 44 int
45 (stream_destroy) (stream_t stream) 45 stream_destroy (stream_t stream)
46 { 46 {
47 if (stream == NULL || stream->vtable == NULL 47 if (stream == NULL || stream->vtable == NULL
48 || stream->vtable->destroy == NULL) 48 || stream->vtable->destroy == NULL)
...@@ -51,7 +51,7 @@ int ...@@ -51,7 +51,7 @@ int
51 } 51 }
52 52
53 int 53 int
54 (stream_open) (stream_t stream, const char *host, int port, int flag) 54 stream_open (stream_t stream, const char *host, int port, int flag)
55 { 55 {
56 if (stream == NULL || stream->vtable == NULL 56 if (stream == NULL || stream->vtable == NULL
57 || stream->vtable->open == NULL) 57 || stream->vtable->open == NULL)
...@@ -60,7 +60,7 @@ int ...@@ -60,7 +60,7 @@ int
60 } 60 }
61 61
62 int 62 int
63 (stream_close) (stream_t stream) 63 stream_close (stream_t stream)
64 { 64 {
65 if (stream == NULL || stream->vtable == NULL 65 if (stream == NULL || stream->vtable == NULL
66 || stream->vtable->close == NULL) 66 || stream->vtable->close == NULL)
...@@ -69,7 +69,7 @@ int ...@@ -69,7 +69,7 @@ int
69 } 69 }
70 70
71 int 71 int
72 (stream_read) (stream_t stream, void *buf, size_t buflen, size_t *n) 72 stream_read (stream_t stream, void *buf, size_t buflen, size_t *n)
73 { 73 {
74 if (stream == NULL || stream->vtable == NULL 74 if (stream == NULL || stream->vtable == NULL
75 || stream->vtable->read == NULL) 75 || stream->vtable->read == NULL)
...@@ -78,7 +78,7 @@ int ...@@ -78,7 +78,7 @@ int
78 } 78 }
79 79
80 int 80 int
81 (stream_readline) (stream_t stream, char *buf, size_t buflen, size_t *n) 81 stream_readline (stream_t stream, char *buf, size_t buflen, size_t *n)
82 { 82 {
83 if (stream == NULL || stream->vtable == NULL 83 if (stream == NULL || stream->vtable == NULL
84 || stream->vtable->readline == NULL) 84 || stream->vtable->readline == NULL)
...@@ -87,7 +87,7 @@ int ...@@ -87,7 +87,7 @@ int
87 } 87 }
88 88
89 int 89 int
90 (stream_write) (stream_t stream, const void *buf, size_t buflen, size_t *n) 90 stream_write (stream_t stream, const void *buf, size_t buflen, size_t *n)
91 { 91 {
92 if (stream == NULL || stream->vtable == NULL 92 if (stream == NULL || stream->vtable == NULL
93 || stream->vtable->write == NULL) 93 || stream->vtable->write == NULL)
...@@ -96,7 +96,7 @@ int ...@@ -96,7 +96,7 @@ int
96 } 96 }
97 97
98 int 98 int
99 (stream_seek) (stream_t stream, off_t off, enum stream_whence whence) 99 stream_seek (stream_t stream, off_t off, enum stream_whence whence)
100 { 100 {
101 if (stream == NULL || stream->vtable == NULL 101 if (stream == NULL || stream->vtable == NULL
102 || stream->vtable->seek == NULL) 102 || stream->vtable->seek == NULL)
...@@ -105,7 +105,7 @@ int ...@@ -105,7 +105,7 @@ int
105 } 105 }
106 106
107 int 107 int
108 (stream_tell) (stream_t stream, off_t *off) 108 stream_tell (stream_t stream, off_t *off)
109 { 109 {
110 if (stream == NULL || stream->vtable == NULL 110 if (stream == NULL || stream->vtable == NULL
111 || stream->vtable->tell == NULL) 111 || stream->vtable->tell == NULL)
...@@ -114,7 +114,7 @@ int ...@@ -114,7 +114,7 @@ int
114 } 114 }
115 115
116 int 116 int
117 (stream_get_size) (stream_t stream, off_t *off) 117 stream_get_size (stream_t stream, off_t *off)
118 { 118 {
119 if (stream == NULL || stream->vtable == NULL 119 if (stream == NULL || stream->vtable == NULL
120 || stream->vtable->get_size == NULL) 120 || stream->vtable->get_size == NULL)
...@@ -123,7 +123,7 @@ int ...@@ -123,7 +123,7 @@ int
123 } 123 }
124 124
125 int 125 int
126 (stream_truncate) (stream_t stream, off_t off) 126 stream_truncate (stream_t stream, off_t off)
127 { 127 {
128 if (stream == NULL || stream->vtable == NULL 128 if (stream == NULL || stream->vtable == NULL
129 || stream->vtable->truncate == NULL) 129 || stream->vtable->truncate == NULL)
...@@ -132,7 +132,7 @@ int ...@@ -132,7 +132,7 @@ int
132 } 132 }
133 133
134 int 134 int
135 (stream_flush) (stream_t stream) 135 stream_flush (stream_t stream)
136 { 136 {
137 if (stream == NULL || stream->vtable == NULL 137 if (stream == NULL || stream->vtable == NULL
138 || stream->vtable->flush == NULL) 138 || stream->vtable->flush == NULL)
...@@ -141,7 +141,7 @@ int ...@@ -141,7 +141,7 @@ int
141 } 141 }
142 142
143 int 143 int
144 (stream_get_fd) (stream_t stream, int *fd) 144 stream_get_fd (stream_t stream, int *fd)
145 { 145 {
146 if (stream == NULL || stream->vtable == NULL 146 if (stream == NULL || stream->vtable == NULL
147 || stream->vtable->get_fd == NULL) 147 || stream->vtable->get_fd == NULL)
...@@ -150,7 +150,7 @@ int ...@@ -150,7 +150,7 @@ int
150 } 150 }
151 151
152 int 152 int
153 (stream_get_flags) (stream_t stream, int *flags) 153 stream_get_flags (stream_t stream, int *flags)
154 { 154 {
155 if (stream == NULL || stream->vtable == NULL 155 if (stream == NULL || stream->vtable == NULL
156 || stream->vtable->get_flags == NULL) 156 || stream->vtable->get_flags == NULL)
...@@ -158,11 +158,48 @@ int ...@@ -158,11 +158,48 @@ int
158 return stream->vtable->get_flags (stream, flags); 158 return stream->vtable->get_flags (stream, flags);
159 } 159 }
160 160
161
161 int 162 int
162 (stream_get_state) (stream_t stream, enum stream_state *state) 163 stream_get_state (stream_t stream, enum stream_state *state)
163 { 164 {
164 if (stream == NULL || stream->vtable == NULL 165 if (stream == NULL || stream->vtable == NULL
165 || stream->vtable->get_state == NULL) 166 || stream->vtable->get_state == NULL)
166 return MU_ERROR_NOT_SUPPORTED; 167 return MU_ERROR_NOT_SUPPORTED;
167 return stream->vtable->get_state (stream, state); 168 return stream->vtable->get_state (stream, state);
168 } 169 }
170
171 int
172 stream_is_readready (stream_t stream, int timeout)
173 {
174 if (stream == NULL || stream->vtable == NULL
175 || stream->vtable->is_readready == NULL)
176 return MU_ERROR_NOT_SUPPORTED;
177 return stream->vtable->is_readready (stream, timeout);
178 }
179
180 int
181 stream_is_writeready (stream_t stream, int timeout)
182 {
183 if (stream == NULL || stream->vtable == NULL
184 || stream->vtable->is_writeready == NULL)
185 return MU_ERROR_NOT_SUPPORTED;
186 return stream->vtable->is_writeready (stream, timeout);
187 }
188
189 int
190 stream_is_exceptionpending (stream_t stream, int timeout)
191 {
192 if (stream == NULL || stream->vtable == NULL
193 || stream->vtable->is_exceptionpending == NULL)
194 return MU_ERROR_NOT_SUPPORTED;
195 return stream->vtable->is_exceptionpending (stream, timeout);
196 }
197
198 int
199 stream_is_open (stream_t stream)
200 {
201 if (stream == NULL || stream->vtable == NULL
202 || stream->vtable->is_open == NULL)
203 return MU_ERROR_NOT_SUPPORTED;
204 return stream->vtable->is_open (stream);
205 }
......
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
31 #include <netinet/in.h> 31 #include <netinet/in.h>
32 #include <arpa/inet.h> 32 #include <arpa/inet.h>
33 #include <unistd.h> 33 #include <unistd.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <unistd.h>
34 37
35 #include <mailutils/sys/tcpstream.h> 38 #include <mailutils/sys/tcpstream.h>
36 #include <mailutils/error.h> 39 #include <mailutils/error.h>
...@@ -354,6 +357,67 @@ _tcp_get_state (stream_t stream, enum stream_state *state) ...@@ -354,6 +357,67 @@ _tcp_get_state (stream_t stream, enum stream_state *state)
354 return 0; 357 return 0;
355 } 358 }
356 359
360 static int
361 _tcp_is_readready (stream_t stream, int timeout)
362 {
363 struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
364 int ready;
365 struct timeval tv;
366 fd_set fds;
367
368 FD_ZERO (&fds);
369 FD_SET (tcp->fd, &fds);
370
371 tv.tv_sec = timeout / 100;
372 tv.tv_usec = (timeout % 1000) * 1000;
373
374 ready = select (tcp->fd + 1, &fds, NULL, NULL, (timeout == -1) ? NULL: &tv);
375 return (ready == -1) ? 0 : 1;
376 }
377
378 static int
379 _tcp_is_writeready (stream_t stream, int timeout)
380 {
381 struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
382 int ready;
383 struct timeval tv;
384 fd_set fds;
385
386 FD_ZERO (&fds);
387 FD_SET (tcp->fd, &fds);
388
389 tv.tv_sec = timeout / 100;
390 tv.tv_usec = (timeout % 1000) * 1000;
391
392 ready = select (tcp->fd + 1, NULL, &fds, NULL, (timeout == -1) ? NULL: &tv);
393 return (ready == -1) ? 0 : 1;
394 }
395
396 static int
397 _tcp_is_exceptionpending (stream_t stream, int timeout)
398 {
399 struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
400 int ready;
401 struct timeval tv;
402 fd_set fds;
403
404 FD_ZERO (&fds);
405 FD_SET (tcp->fd, &fds);
406
407 tv.tv_sec = timeout / 100;
408 tv.tv_usec = (timeout % 1000) * 1000;
409
410 ready = select (tcp->fd + 1, NULL, NULL, &fds, (timeout == -1) ? NULL: &tv);
411 return (ready == -1) ? 0 : 1;
412 }
413
414 static int
415 _tcp_is_open (stream_t stream)
416 {
417 struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
418 return tcp->fd >= 0;
419 }
420
357 static struct _stream_vtable _tcp_vtable = 421 static struct _stream_vtable _tcp_vtable =
358 { 422 {
359 _tcp_add_ref, 423 _tcp_add_ref,
...@@ -376,7 +440,13 @@ static struct _stream_vtable _tcp_vtable = ...@@ -376,7 +440,13 @@ static struct _stream_vtable _tcp_vtable =
376 440
377 _tcp_get_fd, 441 _tcp_get_fd,
378 _tcp_get_flags, 442 _tcp_get_flags,
379 _tcp_get_state 443 _tcp_get_state,
444
445 _tcp_is_readready,
446 _tcp_is_writeready,
447 _tcp_is_exceptionpending,
448
449 _tcp_is_open
380 }; 450 };
381 451
382 int 452 int
......