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.
Showing
14 changed files
with
1587 additions
and
0 deletions
mailbox/body.c
0 → 100644
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 | } |
mailbox/include/private/attribute0.h
0 → 100644
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 */ |
mailbox/include/private/body0.h
0 → 100644
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 */ |
mailbox/include/private/mailer0.h
0 → 100644
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 */ |
mailbox/include/private/net0.h
0 → 100644
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 */ |
mailbox/include/private/tcp.h
0 → 100644
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 | }; |
mailbox/include/public/body.h
0 → 100644
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 */ |
mailbox/include/public/mailer.h
0 → 100644
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 */ |
mailbox/include/public/net.h
0 → 100644
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 */ |
mailbox/mailer.c
0 → 100644
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 | } |
mailbox/mbx_unixscan.c
0 → 100644
This diff is collapsed.
Click to expand it.
mailbox/net.c
0 → 100644
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 | } |
mailbox/tcp.c
0 → 100644
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 |
mailbox/transcode.c
0 → 100644
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment