Commit 91905487 9190548774e3ae77363f993d5f603a394c8815b1 by Alain Magloire

body.c mailer.c mbx_unixscan.c net.c tcp.c transcode.c

 	include/private/attribute0.h include/private/body0.h
 	include/private/mailer0.h include/private/net0.h
 	include/private/tcp.h include/public/body.h
 	include/public/mailer.h include/public/net.h

parsing and little of networking code, making a path for Pop and IMAP.
1 parent d9a9b601
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 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
19 #include <body0.h>
20 #include <io0.h>
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 static int body_read (stream_t is, char *buf, size_t buflen,
29 off_t off, size_t *pnread );
30 static int body_write (stream_t os, const char *buf, size_t buflen,
31 off_t off, size_t *pnwrite);
32 static FILE *lazy_create (void);
33 static int body_get_fd (stream_t stream, int *pfd);
34
35 int
36 body_create (body_t *pbody, void *owner)
37 {
38 body_t body;
39
40 if (pbody == NULL || owner == NULL)
41 return EINVAL;
42
43 body = calloc (1, sizeof (*body));
44 if (body == NULL)
45 return ENOMEM;
46
47 body->owner = owner;
48 *pbody = body;
49 return 0;
50 }
51
52 void
53 body_destroy (body_t *pbody, void *owner)
54 {
55 if (pbody && *pbody)
56 {
57 body_t body = *pbody;
58 if (body->owner == owner)
59 {
60 if (body->file)
61 {
62 fclose (body->file);
63 body->file = NULL;
64 }
65 free (body->filename); body->filename = NULL;
66 stream_destroy (&(body->stream), body);
67 }
68 *pbody = NULL;
69 }
70 }
71
72 int
73 body_get_stream (body_t body, stream_t *pstream)
74 {
75 if (body == NULL || pstream == NULL)
76 return EINVAL;
77
78 if (body->stream == NULL)
79 {
80 stream_t stream;
81 int status;
82 /* lazy floating body it is created when
83 * doing the first body_write call
84 */
85 status = stream_create (&stream, body);
86 if (status != 0)
87 return status;
88 stream_set_read (stream, body_read, body);
89 stream_set_write (stream, body_write, body);
90 stream_set_fd (stream, body_get_fd, body);
91 body->stream = stream;
92 }
93
94 *pstream = body->stream;
95 return 0;
96 }
97
98 int
99 body_set_stream (body_t body, stream_t stream, void *owner)
100 {
101 if (body == NULL)
102 return EINVAL;
103 if (body->owner != owner)
104 return EACCES;
105 /* make sure we destroy the old one if it is own by the body */
106 stream_destroy (&(body->stream), body);
107 if (body->file)
108 {
109 fclose (body->file);
110 body->file = NULL;
111 }
112 body->stream = stream;
113 return 0;
114 }
115
116 int
117 body_set_lines (body_t body, int (*_lines)(body_t, size_t *), void *owner)
118 {
119 if (body == NULL)
120 return EINVAL;
121 if (body->owner == owner)
122 return EACCES;
123 body->_lines = _lines;
124 return 0;
125 }
126
127 int
128 body_lines (body_t body, size_t *plines)
129 {
130 if (body == NULL)
131 return EINVAL;
132 if (body->_lines)
133 return body->_lines (body, plines);
134 if (plines)
135 *plines = 0;
136 return 0;
137 }
138
139 int
140 body_size (body_t body, size_t *psize)
141 {
142 if (body == NULL)
143 return EINVAL;
144
145 /* Check to see if they want to doit themselves,
146 * it was probably not a floating message */
147 if (body->_size)
148 return body->_size (body, psize);
149
150 /* ok we should handle this */
151 if (body->file)
152 {
153 struct stat st;
154 if (fstat (fileno (body->file), &st) == -1)
155 return errno;
156 if (psize)
157 *psize = st.st_size;
158 }
159 else if (body->filename)
160 {
161 struct stat st;
162 if (stat (body->filename, &st) == -1)
163 return errno;
164 if (psize)
165 *psize = st.st_size;
166 }
167 else if (psize)
168 *psize = 0;
169
170 return 0;
171 }
172
173 int
174 body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner)
175 {
176 if (body == NULL)
177 return EINVAL;
178 if (body->owner != owner)
179 return EACCES;
180 body->_size = _size;
181 return 0;
182 }
183
184 static int
185 body_read (stream_t is, char *buf, size_t buflen,
186 off_t off, size_t *pnread )
187 {
188 body_t body;
189 size_t nread = 0;
190
191 if (is == NULL || (body = is->owner) == NULL)
192 return EINVAL;
193
194 /* check if they want to read from a file */
195 if (body->file == NULL && body->filename)
196 {
197 /* try read only, we don't want to
198 * handle nasty security issues here.
199 */
200 body->file = fopen (body->filename, "r");
201 if (body->file == NULL)
202 {
203 if (pnread)
204 *pnread = 0;
205 return errno;
206 }
207 }
208
209 if (body->file)
210 {
211 /* should we check the error of fseek for some handlers
212 * like socket where fseek () will fail.
213 * FIXME: Alternative is to check fseeck and errno == EBADF
214 * if not a seekable stream.
215 */
216 if (fseek (body->file, off, SEEK_SET) == -1)
217 return errno;
218
219 nread = fread (buf, sizeof (char), buflen, body->file);
220 if (nread == 0)
221 {
222 if (ferror (body->file))
223 return errno;
224 /* clear the error for feof() */
225 clearerr (body->file);
226 }
227 }
228
229 if (pnread)
230 *pnread = nread;
231 return 0;
232 }
233
234 static int
235 body_write (stream_t os, const char *buf, size_t buflen,
236 off_t off, size_t *pnwrite)
237 {
238 body_t body;
239 size_t nwrite = 0;
240
241 if (os == NULL || (body = os->owner) == NULL)
242 return EINVAL;
243
244 /* FIXME: security issues, Refuse to write to an unknow file */
245 if (body->file == NULL && body->filename)
246 return EINVAL;
247
248 /* Probably being lazy, then create a body for the stream */
249 if (body->file == NULL)
250 {
251 body->file = lazy_create ();
252 if (body->file == NULL)
253 return errno;
254 }
255
256 /* should we check the error of fseek for some handlers
257 * like socket where it does not make sense.
258 * FIXME: Alternative is to check fseeck and errno == EBADF
259 * if not a seekable stream.
260 */
261 if (fseek (body->file, off, SEEK_SET) == -1)
262 return errno;
263
264 nwrite = fwrite (buf, sizeof (char), buflen, body->file);
265 if (nwrite == 0)
266 {
267 if (ferror (body->file))
268 return errno;
269 /* clear the error for feof() */
270 clearerr (body->file);
271 }
272
273 if (pnwrite)
274 *pnwrite = nwrite;
275 return 0;
276 }
277
278 static int
279 body_get_fd (stream_t stream, int *pfd)
280 {
281 body_t body;
282
283 if (stream == NULL || (body = stream->owner) == NULL)
284 return EINVAL;
285
286 /* Probably being lazy, then create a body for the stream */
287 if (body->file == NULL)
288 {
289 body->file = lazy_create ();
290 if (body->file == 0)
291 return errno;
292 }
293
294 if (pfd)
295 *pfd = fileno (body->file);
296 return 0;
297 }
298
299 static FILE *
300 lazy_create ()
301 {
302 FILE *file;
303 #ifdef HAVE_MKSTEMP
304 char tmpbuf[L_tmpnam + 1];
305 int fd;
306
307 if (tmpnam (tmpbuf) == NULL ||
308 (fd = mkstemp (tmpbuf)) == -1 ||
309 (file = fdopen(fd, "w+")) == NULL)
310 return NULL;
311 (void)remove(tmpbuf);
312 #else
313 file = tmpfile ();
314 /* make sure the mode is right */
315 if (file)
316 fchmod (fileno (file), 0600);
317 #endif
318 return file;
319 }
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 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 #ifndef _ATTRIBUTE0_H
19 # define _ATTRIBUTE0_H
20
21 #include <attribute.h>
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 #ifndef __P
28 # ifdef __STDC__
29 # define __P(args) args
30 # else
31 # define __P(args) ()
32 # endif
33 #endif /*__P */
34
35 struct _attribute
36 {
37 size_t flag;
38 void *owner;
39 };
40
41 #define MU_ATTRIBUTE_SEEN ((int)1)
42 #define MU_ATTRIBUTE_ANSWERED (MU_ATTRIBUTE_SEEN << 1)
43 #define MU_ATTRIBUTE_FLAGGED (MU_ATTRIBUTE_ANSWERED << 1)
44 #define MU_ATTRIBUTE_DELETED (MU_ATTRIBUTE_FLAGGED << 1)
45 #define MU_ATTRIBUTE_DRAFT (MU_ATTRIBUTE_DELETED << 1)
46 #define MU_ATTRIBUTE_RECENT (MU_ATTRIBUTE_DRAFT << 1)
47 #define MU_ATTRIBUTE_READ (MU_ATTRIBUTE_RECENT << 1)
48
49 #ifdef __cplusplus
50 }
51 #endif
52
53 #endif /* _ATTRIBUTE0_H */
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 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 #ifndef _BODY0_H
19 #define _BODY0_H
20
21 #include <io.h>
22 #include <body.h>
23
24 #include <stdio.h>
25 #include <sys/types.h>
26
27 #ifndef __P
28 # ifdef __STDC__
29 # define __P(args) args
30 # else
31 # define __P(args) ()
32 # endif
33 #endif /* __P */
34
35 #ifdef _cplusplus
36 extern "C" {
37 #endif
38
39 struct _body
40 {
41 void *owner;
42
43 /* it's better and more portable to use stdio */
44 FILE *file;
45 char *filename;
46 stream_t stream;
47 int (*_size) (body_t, size_t*);
48 int (*_lines) (body_t, size_t*);
49 };
50
51 #ifdef _cplusplus
52 }
53 #endif
54
55 #endif /* _BODY0_H */
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 _MAILER0_H
19 #define _MAILER0_H
20
21 #include <sys/types.h>
22 #include <mailer.h>
23
24 #ifdef _cplusplus
25 extern "C" {
26 #endif
27
28 #ifndef __P
29 # ifdef __STDC__
30 # define __P(args) args
31 # else
32 # define __P(args) ()
33 # endif
34 #endif /*__P */
35
36 // mailer states
37 #define MAILER_STATE_HDR 1
38 #define MAILER_STATE_MSG 2
39 #define MAILER_STATE_COMPLETE 3
40
41 // mailer messages
42 #define MAILER_HELO 1
43 #define MAILER_MAIL 2
44 #define MAILER_RCPT 3
45 #define MAILER_DATA 4
46 #define MAILER_RSET 5
47 #define MAILER_QUIT 6
48
49 #define MAILER_LINE_BUF_SIZE 1000
50
51 struct _mailer
52 {
53 int socket;
54 char *hostname;
55 char line_buf[MAILER_LINE_BUF_SIZE];
56 int offset;
57 int state;
58 int add_dot;
59 stream_t stream;
60 char last_char;
61 };
62
63 #ifdef _cplusplus
64 }
65 #endif
66
67 #endif /* MAILER0_H */
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 */
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 #include <net0.h>
19
20 #define TCP_STATE_INIT 1
21 #define TCP_STATE_RESOLVE 2
22 #define TCP_STATE_RESOLVING 3
23 #define TCP_STATE_CONNECTING 4
24 #define TCP_STATE_CONNECTED 5
25
26 struct _tcp_options {
27 int non_block;
28 int net_timeout;
29 };
30
31 struct _tcp_instance {
32 struct _tcp_options *options;
33 int fd;
34 char *host;
35 int port;
36 int state;
37 stream_t stream;
38 unsigned long address;
39 };
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 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 #ifndef _BODY_H
19 #define _BODY_H
20
21 #include <sys/types.h>
22 #include <io.h>
23
24 #ifndef __P
25 # ifdef __STDC__
26 # define __P(args) args
27 # else
28 # define __P(args) ()
29 # endif
30 #endif /* __P */
31
32 #ifdef _cplusplus
33 extern "C" {
34 #endif
35
36 /* forward declaration */
37 struct _body;
38 typedef struct _body *body_t;
39
40 extern int body_create __P ((body_t *, void *owner));
41 extern void body_destroy __P ((body_t *, void *owner));
42
43 extern int body_get_stream __P ((body_t, stream_t *));
44 extern int body_set_stream __P ((body_t, stream_t, void *owner));
45
46 extern int body_get_filename __P ((body_t, char *, size_t, size_t *));
47 extern int body_set_filename __P ((body_t, const char*));
48
49 extern int body_size __P ((body_t, size_t*));
50 extern int body_set_size __P ((body_t,
51 int (*_size) __P ((body_t, size_t*)),
52 void *owner));
53 extern int body_lines __P ((body_t, size_t *));
54 extern int body_set_lines __P ((body_t,
55 int (*_lines) __P ((body_t, size_t*)),
56 void *owner));
57
58 #ifdef _cplusplus
59 }
60 #endif
61
62 #endif /* _BODY_H */
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 _MAILER_H
19 #define _MAILER_H
20
21 #include "message.h"
22 #include <sys/types.h>
23
24 #ifndef __P
25 # ifdef __STDC__
26 # define __P(args) args
27 # else
28 # define __P(args) ()
29 # endif
30 #endif /* __P */
31
32 #ifdef _cplusplus
33 extern "C" {
34 #endif
35
36 /* forward declaration */
37 struct _mailer;
38 typedef struct _mailer *mailer_t;
39
40 extern int mailer_create __P ((mailer_t *, message_t));
41 extern int mailer_connect __P ((mailer_t, char *host));
42 extern int mailer_disconnect __P ((mailer_t));
43 extern int mailer_send_header __P ((mailer_t, message_t));
44 extern int mailer_send_message __P ((mailer_t, message_t));
45
46 #ifdef _cplusplus
47 }
48 #endif
49
50 #endif /* _MAILER_H */
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 _NET_H
19 #define _NET_H
20
21 #include <sys/types.h>
22
23 #include <io.h>
24
25 #ifdef _cplusplus
26 extern "C" {
27 #endif
28
29 #ifndef __P
30 #ifdef __STDC__
31 #define __P(args) args
32 #else
33 #define __P(args) ()
34 #endif
35 #endif /*__P */
36
37 struct _net;
38 typedef struct _net *net_t;
39
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
44 struct _netinstance;
45 typedef struct _netinstance *netinstance_t;
46
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
53 #ifdef _cplusplus
54 }
55 #endif
56
57 #endif /* NET_H */
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 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 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <netdb.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/select.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31
32 #include <mailer0.h>
33
34 int _mailer_sock_connect(char *host, int port);
35 char *_mailer_find_mailbox(char *addr);
36 int _mailer_send_command(mailer_t ml, message_t msg, int cmd);
37 char *nb_fgets(char *buf, int size, int s);
38 char *nb_fprintf(int s, char *format, ...);
39
40 #define nb_read read
41 #define nb_write write
42 #define BUFFSIZE 4096
43
44 int
45 mailer_create(mailer_t *pml, message_t msg)
46 {
47 mailer_t ml;
48
49 (void)msg;
50 if (!pml)
51 return EINVAL;
52
53 ml = calloc (1, sizeof (*ml));
54 if (ml == NULL)
55 return (ENOMEM);
56
57 *pml = ml;
58
59 return (0);
60 }
61
62 int
63 mailer_destroy(mailer_t *pml)
64 {
65 mailer_t ml;
66
67 if (!pml)
68 return (EINVAL);
69 ml = *pml;
70 if (ml->hostname)
71 free(ml->hostname);
72 mailer_disconnect(ml);
73 free(ml);
74 *pml = NULL;
75
76 return (0);
77 }
78
79 int
80 mailer_connect(mailer_t ml, char *host)
81 {
82 if (!ml || !host)
83 return (EINVAL);
84
85 if ((ml->socket = _mailer_sock_connect(host, 25)) < 0)
86 return (-1);
87 do
88 {
89 nb_fgets(ml->line_buf, MAILER_LINE_BUF_SIZE, ml->socket); /* read header line */
90 } while ( strlen(ml->line_buf) > 4 && *(ml->line_buf+3) == '-');
91
92 return (0);
93 }
94
95 int
96 mailer_disconnect(mailer_t ml)
97 {
98 if (!ml || (ml->socket != -1))
99 return (EINVAL);
100
101 close(ml->socket);
102 return (0);
103 }
104
105 int
106 mailer_send_header(mailer_t ml, message_t msg)
107 {
108 header_t hdr;
109 char buf[64];
110
111 if (!ml || !msg || (ml->socket == -1))
112 return (EINVAL);
113
114 if (!ml->hostname)
115 {
116 if (gethostname(buf, 64) < 0)
117 return (-1);
118 ml->hostname = strdup(buf);
119 }
120
121 if (_mailer_send_command(ml, msg, MAILER_HELO) != 0)
122 return (-1);
123 if (_mailer_send_command(ml, msg, MAILER_MAIL) != 0)
124 return (-1);
125 if (_mailer_send_command(ml, msg, MAILER_RCPT) != 0)
126 return (-1);
127 if (_mailer_send_command(ml, msg, MAILER_DATA) != 0)
128 return (-1);
129
130 message_get_header(msg, &hdr);
131 header_get_stream(hdr, &(ml->stream));
132
133 ml->state = MAILER_STATE_HDR;
134
135 return (0);
136 }
137
138 int
139 mailer_send_message(mailer_t ml, message_t msg)
140 {
141 int status, len = 0, data_len = 0, consumed = 0;
142 char *data, *p, *q;
143
144 if (!ml || !msg || (ml->socket == -1))
145 return (EINVAL);
146
147 // alloca
148 if (!(data = alloca(MAILER_LINE_BUF_SIZE)))
149 return (ENOMEM);
150
151 memset(data, 0, 1000);
152 if ((status = stream_read(ml->stream, data, MAILER_LINE_BUF_SIZE, ml->offset, &len)) != 0)
153 return (-1);
154
155 if ((len == 0) && (ml->state == MAILER_STATE_HDR))
156 {
157 ml->state = MAILER_STATE_MSG;
158 ml->offset = 0;
159 message_get_stream(msg, &(ml->stream));
160 return (1);
161 }
162 else if (len == 0)
163 {
164 strcpy(ml->line_buf, "\r\n.\r\n");
165 consumed = strlen(data);
166 }
167 else
168 {
169 p = data;
170 q = ml->line_buf;
171 memset(ml->line_buf, 0, MAILER_LINE_BUF_SIZE);
172 while (consumed < len)
173 {
174 // RFC821: if the first character on a line is a '.' you must add an
175 // extra '.' to the line which will get stipped off at the other end
176 if ((*p == '.') && (ml->last_char == '\n'))
177 ml->add_dot = 1;
178 ml->last_char = *p;
179 *q++ = *p++; // store the character
180 data_len++; // increase the length by 1
181 consumed++;
182 if (((MAILER_LINE_BUF_SIZE - data_len) > 1) && (ml->add_dot == 1))
183 {
184 *q++ = '.';
185 data_len++;
186 ml->add_dot = 0;
187 }
188 }
189 }
190
191 ml->offset += consumed;
192 nb_fprintf(ml->socket, "%s\r\n", ml->line_buf);
193
194 if (len == 0)
195 {
196 ml->state = MAILER_STATE_COMPLETE;
197 return (0);
198 }
199
200 return (consumed);
201 }
202
203 int
204 _mailer_sock_connect(char *host, int port)
205 {
206 struct sockaddr_in saddr;
207 struct hostent *hp;
208 int s;
209
210 memset(&saddr, 0, sizeof(struct sockaddr_in));
211 saddr.sin_family = AF_INET;
212 saddr.sin_port = htons(port);
213 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
214 return (-1);
215 if ((hp = gethostbyname(host)) == 0)
216 return (-1);
217 memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
218 if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) == 0)
219 return (s);
220 close(s);
221
222 return (-1);
223 }
224
225 char *
226 _mailer_find_mailbox(char *addr)
227 {
228 char *p, *c;
229 p = addr;
230 if ( (c = strchr( p, '<')) != 0)
231 {
232 p = c+1;
233 if ( c = strchr( p, '>'))
234 *c = '\0';
235 }
236 else if ( (c = strchr( p, '(' )) != 0 )
237 {
238 --c;
239 while ( c > p && *c && isspace( *c ) ) {
240 *c = '\0';
241 --c;
242 }
243 }
244 return p;
245 }
246
247 int
248 _mailer_rctp(mailer_t ml, char *str)
249 {
250 char *p, *c = NULL, *q = NULL;
251
252 for (q = p = str; q && *p; p = q+1)
253 {
254 if ( q = strchr( p, ','))
255 *q = '\0';
256 while ( p && *p && isspace( *p ) )
257 p++;
258 c = strdup(p);
259 p = _mailer_find_mailbox(c);
260 nb_fprintf(ml->socket, "RCPT TO:<%s>\r\n", p);
261 free(c);
262 nb_fgets(ml->line_buf, sizeof(ml->line_buf), ml->socket);
263 if (strncmp(ml->line_buf, "250", 3))
264 return (-strtol(ml->line_buf, 0, 10));
265 }
266 return (0);
267 }
268
269 int
270 _mailer_send_command(mailer_t ml, message_t msg, int cmd)
271 {
272 header_t hdr;
273 char *p, *c = NULL, *q = NULL;
274 char str[128];
275 size_t str_len;
276 char *success = "250";
277
278 switch (cmd)
279 {
280 case MAILER_HELO:
281 nb_fprintf(ml->socket, "HELO %s\r\n", ml->hostname);
282 break;
283 case MAILER_MAIL:
284 message_get_header(msg, &hdr);
285 header_get_value(hdr, MU_HEADER_FROM, str, 128, &str_len);
286 str[str_len] = '\0';
287 p = _mailer_find_mailbox(str);
288 nb_fprintf(ml->socket, "MAIL From: %s\r\n", p);
289 break;
290 case MAILER_RCPT:
291 message_get_header(msg, &hdr);
292 header_get_value(hdr, MU_HEADER_TO, str, 128, &str_len);
293 str[str_len] = '\0';
294 if (_mailer_rctp(ml, str) == -1)
295 return (-1);
296 header_get_value(hdr, MU_HEADER_CC, str, 128, &str_len);
297 str[str_len] = '\0';
298 if (_mailer_rctp(ml, str) == -1)
299 return (-1);
300 return (0);
301 break;
302 case MAILER_DATA:
303 nb_fprintf(ml->socket, "DATA\r\n");
304 success = "354";
305 break;
306 case MAILER_RSET:
307 nb_fprintf(ml->socket, "RSET\r\n");
308 break;
309 case MAILER_QUIT:
310 nb_fprintf(ml->socket, "QUIT\r\n");
311 success = "221";
312 break;
313 }
314
315 nb_fgets(ml->line_buf, sizeof(ml->line_buf), ml->socket);
316 if (strncmp(ml->line_buf, success, 3) == 0)
317 return (0);
318 else
319 return (-strtol(ml->line_buf, 0, 10));
320 }
321
322 char *
323 nb_fgets( char *buf, int size, int s )
324 {
325 static char *buffer[25];
326 char *p, *b, *d;
327 int bytes, i;
328 int flags;
329
330 if ( !buffer[s] && !( buffer[s] = calloc( BUFFSIZE+1, 1 ) ) )
331 return 0;
332 bytes = i = strlen( p = b = buffer[s] );
333 *( d = buf ) = '\0';
334 for ( ; i-- > 0; p++ )
335 {
336 if ( *p == '\n' )
337 {
338 char c = *( p+1 );
339
340 *( p+1 ) = '\0';
341 strcat( d, b );
342 *( p+1 ) = c;
343 memmove( b, p+1, i+1 );
344 return buf;
345 }
346 }
347 flags = fcntl( s, F_GETFL );
348 fcntl( s, F_SETFL, O_NONBLOCK );
349 while ( bytes <= size )
350 {
351 fd_set fds;
352
353 FD_ZERO( &fds );
354 FD_SET( s, &fds );
355 select( s+1, &fds, 0, 0, 0 ); /* we really don't care what it returns */
356 if ( ( i = nb_read( s, p, BUFFSIZE - bytes ) ) == -1 )
357 {
358 *b = '\0';
359 return 0;
360 }
361 else if ( i == 0 )
362 {
363 *( p+1 ) = '\0';
364 strcat( d, b );
365 *b = '\0';
366 fcntl( s, F_SETFL, flags );
367 return strlen( buf ) ? buf : 0;
368 }
369 *( p+i ) = '\0';
370 bytes += i;
371 for ( ; i-- > 0; p++ )
372 {
373 if ( *p == '\n' )
374 {
375 char c = *( p+1 );
376
377 *( p+1 ) = '\0';
378 strcat( d, b );
379 *( p+1 ) = c;
380 memmove( b, p+1, i+1 );
381 fcntl( s, F_SETFL, flags );
382 return buf;
383 }
384 }
385 if ( bytes == BUFFSIZE )
386 {
387 memcpy( d, b, BUFFSIZE );
388 d += BUFFSIZE;
389 size -= BUFFSIZE;
390 bytes = 0;
391 *( p = b ) = '\0';
392 }
393 }
394 memcpy( d, b, size );
395 memmove( b, b+size, strlen( b+size )+1 );
396 fcntl( s, F_SETFL, flags );
397 return buf;
398 }
399
400 char *
401 nb_fprintf( int s, char *format, ... )
402 {
403 char buf[MAILER_LINE_BUF_SIZE];
404 va_list vl;
405 int i;
406
407 va_start( vl, format );
408 vsprintf( buf, format, vl );
409 va_end( vl );
410 i = strlen( buf );
411 if ( nb_write( s, buf, i ) != i )
412 return 0;
413 return format;
414 }
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 <errno.h>
21
22 #include <net0.h>
23
24 static struct _netregistrar _netreg[1] = { "tcp", _tcp_create, _tcp_set_option, _tcp_destroy };
25
26 int net_api_create(net_t *net, net_t parent, const char *type)
27 {
28 net_t n;
29 int i, napis, ret = 0;
30
31 if ( net == NULL || type == NULL )
32 return EINVAL;
33
34 *net = NULL;
35
36 if ( ( n = calloc(1, sizeof(*n)) ) == NULL )
37 return ENOMEM;
38 napis = sizeof(_netreg) / sizeof(_netreg[0]);
39 for( i = 0; i < napis; i++ ) {
40 if ( strcasecmp(_netreg[i].type, type) == 0 )
41 break;
42 }
43 if ( i == napis )
44 return ENOTSUP;
45 if ( ret = ( _netreg[i].create(&(n->data), &(n->api)) ) != 0 )
46 free(n);
47 n->parent = parent;
48 n->net_reg = &_netreg[i];
49 *net = n;
50 return 0;
51 }
52
53 int net_api_set_option(net_t net, const char *name, const char *value)
54 {
55 if ( net && name && value )
56 return net->net_reg->set_option(net->data, name, value);
57 return EINVAL;
58 }
59
60 int net_api_destroy(net_t *net)
61 {
62 net_t n;
63 if ( net == NULL || *net == NULL )
64 return EINVAL;
65
66 n = *net;
67 n->net_reg->destroy(&n->data);
68 free(n);
69 *net = NULL;
70 return 0;
71 }
72
73 int net_new(net_t net, netinstance_t *inst)
74 {
75 netinstance_t netinst;
76 int ret = 0;
77
78 if ( net == NULL || inst == NULL )
79 return EINVAL;
80
81 *inst = NULL;
82
83 if ( ( netinst = calloc(1, sizeof(*netinst)) ) == NULL )
84 return ENOMEM;
85 netinst->api = net->api;
86 if ( ( ret = net->api->new(net->data, net->parent, &(netinst->data)) ) != 0 ) {
87 free(netinst);
88 return ret;
89 }
90 *inst = netinst;
91 return 0;
92 }
93
94 int net_connect(netinstance_t inst, const char *host, int port)
95 {
96 if ( inst == NULL || host == NULL )
97 return EINVAL;
98
99 return inst->api->connect(inst->data, host, port);
100 }
101
102 int net_get_stream(netinstance_t inst, stream_t *iostr)
103 {
104 if ( inst == NULL || iostr == NULL )
105 return EINVAL;
106
107 return inst->api->get_stream(inst->data, iostr);
108 }
109
110 int net_close(netinstance_t inst)
111 {
112 if ( inst == NULL )
113 return EINVAL;
114
115 return inst->api->close(inst->data);
116 }
117
118 int net_free(netinstance_t *pinst)
119 {
120 int ret;
121 netinstance_t inst;
122
123 if ( pinst == NULL || *pinst == NULL )
124 return EINVAL;
125
126 inst = *pinst;
127 ret = inst->api->free(&(inst->data));
128 free(inst);
129 *pinst = NULL;
130 return ret;
131 }
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 #include <stdlib.h>
19 #include <stdio.h>
20 #include <errno.h>
21 #include <netdb.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28
29 #include <net0.h>
30 #include <io0.h>
31 #include <tcp.h>
32
33 static int _tcp_close(void *data);
34
35 static int _tcp_doconnect(struct _tcp_instance *tcp)
36 {
37 int flgs, ret;
38 size_t namelen;
39 struct sockaddr_in peer_addr;
40 struct hostent *phe;
41 struct sockaddr_in soc_addr;
42
43 switch( tcp->state ) {
44 case TCP_STATE_INIT:
45 if ( tcp->fd == -1 ) {
46 if ( ( tcp->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
47 return errno;
48 }
49 if ( tcp->options->non_block ) {
50 flgs = fcntl(tcp->fd, F_GETFL);
51 flgs |= O_NONBLOCK;
52 fcntl(tcp->fd, F_SETFL, flgs);
53 }
54 tcp->state = TCP_STATE_RESOLVING;
55 case TCP_STATE_RESOLVING:
56 if ( tcp->host == NULL || tcp->port == -1 )
57 return EINVAL;
58 tcp->address = inet_addr(tcp->host);
59 if (tcp->address == INADDR_NONE) {
60 phe = gethostbyname(tcp->host);
61 if ( !phe ) {
62 _tcp_close(tcp);
63 return EINVAL;
64 }
65 tcp->address = *(((unsigned long **)phe->h_addr_list)[0]);
66 }
67 tcp->state = TCP_STATE_RESOLVE;
68 case TCP_STATE_RESOLVE:
69 memset (&soc_addr, 0, sizeof (soc_addr));
70 soc_addr.sin_family = AF_INET;
71 soc_addr.sin_port = htons(tcp->port);
72 soc_addr.sin_addr.s_addr = tcp->address;
73
74 if ( ( connect(tcp->fd, (struct sockaddr *) &soc_addr, sizeof(soc_addr)) ) == -1 ) {
75 ret = errno;
76 if ( ret == EINPROGRESS || ret == EAGAIN ) {
77 tcp->state = TCP_STATE_CONNECTING;
78 ret = EAGAIN;
79 } else
80 _tcp_close(tcp);
81 return ret;
82 }
83 tcp->state = TCP_STATE_CONNECTING;
84 case TCP_STATE_CONNECTING:
85 namelen = sizeof (peer_addr);
86 if ( getpeername (tcp->fd, (struct sockaddr *)&peer_addr, &namelen) == 0 )
87 tcp->state = TCP_STATE_CONNECTED;
88 else {
89 ret = errno;
90 _tcp_close(tcp);
91 return ret;
92 }
93 break;
94 }
95 return 0;
96 }
97
98 static int _tcp_get_fd(stream_t stream, int *fd)
99 {
100 struct _tcp_instance *tcp = stream->owner;
101
102 if ( fd == NULL )
103 return EINVAL;
104
105 if ( tcp->fd == -1 ) {
106 if ( ( tcp->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
107 return errno;
108 }
109 *fd = tcp->fd;
110 return 0;
111 }
112
113 static int _tcp_read(stream_t stream, char *buf, size_t buf_size, off_t offset, size_t *br)
114 {
115 struct _tcp_instance *tcp = stream->owner;
116
117 offset;
118 if ( br == NULL )
119 return EINVAL;
120 *br = 0;
121 if ( ( *br = recv(tcp->fd, buf, buf_size, 0) ) == -1 ) {
122 *br = 0;
123 return errno;
124 }
125 return 0;
126 }
127
128 static int _tcp_write(stream_t stream, const char *buf, size_t buf_size, off_t offset, size_t *bw)
129 {
130 struct _tcp_instance *tcp = stream->owner;
131
132 offset;
133 if ( bw == NULL )
134 return EINVAL;
135 *bw = 0;
136 if ( ( *bw = send(tcp->fd, buf, buf_size, 0) ) == -1 ) {
137 *bw = 0;
138 return errno;
139 }
140 return 0;
141 }
142
143 static int _tcp_new(void *netdata, net_t parent, void **data)
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, 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 {
189 struct _tcp_instance *tcp = data;
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
206 if ( tcp->host )
207 free(tcp->host);
208 if ( tcp->fd != -1 )
209 close(tcp->fd);
210
211 free(*data);
212 *data = NULL;
213 return 0;
214 }
215
216 static struct _net_api _tcp_net_api = {
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 {
226 struct _tcp_options *options;
227
228 if ( ( options = malloc(sizeof(*options)) ) == NULL )
229 return ENOMEM;
230
231 options->non_block = 0;
232 options->net_timeout = -1; /* system default */
233
234 *netdata = options;
235 *netapi = &_tcp_net_api;
236 return 0;
237 }
238
239 int _tcp_set_option(void *netdata, const char *name, const char *value)
240 {
241 struct _tcp_options *options = netdata;
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;
263 }
264