Commit bee00121 bee001217ceaed8c188f1048e20dcffbcea31cf2 by Alain Magloire

attribute.c auth.c body.c header.c io.c mailbox.c mbx_pop.c

 	mbx_unix.c mbx_unixscan.c message.c mime.c tcp.c transcode.c
 	include/private/attribute0.h include/private/io0.h
 	include/private/mailbox0.h include/private/tcp.h
 	include/public/attribute.h include/public/auth.h
 	include/public/io.h include/public/mailbox.h
 	include/public/message.h
added the first basic support for pop.
 	include/private/auth0.h

move the definition of auth_t struct here.
 	net.c include/private/net0.h include/public/net.h

Overhaul change of the net_t by D. I.
1 parent 4ccdee87
...@@ -23,27 +23,25 @@ ...@@ -23,27 +23,25 @@
23 #include <errno.h> 23 #include <errno.h>
24 24
25 int 25 int
26 attribute_create (attribute_t *pattr, void *owner) 26 attribute_create (attribute_t *pattr)
27 { 27 {
28 attribute_t attr; 28 attribute_t attr;
29 if (pattr == NULL || owner == NULL) 29 if (pattr == NULL)
30 return EINVAL; 30 return EINVAL;
31 attr = calloc (1, sizeof(*attr)); 31 attr = calloc (1, sizeof(*attr));
32 if (attr == NULL) 32 if (attr == NULL)
33 return ENOMEM; 33 return ENOMEM;
34 attr->owner = owner;
35 *pattr = attr; 34 *pattr = attr;
36 return 0; 35 return 0;
37 } 36 }
38 37
39 void 38 void
40 attribute_destroy (attribute_t *pattr, void *owner) 39 attribute_destroy (attribute_t *pattr)
41 { 40 {
42 if (pattr && *pattr) 41 if (pattr && *pattr)
43 { 42 {
44 attribute_t attr = *pattr; 43 attribute_t attr = *pattr;
45 if (attr->owner == owner) 44 free (attr);
46 free (attr);
47 /* loose the link */ 45 /* loose the link */
48 *pattr = NULL; 46 *pattr = NULL;
49 } 47 }
...@@ -254,12 +252,12 @@ attribute_copy (attribute_t dest, attribute_t src) ...@@ -254,12 +252,12 @@ attribute_copy (attribute_t dest, attribute_t src)
254 } 252 }
255 253
256 int 254 int
257 string_to_attribute (const char *buffer, attribute_t *pattr, void *owner) 255 string_to_attribute (const char *buffer, attribute_t *pattr)
258 { 256 {
259 char *sep; 257 const char *sep;
260 int status; 258 int status;
261 259
262 status = attribute_create (pattr, owner); 260 status = attribute_create (pattr);
263 if (status != 0) 261 if (status != 0)
264 return status; 262 return status;
265 263
...@@ -268,16 +266,19 @@ string_to_attribute (const char *buffer, attribute_t *pattr, void *owner) ...@@ -268,16 +266,19 @@ string_to_attribute (const char *buffer, attribute_t *pattr, void *owner)
268 { 266 {
269 sep = strchr(buffer, ':'); /* pass the ':' */ 267 sep = strchr(buffer, ':'); /* pass the ':' */
270 sep++; 268 sep++;
271 while (*sep == ' ') sep++; /* glob spaces */
272 if (strchr (sep, 'R') != NULL || strchr (sep, 'r') != NULL)
273 attribute_set_read (*pattr);
274 if (strchr (sep, 'O') != NULL || strchr (sep, 'o') != NULL)
275 attribute_set_seen (*pattr);
276 if (strchr (sep, 'A') != NULL || strchr (sep, 'a') != NULL)
277 attribute_set_answered (*pattr);
278 if (strchr (sep, 'F') != NULL || strchr (sep, 'f') != NULL)
279 attribute_set_flagged (*pattr);
280 } 269 }
270 else
271 sep = buffer;
272
273 while (*sep == ' ') sep++; /* glob spaces */
274 if (strchr (sep, 'R') != NULL || strchr (sep, 'r') != NULL)
275 attribute_set_read (*pattr);
276 if (strchr (sep, 'O') != NULL || strchr (sep, 'o') != NULL)
277 attribute_set_seen (*pattr);
278 if (strchr (sep, 'A') != NULL || strchr (sep, 'a') != NULL)
279 attribute_set_answered (*pattr);
280 if (strchr (sep, 'F') != NULL || strchr (sep, 'f') != NULL)
281 attribute_set_flagged (*pattr);
281 return 0; 282 return 0;
282 } 283 }
283 284
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 along with this program; if not, write to the Free Software 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 #include <auth.h> 18 #include <auth0.h>
19 #include <cpystr.h> 19 #include <cpystr.h>
20 20
21 #include <errno.h> 21 #include <errno.h>
...@@ -23,14 +23,6 @@ ...@@ -23,14 +23,6 @@
23 #include <string.h> 23 #include <string.h>
24 #include <stdlib.h> 24 #include <stdlib.h>
25 25
26 struct _auth
27 {
28 void *owner;
29 int (*_prologue) (auth_t);
30 int (*_authenticate) (auth_t);
31 int (*_epilogue) (auth_t);
32 };
33
34 int 26 int
35 auth_create (auth_t *pauth, void *owner) 27 auth_create (auth_t *pauth, void *owner)
36 { 28 {
...@@ -58,7 +50,8 @@ auth_destroy (auth_t *pauth, void *owner) ...@@ -58,7 +50,8 @@ auth_destroy (auth_t *pauth, void *owner)
58 } 50 }
59 51
60 int 52 int
61 auth_set_authenticate (auth_t auth, int (*_authenticate)(auth_t), 53 auth_set_authenticate (auth_t auth,
54 int (*_authenticate)(auth_t, char **, char **),
62 void *owner) 55 void *owner)
63 { 56 {
64 if (auth == NULL) 57 if (auth == NULL)
...@@ -70,11 +63,11 @@ auth_set_authenticate (auth_t auth, int (*_authenticate)(auth_t), ...@@ -70,11 +63,11 @@ auth_set_authenticate (auth_t auth, int (*_authenticate)(auth_t),
70 } 63 }
71 64
72 int 65 int
73 auth_authenticate (auth_t auth) 66 auth_authenticate (auth_t auth, char **user, char **passwd)
74 { 67 {
75 if (auth == NULL || auth->_authenticate == NULL) 68 if (auth == NULL || auth->_authenticate == NULL)
76 return EINVAL; 69 return EINVAL;
77 return auth->_authenticate (auth); 70 return auth->_authenticate (auth, user, passwd);
78 } 71 }
79 72
80 int 73 int
...@@ -91,7 +84,7 @@ auth_set_epilogue (auth_t auth, int (*_epilogue)(auth_t), void *owner) ...@@ -91,7 +84,7 @@ auth_set_epilogue (auth_t auth, int (*_epilogue)(auth_t), void *owner)
91 int 84 int
92 auth_epilogue (auth_t auth) 85 auth_epilogue (auth_t auth)
93 { 86 {
94 if (auth == NULL && auth->_epilogue == NULL) 87 if (auth == NULL || auth->_epilogue == NULL)
95 return EINVAL; 88 return EINVAL;
96 return auth->_epilogue (auth); 89 return auth->_epilogue (auth);
97 } 90 }
...@@ -110,7 +103,7 @@ auth_set_prologue (auth_t auth, int (*_prologue)(auth_t), void *owner) ...@@ -110,7 +103,7 @@ auth_set_prologue (auth_t auth, int (*_prologue)(auth_t), void *owner)
110 int 103 int
111 auth_prologue (auth_t auth) 104 auth_prologue (auth_t auth)
112 { 105 {
113 if (auth == NULL && auth->_prologue == NULL) 106 if (auth == NULL || auth->_prologue == NULL)
114 return EINVAL; 107 return EINVAL;
115 return auth->_prologue (auth); 108 return auth->_prologue (auth);
116 } 109 }
......
...@@ -82,7 +82,7 @@ body_get_stream (body_t body, stream_t *pstream) ...@@ -82,7 +82,7 @@ body_get_stream (body_t body, stream_t *pstream)
82 /* lazy floating body it is created when 82 /* lazy floating body it is created when
83 * doing the first body_write call 83 * doing the first body_write call
84 */ 84 */
85 status = stream_create (&stream, 0, body); 85 status = stream_create (&stream, MU_STREAM_RDWR, body);
86 if (status != 0) 86 if (status != 0)
87 return status; 87 return status;
88 stream_set_read (stream, body_read, body); 88 stream_set_read (stream, body_read, body);
......
...@@ -68,7 +68,7 @@ header_create (header_t *ph, const char *blurb, size_t len, void *owner) ...@@ -68,7 +68,7 @@ header_create (header_t *ph, const char *blurb, size_t len, void *owner)
68 68
69 header_parse (h, (char *)blurb, len); 69 header_parse (h, (char *)blurb, len);
70 70
71 status = stream_create (&(h->stream), 0, h); 71 status = stream_create (&(h->stream), MU_STREAM_READ|MU_STREAM_WRITE, h);
72 if (status != 0) 72 if (status != 0)
73 return status; 73 return status;
74 74
......
...@@ -35,7 +35,6 @@ extern "C" { ...@@ -35,7 +35,6 @@ extern "C" {
35 struct _attribute 35 struct _attribute
36 { 36 {
37 size_t flag; 37 size_t flag;
38 void *owner;
39 }; 38 };
40 39
41 #define MU_ATTRIBUTE_SEEN ((int)1) 40 #define MU_ATTRIBUTE_SEEN ((int)1)
......
...@@ -2,30 +2,25 @@ ...@@ -2,30 +2,25 @@
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Library General Public License as published by 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) 6 the Free Software Foundation; either version 2, or (at your option)
7 any later version. 7 any later version.
8 8
9 This program is distributed in the hope that it will be useful, 9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details. 12 GNU Library General Public License for more details.
13 13
14 You should have received a copy of the GNU Library General Public License 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 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 #ifndef _NET_H 18 #ifndef _AUTH0_H
19 #define _NET_H 19 #define _AUTH0_H
20 20
21 #include <auth.h>
21 #include <sys/types.h> 22 #include <sys/types.h>
22 23
23 #include <io.h>
24
25 #ifdef _cplusplus
26 extern "C" {
27 #endif
28
29 #ifndef __P 24 #ifndef __P
30 #ifdef __STDC__ 25 #ifdef __STDC__
31 #define __P(args) args 26 #define __P(args) args
...@@ -34,24 +29,21 @@ extern "C" { ...@@ -34,24 +29,21 @@ extern "C" {
34 #endif 29 #endif
35 #endif /*__P */ 30 #endif /*__P */
36 31
37 struct _net; 32 #ifdef _cplusplus
38 typedef struct _net *net_t; 33 extern "C" {
39 34 #endif
40 extern int net_api_create __P((net_t *, net_t, const char *type));
41 extern int net_api_set_option __P((net_t net, const char *name, const char *value));
42 extern int net_api_destroy __P((net_t *));
43 35
44 struct _netinstance; 36 struct _auth
45 typedef struct _netinstance *netinstance_t; 37 {
38 void *owner;
39 int (*_prologue) (auth_t);
40 int (*_authenticate) (auth_t, char **user, char **passwd);
41 int (*_epilogue) (auth_t);
42 };
46 43
47 extern int net_new __P((net_t, netinstance_t *));
48 extern int net_connect __P((netinstance_t, const char *host, int port));
49 extern int net_get_stream __P((netinstance_t, stream_t *iostr));
50 extern int net_close __P((netinstance_t));
51 extern int net_free __P((netinstance_t *));
52 44
53 #ifdef _cplusplus 45 #ifdef _cplusplus
54 } 46 }
55 #endif 47 #endif
56 48
57 #endif /* NET_H */ 49 #endif /* _AUTH0_H */
......
...@@ -36,7 +36,9 @@ struct _stream ...@@ -36,7 +36,9 @@ struct _stream
36 { 36 {
37 void *owner; 37 void *owner;
38 int flags; 38 int flags;
39 void (*_destroy) __P ((void *)); 39 void (*_destroy) __P ((stream_t));
40 int (*_open) __P ((stream_t, const char *, int port, int flags));
41 int (*_close) __P ((stream_t));
40 int (*_get_fd) __P ((stream_t, int *)); 42 int (*_get_fd) __P ((stream_t, int *));
41 int (*_read) __P ((stream_t, char *, size_t, off_t, size_t *)); 43 int (*_read) __P ((stream_t, char *, size_t, off_t, size_t *));
42 int (*_write) __P ((stream_t, const char *, size_t, off_t, size_t *)); 44 int (*_write) __P ((stream_t, const char *, size_t, off_t, size_t *));
......
...@@ -42,7 +42,7 @@ struct _mailbox ...@@ -42,7 +42,7 @@ struct _mailbox
42 char *name; 42 char *name;
43 auth_t auth; 43 auth_t auth;
44 locker_t locker; 44 locker_t locker;
45 netinstance_t netinstance; 45 stream_t stream;
46 url_t url; 46 url_t url;
47 47
48 /* register events */ 48 /* register events */
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 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 Library General 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 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 #ifndef _NET0_H
19 #define _NET0_H
20
21 #include <sys/types.h>
22
23 #include <io.h>
24 #include <net.h>
25
26 #ifdef _cplusplus
27 extern "C" {
28 #endif
29
30 #ifndef __P
31 #ifdef __STDC__
32 #define __P(args) args
33 #else
34 #define __P(args) ()
35 #endif
36 #endif /*__P */
37
38
39 struct _net_api {
40 int (*new)(void *netdata, net_t parent, void **data);
41 int (*connect)(void *data, const char *host, int port);
42 int (*get_stream)(void *data, stream_t *iostr);
43 int (*close)(void *data);
44 int (*free)(void **data);
45 };
46
47 struct _netregistrar {
48 const char *type;
49
50 int (*create)(void **netdata, struct _net_api **api);
51 int (*set_option)(void *netdata, const char *name, const char *value);
52 int (*destroy)(void **netdata);
53 };
54
55 struct _net {
56 struct _net_api *api;
57 void *data;
58 struct _net *parent;
59
60 struct _netregistrar *net_reg;
61 };
62
63 struct _netinstance {
64 struct _net_api *api;
65 void *data;
66 };
67
68 int _tcp_create(void **data, struct _net_api **api);
69 int _tcp_set_option(void *data, const char *name, const char *value);
70 int _tcp_destroy(void **data);
71
72 #ifdef _cplusplus
73 }
74 #endif
75
76 #endif /* NET0_H */
...@@ -15,25 +15,16 @@ ...@@ -15,25 +15,16 @@
15 along with this program; if not, write to the Free Software 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 #include <net0.h>
19
20 #define TCP_STATE_INIT 1 18 #define TCP_STATE_INIT 1
21 #define TCP_STATE_RESOLVE 2 19 #define TCP_STATE_RESOLVE 2
22 #define TCP_STATE_RESOLVING 3 20 #define TCP_STATE_RESOLVING 3
23 #define TCP_STATE_CONNECTING 4 21 #define TCP_STATE_CONNECTING 4
24 #define TCP_STATE_CONNECTED 5 22 #define TCP_STATE_CONNECTED 5
25 23
26 struct _tcp_options {
27 int non_block;
28 int net_timeout;
29 };
30
31 struct _tcp_instance { 24 struct _tcp_instance {
32 struct _tcp_options *options; 25 int fd;
33 int fd; 26 char *host;
34 char *host; 27 int port;
35 int port; 28 int state;
36 int state;
37 stream_t stream;
38 unsigned long address; 29 unsigned long address;
39 }; 30 };
......
...@@ -35,8 +35,8 @@ extern "C" { ...@@ -35,8 +35,8 @@ extern "C" {
35 struct _attribute; 35 struct _attribute;
36 typedef struct _attribute * attribute_t; 36 typedef struct _attribute * attribute_t;
37 37
38 extern int attribute_create __P ((attribute_t *, void *owner)); 38 extern int attribute_create __P ((attribute_t *));
39 extern void attribute_destroy __P ((attribute_t *, void *owner)); 39 extern void attribute_destroy __P ((attribute_t *));
40 40
41 extern int attribute_is_seen __P ((attribute_t)); 41 extern int attribute_is_seen __P ((attribute_t));
42 extern int attribute_is_answered __P ((attribute_t)); 42 extern int attribute_is_answered __P ((attribute_t));
...@@ -68,10 +68,10 @@ extern int attribute_copy __P ((attribute_t dst, ...@@ -68,10 +68,10 @@ extern int attribute_copy __P ((attribute_t dst,
68 attribute_t src)); 68 attribute_t src));
69 69
70 extern int string_to_attribute __P ((const char *buf, 70 extern int string_to_attribute __P ((const char *buf,
71 attribute_t *pattr, void *owner)); 71 attribute_t *pattr));
72 extern int attribute_to_string __P ((attribute_t attr, char *buf, 72 extern int attribute_to_string __P ((attribute_t attr, char *buf,
73 size_t len, size_t *)); 73 size_t len, size_t *));
74 extern int attribute_get_owner __P ((attribute_t attr, void **owner)); 74
75 #ifdef __cplusplus 75 #ifdef __cplusplus
76 } 76 }
77 #endif 77 #endif
......
...@@ -36,7 +36,7 @@ extern "C" { ...@@ -36,7 +36,7 @@ extern "C" {
36 struct _auth; 36 struct _auth;
37 typedef struct _auth *auth_t; 37 typedef struct _auth *auth_t;
38 38
39 extern int auth_create __P ((auth_t *, void *owner)); 39 extern int auth_create __P ((auth_t *, void *owner));
40 extern void auth_destroy __P ((auth_t *, void *owner)); 40 extern void auth_destroy __P ((auth_t *, void *owner));
41 41
42 extern int auth_prologue __P ((auth_t)); 42 extern int auth_prologue __P ((auth_t));
...@@ -44,9 +44,10 @@ extern int auth_set_prologue __P ((auth_t auth, ...@@ -44,9 +44,10 @@ extern int auth_set_prologue __P ((auth_t auth,
44 int (*_prologue) __P ((auth_t)), 44 int (*_prologue) __P ((auth_t)),
45 void *owner)); 45 void *owner));
46 46
47 extern int auth_authenticate __P ((auth_t)); 47 extern int auth_authenticate __P ((auth_t, char **, char **));
48 extern int auth_set_authenticate __P ((auth_t auth, 48 extern int auth_set_authenticate __P ((auth_t auth,
49 int (*_authenticate) __P ((auth_t)), 49 int (*_authenticate)
50 __P ((auth_t, char **, char **)),
50 void *owner)); 51 void *owner));
51 52
52 extern int auth_epilogue __P ((auth_t)); 53 extern int auth_epilogue __P ((auth_t));
......
...@@ -36,32 +36,58 @@ struct _stream; ...@@ -36,32 +36,58 @@ struct _stream;
36 typedef struct _stream *stream_t; 36 typedef struct _stream *stream_t;
37 37
38 /* stream will be destroy on stream_destroy */ 38 /* stream will be destroy on stream_destroy */
39 #define MU_STREAM_NO_CHECK 1 39 #define MU_STREAM_READ 0x00000001
40 #define MU_STREAM_WRITE 0x00000002
41 #define MU_STREAM_RDWR 0x00000004
42 #define MU_STREAM_APPEND 0x00000008
43 #define MU_STREAM_CREAT 0x00000010
44 #define MU_STREAM_NONBLOCK 0x00000020
45 #define MU_STREAM_NO_CHECK 0x00000040
40 46
41 extern int stream_create __P ((stream_t *, int flags, void *owner)); 47 extern int stream_create __P ((stream_t *, int flags, void *owner));
42 extern void stream_destroy __P ((stream_t *, void *owner));
43 48
44 extern int stream_set_destroy __P ((stream_t, 49 extern void stream_destroy __P ((stream_t *, void *owner));
45 void (*_destroy) __P ((void *)), 50 extern int stream_set_destroy __P ((stream_t, void (*_destroy) __P ((stream_t)),
46 void *owner)); 51 void *owner));
47 52
53 extern int stream_open __P ((stream_t, const char *, int, int));
54 extern int stream_set_open __P ((stream_t,
55 int (*_open) __P ((stream_t, const char *,
56 int, int)),
57 void *owner));
58
59 extern int stream_close __P ((stream_t));
60 extern int stream_set_close __P ((stream_t, int (*_close) __P ((stream_t)),
61 void *owner));
62
63 extern int stream_get_fd __P ((stream_t , int *));
48 extern int stream_set_fd __P ((stream_t, 64 extern int stream_set_fd __P ((stream_t,
49 int (*_get_fd)(stream_t, int *), 65 int (*_get_fd)(stream_t, int *),
50 void *owner)); 66 void *owner));
67
68 extern int stream_read __P ((stream_t, char *, size_t, off_t, size_t *));
51 extern int stream_set_read __P ((stream_t, 69 extern int stream_set_read __P ((stream_t,
52 int (*_read) __P ((stream_t, char *, 70 int (*_read) __P ((stream_t, char *,
53 size_t, off_t, size_t *)), 71 size_t, off_t, size_t *)),
54 void *owner)); 72 void *owner));
73
74 extern int stream_write __P ((stream_t, const char *, size_t, off_t, size_t *));
55 extern int stream_set_write __P ((stream_t, 75 extern int stream_set_write __P ((stream_t,
56 int (*_write) __P ((stream_t, const char *, 76 int (*_write) __P ((stream_t, const char *,
57 size_t, off_t, 77 size_t, off_t,
58 size_t *)), 78 size_t *)),
59 void *owner)); 79 void *owner));
60 extern int stream_get_fd __P ((stream_t , int *));
61 extern int stream_read __P ((stream_t, char *, size_t, off_t, size_t *));
62 extern int stream_write __P ((stream_t, const char *, size_t,
63 off_t, size_t *));
64 80
81 extern int stream_get_flags __P ((stream_t , int *flags));
82
83 /* misc */
84 extern int file_stream_create __P ((stream_t *stream, const char *filename,
85 int flags));
86 extern int encoder_stream_create __P ((stream_t *stream, stream_t iostream,
87 const char *encoding));
88 extern int decoder_stream_create __P ((stream_t *stream, stream_t iostream,
89 const char *encoding));
90 extern int tcp_stream_create __P ((stream_t *stream));
65 91
66 #ifdef __cplusplus 92 #ifdef __cplusplus
67 } 93 }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 #include <attribute.h> 23 #include <attribute.h>
24 #include <auth.h> 24 #include <auth.h>
25 #include <locker.h> 25 #include <locker.h>
26 #include <net.h> 26 #include <io.h>
27 27
28 #include <sys/types.h> 28 #include <sys/types.h>
29 29
...@@ -48,12 +48,12 @@ extern int mailbox_create __P ((mailbox_t *, const char *, int id)); ...@@ -48,12 +48,12 @@ extern int mailbox_create __P ((mailbox_t *, const char *, int id));
48 extern void mailbox_destroy __P ((mailbox_t *)); 48 extern void mailbox_destroy __P ((mailbox_t *));
49 49
50 /* flags for mailbox_open () */ 50 /* flags for mailbox_open () */
51 #define MU_MAILBOX_RDONLY ((int)1) 51 #define MU_MAILBOX_RDONLY MU_STREAM_READ
52 #define MU_MAILBOX_WRONLY (MU_MAILBOX_RDONLY << 1) 52 #define MU_MAILBOX_WRONLY MU_STREAM_WRITE
53 #define MU_MAILBOX_RDWR (MU_MAILBOX_WRONLY << 1) 53 #define MU_MAILBOX_RDWR MU_STREAM_RDWR
54 #define MU_MAILBOX_APPEND (MU_MAILBOX_RDWR << 1) 54 #define MU_MAILBOX_APPEND MU_STREAM_APPEND
55 #define MU_MAILBOX_CREAT (MU_MAILBOX_APPEND << 1) 55 #define MU_MAILBOX_CREAT MU_STREAM_CREAT
56 #define MU_MAILBOX_NONBLOCK (MU_MAILBOX_CREAT << 1) 56 #define MU_MAILBOX_NONBLOCK MU_STREAM_NONBLOCK
57 57
58 extern int mailbox_open __P ((mailbox_t, int flag)); 58 extern int mailbox_open __P ((mailbox_t, int flag));
59 extern int mailbox_close __P ((mailbox_t)); 59 extern int mailbox_close __P ((mailbox_t));
...@@ -64,9 +64,9 @@ extern int mailbox_append_message __P ((mailbox_t, message_t msg)); ...@@ -64,9 +64,9 @@ extern int mailbox_append_message __P ((mailbox_t, message_t msg));
64 extern int mailbox_messages_count __P ((mailbox_t, size_t *num)); 64 extern int mailbox_messages_count __P ((mailbox_t, size_t *num));
65 extern int mailbox_expunge __P ((mailbox_t)); 65 extern int mailbox_expunge __P ((mailbox_t));
66 66
67 /* netinstance settings */ 67 /* stream settings */
68 extern int mailbox_get_netinstance __P ((mailbox_t, netinstance_t *net)); 68 extern int mailbox_get_stream __P ((mailbox_t, stream_t *pstream));
69 extern int mailbox_set_netinstance __P ((mailbox_t, netinstance_t net)); 69 extern int mailbox_set_stream __P ((mailbox_t, stream_t stream));
70 70
71 /* Lock settings */ 71 /* Lock settings */
72 extern int mailbox_get_locker __P ((mailbox_t, locker_t *locker)); 72 extern int mailbox_get_locker __P ((mailbox_t, locker_t *locker));
......
...@@ -80,14 +80,25 @@ extern int message_set_received __P ((message_t, ...@@ -80,14 +80,25 @@ extern int message_set_received __P ((message_t,
80 extern int message_get_attribute __P ((message_t, attribute_t *)); 80 extern int message_get_attribute __P ((message_t, attribute_t *));
81 extern int message_set_attribute __P ((message_t, attribute_t, void *owner)); 81 extern int message_set_attribute __P ((message_t, attribute_t, void *owner));
82 82
83 //extern int message_clone __P ((message_t));
84
85 /* events */ 83 /* events */
86 #define MU_EVT_MSG_DESTROY 32 84 #define MU_EVT_MSG_DESTROY 32
87 extern int message_register __P ((message_t msg, size_t type, 85 extern int message_register __P ((message_t msg, size_t type,
88 int (*action) (size_t typ, void *arg), 86 int (*action) (size_t typ, void *arg),
89 void *arg)); 87 void *arg));
90 extern int message_deregister __P ((message_t msg, void *action)); 88 extern int message_deregister __P ((message_t msg, void *action));
89
90 /* misc functions */
91 extern int message_create_attachment __P ((const char *content_type,
92 const char *encoding,
93 const char *filename,
94 message_t *newmsg));
95 extern int message_save_attachment __P ((message_t msg,
96 const char *filename, void **data));
97 extern int message_encapsulate __P ((message_t msg, message_t *newmsg,
98 void **data));
99 extern int message_unencapsulate __P ((message_t msg, message_t *newmsg,
100 void **data));
101
91 #ifdef _cplusplus 102 #ifdef _cplusplus
92 } 103 }
93 #endif 104 #endif
......
...@@ -39,21 +39,20 @@ stream_create (stream_t *pstream, int flags, void *owner) ...@@ -39,21 +39,20 @@ stream_create (stream_t *pstream, int flags, void *owner)
39 void 39 void
40 stream_destroy (stream_t *pstream, void *owner) 40 stream_destroy (stream_t *pstream, void *owner)
41 { 41 {
42 if (pstream && *pstream) 42 if (pstream && *pstream)
43 { 43 {
44 stream_t stream = *pstream; 44 stream_t stream = *pstream;
45 45 if (!(stream->flags & MU_STREAM_NO_CHECK) && stream->owner != owner)
46 return;
46 if (stream->_destroy) 47 if (stream->_destroy)
47 stream->_destroy (owner); 48 stream->_destroy (stream);
48 if ((stream->flags & MU_STREAM_NO_CHECK) || stream->owner == owner)
49 free (stream); 49 free (stream);
50 *pstream = NULL; 50 *pstream = NULL;
51 } 51 }
52 } 52 }
53 53
54 int 54 int
55 stream_set_destroy (stream_t stream, void (*_destroy) (void *), 55 stream_set_destroy (stream_t stream, void (*_destroy) (stream_t), void *owner)
56 void *owner)
57 { 56 {
58 if (stream == NULL) 57 if (stream == NULL)
59 return EINVAL; 58 return EINVAL;
...@@ -66,6 +65,53 @@ stream_set_destroy (stream_t stream, void (*_destroy) (void *), ...@@ -66,6 +65,53 @@ stream_set_destroy (stream_t stream, void (*_destroy) (void *),
66 } 65 }
67 66
68 int 67 int
68 stream_open (stream_t stream, const char *name, int port, int flags)
69 {
70 if (stream == NULL)
71 return EINVAL;
72 if (stream->_open)
73 return stream->_open (stream, name, port, flags);
74 return 0;
75 }
76
77 int
78 stream_set_open (stream_t stream,
79 int (*_open) (stream_t, const char *, int, int), void *owner)
80 {
81 if (stream == NULL)
82 return EINVAL;
83 if (owner == stream->owner)
84 {
85 stream->_open = _open;
86 return 0;
87 }
88 return EACCES;
89 }
90
91 int
92 stream_close (stream_t stream)
93 {
94 if (stream == NULL)
95 return EINVAL;
96 if (stream->_close)
97 return stream->_close (stream);
98 return 0;
99 }
100
101 int
102 stream_set_close (stream_t stream, int (*_close) (stream_t), void *owner)
103 {
104 if (stream == NULL)
105 return EINVAL;
106 if (owner == stream->owner)
107 {
108 stream->_close = _close;
109 return 0;
110 }
111 return EACCES;
112 }
113
114 int
69 stream_set_fd (stream_t stream, int (*_get_fd) (stream_t, int *), void *owner) 115 stream_set_fd (stream_t stream, int (*_get_fd) (stream_t, int *), void *owner)
70 { 116 {
71 if (stream == NULL) 117 if (stream == NULL)
...@@ -85,7 +131,9 @@ stream_set_read (stream_t stream, int (*_read) ...@@ -85,7 +131,9 @@ stream_set_read (stream_t stream, int (*_read)
85 { 131 {
86 if (stream == NULL) 132 if (stream == NULL)
87 return EINVAL; 133 return EINVAL;
88 if (owner == stream->owner) 134 if (owner == stream->owner &&
135 ((stream->flags & MU_STREAM_READ) ||
136 (stream->flags & MU_STREAM_RDWR)))
89 { 137 {
90 stream->_read = _read; 138 stream->_read = _read;
91 return 0; 139 return 0;
...@@ -100,7 +148,10 @@ stream_set_write (stream_t stream, int (*_write) ...@@ -100,7 +148,10 @@ stream_set_write (stream_t stream, int (*_write)
100 { 148 {
101 if (stream == NULL) 149 if (stream == NULL)
102 return EINVAL; 150 return EINVAL;
103 if (stream->owner == owner) 151 if (stream->owner == owner &&
152 ((stream->flags & MU_STREAM_WRITE) ||
153 (stream->flags & MU_STREAM_RDWR) ||
154 (stream->flags & MU_STREAM_APPEND)))
104 { 155 {
105 stream->_write = _write; 156 stream->_write = _write;
106 return 0; 157 return 0;
...@@ -133,3 +184,12 @@ stream_get_fd (stream_t stream, int *pfd) ...@@ -133,3 +184,12 @@ stream_get_fd (stream_t stream, int *pfd)
133 return EINVAL; 184 return EINVAL;
134 return stream->_get_fd (stream, pfd); 185 return stream->_get_fd (stream, pfd);
135 } 186 }
187
188 int
189 stream_get_flags (stream_t stream, int *pfl)
190 {
191 if (stream == NULL && pfl == NULL )
192 return EINVAL;
193 *pfl = stream->flags;
194 return 0;
195 }
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
23 #include <message0.h> 23 #include <message0.h>
24 #include <registrar.h> 24 #include <registrar.h>
25 #include <locker.h> 25 #include <locker.h>
26 #include <net.h>
27 26
28 #include <stdlib.h> 27 #include <stdlib.h>
29 #include <string.h> 28 #include <string.h>
...@@ -163,11 +162,12 @@ mailbox_set_locker (mailbox_t mbox, locker_t locker) ...@@ -163,11 +162,12 @@ mailbox_set_locker (mailbox_t mbox, locker_t locker)
163 } 162 }
164 163
165 int 164 int
166 mailbox_get_locker (mailbox_t mbox, locker_t *locker) 165 mailbox_get_locker (mailbox_t mbox, locker_t *plocker)
167 { 166 {
168 if (mbox == NULL || locker == NULL) 167 if (mbox == NULL || plocker == NULL)
169 return EINVAL; 168 return EINVAL;
170 *locker = mbox->locker; 169 if (plocker)
170 *plocker = mbox->locker;
171 return 0; 171 return 0;
172 } 172 }
173 173
...@@ -185,25 +185,27 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth) ...@@ -185,25 +185,27 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth)
185 { 185 {
186 if (mbox == NULL || pauth == NULL) 186 if (mbox == NULL || pauth == NULL)
187 return EINVAL; 187 return EINVAL;
188 *pauth = mbox->auth; 188 if (pauth)
189 *pauth = mbox->auth;
189 return 0; 190 return 0;
190 } 191 }
191 192
192 int 193 int
193 mailbox_set_netinstance (mailbox_t mbox, netinstance_t netinstance) 194 mailbox_set_stream (mailbox_t mbox, stream_t stream)
194 { 195 {
195 if (mbox == NULL) 196 if (mbox == NULL)
196 return EINVAL; 197 return EINVAL;
197 mbox->netinstance = netinstance; 198 mbox->stream = stream;
198 return 0; 199 return 0;
199 } 200 }
200 201
201 int 202 int
202 mailbox_get_netinstance (mailbox_t mbox, netinstance_t *pnetinstance) 203 mailbox_get_stream (mailbox_t mbox, stream_t *pstream)
203 { 204 {
204 if (mbox == NULL || pnetinstance == NULL) 205 if (mbox == NULL || pstream == NULL)
205 return EINVAL; 206 return EINVAL;
206 *pnetinstance = mbox->netinstance; 207 if (pstream)
208 *pstream = mbox->stream;
207 return 0; 209 return 0;
208 } 210 }
209 211
......
...@@ -16,9 +16,21 @@ ...@@ -16,9 +16,21 @@
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 #include <mailbox0.h> 18 #include <mailbox0.h>
19 #include <io0.h>
20 #include <body0.h>
21 #include <message0.h>
19 #include <registrar0.h> 22 #include <registrar0.h>
23 #include <auth0.h>
24 #include <attribute.h>
20 25
26 #include <termios.h>
21 #include <errno.h> 27 #include <errno.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33
22 34
23 static int mailbox_pop_create (mailbox_t *mbox, const char *name); 35 static int mailbox_pop_create (mailbox_t *mbox, const char *name);
24 static void mailbox_pop_destroy (mailbox_t *mbox); 36 static void mailbox_pop_destroy (mailbox_t *mbox);
...@@ -29,6 +41,194 @@ struct mailbox_registrar _mailbox_pop_registrar = ...@@ -29,6 +41,194 @@ struct mailbox_registrar _mailbox_pop_registrar =
29 mailbox_pop_create, mailbox_pop_destroy 41 mailbox_pop_create, mailbox_pop_destroy
30 }; 42 };
31 43
44 static int mailbox_pop_open (mailbox_t, int flags);
45 static int mailbox_pop_close (mailbox_t);
46 static int mailbox_pop_get_message (mailbox_t, size_t msgno, message_t *msg);
47 static int mailbox_pop_messages_count (mailbox_t, size_t *num);
48 static int mailbox_pop_expunge (mailbox_t);
49 static int mailbox_pop_num_deleted (mailbox_t, size_t *);
50
51 /* update and scanning*/
52 static int mailbox_pop_is_updated (mailbox_t);
53 static int mailbox_pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount);
54
55 /* mailbox size ? */
56 static int mailbox_pop_size (mailbox_t, off_t *size);
57
58 static int mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen,
59 off_t offset, size_t *pnread);
60 static int mailbox_pop_getfd (stream_t, int *pfd);
61 static int mailbox_pop_body_size (body_t, size_t *psize);
62
63
64 /* According to the rfc:
65 * RFC 2449 POP3 Extension Mechanism November 1998
66
67 * 4. Parameter and Response Lengths
68
69 * This specification increases the length restrictions on commands and
70 * parameters imposed by RFC 1939.
71
72 * The maximum length of a command is increased from 47 characters (4
73 * character command, single space, 40 character argument, CRLF) to 255
74 * octets, including the terminating CRLF.
75
76 * Servers which support the CAPA command MUST support commands up to
77 * 255 octets. Servers MUST also support the largest maximum command
78 * length specified by any supported capability.
79
80 * The maximum length of the first line of a command response (including
81 * the initial greeting) is unchanged at 512 octets (including the
82 * terminating CRLF).
83 */
84
85 /* buffered IO */
86 struct _bio {
87 #define POP_BUFSIZ 512
88 int fd;
89 size_t maxlen;
90 size_t len;
91 char *current;
92 char *buffer;
93 char *ptr;
94 char *nl;
95 };
96
97 typedef struct _bio *bio_t;
98
99 static int bio_create (bio_t *, int);
100 static void bio_destroy (bio_t *);
101 static int bio_readline (bio_t);
102 static int bio_read (bio_t);
103 static int bio_write (bio_t);
104
105 struct _mailbox_pop_data;
106 struct _mailbox_pop_message;
107
108 typedef struct _mailbox_pop_data * mailbox_pop_data_t;
109 typedef struct _mailbox_pop_message * mailbox_pop_message_t;
110
111 struct _mailbox_pop_message
112 {
113 bio_t bio;
114 int started, inbody;
115 size_t num;
116 off_t body_size;
117 message_t message;
118 mailbox_pop_data_t mpd;
119 };
120
121 struct _mailbox_pop_data
122 {
123 void *func;
124 void *id;
125 int state;
126 mailbox_pop_message_t *pmessages;
127 size_t pmessages_count;
128 size_t messages_count;
129 size_t size;
130 #ifdef HAVE_PTHREAD_H
131 pthread_mutex_t mutex;
132 #endif
133 int flags;
134 int fd;
135 bio_t bio;
136 int is_updated;
137 char *user;
138 char *passwd;
139 mailbox_pop_message_t mpm;
140 } ;
141
142
143 /* Parse the url, allocate mailbox_t etc .. */
144 static int
145 mailbox_pop_create (mailbox_t *pmbox, const char *name)
146 {
147 mailbox_t mbox;
148 mailbox_pop_data_t mpd;
149 size_t name_len;
150 int status;
151
152 /* sanity check */
153 if (pmbox == NULL || name == NULL || *name == '\0')
154 return EINVAL;
155
156 name_len = strlen (name);
157
158 #define POP_SCHEME "pop://"
159 #define POP_SCHEME_LEN 6
160 #define SEPARATOR '/'
161
162 /* skip the url scheme */
163 if (name_len > POP_SCHEME_LEN &&
164 (name[0] == 'p' || name[0] == 'P') &&
165 (name[1] == 'o' || name[1] == 'O') &&
166 (name[2] == 'p' || name[2] == 'P') &&
167 (name[3] == ':' && name[4] == '/' && name[5] == '/'))
168 {
169 name += POP_SCHEME_LEN;
170 name_len -= POP_SCHEME_LEN;
171 }
172
173 /* allocate memory for mbox */
174 mbox = calloc (1, sizeof (*mbox));
175 if (mbox == NULL)
176 return ENOMEM;
177
178 /* allocate specific pop box data */
179 mpd = mbox->data = calloc (1, sizeof (*mpd));
180 if (mbox->data == NULL)
181 {
182 mailbox_pop_destroy (&mbox);
183 return ENOMEM;
184 }
185
186 /* allocate the struct for buffered I/O */
187 status = bio_create (&(mpd->bio), -1);
188 if (status != 0)
189 {
190 mailbox_pop_destroy (&mbox);
191 return status;
192 }
193
194 /* copy the name */
195 mbox->name = calloc (name_len + 1, sizeof (char));
196 if (mbox->name == NULL)
197 {
198 mailbox_pop_destroy (&mbox);
199 return ENOMEM;
200 }
201 memcpy (mbox->name, name, name_len);
202
203 #ifdef HAVE_PHTREAD_H
204 /* mutex when accessing the structure fields */
205 /* FIXME: should we use rdwr locks instead ?? */
206 pthread_mutex_init (&(mud->mutex), NULL);
207 #endif
208
209 /* initialize the structure */
210 mbox->_create = mailbox_pop_create;
211 mbox->_destroy = mailbox_pop_destroy;
212
213 mbox->_open = mailbox_pop_open;
214 mbox->_close = mailbox_pop_close;
215
216 /* messages */
217 mbox->_get_message = mailbox_pop_get_message;
218 mbox->_messages_count = mailbox_pop_messages_count;
219 mbox->_expunge = mailbox_pop_expunge;
220 mbox->_num_deleted = mailbox_pop_num_deleted;
221
222 mbox->_scan = mailbox_pop_scan;
223 mbox->_is_updated = mailbox_pop_is_updated;
224
225 mbox->_size = mailbox_pop_size;
226
227 (*pmbox) = mbox;
228
229 return 0; /* okdoke */
230 }
231
32 static void 232 static void
33 mailbox_pop_destroy (mailbox_t *mbox) 233 mailbox_pop_destroy (mailbox_t *mbox)
34 { 234 {
...@@ -36,9 +236,1017 @@ mailbox_pop_destroy (mailbox_t *mbox) ...@@ -36,9 +236,1017 @@ mailbox_pop_destroy (mailbox_t *mbox)
36 return; 236 return;
37 } 237 }
38 238
239 static struct termios stored_settings;
240
241 static void
242 echo_off(void)
243 {
244 struct termios new_settings;
245 tcgetattr (0, &stored_settings);
246 new_settings = stored_settings;
247 new_settings.c_lflag &= (~ECHO);
248 tcsetattr (0, TCSANOW, &new_settings);
249 }
250
251 static void
252 echo_on(void)
253 {
254 tcsetattr (0, TCSANOW, &stored_settings);
255 }
256
257 static int
258 pop_authenticate (auth_t auth, char **user, char **passwd)
259 {
260 /* FIXME: this incorrect and goes against GNU style: having a limitation
261 * on the user/passwd length, it should be fix
262 */
263 char u[128];
264 char p[128];
265 mailbox_t mbox = auth->owner;
266 int status;
267
268 *u = '\0';
269 *p = '\0';
270
271 /* prompt for the user/login name */
272 status = url_get_user (mbox->url, u, sizeof (u), NULL);
273 if (status != 0 || *u == '\0')
274 {
275 printf ("Pop User: "); fflush (stdout);
276 fgets (u, sizeof (u), stdin);
277 u [strlen (u) - 1] = '\0'; /* nuke the trailing NL */
278 }
279 /* prompt for the passwd */
280 /* FIXME: should turn off echo .... */
281 status = url_get_passwd (mbox->url, p, sizeof (p), NULL);
282 if (status != 0 || *p == '\0' || *p == '*')
283 {
284 printf ("Pop Passwd: ");
285 fflush (stdout);
286 echo_off ();
287 fgets (p, sizeof(p), stdin);
288 echo_on ();
289 p [strlen (p) - 1] = '\0';
290 }
291 *user = strdup (u);
292 *passwd = strdup (p);
293 return 0;
294 }
295
296 static int
297 mailbox_pop_open (mailbox_t mbox, int flags)
298 {
299 mailbox_pop_data_t mpd;
300 int status;
301 bio_t bio;
302 void *func = mailbox_pop_open;
303 int fd;
304 char host[256] ;
305 long port;
306
307 /* sanity checks */
308 if (mbox == NULL || mbox->url == NULL || (mpd = mbox->data) == NULL)
309 return EINVAL;
310
311 /* create the networking stack */
312 if (!mbox->stream)
313 {
314 if ((status = url_get_host (mbox->url, host, sizeof(host), NULL)) != 0 ||
315 (status = url_get_port (mbox->url, &port)) != 0 ||
316 (status = tcp_stream_create (&(mbox->stream))) != 0)
317 {
318 mpd->func = NULL;
319 mpd->state = 0;
320 return status;
321 }
322 }
323
324 /* flag busy */
325 if (mpd->func && mpd->func != func)
326 return EBUSY;
327 mpd->func = func;
328 bio = mpd->bio;
329
330 /* spawn the prologue */
331 if (mbox->auth)
332 auth_prologue (mbox->auth);
333
334 /* enter the state machine */
335 switch (mpd->state)
336 {
337 /* establish the connection */
338 case 0:
339 status = stream_open (mbox->stream, host, port, flags);
340 if (status != 0)
341 {
342 if (status != EAGAIN && status != EINPROGRESS && status != EINTR)
343 {
344 mpd->func = NULL;
345 mpd->state = 0;
346 }
347 return status;
348 }
349 /* get the fd */
350 stream_get_fd (mbox->stream, &fd);
351 mpd->bio->fd = mpd->fd = fd;
352 mpd->state = 1;
353 /* glob the Greetings */
354 case 1:
355 status = bio_readline (bio);
356 if (status != 0)
357 {
358 if (status != EAGAIN && status != EINTR)
359 {
360 mpd->func = NULL;
361 mpd->state = 0;
362 }
363 return status;
364 }
365 if (strncasecmp (bio->buffer, "+OK", 3) != 0)
366 {
367 mpd->func = NULL;
368 mpd->state = 0;
369 close (mpd->fd);
370 mpd->bio->fd = -1;
371 return EACCES;
372 }
373 /* Dealing whith Authentication */
374 /* so far only normal user/pass supported */
375 if (mbox->auth)
376 auth_authenticate (mbox->auth, &mpd->user, &mpd->passwd);
377 else
378 {
379 status = auth_create (&(mbox->auth), mbox);
380 if (status != 0)
381 {
382 mpd->func = NULL;
383 mpd->state = 0;
384 return status;
385 }
386 auth_set_authenticate (mbox->auth, pop_authenticate, mbox);
387 }
388
389 auth_authenticate (mbox->auth, &mpd->user, &mpd->passwd);
390 /* FIXME use snprintf */
391 //mpd->len = sprintf (pop->buffer, POP_BUFSIZ, "USER %s\r\n", user);
392 bio->len = sprintf (bio->buffer, "USER %s\r\n", mpd->user);
393 bio->ptr = bio->buffer;
394 free (mpd->user); mpd->user = NULL;
395 mpd->state = 2;
396 /* send username */
397 case 2:
398 status = bio_write (bio);
399 if (status != 0)
400 {
401 if (status != EAGAIN && status != EINTR)
402 {
403 mpd->func = NULL;
404 mpd->state = 0;
405 }
406 return status;
407 }
408 mpd->state = 3;
409 /* get the ack */
410 case 3:
411 status = bio_readline (bio);
412 if (status != 0)
413 {
414 if (status != EAGAIN && status != EINTR)
415 {
416 mpd->func = NULL;
417 mpd->state = 0;
418 }
419 return status;
420 }
421 if (strncasecmp (bio->buffer, "+OK", 3) != 0)
422 return EACCES;
423
424 /* FIXME use snprintf */
425 //mpd->len = snprintf (mpd->buffer, POP_BUFSIZ, "PASS %s\r\n", passwd);
426 bio->len = sprintf (bio->buffer, "PASS %s\r\n", mpd->passwd);
427 bio->ptr = bio->buffer;
428 free (mpd->passwd); mpd->passwd = NULL;
429 mpd->state = 4;
430 /* send Passwd */
431 case 4:
432 status = bio_write (bio);
433 if (status != 0)
434 {
435 if (status != EAGAIN && status != EINTR)
436 {
437 mpd->func = NULL;
438 mpd->state = 0;
439 }
440 return status;
441 }
442 mpd->state = 5;
443 /* get the ack from passwd */
444 case 5:
445 status = bio_readline (bio);
446 if (status != 0)
447 {
448 if (status != EAGAIN && status != EINTR)
449 {
450 mpd->func = NULL;
451 mpd->state = 0;
452 }
453 return status;
454 }
455 if (strncasecmp (bio->buffer, "+OK", 3) != 0)
456 return EACCES;
457 }/* swith state */
458
459 /* spawn cleanup functions */
460 if (mbox->auth)
461 auth_epilogue (mbox->auth);
462
463 /* clear any state */
464 mpd->func = NULL;
465 mpd->state = 0;
466
467 return 0;
468 }
469
470 static int
471 mailbox_pop_close (mailbox_t mbox)
472 {
473 mailbox_pop_data_t mpd;
474 //mailbox_pop_message_t mpm;
475
476 if (mbox == NULL || (mpd = mbox->data) == NULL)
477 return EINVAL;
478
479 if (mpd->fd != -1)
480 close (mpd->fd);
481 mpd->fd = -1;
482
483 return 0;
484 }
485
486 static int
487 mailbox_pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
488 {
489 mailbox_pop_data_t mpd;
490 bio_t bio;
491 int status;
492 size_t i;
493 void *func = mailbox_pop_get_message;
494
495 /* sanity */
496 if (mbox == NULL || pmsg == NULL || (mpd = mbox->data) == NULL)
497 return EINVAL;
498
499 /* see if we already have this message */
500 for (i = 0; i < mpd->pmessages_count; i++)
501 {
502 if (mpd->pmessages[i])
503 {
504 if (mpd->pmessages[i]->num == msgno)
505 {
506 *pmsg = mpd->pmessages[i]->message;
507 return 0;
508 }
509 }
510 }
511
512 /* are we busy in another function ? */
513 if (mpd->func && mpd->func != func)
514 return EBUSY;
515
516 /* In the function, but are we busy with an other message/request ? */
517 if (mpd->id && mpd->id != *pmsg)
518 return EBUSY;
519
520 mpd->func = func;
521 bio = mpd->bio;
522
523 /* Ok men, we're going in */
524 switch (mpd->state)
525 {
526 /* the message */
527 case 0:
528 {
529 message_t msg;
530 mailbox_pop_message_t mpm ;
531
532 mpm = calloc (1, sizeof (*mpm));
533 if (mpm == NULL)
534 return ENOMEM;
535
536 /* we'll use the bio to store headers */
537 mpm->bio = calloc (1, sizeof (*(mpm->bio)));
538 if (mpm->bio == NULL)
539 {
540 free (mpm);
541 mpd->func = NULL;
542 return ENOMEM;
543 }
544
545 /* create the message */
546 status = message_create (&msg, mpm);
547 if (status != 0)
548 {
549 free (mpm->bio);
550 free (mpm);
551 mpd->func = NULL;
552 return status;
553 }
554
555 /* the message */
556 mpm->message = msg;
557 mpm->num = msgno;
558 mpd->mpm = mpm;
559 /* back pointer */
560 mpm->mpd = mpd;
561 /* set the busy request state */
562 mpd->id = (void *)msg;
563
564 /*
565 * Get the header.
566 * FIXME: TOP is an optionnal command, if we want to
567 * be compliant we can not count on it to exists.
568 * So we should be prepare when it fails and fall to
569 * a second scheme
570 */
571 /*bio->len = snprintf (bio->buffer, POP_BUFSIZ, "TOP %d 0\r\n", msgno);*/
572 bio->len = sprintf (bio->buffer, "TOP %d 0\r\n", msgno);
573 bio->ptr = bio->buffer;
574 mpd->state = 1;
575 }
576 /* send the TOP */
577 case 1:
578 {
579 status = bio_write (bio);
580 if (status != 0)
581 {
582 if (status != EAGAIN && status != EINTR)
583 {
584 mpd->func = mpd->id = NULL;
585 mpd->state = 0;
586 message_destroy (&(mpd->mpm->message), mpd->mpm);
587 bio_destroy (&(mpd->mpm->bio));
588 free (mpd->mpm);
589 mpd->mpm = NULL;
590 }
591 return status;
592 }
593 mpd->state = 2;
594 }
595 /* ack from TOP */
596 case 2:
597 {
598 status = bio_readline (bio);
599 if (status != 0)
600 {
601 if (status != EAGAIN && status != EINTR)
602 {
603 mpd->func = mpd->id = NULL;
604 mpd->state = 0;
605 message_destroy (&(mpd->mpm->message), mpd->mpm);
606 bio_destroy (&(mpd->mpm->bio));
607 free (mpd->mpm);
608 mpd->mpm = NULL;
609 }
610 return status;
611 }
612 if (strncasecmp (bio->buffer, "+OK", 3) != 0)
613 {
614 mpd->func = mpd->id = NULL;
615 mpd->state = 0;
616 message_destroy (&(mpd->mpm->message), mpd->mpm);
617 bio_destroy (&(mpd->mpm->bio));
618 free (mpd->mpm);
619 mpd->mpm = NULL;
620 return ERANGE;
621 }
622 mpd->state = 5;
623 }
624 /* get the header */
625 case 5:
626 {
627 char *tbuf;
628 int nread;
629 while (1)
630 {
631 status = bio_readline (bio);
632 if (status != 0)
633 {
634 /* recoverable */
635 if (status != EAGAIN && status != EINTR)
636 {
637 mpd->func = mpd->id = NULL;
638 mpd->state = 0;
639 message_destroy (&(mpd->mpm->message), mpd->mpm);
640 bio_destroy (&(mpd->mpm->bio));
641 free (mpd->mpm);
642 mpd->mpm = NULL;
643 }
644 return status;
645 }
646
647 /* our ticket out */
648 if (bio->buffer[0] == '\0')
649 {
650 mpd->mpm->bio->buffer[mpd->mpm->bio->maxlen + 1] = '\0';
651 break;
652 }
653
654 nread = (bio->nl) ? bio->nl - bio->buffer :
655 bio->ptr - bio->buffer + 1;
656
657 tbuf = realloc (mpd->mpm->bio->buffer,
658 mpd->mpm->bio->maxlen + nread + 1);
659 if (tbuf == NULL)
660 {
661 mpd->func = mpd->id = NULL;
662 mpd->state = 0;
663 message_destroy (&(mpd->mpm->message), mpd->mpm);
664 bio_destroy (&(mpd->mpm->bio));
665 free (mpd->mpm);
666 mpd->mpm = NULL;
667 return ENOMEM;
668 }
669 else
670 mpd->mpm->bio->buffer = (void *)tbuf;
671 memcpy (mpd->mpm->bio->buffer + mpd->mpm->bio->maxlen,
672 bio->buffer, nread);
673 mpd->mpm->bio->maxlen += nread;
674 } /* while () */
675 } /* case 5: */
676 break;
677 default:
678 /* error here unknow case */
679 fprintf (stderr, "Pop unknown state(get_message)\n");
680 } /* switch (state) */
681
682 /* no need to carry a state anymore */
683 mpd->func = mpd->id = NULL;
684 mpd->state = 0;
685
686 /* create the header */
687 {
688 header_t header;
689 status = header_create (&header, mpd->mpm->bio->buffer,
690 mpd->mpm->bio->maxlen, mpd->mpm);
691 bio_destroy (&(mpd->mpm->bio));
692 if (status != 0)
693 {
694 message_destroy (&(mpd->mpm->message), mpd->mpm);
695 free (mpd->mpm);
696 mpd->mpm = NULL;
697 return status;
698 }
699 message_set_header ((mpd->mpm->message), header, mpd->mpm);
700 }
701
702 /* reallocate the working buffer */
703 bio_create (&(mpd->mpm->bio), mpd->fd);
704
705 /* create the attribute */
706 {
707 attribute_t attribute;
708 char hdr_status[64];
709 header_t header = NULL;
710 hdr_status[0] = '\0';
711 message_get_header (mpd->mpm->message, &header);
712 header_get_value (header, "Status", hdr_status, sizeof (hdr_status), NULL);
713 /* create the attribute */
714 status = string_to_attribute (hdr_status, &attribute);
715 if (status != 0)
716 {
717 message_destroy (&(mpd->mpm->message), mpd->mpm);
718 bio_destroy (&(mpd->mpm->bio));
719 free (mpd->mpm);
720 mpd->mpm = NULL;
721 return status;
722 }
723 message_set_attribute (mpd->mpm->message, attribute, mpd->mpm);
724 }
725
726 /* create the body */
727 {
728 stream_t stream;
729 body_t body;
730 status = body_create (&body, mpd->mpm);
731 if (status != 0)
732 {
733 message_destroy (&(mpd->mpm->message), mpd->mpm);
734 bio_destroy (&(mpd->mpm->bio));
735 free (mpd->mpm);
736 mpd->mpm = NULL;
737 return status;
738 }
739 message_set_body (mpd->mpm->message, body, mpd->mpm);
740 status = stream_create (&stream, MU_STREAM_READ, mpd->mpm);
741 if (status != 0)
742 {
743 message_destroy (&(mpd->mpm->message), mpd->mpm);
744 bio_destroy (&(mpd->mpm->bio));
745 free (mpd->mpm);
746 mpd->mpm = NULL;
747 return status;
748 }
749 stream_set_read (stream, mailbox_pop_readstream, mpd->mpm);
750 stream_set_fd (stream, mailbox_pop_getfd, mpd->mpm);
751 body_set_size (body, mailbox_pop_body_size, mpd->mpm);
752 //body_set_lines (body, mailbox_pop_body_lines, mpd->mpm);
753 body_set_stream (body, stream, mpd->mpm);
754 }
755
756
757 /* add it to the list */
758 {
759 mailbox_pop_message_t *m ;
760 m = realloc (mpd->pmessages, (mpd->pmessages_count + 1)*sizeof (*m));
761 if (m == NULL)
762 {
763 message_destroy (&(mpd->mpm->message), mpd->mpm);
764 free (mpd->mpm);
765 mpd->mpm = NULL;
766 return ENOMEM;
767 }
768 mpd->pmessages = m;
769 mpd->pmessages[mpd->pmessages_count] = mpd->mpm;
770 mpd->pmessages_count++;
771 }
772
773 *pmsg = mpd->mpm->message;
774
775 return 0;
776 }
777
778 static int
779 mailbox_pop_messages_count (mailbox_t mbox, size_t *pcount)
780 {
781 mailbox_pop_data_t mpd;
782 int status;
783 void *func = mailbox_pop_messages_count;
784 bio_t bio;
785
786 if (mbox == NULL || (mpd = (mailbox_pop_data_t)mbox->data) == NULL)
787 return EINVAL;
788
789 if (mailbox_pop_is_updated (mbox))
790 {
791 if (pcount)
792 *pcount = mpd->messages_count;
793 return 0;
794 }
795
796 if (mpd->func && mpd->func != func)
797 return EBUSY;
798
799 mpd->func = func;
800 bio = mpd->bio;
801 switch (mpd->state)
802 {
803 case 0:
804 bio->len = sprintf (bio->buffer, "STAT\r\n");
805 bio->ptr = bio->buffer;
806 mpd->state = 1;
807 /* Send the STAT */
808 case 1:
809 status = bio_write (bio);
810 if (status != 0)
811 return status;
812 mpd->state = 2;
813 /* get the ACK */
814 case 2:
815 status = bio_readline (bio);
816 if (status != 0)
817 return status;
818 break;
819 default:
820 fprintf (stderr, "unknow state(messages_count)\n");
821 }
822 mpd->id = mpd->func = NULL;
823 mpd->state = 0;
824
825 status = sscanf (bio->buffer, "+OK %d %d", &(mpd->messages_count),
826 &(mpd->size));
827 mpd->is_updated = 1;
828 if (pcount)
829 *pcount = mpd->messages_count;
830 if (status == EOF || status != 2)
831 return EIO;
832 return 0;
833 }
834
835
836 /* update and scanning*/
39 static int 837 static int
40 mailbox_pop_create (mailbox_t *mbox, const char *name) 838 mailbox_pop_is_updated (mailbox_t mbox)
41 { 839 {
42 (void)mbox; (void)name; 840 mailbox_pop_data_t mpd;
43 return ENOSYS; 841 if ((mpd = (mailbox_pop_data_t)mbox->data) == NULL)
842 return 0;
843 return mpd->is_updated;
844 }
845
846 static int
847 mailbox_pop_num_deleted (mailbox_t mbox, size_t *pnum)
848 {
849 mailbox_pop_data_t mpd;
850 size_t i, total;
851 attribute_t attr;
852 if (mbox == NULL ||
853 (mpd = (mailbox_pop_data_t) mbox->data) == NULL)
854 return EINVAL;
855 for (i = total = 0; i < mpd->messages_count; i++)
856 {
857 if (message_get_attribute (mpd->pmessages[i]->message, &attr) != 0)
858 {
859 if (attribute_is_deleted (attr))
860 total++;
861 }
862 }
863
864 if (pnum)
865 *pnum = total;
866 return 0;
867 }
868
869 /* We just simulated */
870 static int
871 mailbox_pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
872 {
873 int status;
874 size_t i;
875 status = mailbox_pop_messages_count (mbox, pcount);
876 if (status != 0)
877 return status;
878 for (i = msgno; i < *pcount; i++)
879 if (mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD) != 0)
880 break;
881 return 0;
882 }
883
884 /* This were we actually sending the DELE command */
885 static int
886 mailbox_pop_expunge (mailbox_t mbox)
887 {
888 mailbox_pop_data_t mpd;
889 size_t i;
890 attribute_t attr;
891
892 if (mbox == NULL ||
893 (mpd = (mailbox_pop_data_t) mbox->data) == NULL)
894 return EINVAL;
895 for (i = 0; i < mpd->messages_count; i++)
896 {
897 if (message_get_attribute (mpd->pmessages[i]->message, &attr) != 0)
898 {
899 if (attribute_is_deleted (attr))
900 {
901 }
902 }
903 }
904
905 return 0;
906 }
907
908 /* mailbox size ? */
909 static int
910 mailbox_pop_size (mailbox_t mbox, off_t *psize)
911 {
912 mailbox_pop_data_t mpd;
913 size_t count;
914 int status;
915
916 if (mbox == NULL || (mpd = (mailbox_pop_data_t)mbox->data) == NULL)
917 return EINVAL;
918
919 if (mailbox_pop_is_updated (mbox))
920 {
921 if (psize)
922 *psize = mpd->size;
923 return 0;
924 }
925 status = mailbox_pop_messages_count (mbox, &count);
926 if (psize)
927 *psize = mpd->size;
928 return status;
929 }
930
931 static int
932 mailbox_pop_body_size (body_t body, size_t *psize)
933 {
934 mailbox_pop_message_t mpm;
935 if (body == NULL || (mpm = body->owner) == NULL)
936 return EINVAL;
937 if (psize)
938 *psize = mpm->body_size;
939 return 0;
940 }
941
942 static int
943 mailbox_pop_getfd (stream_t stream, int *pfd)
944 {
945 mailbox_pop_message_t mpm;
946 if (stream == NULL || (mpm = stream->owner) == NULL)
947 return EINVAL;
948 if (pfd)
949 *pfd = mpm->bio->fd;
950 return 0;
951 }
952
953 static int
954 mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen,
955 off_t offset, size_t *pnread)
956 {
957 mailbox_pop_message_t mpm;
958 mailbox_pop_data_t mpd;
959 size_t nread = 0;
960 bio_t bio;
961 int status = 0;
962 void *func = mailbox_pop_readstream;
963
964 (void)offset;
965 if (is == NULL || (mpm = is->owner) == NULL)
966 return EINVAL;
967
968 if (buffer == NULL || buflen == 0)
969 {
970 if (pnread)
971 *pnread = nread;
972 return 0;
973 }
974
975 bio = mpm->bio;
976 mpd = mpm->mpd;
977
978 /* busy ? */
979 if (mpd->func && mpd->func != func)
980 return EBUSY;
981
982 /* which request */
983 if (mpd->id && mpd->id != mpm)
984 return EBUSY;
985
986 mpd->func = func;
987 mpd->id = mpm;
988
989 switch (mpd->state)
990 {
991 /* send the RETR command */
992 case 0:
993 bio->len = sprintf (bio->buffer, "RETR %d\r\n", mpm->num);
994 mpd->state = 1;
995 case 1:
996 status = bio_write (bio);
997 if (status != 0)
998 {
999 if (status != EAGAIN && status != EINTR)
1000 {
1001 mpd->func = mpd->id = NULL;
1002 mpd->state = 0;
1003 }
1004 return status;
1005 }
1006 mpd->state = 2;
1007 /* RETR ACK */
1008 case 2:
1009 status = bio_readline (bio);
1010 if (status != 0)
1011 {
1012 if (status != EAGAIN && status != EINTR)
1013 {
1014 mpd->func = mpd->id = NULL;
1015 mpd->state = 0;
1016 }
1017 return status;
1018 }
1019 if (strncasecmp (bio->buffer, "+OK", 3) != 0)
1020 return EINVAL;
1021 mpd->state = 3;
1022 /* skip the header */
1023 case 3:
1024 while (!mpm->inbody)
1025 {
1026 status = bio_readline (bio);
1027 if (status != 0)
1028 {
1029 if (status != EAGAIN && status != EINTR)
1030 {
1031 mpd->func = mpd->id = NULL;
1032 mpd->state = 0;
1033 }
1034 return status;
1035 }
1036 if (bio->buffer[0] == '\n')
1037 {
1038 mpm->inbody = 1;
1039 break;
1040 }
1041 }
1042 /* skip the newline */
1043 bio_readline (bio);
1044 /* start taking the header */
1045 mpd->state = 4;
1046 bio->current = bio->buffer;
1047 case 4:
1048 {
1049 int nleft, n;
1050 /* do we need to fill up */
1051 if (bio->current >= bio->nl)
1052 {
1053 bio->current = bio->buffer;
1054 status = bio_readline (bio);
1055 if (status != 0)
1056 {
1057 if (status != EAGAIN && status != EINTR)
1058 {
1059 mpd->func = mpd->id = NULL;
1060 mpd->state = 0;
1061 }
1062 }
1063 }
1064 n = bio->nl - bio->current;
1065 nleft = buflen - n;
1066 /* we got more then requested */
1067 if (nleft <= 0)
1068 {
1069 memcpy (buffer, bio->current, buflen);
1070 bio->current += buflen;
1071 nread = buflen;
1072 }
1073 else
1074 {
1075 /* drain the buffer */
1076 memcpy (buffer, bio->current, n);
1077 bio->current += n;
1078 nread = n;
1079 }
1080 }
1081 } /* switch state */
1082
1083 if (nread == 0)
1084 {
1085 mpd->func = mpd->id = NULL;
1086 mpd->state = 0;
1087 }
1088 if (pnread)
1089 *pnread = nread;
1090 return 0;
1091 }
1092
1093 static int
1094 bio_create (bio_t *pbio, int fd)
1095 {
1096 bio_t bio;
1097 bio = calloc (1, sizeof (*bio));
1098 if (bio == NULL)
1099 return ENOMEM;
1100 bio->maxlen = POP_BUFSIZ + 1;
1101 bio->current = bio->ptr = bio->buffer = calloc (1, POP_BUFSIZ + 1);
1102 if (bio->buffer == NULL)
1103 {
1104 free (bio);
1105 return ENOMEM;
1106 }
1107 bio->fd = fd;
1108 *pbio = bio;
1109 return 0;
1110 }
1111
1112 static void
1113 bio_destroy (bio_t *pbio)
1114 {
1115 if (pbio && *pbio)
1116 {
1117 bio_t bio = *pbio;
1118 free (bio->buffer);
1119 free (bio);
1120 *pbio = NULL;
1121 }
1122 }
1123
1124 static int
1125 bio_write (bio_t bio)
1126 {
1127 int nwritten;
1128
1129 while (bio->len > 0)
1130 {
1131 nwritten = write (bio->fd, bio->ptr, bio->len);
1132 if (nwritten < 0)
1133 return errno;
1134 bio->len -= nwritten;
1135 bio->ptr += nwritten;
1136 }
1137
1138 bio->ptr = bio->buffer;
1139 return 0;
1140 }
1141
1142 static int
1143 bio_read (bio_t bio)
1144 {
1145 int nread, len;
1146
1147 len = bio->maxlen - (bio->ptr - bio->buffer) - 1;
1148 nread = read (bio->fd, bio->ptr, len);
1149 if (nread < 0)
1150 return errno;
1151 else if (nread == 0)
1152 { /* EOF ???? We got a situation here ??? */
1153 bio->buffer[0] = '.';
1154 bio->buffer[1] = '\r';
1155 bio->buffer[2] = '\n';
1156 nread = 3;
1157 }
1158 bio->ptr[nread] = '\0';
1159 bio->ptr += nread;
1160 return 0;
1161 }
1162
1163 /*
1164 * Responses to certain commands are multi-line. In these cases, which
1165 * are clearly indicated below, after sending the first line of the
1166 * response and a CRLF, any additional lines are sent, each terminated
1167 * by a CRLF pair. When all lines of the response have been sent, a
1168 * final line is sent, consisting of a termination octet (decimal code
1169 * 046, ".") and a CRLF pair.
1170 */
1171 static int
1172 bio_readline (bio_t bio)
1173 {
1174 size_t len;
1175 int status;
1176
1177 /* Still unread lines in the buffer ? */
1178 if (bio->nl && bio->nl < bio->ptr)
1179 {
1180 memmove (bio->buffer, bio->nl + 1, bio->ptr - bio->nl);
1181 bio->ptr = bio->buffer + (bio->ptr - bio->nl) - 1;
1182 bio->nl = memchr (bio->buffer, '\n', bio->ptr - bio->buffer + 1);
1183 //if (bio->nl == NULL)
1184 //bio->nl = bio->buffer;
1185 }
1186 else
1187 bio->nl = bio->ptr = bio->buffer;
1188
1189 if (bio->nl == NULL || bio->nl == bio->ptr)
1190 {
1191 for (;;)
1192 {
1193 status = bio_read (bio);
1194 if (status < 0)
1195 return status;
1196 len = bio->ptr - bio->buffer;
1197 /* a newline */
1198 bio->nl = memchr (bio->buffer, '\n', len);
1199 if (bio->nl == NULL)
1200 {
1201 if (len >= bio->maxlen)
1202 {
1203 char *tbuf = realloc (bio->buffer,
1204 (2*(bio->maxlen) + 1)*(sizeof(char)));
1205 if (tbuf == NULL)
1206 return ENOMEM;
1207 bio->buffer = tbuf;
1208 bio->maxlen *= 2;
1209 }
1210 bio->ptr = bio->buffer + len;
1211 }
1212 else
1213 break;
1214 }
1215 }
1216
1217 /*
1218 * When examining a multi-line response, the client checks
1219 * to see if the line begins with the termination octet "."(DOT).
1220 * If so and if octets other than CRLF follow, the first octet
1221 * of the line (the termination octet) is stripped away.
1222 */
1223 if (bio->buffer[0] == '.')
1224 {
1225 if (bio->buffer[1] != '\r' && bio->buffer[2] != '\n')
1226 {
1227 memmove (bio->buffer, bio->buffer + 1, bio->ptr - bio->buffer);
1228 bio->ptr--;
1229 bio->nl--;
1230 }
1231 /* If so and if CRLF immediately
1232 * follows the termination character, then the response from the POP
1233 * server is ended and the line containing ".CRLF" is not considered
1234 * part of the multi-line response.
1235 */
1236 else if (bio->buffer[1] == '\r' && bio->buffer[2] == '\n')
1237 {
1238 bio->buffer[0] = '\0';
1239 bio->nl = bio->ptr = bio->buffer;
1240 return 0;
1241 }
1242 }
1243
1244 /* \r\n --> \n\0 */
1245 if (bio->nl > bio->buffer)
1246 {
1247 *(bio->nl - 1) = '\n';
1248 *(bio->nl) = '\0';
1249 }
1250
1251 return 0;
44 } 1252 }
......
...@@ -313,8 +313,8 @@ mailbox_unix_destroy (mailbox_t *pmbox) ...@@ -313,8 +313,8 @@ mailbox_unix_destroy (mailbox_t *pmbox)
313 continue; 313 continue;
314 /* Destroy the attach messages */ 314 /* Destroy the attach messages */
315 message_destroy (&(mum->message), mum); 315 message_destroy (&(mum->message), mum);
316 attribute_destroy (&(mum->old_attr), mbox); 316 attribute_destroy (&(mum->old_attr));
317 attribute_destroy (&(mum->new_attr), mbox); 317 attribute_destroy (&(mum->new_attr));
318 free (mum); 318 free (mum);
319 } 319 }
320 free (mud->umessages); 320 free (mud->umessages);
...@@ -399,7 +399,11 @@ mailbox_unix_open (mailbox_t mbox, int flags) ...@@ -399,7 +399,11 @@ mailbox_unix_open (mailbox_t mbox, int flags)
399 /* Authentication */ 399 /* Authentication */
400 if (mbox->auth) 400 if (mbox->auth)
401 { 401 {
402 int status = auth_authenticate (mbox->auth); 402 char *user = NULL;
403 char *passwd = NULL;
404 int status = auth_authenticate (mbox->auth, &user, &passwd);
405 free (user);
406 free (passwd);
403 if (status != 0) 407 if (status != 0)
404 return status; 408 return status;
405 } 409 }
...@@ -516,7 +520,7 @@ mailbox_unix_is_updated (mailbox_t mbox) ...@@ -516,7 +520,7 @@ mailbox_unix_is_updated (mailbox_t mbox)
516 } 520 }
517 521
518 static int 522 static int
519 mailbox_unix_num_deleted (mailbox_t mbox, size_t *num) 523 mailbox_unix_num_deleted (mailbox_t mbox, size_t *pnum)
520 { 524 {
521 mailbox_unix_data_t mud; 525 mailbox_unix_data_t mud;
522 mailbox_unix_message_t mum; 526 mailbox_unix_message_t mum;
...@@ -531,8 +535,8 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *num) ...@@ -531,8 +535,8 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *num)
531 total++; 535 total++;
532 } 536 }
533 537
534 if (num) 538 if (pnum)
535 *num = total; 539 *pnum = total;
536 return 0; 540 return 0;
537 } 541 }
538 542
...@@ -894,7 +898,7 @@ mailbox_unix_getfd (stream_t is, int *pfd) ...@@ -894,7 +898,7 @@ mailbox_unix_getfd (stream_t is, int *pfd)
894 { 898 {
895 mailbox_unix_message_t mum; 899 mailbox_unix_message_t mum;
896 900
897 if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL) 901 if (is == NULL || (mum = is->owner) == NULL)
898 return EINVAL; 902 return EINVAL;
899 if (pfd) 903 if (pfd)
900 *pfd = fileno (mum->file); 904 *pfd = fileno (mum->file);
...@@ -908,7 +912,7 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, ...@@ -908,7 +912,7 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen,
908 mailbox_unix_message_t mum; 912 mailbox_unix_message_t mum;
909 size_t nread = 0; 913 size_t nread = 0;
910 914
911 if (is == NULL || (mum = is->owner) == NULL) 915 if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL)
912 return EINVAL; 916 return EINVAL;
913 917
914 if (buffer == NULL || buflen == 0) 918 if (buffer == NULL || buflen == 0)
...@@ -1169,7 +1173,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) ...@@ -1169,7 +1173,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
1169 } 1173 }
1170 message_set_body (msg, body, mum); 1174 message_set_body (msg, body, mum);
1171 1175
1172 status = stream_create (&stream, 0, mum); 1176 status = stream_create (&stream, MU_STREAM_READ, mum);
1173 if (status != 0) 1177 if (status != 0)
1174 { 1178 {
1175 message_destroy (&msg, mum); 1179 message_destroy (&msg, mum);
......
...@@ -254,7 +254,7 @@ do \ ...@@ -254,7 +254,7 @@ do \
254 } while (0) 254 } while (0)
255 255
256 /* skip a function call, ?? do we gain that much */ 256 /* skip a function call, ?? do we gain that much */
257 #define ATTRIBUTE_CREATE(attr,own) \ 257 #define ATTRIBUTE_CREATE(attr,mbox) \
258 do \ 258 do \
259 { \ 259 { \
260 attr = calloc (1, sizeof(*(attr))); \ 260 attr = calloc (1, sizeof(*(attr))); \
...@@ -265,7 +265,6 @@ do \ ...@@ -265,7 +265,6 @@ do \
265 mailbox_unix_unlock (mbox); \ 265 mailbox_unix_unlock (mbox); \
266 return ENOMEM; \ 266 return ENOMEM; \
267 } \ 267 } \
268 (attr)->owner = own; \
269 } while (0) 268 } while (0)
270 269
271 /* allocate slots for the new messages */ 270 /* allocate slots for the new messages */
......
...@@ -47,7 +47,7 @@ message_create (message_t *pmsg, void *owner) ...@@ -47,7 +47,7 @@ message_create (message_t *pmsg, void *owner)
47 msg = calloc (1, sizeof (*msg)); 47 msg = calloc (1, sizeof (*msg));
48 if (msg == NULL) 48 if (msg == NULL)
49 return ENOMEM; 49 return ENOMEM;
50 status = stream_create (&stream, 0, msg); 50 status = stream_create (&stream, MU_STREAM_RDWR, msg);
51 if (status != 0) 51 if (status != 0)
52 { 52 {
53 free (msg); 53 free (msg);
...@@ -92,7 +92,7 @@ message_destroy (message_t *pmsg, void *owner) ...@@ -92,7 +92,7 @@ message_destroy (message_t *pmsg, void *owner)
92 /* header */ 92 /* header */
93 header_destroy (&header, owner); 93 header_destroy (&header, owner);
94 /* attribute */ 94 /* attribute */
95 attribute_destroy (&attribute, owner); 95 attribute_destroy (&attribute);
96 /* stream */ 96 /* stream */
97 stream_destroy (&stream, owner); 97 stream_destroy (&stream, owner);
98 98
...@@ -188,7 +188,7 @@ message_get_stream (message_t msg, stream_t *pstream) ...@@ -188,7 +188,7 @@ message_get_stream (message_t msg, stream_t *pstream)
188 { 188 {
189 stream_t stream; 189 stream_t stream;
190 int status; 190 int status;
191 status = stream_create (&stream, 0, msg); 191 status = stream_create (&stream, MU_STREAM_RDWR, msg);
192 if (status != 0) 192 if (status != 0)
193 return status; 193 return status;
194 stream_set_read (stream, message_read, msg); 194 stream_set_read (stream, message_read, msg);
...@@ -350,7 +350,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute) ...@@ -350,7 +350,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute)
350 if (msg->attribute == NULL && msg->owner == NULL) 350 if (msg->attribute == NULL && msg->owner == NULL)
351 { 351 {
352 attribute_t attribute; 352 attribute_t attribute;
353 int status = attribute_create (&attribute, msg); 353 int status = attribute_create (&attribute);
354 if (status != 0) 354 if (status != 0)
355 return status; 355 return status;
356 msg->attribute = attribute; 356 msg->attribute = attribute;
...@@ -366,7 +366,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) ...@@ -366,7 +366,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
366 return EINVAL; 366 return EINVAL;
367 if (msg->owner != owner) 367 if (msg->owner != owner)
368 return EACCES; 368 return EACCES;
369 attribute_destroy (&(msg->attribute), msg); 369 attribute_destroy (&(msg->attribute));
370 msg->attribute = attribute; 370 msg->attribute = attribute;
371 return 0; 371 return 0;
372 } 372 }
......
...@@ -83,17 +83,6 @@ static int _mime_append_part(mime_t mime, message_t msg, int body_offset, int bo ...@@ -83,17 +83,6 @@ static int _mime_append_part(mime_t mime, message_t msg, int body_offset, int bo
83 return 0; 83 return 0;
84 } 84 }
85 85
86 static struct _mime_part *_mime_get_owner(mime_t mime, message_t msg)
87 {
88 int i;
89
90 for ( i = 0; i < mime->nmtp_parts; i++ ) {
91 if ( mime->mtp_parts[i] == msg->owner )
92 return mime->mtp_parts[i];
93 }
94 return NULL;
95 }
96
97 static char *_strltrim(char *str) 86 static char *_strltrim(char *str)
98 { 87 {
99 char *p; 88 char *p;
...@@ -119,7 +108,7 @@ char *_strtrim(char *str); ...@@ -119,7 +108,7 @@ char *_strtrim(char *str);
119 #define _ISSPECIAL(c) ( \ 108 #define _ISSPECIAL(c) ( \
120 ((c) == '(') || ((c) == ')') || ((c) == '<') || ((c) == '>') \ 109 ((c) == '(') || ((c) == ')') || ((c) == '<') || ((c) == '>') \
121 || ((c) == '@') || ((c) == ',') || ((c) == ';') || ((c) == ':') \ 110 || ((c) == '@') || ((c) == ',') || ((c) == ';') || ((c) == ':') \
122 || ((c) == '\\') || ((c) == '"') || ((c) == '.') || ((c) == '[') \ 111 || ((c) == '\\') || ((c) == '.') || ((c) == '[') \
123 || ((c) == ']') ) 112 || ((c) == ']') )
124 113
125 static void _mime_munge_content_header(char *field_body ) 114 static void _mime_munge_content_header(char *field_body )
...@@ -129,23 +118,26 @@ static void _mime_munge_content_header(char *field_body ) ...@@ -129,23 +118,26 @@ static void _mime_munge_content_header(char *field_body )
129 118
130 _strtrim(field_body); 119 _strtrim(field_body);
131 120
132 if ( ( e = p = strchr(str, ';') ) == NULL ) 121 if ( ( e = strchr(str, ';') ) == NULL )
133 return; 122 return;
134 e++; 123 while( *e == ';' ) {
135 while ( *e && isspace(*e) ) /* remove space upto param */ 124 p = e;
136 e++; 125 e++;
137 memmove(p+1, e, strlen(e)+1); 126 while ( *e && isspace(*e) ) /* remove space upto param */
138 e = p+1; 127 e++;
139 128 memmove(p+1, e, strlen(e)+1);
140 while ( *e && *e != '=' ) /* find end of value */ 129 e = p+1;
141 e++; 130
142 e = p = e+1; 131 while ( *e && *e != '=' ) /* find end of value */
143 while ( *e && (quoted || !_ISSPECIAL(*e) || !isspace(*e) ) ) { 132 e++;
144 if ( *e == '\\' ) { /* escaped */ 133 e = p = e+1;
145 memmove(e, e+1, strlen(e)+2); 134 while ( *e && (quoted || ( !_ISSPECIAL(*e) && !isspace(*e) ) ) ) {
146 } else if ( *e == '\"' ) 135 if ( *e == '\\' ) { /* escaped */
147 quoted = ~quoted; 136 memmove(e, e+1, strlen(e)+2);
148 e++; 137 } else if ( *e == '\"' )
138 quoted = ~quoted;
139 e++;
140 }
149 } 141 }
150 } 142 }
151 143
...@@ -164,7 +156,7 @@ static char *_mime_get_param(char *field_body, const char *param, int *len) ...@@ -164,7 +156,7 @@ static char *_mime_get_param(char *field_body, const char *param, int *len)
164 break; 156 break;
165 *len = 0; 157 *len = 0;
166 v = e = v + 1; 158 v = e = v + 1;
167 while ( *e && (quoted || !_ISSPECIAL(*e) || !isspace(*e) ) ) { /* skip pass value and calc len */ 159 while ( *e && (quoted || ( !_ISSPECIAL(*e) && !isspace(*e) ) ) ) { /* skip pass value and calc len */
168 if ( *e == '\"' ) 160 if ( *e == '\"' )
169 quoted = ~quoted, was_quoted = 1; 161 quoted = ~quoted, was_quoted = 1;
170 else 162 else
...@@ -256,6 +248,8 @@ static int _mime_parse_mpart_message(mime_t mime) ...@@ -256,6 +248,8 @@ static int _mime_parse_mpart_message(mime_t mime)
256 _mime_append_part(mime, NULL, body_offset, body_length, FALSE ); 248 _mime_append_part(mime, NULL, body_offset, body_length, FALSE );
257 if ( ( cp2 + blength + 2 < cp && !strncasecmp(cp2+2+blength, "--",2) ) || 249 if ( ( cp2 + blength + 2 < cp && !strncasecmp(cp2+2+blength, "--",2) ) ||
258 !strncasecmp(cp2+blength, "--",2) ) { /* very last boundary */ 250 !strncasecmp(cp2+blength, "--",2) ) { /* very last boundary */
251 mime->parser_state = MIME_STATE_BEGIN_LINE;
252 mime->header_length = 0;
259 break; 253 break;
260 } 254 }
261 mime->line_ndx = -1; /* headers parsing requires empty line */ 255 mime->line_ndx = -1; /* headers parsing requires empty line */
...@@ -293,6 +287,8 @@ static int _mime_parse_mpart_message(mime_t mime) ...@@ -293,6 +287,8 @@ static int _mime_parse_mpart_message(mime_t mime)
293 mime->body_length = body_length; 287 mime->body_length = body_length;
294 mime->body_offset = body_offset; 288 mime->body_offset = body_offset;
295 if ( ret != EAGAIN ) { /* finished cleanup */ 289 if ( ret != EAGAIN ) { /* finished cleanup */
290 if ( mime->header_length ) /* this skips the preamble */
291 _mime_append_part(mime, NULL, body_offset, body_length, FALSE );
296 mime->flags &= ~MIME_PARSER_ACTIVE; 292 mime->flags &= ~MIME_PARSER_ACTIVE;
297 mime->body_offset = mime->body_length = mime->header_length = 0; 293 mime->body_offset = mime->body_length = mime->header_length = 0;
298 } 294 }
...@@ -365,7 +361,7 @@ int mime_create(mime_t *pmime, message_t msg, int flags) ...@@ -365,7 +361,7 @@ int mime_create(mime_t *pmime, message_t msg, int flags)
365 } 361 }
366 } 362 }
367 else { 363 else {
368 if ( ( ret = message_create( &msg, mime ) ) == 0 ) { 364 if ( ( ret = message_create( &(mime->msg), mime ) ) == 0 ) {
369 mime->flags |= MIME_NEW_MESSAGE; 365 mime->flags |= MIME_NEW_MESSAGE;
370 } 366 }
371 } 367 }
...@@ -449,7 +445,7 @@ int mime_get_part(mime_t mime, int part, message_t *msg) ...@@ -449,7 +445,7 @@ int mime_get_part(mime_t mime, int part, message_t *msg)
449 message_set_header(mime_part->msg, mime_part->hdr, mime_part); 445 message_set_header(mime_part->msg, mime_part->hdr, mime_part);
450 header_size(mime_part->hdr, &hsize); 446 header_size(mime_part->hdr, &hsize);
451 if ( ( ret = body_create(&body, mime_part) ) == 0 ) { 447 if ( ( ret = body_create(&body, mime_part) ) == 0 ) {
452 if ( ( ret = stream_create(&stream, 0, mime_part) ) == 0 ) { 448 if ( ( ret = stream_create(&stream, MU_STREAM_READ, mime_part) ) == 0 ) {
453 body_set_size (body, _mime_body_size, mime_part); 449 body_set_size (body, _mime_body_size, mime_part);
454 stream_set_read(stream, _mime_message_read, mime_part); 450 stream_set_read(stream, _mime_message_read, mime_part);
455 body_set_stream(body, stream, mime_part); 451 body_set_stream(body, stream, mime_part);
...@@ -464,82 +460,6 @@ int mime_get_part(mime_t mime, int part, message_t *msg) ...@@ -464,82 +460,6 @@ int mime_get_part(mime_t mime, int part, message_t *msg)
464 return ret; 460 return ret;
465 } 461 }
466 462
467 int mime_unencapsulate(mime_t mime, message_t msg, message_t *newmsg)
468 {
469 size_t size, nbytes;
470 int ret, body_offset = 0, body_length = 0, done = 0;
471 char *content_type, *cp;
472 header_t hdr;
473 stream_t stream;
474 body_t body;
475 struct _mime_part *mime_part;
476
477 if ( mime == NULL || msg == NULL || newmsg == NULL || mime->flags & MIME_NEW_MESSAGE )
478 return EINVAL;
479
480 if ( mime->msg != msg && ( mime_part = _mime_get_owner( mime, msg ) ) == NULL ) /* I don't know about or own this message */
481 return EPERM;
482
483 if ( ( ret = message_get_header(msg, &hdr) ) == 0 ) {
484 if ( ( ret = header_get_value(hdr, "Content-Type", NULL, 0, &size) ) == 0 && size ) {
485 if ( ( content_type = malloc(size+1) ) == NULL )
486 ret = ENOMEM;
487 else if ( ( ret = header_get_value(hdr, "Content-Type", content_type, size+1, 0) ) == 0 ) {
488 _mime_munge_content_header(content_type);
489 if ( strncasecmp(content_type, "message/rfc822", strlen(content_type)) != 0 )
490 ret = EINVAL;
491 else {
492 if ( mime_part ) {
493 body_offset = mime_part->body_offset;
494 body_length = mime_part->body_len;
495 }
496 if ( ( ret = _mime_setup_buffers(mime) ) == 0 ) {
497 mime->line_ndx = 0;
498 mime->cur_offset = body_offset;
499 while ( !done && ( ret = stream_read(mime->stream, mime->cur_buf, mime->buf_size, mime->cur_offset, &nbytes) ) == 0 && nbytes ) {
500 cp = mime->cur_buf;
501 while ( nbytes ) {
502 mime->cur_line[mime->line_ndx] = *cp;
503 mime->line_ndx++;
504 if ( *cp == '\n' ) {
505 _mime_append_header_line(mime);
506 if ( mime->line_ndx == 1 ) {
507 done = 1;
508 break;
509 }
510 mime->line_ndx = 0;
511 }
512 mime->cur_offset++;
513 nbytes--;
514 cp++;
515 }
516 }
517 body_length -= mime->cur_offset - body_offset;
518 body_offset = mime->cur_offset + 1;
519 if ( ( ret = _mime_append_part( mime, NULL, body_offset, body_length, TRUE ) ) == 0 ) {
520 mime_part = mime->cap_msgs[mime->ncap_msgs - 1];
521 if ( ( ret = message_create(&(mime_part->msg), mime_part) ) == 0) {
522 message_set_header(mime_part->msg, mime_part->hdr, mime_part);
523 if ( ( ret = body_create(&body, mime_part) ) == 0 ) {
524 if ( ( ret = stream_create(&stream, 0, mime_part) ) == 0 ) {
525 stream_set_read(stream, _mime_message_read, mime_part);
526 body_set_size (body, _mime_body_size, mime_part);
527 body_set_stream( body, stream, mime_part);
528 *newmsg = mime_part->msg;
529 return 0;
530 }
531 message_destroy(&mime_part->msg, mime_part);
532 }
533 }
534 }
535 }
536 }
537 }
538 }
539 }
540 return ret;
541 }
542
543 int mime_get_num_parts(mime_t mime, int *nmtp_parts) 463 int mime_get_num_parts(mime_t mime, int *nmtp_parts)
544 { 464 {
545 int ret = 0; 465 int ret = 0;
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 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 Library General 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 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
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22
23 #include <net0.h>
24
25 static struct _netregistrar _netreg[1] = { "tcp", _tcp_create, _tcp_set_option, _tcp_destroy };
26
27 int net_api_create(net_t *net, net_t parent, const char *type)
28 {
29 net_t n;
30 int i, napis, ret = 0;
31
32 if ( net == NULL || type == NULL )
33 return EINVAL;
34
35 *net = NULL;
36
37 if ( ( n = calloc(1, sizeof(*n)) ) == NULL )
38 return ENOMEM;
39 napis = sizeof(_netreg) / sizeof(_netreg[0]);
40 for( i = 0; i < napis; i++ ) {
41 if ( strcasecmp(_netreg[i].type, type) == 0 )
42 break;
43 }
44 if ( i == napis )
45 return ENOTSUP;
46 if ( (ret = ( _netreg[i].create(&(n->data), &(n->api)) )) != 0 )
47 free(n);
48 n->parent = parent;
49 n->net_reg = &_netreg[i];
50 *net = n;
51 return 0;
52 }
53
54 int net_api_set_option(net_t net, const char *name, const char *value)
55 {
56 if ( net && name && value )
57 return net->net_reg->set_option(net->data, name, value);
58 return EINVAL;
59 }
60
61 int net_api_destroy(net_t *net)
62 {
63 net_t n;
64 if ( net == NULL || *net == NULL )
65 return EINVAL;
66
67 n = *net;
68 n->net_reg->destroy(&n->data);
69 free(n);
70 *net = NULL;
71 return 0;
72 }
73
74 int net_new(net_t net, netinstance_t *inst)
75 {
76 netinstance_t netinst;
77 int ret = 0;
78
79 if ( net == NULL || inst == NULL )
80 return EINVAL;
81
82 *inst = NULL;
83
84 if ( ( netinst = calloc(1, sizeof(*netinst)) ) == NULL )
85 return ENOMEM;
86 netinst->api = net->api;
87 if ( ( ret = net->api->new(net->data, net->parent, &(netinst->data)) ) != 0 ) {
88 free(netinst);
89 return ret;
90 }
91 *inst = netinst;
92 return 0;
93 }
94
95 int net_connect(netinstance_t inst, const char *host, int port)
96 {
97 if ( inst == NULL || host == NULL )
98 return EINVAL;
99
100 return inst->api->connect(inst->data, host, port);
101 }
102
103 int net_get_stream(netinstance_t inst, stream_t *iostr)
104 {
105 if ( inst == NULL || iostr == NULL )
106 return EINVAL;
107
108 return inst->api->get_stream(inst->data, iostr);
109 }
110
111 int net_close(netinstance_t inst)
112 {
113 if ( inst == NULL )
114 return EINVAL;
115
116 return inst->api->close(inst->data);
117 }
118
119 int net_free(netinstance_t *pinst)
120 {
121 int ret;
122 netinstance_t inst;
123
124 if ( pinst == NULL || *pinst == NULL )
125 return EINVAL;
126
127 inst = *pinst;
128 ret = inst->api->free(&(inst->data));
129 free(inst);
130 *pinst = NULL;
131 return ret;
132 }
...@@ -26,30 +26,46 @@ ...@@ -26,30 +26,46 @@
26 #include <netinet/in.h> 26 #include <netinet/in.h>
27 #include <arpa/inet.h> 27 #include <arpa/inet.h>
28 28
29 #include <net0.h>
30 #include <io0.h> 29 #include <io0.h>
31 #include <tcp.h> 30 #include <tcp.h>
32 31
33 static int _tcp_close(void *data); 32 static int _tcp_close(stream_t stream)
33 {
34 struct _tcp_instance *tcp = stream->owner;
34 35
35 static int _tcp_doconnect(struct _tcp_instance *tcp) 36 if ( tcp->fd != -1 )
37 close(tcp->fd);
38 tcp->fd = -1;
39 tcp->state = TCP_STATE_INIT;
40 return 0;
41 }
42
43 static int _tcp_open(stream_t stream, const char *host, int port, int flags)
36 { 44 {
45 struct _tcp_instance *tcp = stream->owner;
37 int flgs, ret; 46 int flgs, ret;
38 size_t namelen; 47 size_t namelen;
39 struct sockaddr_in peer_addr; 48 struct sockaddr_in peer_addr;
40 struct hostent *phe; 49 struct hostent *phe;
41 struct sockaddr_in soc_addr; 50 struct sockaddr_in soc_addr;
42 51
52 if ( tcp->state == TCP_STATE_INIT ) {
53 tcp->port = port;
54 if ( ( tcp->host = strdup(host) ) == NULL )
55 return ENOMEM;
56 }
57
43 switch( tcp->state ) { 58 switch( tcp->state ) {
44 case TCP_STATE_INIT: 59 case TCP_STATE_INIT:
45 if ( tcp->fd == -1 ) { 60 if ( tcp->fd == -1 ) {
46 if ( ( tcp->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 61 if ( ( tcp->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
47 return errno; 62 return errno;
48 } 63 }
49 if ( tcp->options->non_block ) { 64 if ( flags & MU_STREAM_NONBLOCK ) {
50 flgs = fcntl(tcp->fd, F_GETFL); 65 flgs = fcntl(tcp->fd, F_GETFL);
51 flgs |= O_NONBLOCK; 66 flgs |= O_NONBLOCK;
52 fcntl(tcp->fd, F_SETFL, flgs); 67 fcntl(tcp->fd, F_SETFL, flgs);
68 stream->flags |= MU_STREAM_NONBLOCK;
53 } 69 }
54 tcp->state = TCP_STATE_RESOLVING; 70 tcp->state = TCP_STATE_RESOLVING;
55 case TCP_STATE_RESOLVING: 71 case TCP_STATE_RESOLVING:
...@@ -59,7 +75,7 @@ static int _tcp_doconnect(struct _tcp_instance *tcp) ...@@ -59,7 +75,7 @@ static int _tcp_doconnect(struct _tcp_instance *tcp)
59 if (tcp->address == INADDR_NONE) { 75 if (tcp->address == INADDR_NONE) {
60 phe = gethostbyname(tcp->host); 76 phe = gethostbyname(tcp->host);
61 if ( !phe ) { 77 if ( !phe ) {
62 _tcp_close(tcp); 78 _tcp_close(stream);
63 return EINVAL; 79 return EINVAL;
64 } 80 }
65 tcp->address = *(((unsigned long **)phe->h_addr_list)[0]); 81 tcp->address = *(((unsigned long **)phe->h_addr_list)[0]);
...@@ -77,7 +93,7 @@ static int _tcp_doconnect(struct _tcp_instance *tcp) ...@@ -77,7 +93,7 @@ static int _tcp_doconnect(struct _tcp_instance *tcp)
77 tcp->state = TCP_STATE_CONNECTING; 93 tcp->state = TCP_STATE_CONNECTING;
78 ret = EAGAIN; 94 ret = EAGAIN;
79 } else 95 } else
80 _tcp_close(tcp); 96 _tcp_close(stream);
81 return ret; 97 return ret;
82 } 98 }
83 tcp->state = TCP_STATE_CONNECTING; 99 tcp->state = TCP_STATE_CONNECTING;
...@@ -87,7 +103,7 @@ static int _tcp_doconnect(struct _tcp_instance *tcp) ...@@ -87,7 +103,7 @@ static int _tcp_doconnect(struct _tcp_instance *tcp)
87 tcp->state = TCP_STATE_CONNECTED; 103 tcp->state = TCP_STATE_CONNECTED;
88 else { 104 else {
89 ret = errno; 105 ret = errno;
90 _tcp_close(tcp); 106 _tcp_close(stream);
91 return ret; 107 return ret;
92 } 108 }
93 break; 109 break;
...@@ -95,17 +111,14 @@ static int _tcp_doconnect(struct _tcp_instance *tcp) ...@@ -95,17 +111,14 @@ static int _tcp_doconnect(struct _tcp_instance *tcp)
95 return 0; 111 return 0;
96 } 112 }
97 113
114
98 static int _tcp_get_fd(stream_t stream, int *fd) 115 static int _tcp_get_fd(stream_t stream, int *fd)
99 { 116 {
100 struct _tcp_instance *tcp = stream->owner; 117 struct _tcp_instance *tcp = stream->owner;
101 118
102 if ( fd == NULL ) 119 if ( fd == NULL || tcp->fd == EINVAL )
103 return EINVAL; 120 return EINVAL;
104 121
105 if ( tcp->fd == -1 ) {
106 if ( ( tcp->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
107 return errno;
108 }
109 *fd = tcp->fd; 122 *fd = tcp->fd;
110 return 0; 123 return 0;
111 } 124 }
...@@ -113,152 +126,67 @@ static int _tcp_get_fd(stream_t stream, int *fd) ...@@ -113,152 +126,67 @@ static int _tcp_get_fd(stream_t stream, int *fd)
113 static int _tcp_read(stream_t stream, char *buf, size_t buf_size, off_t offset, size_t *br) 126 static int _tcp_read(stream_t stream, char *buf, size_t buf_size, off_t offset, size_t *br)
114 { 127 {
115 struct _tcp_instance *tcp = stream->owner; 128 struct _tcp_instance *tcp = stream->owner;
116 129 int bytes;
117 offset; 130
118 if ( br == NULL ) 131 offset = offset;
132 if ( br == NULL )
119 return EINVAL; 133 return EINVAL;
120 *br = 0; 134 *br = 0;
121 if ( ( *br = recv(tcp->fd, buf, buf_size, 0) ) == -1 ) { 135 if ( ( bytes = recv(tcp->fd, buf, buf_size, 0) ) == -1 ) {
122 *br = 0; 136 *br = 0;
123 return errno; 137 return errno;
124 } 138 }
139 *br = bytes;
125 return 0; 140 return 0;
126 } 141 }
127 142
128 static int _tcp_write(stream_t stream, const char *buf, size_t buf_size, off_t offset, size_t *bw) 143 static int _tcp_write(stream_t stream, const char *buf, size_t buf_size, off_t offset, size_t *bw)
129 { 144 {
130 struct _tcp_instance *tcp = stream->owner; 145 struct _tcp_instance *tcp = stream->owner;
131 146 int bytes;
132 offset; 147
133 if ( bw == NULL ) 148 offset = offset;
149 if ( bw == NULL )
134 return EINVAL; 150 return EINVAL;
135 *bw = 0; 151 *bw = 0;
136 if ( ( *bw = send(tcp->fd, buf, buf_size, 0) ) == -1 ) { 152 if ( ( bytes = send(tcp->fd, buf, buf_size, 0) ) == -1 ) {
137 *bw = 0; 153 *bw = 0;
138 return errno; 154 return errno;
139 } 155 }
156 *bw = bytes;
140 return 0; 157 return 0;
141 } 158 }
142 159
143 static int _tcp_new(void *netdata, net_t parent, void **data) 160 static void _tcp_destroy(stream_t stream)
144 {
145 struct _tcp_instance *tcp;
146
147 if ( parent ) /* tcp must be top level api */
148 return EINVAL;
149
150 if ( ( tcp = malloc(sizeof(*tcp)) ) == NULL )
151 return ENOMEM;
152 tcp->options = (struct _tcp_options *)netdata;
153 tcp->fd = -1;
154 tcp->host = NULL;
155 tcp->port = -1;
156 tcp->state = TCP_STATE_INIT;
157 stream_create(&tcp->stream, 0, tcp);
158 stream_set_read(tcp->stream, _tcp_read, tcp);
159 stream_set_write(tcp->stream, _tcp_write, tcp);
160 stream_set_fd(tcp->stream, _tcp_get_fd, tcp);
161 *data = tcp;
162 return 0;
163 }
164
165 static int _tcp_connect(void *data, const char *host, int port)
166 {
167 struct _tcp_instance *tcp = data;
168
169 if ( tcp->state == TCP_STATE_INIT ) {
170 tcp->port = port;
171 if ( ( tcp->host = strdup(host) ) == NULL )
172 return ENOMEM;
173 }
174 if ( tcp->state < TCP_STATE_CONNECTED )
175 return _tcp_doconnect(tcp);
176 return 0;
177 }
178
179 static int _tcp_get_stream(void *data, stream_t *stream)
180 {
181 struct _tcp_instance *tcp = data;
182
183 *stream = tcp->stream;
184 return 0;
185 }
186
187 static int _tcp_close(void *data)
188 { 161 {
189 struct _tcp_instance *tcp = data; 162 struct _tcp_instance *tcp = stream->owner;
190
191 if ( tcp->fd != -1 )
192 close(tcp->fd);
193 tcp->fd = -1;
194 tcp->state = TCP_STATE_INIT;
195 return 0;
196 }
197
198 static int _tcp_free(void **data)
199 {
200 struct _tcp_instance *tcp;
201
202 if ( data == NULL || *data == NULL )
203 return EINVAL;
204 tcp = *data;
205 163
206 if ( tcp->host ) 164 if ( tcp->host )
207 free(tcp->host); 165 free(tcp->host);
208 if ( tcp->fd != -1 ) 166 if ( tcp->fd != -1 )
209 close(tcp->fd); 167 close(tcp->fd);
210 168
211 free(*data); 169 free(tcp);
212 *data = NULL;
213 return 0;
214 } 170 }
215 171
216 static struct _net_api _tcp_net_api = { 172 int tcp_stream_create(stream_t *stream)
217 _tcp_new,
218 _tcp_connect,
219 _tcp_get_stream,
220 _tcp_close,
221 _tcp_free
222 };
223
224 int _tcp_create(void **netdata, struct _net_api **netapi)
225 { 173 {
226 struct _tcp_options *options; 174 struct _tcp_instance *tcp;
175 int ret;
227 176
228 if ( ( options = malloc(sizeof(*options)) ) == NULL ) 177 if ( ( tcp = malloc(sizeof(*tcp)) ) == NULL )
229 return ENOMEM; 178 return ENOMEM;
230 179 tcp->fd = -1;
231 options->non_block = 0; 180 tcp->host = NULL;
232 options->net_timeout = -1; /* system default */ 181 tcp->port = -1;
233 182 tcp->state = TCP_STATE_INIT;
234 *netdata = options; 183 if ( ( ret = stream_create(stream, MU_STREAM_NO_CHECK|MU_STREAM_RDWR, tcp) ) != 0 )
235 *netapi = &_tcp_net_api; 184 return ret;
236 return 0; 185 stream_set_open(*stream, _tcp_open, tcp);
237 } 186 stream_set_close(*stream, _tcp_close, tcp);
238 187 stream_set_read(*stream, _tcp_read, tcp);
239 int _tcp_set_option(void *netdata, const char *name, const char *value) 188 stream_set_write(*stream, _tcp_write, tcp);
240 { 189 stream_set_fd(*stream, _tcp_get_fd, tcp);
241 struct _tcp_options *options = netdata; 190 stream_set_destroy(*stream, _tcp_destroy, tcp);
242
243 if ( strcasecmp(name, "tcp_non_block") == 0 ) {
244 if ( value[0] == 't' || value[0] == 'T' || value[0] == '1' || value[0] == 'y' || value[0] == 'Y')
245 options->non_block = 1;
246 else
247 options->non_block = 0;
248 }
249 else if ( strcasecmp(name, "tcp_timeout") == 0 )
250 options->net_timeout = atoi(value);
251 else
252 return EINVAL;
253 return 0;
254 }
255
256 int _tcp_destroy(void **netdata)
257 {
258 struct _tcp_options *options = *netdata;
259
260 free(options);
261 *netdata = NULL;
262 return 0; 191 return 0;
263 } 192 }
264
......